Skip to content

feat(cli): fail fast when the vite alias skews from the CLI version - #2462

Draft
fengmk2 wants to merge 6 commits into
mainfrom
feat/core-version-skew-guard
Draft

feat(cli): fail fast when the vite alias skews from the CLI version#2462
fengmk2 wants to merge 6 commits into
mainfrom
feat/core-version-skew-guard

Conversation

@fengmk2

@fengmk2 fengmk2 commented Aug 16, 2026

Copy link
Copy Markdown
Member

vp create/vp migrate scaffold vite-plus and the vite alias (npm:@voidzero-dev/vite-plus-core@<same version>) as two entries that must move in lockstep. Dependency bots treat them as unrelated packages and bump them in separate PRs, so a repo ends up running a vite-plus/core pairing that was never published together, and nothing fails. See #2356 for real cases (voidzero-dev/setup.viteplus.dev#36/#37, voidzero-dev/setup-vp#119).

This adds the fail-fast guard from #2356 idea 2: the vite and test resolvers read what vite resolves to from the project and error when it is @voidzero-dev/vite-plus-core at a version different from the running CLI. A mismatched bot PR now fails vp dev/vp build/vp preview/vp test in CI with instructions to realign the alias (or run vp migrate). Because vp run tasks that invoke vp build/vp test synthesize the same resolvers in-process, they are covered too.

The check skips projects on real Vite, projects where vite is not resolvable, preview/override flows (VP_VERSION set), and the VP_SKIP_CORE_VERSION_CHECK=1 escape hatch. vp install, vp migrate, vp lint, and vp fmt are untouched, so the repair path stays open after a bad merge.

Covered by unit tests and a PTY snapshot case (core_version_guard) that shadows the runner's vite link with a core at a version the CLI never shipped with; the error message keeps every version inside the @voidzero-dev/vite-plus-core@<x> form so the existing snapshot redaction masks it and the case survives release bumps.

Follow-ups tracked in #2356: an official Renovate preset plus docs, and possibly extending the guard to the pinned vitest override.

Refs #2356

@netlify

netlify Bot commented Aug 16, 2026

Copy link
Copy Markdown

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit 8e0b89b
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a82c03de1e1fe000812e801

@fengmk2
fengmk2 marked this pull request as draft August 16, 2026 09:47
Comment thread packages/cli/src/utils/core-version-guard.ts Outdated
@fengmk2
fengmk2 marked this pull request as ready for review August 16, 2026 09:59
@fengmk2
fengmk2 marked this pull request as draft August 16, 2026 10:09
@fengmk2

fengmk2 commented Aug 16, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bb256e084

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/utils/core-version-guard.ts Outdated
Comment thread packages/cli/src/utils/core-version-guard.ts Outdated
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Native binary sizes (8e0b89b)

Final release artifacts built by the canonical build-upstream and build-windows-cli actions.

Artifact Format Base PR Change
vp (Linux x64) Binary 10.67 MiB 10.67 MiB 0 B (0.00%)
vp (Linux x64) gzip -9 4.62 MiB 4.62 MiB 0 B (0.00%)
NAPI (Linux x64) Binary 32.02 MiB 32.03 MiB +4.00 KiB (+0.01%)
NAPI (Linux x64) gzip -9 12.61 MiB 12.61 MiB -89 B (-0.00%)
vp (macOS ARM64) Binary 7.98 MiB 7.98 MiB 0 B (0.00%)
vp (macOS ARM64) gzip -9 4.03 MiB 4.03 MiB 0 B (0.00%)
NAPI (macOS ARM64) Binary 39.68 MiB 39.68 MiB 0 B (0.00%)
NAPI (macOS ARM64) gzip -9 16.92 MiB 16.92 MiB +2.78 KiB (+0.02%)
vp (Windows x64) Binary 8.55 MiB 8.55 MiB 0 B (0.00%)
vp (Windows x64) gzip -9 3.73 MiB 3.73 MiB 0 B (0.00%)
NAPI (Windows x64) Binary 26.89 MiB 26.90 MiB +4.50 KiB (+0.02%)
NAPI (Windows x64) gzip -9 10.68 MiB 10.68 MiB +54 B (+0.00%)
Trampoline (Windows x64) Binary 205.00 KiB 205.00 KiB 0 B (0.00%)
Trampoline (Windows x64) gzip -9 99.00 KiB 99.00 KiB 0 B (0.00%)
Installer (Windows x64) Binary 4.47 MiB 4.47 MiB 0 B (0.00%)
Installer (Windows x64) gzip -9 2.09 MiB 2.09 MiB 0 B (0.00%)

