Retry GitHub API calls, and make the writes safe to retry - #35
Conversation
GitHub had an incident on 2026-08-17. It produced five separate red checks on this repo with nothing wrong in the code: Enable auto-merge 503 Service Unavailable from gh pr merge Jules Review 503 posting a comment Clear Failure Report 503 from gh issue close, three attempts running Fresh Install artifact ENOTFOUND uploading (GitHub-side, not fixable here) workflow_dispatch 503 twice before it was accepted The one that actually costs something is Clear Failure Report. It closes the failure issue when CI goes green again, so when it fails the tracker keeps saying "currently broken" about something already fixed. #28 is open right now for exactly that reason: the scheduled run passed and the close 503'd. That is the signal this job exists to protect. The rest just train people to ignore a red X. A blanket retry would be wrong for two of these. `gh issue create` and `gh issue comment` are not idempotent, so retrying a lost response files a duplicate. Rather than assume a 503 never reached the backend, both loops now RE-DERIVE state before every attempt: re-list the open issue, then decide comment-vs-create; or re-list and exit clean if it is already closed. Idempotent by construction. `gh pr merge --auto` needs none of that. It sets a flag, so arming it twice is the same as arming it once. Verified against a stub gh that simulates the outage, all four paths: outage then ok list 503s twice, then closes #28, exit 0 lost response close reports failure but had worked -> next pass finds nothing open and exits 0. No double close. create lost create reports failure but had worked -> next pass finds the issue and comments. No duplicate filed. always down five attempts, then exit 1 rather than a silent pass
Jules ReviewCOVERAGE: 5b5e10c 2 files SummaryThis PR wraps GitHub API calls ( Findings[WARN]
[NIT]
VERDICT: approve This review never edits code or force-blocks a merge. No blocking issues were found, so this PR was auto-approved. |
GitHub had an incident on 2026-08-17 that produced five separate red checks on this repo with nothing wrong in the code:
Enable auto-merge503 Service Unavailablefromgh pr mergeJules Review503posting a commentClear Failure Report503fromgh issue close, three attempts runningFresh Installartifact uploadENOTFOUND(GitHub-side, not fixable here)workflow_dispatch503twice before it was acceptedThe one that actually costs something
Clear Failure Reportcloses the failure issue when CI goes green again, so when it fails the tracker keeps saying "currently broken" about something that is already fixed.#28 is open right now for exactly that reason. The scheduled run passed after #34 and the close 503'd three times. An issue that says "broken" when it is not is precisely the signal that job exists to protect. The others are milder but not free: a red X that means "GitHub had a bad minute" trains people to stop reading red Xs.
Why not just wrap everything in a retry
gh issue createandgh issue commentare not idempotent. If the write actually succeeded and only the response was lost, a naive retry files a duplicate issue or double-comments.So rather than assume a 503 never reached the backend, both loops re-derive state before every attempt: re-list the open issue, then decide comment-vs-create, or re-list and exit clean if it is already closed. Idempotent by construction rather than by assumption.
gh pr merge --autoneeds none of that. It sets a flag on the PR, so arming it twice is the same as arming it once, and it is retried directly.Verified, not asserted
Both
run:blocks were extracted from the YAML and executed against a stubghthat simulates the outage, including the lost-response cases the design exists to handle:Follows #34, which fixed the three-week-old Python 3.10 break. That one was our own code; this one is not, but it is our own code that decides how loudly someone else's bad minute shows up here.