@usepipr/runtime 0.4.3 → 0.5.0
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/LICENSE +21 -0
- package/README.md +8 -5
- package/dist/{commands-DA0Ij4Di.d.mts → commands-CF59DZXx.d.mts} +2 -2
- package/dist/{commands-DA0Ij4Di.d.mts.map → commands-CF59DZXx.d.mts.map} +1 -1
- package/dist/{commands-B9qNW4pk.mjs → commands-DgZU7tf7.mjs} +474 -334
- package/dist/commands-DgZU7tf7.mjs.map +1 -0
- package/dist/index.d.mts +16 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +117 -15
- package/dist/index.mjs.map +1 -1
- package/dist/internal/action-result.d.mts +4 -2
- package/dist/internal/action-result.d.mts.map +1 -1
- package/dist/internal/action-result.mjs +28 -12
- package/dist/internal/action-result.mjs.map +1 -1
- package/dist/internal/docs.mjs +1 -1
- package/dist/internal/pipr-result.d.mts +24 -0
- package/dist/internal/pipr-result.d.mts.map +1 -0
- package/dist/internal/pipr-result.mjs +126 -0
- package/dist/internal/pipr-result.mjs.map +1 -0
- package/dist/internal/testing.d.mts +11 -11
- package/dist/internal/testing.d.mts.map +1 -1
- package/dist/internal/testing.mjs +1 -1
- package/dist/main-comment-envelope-DFirHYhW.mjs +69 -0
- package/dist/main-comment-envelope-DFirHYhW.mjs.map +1 -0
- package/dist/{official-github-workflow-Bjlu-FL3.mjs → official-github-workflow-DNzV5Z70.mjs} +183 -33
- package/dist/official-github-workflow-DNzV5Z70.mjs.map +1 -0
- package/dist/{types-BAis_Lwm.d.mts → types-Dn1U3MDG.d.mts} +30 -18
- package/dist/types-Dn1U3MDG.d.mts.map +1 -0
- package/package.json +16 -8
- package/dist/commands-B9qNW4pk.mjs.map +0 -1
- package/dist/official-github-workflow-Bjlu-FL3.mjs.map +0 -1
- package/dist/types-BAis_Lwm.d.mts.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import { a as runInspectCommand, c as OfficialInitAdapter, i as runInitCommand, l as supportedOfficialInitAdapters, n as runHostRunCommand, o as runLocalReviewCommand, s as runValidateCommand, t as runDryRunCommand } from "./commands-
|
|
1
|
+
import { a as runInspectCommand, c as OfficialInitAdapter, i as runInitCommand, l as supportedOfficialInitAdapters, n as runHostRunCommand, o as runLocalReviewCommand, s as runValidateCommand, t as runDryRunCommand } from "./commands-CF59DZXx.mjs";
|
|
2
2
|
import { a as OfficialInitRecipeFile, i as OfficialInitRecipe, n as listOfficialInitRecipes, r as supportedOfficialInitRecipes, t as OfficialInitRecipeId } from "./recipes-w72EpAOi.mjs";
|
|
3
|
-
import { A as RuntimeSettings, C as ChangeRequestEventContext, D as PlatformInfo, E as PiprConfig, O as ProviderConfig, S as PublicationResult, T as DiffManifest, _ as RuntimeLogRecord, a as HostRunCommandResult, c as LocalReviewCommandOptions, i as HostRunCommandOptions, k as RepositoryRef, l as LocalReviewCommandResult, n as DryRunCommandResult, o as InitCommandOptions, s as InspectCommandResult, t as DryRunCommandOptions, u as RuntimeCommandOptions, v as RuntimeLogSink, w as ChangeRequestRef, x as PublicationError } from "./types-
|
|
3
|
+
import { A as RuntimeSettings, C as ChangeRequestEventContext, D as PlatformInfo, E as PiprConfig, O as ProviderConfig, S as PublicationResult, T as DiffManifest, _ as RuntimeLogRecord, a as HostRunCommandResult, c as LocalReviewCommandOptions, i as HostRunCommandOptions, k as RepositoryRef, l as LocalReviewCommandResult, n as DryRunCommandResult, o as InitCommandOptions, s as InspectCommandResult, t as DryRunCommandOptions, u as RuntimeCommandOptions, v as RuntimeLogSink, w as ChangeRequestRef, x as PublicationError } from "./types-Dn1U3MDG.mjs";
|
|
4
|
+
import { PiprResult } from "@usepipr/sdk";
|
|
4
5
|
//#region src/hosts/webhook.d.ts
|
|
5
6
|
type WebhookHost = "gitlab" | "azure-devops" | "bitbucket";
|
|
6
7
|
//#endregion
|
|
7
8
|
//#region src/host-run/webhook-server.d.ts
|
|
9
|
+
type WebhookDeliveryStatus = {
|
|
10
|
+
id: string;
|
|
11
|
+
host: string;
|
|
12
|
+
status: string;
|
|
13
|
+
attempts: number;
|
|
14
|
+
resultKind?: string;
|
|
15
|
+
runId?: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
result?: PiprResult;
|
|
18
|
+
resultOmittedReason?: "size-limit" | "retention" | "invalid";
|
|
19
|
+
};
|
|
20
|
+
declare function readWebhookDeliveryStatus(databasePath: string, limit?: number): WebhookDeliveryStatus[];
|
|
8
21
|
declare function runWebhookServer(options: {
|
|
9
22
|
host: WebhookHost;
|
|
10
23
|
workspace: string;
|
|
@@ -17,5 +30,5 @@ declare function runWebhookServer(options: {
|
|
|
17
30
|
env?: NodeJS.ProcessEnv;
|
|
18
31
|
}): Promise<void>;
|
|
19
32
|
//#endregion
|
|
20
|
-
export { type ChangeRequestEventContext, type ChangeRequestRef, type DiffManifest, type DryRunCommandOptions, type DryRunCommandResult, type HostRunCommandOptions, type HostRunCommandResult, type InitCommandOptions, type InspectCommandResult, type LocalReviewCommandOptions, type LocalReviewCommandResult, type OfficialInitAdapter, type OfficialInitRecipe, type OfficialInitRecipeFile, type OfficialInitRecipeId, type PiprConfig, type PlatformInfo, type ProviderConfig, PublicationError, type PublicationResult, type RepositoryRef, type RuntimeCommandOptions, type RuntimeLogRecord, type RuntimeLogSink, type RuntimeSettings, type WebhookHost, listOfficialInitRecipes, runDryRunCommand, runHostRunCommand, runInitCommand, runInspectCommand, runLocalReviewCommand, runValidateCommand, runWebhookServer, supportedOfficialInitAdapters, supportedOfficialInitRecipes };
|
|
33
|
+
export { type ChangeRequestEventContext, type ChangeRequestRef, type DiffManifest, type DryRunCommandOptions, type DryRunCommandResult, type HostRunCommandOptions, type HostRunCommandResult, type InitCommandOptions, type InspectCommandResult, type LocalReviewCommandOptions, type LocalReviewCommandResult, type OfficialInitAdapter, type OfficialInitRecipe, type OfficialInitRecipeFile, type OfficialInitRecipeId, type PiprConfig, type PlatformInfo, type ProviderConfig, PublicationError, type PublicationResult, type RepositoryRef, type RuntimeCommandOptions, type RuntimeLogRecord, type RuntimeLogSink, type RuntimeSettings, type WebhookDeliveryStatus, type WebhookHost, listOfficialInitRecipes, readWebhookDeliveryStatus, runDryRunCommand, runHostRunCommand, runInitCommand, runInspectCommand, runLocalReviewCommand, runValidateCommand, runWebhookServer, supportedOfficialInitAdapters, supportedOfficialInitRecipes };
|
|
21
34
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/hosts/webhook.ts","../src/host-run/webhook-server.ts"],"mappings":";;;;;KAIY;;;KC0BA;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT;;iBAGc,0BACd,sBACA,iBACC;iBA4LmB,iBAAiB;EACrC,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,OAAO;IACX"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { a as runInspectCommand, c as createGitLabClient, d as
|
|
2
|
-
import { n as listOfficialInitRecipes, o as supportedOfficialInitRecipes } from "./official-github-workflow-
|
|
1
|
+
import { a as runInspectCommand, c as createGitLabClient, d as createAzureDevOpsClient, f as azureOrganizationFromUrl, h as supportedOfficialInitAdapters, i as runInitCommand, n as runHostRunCommand, o as runLocalReviewCommand, p as PublicationError, s as runValidateCommand, t as runDryRunCommand, u as createBitbucketClient } from "./commands-DgZU7tf7.mjs";
|
|
2
|
+
import { n as listOfficialInitRecipes, o as supportedOfficialInitRecipes } from "./official-github-workflow-DNzV5Z70.mjs";
|
|
3
|
+
import { toPiprErrorResult, toPiprResult } from "./internal/pipr-result.mjs";
|
|
3
4
|
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { z } from "zod";
|
|
7
|
+
import { parsePiprResult } from "@usepipr/sdk";
|
|
6
8
|
import os from "node:os";
|
|
9
|
+
import { chmodSync, existsSync } from "node:fs";
|
|
7
10
|
import { Database } from "bun:sqlite";
|
|
8
11
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
9
12
|
//#region src/hosts/webhook-shared.ts
|
|
@@ -174,6 +177,51 @@ function createCodeHostWebhookProtocol(host) {
|
|
|
174
177
|
//#endregion
|
|
175
178
|
//#region src/host-run/webhook-server.ts
|
|
176
179
|
const MAX_WEBHOOK_PAYLOAD_BYTES = 2 * 1024 * 1024;
|
|
180
|
+
function readWebhookDeliveryStatus(databasePath, limit = 20) {
|
|
181
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 200) throw new Error("--limit must be an integer from 1 to 200");
|
|
182
|
+
if (!existsSync(databasePath)) throw new Error(`Webhook database not found: ${databasePath}`);
|
|
183
|
+
const database = new Database(databasePath, {
|
|
184
|
+
readonly: true,
|
|
185
|
+
strict: true
|
|
186
|
+
});
|
|
187
|
+
try {
|
|
188
|
+
const columns = new Set(database.query("PRAGMA table_info(webhook_deliveries)").all().map((column) => column.name));
|
|
189
|
+
if (columns.size === 0) throw new Error("Webhook database is missing webhook_deliveries");
|
|
190
|
+
const field = (name, alias) => columns.has(name) ? `${name} AS ${alias}` : `NULL AS ${alias}`;
|
|
191
|
+
return database.query(`SELECT id, host, status, attempts, ${field("result_kind", "resultKind")}, ${field("run_id", "runId")}, ${field("result_json", "resultJson")}, ${field("result_omitted_reason", "omittedReason")}, updated_at AS updatedAt FROM webhook_deliveries ORDER BY updated_at DESC, id DESC LIMIT ?`).all(limit).map((row) => deliveryStatus(row));
|
|
192
|
+
} finally {
|
|
193
|
+
database.close();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function deliveryStatus(row) {
|
|
197
|
+
const common = {
|
|
198
|
+
id: row.id,
|
|
199
|
+
host: row.host,
|
|
200
|
+
status: row.status,
|
|
201
|
+
attempts: row.attempts,
|
|
202
|
+
...row.resultKind ? { resultKind: row.resultKind } : {},
|
|
203
|
+
...row.runId ? { runId: row.runId } : {},
|
|
204
|
+
updatedAt: row.updatedAt
|
|
205
|
+
};
|
|
206
|
+
if (!row.resultJson) {
|
|
207
|
+
const reason = row.omittedReason;
|
|
208
|
+
return reason === "size-limit" || reason === "retention" ? {
|
|
209
|
+
...common,
|
|
210
|
+
resultOmittedReason: reason
|
|
211
|
+
} : common;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
return {
|
|
215
|
+
...common,
|
|
216
|
+
result: parsePiprResult(JSON.parse(row.resultJson))
|
|
217
|
+
};
|
|
218
|
+
} catch {
|
|
219
|
+
return {
|
|
220
|
+
...common,
|
|
221
|
+
resultOmittedReason: "invalid"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
177
225
|
function createWebhookIngress(options) {
|
|
178
226
|
const maxPayloadBytes = options.maxPayloadBytes ?? MAX_WEBHOOK_PAYLOAD_BYTES;
|
|
179
227
|
const protocol = createCodeHostWebhookProtocol(options.host);
|
|
@@ -213,12 +261,14 @@ async function processNextWebhookDelivery(options) {
|
|
|
213
261
|
const delivery = options.store.next();
|
|
214
262
|
if (!delivery) return false;
|
|
215
263
|
try {
|
|
216
|
-
await options.run(delivery);
|
|
217
|
-
options.store.complete(delivery.id
|
|
264
|
+
const result = await options.run(delivery);
|
|
265
|
+
options.store.complete(delivery.id, toPiprResult({
|
|
266
|
+
source: "host",
|
|
267
|
+
result
|
|
268
|
+
}));
|
|
218
269
|
options.log?.(`webhook delivery completed: ${delivery.id.slice(0, 200)}`);
|
|
219
270
|
} catch (error) {
|
|
220
|
-
|
|
221
|
-
options.store.fail(delivery.id, message.slice(0, 1e3));
|
|
271
|
+
options.store.fail(delivery.id, toPiprErrorResult(error));
|
|
222
272
|
options.log?.(`webhook delivery failed and was retained for retry or inspection: ${delivery.id.slice(0, 200)}`);
|
|
223
273
|
}
|
|
224
274
|
return true;
|
|
@@ -302,6 +352,8 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
302
352
|
maxPendingDeliveries;
|
|
303
353
|
maxRetainedPayloadBytes;
|
|
304
354
|
maxRetainedDeliveries;
|
|
355
|
+
maxResultBytes;
|
|
356
|
+
maxRetainedResultBytes;
|
|
305
357
|
constructor(databasePath, options = {}) {
|
|
306
358
|
this.database = new Database(databasePath, {
|
|
307
359
|
create: true,
|
|
@@ -310,7 +362,11 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
310
362
|
this.maxPendingDeliveries = options.maxPendingDeliveries ?? 1e3;
|
|
311
363
|
this.maxRetainedPayloadBytes = options.maxRetainedPayloadBytes ?? 32 * 1024 * 1024;
|
|
312
364
|
this.maxRetainedDeliveries = options.maxRetainedDeliveries ?? 1e4;
|
|
365
|
+
this.maxResultBytes = options.maxResultBytes ?? 512 * 1024;
|
|
366
|
+
this.maxRetainedResultBytes = options.maxRetainedResultBytes ?? 32 * 1024 * 1024;
|
|
367
|
+
secureWebhookDatabaseFiles(databasePath);
|
|
313
368
|
this.database.exec("PRAGMA journal_mode = WAL");
|
|
369
|
+
secureWebhookDatabaseFiles(databasePath);
|
|
314
370
|
this.database.transaction(() => {
|
|
315
371
|
this.database.exec(`
|
|
316
372
|
CREATE TABLE IF NOT EXISTS webhook_deliveries (
|
|
@@ -321,12 +377,27 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
321
377
|
status TEXT NOT NULL,
|
|
322
378
|
attempts INTEGER NOT NULL DEFAULT 0,
|
|
323
379
|
error TEXT,
|
|
380
|
+
run_id TEXT,
|
|
381
|
+
result_kind TEXT,
|
|
382
|
+
result_json TEXT,
|
|
383
|
+
result_omitted_reason TEXT,
|
|
324
384
|
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
325
385
|
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
326
386
|
);
|
|
327
387
|
`);
|
|
328
|
-
|
|
329
|
-
|
|
388
|
+
const columns = this.database.query("PRAGMA table_info(webhook_deliveries)").all();
|
|
389
|
+
if (!columns.some((column) => column.name === "event_name")) this.database.exec("ALTER TABLE webhook_deliveries ADD COLUMN event_name TEXT");
|
|
390
|
+
for (const column of [
|
|
391
|
+
"run_id",
|
|
392
|
+
"result_kind",
|
|
393
|
+
"result_json",
|
|
394
|
+
"result_omitted_reason"
|
|
395
|
+
]) if (!columns.some((candidate) => candidate.name === column)) this.database.exec(`ALTER TABLE webhook_deliveries ADD COLUMN ${column} TEXT`);
|
|
396
|
+
this.database.query("UPDATE webhook_deliveries SET status = 'pending', updated_at = CURRENT_TIMESTAMP WHERE status = 'processing' AND attempts < 3").run();
|
|
397
|
+
const interrupted = toPiprErrorResult(void 0);
|
|
398
|
+
const stored = this.storedResult(interrupted);
|
|
399
|
+
this.database.query("UPDATE webhook_deliveries SET status = 'failed', payload = NULL, error = ?, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE status = 'processing' AND attempts >= 3").run(interrupted.message, stored.runId, interrupted.kind, stored.json, stored.omittedReason);
|
|
400
|
+
this.enforceResultRetention();
|
|
330
401
|
})();
|
|
331
402
|
}
|
|
332
403
|
enqueue(delivery) {
|
|
@@ -343,7 +414,7 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
343
414
|
return this.database.transaction(() => {
|
|
344
415
|
const row = this.database.query("SELECT id, host, payload, event_name AS eventName FROM webhook_deliveries WHERE status = 'pending' AND attempts < 3 ORDER BY created_at, id LIMIT 1").get();
|
|
345
416
|
if (!row) return void 0;
|
|
346
|
-
this.database.query("UPDATE webhook_deliveries SET status = 'processing', attempts = attempts + 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(row.id);
|
|
417
|
+
this.database.query("UPDATE webhook_deliveries SET status = 'processing', attempts = attempts + 1, run_id = NULL, result_kind = NULL, result_json = NULL, result_omitted_reason = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(row.id);
|
|
347
418
|
return row.eventName ? row : {
|
|
348
419
|
id: row.id,
|
|
349
420
|
host: row.host,
|
|
@@ -351,15 +422,20 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
351
422
|
};
|
|
352
423
|
})();
|
|
353
424
|
}
|
|
354
|
-
complete(id) {
|
|
425
|
+
complete(id, result) {
|
|
355
426
|
this.database.transaction(() => {
|
|
356
|
-
|
|
427
|
+
const stored = this.storedResult(result);
|
|
428
|
+
this.database.query("UPDATE webhook_deliveries SET status = 'completed', payload = NULL, error = NULL, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(stored.runId, result.kind, stored.json, stored.omittedReason, id);
|
|
429
|
+
this.enforceResultRetention();
|
|
357
430
|
this.pruneTerminalDeliveries();
|
|
358
431
|
})();
|
|
359
432
|
}
|
|
360
|
-
fail(id,
|
|
433
|
+
fail(id, result) {
|
|
361
434
|
this.database.transaction(() => {
|
|
362
|
-
|
|
435
|
+
const stored = this.storedResult(result);
|
|
436
|
+
const message = "message" in result ? result.message : "Pipr failed; see logs for details.";
|
|
437
|
+
this.database.query("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 = ?, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(message, stored.runId, result.kind, stored.json, stored.omittedReason, id);
|
|
438
|
+
this.enforceResultRetention();
|
|
363
439
|
this.pruneTerminalDeliveries();
|
|
364
440
|
})();
|
|
365
441
|
}
|
|
@@ -369,14 +445,40 @@ var SqliteWebhookDeliveryStore = class {
|
|
|
369
445
|
pruneTerminalDeliveries() {
|
|
370
446
|
this.database.query("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 ?)").run(this.maxRetainedDeliveries);
|
|
371
447
|
}
|
|
448
|
+
storedResult(result) {
|
|
449
|
+
const json = JSON.stringify(result);
|
|
450
|
+
return {
|
|
451
|
+
runId: "run" in result ? result.run.id : null,
|
|
452
|
+
json: Buffer.byteLength(json) <= this.maxResultBytes ? json : null,
|
|
453
|
+
omittedReason: Buffer.byteLength(json) <= this.maxResultBytes ? null : "size-limit"
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
enforceResultRetention() {
|
|
457
|
+
let retained = this.database.query("SELECT COALESCE(SUM(length(CAST(result_json AS BLOB))), 0) AS bytes FROM webhook_deliveries").get()?.bytes ?? 0;
|
|
458
|
+
if (retained <= this.maxRetainedResultBytes) return;
|
|
459
|
+
const rows = this.database.query("SELECT id, length(CAST(result_json AS BLOB)) AS bytes FROM webhook_deliveries WHERE result_json IS NOT NULL ORDER BY updated_at, id").all();
|
|
460
|
+
for (const row of rows) {
|
|
461
|
+
if (retained <= this.maxRetainedResultBytes) break;
|
|
462
|
+
this.database.query("UPDATE webhook_deliveries SET result_json = NULL, result_omitted_reason = 'retention' WHERE id = ?").run(row.id);
|
|
463
|
+
retained -= row.bytes;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
372
466
|
};
|
|
467
|
+
function secureWebhookDatabaseFiles(databasePath) {
|
|
468
|
+
if (databasePath === ":memory:") return;
|
|
469
|
+
for (const candidate of [
|
|
470
|
+
databasePath,
|
|
471
|
+
`${databasePath}-wal`,
|
|
472
|
+
`${databasePath}-shm`
|
|
473
|
+
]) if (existsSync(candidate)) chmodSync(candidate, 384);
|
|
474
|
+
}
|
|
373
475
|
async function runWebhookDelivery(delivery, options, runHostRun = runHostRunCommand) {
|
|
374
476
|
const directory = await mkdtemp(path.join(os.tmpdir(), "pipr-webhook-"));
|
|
375
477
|
const eventPath = path.join(directory, "event.json");
|
|
376
478
|
const protocol = createCodeHostWebhookProtocol(delivery.host);
|
|
377
479
|
try {
|
|
378
480
|
await Bun.write(eventPath, delivery.payload);
|
|
379
|
-
await runHostRun({
|
|
481
|
+
return await runHostRun({
|
|
380
482
|
rootDir: options.workspace,
|
|
381
483
|
configDir: options.configDir,
|
|
382
484
|
host: delivery.host,
|
|
@@ -406,6 +508,6 @@ const consoleRuntimeLogSink = {
|
|
|
406
508
|
}
|
|
407
509
|
};
|
|
408
510
|
//#endregion
|
|
409
|
-
export { PublicationError, listOfficialInitRecipes, runDryRunCommand, runHostRunCommand, runInitCommand, runInspectCommand, runLocalReviewCommand, runValidateCommand, runWebhookServer, supportedOfficialInitAdapters, supportedOfficialInitRecipes };
|
|
511
|
+
export { PublicationError, listOfficialInitRecipes, readWebhookDeliveryStatus, runDryRunCommand, runHostRunCommand, runInitCommand, runInspectCommand, runLocalReviewCommand, runValidateCommand, runWebhookServer, supportedOfficialInitAdapters, supportedOfficialInitRecipes };
|
|
410
512
|
|
|
411
513
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 { 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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"}
|
|
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 { chmodSync, existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { type PiprResult, parsePiprResult } from \"@usepipr/sdk\";\nimport { createCodeHostWebhookProtocol, type WebhookHost } from \"../hosts/webhook.js\";\nimport { toPiprErrorResult, toPiprResult } from \"../internal/pipr-result.js\";\nimport type { RuntimeLogSink } from \"../shared/logging.js\";\nimport { runHostRunCommand } from \"./commands.js\";\nimport type { HostRunCommandResult } from \"./types.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, result: PiprResult): void;\n fail(id: string, result: PiprResult): void;\n};\n\nexport type WebhookDeliveryStatus = {\n id: string;\n host: string;\n status: string;\n attempts: number;\n resultKind?: string;\n runId?: string;\n updatedAt: string;\n result?: PiprResult;\n resultOmittedReason?: \"size-limit\" | \"retention\" | \"invalid\";\n};\n\nexport function readWebhookDeliveryStatus(\n databasePath: string,\n limit = 20,\n): WebhookDeliveryStatus[] {\n if (!Number.isInteger(limit) || limit < 1 || limit > 200) {\n throw new Error(\"--limit must be an integer from 1 to 200\");\n }\n if (!existsSync(databasePath)) {\n throw new Error(`Webhook database not found: ${databasePath}`);\n }\n const database = new Database(databasePath, { readonly: true, strict: true });\n try {\n const columns = new Set(\n database\n .query<{ name: string }, []>(\"PRAGMA table_info(webhook_deliveries)\")\n .all()\n .map((column) => column.name),\n );\n if (columns.size === 0) throw new Error(\"Webhook database is missing webhook_deliveries\");\n const field = (name: string, alias: string) =>\n columns.has(name) ? `${name} AS ${alias}` : `NULL AS ${alias}`;\n const rows = database\n .query<\n {\n id: string;\n host: string;\n status: string;\n attempts: number;\n resultKind: string | null;\n runId: string | null;\n resultJson: string | null;\n omittedReason: string | null;\n updatedAt: string;\n },\n [number]\n >(\n `SELECT id, host, status, attempts, ${field(\"result_kind\", \"resultKind\")}, ${field(\"run_id\", \"runId\")}, ${field(\"result_json\", \"resultJson\")}, ${field(\"result_omitted_reason\", \"omittedReason\")}, updated_at AS updatedAt FROM webhook_deliveries ORDER BY updated_at DESC, id DESC LIMIT ?`,\n )\n .all(limit);\n return rows.map((row) => deliveryStatus(row));\n } finally {\n database.close();\n }\n}\n\nfunction deliveryStatus(row: {\n id: string;\n host: string;\n status: string;\n attempts: number;\n resultKind: string | null;\n runId: string | null;\n resultJson: string | null;\n omittedReason: string | null;\n updatedAt: string;\n}): WebhookDeliveryStatus {\n const common = {\n id: row.id,\n host: row.host,\n status: row.status,\n attempts: row.attempts,\n ...(row.resultKind ? { resultKind: row.resultKind } : {}),\n ...(row.runId ? { runId: row.runId } : {}),\n updatedAt: row.updatedAt,\n };\n if (!row.resultJson) {\n const reason = row.omittedReason;\n return reason === \"size-limit\" || reason === \"retention\"\n ? { ...common, resultOmittedReason: reason }\n : common;\n }\n try {\n return { ...common, result: parsePiprResult(JSON.parse(row.resultJson)) };\n } catch {\n return { ...common, resultOmittedReason: \"invalid\" };\n }\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<HostRunCommandResult>;\n log?: (message: string) => void;\n}): Promise<boolean> {\n const delivery = options.store.next();\n if (!delivery) return false;\n try {\n const result = await options.run(delivery);\n options.store.complete(delivery.id, toPiprResult({ source: \"host\", result }));\n options.log?.(`webhook delivery completed: ${delivery.id.slice(0, 200)}`);\n } catch (error) {\n options.store.fail(delivery.id, toPiprErrorResult(error));\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<HostRunCommandResult>;\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 private readonly maxResultBytes: number;\n private readonly maxRetainedResultBytes: number;\n\n constructor(\n databasePath: string,\n options: {\n maxPendingDeliveries?: number;\n maxRetainedPayloadBytes?: number;\n maxRetainedDeliveries?: number;\n maxResultBytes?: number;\n maxRetainedResultBytes?: 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.maxResultBytes = options.maxResultBytes ?? 512 * 1024;\n this.maxRetainedResultBytes = options.maxRetainedResultBytes ?? 32 * 1024 * 1024;\n secureWebhookDatabaseFiles(databasePath);\n this.database.exec(\"PRAGMA journal_mode = WAL\");\n secureWebhookDatabaseFiles(databasePath);\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 run_id TEXT,\n result_kind TEXT,\n result_json TEXT,\n result_omitted_reason 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 for (const column of [\"run_id\", \"result_kind\", \"result_json\", \"result_omitted_reason\"]) {\n if (!columns.some((candidate) => candidate.name === column)) {\n this.database.exec(`ALTER TABLE webhook_deliveries ADD COLUMN ${column} TEXT`);\n }\n }\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'pending', updated_at = CURRENT_TIMESTAMP WHERE status = 'processing' AND attempts < 3\",\n )\n .run();\n const interrupted = toPiprErrorResult(undefined);\n const stored = this.storedResult(interrupted);\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'failed', payload = NULL, error = ?, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE status = 'processing' AND attempts >= 3\",\n )\n .run(\n interrupted.message,\n stored.runId,\n interrupted.kind,\n stored.json,\n stored.omittedReason,\n );\n this.enforceResultRetention();\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, run_id = NULL, result_kind = NULL, result_json = NULL, result_omitted_reason = NULL, 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, result: PiprResult): void {\n this.database.transaction(() => {\n const stored = this.storedResult(result);\n this.database\n .query(\n \"UPDATE webhook_deliveries SET status = 'completed', payload = NULL, error = NULL, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(stored.runId, result.kind, stored.json, stored.omittedReason, id);\n this.enforceResultRetention();\n this.pruneTerminalDeliveries();\n })();\n }\n\n fail(id: string, result: PiprResult): void {\n this.database.transaction(() => {\n const stored = this.storedResult(result);\n const message = \"message\" in result ? result.message : \"Pipr failed; see logs for details.\";\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 = ?, run_id = ?, result_kind = ?, result_json = ?, result_omitted_reason = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?\",\n )\n .run(message, stored.runId, result.kind, stored.json, stored.omittedReason, id);\n this.enforceResultRetention();\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 private storedResult(result: PiprResult): {\n runId: string | null;\n json: string | null;\n omittedReason: string | null;\n } {\n const json = JSON.stringify(result);\n return {\n runId: \"run\" in result ? result.run.id : null,\n json: Buffer.byteLength(json) <= this.maxResultBytes ? json : null,\n omittedReason: Buffer.byteLength(json) <= this.maxResultBytes ? null : \"size-limit\",\n };\n }\n\n private enforceResultRetention(): void {\n let retained =\n this.database\n .query<{ bytes: number }, []>(\n \"SELECT COALESCE(SUM(length(CAST(result_json AS BLOB))), 0) AS bytes FROM webhook_deliveries\",\n )\n .get()?.bytes ?? 0;\n if (retained <= this.maxRetainedResultBytes) return;\n const rows = this.database\n .query<{ id: string; bytes: number }, []>(\n \"SELECT id, length(CAST(result_json AS BLOB)) AS bytes FROM webhook_deliveries WHERE result_json IS NOT NULL ORDER BY updated_at, id\",\n )\n .all();\n for (const row of rows) {\n if (retained <= this.maxRetainedResultBytes) break;\n this.database\n .query(\n \"UPDATE webhook_deliveries SET result_json = NULL, result_omitted_reason = 'retention' WHERE id = ?\",\n )\n .run(row.id);\n retained -= row.bytes;\n }\n }\n}\n\nfunction secureWebhookDatabaseFiles(databasePath: string): void {\n if (databasePath === \":memory:\") return;\n for (const candidate of [databasePath, `${databasePath}-wal`, `${databasePath}-shm`]) {\n if (existsSync(candidate)) chmodSync(candidate, 0o600);\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<HostRunCommandResult> {\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 return 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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as HostRunCommandResult } from "../types-
|
|
1
|
+
import { a as HostRunCommandResult, x as PublicationError } from "../types-Dn1U3MDG.mjs";
|
|
2
2
|
//#region src/internal/action-result.d.ts
|
|
3
3
|
type GitHubActionResultPresenter = {
|
|
4
4
|
info(message: string): void | Promise<void>;
|
|
@@ -6,6 +6,8 @@ type GitHubActionResultPresenter = {
|
|
|
6
6
|
setOutput(name: string, value: string): void | Promise<void>;
|
|
7
7
|
};
|
|
8
8
|
declare function presentGitHubActionResult(result: HostRunCommandResult, presenter: GitHubActionResultPresenter): Promise<void>;
|
|
9
|
+
declare function presentGitHubActionPublicationError(error: PublicationError, presenter: GitHubActionResultPresenter): Promise<void>;
|
|
10
|
+
declare function presentGitHubActionError(presenter: GitHubActionResultPresenter): Promise<void>;
|
|
9
11
|
//#endregion
|
|
10
|
-
export { GitHubActionResultPresenter, presentGitHubActionResult };
|
|
12
|
+
export { GitHubActionResultPresenter, presentGitHubActionError, presentGitHubActionPublicationError, presentGitHubActionResult };
|
|
11
13
|
//# sourceMappingURL=action-result.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-result.d.mts","names":[],"sources":["../../src/internal/action-result.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"action-result.d.mts","names":[],"sources":["../../src/internal/action-result.ts"],"mappings":";;KAIY;EACV,KAAK,yBAAyB;EAC9B,QAAQ,yBAAyB;EACjC,UAAU,cAAc,uBAAuB;;iBAG3B,0BACpB,QAAQ,sBACR,WAAW,8BACV;iBA+DmB,oCACpB,OAAO,kBACP,WAAW,8BACV;iBAYmB,yBACpB,WAAW,8BACV"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { stripPiprMainCommentMarkers, toPiprErrorResult, toPiprResult } from "./pipr-result.mjs";
|
|
1
2
|
//#region src/internal/action-result.ts
|
|
2
3
|
async function presentGitHubActionResult(result, presenter) {
|
|
3
4
|
if (result.kind === "ignored") {
|
|
4
5
|
await presenter.info(`pipr ignored event: ${result.reason}`);
|
|
6
|
+
await setResultOutput(result, presenter);
|
|
5
7
|
return;
|
|
6
8
|
}
|
|
7
9
|
await presenter.info(`pipr loaded change #${result.event.change.number} for ${result.event.repository.slug}`);
|
|
@@ -9,38 +11,52 @@ async function presentGitHubActionResult(result, presenter) {
|
|
|
9
11
|
switch (result.kind) {
|
|
10
12
|
case "dry-run":
|
|
11
13
|
await presenter.info("PIPR_DRY_RUN=1; stopping before review runtime, model, or GitHub publishing calls");
|
|
12
|
-
|
|
14
|
+
break;
|
|
13
15
|
case "command-help":
|
|
14
16
|
await presenter.info(`pipr command help: ${result.reason}`);
|
|
15
17
|
await presenter.setOutput("main-comment", result.body);
|
|
16
|
-
|
|
18
|
+
break;
|
|
17
19
|
case "command-response":
|
|
18
20
|
await presenter.info(`pipr command '${result.command}' published response comment (${result.publication.action})`);
|
|
19
21
|
await presenter.setOutput("main-comment", result.response.body);
|
|
20
|
-
|
|
21
|
-
return;
|
|
22
|
+
break;
|
|
22
23
|
case "verifier":
|
|
23
24
|
await presenter.info(`pipr verifier processed review comment reply with ${result.errors.length} publication error(s)`);
|
|
24
25
|
await warnInlineResolutionErrors(result.errors, presenter);
|
|
25
|
-
|
|
26
|
-
return;
|
|
26
|
+
break;
|
|
27
27
|
case "review":
|
|
28
28
|
await presenter.info(`pipr review produced ${result.review.validated.validFindings.length} valid inline finding(s), ${result.review.validated.droppedFindings.length} dropped finding(s)`);
|
|
29
29
|
await presenter.info(`pipr published main comment (${result.publication.mainComment.action}) and ${result.publication.inlineComments.posted} inline comment(s); ${result.publication.inlineComments.skipped} skipped`);
|
|
30
30
|
await warnInlineResolutionErrors(result.publication.metadata.inlineResolutionErrors, presenter);
|
|
31
31
|
if (result.review.repairAttempted) await presenter.info("pipr repaired reviewer JSON once before validation");
|
|
32
|
-
await presenter.setOutput("main-comment", result.review.mainComment);
|
|
33
|
-
|
|
34
|
-
await presenter.setOutput("dropped-findings", JSON.stringify(result.review.validated.droppedFindings));
|
|
35
|
-
await presenter.setOutput("publication", JSON.stringify(result.publication));
|
|
36
|
-
return;
|
|
32
|
+
await presenter.setOutput("main-comment", stripPiprMainCommentMarkers(result.review.mainComment));
|
|
33
|
+
break;
|
|
37
34
|
default:
|
|
38
35
|
}
|
|
36
|
+
await setResultOutput(result, presenter);
|
|
37
|
+
}
|
|
38
|
+
async function presentGitHubActionPublicationError(error, presenter) {
|
|
39
|
+
await presenter.setOutput("result", JSON.stringify(toPiprResult({
|
|
40
|
+
source: "host",
|
|
41
|
+
result: {
|
|
42
|
+
kind: "publication-error",
|
|
43
|
+
publication: error.result
|
|
44
|
+
}
|
|
45
|
+
})));
|
|
46
|
+
}
|
|
47
|
+
async function presentGitHubActionError(presenter) {
|
|
48
|
+
await presenter.setOutput("result", JSON.stringify(toPiprErrorResult(void 0)));
|
|
49
|
+
}
|
|
50
|
+
async function setResultOutput(result, presenter) {
|
|
51
|
+
await presenter.setOutput("result", JSON.stringify(toPiprResult({
|
|
52
|
+
source: "host",
|
|
53
|
+
result
|
|
54
|
+
})));
|
|
39
55
|
}
|
|
40
56
|
async function warnInlineResolutionErrors(errors, presenter) {
|
|
41
57
|
for (const error of errors) await presenter.warning(`pipr inline resolution failed: ${error}`);
|
|
42
58
|
}
|
|
43
59
|
//#endregion
|
|
44
|
-
export { presentGitHubActionResult };
|
|
60
|
+
export { presentGitHubActionError, presentGitHubActionPublicationError, presentGitHubActionResult };
|
|
45
61
|
|
|
46
62
|
//# sourceMappingURL=action-result.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-result.mjs","names":[],"sources":["../../src/internal/action-result.ts"],"sourcesContent":["import type { HostRunCommandResult } from \"../host-run/types.js\";\n\nexport type GitHubActionResultPresenter = {\n info(message: string): void | Promise<void>;\n warning(message: string): void | Promise<void>;\n setOutput(name: string, value: string): void | Promise<void>;\n};\n\nexport async function presentGitHubActionResult(\n result: HostRunCommandResult,\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n if (result.kind === \"ignored\") {\n await presenter.info(`pipr ignored event: ${result.reason}`);\n return;\n }\n\n await presenter.info(\n `pipr loaded change #${result.event.change.number} for ${result.event.repository.slug}`,\n );\n await presenter.info(`pipr config source: ${result.configSource}`);\n\n switch (result.kind) {\n case \"dry-run\":\n await presenter.info(\n \"PIPR_DRY_RUN=1; stopping before review runtime, model, or GitHub publishing calls\",\n );\n
|
|
1
|
+
{"version":3,"file":"action-result.mjs","names":[],"sources":["../../src/internal/action-result.ts"],"sourcesContent":["import type { HostRunCommandResult } from \"../host-run/types.js\";\nimport type { PublicationError } from \"../review/publication-result.js\";\nimport { stripPiprMainCommentMarkers, toPiprErrorResult, toPiprResult } from \"./pipr-result.js\";\n\nexport type GitHubActionResultPresenter = {\n info(message: string): void | Promise<void>;\n warning(message: string): void | Promise<void>;\n setOutput(name: string, value: string): void | Promise<void>;\n};\n\nexport async function presentGitHubActionResult(\n result: HostRunCommandResult,\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n if (result.kind === \"ignored\") {\n await presenter.info(`pipr ignored event: ${result.reason}`);\n await setResultOutput(result, presenter);\n return;\n }\n\n await presenter.info(\n `pipr loaded change #${result.event.change.number} for ${result.event.repository.slug}`,\n );\n await presenter.info(`pipr config source: ${result.configSource}`);\n\n switch (result.kind) {\n case \"dry-run\":\n await presenter.info(\n \"PIPR_DRY_RUN=1; stopping before review runtime, model, or GitHub publishing calls\",\n );\n break;\n case \"command-help\":\n await presenter.info(`pipr command help: ${result.reason}`);\n await presenter.setOutput(\"main-comment\", result.body);\n break;\n case \"command-response\":\n await presenter.info(\n `pipr command '${result.command}' published response comment (${result.publication.action})`,\n );\n await presenter.setOutput(\"main-comment\", result.response.body);\n break;\n case \"verifier\":\n await presenter.info(\n `pipr verifier processed review comment reply with ${result.errors.length} publication error(s)`,\n );\n await warnInlineResolutionErrors(result.errors, presenter);\n break;\n case \"review\":\n await presenter.info(\n `pipr review produced ${result.review.validated.validFindings.length} valid inline finding(s), ` +\n `${result.review.validated.droppedFindings.length} dropped finding(s)`,\n );\n await presenter.info(\n `pipr published main comment (${result.publication.mainComment.action}) and ` +\n `${result.publication.inlineComments.posted} inline comment(s); ` +\n `${result.publication.inlineComments.skipped} skipped`,\n );\n await warnInlineResolutionErrors(\n result.publication.metadata.inlineResolutionErrors,\n presenter,\n );\n if (result.review.repairAttempted) {\n await presenter.info(\"pipr repaired reviewer JSON once before validation\");\n }\n await presenter.setOutput(\n \"main-comment\",\n stripPiprMainCommentMarkers(result.review.mainComment),\n );\n break;\n default:\n result satisfies never;\n }\n\n await setResultOutput(result, presenter);\n}\n\nexport async function presentGitHubActionPublicationError(\n error: PublicationError,\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n await presenter.setOutput(\n \"result\",\n JSON.stringify(\n toPiprResult({\n source: \"host\",\n result: { kind: \"publication-error\", publication: error.result },\n }),\n ),\n );\n}\n\nexport async function presentGitHubActionError(\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n await presenter.setOutput(\"result\", JSON.stringify(toPiprErrorResult(undefined)));\n}\n\nasync function setResultOutput(\n result: HostRunCommandResult,\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n await presenter.setOutput(\"result\", JSON.stringify(toPiprResult({ source: \"host\", result })));\n}\n\nasync function warnInlineResolutionErrors(\n errors: readonly string[],\n presenter: GitHubActionResultPresenter,\n): Promise<void> {\n for (const error of errors) {\n await presenter.warning(`pipr inline resolution failed: ${error}`);\n }\n}\n"],"mappings":";;AAUA,eAAsB,0BACpB,QACA,WACe;CACf,IAAI,OAAO,SAAS,WAAW;EAC7B,MAAM,UAAU,KAAK,uBAAuB,OAAO,QAAQ;EAC3D,MAAM,gBAAgB,QAAQ,SAAS;EACvC;CACF;CAEA,MAAM,UAAU,KACd,uBAAuB,OAAO,MAAM,OAAO,OAAO,OAAO,OAAO,MAAM,WAAW,MACnF;CACA,MAAM,UAAU,KAAK,uBAAuB,OAAO,cAAc;CAEjE,QAAQ,OAAO,MAAf;EACE,KAAK;GACH,MAAM,UAAU,KACd,mFACF;GACA;EACF,KAAK;GACH,MAAM,UAAU,KAAK,sBAAsB,OAAO,QAAQ;GAC1D,MAAM,UAAU,UAAU,gBAAgB,OAAO,IAAI;GACrD;EACF,KAAK;GACH,MAAM,UAAU,KACd,iBAAiB,OAAO,QAAQ,gCAAgC,OAAO,YAAY,OAAO,EAC5F;GACA,MAAM,UAAU,UAAU,gBAAgB,OAAO,SAAS,IAAI;GAC9D;EACF,KAAK;GACH,MAAM,UAAU,KACd,qDAAqD,OAAO,OAAO,OAAO,sBAC5E;GACA,MAAM,2BAA2B,OAAO,QAAQ,SAAS;GACzD;EACF,KAAK;GACH,MAAM,UAAU,KACd,wBAAwB,OAAO,OAAO,UAAU,cAAc,OAAO,4BAChE,OAAO,OAAO,UAAU,gBAAgB,OAAO,oBACtD;GACA,MAAM,UAAU,KACd,gCAAgC,OAAO,YAAY,YAAY,OAAO,QACjE,OAAO,YAAY,eAAe,OAAO,sBACzC,OAAO,YAAY,eAAe,QAAQ,SACjD;GACA,MAAM,2BACJ,OAAO,YAAY,SAAS,wBAC5B,SACF;GACA,IAAI,OAAO,OAAO,iBAChB,MAAM,UAAU,KAAK,oDAAoD;GAE3E,MAAM,UAAU,UACd,gBACA,4BAA4B,OAAO,OAAO,WAAW,CACvD;GACA;EACF;CAEF;CAEA,MAAM,gBAAgB,QAAQ,SAAS;AACzC;AAEA,eAAsB,oCACpB,OACA,WACe;CACf,MAAM,UAAU,UACd,UACA,KAAK,UACH,aAAa;EACX,QAAQ;EACR,QAAQ;GAAE,MAAM;GAAqB,aAAa,MAAM;EAAO;CACjE,CAAC,CACH,CACF;AACF;AAEA,eAAsB,yBACpB,WACe;CACf,MAAM,UAAU,UAAU,UAAU,KAAK,UAAU,kBAAkB,KAAA,CAAS,CAAC,CAAC;AAClF;AAEA,eAAe,gBACb,QACA,WACe;CACf,MAAM,UAAU,UAAU,UAAU,KAAK,UAAU,aAAa;EAAE,QAAQ;EAAQ;CAAO,CAAC,CAAC,CAAC;AAC9F;AAEA,eAAe,2BACb,QACA,WACe;CACf,KAAK,MAAM,SAAS,QAClB,MAAM,UAAU,QAAQ,kCAAkC,OAAO;AAErE"}
|
package/dist/internal/docs.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as listOfficialInitRecipes, t as renderOfficialGithubWorkflow } from "../official-github-workflow-
|
|
1
|
+
import { n as listOfficialInitRecipes, t as renderOfficialGithubWorkflow } from "../official-github-workflow-DNzV5Z70.mjs";
|
|
2
2
|
export { listOfficialInitRecipes, renderOfficialGithubWorkflow };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { a as HostRunCommandResult, l as LocalReviewCommandResult, x as PublicationError } from "../types-Dn1U3MDG.mjs";
|
|
2
|
+
import { PiprResult } from "@usepipr/sdk";
|
|
3
|
+
//#region src/internal/pipr-result.d.ts
|
|
4
|
+
type ResultInput = {
|
|
5
|
+
source: "host";
|
|
6
|
+
result: HostRunCommandResult;
|
|
7
|
+
} | {
|
|
8
|
+
source: "local";
|
|
9
|
+
result: LocalReviewCommandResult;
|
|
10
|
+
} | {
|
|
11
|
+
source: "host";
|
|
12
|
+
result: {
|
|
13
|
+
kind: "publication-error";
|
|
14
|
+
publication: PublicationError["result"];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
declare function toPiprResult(input: ResultInput): PiprResult;
|
|
18
|
+
declare function toPiprErrorResult(_error: unknown): Extract<PiprResult, {
|
|
19
|
+
kind: "error";
|
|
20
|
+
}>;
|
|
21
|
+
declare function stripPiprMainCommentMarkers(mainComment: string): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { stripPiprMainCommentMarkers, toPiprErrorResult, toPiprResult };
|
|
24
|
+
//# sourceMappingURL=pipr-result.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipr-result.d.mts","names":[],"sources":["../../src/internal/pipr-result.ts"],"mappings":";;;KAUK;EACC;EAAgB,QAAQ;;EACxB;EAAiB,QAAQ;;EAEzB;EACA;IAAU;IAA2B,aAAa;;;iBAGxC,aAAa,OAAO,cAAc;iBAMlC,kBAAkB,kBAAkB,QAAQ;EAAc;;iBAgH1D,4BAA4B"}
|