@usepipr/runtime 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,29 +1,5 @@
1
- import { A as PiprConfig, D as ChangeRequestEventContext, E as PublicationResult, F as OfficialInitAdapter, I as supportedOfficialInitAdapters, M as ProviderConfig, N as RepositoryRef, O as ChangeRequestRef, P as RuntimeSettings, S as RuntimeLogSink, T as PublicationError, a as runInspectCommand, c as DryRunCommandOptions, d as HostRunCommandResult, f as InitCommandOptions, g as RuntimeCommandOptions, h as LocalReviewCommandResult, i as runInitCommand, j as PlatformInfo, k as DiffManifest, l as DryRunCommandResult, m as LocalReviewCommandOptions, n as runHostRunCommand, o as runLocalReviewCommand, p as InspectCommandResult, s as runValidateCommand, t as runDryRunCommand, u as HostRunCommandOptions, x as RuntimeLogRecord } from "./commands-YFjB3wx8.mjs";
2
- //#region src/config/recipes/types.d.ts
3
- type OfficialInitRecipeFile = {
4
- relativePath: string;
5
- contents: string;
6
- };
7
- type OfficialInitRecipeWorkflowEnvSecret = {
8
- env: string;
9
- secret: string;
10
- };
11
- type OfficialInitRecipe = {
12
- id: string;
13
- title: string;
14
- description: string;
15
- sourceTools: readonly string[];
16
- configTs: string;
17
- files?: readonly OfficialInitRecipeFile[];
18
- workflowEnvSecrets?: readonly OfficialInitRecipeWorkflowEnvSecret[];
19
- docsDetailsMdx?: string;
20
- };
21
- //#endregion
22
- //#region src/config/recipes.d.ts
23
- declare const supportedOfficialInitRecipes: readonly ["default-review", "bug-hunter", "rich-review", "fix-suggestions", "security-sast", "quality-gate", "diff-diagnostics", "pr-hygiene", "dependency-risk", "ci-triage-command", "multi-agent-review", "plugin-tool-review", "pr-briefing", "interactive-ask", "changelog-draft"];
24
- type OfficialInitRecipeId = (typeof supportedOfficialInitRecipes)[number];
25
- declare function listOfficialInitRecipes(): OfficialInitRecipe[];
26
- //#endregion
1
+ import { A as DiffManifest, C as RuntimeLogSink, D as PublicationResult, E as PublicationError, F as RuntimeSettings, I as OfficialInitAdapter, L as supportedOfficialInitAdapters, M as PlatformInfo, N as ProviderConfig, O as ChangeRequestEventContext, P as RepositoryRef, S as RuntimeLogRecord, a as runInspectCommand, c as DryRunCommandOptions, d as HostRunCommandResult, f as InitCommandOptions, g as RuntimeCommandOptions, h as LocalReviewCommandResult, i as runInitCommand, j as PiprConfig, k as ChangeRequestRef, l as DryRunCommandResult, m as LocalReviewCommandOptions, n as runHostRunCommand, o as runLocalReviewCommand, p as InspectCommandResult, s as runValidateCommand, t as runDryRunCommand, u as HostRunCommandOptions } from "./commands-DtdTtej_.mjs";
2
+ import { a as OfficialInitRecipeFile, i as OfficialInitRecipe, n as listOfficialInitRecipes, r as supportedOfficialInitRecipes, t as OfficialInitRecipeId } from "./recipes-w72EpAOi.mjs";
27
3
  //#region src/hosts/webhook.d.ts
28
4
  type WebhookHost = "gitlab" | "azure-devops" | "bitbucket";
29
5
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/recipes/types.ts","../src/config/recipes.ts","../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"mappings":";;KAAY;EACV;EACA;;KAGU;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB,8BAA8B;EAC9B;;;;cCGW;KAkBD,+BAA+B;iBAqB3B,2BAA2B;;;KCxD/B;;;iBCyIU,iBAAiB;EACrC,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,OAAO;IACX"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"mappings":";;;KAIY;;;iBCwIU,iBAAiB;EACrC,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,OAAO;IACX"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { _ as supportedOfficialInitRecipes, a as runInspectCommand, d as createBitbucketClient, f as createAzureDevOpsClient, g as listOfficialInitRecipes, h as supportedOfficialInitAdapters, i as runInitCommand, l as PublicationError, m as redactPotentialSecrets, n as runHostRunCommand, o as runLocalReviewCommand, p as azureOrganizationFromUrl, s as runValidateCommand, t as runDryRunCommand, u as createGitLabClient } from "./commands-ZZkXwqEn.mjs";
1
+ import { a as runInspectCommand, d as createGitLabClient, f as createBitbucketClient, h as supportedOfficialInitAdapters, i as runInitCommand, l as PublicationError, m as azureOrganizationFromUrl, n as runHostRunCommand, o as runLocalReviewCommand, p as createAzureDevOpsClient, s as runValidateCommand, t as runDryRunCommand } from "./commands-EZV-Icbs.mjs";
2
+ import { n as listOfficialInitRecipes, o as supportedOfficialInitRecipes } from "./official-github-workflow-BuZs6bOx.mjs";
2
3
  import { mkdir, mkdtemp, rm } from "node:fs/promises";
3
4
  import path from "node:path";
4
5
  import { z } from "zod";
