refactor(dev): simplify local dev workflow #1537
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 create-related files changed | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| contains(github.event.pull_request.labels.*.name, 'test: create-e2e') || | |
| 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@ab97f03642370d79a7e96dd286bd02a1be40e0ba # v1.3.0 | |
| - 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 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" |