diff --git a/scripts/github/pr-ci-sweeper.mjs b/scripts/github/pr-ci-sweeper.mjs index 30175755386f..4c414a28002f 100644 --- a/scripts/github/pr-ci-sweeper.mjs +++ b/scripts/github/pr-ci-sweeper.mjs @@ -37,15 +37,14 @@ export function classifyPrForSweep({ pr, ciRuns, botCloseCount, now }) { return { action: "skip", reason: "recently-updated" }; } // A conflicted PR legitimately has no merge ref; CI cannot attach until the - // author resolves, so re-firing would loop forever. + // author resolves, so re-firing would loop forever. Null/unknown mergeability + // is NOT skipped: live testing showed dropped-CI PRs stay mergeable=null + // indefinitely (the stuck merge-ref computation IS the pathology), and + // close/reopen is what un-sticks it. A not-yet-computed conflict costs at + // most one budgeted re-fire before the recomputed false skips it. if (pr.mergeable === false) { return { action: "skip", reason: "merge-conflict" }; } - // Pending computation resolves by the next hourly sweep; do not close/reopen - // on an unknown merge state. - if (pr.mergeable === null || pr.mergeable === undefined) { - return { action: "skip", reason: "mergeability-pending" }; - } // Closing a PR silently cancels enabled auto-merge and reopening does not // restore it; leave those PRs (e.g. generated locale refreshes) to a human. if (pr.auto_merge) { @@ -203,7 +202,7 @@ export async function runPrCiSweeper({ github, context, core, dryRun = false, ap fresh.state !== "open" || fresh.head.sha !== pr.head.sha || fresh.auto_merge || - fresh.mergeable !== true + fresh.mergeable === false ) { core.info(`pr-ci-sweeper: #${pr.number} changed during sweep; leaving it alone`); continue; diff --git a/test/scripts/pr-ci-sweeper.test.ts b/test/scripts/pr-ci-sweeper.test.ts index 5175f92c4145..777b8fe4d76d 100644 --- a/test/scripts/pr-ci-sweeper.test.ts +++ b/test/scripts/pr-ci-sweeper.test.ts @@ -113,9 +113,9 @@ describe("classifyPrForSweep", () => { expected: { action: "skip", reason: "refire-budget-exhausted" }, }, { - name: "skips while mergeability is still computing", + name: "re-fires on unknown mergeability (stuck merge-ref IS the pathology)", input: { pr: pr({ mergeable: null }), ciRuns: [], botCloseCount: 0, now: NOW }, - expected: { action: "skip", reason: "mergeability-pending" }, + expected: { action: "refire", reason: "ci-run-missing" }, }, ];