Skip to content

Dependency bots update vite-plus and the vite catalog alias out of lockstep #2356

Description

@fengmk2

What happens

vp create / vp migrate scaffold two entries that must move in lockstep (packages/cli/src/utils/constants.ts):

catalog:
  vite: npm:@voidzero-dev/vite-plus-core@0.2.8
  vite-plus: 0.2.8

To a dependency bot these are two unrelated packages, vite-plus and @voidzero-dev/vite-plus-core, so a normal Renovate configuration turns one Vite+ release into two independent PRs: one bumps vite-plus and leaves the alias at the old version, the other bumps the alias and leaves vite-plus at the old version. Each PR's CI, and the repo state after merging either one, runs vite-plus X against core Y, a pairing that is never released together. Nothing ties the two PRs to each other, and any per-package difference in schedule, minimumReleaseAge, or automerge policy pushes them further apart.

Real case: in voidzero-dev/setup.viteplus.dev#36 and voidzero-dev/setup.viteplus.dev#37, one PR reached vite-plus 0.2.8 with the alias still at 0.2.1 while the other reached the alias at 0.2.7 with vite-plus still at 0.2.1, and both sat open for a month. voidzero-dev/setup-vp#119 hit the same split through mismatched age gates. Every repo the migrator produces has this shape, so any Vite+ project with Renovate or Dependabot enabled is exposed. The exact vitest override from the same constants is the same class of problem: a bot can bump it away from the version bundled in vite-plus.

Repo-level workaround

A Renovate group rule puts the bumps in one PR so they move in lockstep:

{
  "groupName": "vite+",
  "matchPackageNames": ["vite-plus", "@voidzero-dev/vite-plus-*", "vitest"]
}

Include vitest when the project depends on it: vp pins the vitest override to the version bundled in vite-plus, so an independent vitest PR desyncs that pin the same way. Installed @vitest/coverage-* providers belong in the group too, since vp requires them aligned with the bundled vitest. Note that grouping keeps vitest in the same PR only when updates coincide; a vitest release with no simultaneous vite-plus release still produces a lone vitest bump ahead of the bundled version, which only the skew guard below catches.

minimumReleaseAge and schedule are only needed on top of this when some other rule treats the grouped packages differently. Grouping decides where an update lands, not when it becomes eligible; eligibility is still evaluated per package. With no other rules, all members inherit the same policy and the group rule alone keeps them in lockstep. But if another rule (commonly a shared org preset that special-cases vite-plus) gives members different minimumReleaseAge or schedule values, they become eligible at different times and the grouped PR ships with only the eligible members, recreating the mismatch. That is exactly what happened in voidzero-dev/setup-vp#119: vite-plus at 0 days, the alias behind a 3-day gate and a Monday schedule. In that case set both fields on the group rule so every member shares one value; a short buffer like "1 day" works well since the packages publish seconds apart and clear the gate together.

Merged examples: voidzero-dev/setup-vp#121, voidzero-dev/setup.viteplus.dev#42. But each repo has to rediscover this rule, and nothing fails when it is missing.

Ideas

  1. Ship an official Renovate preset in this repo (a checked-in default.json, consumed as "extends": ["github>voidzero-dev/vite-plus"]) with the group rule above plus the vitest handling. Document it in the migration guide; vp migrate could suggest it when the repo already has a Renovate config.
  2. Fail fast on skew: vp warns or errors when the resolved @voidzero-dev/vite-plus-core version differs from the CLI version, so a mismatched bot PR fails CI instead of shipping an untested pairing. The coverage-provider guard in define-config.ts is precedent for this kind of check.

The preset prevents the split for Renovate users; the guard catches everything else (Dependabot, manual edits).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions