Skip to content

Skip re-installing an already-installed Vite+ version: setup-vp and install.sh re-download on every job (~3s each) #145

Description

@jasonkuhrt

Summary

setup-vp re-runs the Vite+ installer on every job, and the installer has no path that notices the requested version is already installed. On a runner whose home directory persists across jobs (Blacksmith sticky disks, most self-hosted runners), every job pays the same ~3s to download and re-install a vp that is already there. The Node half is already idempotent: vp env use on a present runtime returns in a few milliseconds. Only the installer is not.

Measurement

Repository: a pnpm monorepo, setup-vp@v1.18.0 (the install path is unchanged on main at 0499fae), Vite+ 0.3.0 resolved from package.json, Node 22.23.1 resolved from package.json, cache: false, run-install: false. Runner: blacksmith-4vcpu-ubuntu-2404. vp env keeps its own runtimes under $VP_HOME/js_runtime, so the pinned 22.23.1 is a download on every fresh runner whatever Node the image ships.

One job, timestamps from the log (2026-09-10):

02:33:12.740  curl -fsSL ... /v0.3.0/packages/cli/install.sh -o "$installer_file"; source "$installer_file"
02:33:12.767  Setting up VITE+...
02:33:15.639  ✔ VITE+ successfully installed!              <- 2.9s
02:33:15.644  Setting up Node.js 22.23.1 via vp env use...
02:33:15.647  Installing Node.js v22.23.1...
02:33:16.260  Using Node.js v22.23.1 (resolved from 22.23.1) <- 0.6s
##[end-action id=__self.setup-vp;... duration_ms=3613]

Across our jobs the step runs 3.6s to 6.1s: 2.8s to 2.9s in the installer, 0.6s to 1.1s for the Node download, the rest in vp env use and version reporting. Our PR workflow alone starts about 240 runs a day, each with up to six jobs that run this step; even discounting runs cancelled by a newer push, that is on the order of a thousand installs of the same version a day, roughly an hour of runner time spent re-installing a binary the runner already has.

For comparison, once the version directory exists, vp env use 22.23.1 on a present runtime takes about 6 ms, and a pnpm store on a persistent disk turns our workspace install into a link-only 4s. The installer is now the largest fixed cost in the step.

What happens today, from the source

setup-vp (src/install-viteplus.ts, installVitePlus) fetches install.sh for the resolved tag and sources it, unconditionally; there is no check of an existing vp at the target directory and no use of @actions/tool-cache. The only vp --version call in src/index.ts runs after the install, to report the version.

install.sh (packages/cli/install.sh on main at 31b0922a), in main():

  1. get_version_from_metadata fetches the registry metadata for VP_VERSION and sets RESOLVED_VERSION (network).
  2. download_and_extract fetches @voidzero-dev/vite-plus-cli-<platform>-<version>.tgz into a temp dir (network) and copies the binary into $INSTALL_DIR/$VP_VERSION/bin.
  3. It rewrites $INSTALL_DIR/$VP_VERSION/package.json (the vp-global wrapper pinned to pnpm@10.33.0) and runs vp install there to install the vite-plus JS package and its transitive dependencies (network).
  4. It repoints $INSTALL_DIR/current and sets up shims.

None of these steps compares the resolved version against what is already in $INSTALL_DIR. detect_previous_install_dir / is_vite_plus_install_dir exist, but they detect an older layout to migrate, not a current same-version install to keep. So a persisted $VP_HOME (we can mount ~/.local/share/vite-plus as a sticky disk) does not save anything: the job still downloads the tarball, re-copies the binary and re-runs the wrapper install on top of an identical tree.

Ask

Either half would do; both would be ideal.

  1. Installer: after RESOLVED_VERSION is known, if $INSTALL_DIR/$RESOLVED_VERSION/bin/vp --version reports that version and the wrapper install is complete (the current symlink and node_modules/vite-plus present), skip steps 2 and 3 and go straight to current/shim/Node setup. That makes a persisted $VP_HOME free for GitHub, the GitLab template, and any other CI that keeps a home directory, and it also makes re-running the installer locally a no-op.
  2. setup-vp: before running the installer, look for vp at the target bin directory and skip the installer when its --version matches the resolved version; and, for GitHub-hosted runners without a persistent home, cache the installed version directory through @actions/tool-cache so a warm runner skips the network entirely.

Happy to try a prerelease on our runners and report timings.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions