diff --git a/config/scripts/ci-runner-demand.mjs b/config/scripts/ci-runner-demand.mjs index a5b101d0e95..961b16c51f7 100644 --- a/config/scripts/ci-runner-demand.mjs +++ b/config/scripts/ci-runner-demand.mjs @@ -3,21 +3,27 @@ import { pathToFileURL } from 'node:url' import { runnerDemand, sampleWorkflowRuns } from './ci-runner-metrics.mjs' async function api(path, env) { - const response = await fetch( - `${env.GITHUB_API_URL ?? 'https://api.github.com'}/repos/${env.GITHUB_REPOSITORY}/${path}`, - { - headers: { - Authorization: `Bearer ${env.GH_TOKEN}`, - Accept: 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28' - }, - signal: AbortSignal.timeout(30_000) + // Hundreds of calls per report make transient 5xx responses routine. + for (let attempt = 1; ; attempt++) { + const response = await fetch( + `${env.GITHUB_API_URL ?? 'https://api.github.com'}/repos/${env.GITHUB_REPOSITORY}/${path}`, + { + headers: { + Authorization: `Bearer ${env.GH_TOKEN}`, + Accept: 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28' + }, + signal: AbortSignal.timeout(30_000) + } + ) + if (response.ok) { + return response.json() } - ) - if (!response.ok) { - throw new Error(`Actions API: ${response.status}`) + if (response.status < 500 || attempt === 3) { + throw new Error(`Actions API: ${response.status}`) + } + await new Promise((resolve) => setTimeout(resolve, attempt * 5000)) } - return response.json() } // The runs API serves at most 1000 results per query, so busy intervals are halved until each fits.