From 2b26e9f6eeefef80d6068b026ba71267460c01e6 Mon Sep 17 00:00:00 2001 From: MK Date: Wed, 20 May 2026 16:35:15 +0800 Subject: [PATCH 1/4] ci: pin to older version before upgrade test to avoid release-day flake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right after a release commit lands on main, the dev build's package.json version equals npm latest, so `vp upgrade --force` is a no-op and the "version must change" assertion fails (e.g. v0.1.22 → v0.1.22 on run 26112690623). Downgrade to a known prior release first so the upgrade-to-latest below has a guaranteed version delta to assert against. The pin version is hoisted to a single job-level env var for easy bumps. --- .github/workflows/ci.yml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61e40a40ea..8efb209026 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -207,6 +207,11 @@ jobs: - os: windows-latest target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} + env: + # Any released version older than the current package.json version. + # Used by upgrade tests to create a guaranteed version delta against npm + # latest (otherwise `vp upgrade --force` is a no-op on release-day mains). + UPGRADE_TEST_PIN_VERSION: '0.1.21' steps: - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 - uses: ./.github/actions/clone @@ -424,9 +429,18 @@ jobs: node -p "require(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version" } - # Save initial (dev build) version + # Pin to a known older version first so the upgrade-to-latest below + # has a version delta to assert against. Right after a release commit + # on main, the dev build's package.json version equals npm latest, so + # `vp upgrade --force` would be a no-op and the assertion would fail. + vp upgrade "$UPGRADE_TEST_PIN_VERSION" --force + INITIAL_VERSION=$(get_cli_version) echo "Initial version: $INITIAL_VERSION" + if [ "$INITIAL_VERSION" != "$UPGRADE_TEST_PIN_VERSION" ]; then + echo "Error: failed to pin to $UPGRADE_TEST_PIN_VERSION (got $INITIAL_VERSION)" + exit 1 + fi # --check queries npm registry and prints update status vp upgrade --check @@ -472,9 +486,15 @@ jobs: node -p "require(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version" } - # Save initial (dev build) version + # See bash block above for why we pin to an older version first. + vp upgrade $env:UPGRADE_TEST_PIN_VERSION --force + $initialVersion = Get-CliVersion Write-Host "Initial version: $initialVersion" + if ($initialVersion -ne $env:UPGRADE_TEST_PIN_VERSION) { + Write-Error "Error: failed to pin to $env:UPGRADE_TEST_PIN_VERSION (got $initialVersion)" + exit 1 + } # --check queries npm registry and prints update status vp upgrade --check @@ -511,9 +531,15 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} shell: cmd run: | - REM Save initial (dev build) version + REM See bash block above for why we pin to an older version first. + vp upgrade %UPGRADE_TEST_PIN_VERSION% --force + for /f "usebackq delims=" %%v in (`node -p "require(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version"`) do set INITIAL_VERSION=%%v echo Initial version: %INITIAL_VERSION% + if not "%INITIAL_VERSION%"=="%UPGRADE_TEST_PIN_VERSION%" ( + echo Error: failed to pin to %UPGRADE_TEST_PIN_VERSION%, got %INITIAL_VERSION% + exit /b 1 + ) REM --check queries npm registry and prints update status vp upgrade --check From 784dd7d7b8fb374ec6da6e1be059c51a76384cdd Mon Sep 17 00:00:00 2001 From: MK Date: Wed, 20 May 2026 16:47:20 +0800 Subject: [PATCH 2/4] ci: assert install-dir change instead of version change in upgrade test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous approach pinned to an older release first, but that caused `vp upgrade --force` to run from the *released* 0.1.21 binary instead of the dev build — so dev's upgrade logic wasn't actually exercised. Switch the assertion to verify that `~/.vite-plus/current` resolves to a different install directory after upgrade (dev `local-dev-/` → release `/`) and that rollback restores it. This exercises dev's full download/extract/swap path end-to-end, regardless of whether the dev version equals npm latest. Node's `fs.realpathSync` resolves both Unix symlinks and Windows junctions, so all three shells share the same helper. --- .github/workflows/ci.yml | 122 +++++++++++++++------------------------ 1 file changed, 48 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8efb209026..aca5b204fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -207,11 +207,6 @@ jobs: - os: windows-latest target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} - env: - # Any released version older than the current package.json version. - # Used by upgrade tests to create a guaranteed version delta against npm - # latest (otherwise `vp upgrade --force` is a no-op on release-day mains). - UPGRADE_TEST_PIN_VERSION: '0.1.21' steps: - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 - uses: ./.github/actions/clone @@ -424,23 +419,21 @@ jobs: - name: Test upgrade (bash) shell: bash run: | - # Helper to read the installed CLI version from package.json - get_cli_version() { - node -p "require(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version" + # Resolve `current` (symlink on Unix, junction on Windows) and return + # the install dir basename — "local-dev-" for the dev + # build, "" for a downloaded release. Node's realpathSync + # handles symlinks and junctions uniformly. + get_current_dirname() { + node -p "require('path').basename(require('fs').realpathSync(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current')))" } - # Pin to a known older version first so the upgrade-to-latest below - # has a version delta to assert against. Right after a release commit - # on main, the dev build's package.json version equals npm latest, so - # `vp upgrade --force` would be a no-op and the assertion would fail. - vp upgrade "$UPGRADE_TEST_PIN_VERSION" --force - - INITIAL_VERSION=$(get_cli_version) - echo "Initial version: $INITIAL_VERSION" - if [ "$INITIAL_VERSION" != "$UPGRADE_TEST_PIN_VERSION" ]; then - echo "Error: failed to pin to $UPGRADE_TEST_PIN_VERSION (got $INITIAL_VERSION)" - exit 1 - fi + # Assert on the `current` target dir, not the version: right after a + # release commit on main, the dev build's version equals npm latest, + # so `vp upgrade --force` succeeds but the version is unchanged. + # The dir flip (dev → release → dev) is the real signal that the + # download/extract/swap and rollback flows ran end-to-end. + INITIAL_DIR=$(get_current_dirname) + echo "Initial install dir: $INITIAL_DIR" # --check queries npm registry and prints update status vp upgrade --check @@ -452,24 +445,22 @@ jobs: ls -la ~/.vite-plus/ - # Verify version changed after update - UPDATED_VERSION=$(get_cli_version) - echo "Updated version: $UPDATED_VERSION" - if [ "$UPDATED_VERSION" == "$INITIAL_VERSION" ]; then - echo "Error: version should have changed after upgrade (still $INITIAL_VERSION)" + UPDATED_DIR=$(get_current_dirname) + echo "Updated install dir: $UPDATED_DIR" + if [ "$UPDATED_DIR" == "$INITIAL_DIR" ]; then + echo "Error: current install dir should have changed after upgrade (still $INITIAL_DIR)" exit 1 fi - # rollback to the previous version + # rollback to the previous install vp upgrade --rollback vp --version vp env doctor - # Verify version restored after rollback - ROLLBACK_VERSION=$(get_cli_version) - echo "Rollback version: $ROLLBACK_VERSION" - if [ "$ROLLBACK_VERSION" != "$INITIAL_VERSION" ]; then - echo "Error: version should have been restored after rollback (expected $INITIAL_VERSION, got $ROLLBACK_VERSION)" + ROLLBACK_DIR=$(get_current_dirname) + echo "Rollback install dir: $ROLLBACK_DIR" + if [ "$ROLLBACK_DIR" != "$INITIAL_DIR" ]; then + echo "Error: current install dir should have been restored after rollback (expected $INITIAL_DIR, got $ROLLBACK_DIR)" exit 1 fi @@ -481,20 +472,13 @@ jobs: . (Join-Path $vpHome 'env.ps1') Get-ChildItem $vpHome - # Helper to read the installed CLI version from package.json - function Get-CliVersion { - node -p "require(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version" + # See bash block above for why we assert on the install dir basename. + function Get-CurrentDirname { + node -p "require('path').basename(require('fs').realpathSync(require('path').resolve(process.env.USERPROFILE || process.env.HOME, '.vite-plus', 'current')))" } - # See bash block above for why we pin to an older version first. - vp upgrade $env:UPGRADE_TEST_PIN_VERSION --force - - $initialVersion = Get-CliVersion - Write-Host "Initial version: $initialVersion" - if ($initialVersion -ne $env:UPGRADE_TEST_PIN_VERSION) { - Write-Error "Error: failed to pin to $env:UPGRADE_TEST_PIN_VERSION (got $initialVersion)" - exit 1 - } + $initialDir = Get-CurrentDirname + Write-Host "Initial install dir: $initialDir" # --check queries npm registry and prints update status vp upgrade --check @@ -506,24 +490,22 @@ jobs: Get-ChildItem $vpHome - # Verify version changed after update - $updatedVersion = Get-CliVersion - Write-Host "Updated version: $updatedVersion" - if ($updatedVersion -eq $initialVersion) { - Write-Error "Error: version should have changed after upgrade (still $initialVersion)" + $updatedDir = Get-CurrentDirname + Write-Host "Updated install dir: $updatedDir" + if ($updatedDir -eq $initialDir) { + Write-Error "Error: current install dir should have changed after upgrade (still $initialDir)" exit 1 } - # rollback to the previous version + # rollback to the previous install vp upgrade --rollback vp --version vp env doctor - # Verify version restored after rollback - $rollbackVersion = Get-CliVersion - Write-Host "Rollback version: $rollbackVersion" - if ($rollbackVersion -ne $initialVersion) { - Write-Error "Error: version should have been restored after rollback (expected $initialVersion, got $rollbackVersion)" + $rollbackDir = Get-CurrentDirname + Write-Host "Rollback install dir: $rollbackDir" + if ($rollbackDir -ne $initialDir) { + Write-Error "Error: current install dir should have been restored after rollback (expected $initialDir, got $rollbackDir)" exit 1 } @@ -531,15 +513,9 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} shell: cmd run: | - REM See bash block above for why we pin to an older version first. - vp upgrade %UPGRADE_TEST_PIN_VERSION% --force - - for /f "usebackq delims=" %%v in (`node -p "require(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version"`) do set INITIAL_VERSION=%%v - echo Initial version: %INITIAL_VERSION% - if not "%INITIAL_VERSION%"=="%UPGRADE_TEST_PIN_VERSION%" ( - echo Error: failed to pin to %UPGRADE_TEST_PIN_VERSION%, got %INITIAL_VERSION% - exit /b 1 - ) + REM See bash block above for why we assert on the install dir basename. + for /f "usebackq delims=" %%v in (`node -p "require('path').basename(require('fs').realpathSync(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current')))"`) do set INITIAL_DIR=%%v + echo Initial install dir: %INITIAL_DIR% REM --check queries npm registry and prints update status vp upgrade --check @@ -551,24 +527,22 @@ jobs: dir "%USERPROFILE%\.vite-plus\" - REM Verify version changed after update - for /f "usebackq delims=" %%v in (`node -p "require(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version"`) do set UPDATED_VERSION=%%v - echo Updated version: %UPDATED_VERSION% - if "%UPDATED_VERSION%"=="%INITIAL_VERSION%" ( - echo Error: version should have changed after upgrade, still %INITIAL_VERSION% + for /f "usebackq delims=" %%v in (`node -p "require('path').basename(require('fs').realpathSync(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current')))"`) do set UPDATED_DIR=%%v + echo Updated install dir: %UPDATED_DIR% + if "%UPDATED_DIR%"=="%INITIAL_DIR%" ( + echo Error: current install dir should have changed after upgrade, still %INITIAL_DIR% exit /b 1 ) - REM rollback to the previous version + REM rollback to the previous install vp upgrade --rollback vp --version vp env doctor - REM Verify version restored after rollback - for /f "usebackq delims=" %%v in (`node -p "require(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current', 'node_modules', 'vite-plus', 'package.json')).version"`) do set ROLLBACK_VERSION=%%v - echo Rollback version: %ROLLBACK_VERSION% - if not "%ROLLBACK_VERSION%"=="%INITIAL_VERSION%" ( - echo Error: version should have been restored after rollback, expected %INITIAL_VERSION%, got %ROLLBACK_VERSION% + for /f "usebackq delims=" %%v in (`node -p "require('path').basename(require('fs').realpathSync(require('path').resolve(process.env.USERPROFILE, '.vite-plus', 'current')))"`) do set ROLLBACK_DIR=%%v + echo Rollback install dir: %ROLLBACK_DIR% + if not "%ROLLBACK_DIR%"=="%INITIAL_DIR%" ( + echo Error: current install dir should have been restored after rollback, expected %INITIAL_DIR%, got %ROLLBACK_DIR% exit /b 1 ) From e4556aecaadf39c6a65beaabf1d0680232bf8b1a Mon Sep 17 00:00:00 2001 From: MK Date: Wed, 20 May 2026 16:56:09 +0800 Subject: [PATCH 3/4] test(snap): query alpha tag in upgrade --check to avoid release-day flake The command-upgrade-check snap test was failing on PR CIs running after v0.1.22 shipped because dev's package.json version (0.1.22) now equals npm latest (0.1.22), so `vp upgrade --check` takes the "Already up to date" branch instead of the recorded "Update available" output. Query the `alpha` dist-tag instead. Alpha is always a different version from latest (currently 0.1.21-alpha.7), so the "Update available" branch is always taken and the snapshot is stable across release cycles. The semver normalization in the snap-test framework masks the actual version numbers, so the body of snap.txt is unchanged. Same root cause as the cli-e2e-test upgrade-bash fix in this PR; the snap test surfaced on PR #1635 first because that PR also triggered CI after the release. --- packages/cli/snap-tests-global/command-upgrade-check/snap.txt | 2 +- .../cli/snap-tests-global/command-upgrade-check/steps.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cli/snap-tests-global/command-upgrade-check/snap.txt b/packages/cli/snap-tests-global/command-upgrade-check/snap.txt index aac15e99dc..305fe64ef8 100644 --- a/packages/cli/snap-tests-global/command-upgrade-check/snap.txt +++ b/packages/cli/snap-tests-global/command-upgrade-check/snap.txt @@ -1,4 +1,4 @@ -> vp upgrade --check # check for updates without installing +> vp upgrade --check --tag alpha # alpha tag avoids release-day flake (dev version equals npm latest right after a release, hiding the Update-available branch) info: checking for updates... info: found vite-plus@ (current: ) Update available: diff --git a/packages/cli/snap-tests-global/command-upgrade-check/steps.json b/packages/cli/snap-tests-global/command-upgrade-check/steps.json index eeab1191db..dee7de1a2f 100644 --- a/packages/cli/snap-tests-global/command-upgrade-check/steps.json +++ b/packages/cli/snap-tests-global/command-upgrade-check/steps.json @@ -1,4 +1,6 @@ { "ignoredPlatforms": ["win32", { "os": "linux", "libc": "musl" }], - "commands": ["vp upgrade --check # check for updates without installing"] + "commands": [ + "vp upgrade --check --tag alpha # alpha tag avoids release-day flake (dev version equals npm latest right after a release, hiding the Update-available branch)" + ] } From 03fec6edecdbf8d1723dc4e2e0b0055ce890b6a1 Mon Sep 17 00:00:00 2001 From: MK Date: Wed, 20 May 2026 19:50:35 +0800 Subject: [PATCH 4/4] Fixup --- packages/cli/snap-tests-global/command-upgrade-check/snap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/snap-tests-global/command-upgrade-check/snap.txt b/packages/cli/snap-tests-global/command-upgrade-check/snap.txt index 305fe64ef8..9c1f99380b 100644 --- a/packages/cli/snap-tests-global/command-upgrade-check/snap.txt +++ b/packages/cli/snap-tests-global/command-upgrade-check/snap.txt @@ -1,5 +1,5 @@ > vp upgrade --check --tag alpha # alpha tag avoids release-day flake (dev version equals npm latest right after a release, hiding the Update-available branch) info: checking for updates... -info: found vite-plus@ (current: ) +info: found vite-plus@ Update available: Run `vp upgrade` to update.