name: Coverage # Runs vitest with --coverage and the per-path threshold gate # (scripts/verify-test-coverage.mjs reads scripts/coverage-targets.json). # Uploads the lightweight gate summary as an artifact and posts a sticky PR # comment with the coverage-summary.json totals. # # Spec: docs/improvement-plan/10-compliance-polish/test-coverage.md # Docs: docs/architecture/test-coverage.md on: pull_request: paths: - "apps/**" - "packages/**" - "scripts/coverage-targets.json" - "scripts/verify-test-coverage.mjs" - "scripts/coverage-summary.mjs" - "vitest.config.ts" - ".github/workflows/coverage.yml" push: branches: [main] permissions: contents: read pull-requests: write jobs: coverage: name: Measure coverage and gate thresholds runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v4 - name: Enable Corepack run: corepack enable - name: Prepare pnpm 10.33.0 run: corepack prepare pnpm@10.33.0 --activate - name: Configure pnpm store run: pnpm config set store-dir .pnpm-store - name: Cache pnpm store uses: actions/cache@v4 with: path: .pnpm-store key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm- - name: Install dependencies run: pnpm install --frozen-lockfile --prefer-offline - name: Run vitest with coverage (enforces per-path gates) env: TOOLCTRL_COVERAGE_GATE: "1" run: pnpm run verify:test-coverage - name: Upload coverage gate summary if: always() uses: actions/upload-artifact@v4 with: name: coverage-gate-summary-${{ github.run_id }} path: coverage-gate/coverage-summary.json retention-days: 14 - name: Render PR coverage comment if: github.event_name == 'pull_request' env: COVERAGE_SUMMARY_PATH: coverage-gate/coverage-summary.json run: node scripts/coverage-summary.mjs --pr-comment > coverage-comment.md - name: Post sticky PR comment if: github.event_name == 'pull_request' uses: marocchino/sticky-pull-request-comment@v2 with: header: coverage-report path: coverage-comment.md