voidzero-dev / voidzero-dev/vite-plus

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

Open
#2,356 0 comments 1 reaction 1 assignee Claimed by @fengmk2 View on GitHub
Dominant language
Rust
Stars
5.8k
Forks
261
Avg merge
1d 34m
Merged PRs (30d)
135

Description

## What happens

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

```yaml
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:

```json
{
"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).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.