Skip to content

Commit cc37ea4

Browse files
committed
test(e2e): add cloudflare/vinext to ecosystem-ci (#1050)
- Add vinext to repo.json with forceFreshMigration (already uses vite-plus) - Add e2e matrix entry: build, check, test on node 24, ubuntu-only - Update add-ecosystem-ci skill to handle projects already using vite-plus
1 parent 38265d4 commit cc37ea4

File tree

8 files changed

+94
-28
lines changed

8 files changed

+94
-28
lines changed

.claude/skills/add-ecosystem-ci/SKILL.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ gh api repos/OWNER/REPO/commits/BRANCH --jq '.sha'
2525

2626
Fetch the repository's root to check if the main package.json is in a subdirectory (like `web/`, `app/`, `frontend/`).
2727

28-
### 2.2 Auto-detect Commands from GitHub Workflows
28+
### 2.2 Check if Project Already Uses Vite-Plus
29+
30+
Check the project's root `package.json` for `vite-plus` in `dependencies` or `devDependencies`. If the project already uses vite-plus, set `forceFreshMigration: true` in `repo.json`. This tells `patch-project.ts` to set `VITE_PLUS_FORCE_MIGRATE=1` so `vp migrate` forces full dependency rewriting instead of skipping with "already using Vite+".
31+
32+
### 2.3 Auto-detect Commands from GitHub Workflows
2933

3034
Fetch the project's GitHub workflow files to detect available commands:
3135

@@ -43,7 +47,7 @@ Look for common patterns in workflow files:
4347
- Commands like: `lint`, `build`, `test`, `type-check`, `typecheck`, `format`, `format:check`
4448
- Map detected commands to `vp` equivalents: `vp run lint`, `vp run build`, etc.
4549

46-
### 2.3 Ask User to Confirm
50+
### 2.4 Ask User to Confirm
4751

4852
Present the auto-detected configuration and ask user to confirm or modify:
4953

@@ -62,7 +66,8 @@ Present the auto-detected configuration and ask user to confirm or modify:
6266
"repository": "https://github.com/owner/repo.git",
6367
"branch": "main",
6468
"hash": "full-commit-sha",
65-
"directory": "web" // only if subdirectory is needed
69+
"directory": "web", // only if subdirectory is needed
70+
"forceFreshMigration": true // only if project already uses vite-plus
6671
}
6772
}
6873
```
@@ -110,4 +115,5 @@ node ecosystem-ci/clone.ts project-name
110115
- The `directory` field is optional - only add it if the package.json is not in the project root
111116
- If `directory` is specified in repo.json, it must also be specified in the workflow matrix
112117
- `patch-project.ts` automatically handles running `vp migrate` in the correct directory
118+
- `forceFreshMigration` is required for projects that already have `vite-plus` in their package.json — it sets `VITE_PLUS_FORCE_MIGRATE=1` so `vp migrate` forces full dependency rewriting instead of skipping
113119
- OS exclusions are added to the existing `exclude` section in the workflow matrix

.github/workflows/e2e-test.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ jobs:
257257
vp check
258258
vp pack
259259
vp test
260+
- name: vinext
261+
node-version: 24
262+
command: |
263+
vp run build
264+
vp check --fix
265+
vp run check
266+
vp run test
260267
exclude:
261268
# frm-stack uses Docker (testcontainers) which doesn't work the same way on Windows
262269
- os: windows-latest
@@ -266,6 +273,10 @@ jobs:
266273
- os: windows-latest
267274
project:
268275
name: dify
276+
# vinext uses workerd native deps that don't build on Windows
277+
- os: windows-latest
278+
project:
279+
name: vinext
269280

270281
steps:
271282
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
@@ -310,6 +321,11 @@ jobs:
310321
node $GITHUB_WORKSPACE/ecosystem-ci/patch-project.ts ${{ matrix.project.name }}
311322
vp install --no-frozen-lockfile
312323
324+
- name: Verify local tgz packages installed
325+
working-directory: ${{ runner.temp }}/vite-plus-ecosystem-ci/${{ matrix.project.name }}${{ matrix.project.directory && format('/{0}', matrix.project.directory) || '' }}
326+
shell: bash
327+
run: node $GITHUB_WORKSPACE/ecosystem-ci/verify-install.ts
328+
313329
- name: Run vite-plus commands in ${{ matrix.project.name }}
314330
working-directory: ${{ runner.temp }}/vite-plus-ecosystem-ci/${{ matrix.project.name }}${{ matrix.project.directory && format('/{0}', matrix.project.directory) || '' }}
315331
run: ${{ matrix.project.command }}

ecosystem-ci/patch-project.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,6 @@ const cwd = directory ? join(repoRoot, directory) : repoRoot;
2121
// run vp migrate
2222
const cli = process.env.VITE_PLUS_CLI_BIN ?? 'vp';
2323

24-
// Projects that already have vite-plus need it removed before migration so
25-
// vp migrate treats them as fresh and applies tgz overrides. Without this,
26-
// vp migrate detects "already using Vite+" and skips override injection.
27-
const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.forceFreshMigration;
28-
if (forceFreshMigration) {
29-
const pkgPath = join(cwd, 'package.json');
30-
const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
31-
delete pkg.devDependencies?.['vite-plus'];
32-
delete pkg.dependencies?.['vite-plus'];
33-
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
34-
}
35-
3624
if (project === 'rollipop') {
3725
const oxfmtrc = await readFile(join(repoRoot, '.oxfmtrc.json'), 'utf-8');
3826
await writeFile(
@@ -42,11 +30,16 @@ if (project === 'rollipop') {
4230
);
4331
}
4432

33+
// Projects that already use vite-plus need VITE_PLUS_FORCE_MIGRATE=1 so
34+
// vp migrate runs full dependency rewriting instead of skipping.
35+
const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.forceFreshMigration;
36+
4537
execSync(`${cli} migrate --no-agent --no-interactive`, {
4638
cwd,
4739
stdio: 'inherit',
4840
env: {
4941
...process.env,
42+
...(forceFreshMigration ? { VITE_PLUS_FORCE_MIGRATE: '1' } : {}),
5043
VITE_PLUS_OVERRIDE_PACKAGES: JSON.stringify({
5144
vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`,
5245
vitest: `file:${tgzDir}/voidzero-dev-vite-plus-test-0.0.0.tgz`,

