Files
msd-core/tests/release-coverage-scope.test.cjs
Tom Boucher ea91268d02 ci(#4335): shard release.yml rc/finalize unit-suite tests (#4338)
* ci(#4335): shard release.yml rc/finalize unit-suite tests

The finalize job's unsharded unit-coverage step outgrew the 30-minute job
timeout that was already raised once for this exact symptom (#2280): run
33988966357 finished all tests with 0 failures at 28m26s, then got cancelled
~80s into the post-test coverage merge — a phase that historically completes
in 54-101s. The suite's wall-clock time, not a hang, ate the budget.

test.yml already fixed the identical cliff for its own full-scope lane
(#2952, #3057) by sharding the unit suite 3 ways with a separate merged
coverage-gate job. Apply the same pattern to rc and finalize (rc has the
byte-identical unsharded shape and would hit the same wall next): each gains
a `*-test` matrix job (raw coverage only, no report/gate) and a
`*-coverage-gate` job that merges the shards' raw V8 dumps before enforcing
the existing gsd-core/bin/lib coverage floor. rc/finalize now depend on their
gate job instead of running the suite inline.

Updates release-coverage-scope.test.cjs's exact-count assertion for the new
command surface and adds release-shard-lane-sharding.test.cjs to pin
shard-set completeness and gate wiring, mirroring ci-full-lane-sharding.test.cjs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Potential fix for pull request finding 'CodeQL / Cache Poisoning via execution of untrusted code'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'CodeQL / Cache Poisoning via execution of untrusted code'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix(#4335): close CodeQL cache-poisoning and missing-permissions findings

CodeQL flagged the PR (10 actions/cache-poisoning/poisonable-step errors, 4
actions/missing-workflow-permissions warnings) on release.yml.

Remove `cache: 'npm'` from every actions/setup-node step in the file (7
occurrences, not just the 4 newly-added jobs the alerts pointed at) —
restoring an npm cache before running install/build code in a
write-permissioned job is exactly the shape this query targets, and the
same pattern was already present unchanged in create/rc/finalize. These are
short CI/release jobs; losing npm's install cache costs a few seconds per
job, closing the finding everywhere it appears in this file rather than
only where the alert happened to land on a changed line.

Add explicit `permissions: contents: read` to rc-test, rc-coverage-gate,
finalize-test, finalize-coverage-gate — the four new jobs had no
permissions block at all and inherited the ambient default. Matches
validate-version's existing least-privilege pattern; create/rc/finalize
keep their own broader write/publish scopes unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: sim <sim@local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-09-05 18:49:35 -04:00

48 lines
2.8 KiB
JavaScript

// allow-test-rule: source-text-is-the-product
// .github/workflows/release.yml is the deployed CI contract; asserting
// the release-gate test command is only expressible against the workflow text.
'use strict';
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const RELEASE_WORKFLOW = path.join(__dirname, '..', '.github', 'workflows', 'release.yml');
describe('release-coverage-scope', () => {
// #4335: rc/finalize used to run one unsharded `npm run test:coverage:unit`
// line each. Both now shard the unit suite (raw coverage only, one line per
// *-test job) and gate on a separate merged-coverage job (one report line
// per *-coverage-gate job) — see rc-test/finalize-test and
// rc-coverage-gate/finalize-coverage-gate. This asserts the new surface is
// still unit-scoped end to end: the unsharded single-shot invocation is
// gone for good (not silently reintroduced), the raw/report scripts appear
// exactly once per job pair, and no bare full-suite line ever appears.
test('release.yml uses the sharded unit-coverage scripts (not the unsharded or full suite) in both rc and finalize gates', () => {
// Normalize an optional leading `run: ` so a single-line `run: npm run
// …` step (the style rc-coverage-gate/finalize-coverage-gate use) counts
// the same as a bare command line inside a multi-line `run: |` block
// (the style the raw-coverage and legacy unit steps use).
const lines = fs.readFileSync(RELEASE_WORKFLOW, 'utf8').split(/\r?\n/)
.map(l => l.trim().replace(/^run:\s*/, ''));
const bareCount = lines.filter(l => l === 'npm run test:coverage').length;
const unshardedUnitCount = lines.filter(l => l === 'npm run test:coverage:unit').length;
const rawShardedCount = lines.filter(l => l === 'npm run test:coverage:unit:raw -- --shard ${{ matrix.shard }}').length;
const reportCount = lines.filter(l => l === 'npm run test:coverage:report').length;
assert.strictEqual(bareCount, 0,
`release.yml still has ${bareCount} bare 'npm run test:coverage' line(s); expected 0`);
assert.strictEqual(unshardedUnitCount, 0,
`release.yml has ${unshardedUnitCount} unsharded 'npm run test:coverage:unit' line(s); ` +
'expected 0 — the #4335 fix sharded rc/finalize onto test:coverage:unit:raw + test:coverage:report');
assert.strictEqual(rawShardedCount, 2,
`release.yml has ${rawShardedCount} sharded raw-coverage line(s) (one expected in each of ` +
`rc-test and finalize-test); expected 2`);
assert.strictEqual(reportCount, 2,
`release.yml has ${reportCount} 'npm run test:coverage:report' line(s) (one expected in each ` +
'of rc-coverage-gate and finalize-coverage-gate); expected 2');
});
});