diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 176449cd03..3b80b2cd9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,21 +3,46 @@ name: CI on: push: - paths-ignore: - - '**/*.md' branches: [next] pull_request: - types: [opened, synchronize] - paths-ignore: - - '**/*.md' + types: [opened, synchronize, reopened] branches: [next] merge_group: + workflow_dispatch: permissions: + contents: read + pull-requests: read id-token: write actions: write +concurrency: + group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: + plan: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.plan.outputs.matrix }} + tests: ${{ steps.plan.outputs.tests }} + profile: ${{ steps.plan.outputs.profile }} + coverage-node: ${{ steps.node.outputs.node-version }} + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + id: node + with: + node-version: '24' + check-latest: true + - name: Check CI planning and coverage guards + run: node --test scripts/test/ci.test.js + - name: Plan tests + id: plan + env: + GH_TOKEN: ${{ github.token }} + run: node scripts/ci-plan.js + typecheck: runs-on: ubuntu-latest @@ -65,29 +90,20 @@ jobs: run: ut run site:build test: + needs: plan + if: needs.plan.outputs.tests == 'true' strategy: fail-fast: false - matrix: - os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] - node: ['22', '24', '26'] - coverage: [false] - # Replace (not duplicate) the ubuntu/24 leg with a coverage-enabled one. - # `include` cannot overwrite an existing matrix dimension, so the base - # coverage:false combo must be excluded first or ubuntu/24 would run twice. - exclude: - - os: 'ubuntu-latest' - node: '24' - coverage: false - include: - - os: 'ubuntu-latest' - node: '24' - coverage: true + matrix: ${{ fromJSON(needs.plan.outputs.matrix) }} - name: Test (${{ matrix.os }}, ${{ matrix.node }}) + name: Test (${{ matrix.os }}, ${{ matrix.node }}, ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}) runs-on: ${{ matrix.os }} + env: + CI_TEST_REPORT: '1' + CI_COVERAGE_REPORT: ${{ matrix.coverage && '1' || '0' }} concurrency: - group: test-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }}) + group: test-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-${{ matrix.os }}-${{ matrix.node }}-${{ matrix.shardIndex }} cancel-in-progress: true steps: @@ -190,7 +206,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: - node-version: ${{ matrix.node }} + node-version: ${{ matrix.coverage && needs.plan.outputs.coverage-node || matrix.node }} - name: Cache Node compile cache uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 @@ -199,7 +215,6 @@ jobs: key: node-compile-cache-${{ runner.os }}-node${{ matrix.node }}-${{ hashFiles('pnpm-workspace.yaml', '**/package.json') }} restore-keys: | node-compile-cache-${{ runner.os }}-node${{ matrix.node }}- - node-compile-cache-${{ runner.os }}- - name: Enable Node compile cache # runner.* is not available in job-level env, so export NODE_COMPILE_CACHE @@ -222,36 +237,60 @@ jobs: - name: Run tests (with coverage) if: ${{ matrix.coverage }} - run: ut run ci + run: ut run ci -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - name: Run tests if: ${{ !matrix.coverage }} - run: ut run test - - # Summarize how parallel the full-isolate-off suite actually ran. The gating - # test run above (`ut run ci` on the coverage leg, `ut run test` on the rest) - # emits Vitest JSON (vitest.config.ts, CI only); this step turns it into - # avg/peak concurrency + efficiency metrics in the job summary. It is - # informational only (always() so failures still surface metrics) and never - # changes the gate — the test run above already set the job's pass/fail. + run: ut run test -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + - name: Report parallelism metrics if: always() # Call node directly: `ut run