ecosystem-ci/repo.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"vibe-dashboard": {
1414
"repository": "https://github.com/voidzero-dev/vibe-dashboard.git",
1515
"branch": "main",
16-
"hash": "fcb0518e75e0f05e09ac910dcc88090220dfd3ae"
16+
"hash": "158e4a0c3d8a1801e330300a5deba4506fd5dfb9",
17+
"forceFreshMigration": true
1718
},
1819
"rollipop": {
1920
"repository": "https://github.com/leegeunhyeok/rollipop.git",
@@ -64,6 +65,13 @@
6465
"vp-config": {
6566
"repository": "https://github.com/kazupon/vp-config.git",
6667
"branch": "main",
67-
"hash": "b58c48d71a17c25dec71a003535e6312791ce2aa"
68+
"hash": "b58c48d71a17c25dec71a003535e6312791ce2aa",
69+
"forceFreshMigration": true
70+
},
71+
"vinext": {
72+
"repository": "https://github.com/cloudflare/vinext.git",
73+
"branch": "main",
74+
"hash": "f78dd2b39f5b02242417e0a684b1f2f55d3dbdff",
75+
"forceFreshMigration": true
6876
}
6977
}

ecosystem-ci/verify-install.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createRequire } from 'node:module';
2+
3+
const require = createRequire(`${process.cwd()}/`);
4+
5+
const expectedVersion = '0.0.0';
6+
7+
try {
8+
const pkg = require('vite-plus/package.json') as { version: string; name: string };
9+
if (pkg.version !== expectedVersion) {
10+
console.error(`✗ vite-plus: expected version ${expectedVersion}, got ${pkg.version}`);
11+
process.exit(1);
12+
}
13+
console.log(`✓ vite-plus@${pkg.version}`);
14+
} catch {
15+
console.error('✗ vite-plus: not installed');
16+
process.exit(1);
17+
}

