Repository navigation
[quality] the CI supply-chain contract's scanners and retiring baselines are never exercised #1246
Description
Finding
tests/ci-supply-chain.test.mjs is the repository's workflow supply-chain
contract: SHA pinning, version comments, permissions:, persist-credentials,
timeout-minutes and runner-image pinning. It runs its scanners over
.github/workflows/** and asserts the offender list is empty.
Every workflow is currently compliant, and all three retiring baselines are
empty — KNOWN_PERSISTING_CHECKOUTS (line 174), KNOWN_UNBOUNDED_JOBS
(line 234) and KNOWN_FLOATING_RUNNERS (line 339) are each new Set([]).
Being compliant is the right outcome; the problem is what it leaves unexecuted.
The three "baseline retires itself" tests assert nothing. Each is a
for (const … of KNOWN_…) loop over an empty set, so its body never runs:
| test | lines | iterations |
|---|---|---|
the persist-credentials baseline retires itself |
205-218 | 0 |
the timeout-minutes baseline retires itself |
308-324 | 0 |
the runner pinning baseline retires itself |
435-451 | 0 |
These are the guards that force an exception to be deleted in the same change
that fixes the workflow. They are the mechanism that stops a baseline from
becoming a permanent allowance, and not one line of that mechanism has ever
been executed. The first contributor to re-add an entry is the first person to
run this code.
The scanners' violation arms never run either. unpinned.push (61-62),
missing.push (81-82), unconstrained.push (96-99) and offenders.push
(192-193) are reached only by a non-compliant workflow, and there are none. A
scanner that stopped detecting — a continue that swallowed every step, a
regex that stopped matching, steps() returning [] — would leave this file
green while checking nothing, and no test in the repository would notice.
The pure predicates are not the gap: timeoutProblem, runnerLabels and
floatingRunnerProblem already have direct unit tests in this same file
(lines 277-290, 364-383, 385-400). The untested part is everything that walks
the workflow set and decides what counts as an offence.
Recommendation
Follow the shape this repository already uses for exactly this problem —
#1231 extracted docs-contract.test.mjs's readers into
tests/helpers-docs-links.mjs and pinned them from
tests/docs-link-helpers.test.mjs with inputs the real docs/ tree does not
supply.
- Move the scanners and the three baseline guards from
tests/ci-supply-chain.test.mjsintotests/helpers-ci-supply-chain.mjs,
each returning its offender list instead of asserting inline. - Import them back into
tests/ci-supply-chain.test.mjsso the contract
over the real workflows is unchanged. - Add
tests/ci-supply-chain-helpers.test.mjsdriving each scanner over
synthetic workflow documents that do offend, and each baseline guard
over a non-empty baseline — covering both the "entry names a workflow
that no longer exists" and the "entry is now compliant" arms.
Evidence and provenance
- Repository revision
59ba83c(main). - Unit.
npm run test:unit:coverage(TZ=UTC node tests/tools/coverage-report.mjs,
node v26.10.0) run locally at that revision reports
tests/ci-supply-chain.test.mjs | 86.12 | 84.94, uncovered lines
61-62 81-82 96-99 192-193 205-218 308-324 435-451. The three contiguous
blocks are the three baseline-guard bodies; the rest are the scanners'
violation arms.src filesare at100.00 | 100.00, so this is the largest
remaining measurable gap in the repository's own test machinery. - End-to-end. Not applicable: this file reads
.github/workflows/**off
disk and never runs in a browser, so no e2e suite can cover it and none is
claimed. Filed astest-infrastructure, notcoverage-gap. - Not occupied.
tests/ci-supply-chain.test.mjsis touched by none of the
open hold-gated PRs (test(e2e): give each fixture overlay directory its own coverage build #1203, test(coverage): give the tests/tools/ harness a floor of its own #1207, test: cover runScriptInSandbox's spawn-failure fallbacks #1215, test: extend the spawn-fallback contract to the importer sandbox helpers #1217, test: cover the pre-22.15 register() fallback in helpers-jsx.mjs #1221, test(ci): pin pipefail on every piped run step #1225, test(coverage): gate --require-source-files on unmappable source files #1227, test: pin the docs/ link readers that the contract never exercises #1231,
fix(security): confine script and style loads to this origin in the meta CSP #1235, fix(security): gate symlinked directories under docs/architectures/ #1242, test: pin the JSONC comment stripper behind the devcontainer contract #1244); test(ci): pin pipefail on every piped run step #1225 is the adjacent one and touches
tests/ci-pipeline-exit-codes.test.mjsonly.
Priority
- Impact: medium — a silently-broken supply-chain scanner is a green check over
an unverified contract. - Effort: medium — mechanical extraction plus one new test file.
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 59ba83c
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
Activity
test(ci): pin the supply-chain scanners the compliant tree never exer…