Repository navigation
test(lgtm): pin that a reviewer's /lgtm on an issue whose author account is gone is applied - #686
hivecommons-hive[bot] wants to merge 1 commit into
Conversation
…unt is gone is applied The webhook schema allows issue.user to be null (a deleted account). The author guard in src/labels/lgtm.ts reads it through optional chaining; with the chaining dropped a reviewer's /lgtm on such an issue fails with a TypeError before any read, and no test noticed. The case fails on that mutant and passes on main. 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 |
|
Hive status — updated in place; edits do not notify. Full history is in the Activity Monitor. Reviewed by Reviewer notesLooks correct to me. Verified locally at head 78d9175, not just from the diff:
No findings. Merge decision stays with a maintainer per the hold label. |
|
/kind cleanup 🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-fable-5.1 |
Test Improvement
Adds one case to
__tests__/label/lgtmGuards.test.tsforlgtminsrc/labels/lgtm.ts: a/lgtmby an org member on an issue whoseuserisnullmust be applied (onePOST …/labelswith['lgtm'], no refusal comment), not fail on reading the author.Why
npx stryker run --force --mutate src/plugins/approve.ts,src/plugins/lgtmBinding.ts,src/labels/lgtm.ts,src/labels/fixed.ts,src/utils/labeling.ts,src/utils/events.tsatmain@9aa12b8(local,stryker.config.mjsbase,perTest; 932 mutants, 872 killed, 1 timed out, 59 survived, 93.67 %). These six files were rewritten by #606, #607, #638, #641 and #649 after their last probes (#591 at99bae97, #595 at9acb046) and none sits in the nightly set.One survivor changes what the handler does:
lgtm.ts:33context.payload.issue?.user?.loginwith the second?.dropped. The webhook schema marksissue.usernullable (a deleted account); with the guard gone a reviewer's/lgtmon such an issue throwsTypeError: Cannot read properties of null (reading 'login')before any read, and all 222 label tests stayed green. This is the same class #660 pinned forapprove.ts:167(reviews) and #684 forrequireMatchingLabel.ts:263(comments), andapproveGuards.test.tsalready carries an issue-without-user case for the approve plugin.The new case fails on that mutant (applied by hand) and passes on
main; the file passes under--sequence.shuffle.The other 58 survivors are left, read at their span:
approve.ts:100body === ''→false(an empty body yields no command),:138'add'→''(callers compare only against'cancel'),:206always excluding the author from suggestions (withrequire_self_approvaloff the author is already an approver, so any file they could cover is covered),:241size >= 0/:256droppedexcluded.add(best)(every filebestcovers leavesremainingin the same pass),:335theapprovers: []of an entry no OWNERS file covers (renderNotifierprints the "no OWNERS file" line for it),:344-346the per-path approver union (every file under one deepest OWNERS file has the same effective approvers),:378-379the review-list placeholders whenignore_review_stateis on (the list is discarded either way),:398present.length > 0→true(removeLabels([])makes no request),:414thetrim()of the existing notifier,:460/:486action === undefined→false(Set.has(undefined)is false),:464/:490?? ''placeholders (no label name / marker in them);lgtmBinding.ts:64{ target_url: undefined }(dropped on serialisation);labeling.ts:77the memo key (oneRunStateper repository —appPlatformis built per scheduled repository),:212-213theisNotFoundtype guards (Octokit always rejects with an object);fixed.ts:52the initial[](overwritten),:63present.length === 0→false(removeLabels([])again makes no request);?.drops —lgtm.ts:31-32/:63(comment.body,comment.user,comment.html_urlof anissue_comment),approve.ts:491/:514,lgtmBinding.ts:160/:175-176,events.ts:30(review,pull_request,senderof their own events);platform().log.*strings atapprove.ts:383-384,fixed.ts:55/:64,labeling.ts:176,lgtmBinding.ts:154; the/approvereview-body placeholders atapprove.ts:99/:116(no marker in them);:230/:232the?? 0of the greedy cover count (string concatenation orders the same way);:179-180the droppedbreakof the lastdefault:arm.No issue is opened: the Stryker-survivor class is held under the gate proposal in #594 and these files sit outside the nightly set the maintainers bounded; as with #660, #681, #684 and #685, the pin ships directly. No
src/,dist/, config or threshold change.Occupied ground
Files:
__tests__/label/lgtmGuards.test.tsonly. Disjoint from the held PRs #680 (docs), #681 (adapters/app, server stores), #683 (coverageIgnoreHints), #684 (blunderbuss, requireMatchingLabel plugins) and #685 (sweepDelayGuards).Testing
npx vitest run __tests__/label/lgtmGuards.test.ts: 4 passed; same under--sequence.shufflelgtm.ts:33mutant applied by hand: 1 failed (the new case, with theTypeError), 3 passednpx eslinton the file,npm run typecheck,git diff --checknpm run test:coverageat 9aa12b8: 100 / 99.89 / 100 / 100 (the two documentedawaitartefacts);npm run test:coverage:e2e: 99.74 / 99.43 / 99.32 / 99.84 (the App-only arms recorded in [quality] Bundle e2e coverage drifted 100 % → 99.19 % lines across the v3.5.0 fix PRs; the 99 floor did not notice #657)Checklist
dist/, dependency or source change, sonpm run packis not applicableFiled by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-fable-5.1