@@ -216,7 +217,7 @@ async function processNextWebhookDelivery(options) {
216
217
  options.store.complete(delivery.id);
217
218
  options.log?.(`webhook delivery completed: ${delivery.id.slice(0, 200)}`);
218
219
  } catch (error) {
219
- const message = redactPotentialSecrets(error instanceof Error ? error.message : String(error));
220
+ const message = error instanceof Error ? error.message : String(error);
220
221
  options.store.fail(delivery.id, message.slice(0, 1e3));
221
222
  options.log?.(`webhook delivery failed and was retained for retry or inspection: ${delivery.id.slice(0, 200)}`);
222
223
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["eventSchema","isExpectedRepository"],"sources":["../src/hosts/webhook-shared.ts","../src/hosts/azure-devops/webhook.ts","../src/hosts/bitbucket/webhook.ts","../src/hosts/gitlab/webhook.ts","../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"sourcesContent":["import { timingSafeEqual } from \"node:crypto\";\n\nexport function parseWebhookJson(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nexport function webhookSecretsEqual(supplied: string | null, expected: string): boolean {\n if (!supplied) return false;\n const expectedBytes = Buffer.from(expected);\n const suppliedBytes = Buffer.from(supplied);\n return (\n expectedBytes.length === suppliedBytes.length && timingSafeEqual(expectedBytes, suppliedBytes)\n );\n}\n","import { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson, webhookSecretsEqual } from \"../webhook-shared.js\";\nimport { createAzureDevOpsClient } from \"./client.js\";\nimport { azureOrganizationFromUrl } from \"./coordinates.js\";\n\nconst eventSchema = z.looseObject({\n id: z.string().min(1),\n eventType: z.enum([\n \"git.pullrequest.created\",\n \"git.pullrequest.updated\",\n \"ms.vss-code.git-pullrequest-comment-event\",\n ]),\n subscriptionId: z.string().min(1),\n notificationId: z.union([z.number(), z.string()]).transform(String).optional(),\n resource: z.looseObject({\n repository: z\n .looseObject({ id: z.string().min(1), project: z.looseObject({ id: z.string().min(1) }) })\n .optional(),\n pullRequest: z\n .looseObject({\n repository: z.looseObject({\n id: z.string().min(1),\n project: z.looseObject({ id: z.string().min(1) }),\n }),\n })\n .optional(),\n }),\n resourceContainers: z.looseObject({\n account: z.looseObject({ baseUrl: z.string().url() }),\n project: z.looseObject({ id: z.string().min(1) }),\n }),\n});\n\ntype ExpectedRepository = {\n organization: string;\n projectId: string;\n repositoryId: string;\n subscriptionId: string;\n};\n\nexport function createAzureDevOpsWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"azure-devops\",\n async resolveExpectedRepository(env, repository) {\n const client = createAzureDevOpsClient(env);\n const resolved = await client.getRepository(repository);\n const subscriptionId = env.PIPR_AZURE_SUBSCRIPTION_ID;\n if (!subscriptionId)\n throw new Error(\"PIPR_AZURE_SUBSCRIPTION_ID is required for Azure DevOps webhooks\");\n return {\n organization: client.organization,\n projectId: resolved.projectId,\n repositoryId: resolved.id,\n subscriptionId,\n };\n },\n verifySecret(headers, secret, _payload) {\n return webhookSecretsEqual(\n headers.get(\"X-Pipr-Webhook-Secret\") ?? basicPassword(headers.get(\"Authorization\")),\n secret,\n );\n },\n matchesExpectedRepository(payload, expected) {\n if (!isExpectedRepository(expected)) return false;\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n if (!event.success) return false;\n const repository =\n event.data.resource.repository ?? event.data.resource.pullRequest?.repository;\n return (\n azureOrganizationFromUrl(event.data.resourceContainers.account.baseUrl) ===\n expected.organization &&\n event.data.resourceContainers.project.id === expected.projectId &&\n repository?.project.id === expected.projectId &&\n repository.id === expected.repositoryId &&\n event.data.subscriptionId === expected.subscriptionId\n );\n },\n deliveryId(_headers, payload) {\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n return event.success\n ? `azure-devops:${event.data.subscriptionId}:${event.data.id}:${event.data.notificationId ?? \"initial\"}`\n : undefined;\n },\n };\n}\n\nfunction isExpectedRepository(value: unknown): value is ExpectedRepository {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"organization\" in value &&\n \"projectId\" in value &&\n \"repositoryId\" in value &&\n \"subscriptionId\" in value\n );\n}\n\nfunction basicPassword(value: string | null): string | null {\n if (!value?.startsWith(\"Basic \")) return null;\n try {\n return Buffer.from(value.slice(6), \"base64\").toString().split(\":\").slice(1).join(\":\") || null;\n } catch {\n return null;\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson } from \"../webhook-shared.js\";\nimport { createBitbucketClient } from \"./client.js\";\n\nconst eventSchema = z.looseObject({\n repository: z.looseObject({ uuid: z.string().min(1), full_name: z.string().min(1) }),\n pullrequest: z.looseObject({ id: z.number().int().positive() }),\n});\n\nexport function createBitbucketWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"bitbucket\",\n async resolveExpectedRepository(env, expectedRepository) {\n const client = createBitbucketClient(env);\n if (expectedRepository !== client.repository)\n throw new Error(\n `Bitbucket --repository '${expectedRepository}' does not match BITBUCKET_REPO_SLUG '${client.repository}'`,\n );\n const repository = await client.getRepository();\n return { uuid: repository.uuid, fullName: repository.fullName };\n },\n verifySecret(headers, secret, payload) {\n return verifyBitbucketSignature(payload, headers.get(\"X-Hub-Signature\"), secret);\n },\n matchesExpectedRepository(payload, expected) {\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n return (\n event.success &&\n typeof expected === \"object\" &&\n expected !== null &&\n \"uuid\" in expected &&\n \"fullName\" in expected &&\n event.data.repository.uuid === expected.uuid &&\n event.data.repository.full_name === expected.fullName\n );\n },\n deliveryId(headers, payload) {\n const request = headers.get(\"X-Request-UUID\");\n const hook = headers.get(\"X-Hook-UUID\");\n if (!request || !hook) return undefined;\n const digest = createHmac(\"sha256\", hook).update(payload).digest(\"hex\").slice(0, 16);\n return `bitbucket:${hook}:${request}:${digest}`;\n },\n eventName(headers) {\n return headers.get(\"X-Event-Key\") ?? undefined;\n },\n runtimeEnv(eventName) {\n return eventName ? { BITBUCKET_EVENT_KEY: eventName } : {};\n },\n };\n}\n\nfunction verifyBitbucketSignature(payload: string, signature: string | null, secret: string) {\n if (!signature?.startsWith(\"sha256=\")) return false;\n const supplied = Buffer.from(signature.slice(7), \"hex\");\n const expected = createHmac(\"sha256\", secret).update(payload).digest();\n return supplied.length === expected.length && timingSafeEqual(supplied, expected);\n}\n","import { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson, webhookSecretsEqual } from \"../webhook-shared.js\";\nimport { createGitLabClient } from \"./client.js\";\n\nconst projectSchema = z.looseObject({\n project: z.looseObject({\n id: z.union([z.number(), z.string()]).transform(String),\n path_with_namespace: z.string().min(1),\n }),\n});\n\ntype ExpectedRepository = { id: string; path: string };\n\nexport function createGitLabWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"gitlab\",\n resolveExpectedRepository: (env, repository) => createGitLabClient(env).getProject(repository),\n verifySecret(headers, secret, _payload) {\n return webhookSecretsEqual(headers.get(\"X-Gitlab-Token\"), secret);\n },\n matchesExpectedRepository(payload, expected) {\n if (!isExpectedRepository(expected)) return false;\n const event = projectSchema.safeParse(parseWebhookJson(payload));\n return (\n event.success &&\n event.data.project.id === expected.id &&\n event.data.project.path_with_namespace === expected.path\n );\n },\n deliveryId(headers) {\n const id = headers.get(\"X-Gitlab-Webhook-UUID\") ?? headers.get(\"X-Gitlab-Event-UUID\");\n return id ? `gitlab:${id}` : undefined;\n },\n };\n}\n\nfunction isExpectedRepository(value: unknown): value is ExpectedRepository {\n return typeof value === \"object\" && value !== null && \"id\" in value && \"path\" in value;\n}\n","import { createAzureDevOpsWebhookProtocol } from \"./azure-devops/webhook.js\";\nimport { createBitbucketWebhookProtocol } from \"./bitbucket/webhook.js\";\nimport { createGitLabWebhookProtocol } from \"./gitlab/webhook.js\";\n\nexport type WebhookHost = \"gitlab\" | \"azure-devops\" | \"bitbucket\";\n\nexport type CodeHostWebhookProtocol = {\n host: WebhookHost;\n resolveExpectedRepository(env: NodeJS.ProcessEnv, repository: string): Promise<unknown>;\n verifySecret(headers: Headers, secret: string, payload: string): boolean;\n matchesExpectedRepository(payload: string, expected: unknown): boolean;\n deliveryId(headers: Headers, payload: string): string | undefined;\n eventName?(headers: Headers): string | undefined;\n runtimeEnv?(eventName: string | undefined): NodeJS.ProcessEnv;\n};\n\nexport function createCodeHostWebhookProtocol(host: WebhookHost): CodeHostWebhookProtocol {\n if (host === \"gitlab\") return createGitLabWebhookProtocol();\n if (host === \"azure-devops\") return createAzureDevOpsWebhookProtocol();\n if (host === \"bitbucket\") return createBitbucketWebhookProtocol();\n throw new Error(`Unsupported webhook host: ${host}`);\n}\n","import { Database } from \"bun:sqlite\";\nimport { mkdir, mkdtemp, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createCodeHostWebhookProtocol, type WebhookHost } from \"../hosts/webhook.js\";\nimport type { RuntimeLogSink } from \"../shared/logging.js\";\nimport { redactPotentialSecrets } from \"../shared/redaction.js\";\nimport { runHostRunCommand } from \"./commands.js\";\n\nconst MAX_WEBHOOK_PAYLOAD_BYTES = 2 * 1024 * 1024;\n\nexport type { WebhookHost } from \"../hosts/webhook.js\";\n\nexport type WebhookDelivery = {\n id: string;\n host: WebhookHost;\n payload: string;\n eventName?: string;\n};\n\nexport type WebhookDeliveryStore = {\n enqueue(delivery: WebhookDelivery): \"created\" | \"duplicate\" | \"full\";\n next(): WebhookDelivery | undefined;\n complete(id: string): void;\n fail(id: string, error: string): void;\n};\n\nexport function createWebhookIngress(options: {\n host: WebhookHost;\n secret: string;\n expectedRepository: unknown;\n store: WebhookDeliveryStore;\n maxPayloadBytes?: number;\n}) {\n const maxPayloadBytes = options.maxPayloadBytes ?? MAX_WEBHOOK_PAYLOAD_BYTES;\n const protocol = createCodeHostWebhookProtocol(options.host);\n return async (request: Request): Promise<Response> => {\n const healthResponse = webhookHealthResponse(request);\n if (healthResponse) return healthResponse;\n const authenticated = await readAuthenticatedWebhookPayload(\n request,\n maxPayloadBytes,\n options.secret,\n protocol.verifySecret,\n );\n if (authenticated instanceof Response) return authenticated;\n const payload = authenticated;\n if (!protocol.matchesExpectedRepository(payload, options.expectedRepository)) {\n return new Response(\"Repository mismatch\", { status: 403 });\n }\n const id = protocol.deliveryId(request.headers, payload);\n if (!id) {\n return new Response(\"Missing delivery id\", { status: 400 });\n }\n const result = options.store.enqueue({\n id,\n host: options.host,\n payload,\n eventName: protocol.eventName?.(request.headers),\n });\n if (result === \"full\") {\n return new Response(\"Queue Full\", { status: 503, headers: { \"Retry-After\": \"30\" } });\n }\n return new Response(result === \"created\" ? \"Accepted\" : \"Duplicate\", {\n status: result === \"created\" ? 202 : 200,\n });\n };\n}\n\nfunction webhookHealthResponse(request: Request): Response | undefined {\n if (request.method !== \"GET\" && request.method !== \"HEAD\") return undefined;\n return new URL(request.url).pathname === \"/healthz\" ? new Response(\"OK\") : undefined;\n}\n\nasync function readAuthenticatedWebhookPayload(\n request: Request,\n maxPayloadBytes: number,\n secret: string,\n verify: (headers: Headers, secret: string, payload: string) => boolean,\n): Promise<string | Response> {\n if (request.method !== \"POST\") return new Response(\"Method Not Allowed\", { status: 405 });\n const payload = await request.text();\n if (new TextEncoder().encode(payload).byteLength > maxPayloadBytes)\n return new Response(\"Payload Too Large\", { status: 413 });\n return verify(request.headers, secret, payload)\n ? payload\n : new Response(\"Unauthorized\", { status: 401 });\n}\n\nexport async function processNextWebhookDelivery(options: {\n store: WebhookDeliveryStore;\n run: (delivery: WebhookDelivery) => Promise<unknown>;\n log?: (message: string) => void;\n}): Promise<boolean> {\n const delivery = options.store.next();\n if (!delivery) return false;\n try {\n await options.run(delivery);\n options.store.complete(delivery.id);\n options.log?.(`webhook delivery completed: ${delivery.id.slice(0, 200)}`);\n } catch (error) {\n const message = redactPotentialSecrets(error instanceof Error ? error.message : String(error));\n options.store.fail(delivery.id, message.slice(0, 1_000));\n options.log?.(\n `webhook delivery failed and was retained for retry or inspection: ${delivery.id.slice(0, 200)}`,\n );\n }\n return true;\n}\n\nexport function createWebhookQueueProcessor(options: {\n store: WebhookDeliveryStore;\n run: (delivery: WebhookDelivery) => Promise<unknown>;\n log?: (message: string) => void;\n}) {\n let active: Promise<void> | undefined;\n let stopped = false;\n\n return {\n run(): Promise<void> {\n if (stopped) return Promise.resolve();\n active ??= (async () => {\n try {\n while (await processNextWebhookDelivery(options)) {\n // Deliveries run serially because each checkout mutates the shared workspace.\n }\n } catch {\n options.log?.(\"webhook queue processing failed; the next interval will retry\");\n }\n })().finally(() => {\n active = undefined;\n });\n return active;\n },\n async stop(): Promise<void> {\n stopped = true;\n await active;\n },\n };\n}\n\nexport async function runWebhookServer(options: {\n host: WebhookHost;\n workspace: string;\n configDir: string;\n databasePath: string;\n expectedRepository: string;\n secret: string;\n port: number;\n hostname?: string;\n env?: NodeJS.ProcessEnv;\n}): Promise<void> {\n await mkdir(path.dirname(path.resolve(options.databasePath)), { recursive: true });\n const env = { ...process.env, ...options.env };\n const protocol = createCodeHostWebhookProtocol(options.host);\n const expectedRepository = await protocol.resolveExpectedRepository(\n env,\n options.expectedRepository,\n );\n const store = new SqliteWebhookDeliveryStore(options.databasePath);\n const ingress = createWebhookIngress({\n host: options.host,\n secret: options.secret,\n expectedRepository,\n store,\n });\n const processor = createWebhookQueueProcessor({\n store,\n run: (delivery) => runWebhookDelivery(delivery, { ...options, env }),\n log: console.error,\n });\n const server = Bun.serve({\n hostname: options.hostname ?? \"127.0.0.1\",\n port: options.port,\n maxRequestBodySize: MAX_WEBHOOK_PAYLOAD_BYTES,\n fetch: ingress,\n });\n const interval = setInterval(() => void processor.run(), 250);\n const shutdown = Promise.withResolvers<void>();\n let stopping: Promise<void> | undefined;\n const stop = () => {\n stopping ??= (async () => {\n clearInterval(interval);\n server.stop();\n await processor.stop();\n store.close();\n })();\n void stopping.then(shutdown.resolve, shutdown.reject);\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n try {\n console.error(`pipr webhook server listening on ${server.hostname}:${server.port}`);\n await processor.run();\n await shutdown.promise;\n } finally {\n process.off(\"SIGINT\", stop);\n process.off(\"SIGTERM\", stop);\n }\n}\n\nexport class SqliteWebhookDeliveryStore implements WebhookDeliveryStore {\n private readonly database: Database;\n private readonly maxPendingDeliveries: number;\n private readonly maxRetainedPayloadBytes: number;\n private readonly maxRetainedDeliveries: number;\n\n constructor(\n databasePath: string,\n options: {\n maxPendingDeliveries?: number;\n maxRetainedPayloadBytes?: number;\n maxRetainedDeliveries?: number;\n } = {},\n ) {\n this.database = new Database(databasePath, { create: true, strict: true });\n this.maxPendingDeliveries = options.maxPendingDeliveries ?? 1_000;\n this.maxRetainedPayloadBytes = options.maxRetainedPayloadBytes ?? 32 * 1024 * 1024;\n this.maxRetainedDeliveries = options.maxRetainedDeliveries ?? 10_000;\n this.database.exec(\"PRAGMA journal_mode = WAL\");\n this.database.transaction(() => {\n this.database.exec(`\n CREATE TABLE IF NOT EXISTS webhook_deliveries (\n id TEXT PRIMARY KEY,\n host TEXT NOT NULL,\n payload TEXT,\n event_name TEXT,\n status TEXT NOT NULL,\n attempts INTEGER NOT NULL DEFAULT 0,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP\n );\n `);\n const columns = this.database\n .query<{ name: string }, []>(\"PRAGMA table_info(webhook_deliveries)\")\n .all();\n if (!columns.some((column) => column.name === \"event_name\")) {\n this.database.exec(\"ALTER TABLE webhook_deliveries ADD COLUMN event_name TEXT\");\n }\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = CASE WHEN attempts < 3 THEN 'pending' ELSE 'failed' END, payload = CASE WHEN attempts < 3 THEN payload ELSE NULL END, error = CASE WHEN attempts < 3 THEN error ELSE COALESCE(error, 'delivery interrupted during final attempt') END, updated_at = CURRENT_TIMESTAMP WHERE status = 'processing'\",\n )\n .run();\n })();\n }\n\n enqueue(delivery: WebhookDelivery): \"created\" | \"duplicate\" | \"full\" {\n return this.database.transaction(() => {\n const existing = this.database\n .query<{ id: string }, [string]>(\"SELECT id FROM webhook_deliveries WHERE id = ?\")\n .get(delivery.id);\n if (existing) return \"duplicate\";\n const retained = this.database\n .query<{ count: number; bytes: number }, []>(\n \"SELECT COALESCE(SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END), 0) AS count, COALESCE(SUM(length(CAST(payload AS BLOB))), 0) AS bytes FROM webhook_deliveries WHERE payload IS NOT NULL\",\n )\n .get();\n const payloadBytes = Buffer.byteLength(delivery.payload);\n if (\n !retained ||\n retained.count >= this.maxPendingDeliveries ||\n retained.bytes + payloadBytes > this.maxRetainedPayloadBytes\n ) {\n return \"full\";\n }\n this.database\n .query(\n \"INSERT INTO webhook_deliveries (id, host, payload, event_name, status) VALUES (?, ?, ?, ?, 'pending')\",\n )\n .run(delivery.id, delivery.host, delivery.payload, delivery.eventName ?? null);\n return \"created\";\n })();\n }\n\n next(): WebhookDelivery | undefined {\n return this.database.transaction(() => {\n const row = this.database\n .query<{ id: string; host: WebhookHost; payload: string; eventName?: string }, []>(\n \"SELECT id, host, payload, event_name AS eventName FROM webhook_deliveries WHERE status = 'pending' AND attempts < 3 ORDER BY created_at, id LIMIT 1\",\n )\n .get();\n if (!row) return undefined;\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'processing', attempts = attempts + 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(row.id);\n return row.eventName ? row : { id: row.id, host: row.host, payload: row.payload };\n })();\n }\n\n complete(id: string): void {\n this.database.transaction(() => {\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'completed', payload = NULL, error = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(id);\n this.pruneTerminalDeliveries();\n })();\n }\n\n fail(id: string, error: string): void {\n this.database.transaction(() => {\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = CASE WHEN attempts < 3 THEN 'pending' ELSE 'failed' END, payload = CASE WHEN attempts < 3 THEN payload ELSE NULL END, error = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(error, id);\n this.pruneTerminalDeliveries();\n })();\n }\n\n close(): void {\n this.database.close();\n }\n\n private pruneTerminalDeliveries(): void {\n // SQLite uses LIMIT -1 to leave the result unbounded after skipping the retained rows.\n this.database\n .query(\n \"DELETE FROM webhook_deliveries WHERE id IN (SELECT id FROM webhook_deliveries WHERE status IN ('completed', 'failed') ORDER BY updated_at DESC, id DESC LIMIT -1 OFFSET ?)\",\n )\n .run(this.maxRetainedDeliveries);\n }\n}\n\nexport async function runWebhookDelivery(\n delivery: WebhookDelivery,\n options: {\n workspace: string;\n configDir: string;\n env?: NodeJS.ProcessEnv;\n },\n runHostRun: typeof runHostRunCommand = runHostRunCommand,\n): Promise<void> {\n const directory = await mkdtemp(path.join(os.tmpdir(), \"pipr-webhook-\"));\n const eventPath = path.join(directory, \"event.json\");\n const protocol = createCodeHostWebhookProtocol(delivery.host);\n try {\n await Bun.write(eventPath, delivery.payload);\n await runHostRun({\n rootDir: options.workspace,\n configDir: options.configDir,\n host: delivery.host,\n eventPath,\n env: {\n ...process.env,\n ...options.env,\n PIPR_CODE_HOST: delivery.host,\n ...protocol.runtimeEnv?.(delivery.eventName),\n },\n dryRun: false,\n logSink: consoleRuntimeLogSink,\n });\n } finally {\n await rm(directory, { recursive: true, force: true });\n }\n}\n\nconst consoleRuntimeLogSink: RuntimeLogSink = {\n log(record) {\n console.log(JSON.stringify(record));\n },\n async group(_name, run) {\n return await run();\n },\n};\n"],"mappings":";;;;;;;;AAEA,SAAgB,iBAAiB,OAAwB;CACvD,IAAI;EACF,OAAO,KAAK,MAAM,KAAK;CACzB,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,oBAAoB,UAAyB,UAA2B;CACtF,IAAI,CAAC,UAAU,OAAO;CACtB,MAAM,gBAAgB,OAAO,KAAK,QAAQ;CAC1C,MAAM,gBAAgB,OAAO,KAAK,QAAQ;CAC1C,OACE,cAAc,WAAW,cAAc,UAAU,gBAAgB,eAAe,aAAa;AAEjG;;;ACXA,MAAMA,gBAAc,EAAE,YAAY;CAChC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACpB,WAAW,EAAE,KAAK;EAChB;EACA;EACA;CACF,CAAC;CACD,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CAChC,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,SAAS;CAC7E,UAAU,EAAE,YAAY;EACtB,YAAY,EACT,YAAY;GAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;GAAG,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;EAAE,CAAC,CAAC,CACzF,SAAS;EACZ,aAAa,EACV,YAAY,EACX,YAAY,EAAE,YAAY;GACxB,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;GACpB,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;EAClD,CAAC,EACH,CAAC,CAAC,CACD,SAAS;CACd,CAAC;CACD,oBAAoB,EAAE,YAAY;EAChC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;EACpD,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;CAClD,CAAC;AACH,CAAC;AASD,SAAgB,mCAA4D;CAC1E,OAAO;EACL,MAAM;EACN,MAAM,0BAA0B,KAAK,YAAY;GAC/C,MAAM,SAAS,wBAAwB,GAAG;GAC1C,MAAM,WAAW,MAAM,OAAO,cAAc,UAAU;GACtD,MAAM,iBAAiB,IAAI;GAC3B,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,kEAAkE;GACpF,OAAO;IACL,cAAc,OAAO;IACrB,WAAW,SAAS;IACpB,cAAc,SAAS;IACvB;GACF;EACF;EACA,aAAa,SAAS,QAAQ,UAAU;GACtC,OAAO,oBACL,QAAQ,IAAI,uBAAuB,KAAK,cAAc,QAAQ,IAAI,eAAe,CAAC,GAClF,MACF;EACF;EACA,0BAA0B,SAAS,UAAU;GAC3C,IAAI,CAACC,uBAAqB,QAAQ,GAAG,OAAO;GAC5C,MAAM,QAAQD,cAAY,UAAU,iBAAiB,OAAO,CAAC;GAC7D,IAAI,CAAC,MAAM,SAAS,OAAO;GAC3B,MAAM,aACJ,MAAM,KAAK,SAAS,cAAc,MAAM,KAAK,SAAS,aAAa;GACrE,OACE,yBAAyB,MAAM,KAAK,mBAAmB,QAAQ,OAAO,MACpE,SAAS,gBACX,MAAM,KAAK,mBAAmB,QAAQ,OAAO,SAAS,aACtD,YAAY,QAAQ,OAAO,SAAS,aACpC,WAAW,OAAO,SAAS,gBAC3B,MAAM,KAAK,mBAAmB,SAAS;EAE3C;EACA,WAAW,UAAU,SAAS;GAC5B,MAAM,QAAQA,cAAY,UAAU,iBAAiB,OAAO,CAAC;GAC7D,OAAO,MAAM,UACT,gBAAgB,MAAM,KAAK,eAAe,GAAG,MAAM,KAAK,GAAG,GAAG,MAAM,KAAK,kBAAkB,cAC3F,KAAA;EACN;CACF;AACF;AAEA,SAASC,uBAAqB,OAA6C;CACzE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,kBAAkB,SAClB,eAAe,SACf,kBAAkB,SAClB,oBAAoB;AAExB;AAEA,SAAS,cAAc,OAAqC;CAC1D,IAAI,CAAC,OAAO,WAAW,QAAQ,GAAG,OAAO;CACzC,IAAI;EACF,OAAO,OAAO,KAAK,MAAM,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK;CAC3F,QAAQ;EACN,OAAO;CACT;AACF;;;ACnGA,MAAM,cAAc,EAAE,YAAY;CAChC,YAAY,EAAE,YAAY;EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;EAAG,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CAAE,CAAC;CACnF,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;AAChE,CAAC;AAED,SAAgB,iCAA0D;CACxE,OAAO;EACL,MAAM;EACN,MAAM,0BAA0B,KAAK,oBAAoB;GACvD,MAAM,SAAS,sBAAsB,GAAG;GACxC,IAAI,uBAAuB,OAAO,YAChC,MAAM,IAAI,MACR,2BAA2B,mBAAmB,wCAAwC,OAAO,WAAW,EAC1G;GACF,MAAM,aAAa,MAAM,OAAO,cAAc;GAC9C,OAAO;IAAE,MAAM,WAAW;IAAM,UAAU,WAAW;GAAS;EAChE;EACA,aAAa,SAAS,QAAQ,SAAS;GACrC,OAAO,yBAAyB,SAAS,QAAQ,IAAI,iBAAiB,GAAG,MAAM;EACjF;EACA,0BAA0B,SAAS,UAAU;GAC3C,MAAM,QAAQ,YAAY,UAAU,iBAAiB,OAAO,CAAC;GAC7D,OACE,MAAM,WACN,OAAO,aAAa,YACpB,aAAa,QACb,UAAU,YACV,cAAc,YACd,MAAM,KAAK,WAAW,SAAS,SAAS,QACxC,MAAM,KAAK,WAAW,cAAc,SAAS;EAEjD;EACA,WAAW,SAAS,SAAS;GAC3B,MAAM,UAAU,QAAQ,IAAI,gBAAgB;GAC5C,MAAM,OAAO,QAAQ,IAAI,aAAa;GACtC,IAAI,CAAC,WAAW,CAAC,MAAM,OAAO,KAAA;GAE9B,OAAO,aAAa,KAAK,GAAG,QAAQ,GADrB,WAAW,UAAU,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EACrC;EAC9C;EACA,UAAU,SAAS;GACjB,OAAO,QAAQ,IAAI,aAAa,KAAK,KAAA;EACvC;EACA,WAAW,WAAW;GACpB,OAAO,YAAY,EAAE,qBAAqB,UAAU,IAAI,CAAC;EAC3D;CACF;AACF;AAEA,SAAS,yBAAyB,SAAiB,WAA0B,QAAgB;CAC3F,IAAI,CAAC,WAAW,WAAW,SAAS,GAAG,OAAO;CAC9C,MAAM,WAAW,OAAO,KAAK,UAAU,MAAM,CAAC,GAAG,KAAK;CACtD,MAAM,WAAW,WAAW,UAAU,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO;CACrE,OAAO,SAAS,WAAW,SAAS,UAAU,gBAAgB,UAAU,QAAQ;AAClF;;;ACtDA,MAAM,gBAAgB,EAAE,YAAY,EAClC,SAAS,EAAE,YAAY;CACrB,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM;CACtD,qBAAqB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC,EACH,CAAC;AAID,SAAgB,8BAAuD;CACrE,OAAO;EACL,MAAM;EACN,4BAA4B,KAAK,eAAe,mBAAmB,GAAG,CAAC,CAAC,WAAW,UAAU;EAC7F,aAAa,SAAS,QAAQ,UAAU;GACtC,OAAO,oBAAoB,QAAQ,IAAI,gBAAgB,GAAG,MAAM;EAClE;EACA,0BAA0B,SAAS,UAAU;GAC3C,IAAI,CAAC,qBAAqB,QAAQ,GAAG,OAAO;GAC5C,MAAM,QAAQ,cAAc,UAAU,iBAAiB,OAAO,CAAC;GAC/D,OACE,MAAM,WACN,MAAM,KAAK,QAAQ,OAAO,SAAS,MACnC,MAAM,KAAK,QAAQ,wBAAwB,SAAS;EAExD;EACA,WAAW,SAAS;GAClB,MAAM,KAAK,QAAQ,IAAI,uBAAuB,KAAK,QAAQ,IAAI,qBAAqB;GACpF,OAAO,KAAK,UAAU,OAAO,KAAA;EAC/B;CACF;AACF;AAEA,SAAS,qBAAqB,OAA6C;CACzE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,QAAQ,SAAS,UAAU;AACnF;;;ACvBA,SAAgB,8BAA8B,MAA4C;CACxF,IAAI,SAAS,UAAU,OAAO,4BAA4B;CAC1D,IAAI,SAAS,gBAAgB,OAAO,iCAAiC;CACrE,IAAI,SAAS,aAAa,OAAO,+BAA+B;CAChE,MAAM,IAAI,MAAM,6BAA6B,MAAM;AACrD;;;ACZA,MAAM,4BAA4B,IAAI,OAAO;AAkB7C,SAAgB,qBAAqB,SAMlC;CACD,MAAM,kBAAkB,QAAQ,mBAAmB;CACnD,MAAM,WAAW,8BAA8B,QAAQ,IAAI;CAC3D,OAAO,OAAO,YAAwC;EACpD,MAAM,iBAAiB,sBAAsB,OAAO;EACpD,IAAI,gBAAgB,OAAO;EAC3B,MAAM,gBAAgB,MAAM,gCAC1B,SACA,iBACA,QAAQ,QACR,SAAS,YACX;EACA,IAAI,yBAAyB,UAAU,OAAO;EAC9C,MAAM,UAAU;EAChB,IAAI,CAAC,SAAS,0BAA0B,SAAS,QAAQ,kBAAkB,GACzE,OAAO,IAAI,SAAS,uBAAuB,EAAE,QAAQ,IAAI,CAAC;EAE5D,MAAM,KAAK,SAAS,WAAW,QAAQ,SAAS,OAAO;EACvD,IAAI,CAAC,IACH,OAAO,IAAI,SAAS,uBAAuB,EAAE,QAAQ,IAAI,CAAC;EAE5D,MAAM,SAAS,QAAQ,MAAM,QAAQ;GACnC;GACA,MAAM,QAAQ;GACd;GACA,WAAW,SAAS,YAAY,QAAQ,OAAO;EACjD,CAAC;EACD,IAAI,WAAW,QACb,OAAO,IAAI,SAAS,cAAc;GAAE,QAAQ;GAAK,SAAS,EAAE,eAAe,KAAK;EAAE,CAAC;EAErF,OAAO,IAAI,SAAS,WAAW,YAAY,aAAa,aAAa,EACnE,QAAQ,WAAW,YAAY,MAAM,IACvC,CAAC;CACH;AACF;AAEA,SAAS,sBAAsB,SAAwC;CACrE,IAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,QAAQ,OAAO,KAAA;CAClE,OAAO,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,aAAa,aAAa,IAAI,SAAS,IAAI,IAAI,KAAA;AAC7E;AAEA,eAAe,gCACb,SACA,iBACA,QACA,QAC4B;CAC5B,IAAI,QAAQ,WAAW,QAAQ,OAAO,IAAI,SAAS,sBAAsB,EAAE,QAAQ,IAAI,CAAC;CACxF,MAAM,UAAU,MAAM,QAAQ,KAAK;CACnC,IAAI,IAAI,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,aAAa,iBACjD,OAAO,IAAI,SAAS,qBAAqB,EAAE,QAAQ,IAAI,CAAC;CAC1D,OAAO,OAAO,QAAQ,SAAS,QAAQ,OAAO,IAC1C,UACA,IAAI,SAAS,gBAAgB,EAAE,QAAQ,IAAI,CAAC;AAClD;AAEA,eAAsB,2BAA2B,SAI5B;CACnB,MAAM,WAAW,QAAQ,MAAM,KAAK;CACpC,IAAI,CAAC,UAAU,OAAO;CACtB,IAAI;EACF,MAAM,QAAQ,IAAI,QAAQ;EAC1B,QAAQ,MAAM,SAAS,SAAS,EAAE;EAClC,QAAQ,MAAM,+BAA+B,SAAS,GAAG,MAAM,GAAG,GAAG,GAAG;CAC1E,SAAS,OAAO;EACd,MAAM,UAAU,uBAAuB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EAC7F,QAAQ,MAAM,KAAK,SAAS,IAAI,QAAQ,MAAM,GAAG,GAAK,CAAC;EACvD,QAAQ,MACN,qEAAqE,SAAS,GAAG,MAAM,GAAG,GAAG,GAC/F;CACF;CACA,OAAO;AACT;AAEA,SAAgB,4BAA4B,SAIzC;CACD,IAAI;CACJ,IAAI,UAAU;CAEd,OAAO;EACL,MAAqB;GACnB,IAAI,SAAS,OAAO,QAAQ,QAAQ;GACpC,YAAY,YAAY;IACtB,IAAI;KACF,OAAO,MAAM,2BAA2B,OAAO;IAGjD,QAAQ;KACN,QAAQ,MAAM,+DAA+D;IAC/E;GACF,EAAA,CAAG,CAAC,CAAC,cAAc;IACjB,SAAS,KAAA;GACX,CAAC;GACD,OAAO;EACT;EACA,MAAM,OAAsB;GAC1B,UAAU;GACV,MAAM;EACR;CACF;AACF;AAEA,eAAsB,iBAAiB,SAUrB;CAChB,MAAM,MAAM,KAAK,QAAQ,KAAK,QAAQ,QAAQ,YAAY,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;CACjF,MAAM,MAAM;EAAE,GAAG,QAAQ;EAAK,GAAG,QAAQ;CAAI;CAE7C,MAAM,qBAAqB,MADV,8BAA8B,QAAQ,IACf,CAAC,CAAC,0BACxC,KACA,QAAQ,kBACV;CACA,MAAM,QAAQ,IAAI,2BAA2B,QAAQ,YAAY;CACjE,MAAM,UAAU,qBAAqB;EACnC,MAAM,QAAQ;EACd,QAAQ,QAAQ;EAChB;EACA;CACF,CAAC;CACD,MAAM,YAAY,4BAA4B;EAC5C;EACA,MAAM,aAAa,mBAAmB,UAAU;GAAE,GAAG;GAAS;EAAI,CAAC;EACnE,KAAK,QAAQ;CACf,CAAC;CACD,MAAM,SAAS,IAAI,MAAM;EACvB,UAAU,QAAQ,YAAY;EAC9B,MAAM,QAAQ;EACd,oBAAoB;EACpB,OAAO;CACT,CAAC;CACD,MAAM,WAAW,kBAAkB,KAAK,UAAU,IAAI,GAAG,GAAG;CAC5D,MAAM,WAAW,QAAQ,cAAoB;CAC7C,IAAI;CACJ,MAAM,aAAa;EACjB,cAAc,YAAY;GACxB,cAAc,QAAQ;GACtB,OAAO,KAAK;GACZ,MAAM,UAAU,KAAK;GACrB,MAAM,MAAM;EACd,EAAA,CAAG;EACH,SAAc,KAAK,SAAS,SAAS,SAAS,MAAM;CACtD;CACA,QAAQ,KAAK,UAAU,IAAI;CAC3B,QAAQ,KAAK,WAAW,IAAI;CAC5B,IAAI;EACF,QAAQ,MAAM,oCAAoC,OAAO,SAAS,GAAG,OAAO,MAAM;EAClF,MAAM,UAAU,IAAI;EACpB,MAAM,SAAS;CACjB,UAAU;EACR,QAAQ,IAAI,UAAU,IAAI;EAC1B,QAAQ,IAAI,WAAW,IAAI;CAC7B;AACF;AAEA,IAAa,6BAAb,MAAwE;CACtE;CACA;CACA;CACA;CAEA,YACE,cACA,UAII,CAAC,GACL;EACA,KAAK,WAAW,IAAI,SAAS,cAAc;GAAE,QAAQ;GAAM,QAAQ;EAAK,CAAC;EACzE,KAAK,uBAAuB,QAAQ,wBAAwB;EAC5D,KAAK,0BAA0B,QAAQ,2BAA2B,KAAK,OAAO;EAC9E,KAAK,wBAAwB,QAAQ,yBAAyB;EAC9D,KAAK,SAAS,KAAK,2BAA2B;EAC9C,KAAK,SAAS,kBAAkB;GAC9B,KAAK,SAAS,KAAK;;;;;;;;;;;;OAYlB;GAID,IAAI,CAHY,KAAK,SAClB,MAA4B,uCAAuC,CAAC,CACpE,IACQ,CAAC,CAAC,MAAM,WAAW,OAAO,SAAS,YAAY,GACxD,KAAK,SAAS,KAAK,2DAA2D;GAEhF,KAAK,SACF,MACC,0UACF,CAAC,CACA,IAAI;EACT,CAAC,CAAC,CAAC;CACL;CAEA,QAAQ,UAA6D;EACnE,OAAO,KAAK,SAAS,kBAAkB;GAIrC,IAHiB,KAAK,SACnB,MAAgC,gDAAgD,CAAC,CACjF,IAAI,SAAS,EACL,GAAG,OAAO;GACrB,MAAM,WAAW,KAAK,SACnB,MACC,8LACF,CAAC,CACA,IAAI;GACP,MAAM,eAAe,OAAO,WAAW,SAAS,OAAO;GACvD,IACE,CAAC,YACD,SAAS,SAAS,KAAK,wBACvB,SAAS,QAAQ,eAAe,KAAK,yBAErC,OAAO;GAET,KAAK,SACF,MACC,uGACF,CAAC,CACA,IAAI,SAAS,IAAI,SAAS,MAAM,SAAS,SAAS,SAAS,aAAa,IAAI;GAC/E,OAAO;EACT,CAAC,CAAC,CAAC;CACL;CAEA,OAAoC;EAClC,OAAO,KAAK,SAAS,kBAAkB;GACrC,MAAM,MAAM,KAAK,SACd,MACC,qJACF,CAAC,CACA,IAAI;GACP,IAAI,CAAC,KAAK,OAAO,KAAA;GACjB,KAAK,SACF,MACC,2HACF,CAAC,CACA,IAAI,IAAI,EAAE;GACb,OAAO,IAAI,YAAY,MAAM;IAAE,IAAI,IAAI;IAAI,MAAM,IAAI;IAAM,SAAS,IAAI;GAAQ;EAClF,CAAC,CAAC,CAAC;CACL;CAEA,SAAS,IAAkB;EACzB,KAAK,SAAS,kBAAkB;GAC9B,KAAK,SACF,MACC,+HACF,CAAC,CACA,IAAI,EAAE;GACT,KAAK,wBAAwB;EAC/B,CAAC,CAAC,CAAC;CACL;CAEA,KAAK,IAAY,OAAqB;EACpC,KAAK,SAAS,kBAAkB;GAC9B,KAAK,SACF,MACC,qNACF,CAAC,CACA,IAAI,OAAO,EAAE;GAChB,KAAK,wBAAwB;EAC/B,CAAC,CAAC,CAAC;CACL;CAEA,QAAc;EACZ,KAAK,SAAS,MAAM;CACtB;CAEA,0BAAwC;EAEtC,KAAK,SACF,MACC,4KACF,CAAC,CACA,IAAI,KAAK,qBAAqB;CACnC;AACF;AAEA,eAAsB,mBACpB,UACA,SAKA,aAAuC,mBACxB;CACf,MAAM,YAAY,MAAM,QAAQ,KAAK,KAAK,GAAG,OAAO,GAAG,eAAe,CAAC;CACvE,MAAM,YAAY,KAAK,KAAK,WAAW,YAAY;CACnD,MAAM,WAAW,8BAA8B,SAAS,IAAI;CAC5D,IAAI;EACF,MAAM,IAAI,MAAM,WAAW,SAAS,OAAO;EAC3C,MAAM,WAAW;GACf,SAAS,QAAQ;GACjB,WAAW,QAAQ;GACnB,MAAM,SAAS;GACf;GACA,KAAK;IACH,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,gBAAgB,SAAS;IACzB,GAAG,SAAS,aAAa,SAAS,SAAS;GAC7C;GACA,QAAQ;GACR,SAAS;EACX,CAAC;CACH,UAAU;EACR,MAAM,GAAG,WAAW;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CACtD;AACF;AAEA,MAAM,wBAAwC;CAC5C,IAAI,QAAQ;EACV,QAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;CACpC;CACA,MAAM,MAAM,OAAO,KAAK;EACtB,OAAO,MAAM,IAAI;CACnB;AACF"}
1
+ {"version":3,"file":"index.mjs","names":["eventSchema","isExpectedRepository"],"sources":["../src/hosts/webhook-shared.ts","../src/hosts/azure-devops/webhook.ts","../src/hosts/bitbucket/webhook.ts","../src/hosts/gitlab/webhook.ts","../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"sourcesContent":["import { timingSafeEqual } from \"node:crypto\";\n\nexport function parseWebhookJson(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nexport function webhookSecretsEqual(supplied: string | null, expected: string): boolean {\n if (!supplied) return false;\n const expectedBytes = Buffer.from(expected);\n const suppliedBytes = Buffer.from(supplied);\n return (\n expectedBytes.length === suppliedBytes.length && timingSafeEqual(expectedBytes, suppliedBytes)\n );\n}\n","import { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson, webhookSecretsEqual } from \"../webhook-shared.js\";\nimport { createAzureDevOpsClient } from \"./client.js\";\nimport { azureOrganizationFromUrl } from \"./coordinates.js\";\n\nconst eventSchema = z.looseObject({\n id: z.string().min(1),\n eventType: z.enum([\n \"git.pullrequest.created\",\n \"git.pullrequest.updated\",\n \"ms.vss-code.git-pullrequest-comment-event\",\n ]),\n subscriptionId: z.string().min(1),\n notificationId: z.union([z.number(), z.string()]).transform(String).optional(),\n resource: z.looseObject({\n repository: z\n .looseObject({ id: z.string().min(1), project: z.looseObject({ id: z.string().min(1) }) })\n .optional(),\n pullRequest: z\n .looseObject({\n repository: z.looseObject({\n id: z.string().min(1),\n project: z.looseObject({ id: z.string().min(1) }),\n }),\n })\n .optional(),\n }),\n resourceContainers: z.looseObject({\n account: z.looseObject({ baseUrl: z.string().url() }),\n project: z.looseObject({ id: z.string().min(1) }),\n }),\n});\n\ntype ExpectedRepository = {\n organization: string;\n projectId: string;\n repositoryId: string;\n subscriptionId: string;\n};\n\nexport function createAzureDevOpsWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"azure-devops\",\n async resolveExpectedRepository(env, repository) {\n const client = createAzureDevOpsClient(env);\n const resolved = await client.getRepository(repository);\n const subscriptionId = env.PIPR_AZURE_SUBSCRIPTION_ID;\n if (!subscriptionId)\n throw new Error(\"PIPR_AZURE_SUBSCRIPTION_ID is required for Azure DevOps webhooks\");\n return {\n organization: client.organization,\n projectId: resolved.projectId,\n repositoryId: resolved.id,\n subscriptionId,\n };\n },\n verifySecret(headers, secret, _payload) {\n return webhookSecretsEqual(\n headers.get(\"X-Pipr-Webhook-Secret\") ?? basicPassword(headers.get(\"Authorization\")),\n secret,\n );\n },\n matchesExpectedRepository(payload, expected) {\n if (!isExpectedRepository(expected)) return false;\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n if (!event.success) return false;\n const repository =\n event.data.resource.repository ?? event.data.resource.pullRequest?.repository;\n return (\n azureOrganizationFromUrl(event.data.resourceContainers.account.baseUrl) ===\n expected.organization &&\n event.data.resourceContainers.project.id === expected.projectId &&\n repository?.project.id === expected.projectId &&\n repository.id === expected.repositoryId &&\n event.data.subscriptionId === expected.subscriptionId\n );\n },\n deliveryId(_headers, payload) {\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n return event.success\n ? `azure-devops:${event.data.subscriptionId}:${event.data.id}:${event.data.notificationId ?? \"initial\"}`\n : undefined;\n },\n };\n}\n\nfunction isExpectedRepository(value: unknown): value is ExpectedRepository {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"organization\" in value &&\n \"projectId\" in value &&\n \"repositoryId\" in value &&\n \"subscriptionId\" in value\n );\n}\n\nfunction basicPassword(value: string | null): string | null {\n if (!value?.startsWith(\"Basic \")) return null;\n try {\n return Buffer.from(value.slice(6), \"base64\").toString().split(\":\").slice(1).join(\":\") || null;\n } catch {\n return null;\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson } from \"../webhook-shared.js\";\nimport { createBitbucketClient } from \"./client.js\";\n\nconst eventSchema = z.looseObject({\n repository: z.looseObject({ uuid: z.string().min(1), full_name: z.string().min(1) }),\n pullrequest: z.looseObject({ id: z.number().int().positive() }),\n});\n\nexport function createBitbucketWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"bitbucket\",\n async resolveExpectedRepository(env, expectedRepository) {\n const client = createBitbucketClient(env);\n if (expectedRepository !== client.repository)\n throw new Error(\n `Bitbucket --repository '${expectedRepository}' does not match BITBUCKET_REPO_SLUG '${client.repository}'`,\n );\n const repository = await client.getRepository();\n return { uuid: repository.uuid, fullName: repository.fullName };\n },\n verifySecret(headers, secret, payload) {\n return verifyBitbucketSignature(payload, headers.get(\"X-Hub-Signature\"), secret);\n },\n matchesExpectedRepository(payload, expected) {\n const event = eventSchema.safeParse(parseWebhookJson(payload));\n return (\n event.success &&\n typeof expected === \"object\" &&\n expected !== null &&\n \"uuid\" in expected &&\n \"fullName\" in expected &&\n event.data.repository.uuid === expected.uuid &&\n event.data.repository.full_name === expected.fullName\n );\n },\n deliveryId(headers, payload) {\n const request = headers.get(\"X-Request-UUID\");\n const hook = headers.get(\"X-Hook-UUID\");\n if (!request || !hook) return undefined;\n const digest = createHmac(\"sha256\", hook).update(payload).digest(\"hex\").slice(0, 16);\n return `bitbucket:${hook}:${request}:${digest}`;\n },\n eventName(headers) {\n return headers.get(\"X-Event-Key\") ?? undefined;\n },\n runtimeEnv(eventName) {\n return eventName ? { BITBUCKET_EVENT_KEY: eventName } : {};\n },\n };\n}\n\nfunction verifyBitbucketSignature(payload: string, signature: string | null, secret: string) {\n if (!signature?.startsWith(\"sha256=\")) return false;\n const supplied = Buffer.from(signature.slice(7), \"hex\");\n const expected = createHmac(\"sha256\", secret).update(payload).digest();\n return supplied.length === expected.length && timingSafeEqual(supplied, expected);\n}\n","import { z } from \"zod\";\nimport type { CodeHostWebhookProtocol } from \"../webhook.js\";\nimport { parseWebhookJson, webhookSecretsEqual } from \"../webhook-shared.js\";\nimport { createGitLabClient } from \"./client.js\";\n\nconst projectSchema = z.looseObject({\n project: z.looseObject({\n id: z.union([z.number(), z.string()]).transform(String),\n path_with_namespace: z.string().min(1),\n }),\n});\n\ntype ExpectedRepository = { id: string; path: string };\n\nexport function createGitLabWebhookProtocol(): CodeHostWebhookProtocol {\n return {\n host: \"gitlab\",\n resolveExpectedRepository: (env, repository) => createGitLabClient(env).getProject(repository),\n verifySecret(headers, secret, _payload) {\n return webhookSecretsEqual(headers.get(\"X-Gitlab-Token\"), secret);\n },\n matchesExpectedRepository(payload, expected) {\n if (!isExpectedRepository(expected)) return false;\n const event = projectSchema.safeParse(parseWebhookJson(payload));\n return (\n event.success &&\n event.data.project.id === expected.id &&\n event.data.project.path_with_namespace === expected.path\n );\n },\n deliveryId(headers) {\n const id = headers.get(\"X-Gitlab-Webhook-UUID\") ?? headers.get(\"X-Gitlab-Event-UUID\");\n return id ? `gitlab:${id}` : undefined;\n },\n };\n}\n\nfunction isExpectedRepository(value: unknown): value is ExpectedRepository {\n return typeof value === \"object\" && value !== null && \"id\" in value && \"path\" in value;\n}\n","import { createAzureDevOpsWebhookProtocol } from \"./azure-devops/webhook.js\";\nimport { createBitbucketWebhookProtocol } from \"./bitbucket/webhook.js\";\nimport { createGitLabWebhookProtocol } from \"./gitlab/webhook.js\";\n\nexport type WebhookHost = \"gitlab\" | \"azure-devops\" | \"bitbucket\";\n\nexport type CodeHostWebhookProtocol = {\n host: WebhookHost;\n resolveExpectedRepository(env: NodeJS.ProcessEnv, repository: string): Promise<unknown>;\n verifySecret(headers: Headers, secret: string, payload: string): boolean;\n matchesExpectedRepository(payload: string, expected: unknown): boolean;\n deliveryId(headers: Headers, payload: string): string | undefined;\n eventName?(headers: Headers): string | undefined;\n runtimeEnv?(eventName: string | undefined): NodeJS.ProcessEnv;\n};\n\nexport function createCodeHostWebhookProtocol(host: WebhookHost): CodeHostWebhookProtocol {\n if (host === \"gitlab\") return createGitLabWebhookProtocol();\n if (host === \"azure-devops\") return createAzureDevOpsWebhookProtocol();\n if (host === \"bitbucket\") return createBitbucketWebhookProtocol();\n throw new Error(`Unsupported webhook host: ${host}`);\n}\n","import { Database } from \"bun:sqlite\";\nimport { mkdir, mkdtemp, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createCodeHostWebhookProtocol, type WebhookHost } from \"../hosts/webhook.js\";\nimport type { RuntimeLogSink } from \"../shared/logging.js\";\nimport { runHostRunCommand } from \"./commands.js\";\n\nconst MAX_WEBHOOK_PAYLOAD_BYTES = 2 * 1024 * 1024;\n\nexport type { WebhookHost } from \"../hosts/webhook.js\";\n\nexport type WebhookDelivery = {\n id: string;\n host: WebhookHost;\n payload: string;\n eventName?: string;\n};\n\nexport type WebhookDeliveryStore = {\n enqueue(delivery: WebhookDelivery): \"created\" | \"duplicate\" | \"full\";\n next(): WebhookDelivery | undefined;\n complete(id: string): void;\n fail(id: string, error: string): void;\n};\n\nexport function createWebhookIngress(options: {\n host: WebhookHost;\n secret: string;\n expectedRepository: unknown;\n store: WebhookDeliveryStore;\n maxPayloadBytes?: number;\n}) {\n const maxPayloadBytes = options.maxPayloadBytes ?? MAX_WEBHOOK_PAYLOAD_BYTES;\n const protocol = createCodeHostWebhookProtocol(options.host);\n return async (request: Request): Promise<Response> => {\n const healthResponse = webhookHealthResponse(request);\n if (healthResponse) return healthResponse;\n const authenticated = await readAuthenticatedWebhookPayload(\n request,\n maxPayloadBytes,\n options.secret,\n protocol.verifySecret,\n );\n if (authenticated instanceof Response) return authenticated;\n const payload = authenticated;\n if (!protocol.matchesExpectedRepository(payload, options.expectedRepository)) {\n return new Response(\"Repository mismatch\", { status: 403 });\n }\n const id = protocol.deliveryId(request.headers, payload);\n if (!id) {\n return new Response(\"Missing delivery id\", { status: 400 });\n }\n const result = options.store.enqueue({\n id,\n host: options.host,\n payload,\n eventName: protocol.eventName?.(request.headers),\n });\n if (result === \"full\") {\n return new Response(\"Queue Full\", { status: 503, headers: { \"Retry-After\": \"30\" } });\n }\n return new Response(result === \"created\" ? \"Accepted\" : \"Duplicate\", {\n status: result === \"created\" ? 202 : 200,\n });\n };\n}\n\nfunction webhookHealthResponse(request: Request): Response | undefined {\n if (request.method !== \"GET\" && request.method !== \"HEAD\") return undefined;\n return new URL(request.url).pathname === \"/healthz\" ? new Response(\"OK\") : undefined;\n}\n\nasync function readAuthenticatedWebhookPayload(\n request: Request,\n maxPayloadBytes: number,\n secret: string,\n verify: (headers: Headers, secret: string, payload: string) => boolean,\n): Promise<string | Response> {\n if (request.method !== \"POST\") return new Response(\"Method Not Allowed\", { status: 405 });\n const payload = await request.text();\n if (new TextEncoder().encode(payload).byteLength > maxPayloadBytes)\n return new Response(\"Payload Too Large\", { status: 413 });\n return verify(request.headers, secret, payload)\n ? payload\n : new Response(\"Unauthorized\", { status: 401 });\n}\n\nexport async function processNextWebhookDelivery(options: {\n store: WebhookDeliveryStore;\n run: (delivery: WebhookDelivery) => Promise<unknown>;\n log?: (message: string) => void;\n}): Promise<boolean> {\n const delivery = options.store.next();\n if (!delivery) return false;\n try {\n await options.run(delivery);\n options.store.complete(delivery.id);\n options.log?.(`webhook delivery completed: ${delivery.id.slice(0, 200)}`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n options.store.fail(delivery.id, message.slice(0, 1_000));\n options.log?.(\n `webhook delivery failed and was retained for retry or inspection: ${delivery.id.slice(0, 200)}`,\n );\n }\n return true;\n}\n\nexport function createWebhookQueueProcessor(options: {\n store: WebhookDeliveryStore;\n run: (delivery: WebhookDelivery) => Promise<unknown>;\n log?: (message: string) => void;\n}) {\n let active: Promise<void> | undefined;\n let stopped = false;\n\n return {\n run(): Promise<void> {\n if (stopped) return Promise.resolve();\n active ??= (async () => {\n try {\n while (await processNextWebhookDelivery(options)) {\n // Deliveries run serially because each checkout mutates the shared workspace.\n }\n } catch {\n options.log?.(\"webhook queue processing failed; the next interval will retry\");\n }\n })().finally(() => {\n active = undefined;\n });\n return active;\n },\n async stop(): Promise<void> {\n stopped = true;\n await active;\n },\n };\n}\n\nexport async function runWebhookServer(options: {\n host: WebhookHost;\n workspace: string;\n configDir: string;\n databasePath: string;\n expectedRepository: string;\n secret: string;\n port: number;\n hostname?: string;\n env?: NodeJS.ProcessEnv;\n}): Promise<void> {\n await mkdir(path.dirname(path.resolve(options.databasePath)), { recursive: true });\n const env = { ...process.env, ...options.env };\n const protocol = createCodeHostWebhookProtocol(options.host);\n const expectedRepository = await protocol.resolveExpectedRepository(\n env,\n options.expectedRepository,\n );\n const store = new SqliteWebhookDeliveryStore(options.databasePath);\n const ingress = createWebhookIngress({\n host: options.host,\n secret: options.secret,\n expectedRepository,\n store,\n });\n const processor = createWebhookQueueProcessor({\n store,\n run: (delivery) => runWebhookDelivery(delivery, { ...options, env }),\n log: console.error,\n });\n const server = Bun.serve({\n hostname: options.hostname ?? \"127.0.0.1\",\n port: options.port,\n maxRequestBodySize: MAX_WEBHOOK_PAYLOAD_BYTES,\n fetch: ingress,\n });\n const interval = setInterval(() => void processor.run(), 250);\n const shutdown = Promise.withResolvers<void>();\n let stopping: Promise<void> | undefined;\n const stop = () => {\n stopping ??= (async () => {\n clearInterval(interval);\n server.stop();\n await processor.stop();\n store.close();\n })();\n void stopping.then(shutdown.resolve, shutdown.reject);\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n try {\n console.error(`pipr webhook server listening on ${server.hostname}:${server.port}`);\n await processor.run();\n await shutdown.promise;\n } finally {\n process.off(\"SIGINT\", stop);\n process.off(\"SIGTERM\", stop);\n }\n}\n\nexport class SqliteWebhookDeliveryStore implements WebhookDeliveryStore {\n private readonly database: Database;\n private readonly maxPendingDeliveries: number;\n private readonly maxRetainedPayloadBytes: number;\n private readonly maxRetainedDeliveries: number;\n\n constructor(\n databasePath: string,\n options: {\n maxPendingDeliveries?: number;\n maxRetainedPayloadBytes?: number;\n maxRetainedDeliveries?: number;\n } = {},\n ) {\n this.database = new Database(databasePath, { create: true, strict: true });\n this.maxPendingDeliveries = options.maxPendingDeliveries ?? 1_000;\n this.maxRetainedPayloadBytes = options.maxRetainedPayloadBytes ?? 32 * 1024 * 1024;\n this.maxRetainedDeliveries = options.maxRetainedDeliveries ?? 10_000;\n this.database.exec(\"PRAGMA journal_mode = WAL\");\n this.database.transaction(() => {\n this.database.exec(`\n CREATE TABLE IF NOT EXISTS webhook_deliveries (\n id TEXT PRIMARY KEY,\n host TEXT NOT NULL,\n payload TEXT,\n event_name TEXT,\n status TEXT NOT NULL,\n attempts INTEGER NOT NULL DEFAULT 0,\n error TEXT,\n created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP\n );\n `);\n const columns = this.database\n .query<{ name: string }, []>(\"PRAGMA table_info(webhook_deliveries)\")\n .all();\n if (!columns.some((column) => column.name === \"event_name\")) {\n this.database.exec(\"ALTER TABLE webhook_deliveries ADD COLUMN event_name TEXT\");\n }\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = CASE WHEN attempts < 3 THEN 'pending' ELSE 'failed' END, payload = CASE WHEN attempts < 3 THEN payload ELSE NULL END, error = CASE WHEN attempts < 3 THEN error ELSE COALESCE(error, 'delivery interrupted during final attempt') END, updated_at = CURRENT_TIMESTAMP WHERE status = 'processing'\",\n )\n .run();\n })();\n }\n\n enqueue(delivery: WebhookDelivery): \"created\" | \"duplicate\" | \"full\" {\n return this.database.transaction(() => {\n const existing = this.database\n .query<{ id: string }, [string]>(\"SELECT id FROM webhook_deliveries WHERE id = ?\")\n .get(delivery.id);\n if (existing) return \"duplicate\";\n const retained = this.database\n .query<{ count: number; bytes: number }, []>(\n \"SELECT COALESCE(SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END), 0) AS count, COALESCE(SUM(length(CAST(payload AS BLOB))), 0) AS bytes FROM webhook_deliveries WHERE payload IS NOT NULL\",\n )\n .get();\n const payloadBytes = Buffer.byteLength(delivery.payload);\n if (\n !retained ||\n retained.count >= this.maxPendingDeliveries ||\n retained.bytes + payloadBytes > this.maxRetainedPayloadBytes\n ) {\n return \"full\";\n }\n this.database\n .query(\n \"INSERT INTO webhook_deliveries (id, host, payload, event_name, status) VALUES (?, ?, ?, ?, 'pending')\",\n )\n .run(delivery.id, delivery.host, delivery.payload, delivery.eventName ?? null);\n return \"created\";\n })();\n }\n\n next(): WebhookDelivery | undefined {\n return this.database.transaction(() => {\n const row = this.database\n .query<{ id: string; host: WebhookHost; payload: string; eventName?: string }, []>(\n \"SELECT id, host, payload, event_name AS eventName FROM webhook_deliveries WHERE status = 'pending' AND attempts < 3 ORDER BY created_at, id LIMIT 1\",\n )\n .get();\n if (!row) return undefined;\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'processing', attempts = attempts + 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(row.id);\n return row.eventName ? row : { id: row.id, host: row.host, payload: row.payload };\n })();\n }\n\n complete(id: string): void {\n this.database.transaction(() => {\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'completed', payload = NULL, error = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(id);\n this.pruneTerminalDeliveries();\n })();\n }\n\n fail(id: string, error: string): void {\n this.database.transaction(() => {\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = CASE WHEN attempts < 3 THEN 'pending' ELSE 'failed' END, payload = CASE WHEN attempts < 3 THEN payload ELSE NULL END, error = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(error, id);\n this.pruneTerminalDeliveries();\n })();\n }\n\n close(): void {\n this.database.close();\n }\n\n private pruneTerminalDeliveries(): void {\n // SQLite uses LIMIT -1 to leave the result unbounded after skipping the retained rows.\n this.database\n .query(\n \"DELETE FROM webhook_deliveries WHERE id IN (SELECT id FROM webhook_deliveries WHERE status IN ('completed', 'failed') ORDER BY updated_at DESC, id DESC LIMIT -1 OFFSET ?)\",\n )\n .run(this.maxRetainedDeliveries);\n }\n}\n\nexport async function runWebhookDelivery(\n delivery: WebhookDelivery,\n options: {\n workspace: string;\n configDir: string;\n env?: NodeJS.ProcessEnv;\n },\n runHostRun: typeof runHostRunCommand = runHostRunCommand,\n): Promise<void> {\n const directory = await mkdtemp(path.join(os.tmpdir(), \"pipr-webhook-\"));\n const eventPath = path.join(directory, \"event.json\");\n const protocol = createCodeHostWebhookProtocol(delivery.host);\n try {\n await Bun.write(eventPath, delivery.payload);\n await runHostRun({\n rootDir: options.workspace,\n configDir: options.configDir,\n host: delivery.host,\n eventPath,\n env: {\n ...process.env,\n ...options.env,\n PIPR_CODE_HOST: delivery.host,\n ...protocol.runtimeEnv?.(delivery.eventName),\n },\n dryRun: false,\n logSink: consoleRuntimeLogSink,\n });\n } finally {\n await rm(directory, { recursive: true, force: true });\n }\n}\n\nconst consoleRuntimeLogSink: RuntimeLogSink = {\n log(record) {\n console.log(JSON.stringify(record));\n },\n async group(_name, run) {\n return await run();\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { n as listOfficialInitRecipes } from "../recipes-w72EpAOi.mjs";
2
+ //#region src/config/official-github-workflow.d.ts
3
+ type RenderOfficialGithubWorkflowOptions = {
4
+ relativeConfigDir?: string;
5
+ recipe?: string;
6
+ minimal?: boolean;
7
+ includeReleasePleaseVersionMarker?: boolean;
8
+ };
9
+ /** Internal shared renderer for `pipr init` and generated recipe docs. */
10
+ declare function renderOfficialGithubWorkflow(options?: RenderOfficialGithubWorkflowOptions): string;
11
+ //#endregion
12
+ export { listOfficialInitRecipes, renderOfficialGithubWorkflow };
13
+ //# sourceMappingURL=docs.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.mts","names":[],"sources":["../../src/config/official-github-workflow.ts"],"mappings":";;KAIY;EACV;EACA;EACA;EACA;;;iBAIc,6BACd,UAAS"}
@@ -0,0 +1,2 @@
1
+ import { n as listOfficialInitRecipes, t as renderOfficialGithubWorkflow } from "../official-github-workflow-BuZs6bOx.mjs";
2
+ export { listOfficialInitRecipes, renderOfficialGithubWorkflow };
@@ -1,4 +1,4 @@
1
- import { C as CodeHostAdapter, N as RepositoryRef, O as ChangeRequestRef, _ as piBuiltinToolNames, b as piThinkingLevels, d as HostRunCommandResult, r as runHostRunCommandWithDependencies, v as piReadOnlyToolNames, w as RepositoryPermission, y as piRequiredCliFlags } from "../commands-YFjB3wx8.mjs";
1
+ import { P as RepositoryRef, T as RepositoryPermission, _ as piBuiltinToolNames, b as piThinkingLevels, d as HostRunCommandResult, k as ChangeRequestRef, r as runHostRunCommandWithDependencies, v as piReadOnlyToolNames, w as CodeHostAdapter, x as SecretRedactor, y as piRequiredCliFlags } from "../commands-DtdTtej_.mjs";
2
2
  import { z } from "zod";
3
3
  //#region src/hosts/github/command.d.ts
4
4
  type GitHubPullRequestDetails = {
@@ -171,5 +171,10 @@ type GitHubHostAdapterOptions = {
171
171
  };
172
172
  declare function createGitHubHostAdapter(options?: GitHubHostAdapterOptions): CodeHostAdapter;
173
173
  //#endregion
174
- export { type GitHubPublicationClient, type HostRunCommandResult, createGitHubHostAdapter, piBuiltinToolNames, piReadOnlyToolNames, piRequiredCliFlags, piThinkingLevels, runHostRunCommandWithDependencies };
174
+ //#region src/shared/secret-redactor.d.ts
175
+ declare function createKnownSecretRedactor(options?: {
176
+ env?: NodeJS.ProcessEnv;
177
+ }): SecretRedactor;
178
+ //#endregion
179
+ export { type GitHubPublicationClient, type HostRunCommandResult, createGitHubHostAdapter, createKnownSecretRedactor, piBuiltinToolNames, piReadOnlyToolNames, piRequiredCliFlags, piThinkingLevels, runHostRunCommandWithDependencies };
175
180
  //# sourceMappingURL=testing.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.mts","names":[],"sources":["../../src/hosts/github/command.ts","../../src/hosts/github/publication-client.ts","../../src/hosts/github/adapter.ts"],"mappings":";;;KAiDY;EACV,YAAY;EACZ,QAAQ;;KAGE;EACV,eAAe;IACb,YAAY;IACZ;MACE,QAAQ;EACZ,wBAAwB;IACtB,YAAY;IACZ;MACE,QAAQ;;;;cChDR,0BAAwB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;cAMxB,2BAAyB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA2BzB,0BAAwB,EAAA;;;;;cAwExB,sBAAoB,EAAA;;;;KAKd,qBAAqB,EAAE,aAAa;KACpC,sBAAsB,EAAE,aAAa;KACrC,qBAAqB,EAAE,aAAa;KACpC,iBAAiB,EAAE,aAAa;KAEhC;EACV,6BAA6B;EAC7B,sBAAsB;IAAW;IAAc;MAA8B;EAC7E,kBAAkB;IAAW;IAAc;MAAwB,QAAQ;EAC3E,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;MACE,QAAQ;EACZ,kBAAkB;IAChB;IACA;MACE,QAAQ;EACZ,oBAAoB;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;MACE;IAAU;;EACd,yBAAyB;IACvB;IACA;IACA;IACA;MACE;IAAU;;EACd,oBAAoB;IAAW;MAAqB;EACpD,eAAe;IACb;IACA;IACA;IACA;MACE,QAAQ;EACZ,eAAe;IACb;IACA;IACA;IACA;IACA;MACE;;;;KCjKM;EACV,MAAM,OAAO;EACb,gBAAgB;EAChB,oBAAoB;;iBAGN,wBAAwB,UAAS,2BAAgC"}
1
+ {"version":3,"file":"testing.d.mts","names":[],"sources":["../../src/hosts/github/command.ts","../../src/hosts/github/publication-client.ts","../../src/hosts/github/adapter.ts","../../src/shared/secret-redactor.ts"],"mappings":";;;KAiDY;EACV,YAAY;EACZ,QAAQ;;KAGE;EACV,eAAe;IACb,YAAY;IACZ;MACE,QAAQ;EACZ,wBAAwB;IACtB,YAAY;IACZ;MACE,QAAQ;;;;cChDR,0BAAwB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;cAMxB,2BAAyB,EAAA,QAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA2BzB,0BAAwB,EAAA;;;;;cAwExB,sBAAoB,EAAA;;;;KAKd,qBAAqB,EAAE,aAAa;KACpC,sBAAsB,EAAE,aAAa;KACrC,qBAAqB,EAAE,aAAa;KACpC,iBAAiB,EAAE,aAAa;KAEhC;EACV,6BAA6B;EAC7B,sBAAsB;IAAW;IAAc;MAA8B;EAC7E,kBAAkB;IAAW;IAAc;MAAwB,QAAQ;EAC3E,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;IACA;MACE;IAAU;;EACd,mBAAmB;IACjB;IACA;MACE,QAAQ;EACZ,kBAAkB;IAChB;IACA;MACE,QAAQ;EACZ,oBAAoB;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;MACE;IAAU;;EACd,yBAAyB;IACvB;IACA;IACA;IACA;MACE;IAAU;;EACd,oBAAoB;IAAW;MAAqB;EACpD,eAAe;IACb;IACA;IACA;IACA;MACE,QAAQ;EACZ,eAAe;IACb;IACA;IACA;IACA;IACA;MACE;;;;KCjKM;EACV,MAAM,OAAO;EACb,gBAAgB;EAChB,oBAAoB;;iBAGN,wBAAwB,UAAS,2BAAgC;;;iBCvBjE,0BAA0B;EAAY,MAAM,OAAO;IAAA"}
@@ -1,2 +1,2 @@
1
- import { b as piRequiredCliFlags, c as createGitHubHostAdapter, r as runHostRunCommandWithDependencies, v as piBuiltinToolNames, x as piThinkingLevels, y as piReadOnlyToolNames } from "../commands-ZZkXwqEn.mjs";
2
- export { createGitHubHostAdapter, piBuiltinToolNames, piReadOnlyToolNames, piRequiredCliFlags, piThinkingLevels, runHostRunCommandWithDependencies };
1
+ import { _ as piReadOnlyToolNames, c as createGitHubHostAdapter, g as piBuiltinToolNames, r as runHostRunCommandWithDependencies, u as createKnownSecretRedactor, v as piRequiredCliFlags, y as piThinkingLevels } from "../commands-EZV-Icbs.mjs";
2
+ export { createGitHubHostAdapter, createKnownSecretRedactor, piBuiltinToolNames, piReadOnlyToolNames, piRequiredCliFlags, piThinkingLevels, runHostRunCommandWithDependencies };