Download superlog/apps/api/src/github.test.ts from smlflg/Experimente: direct link, hf CLI and curl.
- Browser
- Download file 8.61 kB
-
https://huggingface.co/smlflg/Experimente/resolve/main/superlog/apps/api/src/github.test.ts
- Command line
-
hf download hf://smlflg/Experimente/superlog/apps/api/src/github.test.ts
-
curl -L -o github.test.ts https://huggingface.co/smlflg/Experimente/resolve/main/superlog/apps/api/src/github.test.ts
8.61 kB
| import "dotenv/config"; | |
| import { strict as assert } from "node:assert"; | |
| import crypto from "node:crypto"; | |
| import { after, before, test } from "node:test"; | |
| import { closeDb, db, runMigrations, schema } from "@superlog/db"; | |
| import { and, eq } from "drizzle-orm"; | |
| import { Hono } from "hono"; | |
| import { mountGithubPublic } from "./github.js"; | |
| const GH_WEBHOOK_SECRET = "github-test-secret"; | |
| process.env.GITHUB_APP_WEBHOOK_SECRET = GH_WEBHOOK_SECRET; | |
| const orgIds: string[] = []; | |
| before(async () => { | |
| await runMigrations(); | |
| }); | |
| after(async () => { | |
| try { | |
| for (const orgId of orgIds.reverse()) { | |
| await db.delete(schema.orgs).where(eq(schema.orgs.id, orgId)); | |
| } | |
| } finally { | |
| await closeDb(); | |
| } | |
| }); | |
| test("merged agent PR resolves incident, cascades linked issues, and writes timeline events", async () => { | |
| const fixture = await seedAgentPrFixture("merged"); | |
| const app = new Hono(); | |
| mountGithubPublic(app); | |
| const mergedAt = new Date().toISOString(); | |
| const res = await postGithub(app, "pull_request", `gh-${fixture.tag}-merged`, { | |
| action: "closed", | |
| repository: { full_name: fixture.repoFullName }, | |
| pull_request: { | |
| number: fixture.prNumber, | |
| merged: true, | |
| merged_at: mergedAt, | |
| closed_at: mergedAt, | |
| merged_by: { login: "alice", id: 100 }, | |
| user: { login: "superlog-bot", id: 999 }, | |
| head: { sha: "cafebabe", ref: fixture.branchName }, | |
| }, | |
| sender: { login: "alice", id: 100 }, | |
| installation: { id: fixture.installationId }, | |
| }); | |
| assert.equal(res.status, 200); | |
| const pr = await db.query.agentPullRequests.findFirst({ | |
| where: eq(schema.agentPullRequests.id, fixture.agentPrId), | |
| }); | |
| assert.equal(pr?.state, "merged"); | |
| assert.equal(pr?.mergedByLogin, "alice"); | |
| assert.ok(pr?.mergedAt); | |
| const incident = await db.query.incidents.findFirst({ | |
| where: eq(schema.incidents.id, fixture.incidentId), | |
| }); | |
| assert.equal(incident?.status, "resolved"); | |
| const issue = await db.query.issues.findFirst({ | |
| where: eq(schema.issues.id, fixture.issueId), | |
| }); | |
| assert.ok(issue); | |
| const resolvedEvents = await db.query.incidentEvents.findMany({ | |
| where: and( | |
| eq(schema.incidentEvents.agentRunId, fixture.agentRunId), | |
| eq(schema.incidentEvents.kind, "incident_resolved"), | |
| ), | |
| }); | |
| assert.equal(resolvedEvents.length, 1); | |
| assert.equal( | |
| resolvedEvents[0]?.summary, | |
| `Incident resolved because PR #${fixture.prNumber} was merged.`, | |
| ); | |
| assert.equal(resolvedEvents[0]?.detail?.reason, "agent_pr_merged"); | |
| const prMergedEvent = await db.query.agentPrEvents.findFirst({ | |
| where: and( | |
| eq(schema.agentPrEvents.agentPrId, fixture.agentPrId), | |
| eq(schema.agentPrEvents.kind, "pr_merged"), | |
| ), | |
| }); | |
| assert.ok(prMergedEvent); | |
| const duplicate = await postGithub(app, "pull_request", `gh-${fixture.tag}-merged`, { | |
| action: "closed", | |
| repository: { full_name: fixture.repoFullName }, | |
| pull_request: { | |
| number: fixture.prNumber, | |
| merged: true, | |
| merged_at: mergedAt, | |
| closed_at: mergedAt, | |
| merged_by: { login: "alice", id: 100 }, | |
| }, | |
| sender: { login: "alice", id: 100 }, | |
| installation: { id: fixture.installationId }, | |
| }); | |
| assert.equal(duplicate.status, 200); | |
| const resolvedEventsAfterDuplicate = await db.query.incidentEvents.findMany({ | |
| where: and( | |
| eq(schema.incidentEvents.agentRunId, fixture.agentRunId), | |
| eq(schema.incidentEvents.kind, "incident_resolved"), | |
| ), | |
| }); | |
| assert.equal(resolvedEventsAfterDuplicate.length, 1); | |
| }); | |
| test("closed unmerged agent PR does not resolve incident or linked issue", async () => { | |
| const fixture = await seedAgentPrFixture("closed"); | |
| const app = new Hono(); | |
| mountGithubPublic(app); | |
| const closedAt = new Date().toISOString(); | |
| const res = await postGithub(app, "pull_request", `gh-${fixture.tag}-closed`, { | |
| action: "closed", | |
| repository: { full_name: fixture.repoFullName }, | |
| pull_request: { | |
| number: fixture.prNumber, | |
| merged: false, | |
| closed_at: closedAt, | |
| user: { login: "superlog-bot", id: 999 }, | |
| }, | |
| sender: { login: "alice", id: 100 }, | |
| installation: { id: fixture.installationId }, | |
| }); | |
| assert.equal(res.status, 200); | |
| const pr = await db.query.agentPullRequests.findFirst({ | |
| where: eq(schema.agentPullRequests.id, fixture.agentPrId), | |
| }); | |
| assert.equal(pr?.state, "closed"); | |
| const incident = await db.query.incidents.findFirst({ | |
| where: eq(schema.incidents.id, fixture.incidentId), | |
| }); | |
| assert.equal(incident?.status, "open"); | |
| const issue = await db.query.issues.findFirst({ | |
| where: eq(schema.issues.id, fixture.issueId), | |
| }); | |
| assert.ok(issue); | |
| const resolvedEvent = await db.query.incidentEvents.findFirst({ | |
| where: and( | |
| eq(schema.incidentEvents.agentRunId, fixture.agentRunId), | |
| eq(schema.incidentEvents.kind, "incident_resolved"), | |
| ), | |
| }); | |
| assert.equal(resolvedEvent, undefined); | |
| }); | |
| async function seedAgentPrFixture(label: string): Promise<{ | |
| tag: string; | |
| repoFullName: string; | |
| branchName: string; | |
| installationId: number; | |
| incidentId: string; | |
| issueId: string; | |
| agentRunId: string; | |
| agentPrId: string; | |
| prNumber: number; | |
| }> { | |
| const tag = `test-${label}-${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`; | |
| const repoFullName = `acme/${tag}`; | |
| const branchName = `superlog/${tag}`; | |
| const installationId = Math.floor(Date.now() / 1000) + Math.floor(Math.random() * 1_000_000); | |
| const prNumber = Math.floor(Math.random() * 10_000) + 1; | |
| const [org] = await db | |
| .insert(schema.orgs) | |
| .values({ name: tag, slug: tag }) | |
| .returning(); | |
| if (!org) throw new Error("failed to seed org"); | |
| orgIds.push(org.id); | |
| const [project] = await db | |
| .insert(schema.projects) | |
| .values({ orgId: org.id, name: "test", slug: tag }) | |
| .returning(); | |
| if (!project) throw new Error("failed to seed project"); | |
| const now = new Date(); | |
| const [incident] = await db | |
| .insert(schema.incidents) | |
| .values({ | |
| projectId: project.id, | |
| title: "Test incident", | |
| service: "api", | |
| firstSeen: now, | |
| lastSeen: now, | |
| }) | |
| .returning(); | |
| if (!incident) throw new Error("failed to seed incident"); | |
| const [issue] = await db | |
| .insert(schema.issues) | |
| .values({ | |
| projectId: project.id, | |
| fingerprint: `fp-${tag}`, | |
| kind: "span", | |
| service: "api", | |
| exceptionType: "Error", | |
| title: "Test issue", | |
| message: "boom", | |
| firstSeen: now, | |
| lastSeen: now, | |
| }) | |
| .returning(); | |
| if (!issue) throw new Error("failed to seed issue"); | |
| await db.insert(schema.incidentIssues).values({ | |
| incidentId: incident.id, | |
| issueId: issue.id, | |
| }); | |
| const [agentRun] = await db | |
| .insert(schema.agentRuns) | |
| .values({ incidentId: incident.id, runtime: "anthropic", state: "running" }) | |
| .returning(); | |
| if (!agentRun) throw new Error("failed to seed agent run"); | |
| const [installation] = await db | |
| .insert(schema.githubInstallations) | |
| .values({ | |
| orgId: org.id, | |
| projectId: project.id, | |
| installationId, | |
| accountLogin: "acme-bot", | |
| accountType: "Organization", | |
| repos: [{ id: 1, fullName: repoFullName, private: false }], | |
| }) | |
| .returning(); | |
| if (!installation) throw new Error("failed to seed GitHub installation"); | |
| const [agentPr] = await db | |
| .insert(schema.agentPullRequests) | |
| .values({ | |
| incidentId: incident.id, | |
| agentRunId: agentRun.id, | |
| installationId: installation.id, | |
| repoFullName, | |
| prNumber, | |
| prNodeId: `PR_${tag}`, | |
| url: `https://github.com/${repoFullName}/pull/${prNumber}`, | |
| branchName, | |
| baseBranch: "main", | |
| headSha: "deadbeef", | |
| title: "[superlog] Fix bug", | |
| state: "open", | |
| lastSyncedAt: now, | |
| }) | |
| .returning(); | |
| if (!agentPr) throw new Error("failed to seed agent PR"); | |
| return { | |
| tag, | |
| repoFullName, | |
| branchName, | |
| installationId, | |
| incidentId: incident.id, | |
| issueId: issue.id, | |
| agentRunId: agentRun.id, | |
| agentPrId: agentPr.id, | |
| prNumber, | |
| }; | |
| } | |
| async function postGithub( | |
| app: Hono, | |
| event: string, | |
| delivery: string, | |
| payload: unknown, | |
| ): Promise<Response> { | |
| const body = JSON.stringify(payload); | |
| return app.request("/github/webhook", { | |
| method: "POST", | |
| headers: { | |
| "content-type": "application/json", | |
| "x-github-event": event, | |
| "x-github-delivery": delivery, | |
| "x-hub-signature-256": ghSign(body), | |
| }, | |
| body, | |
| }); | |
| } | |
| function ghSign(body: string): string { | |
| return `sha256=${crypto.createHmac("sha256", GH_WEBHOOK_SECRET).update(body).digest("hex")}`; | |
| } | |