ci: pin cargo-zigbuild to git rev to fix aarch64-musl link failure #2120
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test vp create | |
| permissions: {} | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'packages/cli/src/create/**' | |
| - 'packages/cli/templates/**' | |
| - 'packages/cli/src/migration/**' | |
| - '.github/workflows/test-vp-create.yml' | |
| pull_request: | |
| types: [opened, synchronize, labeled] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: ${{ github.ref_name != 'main' }} | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| detect-changes: | |
| runs-on: namespace-profile-linux-x64-default | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| related-files-changed: ${{ steps.filter.outputs.related-files }} | |
| steps: | |
| - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 | |
| - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 | |
| id: filter | |
| with: | |
| filters: | | |
| related-files: | |
| - 'packages/cli/src/create/**' | |
| - 'packages/cli/templates/**' | |
| - 'packages/cli/src/migration/**' | |
| - .github/workflows/test-vp-create.yml | |
| download-previous-rolldown-binaries: | |
| needs: detect-changes | |
| runs-on: namespace-profile-linux-x64-default | |
| # Run if: not a PR, OR PR has 'test: create-e2e' label, OR PR is from the deps/upstream-update or a renovate/** dependency branch, OR create-related files changed | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| contains(github.event.pull_request.labels.*.name, 'test: create-e2e') || | |
| github.head_ref == 'deps/upstream-update' || | |
| startsWith(github.head_ref, 'renovate/') || | |
| needs.detect-changes.outputs.related-files-changed == 'true' | |
| permissions: | |
| contents: read | |
| packages: read | |
| steps: | |
| - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 | |
| - uses: ./.github/actions/download-rolldown-binaries | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| build: | |
| name: Build vite-plus packages | |
| runs-on: namespace-profile-linux-x64-default | |
| permissions: | |
| contents: read | |
| packages: read | |
| needs: | |
| - download-previous-rolldown-binaries | |
| steps: | |
| - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 | |
| - uses: ./.github/actions/clone | |
| - uses: oxc-project/setup-rust@68c3199c5339f965e6e163924c3c450773eba42b # main (pending v1.0.17 — Swatinem/rust-cache v2.9.1 for node24) | |
| with: | |
| save-cache: ${{ github.ref_name == 'main' }} | |
| cache-key: create-e2e-build | |
| - uses: oxc-project/setup-node@4c588e9266bd930b6ddc34307df0659ed511d187 # v1.3.1 | |
| - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: rolldown-binaries | |
| path: ./rolldown/packages/rolldown/src | |
| merge-multiple: true | |
| - name: Build with upstream | |
| uses: ./.github/actions/build-upstream | |
| with: | |
| target: x86_64-unknown-linux-gnu | |
| - name: Pack packages into tgz | |
| run: | | |
| mkdir -p tmp/tgz | |
| cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. | |
| cd packages/test && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. | |
| cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. | |
| # Copy vp binary for test jobs | |
| cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp | |
| ls -la tmp/tgz | |
| - name: Upload tgz artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: vite-plus-packages | |
| path: tmp/tgz/ | |
| retention-days: 1 | |
| test-vp-create: | |
| name: vp create ${{ matrix.template.name }} (${{ matrix.package-manager }}) | |
| runs-on: namespace-profile-linux-x64-default | |
| permissions: | |
| contents: read | |
| needs: | |
| - build | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| template: | |
| - name: monorepo | |
| create-args: vite:monorepo --directory test-project | |
| template-args: '' | |
| verify-command: vp run ready | |
| verify-migration: 'false' | |
| - name: application | |
| create-args: vite:application --directory test-project | |
| template-args: '-- --template vanilla-ts' | |
| verify-command: vp run build | |
| verify-migration: 'false' | |
| - name: library | |
| create-args: vite:library --directory test-project | |
| template-args: '' | |
| verify-command: | | |
| vp run build | |
| vp run test | |
| verify-migration: 'false' | |
| # Remote template that ships ESLint (+ an eslint.config.js importing | |
| # @eslint/js etc.). Exercises the migrate-before-rewrite reorder in | |
| # `vp create`: after scaffold, ESLint → oxlint and Prettier → oxfmt | |
| # run before the vite-plus rewrite so `.oxlintrc` / `.oxfmtrc` get | |
| # merged into vite.config.ts. | |
| - name: remote-vite-react-ts | |
| create-args: vite@9.0.5 | |
| template-args: '-- test-project --template react-ts' | |
| verify-command: vp run build | |
| verify-migration: 'true' | |
| package-manager: | |
| - pnpm | |
| - npm | |
| - yarn | |
| - bun | |
| env: | |
| # Force full dependency rewriting so the library template's existing | |
| # vite-plus dep gets overridden with the local tgz | |
| VP_FORCE_MIGRATE: '1' | |
| steps: | |
| - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| - name: Download vite-plus packages | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: vite-plus-packages | |
| path: tmp/tgz | |
| - name: Resolve tgz paths | |
| run: | | |
| CLI_TGZ=$(ls "$GITHUB_WORKSPACE"/tmp/tgz/vite-plus-[0-9]*.tgz | head -n1) | |
| CORE_TGZ=$(ls "$GITHUB_WORKSPACE"/tmp/tgz/voidzero-dev-vite-plus-core-[0-9]*.tgz | head -n1) | |
| TEST_TGZ=$(ls "$GITHUB_WORKSPACE"/tmp/tgz/voidzero-dev-vite-plus-test-[0-9]*.tgz | head -n1) | |
| echo "CLI_TGZ=$CLI_TGZ" >> $GITHUB_ENV | |
| echo "VP_VERSION=file:$CLI_TGZ" >> $GITHUB_ENV | |
| printf 'VP_OVERRIDE_PACKAGES={"vite":"file:%s","vitest":"file:%s","@voidzero-dev/vite-plus-core":"file:%s","@voidzero-dev/vite-plus-test":"file:%s"}\n' \ | |
| "$CORE_TGZ" "$TEST_TGZ" "$CORE_TGZ" "$TEST_TGZ" >> $GITHUB_ENV | |
| - name: Install vp CLI | |
| run: | | |
| mkdir -p target/release | |
| cp tmp/tgz/vp target/release/vp | |
| chmod +x target/release/vp | |
| node $GITHUB_WORKSPACE/packages/tools/src/install-global-cli.ts --tgz "$CLI_TGZ" | |
| echo "$HOME/.vite-plus/bin" >> $GITHUB_PATH | |
| - name: Verify vp installation | |
| run: | | |
| which vp | |
| vp --version | |
| - name: Run vp create ${{ matrix.template.name }} with ${{ matrix.package-manager }} | |
| working-directory: ${{ runner.temp }} | |
| run: | | |
| vp create ${{ matrix.template.create-args }} \ | |
| --no-interactive \ | |
| --no-agent \ | |
| --package-manager ${{ matrix.package-manager }} \ | |
| ${{ matrix.template.template-args }} | |
| - name: Verify project structure | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: | | |
| # package.json must exist | |
| test -f package.json | |
| echo "✓ package.json exists" | |
| cat package.json | |
| # List all files for debugging | |
| echo "--- Project root files ---" | |
| ls -la | |
| # Check correct lockfile exists | |
| case "${{ matrix.package-manager }}" in | |
| pnpm) | |
| test -f pnpm-lock.yaml | |
| echo "✓ pnpm-lock.yaml exists" | |
| ;; | |
| npm) | |
| test -f package-lock.json | |
| echo "✓ package-lock.json exists" | |
| ;; | |
| yarn) | |
| test -f yarn.lock | |
| echo "✓ yarn.lock exists" | |
| ;; | |
| bun) | |
| if [ -f bun.lock ]; then | |
| echo "✓ bun.lock exists" | |
| elif [ -f bun.lockb ]; then | |
| echo "✓ bun.lockb exists" | |
| else | |
| echo "✗ No bun lockfile found" | |
| exit 1 | |
| fi | |
| ;; | |
| esac | |
| # node_modules must exist (vp install ran successfully) | |
| test -d node_modules | |
| echo "✓ node_modules exists" | |
| # Monorepo-specific checks | |
| if [ "${{ matrix.template.name }}" = "monorepo" ]; then | |
| test -d apps/website | |
| echo "✓ apps/website exists" | |
| test -d packages/utils | |
| echo "✓ packages/utils exists" | |
| case "${{ matrix.package-manager }}" in | |
| pnpm) | |
| test -f pnpm-workspace.yaml | |
| echo "✓ pnpm-workspace.yaml exists" | |
| ;; | |
| yarn) | |
| test -f .yarnrc.yml | |
| echo "✓ .yarnrc.yml exists" | |
| ;; | |
| esac | |
| fi | |
| - name: Verify local tgz packages installed | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: | | |
| node -e " | |
| const path = require('path'); | |
| const expected = require('$GITHUB_WORKSPACE/packages/cli/package.json').version; | |
| const pkg = require(path.resolve('node_modules/vite-plus/package.json')); | |
| if (pkg.version !== expected) { | |
| console.error('Expected vite-plus@' + expected + ', got ' + pkg.version); | |
| process.exit(1); | |
| } | |
| console.log('✓ vite-plus@' + pkg.version + ' installed correctly'); | |
| " | |
| - name: Verify monorepo sub-package deps | |
| if: matrix.template.name == 'monorepo' | |
| working-directory: ${{ runner.temp }}/test-project | |
| env: | |
| PACKAGE_MANAGER: ${{ matrix.package-manager }} | |
| run: | | |
| # Issue 1: packages/utils inherits `vite-plus: ^x.y.z` from the | |
| # library template. In catalog-supporting monorepos (pnpm/yarn/bun) | |
| # the migrator must normalize it so siblings don't drift. | |
| # Issue 2: apps/website is scaffolded by create-vite which ships | |
| # `vite` (and sometimes `vitest`) in devDependencies. After | |
| # migration the scripts are rewritten to `vp ...` and `vite-plus` | |
| # brings the runtime in transitively. For npm/yarn/bun those keys | |
| # are dropped (the root overrides/resolutions redirect the | |
| # transitive/peer vite to @voidzero-dev/vite-plus-core regardless). | |
| # For pnpm the aliased `vite` is kept on purpose: pnpm only surfaces | |
| # the pnpm-workspace.yaml `overrides.vite: catalog:` entry through a | |
| # package that directly depends on `vite`, so dropping it would make | |
| # `vp why vite` report upstream vite and the override look ineffective. | |
| node -e " | |
| const fs = require('fs'); | |
| const pm = process.env.PACKAGE_MANAGER; | |
| for (const f of ['apps/website/package.json', 'packages/utils/package.json']) { | |
| if (!fs.existsSync(f)) { | |
| console.error('✗ expected ' + f + ' to exist after vp create vite:monorepo'); | |
| process.exit(1); | |
| } | |
| } | |
| const app = JSON.parse(fs.readFileSync('apps/website/package.json', 'utf8')); | |
| const utils = JSON.parse(fs.readFileSync('packages/utils/package.json', 'utf8')); | |
| const appDev = app.devDependencies || {}; | |
| const utilsDev = utils.devDependencies || {}; | |
| if (pm === 'pnpm') { | |
| if (!appDev['vite']) { | |
| console.error('✗ pnpm apps/website should keep aliased vite so the workspace override stays effective'); | |
| process.exit(1); | |
| } | |
| console.log('✓ pnpm apps/website keeps aliased vite'); | |
| } else { | |
| for (const name of ['vite', 'vitest']) { | |
| if (appDev[name]) { | |
| console.error('✗ apps/website devDependencies still has ' + name + ': ' + appDev[name]); | |
| process.exit(1); | |
| } | |
| } | |
| console.log('✓ apps/website devDependencies has no vite/vitest'); | |
| } | |
| if (!appDev['vite-plus']) { | |
| console.error('✗ apps/website missing vite-plus devDependency'); | |
| process.exit(1); | |
| } | |
| if (!utilsDev['vite-plus']) { | |
| console.error('✗ packages/utils missing vite-plus devDependency'); | |
| process.exit(1); | |
| } | |
| if (pm !== 'npm' && appDev['vite-plus'] !== utilsDev['vite-plus']) { | |
| console.error('✗ vite-plus spec drift: apps/website=' + appDev['vite-plus'] + ' packages/utils=' + utilsDev['vite-plus']); | |
| process.exit(1); | |
| } | |
| console.log('✓ vite-plus consistent across sub-packages: app=' + appDev['vite-plus'] + ' utils=' + utilsDev['vite-plus']); | |
| " | |
| - name: Verify ESLint/Prettier auto-migration | |
| if: matrix.template.verify-migration == 'true' | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: | | |
| # eslint.config.js must be gone (migration deleted it) | |
| test ! -f eslint.config.js | |
| echo "✓ eslint.config.js removed" | |
| # .oxlintrc.json must NOT be loose on disk — it was merged into | |
| # vite.config.ts by the rewrite step that runs after migration. | |
| test ! -f .oxlintrc.json | |
| echo "✓ .oxlintrc.json merged into vite.config.ts" | |
| # vite.config.ts must contain the merged oxlint config. | |
| grep -q '^[[:space:]]*lint:' vite.config.ts | |
| echo "✓ vite.config.ts has merged lint section" | |
| # package.json: eslint devDep removed, vite-plus present, lint script rewritten. | |
| node -e " | |
| const pkg = require('./package.json'); | |
| if (pkg.devDependencies && pkg.devDependencies.eslint) { | |
| console.error('✗ eslint devDependency should have been removed'); | |
| process.exit(1); | |
| } | |
| if (!pkg.devDependencies || !pkg.devDependencies['vite-plus']) { | |
| console.error('✗ vite-plus devDependency missing'); | |
| process.exit(1); | |
| } | |
| if (!pkg.scripts || !pkg.scripts.lint || !pkg.scripts.lint.includes('vp lint')) { | |
| console.error('✗ lint script should invoke vp lint, got: ' + (pkg.scripts && pkg.scripts.lint)); | |
| process.exit(1); | |
| } | |
| console.log('✓ package.json migrated (eslint gone, vite-plus added, lint script rewritten)'); | |
| " | |
| - name: Run vp check | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: vp check | |
| - name: Verify project builds | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: ${{ matrix.template.verify-command }} | |
| - name: Verify cache (monorepo only) | |
| if: matrix.template.name == 'monorepo' | |
| working-directory: ${{ runner.temp }}/test-project | |
| run: | | |
| # Under npm, `vp run ready` reaches 100% cache hit only on the | |
| # third invocation (#1638): vite-task's directory-listing | |
| # fingerprint and fspy read/write tracking surface false-positive | |
| # misses on run #2 because `packages/utils/node_modules/` is born | |
| # during run #1. pnpm/yarn/bun pre-create per-package | |
| # `node_modules/` at install time and reach 100% on run #2. | |
| # The preceding `Verify project builds` step already invoked | |
| # `vp run ready` once (verify-command for monorepo), so one | |
| # extra warm-up here is enough under npm. | |
| if [ "${{ matrix.package-manager }}" = "npm" ]; then | |
| vp run ready >/dev/null 2>&1 | |
| fi | |
| output=$(vp run ready 2>&1) | |
| echo "$output" | |
| if ! echo "$output" | grep -q 'cache hit (100%)'; then | |
| echo "✗ Expected 100% cache hit" | |
| echo "--- vp run --last-details (cache-miss diagnostics) ---" | |
| vp run --last-details || true | |
| exit 1 | |
| fi | |
| echo "✓ 100% cache hit verified" |