packages/cli/src/migration/bin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
selectAgentTargetPaths,
1919
writeAgentInstructions,
2020
} from '../utils/agent.js';
21+
import { isForceOverrideMode } from '../utils/constants.js';
2122
import {
2223
detectEditorConflicts,
2324
type EditorId,
@@ -747,8 +748,9 @@ async function main() {
747748
const resolvedPackageManager = workspaceInfoOptional.packageManager ?? 'unknown';
748749

749750
// Early return if already using Vite+ (only ESLint/hooks migration may be needed)
751+
// In force-override mode (file: tgz overrides), skip this check and run full migration
750752
const rootPkg = readNearestPackageJson<PackageDependencies>(workspaceInfoOptional.rootDir);
751-
if (hasVitePlusDependency(rootPkg)) {
753+
if (hasVitePlusDependency(rootPkg) && !isForceOverrideMode()) {
752754
let didMigrate = false;
753755
let installDurationMs = 0;
754756
const report = createMigrationReport();

packages/cli/src/migration/migrator.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
VITE_PLUS_NAME,
2323
VITE_PLUS_OVERRIDE_PACKAGES,
2424
VITE_PLUS_VERSION,
25+
isForceOverrideMode,
2526
} from '../utils/constants.js';
2627
import { editJsonFile, isJsonFile, readJsonFile } from '../utils/json.js';
2728
import { detectPackageMetadata } from '../utils/package.js';
@@ -982,16 +983,30 @@ function rewriteRootWorkspacePackageJson(
982983
...VITE_PLUS_OVERRIDE_PACKAGES,
983984
};
984985
} else if (packageManager === PackageManager.pnpm) {
985-
// pnpm use overrides field at pnpm-workspace.yaml
986-
// so we don't need to set overrides field at package.json
987-
// remove packages from `resolutions` field and `pnpm.overrides` field if they exist
988-
// https://pnpm.io/9.x/package_json#resolutions
989-
for (const key of [...Object.keys(VITE_PLUS_OVERRIDE_PACKAGES), ...REMOVE_PACKAGES]) {
990-
if (pkg.pnpm?.overrides?.[key]) {
991-
delete pkg.pnpm.overrides[key];
992-
}
993-
if (pkg.resolutions?.[key]) {
994-
delete pkg.resolutions[key];
986+
if (isForceOverrideMode()) {
987+
// In force-override mode, keep overrides in package.json pnpm.overrides
988+
// because pnpm ignores pnpm-workspace.yaml overrides when pnpm.overrides
989+
// exists in package.json (even with unrelated entries like rollup).
990+
pkg.pnpm = {
991+
...pkg.pnpm,
992+
overrides: {
993+
...pkg.pnpm?.overrides,
994+
...VITE_PLUS_OVERRIDE_PACKAGES,
995+
[VITE_PLUS_NAME]: VITE_PLUS_VERSION,
996+
},
997+
};
998+
} else {
999+
// pnpm use overrides field at pnpm-workspace.yaml
1000+
// so we don't need to set overrides field at package.json
1001+
// remove packages from `resolutions` field and `pnpm.overrides` field if they exist
1002+
// https://pnpm.io/9.x/package_json#resolutions
1003+
for (const key of [...Object.keys(VITE_PLUS_OVERRIDE_PACKAGES), ...REMOVE_PACKAGES]) {
1004+
if (pkg.pnpm?.overrides?.[key]) {
1005+
delete pkg.pnpm.overrides[key];
1006+
}
1007+
if (pkg.resolutions?.[key]) {
1008+
delete pkg.resolutions[key];
1009+
}
9951010
}
9961011
}
9971012
// remove dependency selector from vite, e.g. "vite-plugin-svgr>vite": "npm:vite@7.0.12"

packages/cli/src/utils/constants.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ export const VITE_PLUS_OVERRIDE_PACKAGES: Record<string, string> = process.env
1111
vitest: 'npm:@voidzero-dev/vite-plus-test@latest',
1212
};
1313

14+
/**
15+
* When VITE_PLUS_FORCE_MIGRATE is set, force full dependency rewriting
16+
* even for projects already using vite-plus. Used by ecosystem CI to
17+
* override dependencies with locally built tgz packages.
18+
*/
19+
export function isForceOverrideMode(): boolean {
20+
return process.env.VITE_PLUS_FORCE_MIGRATE === '1';
21+
}
22+
1423
const require = createRequire(import.meta.url);
1524

1625
export function resolve(path: string) {

0 commit comments

Comments
 (0)