vp create / vp migrate scaffold two entries that must move in lockstep:
the vite-plus dependency and the vite alias
(npm:@voidzero-dev/vite-plus-core@<same version>). A dependency bot sees
two unrelated packages and bumps them in separate PRs, leaving a project
on a CLI/core pairing that was never published together. The skew is
silent: the CLI executes its own core dependency while plugins and
configs importing vite load the aliased copy at the other version.

The vite and test resolvers now check what vite resolves to from the
project and error when it is @voidzero-dev/vite-plus-core at a version
different from the CLI, so vp dev/build/preview/test fail the mismatched
bot PR in CI instead of shipping the pairing. The check skips real Vite
installs, projects without vite, preview flows (VP_VERSION), and the
VP_SKIP_CORE_VERSION_CHECK=1 escape hatch.

Refs #2356
The fixture's node_modules/vite/package.json is the shadowed core copy
the case depends on; the root node_modules gitignore entry excluded it
from the previous commit.
The alias can live in a catalog, overrides, resolutions, or a direct
dependency spec depending on the package manager, so the error hint no
longer names pnpm.
Review cleanups from a four-angle pass:

- Reuse detectPackageMetadata for the project vite lookup instead of a
  hand-rolled createRequire/readFile resolver; this also covers Yarn PnP
  and exports-blocked package.json layouts for free.
- Derive the expected version by parsing the vite alias spec the CLI
  scaffolds (VITE_PLUS_OVERRIDE_PACKAGES.vite) instead of special-casing
  the VP_VERSION env var. The Rust CLI injects VP_VERSION into every
  child env, so nested vp runs would have silently lost the check; a
  non-exact spec (preview tarball, file:) now skips by shape instead.
- Move the core package name into constants.ts next to VITE_PLUS_NAME.
- Memoize the check for the resolver path: resolvers fire once per
  intercepted script command, so a workspace run repeated the same read.
- Collapse the guard's input to the aliased core version (string or
  null), drop the injectable deps plumbing, and test the orchestrator
  against real temp fixture dirs.

The user-facing error message is unchanged; the recorded PTY snapshot
passes without re-recording.
Two review findings on the skew guard:

- The expected core version came from VITE_PLUS_VERSION, which VP_VERSION
  overrides. The installer docs tell PowerShell users to set VP_VERSION
  for the session, and the Rust CLI injects it into every child env, so
  an aligned project could fail (or a stale pairing pass) against an
  inherited value. The guard now compares against the running CLI
  package's own version (CLI_PACKAGE_VERSION); preview and ecosystem
  builds publish CLI and core from one commit, so no spec-shape skip is
  needed and the alias parsing is gone.

- The guard resolved vite from the process cwd, so retargeted runs
  (defaultPackage, vp run -r script commands) checked the invocation
  root instead of the package the command executes in. The Rust
  resolver now forwards each command's cwd to the JS resolvers, and the
  guard memoizes per directory.
@fengmk2
fengmk2 force-pushed the feat/core-version-skew-guard branch from 85a099c to bc56e4d Compare August 17, 2026 07:23
@fengmk2

fengmk2 commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc56e4d460

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/binding/src/cli/resolver.rs Outdated
vp build apps/web (or an explicit -c apps/web/vite.config.ts) rebases
Vite's config lookup onto the selected root while the process cwd stays
put, so the guard checked the wrong directory: a skewed app alias could
pass and a skewed root alias could reject an aligned app.

The vite resolver arms now derive the guard directory from the args
with the same cac/mri walk app_target already uses for elicitation: the
parent of an explicit -c/--config file wins, else the [root]
positional, else the command cwd. The snapshot case gains a
positional-root step that vendors a real-vite-shaped package in app/,
so it only passes when the guard checks the selected root instead of
the workspace cwd.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant