From 944da0e2d3cdc32829dbb71455406a1ed2669130 Mon Sep 17 00:00:00 2001 From: hshoff Date: Thu, 18 Jun 2026 12:51:23 -0400 Subject: [PATCH] fix(release): retry GitHub compare requests --- .../performRelease/fetchCommitsSinceTag.ts | 15 ++++++----- .../runGithubRequestWithRetries.ts | 26 ++++++++++++++++--- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/scripts/performRelease/fetchCommitsSinceTag.ts b/scripts/performRelease/fetchCommitsSinceTag.ts index d9ee1a8be6..e29328588a 100644 --- a/scripts/performRelease/fetchCommitsSinceTag.ts +++ b/scripts/performRelease/fetchCommitsSinceTag.ts @@ -1,14 +1,17 @@ import type { GithubClient } from '../utils/getGitHubClient'; import getRepoContext from '../utils/getRepoContext'; +import runGithubRequestWithRetries from './runGithubRequestWithRetries'; export default async function fetchCommitsSinceTag(client: GithubClient, tagSha: string) { console.log('Fetching commits since sha', tagSha); const { owner, repo } = getRepoContext(); - return client.request('GET /repos/{owner}/{repo}/compare/{base}...{head}', { - owner, - repo, - base: tagSha, - head: 'HEAD', - }); + return runGithubRequestWithRetries(`Fetch commits since ${tagSha}`, () => + client.request('GET /repos/{owner}/{repo}/compare/{base}...{head}', { + owner, + repo, + base: tagSha, + head: 'HEAD', + }), + ); } diff --git a/scripts/performRelease/runGithubRequestWithRetries.ts b/scripts/performRelease/runGithubRequestWithRetries.ts index 7bb1489416..24adb4d085 100644 --- a/scripts/performRelease/runGithubRequestWithRetries.ts +++ b/scripts/performRelease/runGithubRequestWithRetries.ts @@ -23,11 +23,27 @@ function getErrorMessage(error: unknown) { } } -function isRateLimitError(error: unknown) { +function getErrorStatus(error: unknown) { const status = typeof error === 'object' && error !== null && 'status' in error ? error.status : null; - return status === 429 || /rate limit|secondary limit/i.test(getErrorMessage(error)); + return typeof status === 'number' ? status : null; +} + +function isRetryableGitHubRequestError(error: unknown) { + const status = getErrorStatus(error); + const message = getErrorMessage(error); + + return ( + status === 429 || + status === 500 || + status === 502 || + status === 503 || + status === 504 || + /rate limit|secondary limit|premature close|socket hang up|econnreset|etimedout|eai_again|fetch failed/i.test( + message, + ) + ); } export async function pauseBetweenGitHubRequests() { @@ -44,12 +60,14 @@ export default async function runGithubRequestWithRetries( } catch (error) { const delayMs = RETRY_DELAYS_MS[attempt]; - if (!isRateLimitError(error) || delayMs === undefined) { + if (!isRetryableGitHubRequestError(error) || delayMs === undefined) { throw error; } console.warn( - `${label} hit a GitHub rate limit. Retrying in ${delayMs / 1000}s: ${getErrorMessage(error)}`, + `${label} hit a retryable GitHub request error. Retrying in ${ + delayMs / 1000 + }s: ${getErrorMessage(error)}`, ); await wait(delayMs); return runGithubRequestWithRetries(label, request, attempt + 1);