Skip to content

Commit e9adc75

Browse files
authored
fix(ci): don't fail scoped test selection when zero test files match (#8167)
A PR whose scoped-selection paths (backend/miner/mcp/discoveryIndex) only touch files no test imports -- e.g. a pure docs-only change under packages/loopover-miner/docs/** -- correctly triggers scoped test selection (vitest --changed=origin/main), which then correctly finds nothing to run ("No test files found, exiting with code 0"). That legitimate outcome wrote no coverage/lcov.info, which "Verify coverage report exists" treated as a hard failure regardless of cause. Confirmed live: PR #8165 (packages/loopover-miner/docs + apps/loopover-ui/ content/docs mdx only) failed all 3 validate-tests shards this way despite nothing being broken. Captures vitest's own "No test files found" stdout in the scoped branch and skips the coverage-existence check specifically for that case, while a real failure (tests ran and failed, or the step crashed before producing output) still fails the job exactly as before.
1 parent ba93111 commit e9adc75

1 file changed

Lines changed: 21 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,21 @@ jobs:
10281028
# ~2,900-file suite is 0% covered, polluting Codecov's project trend on every scoped PR. Real
10291029
# coverage for files actually exercised is unaffected either way.
10301030
SCOPE_ARGS+=(--changed=origin/main --coverage.all=false)
1031-
npm run test:coverage -- --maxWorkers=4 --shard=${{ matrix.shard }}/3 --reporter=default --reporter=blob --reporter=junit --outputFile.blob=blob-report/report-${{ matrix.shard }}.blob --outputFile.junit=reports/junit/vitest.xml "${EXCLUDE_ARGS[@]}" "${SCOPE_ARGS[@]}"
1031+
# A scoped PR touching zero files any test imports (a pure docs/comment-only diff under a
1032+
# scoped path, e.g. packages/loopover-miner/docs/**) is a real, valid outcome here -- vitest
1033+
# itself prints "No test files found, exiting with code 0" and exits clean, writing no
1034+
# coverage/lcov.info at all (nothing was instrumented). Confirmed live: PR #8165, a pure
1035+
# packages/loopover-miner/docs + apps/loopover-ui/content/docs mdx change, matched zero test
1036+
# files and failed "Verify coverage report exists" even though nothing was actually broken.
1037+
# Capture vitest's own stdout (the same "No test files found" string this file's own comment
1038+
# above already documents relying on) rather than re-deriving the zero-files case from
1039+
# scratch, and record it as a step output so "Verify coverage report exists" below can tell
1040+
# this apart from a real crash that should still fail loudly.
1041+
set -o pipefail
1042+
npm run test:coverage -- --maxWorkers=4 --shard=${{ matrix.shard }}/3 --reporter=default --reporter=blob --reporter=junit --outputFile.blob=blob-report/report-${{ matrix.shard }}.blob --outputFile.junit=reports/junit/vitest.xml "${EXCLUDE_ARGS[@]}" "${SCOPE_ARGS[@]}" 2>&1 | tee vitest-scoped-output.log
1043+
if grep -q "No test files found" vitest-scoped-output.log; then
1044+
echo "no_tests_matched=true" >> "$GITHUB_OUTPUT"
1045+
fi
10321046
else
10331047
# Duration-aware sharding (#ci-duration-aware-sharding), full-suite case only: vitest's own
10341048
# --shard splits by file COUNT alone, no duration awareness -- confirmed via real per-shard CI
@@ -1060,7 +1074,12 @@ jobs:
10601074
echo "Coverage itself is gated by Codecov on changed lines (codecov/patch), computed from all shards' merged lcov."
10611075
echo "Reproduce locally with: 'npm run test:coverage' (unsharded, runs the whole suite)."
10621076
- name: Verify coverage report exists
1063-
if: ${{ success() }}
1077+
# Skipped when the scoped-selection branch above matched zero test files (steps.coverage.outputs.
1078+
# no_tests_matched) -- a legitimately test-free diff (e.g. docs-only under a scoped path) writes no
1079+
# coverage/lcov.info at all, and that is not a failure. A real failure (tests ran and either failed
1080+
# or the coverage step crashed before writing output) still fails this job via `success()` below,
1081+
# same as before.
1082+
if: ${{ success() && steps.coverage.outputs.no_tests_matched != 'true' }}
10641083
run: |
10651084
if [ ! -s coverage/lcov.info ]; then
10661085
echo "::error title=Coverage::coverage/lcov.info is missing or empty"

0 commit comments

Comments
 (0)