Repository navigation
[quality] the sweep cron's enqueued outcome (sweep.ts:75) has no end-to-end coverage — no bundle test runs jobs: sweep on a merge-queue branch #384
Description
Finding
src/cronJobs/sweep.ts:75 — the sweep cron's enqueued outcome (result.enqueued.push(pr.number) when tide answers { result: 'enqueued' } for a candidate whose base branch requires a merge queue) — is exercised by unit tests only. No bundle (end-to-end) test runs schedule with jobs: sweep against a queue-enabled base branch, so the shipped dist/index.js has never been seen enqueueing a pull request from the sweep.
The arm fell between two held PRs: #345 (sweepArms.test.ts) states "Line 75 (enqueued) is deliberately left to #322's merge-queue cluster", but #322 (mergeQueueArms.test.ts) drives pull_request labeled lgtm and never runs the sweep job. bundle.test.ts's only queue-branch cron test uses jobs: lgtm (the lgtm cron), which enqueues via a different caller (src/cronJobs/ → evaluateMerge) and does not touch sweep.ts.
Evidence
- Unit:
npx vitest run --coverageonmain@ aa6a0f8 (Node v26.10.0, vitest 5.0.3, @vitest/coverage-v8): 101 files / 1852 tests, 100 % statements (2588/2588), 100 % lines (2463/2463), 99.82 % branches.sweep.ts:75is covered by__tests__/cronJobs/sweep.test.ts. - End-to-end, main alone:
npm run pack:coverage && vitest run --coverage --config vitest.e2e-coverage.config.mjs __tests__/bundleonmain@ aa6a0f8: 22 files / 215 tests, 85.29 % lines (2100/2462);sweep.ts:75has 0 hits. - End-to-end, main + every open hold-gated bundle PR: scratch branch =
origin/main(aa6a0f8) + the heads of test(bundle): drive root-OWNERS authorization on an issue and the OWNERS-based /lgtm refusal through dist/index.js #283 test(bundle): drive the tide merge gate's missing_labels block and labelMatch wildcards through dist/index.js #289 test(bundle): drive the configured hold and sweep sections through dist/index.js #293 test(bundle): drive plain /close, its write failure and the /milestone refusals through dist/index.js #296 test(bundle): drive owners-label's early-return and failure arms through dist/index.js #298 test(bundle): drive /retest's no-failed and already-re-running arms and /ok-to-test's author, already-trusted and approval-failure arms through dist/index.js #304 test(bundle): drive /reopen's and /retitle's collaborator-read 500 and refused-write arms through dist/index.js #306 test(bundle): drive handlePullReq's unsupported-job and failed-lgtm-read arms through dist/index.js #310 test(bundle): drive label-sync's refused-write and description-drift arms through dist/index.js #312 test(bundle): drive the config input's explicit source and the loader's tier read failures through dist/index.js #314 test(bundle): drive lgtmBinding's failure arms and /lgtm cancel's failed reads and writes through dist/index.js #318 test(bundle): drive owners.ts' truncated-tree probes and the base-branch OWNERS probe's arms through dist/index.js #320 test(bundle): drive tide's merge-queue skip and enqueue-refusal arms through dist/index.js #322 test(bundle): drive commandLines' fence-closer, indented-code and info-string guards through dist/index.js #324 test(bundle): drive /hold cancel's no-label, failed-read, failed-removal and already-gone arms through dist/index.js #326 test(bundle): drive pullRequestOwners' rename and base-tip-fallback arms and tide's fork 403 diagnosis arms through dist/index.js #328 test(bundle): drive the issue-side OWNERS fallback and the membership probes' 500 arms through dist/index.js #331 test(bundle): drive the approve plugin's evaluation arms through dist/index.js #333 test(bundle): drive parseProwConfig's schema rejections through dist/index.js #339 test(bundle): drive the missing issue/pull number guards of every command handler and onPrLgtm through dist/index.js #343 test(bundle): drive the sweep cron's empty-window, failed-listing and blunderbuss-freshness arms through dist/index.js #345 test(bundle): drive tide's verdict arms (unknown-retry exhaustion, moved head, 405/409 refusals, merged/closed/locked, check_suite guards, once-per-run) through dist/index.js #347 test(bundle): drive /approve's membership-mode review failures and no-review cancel through dist/index.js #355 test(bundle): drive the prow-commands alias canonicalization and unsupported-command arms through dist/index.js #357 test(bundle): drive the OWNERS filters-ignored arm (owners.ts parseOwners) through dist/index.js #365 test(bundle): drive the repoHasOwners/defaultBranch fallback of approve and the tide gate through dist/index.js #369 test(bundle): drive the cron dispatcher's unknown-job arm through dist/index.js #371 test(bundle): drive /meow's parseCatImage refusals and dropped-connection retry through dist/index.js #372 test(bundle): drive the authorization policy arms of auth.ts (members/collaborators/root-OWNERS admits, trusted refusal, config-load failures, empty login) through dist/index.js #378 test(bundle): drive createCommentOnce's already-carries-marker arm (comments.ts 59-60) through dist/index.js #379 test(bundle): drive the authorization section's schema rejections and the cross-tier users union through dist/index.js #381 test(bundle): drive loadOwnersTree's failure arms (owners.ts L164/L197/L229) through dist/index.js #383 (all merge clean; 52 files / 418 tests pass): 97.64 % lines (2404/2462);sweep.ts:75still 0 hits. Lines 72 (merged), 74, 77 and 78 are hit. - Unit and e2e data cannot be line-merged (different transforms, see
vitest.e2e-coverage.config.mjs), so they are stated separately above.
Everything else left uncovered in that merged run is a catch { throw new Error(...) } wrapper that auth.ts's check* helpers make unreachable (they swallow every error and return false), a reset*Cache() test-only export, or a payload missing … guard.
Recommendation
- Add a bundle test that runs
schedulewithjobs: sweepon a fork pull request carrying a boundlgtmwhose base branch hasisMergeQueueEnabled: true(gh.mergeQueue({ enabled: true })), and assertssweep: #1 enqueued,enqueued pr #1 (position 1), oneenqueuePullRequestmutation withexpectedHeadOid= the candidate's head, and noPUT …/merge. - Cover the mixed arm as well: one candidate enqueued while another's enqueue is refused —
sweep: #1 enqueued,sweep: #2 evaluated with 1 error(s), run exits 1 naming only #2.
Priority
- Impact: medium — covered by unit tests, not end-to-end; it is the only path by which the
pull_requestinstall mode ever reaches a merge queue - Effort: low — one new file under
__tests__/bundle/, no harness change (fakeGithub.mergeQueuealready serves the GraphQL)
Filed by quality agent (hold-gated mode)
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5q9t | SHA: aa6a0f8
— hive: agent=quality backend=copilot model=claude-fable-5.1
Activity
github-actions commentedon Oct 8, 2026
Please add a kind label with
/kind failing-testor/kind cleanup.