(path: string, init: RequestInit, attempt = 0)
| 293 | } |
| 294 | |
| 295 | async function githubRequest(path: string, init: RequestInit, attempt = 0): Promise<Response> { |
| 296 | const response = await fetch(path.startsWith("https://") ? path : `https://api.github.com${path}`, { |
| 297 | ...init, |
| 298 | headers: { |
| 299 | ...headers, |
| 300 | ...init.headers, |
| 301 | }, |
| 302 | }) |
| 303 | |
| 304 | if (response.ok) return response |
| 305 | |
| 306 | const body = await response.text() |
| 307 | const retryAfter = response.headers.get("retry-after") |
| 308 | const reset = response.headers.get("x-ratelimit-reset") |
| 309 | const retryMs = retryAfter |
| 310 | ? Number(retryAfter) * 1000 |
| 311 | : response.headers.get("x-ratelimit-remaining") === "0" && reset |
| 312 | ? Math.max(0, Number(reset) * 1000 - Date.now()) + 1_000 |
| 313 | : body.toLowerCase().includes("secondary rate limit") |
| 314 | ? 300_000 |
| 315 | : response.status >= 500 |
| 316 | ? Math.min(300_000, 10_000 * 2 ** attempt) |
| 317 | : 0 |
| 318 | |
| 319 | if ((response.status === 403 || response.status === 429 || response.status >= 500) && retryMs > 0 && attempt < 10) { |
| 320 | console.warn(`GitHub request failed; sleeping ${Math.ceil(retryMs / 1000)}s before retry ${attempt + 1}`) |
| 321 | await sleep(retryMs) |
| 322 | return githubRequest(path, init, attempt + 1) |
| 323 | } |
| 324 | |
| 325 | throw new Error(`GitHub request failed: ${response.status} ${response.statusText}\n${body}`) |
| 326 | } |
| 327 | |
| 328 | function positiveReactionCount(pr: PullRequest) { |
| 329 | return pr.reactionGroups |
no test coverage detected