Repository navigation
test(auth): pin the repository-less org check, gone-user comment skip, non-RequestError and half-formed root OWNERS reads, and the OWNERS path in role errors - #579
Conversation
…skip, the non-RequestError and half-formed root OWNERS reads, and the OWNERS path in role errors A Stryker probe of src/utils/auth.ts (--mutate src/utils/auth.ts on the harness of #572) left 22 of 273 mutants alive. Eleven of them flip a guard the suite reaches but never distinguishes; this file pins each one: - checkOrgMember on a payload without a repository returns false by the early return, not by a TypeError caught as an unexpected error, so no warning annotation is emitted - checkIssueComments skips a comment whose user is null (e.user?.login) instead of aborting the scan - retrieveOwnersFile reports a string or null rejection of repos.getContent as the OWNERS lookup error rather than tripping on 'status' in e - a contents response with content but no encoding, or an encoding but no content, is rejected as an invalid OWNERS file rather than decoded - a root OWNERS role that is not a list is reported as 'OWNERS at OWNERS:' from both assertRootOwner and rootOwnersIncludes The seven remaining survivors are core.debug strings and the contents === '' short-circuit of rootOwnersIncludes, which is equivalent: parseOwners('OWNERS', '') yields empty lists and expandGroups of an empty list returns an empty set without a request. Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Agent PRs are held at ACMM L3–L5; an Hive will keep the |
There was a problem hiding this comment.
Verified against the tree at f72f8aa, not just the diff — this looks correct to me.
- Test-only change: one new file,
__tests__/utils/authGuards.test.ts(118 lines), nosrc/or existing-test edits, matching the stated scope. - Each claimed guard exists where claimed: the repository-undefined early return (
src/utils/auth.ts:43-46, debug text matches the assertion verbatim),e.user?.loginincheckIssueComments(auth.ts:129), thetypeof e === 'object' && e && 'status' in e && e.status === 404catch and thedata.content === undefined || !data.encodingguard inretrieveOwnersFile(auth.ts:444/auth.ts:454), and theparseOwners('OWNERS', …)call sites atauth.ts:358andauth.ts:421whoseOWNERS at OWNERS:prefix the two role-error tests pin. - The string/null rejection tests correctly produce
error checking for an OWNERS file at the root of the repository: socket hang up/: nullvia the template's${e}, exercising exactly the operands the five444:9mutants flip. - Ran it:
npx vitest run __tests__/utils/authGuards.test.tson the PR head → 8/8 pass. CI (build-test, e2e-coverage, DCO) is green.
The equivalence argument for the three surviving 417:7 mutants (contents === '' → parseOwners of an empty string yields empty role lists → false either way) checks out against rootOwnersIncludes at auth.ts:415-424.
No findings. Leaving approval to a maintainer per the hold gate.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
|
/kind cleanup 🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88 |
|
Consolidated into #588 together with the other eight open mutation-survivor pin PRs (commit cherry-picked unchanged, DCO preserved). Closing in favour of that PR. |
Test Improvement
A Stryker probe of
src/utils/auth.ts(npx stryker run --mutate src/utils/auth.tson #572's harness, main @ e3119ad, Stryker 10.0.0 / Vitest 5.0.4, 8 workers, 10 m 38 s) left 22 of 273 mutants alive. Eleven flip a guard the suite reaches but never distinguishes from its mutation. This PR adds one test file that kills all eleven; re-running the probe with it reports 7 survived / 258 killed / 8 timeout (97.44 %).Files / cluster claimed:
__tests__/utils/authGuards.test.ts(new). Nosrc/,dist/or existing-test change. Disjoint from every held PR on this module: #553 drivesgetErrorDetails' object folds (auth.ts:15-17) through the bundle; #571 edits__tests__/utils/auth.test.ts; #575/#564/#569 areowners.ts. Follows the same pattern as #575 (ownersGuards.test.ts) and #578 (tideGuards.test.ts).Mutants pinned (span → test)
auth.tsspanif (repository === undefined) { … }→{}refuses a payload without a repository quietly, without a warning annotatione.user?.login→e.user.loginnulluser aborts the scan and warns instead of being skippedskips a comment whose user is gone and keeps scanningtypeof e === 'object' && e && 'status' in e— 5 mutants (true× 3,||× 2)'status' in 'string'/null.statusthrow a TypeError instead of the OWNERS lookup errorreports a string / null rejection of the contents read as an OWNERS lookup error(vi.spyOn(octokit.repos, 'getContent').mockRejectedValueOnce, the same precedentauth.test.tsuses forcheckMembershipForUser)content === undefined || !encoding→&&rejects a contents response that carries content but no encodingcontent === undefined→falseBuffer.from(undefined)rejects a contents response that carries an encoding but no contentparseOwners('OWNERS', …)→''OWNERS at OWNERS:prefixnames the root OWNERS file when a role is not a list(assertRootOwner) and… when the trusted policy falls through to a malformed file(rootOwnersIncludes viapolicyAllows)Reviewed survivors, not pinned (7)
379,434,445,459—core.debugstring literals; the same class test(mutation): add a bounded Stryker harness for the merge-decision code #572's docs table excludes.417:7,417:20,417:24— thecontents === ''short-circuit ofrootOwnersIncludes. Equivalent:parseOwners('OWNERS', '')yields empty role lists (contents.trim() === '' ? {}),ownersIncludethen callsexpandGroupswith an empty list, which returns an empty set without any request, so the result isfalseeither way with no observable difference.I have not edited
docs/contributing.md's survivor table because that file is #572's claimed ground; this list is the record until #572 lands.Validation
npx vitest run __tests__/utils/authGuards.test.ts→ 8 passednpx eslint __tests__/utils/authGuards.test.ts→ cleanauth.tsbefore: 246 killed / 5 timeout / 22 survived (91.94 %); after: 258 / 8 / 7 (97.44 %)npm run test:coverage, 167 files / 2330 tests) is already 99.92 % stmts / 99.35 % branches for this module; the remainingauth.ts:220is the phantom branchdocs/contributing.mddocuments. This PR adds assertion strength, not line coverage.Related Issue
Refs #554 — ticks a slice of the "Strengthen assertions and the test harness" section (reviewed mutation survivors on the authorization module); the tracker's CI-enforcement, release-delivery and routing sections stay open and are owned elsewhere.
Filed by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88 requested_by=@mrbobbytables