const TRANSIENT_GITHUB_STATUSES = new Set([ 408, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524, ]) export function githubFailureStatus(error: unknown): number | null { if (!error || typeof error !== 'object') return null const response = 'response' in error ? error.response : null if (response && typeof response === 'object' && 'status' in response) { const status = response.status if (typeof status === 'number' && Number.isFinite(status)) return status } const message = error instanceof Error ? error.message : '' const match = message.match(/GitHub request failed with (\d+)/) return match ? Number(match[1]) : null } export function isTransientGithubFailure(error: unknown): boolean { if (error instanceof Error && error.name === 'GitHubRequestTimeoutError') { return true } const status = githubFailureStatus(error) return status !== null && TRANSIENT_GITHUB_STATUSES.has(status) } export async function withTransientGithubRetry( run: () => Promise, options: { retries?: number; delayMs?: number } = {}, ): Promise { const retries = options.retries ?? 1 const delayMs = options.delayMs ?? 400 let attempt = 0 while (true) { try { return await run() } catch (error) { if (attempt >= retries || !isTransientGithubFailure(error)) throw error attempt += 1 if (delayMs > 0) { await new Promise((resolve) => setTimeout(resolve, delayMs)) } } } }