mirror of
https://github.com/saltbo/agent-kanban.git
synced 2026-09-19 09:01:47 +08:00
b301aac96a
Pin the Biome version used by CI, align Cloudflare worker types, resolve the Assistant UI peer graph, and apply the matching formatter output.
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
import type { Env } from "../../../server/env";
|
|
import { api } from "../../../server/http/app";
|
|
import { createTestEnv, setupMiniflare } from "../../helpers/db";
|
|
|
|
const webhookSecret = "test-webhook-secret-xyz";
|
|
let mf: Awaited<ReturnType<typeof setupMiniflare>>["mf"];
|
|
let env: Env;
|
|
|
|
beforeAll(async () => {
|
|
const setup = await setupMiniflare();
|
|
mf = setup.mf;
|
|
env = { ...createTestEnv(), DB: setup.db, GITHUB_APP_WEBHOOK_SECRET: webhookSecret } as Env;
|
|
});
|
|
|
|
afterAll(async () => mf.dispose());
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
|
|
describe("v2 GitHub webhook routing without Maintainers", () => {
|
|
it.each(["issues", "issue_comment", "pull_request_review", "pull_request_review_comment"])(
|
|
"does not dispatch removed Maintainer event %s",
|
|
async (event) => {
|
|
const fetchMock = vi.fn();
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
const body = JSON.stringify({ action: "created" });
|
|
|
|
const response = await webhookRequest(event, body);
|
|
|
|
expect(response.status).toBe(200);
|
|
await expect(response.json()).resolves.toMatchObject({ handled: false });
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
},
|
|
);
|
|
|
|
it("keeps pull_request task routing without a maintainer_dispatch response", async () => {
|
|
const body = JSON.stringify({ action: "opened", pull_request: { html_url: "https://github.com/acme/repo/pull/1", merged: false } });
|
|
|
|
const response = await webhookRequest("pull_request", body);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(await response.json()).not.toHaveProperty("maintainer_dispatch");
|
|
});
|
|
});
|
|
|
|
async function webhookRequest(event: string, body: string): Promise<Response> {
|
|
return api.request(
|
|
"/api/webhooks/github-app",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
"x-hub-signature-256": await signature(body),
|
|
"x-github-event": event,
|
|
},
|
|
body,
|
|
},
|
|
env,
|
|
);
|
|
}
|
|
|
|
async function signature(body: string): Promise<string> {
|
|
const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(webhookSecret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
const digest = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
|
|
return `sha256=${[...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
}
|