fix(queue): thread ignoredCheckRuns into the live CI aggregate, not just its cache key - #10163
Conversation
…ust its cache key gate.ignoredCheckRuns (JSONbored#9813) is supposed to exclude a maintainer-declared check-run from CI resolution entirely, and the reducer + fetchLiveCiAggregatePreferGraphQl honour it. But ci-resolution.ts folded it into the durable cache key at all three hand-offs while dropping it from the arg object passed downstream, so cachedFetchLiveCiAggregate's ignoredCheckRuns was always undefined -- TypeScript can't catch it because the property is optional at every hop. The consequence on the live maintenance path: ciAggregate's ignoredCheckDetails is always [], ignoredCheckNonPassing is always empty, and unstableExplainedByIgnoredChecks is always false, so the JSONbored#9810 follow-up that stops an ignored check from holding a PR at mergeable_state 'unstable' can never fire in production, and the planner and executor can disagree about the same PR's CI state. Forward args.ignoredCheckRuns at all three call sites (fetchLiveCiAggregateWithRequiredContexts, cachedLiveCiAggregate, refreshLiveCiAggregate), mirroring how advisoryCheckRuns is already threaded through the same hops. Signatures stay optional so positional callers are byte-identical; the requiredContextsKey composition and advisoryCheckRuns threading are unchanged, and nothing outside ci-resolution.ts is touched. Closes JSONbored#10018
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-31 10:39:49 UTC
Review summary Nits — 3 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #10163 +/- ##
==========================================
+ Coverage 80.43% 80.45% +0.02%
==========================================
Files 282 283 +1
Lines 58744 58829 +85
Branches 6963 6983 +20
==========================================
+ Hits 47248 47331 +83
Misses 11205 11205
- Partials 291 293 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
|
What & why
gate.ignoredCheckRuns(#9813) is supposed to exclude a maintainer-declared third-party check-run from CI resolution entirely — "never gates, never pends, never holds." The reducer honours it andfetchLiveCiAggregatePreferGraphQlaccepts it as its 8th positional argument. Butsrc/queue/ci-resolution.tsfolded it into the durable cache key at all three hand-offs while dropping it from the arg object passed downstream:TypeScript can't catch it: the property is optional at every hop. So
args.ignoredCheckRunsinsidecachedFetchLiveCiAggregate(its only consumer) is alwaysundefined. Consequences, all on the live maintenance path:ciAggregate.ignoredCheckDetailsis always[], soignoredCheckNonPassingis always empty andunstableExplainedByIgnoredChecksis alwaysfalse. The fix(ops): scope the PagerDuty cooldown to rows that actually paged #9810 follow-up that stops an ignored check from holding a PR atmergeable_state: "unstable"can never fire in production.ciState/hasPendingin the planner's aggregate, while the executor's and approval-queue's own re-checks pass the list through correctly — so planner and executor can disagree about the same PR's CI state.The fix
Forward
args.ignoredCheckRunsat all three call sites —fetchLiveCiAggregateWithRequiredContexts,cachedLiveCiAggregate, andrefreshLiveCiAggregate— mirroring howadvisoryCheckRunsis already threaded through the same three hops. One added property per call site, nothing else.Unchanged: signatures stay optional so positional callers (
reuseOrRefreshLiveCiAggregateatprocessors.ts:3322) are byte-identical; therequiredContextsKeycomposition (already includes the ignore-list fingerprint) and theadvisoryCheckRunsthreading are unchanged; nothing outsideci-resolution.tsis modified.Tests (
test/unit/ci-resolution.test.ts)fetchLiveCiAggregatePreferGraphQl, its 8th positional argument equals the exact ignore array[{ name: "Contributor trust", appSlug: "example-security-app" }]forcachedLiveCiAggregate,refreshLiveCiAggregate, and the positional entry pointreuseOrRefreshLiveCiAggregate— today it isundefined.ignoredCheckRuns: null) still passesnull/undefinedthrough, so an un-opted-in repo stays byte-identical.main.Validation
src/queue/ci-resolution.tsis 100% line and branch (each of the three touched call sites executed; the populated and absentignoredCheckRunsKeyPartarms both exercised).npm run typecheckclean;npm run engine-parity:drift-checkpasses (not a twin);npm run dead-exports:checkclean; the suite (15 tests) green.git diff --checkclean; no schema/migration/generated-artifact change.Closes #10018