Skip to content

Repair lost closes in repos outside config.repos - #526

Merged
jarstelfox merged 2 commits into
masterfrom
fix-stale-open-pulls
Oct 12, 2026
Merged

jarstelfox merged 2 commits into
masterfrom
fix-stale-open-pulls

Conversation

@jarstelfox

@jarstelfox jarstelfox commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

🤖

Kyle saw iFixit/ops#1055 in PR jail on prod, but it merged on 2026-09-26. Pulldasher still had it stored as open, and nothing would ever have fixed that, because the hourly check for closed PRs only looks at repos in config.repos. ops isn't one of them; its PRs reach Pulldasher through the org webhook alone.

Where the check skips them

The stale-open check lists open PRs per repo through forEachRepo, which defaults to config.repos, then skips every stored-open PR whose repo wasn't listed. So a lost closed webhook in ops, fixbot, ifixit-cli and the rest stays open for good.

The extra listing costs one call per 30 open PRs in each of those repos, every hour.

Prod today (read-only, every stored-open row checked against GitHub's GraphQL API):

rows
stored as open 349
closed or merged on GitHub 21 (17 ops, 3 ifixit-cli, 1 ifixit-schooner-fw)

All 21 closed between 9/26 and 9/30, while prod's webhooks were writing into dev's database. That explains why the closes went missing. The restart and the label repair (#522-#525) aren't involved: the row for ops#1055 was last written 2026-09-25 18:30 UTC.

  • Hourly and startup check: now also lists open PRs in every other repo the DB holds open PRs in, and refetches the ones GitHub no longer lists. On prod that's about 25 more repos.
  • It adds no new PRs from those repos, and skips a repo whose listing fails.
  • bin/repair-stale-open-pulls: fixes the 21 rows now. Lists by default; --apply refetches each one.

Note

A renamed repo would still get stuck: GitHub lists its PRs under the new name, so rows stored under the old name never match. All 25 repos with open PRs on prod match their current name today, so I left that out.

I haven't run the repair or deployed anything. Once this is out, the startup check should clear the 21 rows by itself; the script is for doing it before a deploy, or for checking the count afterwards.

QA

  • Run npm test, confirm 230 pass. The new test in test/stale-open-pulls.test.js fails on master.
  • On prod, run docker exec pulldasher bin/repair-stale-open-pulls, confirm it lists 21 PRs including iFixit/ops#1055.

🤖 Generated with Claude Code

jarstelfox and others added 2 commits October 11, 2026 17:56
A PR closed on GitHub could stay open on the board for good when it
lives in a repo that isn't in config.repos. iFixit/ops#1055 merged
2026-09-26 and still shows in PR jail on prod.

The stale-open check (refreshStaleOpenPulls, run at startup and every
hour) only listed config.repos, then skipped every DB-open pull whose
repo wasn't listed. Org repos like ops, fixbot and ifixit-cli get their
pulls from the org webhook alone, so a lost `closed` webhook there was
never repaired. 21 prod rows are like this today: 17 ops, 3 ifixit-cli,
1 ifixit-schooner-fw, all closed 9/26-9/30, the stretch when prod's
webhooks wrote into dev's DB.

Now the check also lists the open pulls of every other repo the DB holds
open pulls in (one call per 30 open pulls per repo, about 25 repos on
prod) and refetches the ones GitHub no longer lists. It still adds
nothing new from those repos, and a repo whose listing fails is skipped.

bin/repair-stale-open-pulls fixes the existing rows without waiting for
a deploy: it lists them, and with --apply refetches each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From review:

- A repo outside config.repos whose listing failed was dropped from the
  report, so bin/refresh-open-pulls exited 0. refreshStaleOpenPulls now
  resolves to { failedRepos, failedItems } and both callers add them up.
- bin/repair-stale-open-pulls --apply printed "Refreshed N pulls" and
  exited 0 even when a save failed, since refresh.pull logs a failed
  parse or DB write without rejecting. It now reads the DB back, lists
  the pulls still open and exits 1 if there are any. A repo it can't
  list also exits 1.
- Drop the failedRepos parameter: callers only list config.repos, so
  skipping config.repos already covered it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jarstelfox
jarstelfox merged commit 4aee9cc into master Oct 12, 2026
1 check passed
@jarstelfox
jarstelfox deleted the fix-stale-open-pulls branch October 12, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant