diff --git a/.claude/skills/add-ecosystem-ci/SKILL.md b/.claude/skills/add-ecosystem-ci/SKILL.md index 11db2b3817..5cd461ae6e 100644 --- a/.claude/skills/add-ecosystem-ci/SKILL.md +++ b/.claude/skills/add-ecosystem-ci/SKILL.md @@ -25,7 +25,11 @@ gh api repos/OWNER/REPO/commits/BRANCH --jq '.sha' Fetch the repository's root to check if the main package.json is in a subdirectory (like `web/`, `app/`, `frontend/`). -### 2.2 Auto-detect Commands from GitHub Workflows +### 2.2 Check if Project Already Uses Vite-Plus + +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+". + +### 2.3 Auto-detect Commands from GitHub Workflows Fetch the project's GitHub workflow files to detect available commands: @@ -43,7 +47,7 @@ Look for common patterns in workflow files: - Commands like: `lint`, `build`, `test`, `type-check`, `typecheck`, `format`, `format:check` - Map detected commands to `vp` equivalents: `vp run lint`, `vp run build`, etc. -### 2.3 Ask User to Confirm +### 2.4 Ask User to Confirm Present the auto-detected configuration and ask user to confirm or modify: @@ -62,7 +66,8 @@ Present the auto-detected configuration and ask user to confirm or modify: "repository": "https://github.com/owner/repo.git", "branch": "main", "hash": "full-commit-sha", - "directory": "web" // only if subdirectory is needed + "directory": "web", // only if subdirectory is needed + "forceFreshMigration": true // only if project already uses vite-plus } } ``` @@ -110,4 +115,5 @@ node ecosystem-ci/clone.ts project-name - The `directory` field is optional - only add it if the package.json is not in the project root - If `directory` is specified in repo.json, it must also be specified in the workflow matrix - `patch-project.ts` automatically handles running `vp migrate` in the correct directory +- `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 - OS exclusions are added to the existing `exclude` section in the workflow matrix diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 316d0d7171..9cfa99d437 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -257,6 +257,13 @@ jobs: vp check vp pack vp test + - name: vinext + node-version: 24 + command: | + vp run build + vp check --fix + vp run check + vp run test exclude: # frm-stack uses Docker (testcontainers) which doesn't work the same way on Windows - os: windows-latest @@ -266,6 +273,10 @@ jobs: - os: windows-latest project: name: dify + # vinext uses workerd native deps that don't build on Windows + - os: windows-latest + project: + name: vinext steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 @@ -310,6 +321,11 @@ jobs: node $GITHUB_WORKSPACE/ecosystem-ci/patch-project.ts ${{ matrix.project.name }} vp install --no-frozen-lockfile + - name: Verify local tgz packages installed + working-directory: ${{ runner.temp }}/vite-plus-ecosystem-ci/${{ matrix.project.name }}${{ matrix.project.directory && format('/{0}', matrix.project.directory) || '' }} + shell: bash + run: node $GITHUB_WORKSPACE/ecosystem-ci/verify-install.ts + - name: Run vite-plus commands in ${{ matrix.project.name }} working-directory: ${{ runner.temp }}/vite-plus-ecosystem-ci/${{ matrix.project.name }}${{ matrix.project.directory && format('/{0}', matrix.project.directory) || '' }} run: ${{ matrix.project.command }} diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 9215eae5dd..b37bfc5a6a 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -21,18 +21,6 @@ const cwd = directory ? join(repoRoot, directory) : repoRoot; // run vp migrate const cli = process.env.VITE_PLUS_CLI_BIN ?? 'vp'; -// Projects that already have vite-plus need it removed before migration so -// vp migrate treats them as fresh and applies tgz overrides. Without this, -// vp migrate detects "already using Vite+" and skips override injection. -const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.forceFreshMigration; -if (forceFreshMigration) { - const pkgPath = join(cwd, 'package.json'); - const pkg = JSON.parse(await readFile(pkgPath, 'utf-8')); - delete pkg.devDependencies?.['vite-plus']; - delete pkg.dependencies?.['vite-plus']; - await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8'); -} - if (project === 'rollipop') { const oxfmtrc = await readFile(join(repoRoot, '.oxfmtrc.json'), 'utf-8'); await writeFile( @@ -42,11 +30,16 @@ if (project === 'rollipop') { ); } +// Projects that already use vite-plus need VITE_PLUS_FORCE_MIGRATE=1 so +// vp migrate runs full dependency rewriting instead of skipping. +const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.forceFreshMigration; + execSync(`${cli} migrate --no-agent --no-interactive`, { cwd, stdio: 'inherit', env: { ...process.env, + ...(forceFreshMigration ? { VITE_PLUS_FORCE_MIGRATE: '1' } : {}), VITE_PLUS_OVERRIDE_PACKAGES: JSON.stringify({ vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, vitest: `file:${tgzDir}/voidzero-dev-vite-plus-test-0.0.0.tgz`, diff --git a/ecosystem-ci/repo.json b/ecosystem-ci/repo.json index 65418adea2..f9d95dcba8 100644 --- a/ecosystem-ci/repo.json +++ b/ecosystem-ci/repo.json @@ -13,7 +13,8 @@ "vibe-dashboard": { "repository": "https://github.com/voidzero-dev/vibe-dashboard.git", "branch": "main", - "hash": "fcb0518e75e0f05e09ac910dcc88090220dfd3ae" + "hash": "158e4a0c3d8a1801e330300a5deba4506fd5dfb9", + "forceFreshMigration": true }, "rollipop": { "repository": "https://github.com/leegeunhyeok/rollipop.git", @@ -64,6 +65,13 @@ "vp-config": { "repository": "https://github.com/kazupon/vp-config.git", "branch": "main", - "hash": "b58c48d71a17c25dec71a003535e6312791ce2aa" + "hash": "b58c48d71a17c25dec71a003535e6312791ce2aa", + "forceFreshMigration": true + }, + "vinext": { + "repository": "https://github.com/cloudflare/vinext.git", + "branch": "main", + "hash": "f78dd2b39f5b02242417e0a684b1f2f55d3dbdff", + "forceFreshMigration": true } } diff --git a/ecosystem-ci/verify-install.ts b/ecosystem-ci/verify-install.ts new file mode 100644 index 0000000000..984994bded --- /dev/null +++ b/ecosystem-ci/verify-install.ts @@ -0,0 +1,17 @@ +import { createRequire } from 'node:module'; + +const require = createRequire(`${process.cwd()}/`); + +const expectedVersion = '0.0.0'; + +try { + const pkg = require('vite-plus/package.json') as { version: string; name: string }; + if (pkg.version !== expectedVersion) { + console.error(`✗ vite-plus: expected version ${expectedVersion}, got ${pkg.version}`); + process.exit(1); + } + console.log(`✓ vite-plus@${pkg.version}`); +} catch { + console.error('✗ vite-plus: not installed'); + process.exit(1); +} diff --git a/packages/cli/src/migration/bin.ts b/packages/cli/src/migration/bin.ts index 8606445634..24242ccd5e 100644 --- a/packages/cli/src/migration/bin.ts +++ b/packages/cli/src/migration/bin.ts @@ -18,6 +18,7 @@ import { selectAgentTargetPaths, writeAgentInstructions, } from '../utils/agent.js'; +import { isForceOverrideMode } from '../utils/constants.js'; import { detectEditorConflicts, type EditorId, @@ -747,8 +748,9 @@ async function main() { const resolvedPackageManager = workspaceInfoOptional.packageManager ?? 'unknown'; // Early return if already using Vite+ (only ESLint/hooks migration may be needed) + // In force-override mode (file: tgz overrides), skip this check and run full migration const rootPkg = readNearestPackageJson(workspaceInfoOptional.rootDir); - if (hasVitePlusDependency(rootPkg)) { + if (hasVitePlusDependency(rootPkg) && !isForceOverrideMode()) { let didMigrate = false; let installDurationMs = 0; const report = createMigrationReport(); diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 9a26d910db..0932320f27 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -22,6 +22,7 @@ import { VITE_PLUS_NAME, VITE_PLUS_OVERRIDE_PACKAGES, VITE_PLUS_VERSION, + isForceOverrideMode, } from '../utils/constants.js'; import { editJsonFile, isJsonFile, readJsonFile } from '../utils/json.js'; import { detectPackageMetadata } from '../utils/package.js'; @@ -982,16 +983,30 @@ function rewriteRootWorkspacePackageJson( ...VITE_PLUS_OVERRIDE_PACKAGES, }; } else if (packageManager === PackageManager.pnpm) { - // pnpm use overrides field at pnpm-workspace.yaml - // so we don't need to set overrides field at package.json - // remove packages from `resolutions` field and `pnpm.overrides` field if they exist - // https://pnpm.io/9.x/package_json#resolutions - for (const key of [...Object.keys(VITE_PLUS_OVERRIDE_PACKAGES), ...REMOVE_PACKAGES]) { - if (pkg.pnpm?.overrides?.[key]) { - delete pkg.pnpm.overrides[key]; - } - if (pkg.resolutions?.[key]) { - delete pkg.resolutions[key]; + if (isForceOverrideMode()) { + // In force-override mode, keep overrides in package.json pnpm.overrides + // because pnpm ignores pnpm-workspace.yaml overrides when pnpm.overrides + // exists in package.json (even with unrelated entries like rollup). + pkg.pnpm = { + ...pkg.pnpm, + overrides: { + ...pkg.pnpm?.overrides, + ...VITE_PLUS_OVERRIDE_PACKAGES, + [VITE_PLUS_NAME]: VITE_PLUS_VERSION, + }, + }; + } else { + // pnpm use overrides field at pnpm-workspace.yaml + // so we don't need to set overrides field at package.json + // remove packages from `resolutions` field and `pnpm.overrides` field if they exist + // https://pnpm.io/9.x/package_json#resolutions + for (const key of [...Object.keys(VITE_PLUS_OVERRIDE_PACKAGES), ...REMOVE_PACKAGES]) { + if (pkg.pnpm?.overrides?.[key]) { + delete pkg.pnpm.overrides[key]; + } + if (pkg.resolutions?.[key]) { + delete pkg.resolutions[key]; + } } } // remove dependency selector from vite, e.g. "vite-plugin-svgr>vite": "npm:vite@7.0.12" diff --git a/packages/cli/src/utils/constants.ts b/packages/cli/src/utils/constants.ts index 4adf161730..e9e901bc1b 100644 --- a/packages/cli/src/utils/constants.ts +++ b/packages/cli/src/utils/constants.ts @@ -11,6 +11,15 @@ export const VITE_PLUS_OVERRIDE_PACKAGES: Record = process.env vitest: 'npm:@voidzero-dev/vite-plus-test@latest', }; +/** + * When VITE_PLUS_FORCE_MIGRATE is set, force full dependency rewriting + * even for projects already using vite-plus. Used by ecosystem CI to + * override dependencies with locally built tgz packages. + */ +export function isForceOverrideMode(): boolean { + return process.env.VITE_PLUS_FORCE_MIGRATE === '1'; +} + const require = createRequire(import.meta.url); export function resolve(path: string) {