* Look up a GitHub user by numeric ID and return their `created_at`. * Returns `'rate-limited'` so callers can log it distinctly from other * failures (most likely cause at our scale). Any non-2xx is mapped to * `null` so one flaky user doesn't stall the sweep.
( githubId: string, )
| 476 | * `null` so one flaky user doesn't stall the sweep. |
| 477 | */ |
| 478 | async function fetchGithubCreatedAt( |
| 479 | githubId: string, |
| 480 | ): Promise<Date | 'rate-limited' | null> { |
| 481 | try { |
| 482 | const headers: Record<string, string> = { |
| 483 | Accept: 'application/vnd.github+json', |
| 484 | 'X-GitHub-Api-Version': '2022-11-28', |
| 485 | 'User-Agent': 'codebuff-bot-sweep', |
| 486 | } |
| 487 | if (env.BOT_SWEEP_GITHUB_TOKEN) { |
| 488 | headers.Authorization = `Bearer ${env.BOT_SWEEP_GITHUB_TOKEN}` |
| 489 | } |
| 490 | const res = await fetch(`https://api.github.com/user/${githubId}`, { |
| 491 | headers, |
| 492 | signal: AbortSignal.timeout(GITHUB_API_TIMEOUT_MS), |
| 493 | }) |
| 494 | if (res.status === 403 || res.status === 429) return 'rate-limited' |
| 495 | if (!res.ok) return null |
| 496 | const data = (await res.json()) as { created_at?: string } |
| 497 | return data.created_at ? new Date(data.created_at) : null |
| 498 | } catch { |
| 499 | return null |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | function findCreationClusters( |
| 504 | rows: { email: string; createdAt: Date }[], |