@@ -278,22 +278,11 @@ jobs:
278278 run : node --experimental-strip-types scripts/check-package.ts
279279
280280 # Runs the full unit + provider-integration suites under coverage with
281- # thresholds, so a separate unit-tests job would rerun the same tests. The
282- # suite is sharded across runners; each shard writes a blob report and the
283- # Coverage Report job merges them, evaluates thresholds once over the full
284- # suite, and produces every coverage artifact (vitest.config.ts carries the
285- # shard/merge switches).
281+ # thresholds, so a separate unit-tests job would rerun the same tests.
286282 coverage :
287283 name : Coverage
288284 runs-on : ubuntu-latest
289- timeout-minutes : 15
290- strategy :
291- fail-fast : false
292- matrix :
293- shard : [1, 2]
294- env :
295- AGENT_DEVICE_COVERAGE_SHARD : ${{ matrix.shard }}/2
296- OUTPUT_ECONOMY_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
285+ timeout-minutes : 30
297286 steps :
298287 - name : Checkout
299288 uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -304,76 +293,31 @@ jobs:
304293 uses : ./.github/actions/setup-node-pnpm
305294
306295 - name : Test changed-line coverage gate
307- if : matrix.shard == 1
308296 uses : ./.github/actions/run-gate
309297 with : { gate: coverage-model }
310298
311- - name : Run coverage shard
299+ - name : Run coverage
300+ id : run-coverage
301+ env :
302+ OUTPUT_ECONOMY_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
312303 uses : ./.github/actions/run-gate
313304 with : { gate: unit-ci }
314305
315306 # The TMPDIR redirection both test lanes depend on (#1593/#1595). The check is a real
316307 # package script that no workflow ran: it is reachable only through `check:unit`, an
317- # aggregate CI never invokes, so a leak regression could not fail a PR. Runs per shard,
318- # because a leak lands on whichever runner executed the leaking file .
308+ # aggregate CI never invokes, so a leak regression could not fail a PR. Placed here
309+ # because this is the lane whose instrumented suite would leak a run directory .
319310 - name : Check for leaked temp directories
320311 uses : ./.github/actions/run-gate
321312 with : { gate: tmpdir-leaks }
322313
323- - name : Upload coverage blob
324- if : always()
325- uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
326- with :
327- name : coverage-blob-${{ matrix.shard }}
328- path : .vitest-reports/
329- # The directory is dot-prefixed, which v4 excludes by default.
330- include-hidden-files : true
331- if-no-files-found : error
332-
333- coverage-report :
334- name : Coverage Report
335- needs : coverage
336- runs-on : ubuntu-latest
337- timeout-minutes : 10
338- env :
339- AGENT_DEVICE_COVERAGE_MERGE : ' 1'
340- OUTPUT_ECONOMY_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
341- steps :
342- - name : Checkout
343- uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
344- with :
345- fetch-depth : 0
346-
347- - name : Setup toolchain
348- uses : ./.github/actions/setup-node-pnpm
349-
350- - name : Download coverage blobs
351- uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
352- with :
353- pattern : coverage-blob-*
354- path : .tmp/coverage-blobs
355-
356- # download-artifact nests each artifact in its own subdirectory; the blob
357- # merge reads one flat directory.
358- - name : Collect coverage blobs
359- run : |
360- set -euo pipefail
361- mkdir -p .vitest-reports
362- find .tmp/coverage-blobs -name '*.json' -exec mv {} .vitest-reports/ \;
363- ls .vitest-reports
364-
365- # Reuses the blobs the shards wrote (never reruns tests) and fails when
366- # merged changed-line coverage < the threshold in
314+ # Reuses the lcov the coverage step just wrote (never runs coverage twice)
315+ # and fails when changed-line coverage < the threshold in
367316 # scripts/coverage-changed/model.ts. The `coverage-waiver` PR label maps to
368317 # the waiver env, which skips the failure but still prints the numbers.
369- # Gated on the merge step's own outcome (#1781 A5): when it fails,
370- # lcov.info is never written, so this step would just re-report that
318+ # Gated on the coverage step's own outcome (#1781 A5): when `Run coverage`
319+ # fails, lcov.info is never written, so this step would just re-report that
371320 # failure as its own red ("no lcov report") instead of a coverage verdict.
372- - name : Merge coverage shards
373- id : run-coverage
374- uses : ./.github/actions/run-gate
375- with : { gate: unit-ci }
376-
377321 - name : Enforce changed-line coverage gate
378322 if : steps.run-coverage.outcome == 'success' && github.event_name == 'pull_request'
379323 env :
0 commit comments