From fef7870afc5cf751e434f49cd04763ee32645e91 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 2 Dec 2024 21:04:16 +0100 Subject: [PATCH] feat: hono --- .cspell.json | 22 ++++++- .github/knip.ts | 2 +- bun.lockb | Bin 442233 -> 442570 bytes eslint.config.mjs | 2 +- package.json | 1 + src/adapters/cloudflare-worker.ts | 3 + src/kernel.ts | 94 ++++++++++++++++++++++++++++++ src/worker.ts | 81 ------------------------- tests/dispatch.test.ts | 46 ++++----------- tests/main.test.ts | 29 ++++----- wrangler.toml | 20 +++---- 11 files changed, 154 insertions(+), 146 deletions(-) create mode 100644 src/adapters/cloudflare-worker.ts create mode 100644 src/kernel.ts delete mode 100644 src/worker.ts diff --git a/.cspell.json b/.cspell.json index ce50f46..a6887a1 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,8 +4,26 @@ "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log"], "useGitignore": true, "language": "en", - "words": ["dataurl", "devpool", "fkey", "mswjs", "outdir", "servedir", "supabase", "typebox", "ubiquity-os", - "smee", "tomlify", "hono", "cfworker", "pavlovcik", "ghijklmnopqrstuvwxyz", "GHIJKLMNOPQRSTUVWXYZ", "ubiquityos"], + "words": [ + "dataurl", + "devpool", + "fkey", + "mswjs", + "outdir", + "servedir", + "supabase", + "typebox", + "ubiquity-os", + "smee", + "tomlify", + "hono", + "cfworker", + "workerd", + "pavlovcik", + "ghijklmnopqrstuvwxyz", + "GHIJKLMNOPQRSTUVWXYZ", + "ubiquityos" + ], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/.github/knip.ts b/.github/knip.ts index 549ba26..283ac02 100644 --- a/.github/knip.ts +++ b/.github/knip.ts @@ -1,7 +1,7 @@ import type { KnipConfig } from "knip"; const config: KnipConfig = { - entry: ["src/worker.ts", "deploy/setup-kv-namespace.ts"], + entry: ["src/kernel.ts", "src/cloudflare-worker.ts", "deploy/setup-kv-namespace.ts"], project: ["src/**/*.ts"], ignore: ["jest.config.ts"], ignoreBinaries: ["i", "publish"], diff --git a/bun.lockb b/bun.lockb index 044990fb8ad54545883e54bc69ddbd20c74f3d1a..55320c25bed5c5ee7a4aa500310b85afdf84d610 100755 GIT binary patch delta 82587 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 diff --git a/eslint.config.mjs b/eslint.config.mjs index 37fa4d3..8ed97a9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ export default tsEslint.config({ "@typescript-eslint": tsEslint.plugin, "check-file": checkFile, }, - ignores: [".github/knip.ts", "**/.wrangler/**", "jest.config.ts", ".husky/**"], + ignores: [".github/knip.ts", "**/.wrangler/**", "jest.config.ts", ".husky/**", "dist/**"], extends: [eslint.configs.recommended, ...tsEslint.configs.recommended, sonarjs.configs.recommended], languageOptions: { parser: tsEslint.parser, diff --git a/package.json b/package.json index e805beb..8838ab5 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@sinclair/typebox": "0.34.3", "@ubiquity-os/plugin-sdk": "^1.1.0", "dotenv": "16.4.5", + "hono": "^4.6.12", "openai": "^4.70.2", "typebox-validators": "0.3.5", "yaml": "2.4.5" diff --git a/src/adapters/cloudflare-worker.ts b/src/adapters/cloudflare-worker.ts new file mode 100644 index 0000000..87c9d93 --- /dev/null +++ b/src/adapters/cloudflare-worker.ts @@ -0,0 +1,3 @@ +import { app } from "../kernel"; + +export default app; diff --git a/src/kernel.ts b/src/kernel.ts new file mode 100644 index 0000000..ad36c4d --- /dev/null +++ b/src/kernel.ts @@ -0,0 +1,94 @@ +import { emitterEventNames } from "@octokit/webhooks"; +import { Value } from "@sinclair/typebox/value"; +import { GitHubEventHandler } from "./github/github-event-handler"; +import { bindHandlers } from "./github/handlers"; +import { Env, envSchema } from "./github/types/env"; +import { EmptyStore } from "./github/utils/kv-store"; +import { WebhookEventName } from "@octokit/webhooks-types"; +import OpenAI from "openai"; +import { Context, Hono, HonoRequest } from "hono"; +import { env as honoEnv, getRuntimeKey } from "hono/adapter"; +import { StatusCode } from "hono/utils/http-status"; + +export const app = new Hono(); + +app.post("/", async (ctx: Context) => { + try { + const env = honoEnv(ctx); + const request = ctx.req; + + validateEnv(env); + const eventName = getEventName(request); + const signatureSha256 = getSignature(request); + const id = getId(request); + const openAiClient = new OpenAI({ + apiKey: env.OPENAI_API_KEY, + }); + const eventHandler = new GitHubEventHandler({ + environment: env.ENVIRONMENT, + webhookSecret: env.APP_WEBHOOK_SECRET, + appId: env.APP_ID, + privateKey: env.APP_PRIVATE_KEY, + pluginChainState: new EmptyStore(), + openAiClient, + }); + bindHandlers(eventHandler); + + // if running in Cloudflare Worker, handle the webhook in the background and return a response immediately + if (getRuntimeKey() === "workerd") { + const waitUntil = ctx.executionCtx.waitUntil; + waitUntil(eventHandler.webhooks.verifyAndReceive({ id, name: eventName, payload: await request.text(), signature: signatureSha256 })); + } else { + await eventHandler.webhooks.verifyAndReceive({ id, name: eventName, payload: await request.text(), signature: signatureSha256 }); + } + return ctx.text("ok\n", 200); + } catch (error) { + return handleUncaughtError(ctx, error); + } +}); + +function handleUncaughtError(ctx: Context, error: unknown) { + console.error(error); + let status = 500; + let errorMessage = "An uncaught error occurred"; + if (error instanceof AggregateError) { + const err = error.errors[0]; + errorMessage = err.message ? `${err.name}: ${err.message}` : `Error: ${errorMessage}`; + status = typeof err.status !== "undefined" && typeof err.status === "number" ? err.status : 500; + } else { + errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : `Error: ${error}`; + } + return ctx.json({ error: errorMessage }, status as StatusCode); +} + +function validateEnv(env: Env): void { + if (!Value.Check(envSchema, env)) { + const errors = [...Value.Errors(envSchema, env)]; + console.error("Invalid environment variables", errors); + throw new Error("Invalid environment variables"); + } +} + +function getEventName(request: HonoRequest): WebhookEventName { + const eventName = request.header("x-github-event"); + if (!eventName || !emitterEventNames.includes(eventName as WebhookEventName)) { + throw new Error(`Unsupported or missing "x-github-event" header value: ${eventName}`); + } + return eventName as WebhookEventName; +} + +function getSignature(request: HonoRequest): string { + const signatureSha256 = request.header("x-hub-signature-256"); + if (!signatureSha256) { + throw new Error(`Missing "x-hub-signature-256" header`); + } + return signatureSha256; +} + +function getId(request: HonoRequest): string { + const id = request.header("x-github-delivery"); + if (!id) { + throw new Error(`Missing "x-github-delivery" header`); + } + return id; +} diff --git a/src/worker.ts b/src/worker.ts deleted file mode 100644 index 711c0b9..0000000 --- a/src/worker.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { emitterEventNames } from "@octokit/webhooks"; -import { Value } from "@sinclair/typebox/value"; -import { GitHubEventHandler } from "./github/github-event-handler"; -import { bindHandlers } from "./github/handlers"; -import { Env, envSchema } from "./github/types/env"; -import { EmptyStore } from "./github/utils/kv-store"; -import { WebhookEventName } from "@octokit/webhooks-types"; -import OpenAI from "openai"; - -export default { - async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { - try { - validateEnv(env); - const eventName = getEventName(request); - const signatureSha256 = getSignature(request); - const id = getId(request); - const openAiClient = new OpenAI({ - apiKey: env.OPENAI_API_KEY, - }); - const eventHandler = new GitHubEventHandler({ - environment: env.ENVIRONMENT, - webhookSecret: env.APP_WEBHOOK_SECRET, - appId: env.APP_ID, - privateKey: env.APP_PRIVATE_KEY, - pluginChainState: new EmptyStore(), - openAiClient, - }); - bindHandlers(eventHandler); - ctx.waitUntil(eventHandler.webhooks.verifyAndReceive({ id, name: eventName, payload: await request.text(), signature: signatureSha256 })); - return new Response("ok\n", { status: 200, headers: { "content-type": "text/plain" } }); - } catch (error) { - return handleUncaughtError(error); - } - }, -}; - -function handleUncaughtError(error: unknown) { - console.error(error); - let status = 500; - let errorMessage = "An uncaught error occurred"; - if (error instanceof AggregateError) { - const err = error.errors[0]; - errorMessage = err.message ? `${err.name}: ${err.message}` : `Error: ${errorMessage}`; - status = typeof err.status !== "undefined" ? err.status : 500; - } else { - errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : `Error: ${error}`; - } - return new Response(JSON.stringify({ error: errorMessage }), { status: status, headers: { "content-type": "application/json" } }); -} - -function validateEnv(env: Env): void { - if (!Value.Check(envSchema, env)) { - const errors = [...Value.Errors(envSchema, env)]; - console.error("Invalid environment variables", errors); - throw new Error("Invalid environment variables"); - } -} - -function getEventName(request: Request): WebhookEventName { - const eventName = request.headers.get("x-github-event"); - if (!eventName || !emitterEventNames.includes(eventName as WebhookEventName)) { - throw new Error(`Unsupported or missing "x-github-event" header value: ${eventName}`); - } - return eventName as WebhookEventName; -} - -function getSignature(request: Request): string { - const signatureSha256 = request.headers.get("x-hub-signature-256"); - if (!signatureSha256) { - throw new Error(`Missing "x-hub-signature-256" header`); - } - return signatureSha256; -} - -function getId(request: Request): string { - const id = request.headers.get("x-github-delivery"); - if (!id) { - throw new Error(`Missing "x-github-delivery" header`); - } - return id; -} diff --git a/tests/dispatch.test.ts b/tests/dispatch.test.ts index 58ac6a1..365b51e 100644 --- a/tests/dispatch.test.ts +++ b/tests/dispatch.test.ts @@ -142,7 +142,16 @@ describe("handleEvent", () => { const payloadString = JSON.stringify(payload); const signature = calculateSignature(payloadString, secret); - const req = new Request("http://localhost:8080", { + process.env = { + ENVIRONMENT: "production", + APP_WEBHOOK_SECRET: secret, + APP_ID: "1", + APP_PRIVATE_KEY: "1234", + OPENAI_API_KEY: "token", + }; + + const app = (await import("../src/kernel")).app; + const res = await app.request("http://localhost:8080", { method: "POST", headers: { "x-github-event": "issue_comment.created", @@ -153,39 +162,8 @@ describe("handleEvent", () => { body: payloadString, }); - const worker = (await import("../src/worker")).default; - // I didn't find a better option to make sure that the non-awaited ctx.waitUntil is resolved - // eslint-disable-next-line no-async-promise-executor - const waitUntilPromise = new Promise(async (resolve) => { - const res = await worker.fetch( - req, - { - ENVIRONMENT: "production", - APP_WEBHOOK_SECRET: secret, - APP_ID: "1", - APP_PRIVATE_KEY: "1234", - PLUGIN_CHAIN_STATE: {} as KVNamespace, - OPENAI_API_KEY: "token", - }, - { - waitUntil(promise: Promise) { - promise - .then(() => { - resolve(); - }) - .catch(() => { - resolve(); - }); - }, - passThroughOnException() {}, - } - ); - - expect(res).toBeTruthy(); - }); - - await waitUntilPromise; - + expect(res).toBeTruthy(); + // 2 calls means the execution didn't break expect(dispatchWorker).toHaveBeenCalledTimes(2); dispatchWorker.mockReset(); diff --git a/tests/main.test.ts b/tests/main.test.ts index e8c782d..e1bb543 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -5,7 +5,7 @@ import { http, HttpResponse } from "msw"; import { GitHubContext } from "../src/github/github-context"; import { GitHubEventHandler } from "../src/github/github-event-handler"; import { getConfig } from "../src/github/utils/config"; -import worker from "../src/worker"; // has to be imported after the mocks +import { app } from "../src/kernel"; // has to be imported after the mocks import { server } from "./__mocks__/node"; import "./__mocks__/webhooks"; @@ -59,24 +59,19 @@ describe("Worker tests", () => { ); }); it("Should fail on missing env variables", async () => { - const req = new Request("http://localhost:8080"); const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => jest.fn()); - const res = await worker.fetch( - req, - { - ENVIRONMENT: "production", - APP_WEBHOOK_SECRET: "", - APP_ID: "", - APP_PRIVATE_KEY: "", - PLUGIN_CHAIN_STATE: {} as KVNamespace, - OPENAI_API_KEY: "token", - }, - { - waitUntil: function () {}, - passThroughOnException: function () {}, - } - ); + process.env = { + ENVIRONMENT: "production", + APP_WEBHOOK_SECRET: "", + APP_ID: "", + APP_PRIVATE_KEY: "", + OPENAI_API_KEY: "token", + }; + const res = await app.request("http://localhost:8080", { + method: "POST", + }); expect(res.status).toEqual(500); + expect(await res.json()).toEqual({ error: "Error: Invalid environment variables" }); consoleSpy.mockReset(); }); diff --git a/wrangler.toml b/wrangler.toml index 7e06401..26b4cd6 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,19 +1,19 @@ name = "ubiquity-os-kernel" -main = "src/worker.ts" +main = "src/adapters/cloudflare-worker.ts" compatibility_date = "2023-12-06" -compatibility_flags = [ "nodejs_compat" ] +compatibility_flags = ["nodejs_compat"] # Prefer this syntax due to a bug in Wrangler: https://github.com/cloudflare/workers-sdk/issues/5634 [env] - [env.dev] - [[env.dev.kv_namespaces]] - binding = "PLUGIN_CHAIN_STATE" - id = "4f7aadc56bef41a7ae2cc8c0582320b3" +[env.dev] +[[env.dev.kv_namespaces]] +binding = "PLUGIN_CHAIN_STATE" +id = "4f7aadc56bef41a7ae2cc8c0582320b3" - [env.production] - [[env.production.kv_namespaces]] - binding = "PLUGIN_CHAIN_STATE" - id = "TO_BE_DEFINED" +[env.production] +[[env.production.kv_namespaces]] +binding = "PLUGIN_CHAIN_STATE" +id = "TO_BE_DEFINED" # Enables Cloudflare Worker Logs [observability]