Parent: #1936
Problem
mergePullRequest, closePullRequest, createPullRequestReview, updatePullRequestBranch (and createIssueComment/getLastCloserLogin) in src/github/pr-actions.ts call createInstallationToken directly and never route through withInstallationTokenRetry (src/github/app.ts:159-184) — the only caller of expireCachedInstallationToken. Only the check-run creator and the comment poster in comments.ts get evict-and-retry. Related: see the sibling issue filed alongside this one on the 401-misclassified-as-transient merge-retry bug — both stem from the same missing token-retry wiring.
Failure scenario: an installation is suspended, or the App private key is rotated, while a cached token (kept up to ~1h) is still in the cache. Every merge/close/review/update-branch call for that installation keeps reusing the same now-invalid token and re-fails with 401 each time until the cache's own TTL lapses on its own — no self-heal, unlike the paths that already route through the retry helper.
Requirements
- A rejected (401) installation token must be evicted and retried with a fresh mint, not reused until its cache TTL naturally expires.
Deliverables
- Route
mergePullRequest, closePullRequest, createPullRequestReview, updatePullRequestBranch, createIssueComment, and getLastCloserLogin through withInstallationTokenRetry instead of calling createInstallationToken directly, mirroring the existing pattern in src/github/comments.ts.
- Add a regression test: a mutating call gets a 401 — assert the cached token is evicted and a retry with a fresh token is attempted.
Acceptance criteria
- A 401 on any PR-mutating call triggers token eviction and one retry with a freshly-minted token, matching the existing check-run/comment behavior.
Expected outcome
A suspended installation or rotated App key self-heals on the next attempt instead of failing repeatedly against a known-bad cached token for up to an hour.
Parent: #1936
Problem
mergePullRequest,closePullRequest,createPullRequestReview,updatePullRequestBranch(andcreateIssueComment/getLastCloserLogin) insrc/github/pr-actions.tscallcreateInstallationTokendirectly and never route throughwithInstallationTokenRetry(src/github/app.ts:159-184) — the only caller ofexpireCachedInstallationToken. Only the check-run creator and the comment poster incomments.tsget evict-and-retry. Related: see the sibling issue filed alongside this one on the 401-misclassified-as-transient merge-retry bug — both stem from the same missing token-retry wiring.Failure scenario: an installation is suspended, or the App private key is rotated, while a cached token (kept up to ~1h) is still in the cache. Every merge/close/review/update-branch call for that installation keeps reusing the same now-invalid token and re-fails with 401 each time until the cache's own TTL lapses on its own — no self-heal, unlike the paths that already route through the retry helper.
Requirements
Deliverables
mergePullRequest,closePullRequest,createPullRequestReview,updatePullRequestBranch,createIssueComment, andgetLastCloserLoginthroughwithInstallationTokenRetryinstead of callingcreateInstallationTokendirectly, mirroring the existing pattern insrc/github/comments.ts.Acceptance criteria
Expected outcome
A suspended installation or rotated App key self-heals on the next attempt instead of failing repeatedly against a known-bad cached token for up to an hour.