diff --git a/src/github.ts b/src/github.ts index a518a44..08f52e4 100644 --- a/src/github.ts +++ b/src/github.ts @@ -13,7 +13,7 @@ export async function createIssue( token: string, owner: string, repo: string, - opts: { title: string; body: string; assignees?: string[]; labels?: string[] }, + opts: { title: string; body: string; labels?: string[] }, ): Promise { const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/issues`, { method: "POST", @@ -32,6 +32,31 @@ export async function createIssue( return data.number; } +export async function assignIssue( + token: string, + owner: string, + repo: string, + issueNumber: number, + assignees: string[], +): Promise { + const res = await fetch( + `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}/assignees`, + { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + Accept: "application/vnd.github+json", + "User-Agent": "infra-status-worker", + }, + body: JSON.stringify({ assignees }), + }, + ); + if (!res.ok) { + const text = await res.text(); + throw new Error(`GitHub assign issue failed: ${res.status} ${text}`); + } +} + export async function commentOnIssue( token: string, owner: string, diff --git a/src/index.ts b/src/index.ts index fb11e7b..d5d7afd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import { handleUptime } from "./routes/uptime"; import { handleBadgeRoute } from "./routes/badge"; import { handleIndex } from "./routes/index"; import { handleIncidentRoute } from "./routes/incidents"; -import { createIssue, commentOnIssue, closeIssue, parseRepo, syncGitHubIncidents } from "./github"; +import { createIssue, assignIssue, commentOnIssue, closeIssue, parseRepo, syncGitHubIncidents } from "./github"; import { schemas } from "./schemas"; async function handleRequest(request: Request, env: Env): Promise { @@ -128,9 +128,11 @@ export default { const issueNumber = await createIssue(env.GITHUB_TOKEN, parsed.owner, parsed.repo, { title: `${svc.name} is ${result.status}`, body: `Automated incident detected by [infra.dunkirk.sh](https://infra.dunkirk.sh)\n\n**Service:** ${svc.name}\n**Health URL:** ${svc.health_url}\n**Status:** ${result.status}${result.status_code ? ` (HTTP ${result.status_code})` : ""}${result.error ? ` — ${result.error}` : ""}\n**Latency:** ${result.latency_ms}ms\n**Detected at:** ${new Date().toISOString()}\n\n---\n*Comments on this issue will appear on the status page. Close the issue to resolve the incident.*`, - assignees: env.GITHUB_ASSIGNEE ? [env.GITHUB_ASSIGNEE] : [], labels: ["incident"], }); + if (env.GITHUB_ASSIGN_TOKEN && env.GITHUB_ASSIGNEE) { + await assignIssue(env.GITHUB_ASSIGN_TOKEN, parsed.owner, parsed.repo, issueNumber, [env.GITHUB_ASSIGNEE]); + } await setIncidentGitHub(env.DB, id, `${parsed.owner}/${parsed.repo}`, issueNumber); } catch (_) {} // best effort } diff --git a/src/types.ts b/src/types.ts index c6dae52..a8888fa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -65,5 +65,6 @@ export interface Env { TAILSCALE_API_KEY?: string; TRIAGE_AUTH_TOKEN?: string; GITHUB_TOKEN?: string; + GITHUB_ASSIGN_TOKEN?: string; GITHUB_ASSIGNEE?: string; }