@kici-dev/orchestrator 0.1.5 → 0.1.7
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/app.d.ts +9 -3
- package/dist/cli.js +30 -1
- package/dist/cluster/coordinator.d.ts +3 -3
- package/dist/config.d.ts +2 -0
- package/dist/db/types.d.ts +1 -1
- package/dist/orchestrator-core.d.ts +9 -2
- package/dist/pipeline/processor.d.ts +2 -2
- package/dist/pipeline/rerun.d.ts +2 -2
- package/dist/pipeline/test-pipeline.d.ts +2 -2
- package/dist/reporting/{commit-status.d.ts → check-run-reporter.d.ts} +7 -7
- package/dist/reporting/check-run-tracking-store.d.ts +2 -2
- package/dist/routes/admin-sources.d.ts +15 -0
- package/dist/routes/admin.d.ts +14 -0
- package/dist/server.js +527 -352
- package/dist/sources/build-platform-sources.d.ts +26 -0
- package/dist/sources/source-manager.d.ts +14 -0
- package/dist/stale-detector/stale-run-detector.d.ts +3 -3
- package/dist/standalone.js +146 -75
- package/dist/webhook/generic-sources-listener.d.ts +15 -0
- package/dist/ws/platform-client.d.ts +27 -1
- package/package.json +3 -3
- package/sbom.spdx.json +36 -36
package/dist/server.js
CHANGED
|
@@ -135,7 +135,7 @@ var init_verification = __esmMin((() => {}));
|
|
|
135
135
|
//#endregion
|
|
136
136
|
//#region src/webhook/verify-inbound.ts
|
|
137
137
|
init_verification();
|
|
138
|
-
const logger$
|
|
138
|
+
const logger$97 = createLogger({ prefix: "verify-inbound" });
|
|
139
139
|
/** Fixed org_id for source secrets in PgSecretStore (matches SourceStore). */
|
|
140
140
|
const SOURCE_ORG_ID$1 = "__system__";
|
|
141
141
|
/** Default GitHub-style signature header. */
|
|
@@ -151,7 +151,7 @@ async function verifyInboundWebhook(deps, input) {
|
|
|
151
151
|
const { routingKey } = input;
|
|
152
152
|
if (routingKey.startsWith("github:")) return verifyGithub(deps, input);
|
|
153
153
|
if (routingKey.startsWith("generic:")) return verifyGeneric(deps, input);
|
|
154
|
-
logger$
|
|
154
|
+
logger$97.warn("Unknown routing-key prefix", { routingKey });
|
|
155
155
|
return {
|
|
156
156
|
result: "rejected_unknown_source",
|
|
157
157
|
reason: `provider not implemented for routing key prefix`
|
|
@@ -177,7 +177,7 @@ async function verifyGithub(deps, input) {
|
|
|
177
177
|
try {
|
|
178
178
|
secrets = await getGithubWebhookSecrets(secretStore, source.id);
|
|
179
179
|
} catch (err) {
|
|
180
|
-
logger$
|
|
180
|
+
logger$97.error("Failed to read webhook secret from PgSecretStore", {
|
|
181
181
|
routingKey,
|
|
182
182
|
sourceId: source.id,
|
|
183
183
|
error: toErrorMessage(err)
|
|
@@ -227,7 +227,7 @@ async function verifyGeneric(deps, input) {
|
|
|
227
227
|
try {
|
|
228
228
|
config = parseGenericVerificationConfig(source.verification_method, source.verification_config);
|
|
229
229
|
} catch (err) {
|
|
230
|
-
logger$
|
|
230
|
+
logger$97.error("Malformed verification_config JSON", {
|
|
231
231
|
routingKey,
|
|
232
232
|
method: source.verification_method,
|
|
233
233
|
error: toErrorMessage(err)
|
|
@@ -380,6 +380,15 @@ var init_config$5 = __esmMin((() => {
|
|
|
380
380
|
* behavior). Trailing slash optional.
|
|
381
381
|
*/
|
|
382
382
|
dashboardUrl: z.string().optional(),
|
|
383
|
+
/**
|
|
384
|
+
* Public base URL at which this orchestrator's own webhook ingress is
|
|
385
|
+
* reachable (independent/hybrid self-serve generic webhooks:
|
|
386
|
+
* `<base>/webhook/<customerId>/generic/<sourceId>`). Used by
|
|
387
|
+
* `kici-admin source add` to print a generic source's webhook URL. GitHub-App
|
|
388
|
+
* ingress is Platform-relayed, so GitHub URLs come from the Platform's
|
|
389
|
+
* `source.register.ack`, not this value. Trailing slash optional.
|
|
390
|
+
*/
|
|
391
|
+
webhookPublicUrl: z.string().optional(),
|
|
383
392
|
databaseUrl: z.string().default(""),
|
|
384
393
|
lockfileCacheMax: z.coerce.number().default(500),
|
|
385
394
|
lockfileCacheTtlMs: z.coerce.number().default(36e5),
|
|
@@ -572,6 +581,7 @@ var init_config$5 = __esmMin((() => {
|
|
|
572
581
|
platformUrl: "KICI_PLATFORM_URL",
|
|
573
582
|
platformToken: "KICI_PLATFORM_TOKEN",
|
|
574
583
|
dashboardUrl: "KICI_DASHBOARD_URL",
|
|
584
|
+
webhookPublicUrl: "KICI_WEBHOOK_PUBLIC_URL",
|
|
575
585
|
databaseUrl: "KICI_DATABASE_URL",
|
|
576
586
|
cacheStorageType: "KICI_STORAGE_TYPE",
|
|
577
587
|
cacheStoragePath: "KICI_STORAGE_PATH",
|
|
@@ -731,9 +741,9 @@ var init_event_buffer = __esmMin((() => {
|
|
|
731
741
|
* `rejected_misconfigured` ack. This keeps the WS handler inside its 5 s budget
|
|
732
742
|
* and prevents a malicious sender from killing the orch process via a bad frame.
|
|
733
743
|
*/
|
|
734
|
-
var logger$
|
|
744
|
+
var logger$96, DEFAULT_BUFFER_TTL_MS, RelayBufferRegistry;
|
|
735
745
|
var init_relay_buffer = __esmMin((() => {
|
|
736
|
-
logger$
|
|
746
|
+
logger$96 = createLogger({ prefix: "relay-buffer" });
|
|
737
747
|
DEFAULT_BUFFER_TTL_MS = 3e4;
|
|
738
748
|
RelayBufferRegistry = class {
|
|
739
749
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -767,7 +777,7 @@ var init_relay_buffer = __esmMin((() => {
|
|
|
767
777
|
};
|
|
768
778
|
const ttl = setTimeout(() => {
|
|
769
779
|
this.buffers.delete(messageId);
|
|
770
|
-
logger$
|
|
780
|
+
logger$96.warn("Reassembly buffer TTL expired before final chunk", {
|
|
771
781
|
messageId,
|
|
772
782
|
deliveryId: meta.deliveryId,
|
|
773
783
|
receivedChunks: this.buffers.get(messageId)?.expectedSequence ?? 0
|
|
@@ -902,11 +912,11 @@ function toSourceRegistrationEntry(source) {
|
|
|
902
912
|
subtype: source.subtype
|
|
903
913
|
};
|
|
904
914
|
}
|
|
905
|
-
var logger$
|
|
915
|
+
var logger$95, PlatformClient$1;
|
|
906
916
|
var init_platform_client = __esmMin((() => {
|
|
907
917
|
init_event_buffer();
|
|
908
918
|
init_relay_buffer();
|
|
909
|
-
logger$
|
|
919
|
+
logger$95 = createLogger({ prefix: "platform-client" });
|
|
910
920
|
PlatformClient$1 = class {
|
|
911
921
|
ws = null;
|
|
912
922
|
_state = "disconnected";
|
|
@@ -919,6 +929,12 @@ var init_platform_client = __esmMin((() => {
|
|
|
919
929
|
token;
|
|
920
930
|
onWebhookRelay;
|
|
921
931
|
providerSources;
|
|
932
|
+
/**
|
|
933
|
+
* Pending `registerSourceAndAwait()` callers, keyed by routing key. Resolved
|
|
934
|
+
* with the Platform-computed webhook URL when the matching
|
|
935
|
+
* `source.register.ack` arrives, or rejected on timeout / disconnect.
|
|
936
|
+
*/
|
|
937
|
+
pendingSourceRegistrations = /* @__PURE__ */ new Map();
|
|
922
938
|
instanceId;
|
|
923
939
|
clusterName;
|
|
924
940
|
clusterId;
|
|
@@ -961,7 +977,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
961
977
|
/**
|
|
962
978
|
* Returns the cached public alias of the orchestrator's owning org,
|
|
963
979
|
* or `undefined` if Platform has not supplied one yet. Read by
|
|
964
|
-
* `
|
|
980
|
+
* `check-run-reporter.ts` when building `details_url`.
|
|
965
981
|
*/
|
|
966
982
|
getOrgPublicAlias() {
|
|
967
983
|
return this._orgPublicAlias;
|
|
@@ -1048,7 +1064,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1048
1064
|
*/
|
|
1049
1065
|
async completeChunkedRelay(messageId, meta, body) {
|
|
1050
1066
|
if (!this.onVerifyInbound) {
|
|
1051
|
-
logger$
|
|
1067
|
+
logger$95.error("Chunked webhook.relay received but no onVerifyInbound configured", {
|
|
1052
1068
|
messageId,
|
|
1053
1069
|
deliveryId: meta.deliveryId
|
|
1054
1070
|
});
|
|
@@ -1063,7 +1079,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1063
1079
|
}
|
|
1064
1080
|
const outcome = await this.onVerifyInbound(meta, body);
|
|
1065
1081
|
if (outcome.result !== "accepted") {
|
|
1066
|
-
logger$
|
|
1082
|
+
logger$95.warn("Chunked webhook.relay verify rejected", {
|
|
1067
1083
|
messageId,
|
|
1068
1084
|
deliveryId: meta.deliveryId,
|
|
1069
1085
|
routingKey: meta.routingKey,
|
|
@@ -1084,7 +1100,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1084
1100
|
if (contentType.includes("application/json") || contentType === "") try {
|
|
1085
1101
|
payload = body.length === 0 ? {} : JSON.parse(body.toString("utf8"));
|
|
1086
1102
|
} catch (err) {
|
|
1087
|
-
logger$
|
|
1103
|
+
logger$95.warn("Accepted webhook body is not valid JSON; rejecting", {
|
|
1088
1104
|
messageId,
|
|
1089
1105
|
deliveryId: meta.deliveryId,
|
|
1090
1106
|
error: toErrorMessage(err)
|
|
@@ -1119,7 +1135,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1119
1135
|
...meta.requestId && { requestId: meta.requestId }
|
|
1120
1136
|
};
|
|
1121
1137
|
this.onWebhookRelay(relay).catch((err) => {
|
|
1122
|
-
logger$
|
|
1138
|
+
logger$95.error("Error processing chunked webhook relay", {
|
|
1123
1139
|
messageId,
|
|
1124
1140
|
deliveryId: meta.deliveryId,
|
|
1125
1141
|
error: toErrorMessage(err)
|
|
@@ -1132,7 +1148,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1132
1148
|
*/
|
|
1133
1149
|
connect() {
|
|
1134
1150
|
if (this._state !== "disconnected") {
|
|
1135
|
-
logger$
|
|
1151
|
+
logger$95.warn("connect() called while not disconnected", { state: this._state });
|
|
1136
1152
|
return;
|
|
1137
1153
|
}
|
|
1138
1154
|
this.intentionalDisconnect = false;
|
|
@@ -1226,7 +1242,9 @@ var init_platform_client = __esmMin((() => {
|
|
|
1226
1242
|
...this.address !== void 0 && { address: this.address },
|
|
1227
1243
|
...this.version && { version: this.version },
|
|
1228
1244
|
...this.mode && { mode: this.mode },
|
|
1229
|
-
...this.scalerBackends && { scalerBackends: this.scalerBackends }
|
|
1245
|
+
...this.scalerBackends && { scalerBackends: this.scalerBackends },
|
|
1246
|
+
...this.s3LogAccess !== void 0 && { s3LogAccess: this.s3LogAccess },
|
|
1247
|
+
...this.queueTimeoutMs && { queueTimeoutMs: this.queueTimeoutMs }
|
|
1230
1248
|
});
|
|
1231
1249
|
else if (newSources.length === 0 && this.providerSources.length > 0) this.send({
|
|
1232
1250
|
type: "source.register",
|
|
@@ -1245,6 +1263,50 @@ var init_platform_client = __esmMin((() => {
|
|
|
1245
1263
|
this.providerSources.length = 0;
|
|
1246
1264
|
this.providerSources.push(...newSources);
|
|
1247
1265
|
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Push the full source list to the Platform and resolve with the webhook URL
|
|
1268
|
+
* the Platform computed for `routingKey` (from the `source.register.ack`), or
|
|
1269
|
+
* `null` if the Platform has no public webhook base configured.
|
|
1270
|
+
*
|
|
1271
|
+
* Used by `kici-admin source add` (platform/hybrid mode) to print the URL
|
|
1272
|
+
* synchronously. Passing the **full** source list keeps this on the single
|
|
1273
|
+
* `updateSources` push path — the routing key being newly added means
|
|
1274
|
+
* `updateSources` emits a `source.register` whose ack carries the URL; the
|
|
1275
|
+
* later NOTIFY-driven republish then diffs to a no-op.
|
|
1276
|
+
*
|
|
1277
|
+
* Rejects on timeout or disconnect; the caller degrades to a "(unavailable)"
|
|
1278
|
+
* note rather than fabricating a URL.
|
|
1279
|
+
*/
|
|
1280
|
+
registerSourceAndAwait(fullSources, routingKey, timeoutMs = 5e3) {
|
|
1281
|
+
return new Promise((resolve, reject) => {
|
|
1282
|
+
const existing = this.pendingSourceRegistrations.get(routingKey);
|
|
1283
|
+
if (existing) {
|
|
1284
|
+
clearTimeout(existing.timer);
|
|
1285
|
+
existing.reject(/* @__PURE__ */ new Error("superseded by a newer registration"));
|
|
1286
|
+
}
|
|
1287
|
+
const timer = setTimeout(() => {
|
|
1288
|
+
this.pendingSourceRegistrations.delete(routingKey);
|
|
1289
|
+
reject(/* @__PURE__ */ new Error(`timed out waiting for source.register.ack for ${routingKey}`));
|
|
1290
|
+
}, timeoutMs);
|
|
1291
|
+
this.pendingSourceRegistrations.set(routingKey, {
|
|
1292
|
+
resolve,
|
|
1293
|
+
reject,
|
|
1294
|
+
timer
|
|
1295
|
+
});
|
|
1296
|
+
this.updateSources(fullSources);
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Reject every pending `registerSourceAndAwait()` — called on disconnect so a
|
|
1301
|
+
* `source add` issued while the link drops fails fast instead of hanging.
|
|
1302
|
+
*/
|
|
1303
|
+
rejectPendingSourceRegistrations(reason) {
|
|
1304
|
+
for (const [, pending] of this.pendingSourceRegistrations) {
|
|
1305
|
+
clearTimeout(pending.timer);
|
|
1306
|
+
pending.reject(new Error(reason));
|
|
1307
|
+
}
|
|
1308
|
+
this.pendingSourceRegistrations.clear();
|
|
1309
|
+
}
|
|
1248
1310
|
getReconnectDelay() {
|
|
1249
1311
|
return getReconnectDelay(this.reconnectAttempts, this.maxReconnectDelayMs);
|
|
1250
1312
|
}
|
|
@@ -1259,14 +1321,14 @@ var init_platform_client = __esmMin((() => {
|
|
|
1259
1321
|
}
|
|
1260
1322
|
});
|
|
1261
1323
|
} catch (err) {
|
|
1262
|
-
logger$
|
|
1324
|
+
logger$95.error("Failed to create WebSocket", { error: toErrorMessage(err) });
|
|
1263
1325
|
this._state = "disconnected";
|
|
1264
1326
|
this.scheduleReconnect();
|
|
1265
1327
|
return;
|
|
1266
1328
|
}
|
|
1267
1329
|
this.ws.on("open", () => {
|
|
1268
1330
|
this._state = "authenticating";
|
|
1269
|
-
logger$
|
|
1331
|
+
logger$95.info("Connected to Platform, sending auth request", { url: this.url });
|
|
1270
1332
|
this.ws.send(JSON.stringify({
|
|
1271
1333
|
type: "auth.request",
|
|
1272
1334
|
token: this.token,
|
|
@@ -1279,16 +1341,17 @@ var init_platform_client = __esmMin((() => {
|
|
|
1279
1341
|
});
|
|
1280
1342
|
this.ws.on("close", (code, reason) => {
|
|
1281
1343
|
const reasonText = reason.toString();
|
|
1282
|
-
logger$
|
|
1344
|
+
logger$95.info("Platform connection closed", {
|
|
1283
1345
|
code,
|
|
1284
1346
|
reason: reasonText
|
|
1285
1347
|
});
|
|
1286
1348
|
this._state = "disconnected";
|
|
1287
1349
|
this.stopHeartbeat();
|
|
1350
|
+
this.rejectPendingSourceRegistrations("Platform connection closed before ack");
|
|
1288
1351
|
if (!this.intentionalDisconnect) this.scheduleReconnect();
|
|
1289
1352
|
});
|
|
1290
1353
|
this.ws.on("error", (err) => {
|
|
1291
|
-
logger$
|
|
1354
|
+
logger$95.error("Platform WebSocket error", { error: err.message });
|
|
1292
1355
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.close();
|
|
1293
1356
|
});
|
|
1294
1357
|
}
|
|
@@ -1297,7 +1360,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1297
1360
|
try {
|
|
1298
1361
|
raw = JSON.parse(data.toString());
|
|
1299
1362
|
} catch {
|
|
1300
|
-
logger$
|
|
1363
|
+
logger$95.warn("Malformed JSON received from Platform");
|
|
1301
1364
|
return;
|
|
1302
1365
|
}
|
|
1303
1366
|
const parsed = platformToOrchestratorMessageSchema.safeParse(raw);
|
|
@@ -1324,11 +1387,11 @@ var init_platform_client = __esmMin((() => {
|
|
|
1324
1387
|
this.onJoinRequest(joinParsed.data).then((response) => {
|
|
1325
1388
|
this.sendRaw(response);
|
|
1326
1389
|
}).catch((err) => {
|
|
1327
|
-
logger$
|
|
1390
|
+
logger$95.error("Error handling join request", { error: toErrorMessage(err) });
|
|
1328
1391
|
});
|
|
1329
1392
|
return;
|
|
1330
1393
|
}
|
|
1331
|
-
logger$
|
|
1394
|
+
logger$95.warn("Invalid message from Platform", { errors: primaryIssues });
|
|
1332
1395
|
}
|
|
1333
1396
|
/**
|
|
1334
1397
|
* Dispatch a parsed platform message to the appropriate per-area
|
|
@@ -1354,7 +1417,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1354
1417
|
this.handleSourceRegisterAck(msg);
|
|
1355
1418
|
break;
|
|
1356
1419
|
case "source.deregister.ack":
|
|
1357
|
-
logger$
|
|
1420
|
+
logger$95.info("Source deregistration acknowledged", { removed: msg.removed });
|
|
1358
1421
|
break;
|
|
1359
1422
|
case "peer.discover":
|
|
1360
1423
|
this.handlePeerDiscover(msg);
|
|
@@ -1363,14 +1426,14 @@ var init_platform_client = __esmMin((() => {
|
|
|
1363
1426
|
this.handlePeerUpdate(msg);
|
|
1364
1427
|
break;
|
|
1365
1428
|
case "dashboard.run.detail":
|
|
1366
|
-
logger$
|
|
1429
|
+
logger$95.debug("Dashboard run detail request received", {
|
|
1367
1430
|
requestId: msg.requestId,
|
|
1368
1431
|
runId: msg.runId
|
|
1369
1432
|
});
|
|
1370
1433
|
this.onDashboardRunDetail?.(msg);
|
|
1371
1434
|
break;
|
|
1372
1435
|
case "dashboard.step.logs":
|
|
1373
|
-
logger$
|
|
1436
|
+
logger$95.debug("Dashboard step logs request received", {
|
|
1374
1437
|
requestId: msg.requestId,
|
|
1375
1438
|
runId: msg.runId,
|
|
1376
1439
|
jobId: msg.jobId,
|
|
@@ -1379,7 +1442,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1379
1442
|
this.onDashboardStepLogs?.(msg);
|
|
1380
1443
|
break;
|
|
1381
1444
|
case "run.rerun.request":
|
|
1382
|
-
logger$
|
|
1445
|
+
logger$95.info("Run rerun request received", {
|
|
1383
1446
|
requestId: msg.requestId,
|
|
1384
1447
|
runId: msg.runId,
|
|
1385
1448
|
actor: msg.actor
|
|
@@ -1387,7 +1450,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1387
1450
|
this.onRunRerun?.(msg);
|
|
1388
1451
|
break;
|
|
1389
1452
|
case "run.manual_schedule.request":
|
|
1390
|
-
logger$
|
|
1453
|
+
logger$95.info("Manual schedule request received", {
|
|
1391
1454
|
requestId: msg.requestId,
|
|
1392
1455
|
registrationId: msg.registrationId,
|
|
1393
1456
|
actor: msg.actor
|
|
@@ -1395,7 +1458,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1395
1458
|
this.onManualSchedule?.(msg);
|
|
1396
1459
|
break;
|
|
1397
1460
|
case "run.cancel.request":
|
|
1398
|
-
logger$
|
|
1461
|
+
logger$95.info("Run cancel request received", {
|
|
1399
1462
|
requestId: msg.requestId,
|
|
1400
1463
|
runId: msg.runId,
|
|
1401
1464
|
actor: msg.actor
|
|
@@ -1403,14 +1466,14 @@ var init_platform_client = __esmMin((() => {
|
|
|
1403
1466
|
this.onRunCancel?.(msg);
|
|
1404
1467
|
break;
|
|
1405
1468
|
case "dashboard.payload":
|
|
1406
|
-
logger$
|
|
1469
|
+
logger$95.debug("Dashboard payload request received", {
|
|
1407
1470
|
requestId: msg.requestId,
|
|
1408
1471
|
runId: msg.runId
|
|
1409
1472
|
});
|
|
1410
1473
|
this.onDashboardPayload?.(msg);
|
|
1411
1474
|
break;
|
|
1412
1475
|
case "dashboard.orch.logs":
|
|
1413
|
-
logger$
|
|
1476
|
+
logger$95.debug("Dashboard orchestration logs request received", {
|
|
1414
1477
|
requestId: msg.requestId,
|
|
1415
1478
|
runId: msg.runId,
|
|
1416
1479
|
jobId: msg.jobId
|
|
@@ -1418,30 +1481,30 @@ var init_platform_client = __esmMin((() => {
|
|
|
1418
1481
|
this.onDashboardOrchLogs?.(msg);
|
|
1419
1482
|
break;
|
|
1420
1483
|
case "trust_policy.update":
|
|
1421
|
-
logger$
|
|
1484
|
+
logger$95.info("Trust policy updated", { orgId: msg.orgId });
|
|
1422
1485
|
this.onTrustPolicyUpdate?.(msg);
|
|
1423
1486
|
break;
|
|
1424
1487
|
case "stale.checkrun.cleanup":
|
|
1425
|
-
logger$
|
|
1488
|
+
logger$95.info("Stale check run cleanup request received", { runCount: msg.runs.length });
|
|
1426
1489
|
this.onStaleCheckrunCleanup?.(msg);
|
|
1427
1490
|
break;
|
|
1428
1491
|
case "dashboard.diagnostics":
|
|
1429
|
-
logger$
|
|
1492
|
+
logger$95.debug("Dashboard diagnostics request received", { requestId: msg.requestId });
|
|
1430
1493
|
this.onDashboardDiagnostics?.(msg);
|
|
1431
1494
|
break;
|
|
1432
1495
|
case "dashboard.scaler.capacity":
|
|
1433
|
-
logger$
|
|
1496
|
+
logger$95.debug("Dashboard scaler capacity request received", { requestId: msg.requestId });
|
|
1434
1497
|
this.onDashboardScalerCapacity?.(msg);
|
|
1435
1498
|
break;
|
|
1436
1499
|
case "dashboard.scaler.agents":
|
|
1437
|
-
logger$
|
|
1500
|
+
logger$95.debug("Dashboard scaler agents request received", {
|
|
1438
1501
|
requestId: msg.requestId,
|
|
1439
1502
|
scalerName: msg.scalerName
|
|
1440
1503
|
});
|
|
1441
1504
|
this.onDashboardScalerAgents?.(msg);
|
|
1442
1505
|
break;
|
|
1443
1506
|
case "dashboard.access-log.list":
|
|
1444
|
-
logger$
|
|
1507
|
+
logger$95.debug("Dashboard access-log list request received", {
|
|
1445
1508
|
requestId: msg.requestId,
|
|
1446
1509
|
orgId: msg.orgId
|
|
1447
1510
|
});
|
|
@@ -1487,19 +1550,19 @@ var init_platform_client = __esmMin((() => {
|
|
|
1487
1550
|
case "dashboard.backends.test":
|
|
1488
1551
|
case "dashboard.global-workflows.get":
|
|
1489
1552
|
case "dashboard.global-workflows.update":
|
|
1490
|
-
logger$
|
|
1553
|
+
logger$95.debug("Dashboard environment message received", {
|
|
1491
1554
|
type: msg.type,
|
|
1492
1555
|
requestId: msg.requestId
|
|
1493
1556
|
});
|
|
1494
1557
|
this.onDashboardEnvMessage?.(msg);
|
|
1495
1558
|
break;
|
|
1496
1559
|
default:
|
|
1497
|
-
logger$
|
|
1560
|
+
logger$95.warn("Unknown platform message type", { type: msg.type });
|
|
1498
1561
|
break;
|
|
1499
1562
|
}
|
|
1500
1563
|
}
|
|
1501
1564
|
handleAuthSuccess(msg) {
|
|
1502
|
-
logger$
|
|
1565
|
+
logger$95.info("Authenticated with Platform", {
|
|
1503
1566
|
connectionId: msg.connectionId,
|
|
1504
1567
|
orgPublicAlias: msg.orgPublicAlias
|
|
1505
1568
|
});
|
|
@@ -1521,7 +1584,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1521
1584
|
...this.s3LogAccess !== void 0 && { s3LogAccess: this.s3LogAccess },
|
|
1522
1585
|
...this.queueTimeoutMs && { queueTimeoutMs: this.queueTimeoutMs }
|
|
1523
1586
|
});
|
|
1524
|
-
logger$
|
|
1587
|
+
logger$95.info("Sent source.register", {
|
|
1525
1588
|
sources: this.providerSources.map((s) => s.routingKey),
|
|
1526
1589
|
instanceId: this.instanceId,
|
|
1527
1590
|
scalerBackends: this.scalerBackends ?? null
|
|
@@ -1529,7 +1592,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1529
1592
|
this.flushBuffer();
|
|
1530
1593
|
}
|
|
1531
1594
|
handleAuthFailure(msg) {
|
|
1532
|
-
logger$
|
|
1595
|
+
logger$95.error("Platform auth failed", { reason: msg.reason });
|
|
1533
1596
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.close(1e3, "Auth failed");
|
|
1534
1597
|
}
|
|
1535
1598
|
handleWebhookRelayStart(msg) {
|
|
@@ -1547,7 +1610,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1547
1610
|
...msg.requestId && { requestId: msg.requestId }
|
|
1548
1611
|
});
|
|
1549
1612
|
if (startRes.status === "error") {
|
|
1550
|
-
logger$
|
|
1613
|
+
logger$95.warn("Rejecting webhook.relay.start", {
|
|
1551
1614
|
messageId: msg.messageId,
|
|
1552
1615
|
reason: startRes.reason
|
|
1553
1616
|
});
|
|
@@ -1558,7 +1621,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1558
1621
|
result: "rejected_misconfigured",
|
|
1559
1622
|
reason: startRes.reason
|
|
1560
1623
|
});
|
|
1561
|
-
} else logger$
|
|
1624
|
+
} else logger$95.info("Webhook relay stream started", {
|
|
1562
1625
|
messageId: msg.messageId,
|
|
1563
1626
|
deliveryId: msg.deliveryId,
|
|
1564
1627
|
event: msg.event,
|
|
@@ -1570,7 +1633,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1570
1633
|
const applyRes = this.relayBuffer.chunk(msg.messageId, msg.sequence, msg.data, msg.final);
|
|
1571
1634
|
if (applyRes.status === "pending") return;
|
|
1572
1635
|
if (applyRes.status === "error") {
|
|
1573
|
-
logger$
|
|
1636
|
+
logger$95.warn("Rejecting webhook.relay.chunk", {
|
|
1574
1637
|
messageId: msg.messageId,
|
|
1575
1638
|
sequence: msg.sequence,
|
|
1576
1639
|
reason: applyRes.reason
|
|
@@ -1591,7 +1654,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1591
1654
|
routingKey: meta.routingKey
|
|
1592
1655
|
}, () => {
|
|
1593
1656
|
this.completeChunkedRelay(msg.messageId, meta, body).catch((err) => {
|
|
1594
|
-
logger$
|
|
1657
|
+
logger$95.error("Error completing chunked relay", {
|
|
1595
1658
|
messageId: msg.messageId,
|
|
1596
1659
|
error: toErrorMessage(err)
|
|
1597
1660
|
});
|
|
@@ -1608,10 +1671,18 @@ var init_platform_client = __esmMin((() => {
|
|
|
1608
1671
|
handleSourceRegisterAck(msg) {
|
|
1609
1672
|
const accepted = msg.accepted;
|
|
1610
1673
|
const rejected = msg.rejected;
|
|
1611
|
-
if (accepted.length > 0) logger$
|
|
1612
|
-
|
|
1674
|
+
if (accepted.length > 0) logger$95.info("Source registration accepted", { routingKeys: accepted.map((a) => a.routingKey) });
|
|
1675
|
+
for (const entry of accepted) {
|
|
1676
|
+
const pending = this.pendingSourceRegistrations.get(entry.routingKey);
|
|
1677
|
+
if (pending) {
|
|
1678
|
+
clearTimeout(pending.timer);
|
|
1679
|
+
this.pendingSourceRegistrations.delete(entry.routingKey);
|
|
1680
|
+
pending.resolve(entry.webhookUrl);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
if (rejected.length > 0) logger$95.warn("Source registration rejected", { rejected: rejected.map((r) => `${r.routingKey}: ${r.reason}`) });
|
|
1613
1684
|
if (msg.peers && msg.peers.length > 0 && this.onPeerDiscover) for (const peer of msg.peers) {
|
|
1614
|
-
logger$
|
|
1685
|
+
logger$95.info("Peer discovered via source.register.ack", {
|
|
1615
1686
|
connectionId: peer.connectionId,
|
|
1616
1687
|
instanceId: peer.instanceId,
|
|
1617
1688
|
address: peer.address,
|
|
@@ -1623,7 +1694,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1623
1694
|
}
|
|
1624
1695
|
handlePeerDiscover(msg) {
|
|
1625
1696
|
const { peer } = msg;
|
|
1626
|
-
logger$
|
|
1697
|
+
logger$95.info("Peer discovered via Platform matchmaker", {
|
|
1627
1698
|
connectionId: peer.connectionId,
|
|
1628
1699
|
instanceId: peer.instanceId,
|
|
1629
1700
|
address: peer.address,
|
|
@@ -1633,7 +1704,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1633
1704
|
}
|
|
1634
1705
|
handlePeerUpdate(msg) {
|
|
1635
1706
|
if (msg.peers && this.onPeerDiscover) for (const peer of msg.peers) {
|
|
1636
|
-
logger$
|
|
1707
|
+
logger$95.info("Peer discovered via peer.update", {
|
|
1637
1708
|
connectionId: peer.connectionId,
|
|
1638
1709
|
instanceId: peer.instanceId,
|
|
1639
1710
|
address: peer.address,
|
|
@@ -1653,7 +1724,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1653
1724
|
flushBuffer() {
|
|
1654
1725
|
const messages = this.eventBuffer.flush();
|
|
1655
1726
|
if (messages.length > 0) {
|
|
1656
|
-
logger$
|
|
1727
|
+
logger$95.info("Flushing event buffer", { count: messages.length });
|
|
1657
1728
|
for (const msg of messages) this.sendDirect(msg);
|
|
1658
1729
|
}
|
|
1659
1730
|
}
|
|
@@ -1676,7 +1747,7 @@ var init_platform_client = __esmMin((() => {
|
|
|
1676
1747
|
this.cancelReconnect();
|
|
1677
1748
|
const delay = this.getReconnectDelay();
|
|
1678
1749
|
this.reconnectAttempts++;
|
|
1679
|
-
logger$
|
|
1750
|
+
logger$95.info("Scheduling reconnect", {
|
|
1680
1751
|
attempt: this.reconnectAttempts,
|
|
1681
1752
|
delayMs: Math.round(delay)
|
|
1682
1753
|
});
|
|
@@ -2035,7 +2106,7 @@ var trust_resolver_exports = /* @__PURE__ */ __exportAll({
|
|
|
2035
2106
|
function findIdentityLink(identityLinks, provider, providerUsername, providerUserId) {
|
|
2036
2107
|
if (providerUserId === void 0 || providerUserId.length === 0) {
|
|
2037
2108
|
trustMatchRefusedNoIdTotal.add(1, { reason: "event_missing" });
|
|
2038
|
-
logger$
|
|
2109
|
+
logger$94.warn("Trust match refused: webhook event has no provider numeric id", {
|
|
2039
2110
|
provider,
|
|
2040
2111
|
providerUsername
|
|
2041
2112
|
});
|
|
@@ -2047,7 +2118,7 @@ function findIdentityLink(identityLinks, provider, providerUsername, providerUse
|
|
|
2047
2118
|
if (byUsername) {
|
|
2048
2119
|
const reason = byUsername.providerUserId === null || byUsername.providerUserId === void 0 ? "link_missing" : "id_mismatch";
|
|
2049
2120
|
trustMatchRefusedNoIdTotal.add(1, { reason });
|
|
2050
|
-
logger$
|
|
2121
|
+
logger$94.warn("Trust match refused: numeric id missing on link or did not match event", {
|
|
2051
2122
|
provider,
|
|
2052
2123
|
providerUsername,
|
|
2053
2124
|
providerUserId,
|
|
@@ -2075,10 +2146,10 @@ function isReadOrHigher(permission) {
|
|
|
2075
2146
|
function isCiTrustWriteOrHigher(level) {
|
|
2076
2147
|
return level === "write" || level === "admin";
|
|
2077
2148
|
}
|
|
2078
|
-
var logger$
|
|
2149
|
+
var logger$94, TrustResolver$1;
|
|
2079
2150
|
var init_trust_resolver = __esmMin((() => {
|
|
2080
2151
|
init_prometheus();
|
|
2081
|
-
logger$
|
|
2152
|
+
logger$94 = createLogger({ prefix: "trust-resolver" });
|
|
2082
2153
|
TrustResolver$1 = class {
|
|
2083
2154
|
constructor(contributorCache) {
|
|
2084
2155
|
this.contributorCache = contributorCache;
|
|
@@ -2208,14 +2279,14 @@ async function handleApprovalComment(params) {
|
|
|
2208
2279
|
const { commentBody, commenterUsername, commenterUserId, provider, orgId, identityLinks, orgMemberPermissions, heldRunStore } = params;
|
|
2209
2280
|
const command = parseKiciCommand(commentBody);
|
|
2210
2281
|
if (!command) return { handled: false };
|
|
2211
|
-
logger$
|
|
2282
|
+
logger$93.info("Processing /kici command", {
|
|
2212
2283
|
action: command.action,
|
|
2213
2284
|
commenter: commenterUsername,
|
|
2214
2285
|
runId: command.runId
|
|
2215
2286
|
});
|
|
2216
2287
|
const identityLink = findIdentityLink(identityLinks, provider, commenterUsername, commenterUserId);
|
|
2217
2288
|
if (!identityLink) {
|
|
2218
|
-
logger$
|
|
2289
|
+
logger$93.info("No identity link for commenter", {
|
|
2219
2290
|
commenter: commenterUsername,
|
|
2220
2291
|
provider
|
|
2221
2292
|
});
|
|
@@ -2226,7 +2297,7 @@ async function handleApprovalComment(params) {
|
|
|
2226
2297
|
}
|
|
2227
2298
|
const ciTrustLevel = orgMemberPermissions.get(identityLink.userId) ?? "none";
|
|
2228
2299
|
if (ciTrustLevel !== "write" && ciTrustLevel !== "admin") {
|
|
2229
|
-
logger$
|
|
2300
|
+
logger$93.info("Insufficient ci_trust level", {
|
|
2230
2301
|
commenter: commenterUsername,
|
|
2231
2302
|
userId: identityLink.userId,
|
|
2232
2303
|
ciTrustLevel
|
|
@@ -2238,12 +2309,12 @@ async function handleApprovalComment(params) {
|
|
|
2238
2309
|
}
|
|
2239
2310
|
const pendingHolds = await heldRunStore.listByQueueType(orgId, "security", { status: "pending" });
|
|
2240
2311
|
if (pendingHolds.length === 0) {
|
|
2241
|
-
logger$
|
|
2312
|
+
logger$93.info("No pending security holds found", { orgId });
|
|
2242
2313
|
return { handled: true };
|
|
2243
2314
|
}
|
|
2244
2315
|
const targetHolds = command.runId ? pendingHolds.filter((h) => h.run_id === command.runId) : pendingHolds;
|
|
2245
2316
|
if (targetHolds.length === 0) {
|
|
2246
|
-
logger$
|
|
2317
|
+
logger$93.info("No matching security holds found", {
|
|
2247
2318
|
orgId,
|
|
2248
2319
|
runId: command.runId
|
|
2249
2320
|
});
|
|
@@ -2254,14 +2325,14 @@ async function handleApprovalComment(params) {
|
|
|
2254
2325
|
for (const hold of targetHolds) try {
|
|
2255
2326
|
if (approved) {
|
|
2256
2327
|
await heldRunStore.approveByQueueType(orgId, hold.id, identityLink.userId, "security");
|
|
2257
|
-
logger$
|
|
2328
|
+
logger$93.info("Security hold approved", {
|
|
2258
2329
|
heldRunId: hold.id,
|
|
2259
2330
|
runId: hold.run_id,
|
|
2260
2331
|
approvedBy: identityLink.userId
|
|
2261
2332
|
});
|
|
2262
2333
|
} else {
|
|
2263
2334
|
await heldRunStore.reject(orgId, hold.id, `Rejected by ${commenterUsername} via /kici reject`);
|
|
2264
|
-
logger$
|
|
2335
|
+
logger$93.info("Security hold rejected", {
|
|
2265
2336
|
heldRunId: hold.id,
|
|
2266
2337
|
runId: hold.run_id,
|
|
2267
2338
|
rejectedBy: commenterUsername
|
|
@@ -2269,7 +2340,7 @@ async function handleApprovalComment(params) {
|
|
|
2269
2340
|
}
|
|
2270
2341
|
processedCount++;
|
|
2271
2342
|
} catch (err) {
|
|
2272
|
-
logger$
|
|
2343
|
+
logger$93.error("Failed to process security hold", {
|
|
2273
2344
|
heldRunId: hold.id,
|
|
2274
2345
|
action: command.action,
|
|
2275
2346
|
error: toErrorMessage(err)
|
|
@@ -2279,15 +2350,15 @@ async function handleApprovalComment(params) {
|
|
|
2279
2350
|
const title = approved ? "Approved" : "Rejected";
|
|
2280
2351
|
const summary = approved ? `Approved by ${commenterUsername} via /kici approve` : `Rejected by ${commenterUsername} via /kici reject`;
|
|
2281
2352
|
params.checkStatusPoster.postCheckStatus(params.repoIdentifier, params.commitSha, approved ? "success" : "failure", title, summary, params.credentials).catch((err) => {
|
|
2282
|
-
logger$
|
|
2353
|
+
logger$93.warn("Failed to update check status after approval", { error: toErrorMessage(err) });
|
|
2283
2354
|
});
|
|
2284
2355
|
}
|
|
2285
2356
|
return { handled: true };
|
|
2286
2357
|
}
|
|
2287
|
-
var logger$
|
|
2358
|
+
var logger$93;
|
|
2288
2359
|
var init_comment_handler = __esmMin((() => {
|
|
2289
2360
|
init_trust_resolver();
|
|
2290
|
-
logger$
|
|
2361
|
+
logger$93 = createLogger({ prefix: "comment-handler" });
|
|
2291
2362
|
}));
|
|
2292
2363
|
//#endregion
|
|
2293
2364
|
//#region src/registration/extractor.ts
|
|
@@ -2381,9 +2452,9 @@ function payloadFromObject$1(payload) {
|
|
|
2381
2452
|
function payloadFromRawBody(body) {
|
|
2382
2453
|
return { raw: Buffer.from(body, "utf-8") };
|
|
2383
2454
|
}
|
|
2384
|
-
var logger$
|
|
2455
|
+
var logger$92, EventLogWriter;
|
|
2385
2456
|
var init_event_log$1 = __esmMin((() => {
|
|
2386
|
-
logger$
|
|
2457
|
+
logger$92 = createLogger({ prefix: "event-log" });
|
|
2387
2458
|
EventLogWriter = class EventLogWriter {
|
|
2388
2459
|
db;
|
|
2389
2460
|
logStorage;
|
|
@@ -2419,7 +2490,7 @@ var init_event_log$1 = __esmMin((() => {
|
|
|
2419
2490
|
if (sizeBytes > this.opts.maxPayloadBytes) {
|
|
2420
2491
|
payloadOmitted = true;
|
|
2421
2492
|
payloadOmittedReason = PayloadOmittedReason.enum.size_exceeded;
|
|
2422
|
-
logger$
|
|
2493
|
+
logger$92.warn("Webhook payload exceeds soft cap; recording metadata only", {
|
|
2423
2494
|
deliveryId: info.deliveryId,
|
|
2424
2495
|
sizeBytes,
|
|
2425
2496
|
maxBytes: this.opts.maxPayloadBytes
|
|
@@ -2433,7 +2504,7 @@ var init_event_log$1 = __esmMin((() => {
|
|
|
2433
2504
|
} catch (err) {
|
|
2434
2505
|
payloadOmitted = true;
|
|
2435
2506
|
payloadOmittedReason = PayloadOmittedReason.enum.storage_failed;
|
|
2436
|
-
logger$
|
|
2507
|
+
logger$92.error("Failed to upload event-log payload to object storage", {
|
|
2437
2508
|
deliveryId: info.deliveryId,
|
|
2438
2509
|
orgId: outcome.orgId,
|
|
2439
2510
|
error: toErrorMessage(err)
|
|
@@ -2470,7 +2541,7 @@ var init_event_log$1 = __esmMin((() => {
|
|
|
2470
2541
|
ref: row.ref
|
|
2471
2542
|
})).execute();
|
|
2472
2543
|
} catch (err) {
|
|
2473
|
-
logger$
|
|
2544
|
+
logger$92.error("Failed to record event_log row", {
|
|
2474
2545
|
deliveryId: info.deliveryId,
|
|
2475
2546
|
orgId: outcome.orgId,
|
|
2476
2547
|
error: toErrorMessage(err)
|
|
@@ -3501,7 +3572,7 @@ async function mintCloneTokenForReroute(args) {
|
|
|
3501
3572
|
try {
|
|
3502
3573
|
return await args.bundle.cloneTokenProvider?.createCloneToken(args.repoIdentifier, args.credentials) ?? void 0;
|
|
3503
3574
|
} catch (err) {
|
|
3504
|
-
logger$
|
|
3575
|
+
logger$91.warn("Failed to pre-resolve clone token for cluster reroute, agent may fail clone", {
|
|
3505
3576
|
runId: args.runId,
|
|
3506
3577
|
workflow: args.workflowName,
|
|
3507
3578
|
error: toErrorMessage(err)
|
|
@@ -3512,7 +3583,7 @@ async function mintCloneTokenForReroute(args) {
|
|
|
3512
3583
|
/**
|
|
3513
3584
|
* Build the wrapped dispatcher, overlay info with effective routing/provider,
|
|
3514
3585
|
* persist the webhook payload, fire source-location callbacks, and post the
|
|
3515
|
-
* pending
|
|
3586
|
+
* pending check-run check. Pure side-effects + a typed result bag for
|
|
3516
3587
|
* downstream phases.
|
|
3517
3588
|
*/
|
|
3518
3589
|
async function setupDispatchContext(ctx) {
|
|
@@ -3539,14 +3610,14 @@ async function setupDispatchContext(ctx) {
|
|
|
3539
3610
|
const backend = deps.logStorage.constructor.name;
|
|
3540
3611
|
try {
|
|
3541
3612
|
await deps.logStorage.append(payloadPath, payloadBytes);
|
|
3542
|
-
logger$
|
|
3613
|
+
logger$91.info("Stored webhook payload for run", {
|
|
3543
3614
|
runId,
|
|
3544
3615
|
payloadPath,
|
|
3545
3616
|
bytes: payloadBytes.length,
|
|
3546
3617
|
logStorageBackend: backend
|
|
3547
3618
|
});
|
|
3548
3619
|
} catch (err) {
|
|
3549
|
-
logger$
|
|
3620
|
+
logger$91.error("Failed to store webhook payload", {
|
|
3550
3621
|
runId,
|
|
3551
3622
|
payloadPath,
|
|
3552
3623
|
bytes: payloadBytes.length,
|
|
@@ -3563,10 +3634,10 @@ async function setupDispatchContext(ctx) {
|
|
|
3563
3634
|
const locs = job.steps.map((s) => s.sourceLocation);
|
|
3564
3635
|
if (locs.some((l) => l !== void 0)) deps.onSourceLocationsExtracted(workflow.name, job.name, locs);
|
|
3565
3636
|
}
|
|
3566
|
-
if (deps.
|
|
3637
|
+
if (deps.checkRunReporter) {
|
|
3567
3638
|
const [owner, repo] = repoIdentifier.split("/");
|
|
3568
3639
|
const jobNames = workflow.jobs.filter(isLockStaticJob).map((j) => j.name);
|
|
3569
|
-
await deps.
|
|
3640
|
+
await deps.checkRunReporter.setPendingAwait({
|
|
3570
3641
|
provider: info.provider,
|
|
3571
3642
|
owner,
|
|
3572
3643
|
repo,
|
|
@@ -3622,13 +3693,13 @@ async function probeCaches(ctx, setup, contentHash, lockfileHash, targetPlatform
|
|
|
3622
3693
|
sourceHit = await deps.sourceCache.has(contentHash);
|
|
3623
3694
|
if (sourceHit) {
|
|
3624
3695
|
sourceCacheHitsTotal.add(1);
|
|
3625
|
-
logger$
|
|
3696
|
+
logger$91.info("Source cache hit", {
|
|
3626
3697
|
workflow: workflow.name,
|
|
3627
3698
|
contentHash
|
|
3628
3699
|
});
|
|
3629
3700
|
} else {
|
|
3630
3701
|
sourceCacheMissesTotal.add(1);
|
|
3631
|
-
logger$
|
|
3702
|
+
logger$91.info("Source cache miss", {
|
|
3632
3703
|
workflow: workflow.name,
|
|
3633
3704
|
contentHash
|
|
3634
3705
|
});
|
|
@@ -3643,13 +3714,13 @@ async function probeCaches(ctx, setup, contentHash, lockfileHash, targetPlatform
|
|
|
3643
3714
|
depHit = await deps.depCache.has(lockfileHash, targetPlatform, targetArch);
|
|
3644
3715
|
if (depHit) {
|
|
3645
3716
|
depCacheHitsTotal.add(1);
|
|
3646
|
-
logger$
|
|
3717
|
+
logger$91.info("Dep cache hit", {
|
|
3647
3718
|
workflow: workflow.name,
|
|
3648
3719
|
lockfileHash
|
|
3649
3720
|
});
|
|
3650
3721
|
} else {
|
|
3651
3722
|
depCacheMissesTotal.add(1);
|
|
3652
|
-
logger$
|
|
3723
|
+
logger$91.info("Dep cache miss", {
|
|
3653
3724
|
workflow: workflow.name,
|
|
3654
3725
|
lockfileHash
|
|
3655
3726
|
});
|
|
@@ -3718,9 +3789,9 @@ async function runBuildJob(args) {
|
|
|
3718
3789
|
let rejected = false;
|
|
3719
3790
|
let error;
|
|
3720
3791
|
const coalescingKey = `${contentHash || "none"}:${lockfileHash || "none"}`;
|
|
3721
|
-
if (deps.
|
|
3792
|
+
if (deps.checkRunReporter) {
|
|
3722
3793
|
const [owner, repo] = repoIdentifier.split("/");
|
|
3723
|
-
deps.
|
|
3794
|
+
deps.checkRunReporter.setBuildPending({
|
|
3724
3795
|
provider: setup.info.provider,
|
|
3725
3796
|
owner,
|
|
3726
3797
|
repo,
|
|
@@ -3741,7 +3812,7 @@ async function runBuildJob(args) {
|
|
|
3741
3812
|
const result = await setup.dispatcher.dispatch(buildJobInput);
|
|
3742
3813
|
if (result.status === "rejected") {
|
|
3743
3814
|
const reason = `Build job dispatch rejected: ${result.reason}`;
|
|
3744
|
-
logger$
|
|
3815
|
+
logger$91.error(reason, {
|
|
3745
3816
|
runId,
|
|
3746
3817
|
workflow: workflow.name
|
|
3747
3818
|
});
|
|
@@ -3789,9 +3860,9 @@ async function runBuildJob(args) {
|
|
|
3789
3860
|
async function recordBuildFailure(args) {
|
|
3790
3861
|
const { ctx, setup, buildJobTrackedEarly, err, buildJobId } = args;
|
|
3791
3862
|
const { deps, workflow, repoIdentifier, credentials, event, ref, runId } = ctx;
|
|
3792
|
-
if (deps.
|
|
3863
|
+
if (deps.checkRunReporter) {
|
|
3793
3864
|
const [owner, repo] = repoIdentifier.split("/");
|
|
3794
|
-
deps.
|
|
3865
|
+
deps.checkRunReporter.setBuildComplete({
|
|
3795
3866
|
provider: setup.info.provider,
|
|
3796
3867
|
owner,
|
|
3797
3868
|
repo,
|
|
@@ -3809,7 +3880,7 @@ async function recordBuildFailure(args) {
|
|
|
3809
3880
|
if (buildJobTrackedEarly) await deps.executionTracker.onBuildFailed(runId);
|
|
3810
3881
|
else await deps.executionTracker.onBuildFailedBeforeTracking(runId, workflow.name, setup.info.provider, repoIdentifier, event.targetBranch, ref, setup.effectiveDeliveryId, credentials, setup.info.routingKey, buildTriggerEvent(event.type, event.action), extractCommitMessage$1(setup.info.event, setup.info.payload), toErrorMessage(err));
|
|
3811
3882
|
} catch (cleanupErr) {
|
|
3812
|
-
logger$
|
|
3883
|
+
logger$91.warn("Failed to mark run as failed after build error", {
|
|
3813
3884
|
runId,
|
|
3814
3885
|
error: toErrorMessage(cleanupErr)
|
|
3815
3886
|
});
|
|
@@ -3817,7 +3888,7 @@ async function recordBuildFailure(args) {
|
|
|
3817
3888
|
if (buildJobId) try {
|
|
3818
3889
|
await deps.dispatcher.cancelQueuedJob(buildJobId, `Build failed: ${toErrorMessage(err)}`);
|
|
3819
3890
|
} catch (cleanupErr) {
|
|
3820
|
-
logger$
|
|
3891
|
+
logger$91.warn("Failed to mark build job dispatch_queue row as failed", {
|
|
3821
3892
|
runId,
|
|
3822
3893
|
buildJobId,
|
|
3823
3894
|
error: toErrorMessage(cleanupErr)
|
|
@@ -3831,9 +3902,9 @@ async function recordBuildFailure(args) {
|
|
|
3831
3902
|
async function readPostBuildCacheUrls(args) {
|
|
3832
3903
|
const { ctx, setup, contentHash, lockfileHash, targetPlatform, targetArch } = args;
|
|
3833
3904
|
const { deps, workflow, repoIdentifier, credentials, ref, runId } = ctx;
|
|
3834
|
-
if (deps.
|
|
3905
|
+
if (deps.checkRunReporter) {
|
|
3835
3906
|
const [owner, repo] = repoIdentifier.split("/");
|
|
3836
|
-
deps.
|
|
3907
|
+
deps.checkRunReporter.setBuildComplete({
|
|
3837
3908
|
provider: setup.info.provider,
|
|
3838
3909
|
owner,
|
|
3839
3910
|
repo,
|
|
@@ -3929,7 +4000,7 @@ async function prepareCacheAndBuild(ctx, setup) {
|
|
|
3929
4000
|
if (result.error !== void 0) {
|
|
3930
4001
|
const buildDuration = Number(process.hrtime.bigint() - buildStart) / 1e9;
|
|
3931
4002
|
buildDurationSeconds.record(buildDuration);
|
|
3932
|
-
logger$
|
|
4003
|
+
logger$91.warn("Build failed, skipping execution for workflow", {
|
|
3933
4004
|
workflow: workflow.name,
|
|
3934
4005
|
coalescingKey: `${contentHash || "none"}:${lockfileHash || "none"}`,
|
|
3935
4006
|
error: toErrorMessage(result.error)
|
|
@@ -3943,7 +4014,7 @@ async function prepareCacheAndBuild(ctx, setup) {
|
|
|
3943
4014
|
});
|
|
3944
4015
|
if (hasDynamicEntries) {
|
|
3945
4016
|
buildFailed = true;
|
|
3946
|
-
logger$
|
|
4017
|
+
logger$91.info("Build failed but workflow has dynamic entries, continuing with dynamic dispatch", {
|
|
3947
4018
|
workflow: workflow.name,
|
|
3948
4019
|
dynamicEntryCount: dynamicEntries.length
|
|
3949
4020
|
});
|
|
@@ -3989,7 +4060,7 @@ async function prepareCacheAndBuild(ctx, setup) {
|
|
|
3989
4060
|
depsHash = depResult.hash;
|
|
3990
4061
|
}
|
|
3991
4062
|
}
|
|
3992
|
-
if (!contentHash && deps.sourceCache) logger$
|
|
4063
|
+
if (!contentHash && deps.sourceCache) logger$91.debug("Workflow missing contentHash, agents will compile from source", { workflow: workflow.name });
|
|
3993
4064
|
return {
|
|
3994
4065
|
sourceTarUrl,
|
|
3995
4066
|
sourceTarHash,
|
|
@@ -4017,7 +4088,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
|
|
|
4017
4088
|
const declaredContexts = workflow.contexts ?? [];
|
|
4018
4089
|
if (declaredContexts.length > 0) {
|
|
4019
4090
|
if (!deps.secretResolver) {
|
|
4020
|
-
logger$
|
|
4091
|
+
logger$91.error("Workflow declares secret contexts but secrets subsystem is not configured (KICI_SECRET_KEY missing)", {
|
|
4021
4092
|
workflow: workflow.name,
|
|
4022
4093
|
contexts: declaredContexts
|
|
4023
4094
|
});
|
|
@@ -4036,7 +4107,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
|
|
|
4036
4107
|
resolvedNamespacedSecrets = mergedNamespaced;
|
|
4037
4108
|
}
|
|
4038
4109
|
} catch (err) {
|
|
4039
|
-
logger$
|
|
4110
|
+
logger$91.error("Secret resolution failed, skipping workflow", {
|
|
4040
4111
|
workflow: workflow.name,
|
|
4041
4112
|
error: toErrorMessage(err)
|
|
4042
4113
|
});
|
|
@@ -4054,7 +4125,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
|
|
|
4054
4125
|
public_key: runPublicKeyBase64
|
|
4055
4126
|
}).execute();
|
|
4056
4127
|
} catch (err) {
|
|
4057
|
-
logger$
|
|
4128
|
+
logger$91.warn("Failed to generate ephemeral key pair for run, secret outputs disabled", {
|
|
4058
4129
|
runId,
|
|
4059
4130
|
error: toErrorMessage(err)
|
|
4060
4131
|
});
|
|
@@ -4089,7 +4160,7 @@ async function resolveWorkflowInstallSecrets(ctx, secrets) {
|
|
|
4089
4160
|
if (deps.db) try {
|
|
4090
4161
|
allowHttp = (await deps.db.selectFrom("org_settings").select("allow_http_npm_registries").where("customer_id", "=", resolvedOrgId).executeTakeFirst())?.allow_http_npm_registries ?? false;
|
|
4091
4162
|
} catch (err) {
|
|
4092
|
-
logger$
|
|
4163
|
+
logger$91.warn("Failed to read org_settings.allow_http_npm_registries — defaulting to false", {
|
|
4093
4164
|
runId,
|
|
4094
4165
|
workflow: workflow.name,
|
|
4095
4166
|
error: toErrorMessage(err)
|
|
@@ -4113,20 +4184,20 @@ async function resolveWorkflowInstallSecrets(ctx, secrets) {
|
|
|
4113
4184
|
protectionContext
|
|
4114
4185
|
});
|
|
4115
4186
|
if (result.decision === "reject") {
|
|
4116
|
-
logger$
|
|
4187
|
+
logger$91.error("Workflow install-secrets resolution rejected dispatch", {
|
|
4117
4188
|
runId,
|
|
4118
4189
|
workflow: workflow.name,
|
|
4119
4190
|
reason: result.reason
|
|
4120
4191
|
});
|
|
4121
4192
|
return { skipDispatch: true };
|
|
4122
4193
|
}
|
|
4123
|
-
if (result.contributorStripped) logger$
|
|
4194
|
+
if (result.contributorStripped) logger$91.warn("Skipping registries:/installEnv: resolution for untrusted contributor — install will fail naturally if private deps are required", {
|
|
4124
4195
|
runId,
|
|
4125
4196
|
workflow: workflow.name,
|
|
4126
4197
|
contributor: trustResolution?.contributorUsername,
|
|
4127
4198
|
tier: trustResolution?.tier
|
|
4128
4199
|
});
|
|
4129
|
-
else logger$
|
|
4200
|
+
else logger$91.info("Resolved workflow install secrets", {
|
|
4130
4201
|
runId,
|
|
4131
4202
|
workflow: workflow.name,
|
|
4132
4203
|
registryCount: result.npmRegistries?.length ?? 0,
|
|
@@ -4242,7 +4313,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
|
|
|
4242
4313
|
if (gateResult.action === "reject") {
|
|
4243
4314
|
jobEnvData.rejected = true;
|
|
4244
4315
|
jobEnvData.rejectReason = gateResult.reason ?? "Rejected by protection rules";
|
|
4245
|
-
logger$
|
|
4316
|
+
logger$91.info("Job rejected by protection rules", {
|
|
4246
4317
|
runId,
|
|
4247
4318
|
workflow: workflow.name,
|
|
4248
4319
|
job: lockJob.name,
|
|
@@ -4263,7 +4334,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
|
|
|
4263
4334
|
await deps.heldRunStore.create(resolvedOrgId, heldRunData);
|
|
4264
4335
|
}
|
|
4265
4336
|
jobEnvData.held = true;
|
|
4266
|
-
logger$
|
|
4337
|
+
logger$91.info("Job held by protection rules", {
|
|
4267
4338
|
runId,
|
|
4268
4339
|
workflow: workflow.name,
|
|
4269
4340
|
job: lockJob.name,
|
|
@@ -4274,7 +4345,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
|
|
|
4274
4345
|
if (gateResult.holdType === "security" && bundle.checkStatusPoster) {
|
|
4275
4346
|
const holdSummary = buildSecurityHoldSummary("environment_trust", trustResolution?.tier ?? "unknown", trustResolution?.contributorUsername);
|
|
4276
4347
|
bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "pending", "Held for approval", holdSummary, credentials).catch((err) => {
|
|
4277
|
-
logger$
|
|
4348
|
+
logger$91.warn("Failed to post security hold check", {
|
|
4278
4349
|
runId,
|
|
4279
4350
|
job: lockJob.name,
|
|
4280
4351
|
error: toErrorMessage(err)
|
|
@@ -4293,7 +4364,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
|
|
|
4293
4364
|
jobEnvData.jobNamespacedSecrets = { [environmentName]: envSecrets };
|
|
4294
4365
|
}
|
|
4295
4366
|
} catch (err) {
|
|
4296
|
-
logger$
|
|
4367
|
+
logger$91.error("Per-job secret resolution failed", {
|
|
4297
4368
|
runId,
|
|
4298
4369
|
workflow: workflow.name,
|
|
4299
4370
|
job: lockJob.name,
|
|
@@ -4317,7 +4388,7 @@ async function evaluateJobEnvironments(args) {
|
|
|
4317
4388
|
for (const lockJob of buildPrep.staticJobs) {
|
|
4318
4389
|
const jobEnvData = {};
|
|
4319
4390
|
const { inlineEnvironmentName, inlineEnv, inlineConcurrencyGroup } = evaluateInlineFields(lockJob, inlinePayload);
|
|
4320
|
-
if (inlineEnvironmentName || inlineEnv || inlineConcurrencyGroup) logger$
|
|
4391
|
+
if (inlineEnvironmentName || inlineEnv || inlineConcurrencyGroup) logger$91.debug("Inline evaluation resolved dynamic fields", {
|
|
4321
4392
|
job: lockJob.name,
|
|
4322
4393
|
environment: !!inlineEnvironmentName,
|
|
4323
4394
|
env: !!inlineEnv,
|
|
@@ -4433,12 +4504,12 @@ function logRoleAwareFailure(failure, flatLabels, runId, workflowName) {
|
|
|
4433
4504
|
const roleName = roleLabel.replace("kici:role:", "");
|
|
4434
4505
|
const platformLabels = flatLabels.filter((l) => l.startsWith("kici:os:") || l.startsWith("kici:arch:")).map((l) => l.split(":").pop());
|
|
4435
4506
|
const platformDesc = platformLabels.length > 0 ? platformLabels.join(", ") : "any platform";
|
|
4436
|
-
logger$
|
|
4507
|
+
logger$91.error(`No ${roleName} available for [${platformDesc}]. Add 'roles: [${roleName}]' to a scaler with matching labels, or use default 'roles: [all]'.`, {
|
|
4437
4508
|
runId,
|
|
4438
4509
|
workflow: workflowName,
|
|
4439
4510
|
job: failure.jobName
|
|
4440
4511
|
});
|
|
4441
|
-
} else logger$
|
|
4512
|
+
} else logger$91.warn("Job routing failed", {
|
|
4442
4513
|
runId,
|
|
4443
4514
|
workflow: workflowName,
|
|
4444
4515
|
job: failure.jobName,
|
|
@@ -4470,7 +4541,7 @@ async function preRegisterNonRootJobs(args) {
|
|
|
4470
4541
|
jobName: gatedJob.name,
|
|
4471
4542
|
runsOnLabels
|
|
4472
4543
|
});
|
|
4473
|
-
logger$
|
|
4544
|
+
logger$91.info("Job gated by needs scheduler (cluster path)", {
|
|
4474
4545
|
runId,
|
|
4475
4546
|
workflow: workflow.name,
|
|
4476
4547
|
job: gatedJob.name
|
|
@@ -4482,7 +4553,7 @@ async function clusterRouteRootJobs(args) {
|
|
|
4482
4553
|
const { ctx, setup, buildPrep, buildJobConfig, rootDispatchableJobs, needsGatedCount, dispatchedJobs, rejectedJobs } = args;
|
|
4483
4554
|
const { deps, workflow, repoIdentifier, credentials, event, ref, runId, bundle } = ctx;
|
|
4484
4555
|
if (rootDispatchableJobs.length === 0) {
|
|
4485
|
-
logger$
|
|
4556
|
+
logger$91.info("All dispatchable jobs deferred or needs-gated, skipping coordinator routing", {
|
|
4486
4557
|
runId,
|
|
4487
4558
|
workflow: workflow.name,
|
|
4488
4559
|
needsGated: needsGatedCount
|
|
@@ -4530,7 +4601,7 @@ async function clusterRouteRootJobs(args) {
|
|
|
4530
4601
|
const routeResult = await Promise.race([deps.coordinator.routeJobs(runCtx, jobsToRoute), new Promise((_, reject) => {
|
|
4531
4602
|
routeTimeout = setTimeout(() => reject(/* @__PURE__ */ new Error("routeJobs timed out after 30s")), 3e4);
|
|
4532
4603
|
})]).catch((err) => {
|
|
4533
|
-
logger$
|
|
4604
|
+
logger$91.warn("Coordinator routing timed out, dispatching locally", {
|
|
4534
4605
|
runId,
|
|
4535
4606
|
workflow: workflow.name,
|
|
4536
4607
|
error: toErrorMessage(err)
|
|
@@ -4573,7 +4644,7 @@ async function clusterRouteRootJobs(args) {
|
|
|
4573
4644
|
jobId: syntheticId,
|
|
4574
4645
|
reason: result.reason
|
|
4575
4646
|
});
|
|
4576
|
-
} else if (result.status === "queued-no-backend") logger$
|
|
4647
|
+
} else if (result.status === "queued-no-backend") logger$91.warn("Job has no matching backend (cluster fallback), skipping", {
|
|
4577
4648
|
runId,
|
|
4578
4649
|
workflow: workflow.name,
|
|
4579
4650
|
job: jtr.jobName,
|
|
@@ -4603,7 +4674,7 @@ async function clusterRouteRootJobs(args) {
|
|
|
4603
4674
|
jobName: rerouted.jobName,
|
|
4604
4675
|
runsOnLabels: flatLabels
|
|
4605
4676
|
});
|
|
4606
|
-
logger$
|
|
4677
|
+
logger$91.info("Job rerouted to peer", {
|
|
4607
4678
|
runId,
|
|
4608
4679
|
workflow: workflow.name,
|
|
4609
4680
|
job: rerouted.jobName,
|
|
@@ -4620,7 +4691,7 @@ async function dispatchSingleOrchPath(args) {
|
|
|
4620
4691
|
for (const jobOrFactory of buildPrep.staticJobs) {
|
|
4621
4692
|
const envData = jobEnvironmentData.get(jobOrFactory.name);
|
|
4622
4693
|
if (envData?.rejected) {
|
|
4623
|
-
logger$
|
|
4694
|
+
logger$91.info("Job skipped (rejected by protection rules)", {
|
|
4624
4695
|
runId,
|
|
4625
4696
|
workflow: workflow.name,
|
|
4626
4697
|
job: jobOrFactory.name,
|
|
@@ -4629,7 +4700,7 @@ async function dispatchSingleOrchPath(args) {
|
|
|
4629
4700
|
continue;
|
|
4630
4701
|
}
|
|
4631
4702
|
if (envData?.held) {
|
|
4632
|
-
logger$
|
|
4703
|
+
logger$91.info("Job held by protection rules", {
|
|
4633
4704
|
runId,
|
|
4634
4705
|
workflow: workflow.name,
|
|
4635
4706
|
job: jobOrFactory.name
|
|
@@ -4659,7 +4730,7 @@ async function dispatchSingleOrchPath(args) {
|
|
|
4659
4730
|
jobName: jobOrFactory.name,
|
|
4660
4731
|
runsOnLabels
|
|
4661
4732
|
});
|
|
4662
|
-
logger$
|
|
4733
|
+
logger$91.info("Job gated by needs scheduler (not dispatched yet)", {
|
|
4663
4734
|
runId,
|
|
4664
4735
|
workflow: workflow.name,
|
|
4665
4736
|
job: jobOrFactory.name
|
|
@@ -4678,7 +4749,7 @@ async function dispatchSingleOrchPath(args) {
|
|
|
4678
4749
|
jobId: syntheticId,
|
|
4679
4750
|
reason: result.reason
|
|
4680
4751
|
});
|
|
4681
|
-
} else if (result.status === "queued-no-backend") logger$
|
|
4752
|
+
} else if (result.status === "queued-no-backend") logger$91.warn("Job has no matching backend, skipping execution tracking", {
|
|
4682
4753
|
runId,
|
|
4683
4754
|
workflow: workflow.name,
|
|
4684
4755
|
job: jobOrFactory.name,
|
|
@@ -4690,7 +4761,7 @@ async function dispatchSingleOrchPath(args) {
|
|
|
4690
4761
|
jobName: jobOrFactory.name,
|
|
4691
4762
|
runsOnLabels
|
|
4692
4763
|
});
|
|
4693
|
-
logger$
|
|
4764
|
+
logger$91.info("Job dispatched", {
|
|
4694
4765
|
runId,
|
|
4695
4766
|
workflow: workflow.name,
|
|
4696
4767
|
job: jobOrFactory.name,
|
|
@@ -4710,7 +4781,7 @@ async function dispatchStaticJobs(args) {
|
|
|
4710
4781
|
const { ctx, setup, buildPrep, buildJobConfig, jobEnvironmentData, dispatchedJobs, rejectedJobs } = args;
|
|
4711
4782
|
const { deps, workflow, runId } = ctx;
|
|
4712
4783
|
if (buildPrep.buildFailed) {
|
|
4713
|
-
logger$
|
|
4784
|
+
logger$91.info("Skipping static job dispatch due to build failure", {
|
|
4714
4785
|
runId,
|
|
4715
4786
|
workflow: workflow.name,
|
|
4716
4787
|
staticJobCount: buildPrep.staticJobs.length
|
|
@@ -4763,7 +4834,7 @@ async function recordRunStart(args) {
|
|
|
4763
4834
|
await deps.executionTracker.addJobsToRun(runId, executionJobs, declaredContexts.length > 0 ? [...declaredContexts] : void 0);
|
|
4764
4835
|
} else await deps.executionTracker.onExecutionStarted(runId, workflow.name, setup.info.provider, repoIdentifier, event.targetBranch, ref, setup.effectiveDeliveryId, credentials, summarizeDecision(decision), dispatchedJobs, setup.info.routingKey, declaredContexts.length > 0 ? [...declaredContexts] : void 0, buildTriggerEvent(event.type, event.action), extractCommitMessage$1(setup.info.event, setup.info.payload), void 0, void 0, void 0, setup.workflowConcurrency);
|
|
4765
4836
|
if (runEnvironmentName && deps.db) deps.db.updateTable("execution_runs").set({ environment: runEnvironmentName }).where("run_id", "=", runId).execute().catch((err) => {
|
|
4766
|
-
logger$
|
|
4837
|
+
logger$91.error("Failed to set environment on execution run", {
|
|
4767
4838
|
runId,
|
|
4768
4839
|
environment: runEnvironmentName,
|
|
4769
4840
|
error: toErrorMessage(err)
|
|
@@ -4774,7 +4845,7 @@ async function recordRunStart(args) {
|
|
|
4774
4845
|
lock_file_source: lockFileSource,
|
|
4775
4846
|
contributor_username: trustResolution.contributorUsername
|
|
4776
4847
|
}).where("run_id", "=", runId).execute().catch((err) => {
|
|
4777
|
-
logger$
|
|
4848
|
+
logger$91.error("Failed to set trust context on execution run", {
|
|
4778
4849
|
runId,
|
|
4779
4850
|
error: toErrorMessage(err)
|
|
4780
4851
|
});
|
|
@@ -4786,7 +4857,7 @@ async function insertEdgesAndMarkRejected(args) {
|
|
|
4786
4857
|
if (deps.db && dispatchedJobs.length > 0) try {
|
|
4787
4858
|
await insertEdgesForRun(deps.db, runId, staticJobs);
|
|
4788
4859
|
} catch (err) {
|
|
4789
|
-
logger$
|
|
4860
|
+
logger$91.error("Failed to insert needs edges for run", {
|
|
4790
4861
|
runId,
|
|
4791
4862
|
error: toErrorMessage(err)
|
|
4792
4863
|
});
|
|
@@ -4794,7 +4865,7 @@ async function insertEdgesAndMarkRejected(args) {
|
|
|
4794
4865
|
if (deps.executionTracker && rejectedJobs.length > 0) {
|
|
4795
4866
|
const now = Date.now();
|
|
4796
4867
|
for (const { jobId, reason } of rejectedJobs) deps.executionTracker.onJobStatus(runId, jobId, ExecutionJobStatus.enum.failed, now, void 0, { error: reason }).catch((err) => {
|
|
4797
|
-
logger$
|
|
4868
|
+
logger$91.error("Failed to mark rejected job as failed", {
|
|
4798
4869
|
runId,
|
|
4799
4870
|
jobId,
|
|
4800
4871
|
error: toErrorMessage(err)
|
|
@@ -4826,7 +4897,7 @@ async function applyInitResultEnvironment(args) {
|
|
|
4826
4897
|
jobEnvData.jobNamespacedSecrets = { [initResult.environmentName]: envSecrets };
|
|
4827
4898
|
}
|
|
4828
4899
|
} catch (err) {
|
|
4829
|
-
logger$
|
|
4900
|
+
logger$91.error("Deferred init: secret resolution failed", {
|
|
4830
4901
|
runId,
|
|
4831
4902
|
job: lockJob.name,
|
|
4832
4903
|
error: toErrorMessage(err)
|
|
@@ -4903,7 +4974,7 @@ async function dispatchExecutionAfterInit(args) {
|
|
|
4903
4974
|
jobName: local.jobName,
|
|
4904
4975
|
runsOnLabels: jobInput.runsOnLabels
|
|
4905
4976
|
}]).catch((err) => {
|
|
4906
|
-
logger$
|
|
4977
|
+
logger$91.error("Failed to add deferred init job to execution tracker", {
|
|
4907
4978
|
runId,
|
|
4908
4979
|
error: toErrorMessage(err)
|
|
4909
4980
|
});
|
|
@@ -4924,13 +4995,13 @@ async function dispatchExecutionAfterInit(args) {
|
|
|
4924
4995
|
jobName: lockJob.name,
|
|
4925
4996
|
runsOnLabels: jobInput.runsOnLabels
|
|
4926
4997
|
}]).catch((err) => {
|
|
4927
|
-
logger$
|
|
4998
|
+
logger$91.error("Failed to add deferred init job to execution tracker", {
|
|
4928
4999
|
runId,
|
|
4929
5000
|
error: toErrorMessage(err)
|
|
4930
5001
|
});
|
|
4931
5002
|
});
|
|
4932
5003
|
}
|
|
4933
|
-
logger$
|
|
5004
|
+
logger$91.info("Deferred init job resolved, execution job dispatched", {
|
|
4934
5005
|
runId,
|
|
4935
5006
|
workflow: workflow.name,
|
|
4936
5007
|
job: lockJob.name,
|
|
@@ -4941,14 +5012,14 @@ function startDeferredInitDispatch(args) {
|
|
|
4941
5012
|
const { ctx, setup, buildPrep, buildJobConfig, jobEnvironmentData, deferredInitJobs } = args;
|
|
4942
5013
|
const { deps, workflow, runId } = ctx;
|
|
4943
5014
|
if (deferredInitJobs.length === 0 || !deps.pendingInits) return;
|
|
4944
|
-
logger$
|
|
5015
|
+
logger$91.info("Starting deferred init dispatch", {
|
|
4945
5016
|
runId,
|
|
4946
5017
|
count: deferredInitJobs.length
|
|
4947
5018
|
});
|
|
4948
5019
|
const pendingInits = deps.pendingInits;
|
|
4949
5020
|
for (const { lockJob, initJobInput } of deferredInitJobs) (async () => {
|
|
4950
5021
|
try {
|
|
4951
|
-
logger$
|
|
5022
|
+
logger$91.info("Dispatching deferred init job", {
|
|
4952
5023
|
runId,
|
|
4953
5024
|
workflow: workflow.name,
|
|
4954
5025
|
job: lockJob.name,
|
|
@@ -4974,7 +5045,7 @@ function startDeferredInitDispatch(args) {
|
|
|
4974
5045
|
lockJob
|
|
4975
5046
|
});
|
|
4976
5047
|
} catch (err) {
|
|
4977
|
-
logger$
|
|
5048
|
+
logger$91.error("Deferred init job failed", {
|
|
4978
5049
|
runId,
|
|
4979
5050
|
workflow: workflow.name,
|
|
4980
5051
|
job: lockJob.name,
|
|
@@ -4992,7 +5063,7 @@ async function dispatchEvalJob(args) {
|
|
|
4992
5063
|
const { ctx, setup, buildPrep, dynamicEntry } = args;
|
|
4993
5064
|
const { deps, workflow, repoIdentifier, credentials, event, ref, runId, bundle } = ctx;
|
|
4994
5065
|
const evalJobName = `__dynamic__${workflow.name}__${dynamicEntry.source.index}`;
|
|
4995
|
-
logger$
|
|
5066
|
+
logger$91.info("Dispatching dynamic eval job", {
|
|
4996
5067
|
runId,
|
|
4997
5068
|
workflow: workflow.name,
|
|
4998
5069
|
evalJob: evalJobName,
|
|
@@ -5076,7 +5147,7 @@ async function resolveGeneratedJobConfigs(args) {
|
|
|
5076
5147
|
};
|
|
5077
5148
|
}
|
|
5078
5149
|
} catch (err) {
|
|
5079
|
-
logger$
|
|
5150
|
+
logger$91.error("Dynamic job: secret resolution failed", {
|
|
5080
5151
|
runId,
|
|
5081
5152
|
job: genJob.name,
|
|
5082
5153
|
error: toErrorMessage(err)
|
|
@@ -5116,7 +5187,7 @@ async function resolveGeneratedJobConfigs(args) {
|
|
|
5116
5187
|
runsOnLabels: Array.isArray(genJob.runsOn) ? [...genJob.runsOn] : [genJob.runsOn]
|
|
5117
5188
|
});
|
|
5118
5189
|
} catch (err) {
|
|
5119
|
-
logger$
|
|
5190
|
+
logger$91.error("Failed to resolve secrets for dynamic generated job", {
|
|
5120
5191
|
runId,
|
|
5121
5192
|
job: genJob.name,
|
|
5122
5193
|
error: toErrorMessage(err)
|
|
@@ -5173,7 +5244,7 @@ async function gateAndStoreNonRootGeneratedJobs(args) {
|
|
|
5173
5244
|
jobName: genJob.name,
|
|
5174
5245
|
runsOnLabels
|
|
5175
5246
|
}]);
|
|
5176
|
-
logger$
|
|
5247
|
+
logger$91.info("Generated job gated by cross-domain needs", {
|
|
5177
5248
|
runId,
|
|
5178
5249
|
workflow: workflow.name,
|
|
5179
5250
|
job: genJob.name,
|
|
@@ -5211,13 +5282,13 @@ async function directDispatchGeneratedJobs(args) {
|
|
|
5211
5282
|
jobName: genJob.name,
|
|
5212
5283
|
runsOnLabels
|
|
5213
5284
|
}]);
|
|
5214
|
-
logger$
|
|
5285
|
+
logger$91.info("Dynamic generated job dispatched (direct)", {
|
|
5215
5286
|
runId,
|
|
5216
5287
|
job: genJob.name,
|
|
5217
5288
|
status: genResult.status
|
|
5218
5289
|
});
|
|
5219
5290
|
} catch (err) {
|
|
5220
|
-
logger$
|
|
5291
|
+
logger$91.error("Failed to dispatch dynamic generated job", {
|
|
5221
5292
|
runId,
|
|
5222
5293
|
job: genJob.name,
|
|
5223
5294
|
error: toErrorMessage(err)
|
|
@@ -5278,7 +5349,7 @@ async function routeRootGeneratedJobs(args) {
|
|
|
5278
5349
|
const routeResult = await Promise.race([deps.coordinator.routeJobs(genRunCtx, generatedJobsToRoute), new Promise((_, reject) => {
|
|
5279
5350
|
genRouteTimeout = setTimeout(() => reject(/* @__PURE__ */ new Error("routeJobs timed out after 60s")), 6e4);
|
|
5280
5351
|
})]).catch((err) => {
|
|
5281
|
-
logger$
|
|
5352
|
+
logger$91.warn("Generated job coordinator routing timed out, falling back to direct dispatch", {
|
|
5282
5353
|
runId,
|
|
5283
5354
|
workflow: workflow.name,
|
|
5284
5355
|
error: toErrorMessage(err),
|
|
@@ -5303,25 +5374,25 @@ async function routeRootGeneratedJobs(args) {
|
|
|
5303
5374
|
jobName: local.jobName,
|
|
5304
5375
|
runsOnLabels: matchingConfig?.runsOnLabels ?? []
|
|
5305
5376
|
}]).catch((err) => {
|
|
5306
|
-
logger$
|
|
5377
|
+
logger$91.error("Failed to add generated job to execution tracker", {
|
|
5307
5378
|
runId,
|
|
5308
5379
|
job: local.jobName,
|
|
5309
5380
|
error: toErrorMessage(err)
|
|
5310
5381
|
});
|
|
5311
5382
|
});
|
|
5312
5383
|
}
|
|
5313
|
-
for (const rerouted of routeResult.reroutedJobs) logger$
|
|
5384
|
+
for (const rerouted of routeResult.reroutedJobs) logger$91.info("Generated job rerouted to peer", {
|
|
5314
5385
|
runId,
|
|
5315
5386
|
job: rerouted.jobName,
|
|
5316
5387
|
peerId: rerouted.peerId
|
|
5317
5388
|
});
|
|
5318
|
-
for (const failed of routeResult.failedJobs) logger$
|
|
5389
|
+
for (const failed of routeResult.failedJobs) logger$91.error(`Generated job '${failed.jobName}' routing failed: ${failed.reason}. This indicates a capability advertisement mismatch — the peer was selected based on advertised labels but rejected the job.`, {
|
|
5319
5390
|
runId,
|
|
5320
5391
|
workflow: workflow.name,
|
|
5321
5392
|
job: failed.jobName,
|
|
5322
5393
|
reason: failed.reason
|
|
5323
5394
|
});
|
|
5324
|
-
logger$
|
|
5395
|
+
logger$91.info("Generated jobs routed via coordinator", {
|
|
5325
5396
|
runId,
|
|
5326
5397
|
workflow: workflow.name,
|
|
5327
5398
|
local: routeResult.localJobs.length,
|
|
@@ -5334,7 +5405,7 @@ async function setGroupNameAndResolveEdges(args) {
|
|
|
5334
5405
|
const { deps, runId } = ctx;
|
|
5335
5406
|
if (!deps.db || !groupName) return;
|
|
5336
5407
|
for (const memberName of generatedJobNames) await deps.db.updateTable("execution_jobs").set({ group_name: groupName }).where("run_id", "=", runId).where("job_name", "=", memberName).execute().catch((err) => {
|
|
5337
|
-
logger$
|
|
5408
|
+
logger$91.warn("Failed to set group_name on generated job", {
|
|
5338
5409
|
runId,
|
|
5339
5410
|
jobName: memberName,
|
|
5340
5411
|
groupName,
|
|
@@ -5350,7 +5421,7 @@ async function setGroupNameAndResolveEdges(args) {
|
|
|
5350
5421
|
});
|
|
5351
5422
|
if (dependentStaticJobs.length > 0) {
|
|
5352
5423
|
await resolveGroupEdges(deps.db, runId, groupName, generatedJobNames, dependentStaticJobs);
|
|
5353
|
-
logger$
|
|
5424
|
+
logger$91.info("Group edges resolved", {
|
|
5354
5425
|
runId,
|
|
5355
5426
|
groupName,
|
|
5356
5427
|
members: generatedJobNames.length,
|
|
@@ -5408,7 +5479,7 @@ async function detectAndFailCycles(args) {
|
|
|
5408
5479
|
if (visited >= allJobRows.length) return { cycle: false };
|
|
5409
5480
|
const cycleJobs = [...inDegree.entries()].filter(([, d]) => d > 0).map(([n]) => n);
|
|
5410
5481
|
const cycleTrace = cycleJobs.join(" -> ");
|
|
5411
|
-
logger$
|
|
5482
|
+
logger$91.error("Eval-time cycle detected in job graph", {
|
|
5412
5483
|
runId,
|
|
5413
5484
|
cycleTrace
|
|
5414
5485
|
});
|
|
@@ -5443,7 +5514,7 @@ async function processDynamicEntry(args) {
|
|
|
5443
5514
|
dynamicEntry
|
|
5444
5515
|
});
|
|
5445
5516
|
const generatedJobs = await deps.pendingDynamics.track(evalJobId);
|
|
5446
|
-
logger$
|
|
5517
|
+
logger$91.info("Dynamic eval completed, dispatching generated jobs", {
|
|
5447
5518
|
runId,
|
|
5448
5519
|
workflow: workflow.name,
|
|
5449
5520
|
generatedCount: generatedJobs.length,
|
|
@@ -5490,7 +5561,7 @@ async function processDynamicEntry(args) {
|
|
|
5490
5561
|
memberJobNames: generatedJobs.map((j) => j.name)
|
|
5491
5562
|
});
|
|
5492
5563
|
} catch (err) {
|
|
5493
|
-
logger$
|
|
5564
|
+
logger$91.error("Dynamic eval job failed", {
|
|
5494
5565
|
runId,
|
|
5495
5566
|
workflow: workflow.name,
|
|
5496
5567
|
sourceIndex: dynamicEntry.source.index,
|
|
@@ -5613,7 +5684,7 @@ async function dispatchMatchedWorkflow(ctx) {
|
|
|
5613
5684
|
});
|
|
5614
5685
|
if (buildPrep.dynamicEntries.length > 0 && ctx.deps.pendingDynamics) {
|
|
5615
5686
|
const hasStaticJobs = buildPrep.staticJobs.length > 0;
|
|
5616
|
-
logger$
|
|
5687
|
+
logger$91.info(hasStaticJobs ? "Starting deferred dynamic job dispatch" : "Dynamic-only workflow dispatching eval jobs", {
|
|
5617
5688
|
runId: ctx.runId,
|
|
5618
5689
|
workflow: ctx.workflow.name,
|
|
5619
5690
|
dynamicEntryCount: buildPrep.dynamicEntries.length,
|
|
@@ -5637,7 +5708,7 @@ async function dispatchMatchedWorkflow(ctx) {
|
|
|
5637
5708
|
}
|
|
5638
5709
|
return { dispatchedJobCount: dispatchedJobs.length };
|
|
5639
5710
|
}
|
|
5640
|
-
var logger$
|
|
5711
|
+
var logger$91;
|
|
5641
5712
|
var init_dispatch_matched_workflow = __esmMin((() => {
|
|
5642
5713
|
init_pipeline();
|
|
5643
5714
|
init_environment_store();
|
|
@@ -5647,7 +5718,7 @@ var init_dispatch_matched_workflow = __esmMin((() => {
|
|
|
5647
5718
|
init_needs_scheduler();
|
|
5648
5719
|
init_prometheus();
|
|
5649
5720
|
init_processor();
|
|
5650
|
-
logger$
|
|
5721
|
+
logger$91 = createLogger({ prefix: "pipeline" });
|
|
5651
5722
|
}));
|
|
5652
5723
|
//#endregion
|
|
5653
5724
|
//#region src/pipeline/process-webhook.ts
|
|
@@ -5702,7 +5773,7 @@ async function recordSkipEventLog(info, deps, resolvedOrgId, status) {
|
|
|
5702
5773
|
async function dedupAndResolveProvider(info, deps) {
|
|
5703
5774
|
const resolvedOrgId = await resolveOrgIdSafe(deps, info.routingKey);
|
|
5704
5775
|
if (await deps.dedup.exists(info.deliveryId)) {
|
|
5705
|
-
logger$
|
|
5776
|
+
logger$90.debug("Duplicate webhook, skipping", { deliveryId: info.deliveryId });
|
|
5706
5777
|
dedupHitsTotal.add(1);
|
|
5707
5778
|
await recordSkipEventLog(info, deps, resolvedOrgId, EventLogStatus.enum.duplicate);
|
|
5708
5779
|
return { status: "skip" };
|
|
@@ -5714,7 +5785,7 @@ async function dedupAndResolveProvider(info, deps) {
|
|
|
5714
5785
|
});
|
|
5715
5786
|
const bundle = deps.providerRegistry.getByRoutingKey(info.routingKey);
|
|
5716
5787
|
if (!bundle) {
|
|
5717
|
-
logger$
|
|
5788
|
+
logger$90.debug("Unknown provider, skipping", {
|
|
5718
5789
|
deliveryId: info.deliveryId,
|
|
5719
5790
|
provider: info.provider,
|
|
5720
5791
|
routingKey: info.routingKey
|
|
@@ -5751,7 +5822,7 @@ function invalidateContributorCacheForEvent(info, deps, bundle) {
|
|
|
5751
5822
|
totalDeleted += deps.contributorCache.invalidateByUserInOrg(provider, inv.orgLogin, inv.username);
|
|
5752
5823
|
break;
|
|
5753
5824
|
}
|
|
5754
|
-
logger$
|
|
5825
|
+
logger$90.info("Invalidated contributor cache entries", {
|
|
5755
5826
|
deliveryId: info.deliveryId,
|
|
5756
5827
|
event: info.event,
|
|
5757
5828
|
action: info.action,
|
|
@@ -5766,7 +5837,7 @@ function invalidateContributorCacheForEvent(info, deps, bundle) {
|
|
|
5766
5837
|
async function normalizeWebhookEvent(info, deps, bundle, resolvedOrgId) {
|
|
5767
5838
|
const event = bundle.normalizer.normalizeEvent(info.event, info.action, info.payload);
|
|
5768
5839
|
if (event) return event;
|
|
5769
|
-
logger$
|
|
5840
|
+
logger$90.debug("Unknown event type, skipping", {
|
|
5770
5841
|
deliveryId: info.deliveryId,
|
|
5771
5842
|
event: info.event
|
|
5772
5843
|
});
|
|
@@ -5787,7 +5858,7 @@ async function gatherCrossSourceCandidates(info, deps, resolvedOrgId, inboundEve
|
|
|
5787
5858
|
const remoteVersion = await deps.registrationStore.getVersion();
|
|
5788
5859
|
await deps.registrationIndex.refreshIfNeeded(remoteVersion);
|
|
5789
5860
|
} catch (err) {
|
|
5790
|
-
logger$
|
|
5861
|
+
logger$90.warn("Cross-source dispatch: registration index refresh failed", {
|
|
5791
5862
|
deliveryId: info.deliveryId,
|
|
5792
5863
|
error: toErrorMessage(err)
|
|
5793
5864
|
});
|
|
@@ -5847,7 +5918,7 @@ async function dispatchOneCrossSourceCandidate(args) {
|
|
|
5847
5918
|
const { reg } = candidate;
|
|
5848
5919
|
const syntheticEvent = buildCrossSourceEvent(info, deps, candidate, inboundEventName);
|
|
5849
5920
|
if (!syntheticEvent) {
|
|
5850
|
-
logger$
|
|
5921
|
+
logger$90.debug("Cross-source repo dispatch: unable to normalize inbound event", {
|
|
5851
5922
|
deliveryId: info.deliveryId,
|
|
5852
5923
|
registrationId: reg.id,
|
|
5853
5924
|
routingKey: reg.routingKey,
|
|
@@ -5859,7 +5930,7 @@ async function dispatchOneCrossSourceCandidate(args) {
|
|
|
5859
5930
|
if (matchedDecisions.length === 0) return 0;
|
|
5860
5931
|
const crossDedupKey = `${info.deliveryId}:${reg.id}`;
|
|
5861
5932
|
if (await deps.dedup.exists(crossDedupKey)) {
|
|
5862
|
-
logger$
|
|
5933
|
+
logger$90.debug("Cross-source dispatch: composite dedup hit", {
|
|
5863
5934
|
deliveryId: info.deliveryId,
|
|
5864
5935
|
registrationId: reg.id
|
|
5865
5936
|
});
|
|
@@ -5868,7 +5939,7 @@ async function dispatchOneCrossSourceCandidate(args) {
|
|
|
5868
5939
|
await deps.dedup.mark(crossDedupKey);
|
|
5869
5940
|
const regBundle = deps.providerRegistry.getByRoutingKey(reg.routingKey);
|
|
5870
5941
|
if (!regBundle) {
|
|
5871
|
-
logger$
|
|
5942
|
+
logger$90.warn("Cross-source dispatch: registration bundle not found", {
|
|
5872
5943
|
deliveryId: info.deliveryId,
|
|
5873
5944
|
registrationId: reg.id,
|
|
5874
5945
|
routingKey: reg.routingKey
|
|
@@ -5884,7 +5955,7 @@ async function dispatchOneCrossSourceCandidate(args) {
|
|
|
5884
5955
|
token
|
|
5885
5956
|
};
|
|
5886
5957
|
} catch (err) {
|
|
5887
|
-
logger$
|
|
5958
|
+
logger$90.error("Cross-source dispatch: clone token issuance failed", {
|
|
5888
5959
|
deliveryId: info.deliveryId,
|
|
5889
5960
|
registrationId: reg.id,
|
|
5890
5961
|
routingKey: reg.routingKey,
|
|
@@ -5969,7 +6040,7 @@ async function recordCrossSourceCompletion(args) {
|
|
|
5969
6040
|
timestamp: Date.now()
|
|
5970
6041
|
});
|
|
5971
6042
|
webhooksProcessedTotal.add(1, { result: jobsDispatched > 0 ? "matched" : "skipped" });
|
|
5972
|
-
logger$
|
|
6043
|
+
logger$90.info("Cross-source webhook processed", {
|
|
5973
6044
|
deliveryId: info.deliveryId,
|
|
5974
6045
|
inboundEventName,
|
|
5975
6046
|
registrationsConsidered: candidatesConsidered,
|
|
@@ -6004,7 +6075,7 @@ async function dispatchCrossSourceWorkflows(info, deps, event, resolvedOrgId) {
|
|
|
6004
6075
|
const candidates = await gatherCrossSourceCandidates(info, deps, resolvedOrgId, inboundEventName);
|
|
6005
6076
|
crossSourceFanoutSize.record(candidates.length, { event: inboundEventName });
|
|
6006
6077
|
if (candidates.length === 0) {
|
|
6007
|
-
logger$
|
|
6078
|
+
logger$90.debug("Cross-source: no registrations for event, falling through", {
|
|
6008
6079
|
deliveryId: info.deliveryId,
|
|
6009
6080
|
inboundEventName,
|
|
6010
6081
|
orgId: resolvedOrgId
|
|
@@ -6037,7 +6108,7 @@ async function dispatchCrossSourceWorkflows(info, deps, event, resolvedOrgId) {
|
|
|
6037
6108
|
async function extractRepoAndCredentials(info, deps, bundle, resolvedOrgId) {
|
|
6038
6109
|
const repoIdentifier = bundle.normalizer.extractRepoIdentifier(info.payload);
|
|
6039
6110
|
if (!repoIdentifier) {
|
|
6040
|
-
logger$
|
|
6111
|
+
logger$90.debug("Missing repository info in payload, skipping", { deliveryId: info.deliveryId });
|
|
6041
6112
|
webhooksProcessedTotal.add(1, { result: "skipped" });
|
|
6042
6113
|
await recordSkipEventLog(info, deps, resolvedOrgId, EventLogStatus.enum.received);
|
|
6043
6114
|
return null;
|
|
@@ -6082,7 +6153,7 @@ async function handleApprovalCommentIfPresent(args) {
|
|
|
6082
6153
|
credentials
|
|
6083
6154
|
});
|
|
6084
6155
|
if (result.handled) {
|
|
6085
|
-
logger$
|
|
6156
|
+
logger$90.info("Handled /kici command from comment", {
|
|
6086
6157
|
deliveryId: info.deliveryId,
|
|
6087
6158
|
action: command.action,
|
|
6088
6159
|
commenter: senderUsername,
|
|
@@ -6124,7 +6195,7 @@ async function resolveTrustForPR(args) {
|
|
|
6124
6195
|
credentials
|
|
6125
6196
|
});
|
|
6126
6197
|
const lockFileSource = selectLockFileSource(isPREvent, trustResolution.tier);
|
|
6127
|
-
logger$
|
|
6198
|
+
logger$90.info("Trust tier resolved for PR", {
|
|
6128
6199
|
deliveryId: info.deliveryId,
|
|
6129
6200
|
sender: event.senderUsername,
|
|
6130
6201
|
tier: trustResolution.tier,
|
|
@@ -6136,7 +6207,7 @@ async function resolveTrustForPR(args) {
|
|
|
6136
6207
|
lockFileSource
|
|
6137
6208
|
};
|
|
6138
6209
|
} catch (err) {
|
|
6139
|
-
logger$
|
|
6210
|
+
logger$90.warn("Trust resolution failed, defaulting to base lock file", {
|
|
6140
6211
|
deliveryId: info.deliveryId,
|
|
6141
6212
|
sender: event.senderUsername,
|
|
6142
6213
|
error: toErrorMessage(err)
|
|
@@ -6161,7 +6232,7 @@ async function resolveTrustForPR(args) {
|
|
|
6161
6232
|
*/
|
|
6162
6233
|
async function fetchLockFileWithFallbackPhase(args) {
|
|
6163
6234
|
const { info, deps, bundle, event, resolvedOrgId, repoIdentifier, credentials, ref, isPREvent, lockFileSource } = args;
|
|
6164
|
-
if (!bundle.lockFileFetcher) logger$
|
|
6235
|
+
if (!bundle.lockFileFetcher) logger$90.debug("No lock file fetcher available for inbound provider, relying on fallback", { deliveryId: info.deliveryId });
|
|
6165
6236
|
let lockFile;
|
|
6166
6237
|
let headLockFileForDiff;
|
|
6167
6238
|
let resolvedFallbackBundle;
|
|
@@ -6225,7 +6296,7 @@ async function fetchLockFileWithFallbackPhase(args) {
|
|
|
6225
6296
|
if (resolvedFallbackBundle) {
|
|
6226
6297
|
dispatchBundle = resolvedFallbackBundle;
|
|
6227
6298
|
dispatchCredentials = resolvedFallbackCredentials ?? credentials;
|
|
6228
|
-
logger$
|
|
6299
|
+
logger$90.info("Cross-provider dispatch: using fallback bundle for clone URL + token", {
|
|
6229
6300
|
deliveryId: info.deliveryId,
|
|
6230
6301
|
inboundRoutingKey: info.routingKey,
|
|
6231
6302
|
fallbackRoutingKey: resolvedFallbackRoutingKey,
|
|
@@ -6314,7 +6385,7 @@ async function tryDispatchGlobalsWithoutLockFile(args) {
|
|
|
6314
6385
|
if (deps.globalWorkflowPolicy) {
|
|
6315
6386
|
const sourceCheck = await deps.globalWorkflowPolicy.isSourceRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
|
|
6316
6387
|
if (!sourceCheck.allowed) {
|
|
6317
|
-
logger$
|
|
6388
|
+
logger$90.info("Skipping global workflow dispatch: source repo in deny-list", {
|
|
6318
6389
|
sourceRepo: repoIdentifier,
|
|
6319
6390
|
eventRoutingKey: info.routingKey,
|
|
6320
6391
|
workflowRoutingKey: reg.routingKey,
|
|
@@ -6347,7 +6418,7 @@ async function tryDispatchGlobalsWithoutLockFile(args) {
|
|
|
6347
6418
|
});
|
|
6348
6419
|
for (const { lockJobName, input } of inputs) {
|
|
6349
6420
|
const result = await deps.dispatcher.dispatch(input);
|
|
6350
|
-
if (result.status !== "rejected") logger$
|
|
6421
|
+
if (result.status !== "rejected") logger$90.info("Global workflow job dispatched (no lock file path)", {
|
|
6351
6422
|
runId: globalRunId,
|
|
6352
6423
|
workflow: reg.lockEntry.name,
|
|
6353
6424
|
job: lockJobName,
|
|
@@ -6378,7 +6449,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
|
|
|
6378
6449
|
workflowModifications = detectWorkflowModifications(fullLockFile, headLockFileForDiff);
|
|
6379
6450
|
if (workflowModifications.length > 0) {
|
|
6380
6451
|
const tier = trustResolution?.tier ?? "unknown";
|
|
6381
|
-
logger$
|
|
6452
|
+
logger$90.info("Workflow modifications detected in PR", {
|
|
6382
6453
|
deliveryId: info.deliveryId,
|
|
6383
6454
|
sender: event.senderUsername,
|
|
6384
6455
|
tier,
|
|
@@ -6394,7 +6465,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
|
|
|
6394
6465
|
...workflowModifications.map((m) => `- **${m.changeType}**: \`${m.workflowName}\``)
|
|
6395
6466
|
].join("\n");
|
|
6396
6467
|
bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "neutral", "Workflow changes detected", modSummary, credentials).catch((err) => {
|
|
6397
|
-
logger$
|
|
6468
|
+
logger$90.warn("Failed to post workflow modification check", {
|
|
6398
6469
|
deliveryId: info.deliveryId,
|
|
6399
6470
|
error: toErrorMessage(err)
|
|
6400
6471
|
});
|
|
@@ -6404,7 +6475,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
|
|
|
6404
6475
|
if (securityHold && bundle.checkStatusPoster) {
|
|
6405
6476
|
const holdSummary = buildSecurityHoldSummary(securityHold.reason, trustResolution?.tier ?? "unknown", trustResolution?.contributorUsername);
|
|
6406
6477
|
bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "pending", "Held for approval", holdSummary, credentials).catch((err) => {
|
|
6407
|
-
logger$
|
|
6478
|
+
logger$90.warn("Failed to post security hold check", {
|
|
6408
6479
|
deliveryId: info.deliveryId,
|
|
6409
6480
|
error: toErrorMessage(err)
|
|
6410
6481
|
});
|
|
@@ -6434,7 +6505,7 @@ async function registerWorkflowsOnDefaultBranchPush(args) {
|
|
|
6434
6505
|
if (globalWorkflows.length > 0) {
|
|
6435
6506
|
const permission = await deps.globalWorkflowPolicy.isWorkflowRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
|
|
6436
6507
|
if (!permission.allowed) {
|
|
6437
|
-
logger$
|
|
6508
|
+
logger$90.warn("Skipping global workflow registration: not permitted", {
|
|
6438
6509
|
reason: permission.reason,
|
|
6439
6510
|
repo: repoIdentifier
|
|
6440
6511
|
});
|
|
@@ -6452,7 +6523,7 @@ async function registerWorkflowsOnDefaultBranchPush(args) {
|
|
|
6452
6523
|
const newVersion = await deps.registrationStore.bumpVersion();
|
|
6453
6524
|
await deps.registrationIndex.refreshIfNeeded(newVersion);
|
|
6454
6525
|
if (deps.cronScheduler) await deps.cronScheduler.refreshCache();
|
|
6455
|
-
logger$
|
|
6526
|
+
logger$90.info("Workflow registrations updated", {
|
|
6456
6527
|
repoIdentifier,
|
|
6457
6528
|
workflowCount: registerableWorkflows.length,
|
|
6458
6529
|
registryVersion: newVersion
|
|
@@ -6559,7 +6630,7 @@ async function dispatchGlobalWorkflowsForOtherRepos(args) {
|
|
|
6559
6630
|
if (deps.globalWorkflowPolicy) {
|
|
6560
6631
|
const sourceCheck = await deps.globalWorkflowPolicy.isSourceRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
|
|
6561
6632
|
if (!sourceCheck.allowed) {
|
|
6562
|
-
logger$
|
|
6633
|
+
logger$90.info("Skipping global workflow dispatch: source repo in deny-list", {
|
|
6563
6634
|
sourceRepo: repoIdentifier,
|
|
6564
6635
|
eventRoutingKey: info.routingKey,
|
|
6565
6636
|
workflowRoutingKey: reg.routingKey,
|
|
@@ -6593,7 +6664,7 @@ async function dispatchGlobalWorkflowsForOtherRepos(args) {
|
|
|
6593
6664
|
});
|
|
6594
6665
|
for (const { lockJobName, input } of inputs) {
|
|
6595
6666
|
const result = await deps.dispatcher.dispatch(input);
|
|
6596
|
-
if (result.status !== "rejected") logger$
|
|
6667
|
+
if (result.status !== "rejected") logger$90.info("Global workflow job dispatched", {
|
|
6597
6668
|
runId: globalRunId,
|
|
6598
6669
|
workflow: reg.lockEntry.name,
|
|
6599
6670
|
job: lockJobName,
|
|
@@ -6631,7 +6702,7 @@ async function forwardTracesAndRecordEventLog(args) {
|
|
|
6631
6702
|
webhooksProcessedTotal.add(1, { result: matchedCount > 0 ? "matched" : "skipped" });
|
|
6632
6703
|
if (deps.webhookPayloadDir) {
|
|
6633
6704
|
const payloadDir = join(deps.webhookPayloadDir, repoIdentifier, info.deliveryId);
|
|
6634
|
-
mkdir(payloadDir, { recursive: true }).then(() => writeFile(join(payloadDir, "payload.json"), JSON.stringify(payload, null, 2))).catch((err) => logger$
|
|
6705
|
+
mkdir(payloadDir, { recursive: true }).then(() => writeFile(join(payloadDir, "payload.json"), JSON.stringify(payload, null, 2))).catch((err) => logger$90.warn("Failed to write webhook payload", { error: String(err) }));
|
|
6635
6706
|
}
|
|
6636
6707
|
if (deps.eventLog) {
|
|
6637
6708
|
const firstRunId = matchedRunIds[0] ?? null;
|
|
@@ -6645,7 +6716,7 @@ async function forwardTracesAndRecordEventLog(args) {
|
|
|
6645
6716
|
runId: firstRunId
|
|
6646
6717
|
});
|
|
6647
6718
|
}
|
|
6648
|
-
logger$
|
|
6719
|
+
logger$90.info("Webhook processed", {
|
|
6649
6720
|
deliveryId: info.deliveryId,
|
|
6650
6721
|
event: info.event,
|
|
6651
6722
|
matchedWorkflows: matchedCount,
|
|
@@ -6716,7 +6787,7 @@ async function processWebhook$1(info, deps) {
|
|
|
6716
6787
|
lockFileSource: trust.lockFileSource
|
|
6717
6788
|
});
|
|
6718
6789
|
if (!lockOutcome.lockFile) {
|
|
6719
|
-
logger$
|
|
6790
|
+
logger$90.debug("No lock file found for per-repo matching, checking global workflows", {
|
|
6720
6791
|
deliveryId: info.deliveryId,
|
|
6721
6792
|
repoIdentifier,
|
|
6722
6793
|
ref,
|
|
@@ -6818,7 +6889,7 @@ async function processWebhook$1(info, deps) {
|
|
|
6818
6889
|
ref
|
|
6819
6890
|
});
|
|
6820
6891
|
}
|
|
6821
|
-
var logger$
|
|
6892
|
+
var logger$90;
|
|
6822
6893
|
var init_process_webhook = __esmMin((() => {
|
|
6823
6894
|
init_lock_source();
|
|
6824
6895
|
init_workflow_diff();
|
|
@@ -6828,7 +6899,7 @@ var init_process_webhook = __esmMin((() => {
|
|
|
6828
6899
|
init_prometheus();
|
|
6829
6900
|
init_dispatch_matched_workflow();
|
|
6830
6901
|
init_processor();
|
|
6831
|
-
logger$
|
|
6902
|
+
logger$90 = createLogger({ prefix: "pipeline" });
|
|
6832
6903
|
}));
|
|
6833
6904
|
//#endregion
|
|
6834
6905
|
//#region src/pipeline/processor.ts
|
|
@@ -7014,7 +7085,7 @@ async function resolveLockFileWithFallback(args) {
|
|
|
7014
7085
|
};
|
|
7015
7086
|
const sameTenantRegistrations = registrationIndex.getByOrgAndRepo(customerId, repoIdentifier);
|
|
7016
7087
|
if (sameTenantRegistrations.length === 0) {
|
|
7017
|
-
logger$
|
|
7088
|
+
logger$89.info("Multi-provider fallback: no same-customer registrations for repo", {
|
|
7018
7089
|
deliveryId,
|
|
7019
7090
|
inboundRoutingKey,
|
|
7020
7091
|
customerId,
|
|
@@ -7035,7 +7106,7 @@ async function resolveLockFileWithFallback(args) {
|
|
|
7035
7106
|
fallbackRoutingKeys.push(reg.routingKey);
|
|
7036
7107
|
}
|
|
7037
7108
|
if (fallbackRoutingKeys.length === 0) {
|
|
7038
|
-
logger$
|
|
7109
|
+
logger$89.info("Multi-provider fallback: all same-customer registrations share the inbound routingKey", {
|
|
7039
7110
|
deliveryId,
|
|
7040
7111
|
inboundRoutingKey,
|
|
7041
7112
|
customerId,
|
|
@@ -7057,7 +7128,7 @@ async function resolveLockFileWithFallback(args) {
|
|
|
7057
7128
|
try {
|
|
7058
7129
|
lockFile = await lockFileCache.get(fallbackBundle.lockFileFetcher, repoIdentifier, ref, fallbackCredentials);
|
|
7059
7130
|
} catch (err) {
|
|
7060
|
-
logger$
|
|
7131
|
+
logger$89.warn("Multi-provider fallback: fetcher threw, continuing", {
|
|
7061
7132
|
deliveryId,
|
|
7062
7133
|
inboundRoutingKey,
|
|
7063
7134
|
fallbackRoutingKey,
|
|
@@ -7067,7 +7138,7 @@ async function resolveLockFileWithFallback(args) {
|
|
|
7067
7138
|
continue;
|
|
7068
7139
|
}
|
|
7069
7140
|
if (lockFile) {
|
|
7070
|
-
logger$
|
|
7141
|
+
logger$89.info("Lock file resolved via fallback provider bundle", {
|
|
7071
7142
|
deliveryId,
|
|
7072
7143
|
inboundRoutingKey,
|
|
7073
7144
|
fallbackRoutingKey,
|
|
@@ -7084,7 +7155,7 @@ async function resolveLockFileWithFallback(args) {
|
|
|
7084
7155
|
};
|
|
7085
7156
|
}
|
|
7086
7157
|
}
|
|
7087
|
-
logger$
|
|
7158
|
+
logger$89.info("Multi-provider fallback exhausted without resolving lock file", {
|
|
7088
7159
|
deliveryId,
|
|
7089
7160
|
inboundRoutingKey,
|
|
7090
7161
|
customerId,
|
|
@@ -7108,7 +7179,7 @@ async function resolveOrgId(db, routingKey) {
|
|
|
7108
7179
|
if (source?.customer_id) return source.customer_id;
|
|
7109
7180
|
const genericSource = await db.selectFrom("generic_webhook_sources").select("customer_id").where("routing_key", "=", routingKey).executeTakeFirst();
|
|
7110
7181
|
if (genericSource?.customer_id) return genericSource.customer_id;
|
|
7111
|
-
logger$
|
|
7182
|
+
logger$89.warn("No customer_id found for routing key, falling back to __default__", { routingKey });
|
|
7112
7183
|
return "__default__";
|
|
7113
7184
|
}
|
|
7114
7185
|
/**
|
|
@@ -7230,7 +7301,7 @@ function triggerHasPathFilters(trigger) {
|
|
|
7230
7301
|
async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, coordinator, db) {
|
|
7231
7302
|
const pendingCtx = await consumePendingJobContext(db, runId, jobName);
|
|
7232
7303
|
if (!pendingCtx) {
|
|
7233
|
-
logger$
|
|
7304
|
+
logger$89.warn("No pending dispatch context for ready job (may have been dispatched already)", {
|
|
7234
7305
|
runId,
|
|
7235
7306
|
jobName
|
|
7236
7307
|
});
|
|
@@ -7239,13 +7310,13 @@ async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, co
|
|
|
7239
7310
|
try {
|
|
7240
7311
|
const result = await dispatcher.dispatch(pendingCtx.jobInput);
|
|
7241
7312
|
if (result.status === "rejected") {
|
|
7242
|
-
logger$
|
|
7313
|
+
logger$89.error("Scheduler-dispatched job rejected by dispatcher", {
|
|
7243
7314
|
runId,
|
|
7244
7315
|
jobName,
|
|
7245
7316
|
reason: result.reason
|
|
7246
7317
|
});
|
|
7247
7318
|
if (executionTracker) await executionTracker.onJobStatus(runId, jobName, ExecutionJobStatus.enum.failed, Date.now(), void 0, { error: `dispatch rejected: ${result.reason}` });
|
|
7248
|
-
} else if (result.status === "queued-no-backend") logger$
|
|
7319
|
+
} else if (result.status === "queued-no-backend") logger$89.warn("Scheduler-dispatched job has no matching backend", {
|
|
7249
7320
|
runId,
|
|
7250
7321
|
jobName
|
|
7251
7322
|
});
|
|
@@ -7262,14 +7333,14 @@ async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, co
|
|
|
7262
7333
|
ready_at: /* @__PURE__ */ new Date()
|
|
7263
7334
|
}).where("run_id", "=", runId).where("job_id", "=", result.jobId).execute();
|
|
7264
7335
|
}
|
|
7265
|
-
logger$
|
|
7336
|
+
logger$89.info("Scheduler-dispatched job ready and dispatched", {
|
|
7266
7337
|
runId,
|
|
7267
7338
|
jobName,
|
|
7268
7339
|
jobId: result.jobId
|
|
7269
7340
|
});
|
|
7270
7341
|
}
|
|
7271
7342
|
} catch (err) {
|
|
7272
|
-
logger$
|
|
7343
|
+
logger$89.error("Failed to dispatch scheduler-ready job", {
|
|
7273
7344
|
runId,
|
|
7274
7345
|
jobName,
|
|
7275
7346
|
error: toErrorMessage(err)
|
|
@@ -7306,10 +7377,10 @@ function summarizeDecision(decision) {
|
|
|
7306
7377
|
checksCount: decision.checks.length
|
|
7307
7378
|
};
|
|
7308
7379
|
}
|
|
7309
|
-
var logger$
|
|
7380
|
+
var logger$89, pendingJobContexts;
|
|
7310
7381
|
var init_processor = __esmMin((() => {
|
|
7311
7382
|
init_process_webhook();
|
|
7312
|
-
logger$
|
|
7383
|
+
logger$89 = createLogger({ prefix: "pipeline" });
|
|
7313
7384
|
pendingJobContexts = /* @__PURE__ */ new Map();
|
|
7314
7385
|
}));
|
|
7315
7386
|
//#endregion
|
|
@@ -7325,9 +7396,9 @@ var init_processor = __esmMin((() => {
|
|
|
7325
7396
|
* and are not handled here.
|
|
7326
7397
|
*/
|
|
7327
7398
|
var log_pull_handler_exports = /* @__PURE__ */ __exportAll({ LogPullHandler: () => LogPullHandler$1 });
|
|
7328
|
-
var logger$
|
|
7399
|
+
var logger$88, LogPullHandler$1;
|
|
7329
7400
|
var init_log_pull_handler = __esmMin((() => {
|
|
7330
|
-
logger$
|
|
7401
|
+
logger$88 = createLogger({ prefix: "log-pull" });
|
|
7331
7402
|
LogPullHandler$1 = class {
|
|
7332
7403
|
constructor(deps) {
|
|
7333
7404
|
this.deps = deps;
|
|
@@ -7416,7 +7487,7 @@ var init_log_pull_handler = __esmMin((() => {
|
|
|
7416
7487
|
complete: true
|
|
7417
7488
|
});
|
|
7418
7489
|
} catch (err) {
|
|
7419
|
-
logger$
|
|
7490
|
+
logger$88.error("Error handling log request", {
|
|
7420
7491
|
executionId: msg.executionId,
|
|
7421
7492
|
error: toErrorMessage(err)
|
|
7422
7493
|
});
|
|
@@ -7471,13 +7542,13 @@ async function loadEventLogRange(args) {
|
|
|
7471
7542
|
}
|
|
7472
7543
|
} catch (err) {
|
|
7473
7544
|
if (hotRows.length === 0) {
|
|
7474
|
-
logger$
|
|
7545
|
+
logger$87.error("cold-store fetchRange failed with no hot fallback; propagating", {
|
|
7475
7546
|
routingKey,
|
|
7476
7547
|
error: toErrorMessage(err)
|
|
7477
7548
|
});
|
|
7478
7549
|
throw err;
|
|
7479
7550
|
}
|
|
7480
|
-
logger$
|
|
7551
|
+
logger$87.warn("cold-store fetchRange failed; returning hot rows only", {
|
|
7481
7552
|
routingKey,
|
|
7482
7553
|
error: toErrorMessage(err)
|
|
7483
7554
|
});
|
|
@@ -7503,7 +7574,7 @@ async function loadEventLogByDeliveryId(args) {
|
|
|
7503
7574
|
if (hotRow) return hotRow;
|
|
7504
7575
|
if (!coldStore) return null;
|
|
7505
7576
|
if (!routingKey) {
|
|
7506
|
-
logger$
|
|
7577
|
+
logger$87.warn("cold-store delivery lookup without routingKey hint — scan skipped", {
|
|
7507
7578
|
orgId,
|
|
7508
7579
|
deliveryId
|
|
7509
7580
|
});
|
|
@@ -7519,7 +7590,7 @@ async function loadEventLogByDeliveryId(args) {
|
|
|
7519
7590
|
toTs: warmCutoff
|
|
7520
7591
|
})) if (row.org_id === orgId && row.delivery_id === deliveryId) return row;
|
|
7521
7592
|
} catch (err) {
|
|
7522
|
-
logger$
|
|
7593
|
+
logger$87.warn("cold-store fetchRange failed for delivery lookup", {
|
|
7523
7594
|
routingKey,
|
|
7524
7595
|
orgId,
|
|
7525
7596
|
deliveryId,
|
|
@@ -7528,9 +7599,9 @@ async function loadEventLogByDeliveryId(args) {
|
|
|
7528
7599
|
}
|
|
7529
7600
|
return null;
|
|
7530
7601
|
}
|
|
7531
|
-
var logger$
|
|
7602
|
+
var logger$87, EVENT_LOG_WARM_TTL_DAYS;
|
|
7532
7603
|
var init_load_event_log_range = __esmMin((() => {
|
|
7533
|
-
logger$
|
|
7604
|
+
logger$87 = createLogger({ prefix: "load-event-log-range" });
|
|
7534
7605
|
EVENT_LOG_WARM_TTL_DAYS = 30;
|
|
7535
7606
|
}));
|
|
7536
7607
|
//#endregion
|
|
@@ -7593,7 +7664,7 @@ function parsePolicyColumn(raw) {
|
|
|
7593
7664
|
const candidate = typeof raw === "string" ? safeParseJson(raw) : raw;
|
|
7594
7665
|
const result = dashboardWritePolicyMapSchema.safeParse(candidate);
|
|
7595
7666
|
if (!result.success) {
|
|
7596
|
-
logger$
|
|
7667
|
+
logger$86.warn("Invalid dashboard_write_policy column shape — treating as empty", { error: result.error.message });
|
|
7597
7668
|
return {};
|
|
7598
7669
|
}
|
|
7599
7670
|
return result.data;
|
|
@@ -7735,9 +7806,9 @@ async function resetDashboardWritePolicy(db, customerId, options) {
|
|
|
7735
7806
|
if (Object.keys(updates).length === 0) return current;
|
|
7736
7807
|
return setDashboardWritePolicy(db, customerId, updates, options);
|
|
7737
7808
|
}
|
|
7738
|
-
var logger$
|
|
7809
|
+
var logger$86, CACHE_TTL_MS, cache, dashboardWritePolicyEvents$1, DashboardWritePolicyDisabledError;
|
|
7739
7810
|
var init_dashboard_write_policy = __esmMin((() => {
|
|
7740
|
-
logger$
|
|
7811
|
+
logger$86 = createLogger({ prefix: "dashboard-write-policy" });
|
|
7741
7812
|
CACHE_TTL_MS = 3e4;
|
|
7742
7813
|
cache = /* @__PURE__ */ new Map();
|
|
7743
7814
|
dashboardWritePolicyEvents$1 = new EventEmitter();
|
|
@@ -7815,11 +7886,11 @@ function decodeEventLogCursor(s) {
|
|
|
7815
7886
|
return null;
|
|
7816
7887
|
}
|
|
7817
7888
|
}
|
|
7818
|
-
var logger$
|
|
7889
|
+
var logger$85, DashboardHandler$1;
|
|
7819
7890
|
var init_handler = __esmMin((() => {
|
|
7820
7891
|
init_load_event_log_range();
|
|
7821
7892
|
init_dashboard_write_policy();
|
|
7822
|
-
logger$
|
|
7893
|
+
logger$85 = createLogger({ prefix: "dashboard-handler" });
|
|
7823
7894
|
DashboardHandler$1 = class {
|
|
7824
7895
|
db;
|
|
7825
7896
|
logStorage;
|
|
@@ -8074,7 +8145,7 @@ var init_handler = __esmMin((() => {
|
|
|
8074
8145
|
...trustContext && { trustContext }
|
|
8075
8146
|
});
|
|
8076
8147
|
if (!validated.success) {
|
|
8077
|
-
logger$
|
|
8148
|
+
logger$85.error("Outgoing dashboard.run.detail response validation failed", {
|
|
8078
8149
|
runId: msg.runId,
|
|
8079
8150
|
errors: validated.error.issues
|
|
8080
8151
|
});
|
|
@@ -8101,7 +8172,7 @@ var init_handler = __esmMin((() => {
|
|
|
8101
8172
|
...validated.data.trustContext && { trustContext: validated.data.trustContext }
|
|
8102
8173
|
});
|
|
8103
8174
|
} catch (err) {
|
|
8104
|
-
logger$
|
|
8175
|
+
logger$85.error("Error handling dashboard.run.detail", {
|
|
8105
8176
|
runId: msg.runId,
|
|
8106
8177
|
error: toErrorMessage(err)
|
|
8107
8178
|
});
|
|
@@ -8159,7 +8230,7 @@ var init_handler = __esmMin((() => {
|
|
|
8159
8230
|
totalLines: lines.length
|
|
8160
8231
|
});
|
|
8161
8232
|
if (!validated.success) {
|
|
8162
|
-
logger$
|
|
8233
|
+
logger$85.error("Outgoing dashboard.step.logs response validation failed", {
|
|
8163
8234
|
runId: msg.runId,
|
|
8164
8235
|
jobId: msg.jobId,
|
|
8165
8236
|
stepIndex: msg.stepIndex,
|
|
@@ -8189,7 +8260,7 @@ var init_handler = __esmMin((() => {
|
|
|
8189
8260
|
totalLines: validated.data.totalLines
|
|
8190
8261
|
});
|
|
8191
8262
|
} catch (err) {
|
|
8192
|
-
logger$
|
|
8263
|
+
logger$85.error("Error handling dashboard.step.logs", {
|
|
8193
8264
|
runId: msg.runId,
|
|
8194
8265
|
jobId: msg.jobId,
|
|
8195
8266
|
stepIndex: msg.stepIndex,
|
|
@@ -8216,7 +8287,7 @@ var init_handler = __esmMin((() => {
|
|
|
8216
8287
|
const ctx = this.contextOrFallback(await this.resolveOrgForRun(msg.runId));
|
|
8217
8288
|
const payloadPath = `executions/${msg.runId}/webhook-payload.json`;
|
|
8218
8289
|
const backend = this.logStorage.constructor.name;
|
|
8219
|
-
logger$
|
|
8290
|
+
logger$85.info("Dashboard payload request received", {
|
|
8220
8291
|
requestId: msg.requestId,
|
|
8221
8292
|
runId: msg.runId,
|
|
8222
8293
|
payloadPath,
|
|
@@ -8226,7 +8297,7 @@ var init_handler = __esmMin((() => {
|
|
|
8226
8297
|
try {
|
|
8227
8298
|
const result = await this.logStorage.read(payloadPath);
|
|
8228
8299
|
if (!result.data) {
|
|
8229
|
-
logger$
|
|
8300
|
+
logger$85.info("Dashboard payload not found", {
|
|
8230
8301
|
requestId: msg.requestId,
|
|
8231
8302
|
runId: msg.runId,
|
|
8232
8303
|
payloadPath,
|
|
@@ -8248,7 +8319,7 @@ var init_handler = __esmMin((() => {
|
|
|
8248
8319
|
try {
|
|
8249
8320
|
payload = JSON.parse(result.data);
|
|
8250
8321
|
} catch {
|
|
8251
|
-
logger$
|
|
8322
|
+
logger$85.error("Dashboard payload data is not valid JSON", {
|
|
8252
8323
|
requestId: msg.requestId,
|
|
8253
8324
|
runId: msg.runId,
|
|
8254
8325
|
payloadPath,
|
|
@@ -8266,7 +8337,7 @@ var init_handler = __esmMin((() => {
|
|
|
8266
8337
|
});
|
|
8267
8338
|
return;
|
|
8268
8339
|
}
|
|
8269
|
-
logger$
|
|
8340
|
+
logger$85.info("Dashboard payload served", {
|
|
8270
8341
|
requestId: msg.requestId,
|
|
8271
8342
|
runId: msg.runId,
|
|
8272
8343
|
bytes: result.data.length,
|
|
@@ -8282,7 +8353,7 @@ var init_handler = __esmMin((() => {
|
|
|
8282
8353
|
payload
|
|
8283
8354
|
});
|
|
8284
8355
|
} catch (err) {
|
|
8285
|
-
logger$
|
|
8356
|
+
logger$85.error("Error handling dashboard.payload", {
|
|
8286
8357
|
requestId: msg.requestId,
|
|
8287
8358
|
runId: msg.runId,
|
|
8288
8359
|
payloadPath,
|
|
@@ -8370,7 +8441,7 @@ var init_handler = __esmMin((() => {
|
|
|
8370
8441
|
newRunId: result.newRunId
|
|
8371
8442
|
});
|
|
8372
8443
|
} catch (err) {
|
|
8373
|
-
logger$
|
|
8444
|
+
logger$85.error("Error handling run.rerun.request", {
|
|
8374
8445
|
runId: msg.runId,
|
|
8375
8446
|
error: toErrorMessage(err)
|
|
8376
8447
|
});
|
|
@@ -8405,7 +8476,7 @@ var init_handler = __esmMin((() => {
|
|
|
8405
8476
|
cancelledJobs: result.cancelledJobs
|
|
8406
8477
|
});
|
|
8407
8478
|
} catch (err) {
|
|
8408
|
-
logger$
|
|
8479
|
+
logger$85.error("Error handling run.cancel.request", {
|
|
8409
8480
|
runId: msg.runId,
|
|
8410
8481
|
error: toErrorMessage(err)
|
|
8411
8482
|
});
|
|
@@ -8486,7 +8557,7 @@ var init_handler = __esmMin((() => {
|
|
|
8486
8557
|
nextCursor
|
|
8487
8558
|
});
|
|
8488
8559
|
} catch (err) {
|
|
8489
|
-
logger$
|
|
8560
|
+
logger$85.error("Error handling dashboard.event-log.list", {
|
|
8490
8561
|
orgId: msg.orgId,
|
|
8491
8562
|
error: toErrorMessage(err)
|
|
8492
8563
|
});
|
|
@@ -8556,7 +8627,7 @@ var init_handler = __esmMin((() => {
|
|
|
8556
8627
|
nextCursor: result.nextCursor
|
|
8557
8628
|
});
|
|
8558
8629
|
} catch (err) {
|
|
8559
|
-
logger$
|
|
8630
|
+
logger$85.error("Error handling dashboard.access-log.list", {
|
|
8560
8631
|
orgId: msg.orgId,
|
|
8561
8632
|
error: toErrorMessage(err)
|
|
8562
8633
|
});
|
|
@@ -8619,7 +8690,7 @@ var init_handler = __esmMin((() => {
|
|
|
8619
8690
|
item
|
|
8620
8691
|
});
|
|
8621
8692
|
} catch (err) {
|
|
8622
|
-
logger$
|
|
8693
|
+
logger$85.error("Error handling dashboard.event-log.detail", {
|
|
8623
8694
|
orgId: msg.orgId,
|
|
8624
8695
|
deliveryId: msg.deliveryId,
|
|
8625
8696
|
error: toErrorMessage(err)
|
|
@@ -8678,7 +8749,7 @@ var init_handler = __esmMin((() => {
|
|
|
8678
8749
|
routingKey: msg.routingKey
|
|
8679
8750
|
});
|
|
8680
8751
|
} catch (err) {
|
|
8681
|
-
logger$
|
|
8752
|
+
logger$85.error("Error loading event-log row for payload stream", {
|
|
8682
8753
|
orgId: msg.orgId,
|
|
8683
8754
|
deliveryId: msg.deliveryId,
|
|
8684
8755
|
error: toErrorMessage(err)
|
|
@@ -8711,7 +8782,7 @@ var init_handler = __esmMin((() => {
|
|
|
8711
8782
|
const result = await this.logStorage.read(row.payload_key);
|
|
8712
8783
|
decompressed = gunzipSync(Buffer.from(result.data, "binary"));
|
|
8713
8784
|
} catch (err) {
|
|
8714
|
-
logger$
|
|
8785
|
+
logger$85.warn("Failed to read or decode event-log payload for stream", {
|
|
8715
8786
|
deliveryId: msg.deliveryId,
|
|
8716
8787
|
payloadKey: row.payload_key,
|
|
8717
8788
|
error: toErrorMessage(err)
|
|
@@ -8813,7 +8884,7 @@ var init_handler = __esmMin((() => {
|
|
|
8813
8884
|
nextCursor
|
|
8814
8885
|
});
|
|
8815
8886
|
} catch (err) {
|
|
8816
|
-
logger$
|
|
8887
|
+
logger$85.error("Error handling dashboard.event-dlq.list", {
|
|
8817
8888
|
orgId: msg.orgId,
|
|
8818
8889
|
error: toErrorMessage(err)
|
|
8819
8890
|
});
|
|
@@ -8854,7 +8925,7 @@ var init_handler = __esmMin((() => {
|
|
|
8854
8925
|
total
|
|
8855
8926
|
});
|
|
8856
8927
|
} catch (err) {
|
|
8857
|
-
logger$
|
|
8928
|
+
logger$85.error("Error handling dashboard.event-dlq.count", {
|
|
8858
8929
|
orgId: msg.orgId,
|
|
8859
8930
|
error: toErrorMessage(err)
|
|
8860
8931
|
});
|
|
@@ -8915,7 +8986,7 @@ var init_handler = __esmMin((() => {
|
|
|
8915
8986
|
try {
|
|
8916
8987
|
await sql`SELECT pg_notify('kici_event_channel', ${msg.eventId})`.execute(this.eventStore.getDb());
|
|
8917
8988
|
} catch (err) {
|
|
8918
|
-
logger$
|
|
8989
|
+
logger$85.warn("pg_notify failed after DLQ retry; scanner will catch up", {
|
|
8919
8990
|
eventId: msg.eventId,
|
|
8920
8991
|
error: toErrorMessage(err)
|
|
8921
8992
|
});
|
|
@@ -8930,7 +9001,7 @@ var init_handler = __esmMin((() => {
|
|
|
8930
9001
|
retried: true
|
|
8931
9002
|
});
|
|
8932
9003
|
} catch (err) {
|
|
8933
|
-
logger$
|
|
9004
|
+
logger$85.error("Error handling dashboard.event-dlq.retry", {
|
|
8934
9005
|
orgId: msg.orgId,
|
|
8935
9006
|
eventId: msg.eventId,
|
|
8936
9007
|
error: toErrorMessage(err)
|
|
@@ -9001,7 +9072,7 @@ var init_handler = __esmMin((() => {
|
|
|
9001
9072
|
discarded: true
|
|
9002
9073
|
});
|
|
9003
9074
|
} catch (err) {
|
|
9004
|
-
logger$
|
|
9075
|
+
logger$85.error("Error handling dashboard.event-dlq.discard", {
|
|
9005
9076
|
orgId: msg.orgId,
|
|
9006
9077
|
eventId: msg.eventId,
|
|
9007
9078
|
error: toErrorMessage(err)
|
|
@@ -9035,7 +9106,7 @@ var init_handler = __esmMin((() => {
|
|
|
9035
9106
|
newRunId: result.newRunId
|
|
9036
9107
|
});
|
|
9037
9108
|
} catch (err) {
|
|
9038
|
-
logger$
|
|
9109
|
+
logger$85.error("Error handling run.manual_schedule.request", {
|
|
9039
9110
|
registrationId: msg.registrationId,
|
|
9040
9111
|
error: toErrorMessage(err)
|
|
9041
9112
|
});
|
|
@@ -9080,7 +9151,7 @@ var init_handler = __esmMin((() => {
|
|
|
9080
9151
|
if (r.run_id === runId) rows.push(r);
|
|
9081
9152
|
}
|
|
9082
9153
|
} catch (err) {
|
|
9083
|
-
logger$
|
|
9154
|
+
logger$85.warn("cold-store fetchRange failed for run-detail", {
|
|
9084
9155
|
table,
|
|
9085
9156
|
runId,
|
|
9086
9157
|
error: toErrorMessage(err)
|
|
@@ -9417,10 +9488,10 @@ async function loadActiveGenericRoutingKeys$1(db) {
|
|
|
9417
9488
|
has_git_config: row.git_config !== null
|
|
9418
9489
|
}));
|
|
9419
9490
|
}
|
|
9420
|
-
var logger$
|
|
9491
|
+
var logger$84, GenericSourceManager;
|
|
9421
9492
|
var init_generic_sources = __esmMin((() => {
|
|
9422
9493
|
init_config$4();
|
|
9423
|
-
logger$
|
|
9494
|
+
logger$84 = createLogger({ prefix: "generic-sources" });
|
|
9424
9495
|
GenericSourceManager = class {
|
|
9425
9496
|
constructor(db) {
|
|
9426
9497
|
this.db = db;
|
|
@@ -9464,7 +9535,7 @@ var init_generic_sources = __esmMin((() => {
|
|
|
9464
9535
|
git_config: validatedGitConfig ? JSON.stringify(validatedGitConfig) : null
|
|
9465
9536
|
};
|
|
9466
9537
|
const result = await this.db.insertInto("generic_webhook_sources").values(row).returningAll().executeTakeFirstOrThrow();
|
|
9467
|
-
logger$
|
|
9538
|
+
logger$84.info("Generic webhook source created", {
|
|
9468
9539
|
id: result.id,
|
|
9469
9540
|
orgId: input.orgId,
|
|
9470
9541
|
name: input.name,
|
|
@@ -9550,7 +9621,7 @@ var init_generic_sources = __esmMin((() => {
|
|
|
9550
9621
|
...updates,
|
|
9551
9622
|
updated_at: sql`now()`
|
|
9552
9623
|
}).where("id", "=", id).where("deleted_at", "is", null).returningAll().executeTakeFirst();
|
|
9553
|
-
if (result) logger$
|
|
9624
|
+
if (result) logger$84.info("Generic webhook source updated", {
|
|
9554
9625
|
id,
|
|
9555
9626
|
fields: Object.keys(updates)
|
|
9556
9627
|
});
|
|
@@ -9561,14 +9632,14 @@ var init_generic_sources = __esmMin((() => {
|
|
|
9561
9632
|
*/
|
|
9562
9633
|
async softDelete(id) {
|
|
9563
9634
|
await this.db.updateTable("generic_webhook_sources").set({ deleted_at: sql`now()` }).where("id", "=", id).where("deleted_at", "is", null).execute();
|
|
9564
|
-
logger$
|
|
9635
|
+
logger$84.info("Generic webhook source soft-deleted", { id });
|
|
9565
9636
|
}
|
|
9566
9637
|
/**
|
|
9567
9638
|
* Hard delete a source (removes the row entirely).
|
|
9568
9639
|
*/
|
|
9569
9640
|
async hardDelete(id) {
|
|
9570
9641
|
await this.db.deleteFrom("generic_webhook_sources").where("id", "=", id).execute();
|
|
9571
|
-
logger$
|
|
9642
|
+
logger$84.info("Generic webhook source hard-deleted", { id });
|
|
9572
9643
|
}
|
|
9573
9644
|
/**
|
|
9574
9645
|
* Enable a source.
|
|
@@ -9578,7 +9649,7 @@ var init_generic_sources = __esmMin((() => {
|
|
|
9578
9649
|
enabled: true,
|
|
9579
9650
|
updated_at: sql`now()`
|
|
9580
9651
|
}).where("id", "=", id).where("deleted_at", "is", null).execute();
|
|
9581
|
-
logger$
|
|
9652
|
+
logger$84.info("Generic webhook source enabled", { id });
|
|
9582
9653
|
}
|
|
9583
9654
|
/**
|
|
9584
9655
|
* Disable a source.
|
|
@@ -9588,7 +9659,7 @@ var init_generic_sources = __esmMin((() => {
|
|
|
9588
9659
|
enabled: false,
|
|
9589
9660
|
updated_at: sql`now()`
|
|
9590
9661
|
}).where("id", "=", id).where("deleted_at", "is", null).execute();
|
|
9591
|
-
logger$
|
|
9662
|
+
logger$84.info("Generic webhook source disabled", { id });
|
|
9592
9663
|
}
|
|
9593
9664
|
/**
|
|
9594
9665
|
* Check if a request is a duplicate within the dedup window.
|
|
@@ -9820,9 +9891,9 @@ var init_normalizer$3 = __esmMin((() => {
|
|
|
9820
9891
|
* kici.lock.json directly from the local filesystem. Used when the internal
|
|
9821
9892
|
* provider processes webhooks for repos accessible via file:// URLs.
|
|
9822
9893
|
*/
|
|
9823
|
-
var logger$
|
|
9894
|
+
var logger$83, InternalLockFileFetcher;
|
|
9824
9895
|
var init_lock_file_fetcher = __esmMin((() => {
|
|
9825
|
-
logger$
|
|
9896
|
+
logger$83 = createLogger({ prefix: "internal-lock-file" });
|
|
9826
9897
|
InternalLockFileFetcher = class {
|
|
9827
9898
|
provider = "internal";
|
|
9828
9899
|
/**
|
|
@@ -9850,10 +9921,10 @@ var init_lock_file_fetcher = __esmMin((() => {
|
|
|
9850
9921
|
const content = await readFile(lockFilePath, "utf-8");
|
|
9851
9922
|
const lockFile = JSON.parse(content);
|
|
9852
9923
|
if (typeof lockFile.schemaVersion !== "number") {
|
|
9853
|
-
logger$
|
|
9924
|
+
logger$83.warn("Invalid lock file: missing or invalid schemaVersion", { lockFilePath });
|
|
9854
9925
|
return null;
|
|
9855
9926
|
}
|
|
9856
|
-
logger$
|
|
9927
|
+
logger$83.info("Lock file fetched from filesystem", {
|
|
9857
9928
|
lockFilePath,
|
|
9858
9929
|
schemaVersion: lockFile.schemaVersion,
|
|
9859
9930
|
workflowCount: lockFile.workflows.length
|
|
@@ -9861,10 +9932,10 @@ var init_lock_file_fetcher = __esmMin((() => {
|
|
|
9861
9932
|
return lockFile;
|
|
9862
9933
|
} catch (err) {
|
|
9863
9934
|
if (err.code === "ENOENT") {
|
|
9864
|
-
logger$
|
|
9935
|
+
logger$83.info("Lock file not found", { lockFilePath });
|
|
9865
9936
|
return null;
|
|
9866
9937
|
}
|
|
9867
|
-
logger$
|
|
9938
|
+
logger$83.error("Failed to read lock file", {
|
|
9868
9939
|
lockFilePath,
|
|
9869
9940
|
error: toErrorMessage(err)
|
|
9870
9941
|
});
|
|
@@ -9952,13 +10023,6 @@ var init_internal = __esmMin((() => {
|
|
|
9952
10023
|
* Extracted to eliminate code duplication between the two entry points.
|
|
9953
10024
|
* Both entry points import these helpers instead of maintaining separate copies.
|
|
9954
10025
|
*/
|
|
9955
|
-
var entry_helpers_exports = /* @__PURE__ */ __exportAll({
|
|
9956
|
-
canServeGenericProviderType: () => canServeGenericProviderType$1,
|
|
9957
|
-
diffProviderSources: () => diffProviderSources,
|
|
9958
|
-
extractRepoIdentifier: () => extractRepoIdentifier,
|
|
9959
|
-
genericProviderTypeToSubtype: () => genericProviderTypeToSubtype$1,
|
|
9960
|
-
registerInternalProviderIfConfigured: () => registerInternalProviderIfConfigured
|
|
9961
|
-
});
|
|
9962
10026
|
/**
|
|
9963
10027
|
* Map a generic_webhook_sources `provider_type` (plus optional `git_config`
|
|
9964
10028
|
* presence) to the canonical {@link SourceSubtype}.
|
|
@@ -9969,7 +10033,7 @@ var entry_helpers_exports = /* @__PURE__ */ __exportAll({
|
|
|
9969
10033
|
* subtype emitted to Platform stays consistent with what the dashboard
|
|
9970
10034
|
* eventually renders.
|
|
9971
10035
|
*/
|
|
9972
|
-
function genericProviderTypeToSubtype
|
|
10036
|
+
function genericProviderTypeToSubtype(providerType, options) {
|
|
9973
10037
|
if (options.hasGitConfig) return SourceSubtype.enum.universal_git;
|
|
9974
10038
|
if (providerType === "universal-git") return SourceSubtype.enum.universal_git;
|
|
9975
10039
|
if (providerType === "internal") return SourceSubtype.enum.internal;
|
|
@@ -10054,7 +10118,7 @@ function registerInternalProviderIfConfigured(registry, config) {
|
|
|
10054
10118
|
* the same base dir).
|
|
10055
10119
|
* - Any unknown provider_type returns false to fail closed.
|
|
10056
10120
|
*/
|
|
10057
|
-
function canServeGenericProviderType
|
|
10121
|
+
function canServeGenericProviderType(providerType, config) {
|
|
10058
10122
|
if (providerType === "generic" || providerType === "universal-git") return true;
|
|
10059
10123
|
if (providerType === "internal") {
|
|
10060
10124
|
const path = config.internalProviderRepoPath;
|
|
@@ -10071,6 +10135,53 @@ var init_entry_helpers = __esmMin((() => {
|
|
|
10071
10135
|
init_internal();
|
|
10072
10136
|
}));
|
|
10073
10137
|
//#endregion
|
|
10138
|
+
//#region src/sources/build-platform-sources.ts
|
|
10139
|
+
var build_platform_sources_exports = /* @__PURE__ */ __exportAll({ buildPlatformProviderSources: () => buildPlatformProviderSources$1 });
|
|
10140
|
+
/**
|
|
10141
|
+
* Build the full provider-source list the orchestrator advertises to the
|
|
10142
|
+
* Platform: GitHub-app sources from the {@link SourceManager} plus every
|
|
10143
|
+
* *servable* generic-webhook source.
|
|
10144
|
+
*
|
|
10145
|
+
* Used both at boot and by the live republish closure (platform mode). It MUST
|
|
10146
|
+
* return the complete set every time — a live source change re-sends the whole
|
|
10147
|
+
* list via `platformClient.updateSources()`, which diffs against the previously
|
|
10148
|
+
* sent set; a partial list would make the Platform deregister the sources that
|
|
10149
|
+
* happened to be omitted.
|
|
10150
|
+
*
|
|
10151
|
+
* The generic-row loader is injected (rather than taking a `db`) so the merge
|
|
10152
|
+
* logic is unit-testable without a live database.
|
|
10153
|
+
*/
|
|
10154
|
+
async function buildPlatformProviderSources$1(sourceManager, loadGenericRows, config) {
|
|
10155
|
+
const providerSources = [...sourceManager.getSources()];
|
|
10156
|
+
try {
|
|
10157
|
+
const genericRows = await loadGenericRows();
|
|
10158
|
+
const skipped = [];
|
|
10159
|
+
for (const gs of genericRows) if (canServeGenericProviderType(gs.provider_type, config)) providerSources.push({
|
|
10160
|
+
provider: "generic",
|
|
10161
|
+
routingKey: gs.routing_key,
|
|
10162
|
+
name: gs.name,
|
|
10163
|
+
subtype: genericProviderTypeToSubtype(gs.provider_type, { hasGitConfig: gs.has_git_config })
|
|
10164
|
+
});
|
|
10165
|
+
else skipped.push({
|
|
10166
|
+
routing_key: gs.routing_key,
|
|
10167
|
+
provider_type: gs.provider_type
|
|
10168
|
+
});
|
|
10169
|
+
if (genericRows.length > 0) logger$82.info("Added generic sources to Platform registration", {
|
|
10170
|
+
count: genericRows.length - skipped.length,
|
|
10171
|
+
skipped: skipped.length
|
|
10172
|
+
});
|
|
10173
|
+
if (skipped.length > 0) logger$82.info("Skipped non-servable generic sources for Platform registration", { skipped });
|
|
10174
|
+
} catch (err) {
|
|
10175
|
+
logger$82.warn("Failed to load generic sources for Platform registration", { error: toErrorMessage(err) });
|
|
10176
|
+
}
|
|
10177
|
+
return providerSources;
|
|
10178
|
+
}
|
|
10179
|
+
var logger$82;
|
|
10180
|
+
var init_build_platform_sources = __esmMin((() => {
|
|
10181
|
+
init_entry_helpers();
|
|
10182
|
+
logger$82 = createLogger({ prefix: "platform-sources" });
|
|
10183
|
+
}));
|
|
10184
|
+
//#endregion
|
|
10074
10185
|
//#region src/ws/dashboard-env-handler.ts
|
|
10075
10186
|
/**
|
|
10076
10187
|
* Dashboard environment handler for the orchestrator.
|
|
@@ -11271,7 +11382,7 @@ var init_dashboard_registrations_handler = __esmMin((() => {
|
|
|
11271
11382
|
"git_config"
|
|
11272
11383
|
]).where("deleted_at", "is", null).where("routing_key", "in", routingKeys).execute();
|
|
11273
11384
|
for (const row of genericRows) {
|
|
11274
|
-
const subtype = genericProviderTypeToSubtype
|
|
11385
|
+
const subtype = genericProviderTypeToSubtype(row.provider_type, { hasGitConfig: row.git_config !== null });
|
|
11275
11386
|
result.set(row.routing_key, {
|
|
11276
11387
|
routingKey: row.routing_key,
|
|
11277
11388
|
name: row.name,
|
|
@@ -12610,10 +12721,10 @@ async function emitRerunEventAndCheckRun(opts) {
|
|
|
12610
12721
|
sourceRepo: originalRun.repo_identifier,
|
|
12611
12722
|
sourceRoutingKey: originalRun.routing_key ?? void 0
|
|
12612
12723
|
});
|
|
12613
|
-
if (deps.
|
|
12724
|
+
if (deps.checkRunReporter) {
|
|
12614
12725
|
const [owner, repo] = originalRun.repo_identifier.split("/");
|
|
12615
12726
|
const jobNames = workflow.jobs.filter(isLockStaticJob).map((j) => j.name);
|
|
12616
|
-
deps.
|
|
12727
|
+
deps.checkRunReporter.setPending({
|
|
12617
12728
|
provider: originalRun.provider,
|
|
12618
12729
|
owner,
|
|
12619
12730
|
repo,
|
|
@@ -15038,7 +15149,7 @@ var init_peer_client = __esmMin((() => {
|
|
|
15038
15149
|
init_peer_crypto();
|
|
15039
15150
|
init_peer_credentials();
|
|
15040
15151
|
logger$73 = createLogger({ prefix: "peer-client" });
|
|
15041
|
-
SOFTWARE_VERSION$1 = "0.1.
|
|
15152
|
+
SOFTWARE_VERSION$1 = "0.1.7";
|
|
15042
15153
|
PeerClient$1 = class {
|
|
15043
15154
|
ws = null;
|
|
15044
15155
|
_state = "disconnected";
|
|
@@ -16501,7 +16612,7 @@ var init_peer_handler = __esmMin((() => {
|
|
|
16501
16612
|
init_peer_crypto();
|
|
16502
16613
|
init_join_token();
|
|
16503
16614
|
logger$72 = createLogger({ prefix: "peer-handler" });
|
|
16504
|
-
SOFTWARE_VERSION = "0.1.
|
|
16615
|
+
SOFTWARE_VERSION = "0.1.7";
|
|
16505
16616
|
RATE_LIMIT_MAX = 5;
|
|
16506
16617
|
RATE_LIMIT_WINDOW_MS = 6e4;
|
|
16507
16618
|
}));
|
|
@@ -17135,7 +17246,7 @@ var init_coordinator = __esmMin((() => {
|
|
|
17135
17246
|
peerRegistry;
|
|
17136
17247
|
dispatcher;
|
|
17137
17248
|
executionTracker;
|
|
17138
|
-
|
|
17249
|
+
checkRunReporter;
|
|
17139
17250
|
getPeerClient;
|
|
17140
17251
|
sendAndWaitAckViaHandler;
|
|
17141
17252
|
sendToPeerViaHandler;
|
|
@@ -17157,7 +17268,7 @@ var init_coordinator = __esmMin((() => {
|
|
|
17157
17268
|
this.peerRegistry = deps.peerRegistry;
|
|
17158
17269
|
this.dispatcher = deps.dispatcher;
|
|
17159
17270
|
this.executionTracker = deps.executionTracker;
|
|
17160
|
-
this.
|
|
17271
|
+
this.checkRunReporter = deps.checkRunReporter;
|
|
17161
17272
|
this.getPeerClient = deps.getPeerClient;
|
|
17162
17273
|
this.sendAndWaitAckViaHandler = deps.sendAndWaitAckViaHandler;
|
|
17163
17274
|
this.sendToPeerViaHandler = deps.sendToPeerViaHandler;
|
|
@@ -17280,10 +17391,10 @@ var init_coordinator = __esmMin((() => {
|
|
|
17280
17391
|
const repoIdentifier = (msg.repoUrl ?? "").replace(/\.git$/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/^[^/]+@[^:]+:/, "") || "";
|
|
17281
17392
|
const providerContext = msg.providerContext ?? {};
|
|
17282
17393
|
const installationId = typeof providerContext.installationId === "number" ? providerContext.installationId : void 0;
|
|
17283
|
-
if (this.
|
|
17394
|
+
if (this.checkRunReporter && repoIdentifier && msg.sha) {
|
|
17284
17395
|
const [owner, repo] = repoIdentifier.split("/");
|
|
17285
17396
|
if (owner && repo) try {
|
|
17286
|
-
await this.
|
|
17397
|
+
await this.checkRunReporter.setPendingAwait({
|
|
17287
17398
|
provider: msg.provider ?? "",
|
|
17288
17399
|
owner,
|
|
17289
17400
|
repo,
|
|
@@ -23533,7 +23644,7 @@ var init_check_run_summary = __esmMin((() => {
|
|
|
23533
23644
|
];
|
|
23534
23645
|
}));
|
|
23535
23646
|
//#endregion
|
|
23536
|
-
//#region src/reporting/
|
|
23647
|
+
//#region src/reporting/check-run-reporter.ts
|
|
23537
23648
|
/**
|
|
23538
23649
|
* GitHub check run integration module.
|
|
23539
23650
|
*
|
|
@@ -23548,7 +23659,7 @@ var init_check_run_summary = __esmMin((() => {
|
|
|
23548
23659
|
* Check run IDs are tracked in-memory after creation so that subsequent
|
|
23549
23660
|
* updates (job complete, workflow complete) can reference them via checks.update().
|
|
23550
23661
|
*
|
|
23551
|
-
* Enriched output
|
|
23662
|
+
* Enriched output:
|
|
23552
23663
|
* - Live step progress with checklist-style updates (debounced at 5s)
|
|
23553
23664
|
* - Failed check runs include step names, error messages, exit codes, and log context
|
|
23554
23665
|
* - Check run annotations link failures to step source locations in workflow files (.kici/workflows/*.ts)
|
|
@@ -23558,7 +23669,7 @@ var init_check_run_summary = __esmMin((() => {
|
|
|
23558
23669
|
* Note: The engine-level CheckStatusPoster interface (packages/engine/src/provider/check-status-poster.ts)
|
|
23559
23670
|
* provides a provider-agnostic API for posting security-related check statuses (holds, approvals,
|
|
23560
23671
|
* workflow modifications). The GitHub implementation is at packages/orchestrator/src/providers/github/check-status-poster.ts.
|
|
23561
|
-
* This
|
|
23672
|
+
* This CheckRunReporter handles execution lifecycle checks (queued, in_progress, completed per job/workflow).
|
|
23562
23673
|
* Future cleanup may unify both under CheckStatusPoster, but they serve different purposes today.
|
|
23563
23674
|
*/
|
|
23564
23675
|
/**
|
|
@@ -23580,14 +23691,14 @@ function buildJobFailureDescription(data) {
|
|
|
23580
23691
|
if (data.error) return `Job error: ${data.error}`;
|
|
23581
23692
|
return "Job failed";
|
|
23582
23693
|
}
|
|
23583
|
-
var logger$60, PROGRESS_DEBOUNCE_MS,
|
|
23584
|
-
var
|
|
23694
|
+
var logger$60, PROGRESS_DEBOUNCE_MS, CheckRunReporter;
|
|
23695
|
+
var init_check_run_reporter = __esmMin((() => {
|
|
23585
23696
|
init_auth();
|
|
23586
23697
|
init_prometheus();
|
|
23587
23698
|
init_check_run_summary();
|
|
23588
|
-
logger$60 = createLogger({ prefix: "
|
|
23699
|
+
logger$60 = createLogger({ prefix: "check-run-reporter" });
|
|
23589
23700
|
PROGRESS_DEBOUNCE_MS = 5e3;
|
|
23590
|
-
|
|
23701
|
+
CheckRunReporter = class {
|
|
23591
23702
|
/**
|
|
23592
23703
|
* L1 cache: composite key → check run ID.
|
|
23593
23704
|
*
|
|
@@ -23842,7 +23953,7 @@ var init_commit_status = __esmMin((() => {
|
|
|
23842
23953
|
*/
|
|
23843
23954
|
async recoverState() {
|
|
23844
23955
|
if (!this.deps.trackingStore) return;
|
|
23845
|
-
logger$60.info("
|
|
23956
|
+
logger$60.info("CheckRunReporter recovered (DB-backed state lookups enabled)");
|
|
23846
23957
|
}
|
|
23847
23958
|
/** Track a check run key associated with a runId for later cleanup. */
|
|
23848
23959
|
trackRunKey(runId, key) {
|
|
@@ -26975,10 +27086,29 @@ function createSourceRoutes(deps) {
|
|
|
26975
27086
|
privateKey,
|
|
26976
27087
|
webhookSecret
|
|
26977
27088
|
});
|
|
27089
|
+
let webhookUrl = null;
|
|
27090
|
+
let webhookNote;
|
|
27091
|
+
if (deps.resolveSourceWebhookUrl) try {
|
|
27092
|
+
const resolved = await deps.resolveSourceWebhookUrl({
|
|
27093
|
+
routingKey: source.routing_key,
|
|
27094
|
+
provider,
|
|
27095
|
+
sourceId: source.id
|
|
27096
|
+
});
|
|
27097
|
+
webhookUrl = resolved.webhookUrl;
|
|
27098
|
+
webhookNote = resolved.webhookNote;
|
|
27099
|
+
} catch (err) {
|
|
27100
|
+
logger$53.warn("Failed to resolve webhook URL for added source", {
|
|
27101
|
+
routingKey: source.routing_key,
|
|
27102
|
+
error: toErrorMessage(err)
|
|
27103
|
+
});
|
|
27104
|
+
webhookNote = "resolve-failed";
|
|
27105
|
+
}
|
|
26978
27106
|
return c.json({
|
|
26979
27107
|
routingKey: source.routing_key,
|
|
26980
27108
|
id: source.id,
|
|
26981
|
-
name: source.name
|
|
27109
|
+
name: source.name,
|
|
27110
|
+
webhookUrl,
|
|
27111
|
+
...webhookNote && { webhookNote }
|
|
26982
27112
|
}, 201);
|
|
26983
27113
|
} catch (err) {
|
|
26984
27114
|
logger$53.error("Failed to add source", { error: toErrorMessage(err) });
|
|
@@ -30966,7 +31096,10 @@ function createAdminRoutes(deps) {
|
|
|
30966
31096
|
return handleError$3(c, err);
|
|
30967
31097
|
}
|
|
30968
31098
|
});
|
|
30969
|
-
if (deps.sourceStore) app.route("/api/v1/admin", createSourceRoutes({
|
|
31099
|
+
if (deps.sourceStore) app.route("/api/v1/admin", createSourceRoutes({
|
|
31100
|
+
sourceStore: deps.sourceStore,
|
|
31101
|
+
resolveSourceWebhookUrl: deps.resolveSourceWebhookUrl
|
|
31102
|
+
}));
|
|
30970
31103
|
if (deps.db && deps.pool) app.route("/api/v1/admin", createDbRoutes({
|
|
30971
31104
|
db: deps.db,
|
|
30972
31105
|
pool: deps.pool
|
|
@@ -31837,7 +31970,7 @@ var init_universal_git = __esmMin((() => {
|
|
|
31837
31970
|
*/
|
|
31838
31971
|
function registerProviderBundleForSource(row, deps) {
|
|
31839
31972
|
if (row.provider_type === "internal") {
|
|
31840
|
-
if (!canServeGenericProviderType
|
|
31973
|
+
if (!canServeGenericProviderType("internal", deps.config)) {
|
|
31841
31974
|
logger$40.info("Skipping internal provider bundle registration — KICI_INTERNAL_PROVIDER_REPO_PATH not configured on this peer", {
|
|
31842
31975
|
routingKey: row.routing_key,
|
|
31843
31976
|
sourceName: row.name
|
|
@@ -33916,14 +34049,14 @@ var init_admin_config = __esmMin((() => {
|
|
|
33916
34049
|
function createHealthRoutes$1(deps = {}) {
|
|
33917
34050
|
return createHealthRoutes({
|
|
33918
34051
|
livenessInfo: () => ({
|
|
33919
|
-
version: "0.1.
|
|
33920
|
-
buildDate: "2026-05-
|
|
33921
|
-
buildCommit: "
|
|
33922
|
-
sdkVersion: "0.1.
|
|
34052
|
+
version: "0.1.7",
|
|
34053
|
+
buildDate: "2026-05-26T13:18:35.789Z",
|
|
34054
|
+
buildCommit: "4c0abe030",
|
|
34055
|
+
sdkVersion: "0.1.7",
|
|
33923
34056
|
sdkBundleHash: "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128",
|
|
33924
|
-
sharedVersion: "0.1.
|
|
33925
|
-
sharedBundleHash: "
|
|
33926
|
-
engineVersion: "0.1.
|
|
34057
|
+
sharedVersion: "0.1.7",
|
|
34058
|
+
sharedBundleHash: "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae",
|
|
34059
|
+
engineVersion: "0.1.7",
|
|
33927
34060
|
engineBundleHash: "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21"
|
|
33928
34061
|
}),
|
|
33929
34062
|
readinessCheck: deps.db ? async () => {
|
|
@@ -33958,7 +34091,7 @@ function createCapabilitiesRoutes() {
|
|
|
33958
34091
|
const app = new Hono();
|
|
33959
34092
|
app.get("/api/v1/capabilities", (c) => {
|
|
33960
34093
|
const manifest = {
|
|
33961
|
-
orchestratorVersion: "0.1.
|
|
34094
|
+
orchestratorVersion: "0.1.7",
|
|
33962
34095
|
protocolVersion: PROTOCOL_VERSION,
|
|
33963
34096
|
minProtocolVersion: MIN_PROTOCOL_VERSION
|
|
33964
34097
|
};
|
|
@@ -34873,7 +35006,7 @@ function createApp(deps) {
|
|
|
34873
35006
|
sourceCache: deps.sourceCache,
|
|
34874
35007
|
depCache: deps.depCache,
|
|
34875
35008
|
cacheStorage: deps.cacheStorage,
|
|
34876
|
-
onJobStatus: deps.platformClient || deps.executionTracker || deps.
|
|
35009
|
+
onJobStatus: deps.platformClient || deps.executionTracker || deps.checkRunReporter || deps.pendingBuilds || deps.pendingInits ? (_agentId, msg) => {
|
|
34877
35010
|
if (deps.pendingBuilds && deps.pendingBuilds.has(msg.jobId)) {
|
|
34878
35011
|
if (msg.state === ExecutionJobStatus.enum.success && msg.data?.buildComplete) deps.pendingBuilds.resolve(msg.jobId);
|
|
34879
35012
|
else if (msg.state === ExecutionJobStatus.enum.failed || msg.state === ExecutionJobStatus.enum.cancelled) deps.pendingBuilds.reject(msg.jobId, new Error(msg.data?.error ?? `Build ${msg.state}`));
|
|
@@ -34905,13 +35038,13 @@ function createApp(deps) {
|
|
|
34905
35038
|
},
|
|
34906
35039
|
timestamp: msg.timestamp
|
|
34907
35040
|
});
|
|
34908
|
-
if (deps.
|
|
35041
|
+
if (deps.checkRunReporter && deps.executionTracker && (msg.state === ExecutionJobStatus.enum.success || msg.state === ExecutionJobStatus.enum.failed || msg.state === ExecutionJobStatus.enum.cancelled)) {
|
|
34909
35042
|
const execContext = deps.executionTracker.getExecutionContext(msg.runId);
|
|
34910
35043
|
if (execContext) {
|
|
34911
35044
|
const [owner, repo] = execContext.repoIdentifier.split("/");
|
|
34912
35045
|
let description;
|
|
34913
35046
|
if (msg.state === ExecutionJobStatus.enum.failed && msg.data) description = buildJobFailureDescription(msg.data);
|
|
34914
|
-
deps.
|
|
35047
|
+
deps.checkRunReporter.updateJobStatus({
|
|
34915
35048
|
provider: execContext.provider,
|
|
34916
35049
|
owner,
|
|
34917
35050
|
repo,
|
|
@@ -34962,11 +35095,11 @@ function createApp(deps) {
|
|
|
34962
35095
|
} : msg.data;
|
|
34963
35096
|
deps.executionTracker.onStepStatus(msg.runId, msg.jobId, msg.stepIndex, msg.stepName, msg.state, msg.timestamp, data, msg.logBytesStreamed);
|
|
34964
35097
|
}
|
|
34965
|
-
if (deps.
|
|
35098
|
+
if (deps.checkRunReporter && deps.executionTracker) {
|
|
34966
35099
|
const execContext = deps.executionTracker.getExecutionContext(msg.runId);
|
|
34967
35100
|
if (execContext) {
|
|
34968
35101
|
const [owner, repo] = execContext.repoIdentifier.split("/");
|
|
34969
|
-
deps.
|
|
35102
|
+
deps.checkRunReporter.updateStepProgress({
|
|
34970
35103
|
provider: execContext.provider,
|
|
34971
35104
|
owner,
|
|
34972
35105
|
repo,
|
|
@@ -35260,7 +35393,7 @@ function createApp(deps) {
|
|
|
35260
35393
|
pendingBuilds: deps.pendingBuilds,
|
|
35261
35394
|
pendingInits: deps.pendingInits,
|
|
35262
35395
|
pendingDynamics: deps.pendingDynamics,
|
|
35263
|
-
|
|
35396
|
+
checkRunReporter: deps.checkRunReporter,
|
|
35264
35397
|
executionTracker: deps.executionTracker,
|
|
35265
35398
|
onSourceLocationsExtracted,
|
|
35266
35399
|
eventRouter: deps.eventRouter,
|
|
@@ -35301,7 +35434,8 @@ function createApp(deps) {
|
|
|
35301
35434
|
}));
|
|
35302
35435
|
if (deps.adminDeps) app.route("", createAdminRoutes({
|
|
35303
35436
|
...deps.adminDeps,
|
|
35304
|
-
accessLog: deps.accessLogWriter
|
|
35437
|
+
accessLog: deps.accessLogWriter,
|
|
35438
|
+
resolveSourceWebhookUrl: deps.resolveSourceWebhookUrl
|
|
35305
35439
|
}));
|
|
35306
35440
|
if (deps.genericSourceManager && deps.trustStore && deps.adminDeps) app.route("", createAdminEventRoutes({
|
|
35307
35441
|
sourceManager: deps.genericSourceManager,
|
|
@@ -35358,7 +35492,7 @@ function createApp(deps) {
|
|
|
35358
35492
|
lockFileCache: deps.lockFileCache,
|
|
35359
35493
|
dispatcher: deps.dispatcher,
|
|
35360
35494
|
executionTracker: deps.executionTracker,
|
|
35361
|
-
|
|
35495
|
+
checkRunReporter: deps.checkRunReporter,
|
|
35362
35496
|
sourceCache: deps.sourceCache,
|
|
35363
35497
|
buildCoordinator: deps.buildCoordinator,
|
|
35364
35498
|
depCache: deps.depCache,
|
|
@@ -35515,7 +35649,7 @@ var init_app = __esmMin((() => {
|
|
|
35515
35649
|
init_blob_routes();
|
|
35516
35650
|
init_agent_api_registry();
|
|
35517
35651
|
init_server_options();
|
|
35518
|
-
|
|
35652
|
+
init_check_run_reporter();
|
|
35519
35653
|
init_agent_handler();
|
|
35520
35654
|
init_observer_handler();
|
|
35521
35655
|
init_test_trigger();
|
|
@@ -42726,7 +42860,7 @@ var init_stale_run_detector = __esmMin((() => {
|
|
|
42726
42860
|
StaleRunDetector = class {
|
|
42727
42861
|
db;
|
|
42728
42862
|
executionTracker;
|
|
42729
|
-
|
|
42863
|
+
checkRunReporter;
|
|
42730
42864
|
scalerManager;
|
|
42731
42865
|
dispatcher;
|
|
42732
42866
|
registry;
|
|
@@ -42737,7 +42871,7 @@ var init_stale_run_detector = __esmMin((() => {
|
|
|
42737
42871
|
constructor(deps) {
|
|
42738
42872
|
this.db = deps.db;
|
|
42739
42873
|
this.executionTracker = deps.executionTracker;
|
|
42740
|
-
this.
|
|
42874
|
+
this.checkRunReporter = deps.checkRunReporter;
|
|
42741
42875
|
this.scalerManager = deps.scalerManager;
|
|
42742
42876
|
this.dispatcher = deps.dispatcher;
|
|
42743
42877
|
this.registry = deps.registry;
|
|
@@ -42959,11 +43093,11 @@ var init_stale_run_detector = __esmMin((() => {
|
|
|
42959
43093
|
});
|
|
42960
43094
|
markedCount++;
|
|
42961
43095
|
staleRunsDetectedTotal.add(1);
|
|
42962
|
-
if (this.
|
|
43096
|
+
if (this.checkRunReporter) {
|
|
42963
43097
|
const [owner, repo] = entry.repo_identifier.split("/");
|
|
42964
43098
|
const providerCtx = typeof entry.provider_context === "string" ? JSON.parse(entry.provider_context) : entry.provider_context ?? {};
|
|
42965
43099
|
const installationId = typeof providerCtx.installationId === "number" ? providerCtx.installationId : void 0;
|
|
42966
|
-
this.
|
|
43100
|
+
this.checkRunReporter.updateJobStatus({
|
|
42967
43101
|
provider: entry.provider,
|
|
42968
43102
|
owner,
|
|
42969
43103
|
repo,
|
|
@@ -43021,11 +43155,11 @@ var init_stale_run_detector = __esmMin((() => {
|
|
|
43021
43155
|
});
|
|
43022
43156
|
await this.executionTracker.cancelStepsForJob(job.run_id, job.job_id, errorMessage);
|
|
43023
43157
|
affectedRunIds.add(job.run_id);
|
|
43024
|
-
if (this.
|
|
43158
|
+
if (this.checkRunReporter) {
|
|
43025
43159
|
const [owner, repo] = job.repo_identifier.split("/");
|
|
43026
43160
|
const providerCtx = typeof job.provider_context === "string" ? JSON.parse(job.provider_context) : job.provider_context ?? {};
|
|
43027
43161
|
const installationId = typeof providerCtx.installationId === "number" ? providerCtx.installationId : void 0;
|
|
43028
|
-
this.
|
|
43162
|
+
this.checkRunReporter.updateJobStatus({
|
|
43029
43163
|
provider: job.provider,
|
|
43030
43164
|
owner,
|
|
43031
43165
|
repo,
|
|
@@ -44115,10 +44249,27 @@ var init_source_manager = __esmMin((() => {
|
|
|
44115
44249
|
currentSources = [];
|
|
44116
44250
|
debounceTimer = null;
|
|
44117
44251
|
debounceMs;
|
|
44252
|
+
/**
|
|
44253
|
+
* Change callback. Stored in a mutable field (not read off `opts`) so a
|
|
44254
|
+
* mode-specific hook can rewire it after construction — the platform-mode
|
|
44255
|
+
* boot wires it to push the full source list to the Platform via
|
|
44256
|
+
* `platformClient.updateSources()`. Defaults to the (possibly no-op) value
|
|
44257
|
+
* passed at construction.
|
|
44258
|
+
*/
|
|
44259
|
+
onSourcesChanged;
|
|
44118
44260
|
constructor(opts) {
|
|
44119
44261
|
this.opts = opts;
|
|
44120
44262
|
this.registry = new ProviderRegistry();
|
|
44121
44263
|
this.debounceMs = opts.debounceMs ?? 200;
|
|
44264
|
+
this.onSourcesChanged = opts.onSourcesChanged;
|
|
44265
|
+
}
|
|
44266
|
+
/**
|
|
44267
|
+
* Replace the change callback after construction. The SourceManager is built
|
|
44268
|
+
* early (before the Platform client exists); the platform-mode boot calls
|
|
44269
|
+
* this once the client is ready so live source changes propagate upstream.
|
|
44270
|
+
*/
|
|
44271
|
+
setOnSourcesChanged(cb) {
|
|
44272
|
+
this.onSourcesChanged = cb;
|
|
44122
44273
|
}
|
|
44123
44274
|
/** Get current ProviderRegistry (rebuilt on each reload). */
|
|
44124
44275
|
getRegistry() {
|
|
@@ -44193,7 +44344,7 @@ var init_source_manager = __esmMin((() => {
|
|
|
44193
44344
|
added: diff.added.length,
|
|
44194
44345
|
removed: diff.removed.length
|
|
44195
44346
|
});
|
|
44196
|
-
if (diff.added.length > 0 || diff.removed.length > 0) this.
|
|
44347
|
+
if (diff.added.length > 0 || diff.removed.length > 0) this.onSourcesChanged(diff);
|
|
44197
44348
|
}
|
|
44198
44349
|
/**
|
|
44199
44350
|
* Build a ProviderBundle for a source with decrypted secrets.
|
|
@@ -45842,9 +45993,19 @@ var init_generic_sources_listener = __esmMin((() => {
|
|
|
45842
45993
|
pending = /* @__PURE__ */ new Set();
|
|
45843
45994
|
debounceTimer = null;
|
|
45844
45995
|
debounceMs;
|
|
45996
|
+
/**
|
|
45997
|
+
* Drain-applied-change callback. Mutable so the platform-mode boot can wire
|
|
45998
|
+
* it after the Platform client exists (this listener is constructed before).
|
|
45999
|
+
*/
|
|
46000
|
+
onChange;
|
|
45845
46001
|
constructor(opts) {
|
|
45846
46002
|
this.opts = opts;
|
|
45847
46003
|
this.debounceMs = opts.debounceMs ?? 200;
|
|
46004
|
+
this.onChange = opts.onChange;
|
|
46005
|
+
}
|
|
46006
|
+
/** Replace the drain-applied-change callback after construction. */
|
|
46007
|
+
setOnChange(cb) {
|
|
46008
|
+
this.onChange = cb;
|
|
45848
46009
|
}
|
|
45849
46010
|
/** Open the dedicated client and subscribe. Cold-boot bundle
|
|
45850
46011
|
* registration is handled by the orchestrator-core startup loop
|
|
@@ -45890,6 +46051,7 @@ var init_generic_sources_listener = __esmMin((() => {
|
|
|
45890
46051
|
async drain() {
|
|
45891
46052
|
const keys = Array.from(this.pending);
|
|
45892
46053
|
this.pending.clear();
|
|
46054
|
+
let appliedChange = false;
|
|
45893
46055
|
for (const routingKey of keys) try {
|
|
45894
46056
|
const row = await this.opts.sourceManager.getByRoutingKey(routingKey);
|
|
45895
46057
|
if (!row) {
|
|
@@ -45898,6 +46060,7 @@ var init_generic_sources_listener = __esmMin((() => {
|
|
|
45898
46060
|
routingKey,
|
|
45899
46061
|
removed
|
|
45900
46062
|
});
|
|
46063
|
+
appliedChange = true;
|
|
45901
46064
|
continue;
|
|
45902
46065
|
}
|
|
45903
46066
|
this.opts.providerRegistry.unregister(routingKey);
|
|
@@ -45906,12 +46069,14 @@ var init_generic_sources_listener = __esmMin((() => {
|
|
|
45906
46069
|
config: this.opts.config,
|
|
45907
46070
|
secretResolver: this.opts.secretResolver
|
|
45908
46071
|
});
|
|
46072
|
+
appliedChange = true;
|
|
45909
46073
|
} catch (err) {
|
|
45910
46074
|
logger$8.error("Failed to apply generic-source change", {
|
|
45911
46075
|
routingKey,
|
|
45912
46076
|
error: toErrorMessage(err)
|
|
45913
46077
|
});
|
|
45914
46078
|
}
|
|
46079
|
+
if (appliedChange) this.onChange?.();
|
|
45915
46080
|
}
|
|
45916
46081
|
};
|
|
45917
46082
|
}));
|
|
@@ -47659,7 +47824,7 @@ function buildOnEventMatched(dispatcherRef, executionTracker, providerRegistryRe
|
|
|
47659
47824
|
}
|
|
47660
47825
|
};
|
|
47661
47826
|
}
|
|
47662
|
-
function initializeCluster(config, db, agentRegistry, dispatcher, executionTracker,
|
|
47827
|
+
function initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, checkRunReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef) {
|
|
47663
47828
|
const peerClients = /* @__PURE__ */ new Map();
|
|
47664
47829
|
const getLocalInventory = () => ({
|
|
47665
47830
|
instanceId: config.instanceId,
|
|
@@ -47763,7 +47928,7 @@ function initializeCluster(config, db, agentRegistry, dispatcher, executionTrack
|
|
|
47763
47928
|
peerRegistry,
|
|
47764
47929
|
dispatcher,
|
|
47765
47930
|
executionTracker,
|
|
47766
|
-
|
|
47931
|
+
checkRunReporter,
|
|
47767
47932
|
getPeerClient: (instanceId) => peerClients.get(instanceId),
|
|
47768
47933
|
sendAndWaitAckViaHandler: (targetId, msg, timeoutMs) => peerHandlerObj?.sendAndWaitAck(targetId, msg, timeoutMs) ?? Promise.resolve(false),
|
|
47769
47934
|
sendToPeerViaHandler: (targetId, msg) => peerHandlerObj?.sendToPeer(targetId, msg) ?? false
|
|
@@ -47973,7 +48138,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
47973
48138
|
const stepLogBuffer = new StepLogBuffer();
|
|
47974
48139
|
const sourceLocationStore = new SourceLocationStore();
|
|
47975
48140
|
const checkRunTrackingStore = new CheckRunTrackingStore(db);
|
|
47976
|
-
const
|
|
48141
|
+
const checkRunReporter = new CheckRunReporter({
|
|
47977
48142
|
providerRegistry,
|
|
47978
48143
|
stepLogBuffer,
|
|
47979
48144
|
trackingStore: checkRunTrackingStore,
|
|
@@ -48020,7 +48185,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48020
48185
|
});
|
|
48021
48186
|
});
|
|
48022
48187
|
const [owner, repo] = context.repoIdentifier.split("/");
|
|
48023
|
-
|
|
48188
|
+
checkRunReporter.updateWorkflowStatus({
|
|
48024
48189
|
provider: context.provider,
|
|
48025
48190
|
owner,
|
|
48026
48191
|
repo,
|
|
@@ -48070,7 +48235,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48070
48235
|
orgId: trackerExtras?.orgId,
|
|
48071
48236
|
onRunPruned: (runId) => {
|
|
48072
48237
|
stepLogBuffer.cleanup(runId);
|
|
48073
|
-
|
|
48238
|
+
checkRunReporter.cleanupRun(runId);
|
|
48074
48239
|
},
|
|
48075
48240
|
onWorkflowComplete: (data) => {
|
|
48076
48241
|
if (!eventEmitter) return;
|
|
@@ -48176,7 +48341,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48176
48341
|
if (pgSecretStore) {
|
|
48177
48342
|
providerRegistry = await sourceManager.start();
|
|
48178
48343
|
providerRegistryRef.current = providerRegistry;
|
|
48179
|
-
|
|
48344
|
+
checkRunReporter.updateRegistry(providerRegistry);
|
|
48180
48345
|
const registeredKeys = providerRegistry.getRoutingKeys();
|
|
48181
48346
|
if (registeredKeys.length > 0) logger$2.info("Provider registry built from sources", { routingKeys: registeredKeys });
|
|
48182
48347
|
else logger$2.info("No sources configured yet (orchestrator can start with zero sources)");
|
|
@@ -48323,7 +48488,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48323
48488
|
ttl: config.lockfileCacheTtlMs
|
|
48324
48489
|
});
|
|
48325
48490
|
const configReloaderRef = { current: null };
|
|
48326
|
-
const cluster = initializeCluster(config, db, agentRegistry, dispatcher, executionTracker,
|
|
48491
|
+
const cluster = initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, checkRunReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef);
|
|
48327
48492
|
coordinatorRef.current = cluster.coordinator;
|
|
48328
48493
|
if (adminDeps) adminDeps.broadcastAgentTokenRevoke = cluster.broadcastAgentTokenRevoke;
|
|
48329
48494
|
let masterKeyForStore = null;
|
|
@@ -48362,7 +48527,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48362
48527
|
pendingBuilds,
|
|
48363
48528
|
pendingInits,
|
|
48364
48529
|
pendingDynamics,
|
|
48365
|
-
|
|
48530
|
+
checkRunReporter,
|
|
48366
48531
|
stepLogBuffer,
|
|
48367
48532
|
sourceLocationStore,
|
|
48368
48533
|
logStorage,
|
|
@@ -48398,6 +48563,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48398
48563
|
localConfigVersion: localConfigVersionRef.value,
|
|
48399
48564
|
sourceStore,
|
|
48400
48565
|
sourceManager,
|
|
48566
|
+
genericSourcesChangeListener,
|
|
48401
48567
|
eventLogWriter,
|
|
48402
48568
|
accessLogWriter,
|
|
48403
48569
|
coldStore: coldStoreSingleton,
|
|
@@ -48449,7 +48615,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48449
48615
|
await sourceManager.reload();
|
|
48450
48616
|
providerRegistry = sourceManager.getRegistry();
|
|
48451
48617
|
providerRegistryRef.current = providerRegistry;
|
|
48452
|
-
|
|
48618
|
+
checkRunReporter.updateRegistry(providerRegistry);
|
|
48453
48619
|
logger$2.info("Provider registry reloaded from sources", { routingKeys: providerRegistry.getRoutingKeys() });
|
|
48454
48620
|
}),
|
|
48455
48621
|
onScalerReload: scalerManager ? async () => {
|
|
@@ -48550,7 +48716,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48550
48716
|
pendingBuilds,
|
|
48551
48717
|
pendingInits,
|
|
48552
48718
|
pendingDynamics,
|
|
48553
|
-
|
|
48719
|
+
checkRunReporter,
|
|
48554
48720
|
executionTracker,
|
|
48555
48721
|
logWriter,
|
|
48556
48722
|
stepLogBuffer,
|
|
@@ -48604,7 +48770,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
|
|
|
48604
48770
|
const staleRunDetector = new StaleRunDetector({
|
|
48605
48771
|
db,
|
|
48606
48772
|
executionTracker,
|
|
48607
|
-
|
|
48773
|
+
checkRunReporter,
|
|
48608
48774
|
scalerManager: scalerManager ?? void 0,
|
|
48609
48775
|
dispatcher,
|
|
48610
48776
|
registry: agentRegistry,
|
|
@@ -48811,7 +48977,7 @@ var init_orchestrator_core = __esmMin((() => {
|
|
|
48811
48977
|
init_scaler();
|
|
48812
48978
|
init_storage();
|
|
48813
48979
|
init_cache();
|
|
48814
|
-
|
|
48980
|
+
init_check_run_reporter();
|
|
48815
48981
|
init_check_run_tracking_store();
|
|
48816
48982
|
init_scaler_state_store();
|
|
48817
48983
|
init_processor();
|
|
@@ -50060,13 +50226,13 @@ var init_worker_core = __esmMin((() => {
|
|
|
50060
50226
|
init_agent_handler();
|
|
50061
50227
|
init_worker_status();
|
|
50062
50228
|
init_agent_heartbeat();
|
|
50063
|
-
ORCHESTRATOR_VERSION$1 = "0.1.
|
|
50064
|
-
WORKER_BUILD_COMMIT = "
|
|
50065
|
-
WORKER_SDK_VERSION = "0.1.
|
|
50229
|
+
ORCHESTRATOR_VERSION$1 = "0.1.7";
|
|
50230
|
+
WORKER_BUILD_COMMIT = "4c0abe030";
|
|
50231
|
+
WORKER_SDK_VERSION = "0.1.7";
|
|
50066
50232
|
WORKER_SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
|
|
50067
|
-
WORKER_SHARED_VERSION = "0.1.
|
|
50068
|
-
WORKER_SHARED_BUNDLE_HASH = "
|
|
50069
|
-
WORKER_ENGINE_VERSION = "0.1.
|
|
50233
|
+
WORKER_SHARED_VERSION = "0.1.7";
|
|
50234
|
+
WORKER_SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
|
|
50235
|
+
WORKER_ENGINE_VERSION = "0.1.7";
|
|
50070
50236
|
WORKER_ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
|
|
50071
50237
|
logger$1 = createLogger({ prefix: "worker" });
|
|
50072
50238
|
DRAIN_TIMEOUT_MS = 3e5;
|
|
@@ -50088,13 +50254,13 @@ var init_worker_core = __esmMin((() => {
|
|
|
50088
50254
|
* Graceful shutdown in reverse order:
|
|
50089
50255
|
* Platform client -> agent WS -> heartbeat -> HTTP -> DB
|
|
50090
50256
|
*/
|
|
50091
|
-
const ORCHESTRATOR_VERSION = "0.1.
|
|
50092
|
-
const BUILD_COMMIT = "
|
|
50093
|
-
const SDK_VERSION = "0.1.
|
|
50257
|
+
const ORCHESTRATOR_VERSION = "0.1.7";
|
|
50258
|
+
const BUILD_COMMIT = "4c0abe030";
|
|
50259
|
+
const SDK_VERSION = "0.1.7";
|
|
50094
50260
|
const SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
|
|
50095
|
-
const SHARED_VERSION = "0.1.
|
|
50096
|
-
const SHARED_BUNDLE_HASH = "
|
|
50097
|
-
const ENGINE_VERSION = "0.1.
|
|
50261
|
+
const SHARED_VERSION = "0.1.7";
|
|
50262
|
+
const SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
|
|
50263
|
+
const ENGINE_VERSION = "0.1.7";
|
|
50098
50264
|
const ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
|
|
50099
50265
|
const otelSdk = initTelemetry({
|
|
50100
50266
|
serviceName: "kici-orchestrator",
|
|
@@ -50107,7 +50273,7 @@ const { LogPullHandler } = await Promise.resolve().then(() => (init_log_pull_han
|
|
|
50107
50273
|
const { DashboardHandler } = await Promise.resolve().then(() => (init_handler(), handler_exports));
|
|
50108
50274
|
const { payloadFromObject } = await Promise.resolve().then(() => (init_event_log$1(), event_log_exports));
|
|
50109
50275
|
const { loadActiveGenericRoutingKeys } = await Promise.resolve().then(() => (init_generic_sources(), generic_sources_exports));
|
|
50110
|
-
const {
|
|
50276
|
+
const { buildPlatformProviderSources } = await Promise.resolve().then(() => (init_build_platform_sources(), build_platform_sources_exports));
|
|
50111
50277
|
const { DashboardEnvHandler } = await Promise.resolve().then(() => (init_dashboard_env_handler(), dashboard_env_handler_exports));
|
|
50112
50278
|
const { DashboardRegistrationsHandler } = await Promise.resolve().then(() => (init_dashboard_registrations_handler(), dashboard_registrations_handler_exports));
|
|
50113
50279
|
const { DashboardBackendsHandler } = await Promise.resolve().then(() => (init_dashboard_backends_handler(), dashboard_backends_handler_exports));
|
|
@@ -50342,28 +50508,8 @@ await guardStartup(logger, async () => {
|
|
|
50342
50508
|
let identityLinks = [];
|
|
50343
50509
|
let orgMemberPermissions = /* @__PURE__ */ new Map();
|
|
50344
50510
|
const heldRunStore = new HeldRunStore(sub.db);
|
|
50345
|
-
const
|
|
50346
|
-
|
|
50347
|
-
const genericRows = await loadActiveGenericRoutingKeys(sub.db);
|
|
50348
|
-
const skipped = [];
|
|
50349
|
-
for (const gs of genericRows) if (canServeGenericProviderType(gs.provider_type, config)) providerSources.push({
|
|
50350
|
-
provider: "generic",
|
|
50351
|
-
routingKey: gs.routing_key,
|
|
50352
|
-
name: gs.name,
|
|
50353
|
-
subtype: genericProviderTypeToSubtype(gs.provider_type, { hasGitConfig: gs.has_git_config })
|
|
50354
|
-
});
|
|
50355
|
-
else skipped.push({
|
|
50356
|
-
routing_key: gs.routing_key,
|
|
50357
|
-
provider_type: gs.provider_type
|
|
50358
|
-
});
|
|
50359
|
-
if (genericRows.length > 0) logger.info("Added generic sources to Platform registration", {
|
|
50360
|
-
count: genericRows.length - skipped.length,
|
|
50361
|
-
skipped: skipped.length
|
|
50362
|
-
});
|
|
50363
|
-
if (skipped.length > 0) logger.info("Skipped non-servable generic sources for Platform registration", { skipped });
|
|
50364
|
-
} catch (err) {
|
|
50365
|
-
logger.warn("Failed to load generic sources for Platform registration", { error: toErrorMessage(err) });
|
|
50366
|
-
}
|
|
50511
|
+
const loadGenericRows = () => loadActiveGenericRoutingKeys(sub.db);
|
|
50512
|
+
const providerSources = await buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config);
|
|
50367
50513
|
let logPullSendFn = null;
|
|
50368
50514
|
const logPullHandler = new LogPullHandler({
|
|
50369
50515
|
logStorage: sub.logStorage,
|
|
@@ -50391,7 +50537,7 @@ await guardStartup(logger, async () => {
|
|
|
50391
50537
|
dispatcher: sub.dispatcher,
|
|
50392
50538
|
jobQueue: sub.queue,
|
|
50393
50539
|
platformClient,
|
|
50394
|
-
|
|
50540
|
+
checkRunReporter: sub.checkRunReporter,
|
|
50395
50541
|
coordinator: sub.coordinator,
|
|
50396
50542
|
secretResolver: sub.secretResolver,
|
|
50397
50543
|
eventRouter: sub.eventRouter,
|
|
@@ -50412,7 +50558,7 @@ await guardStartup(logger, async () => {
|
|
|
50412
50558
|
dispatcher: sub.dispatcher,
|
|
50413
50559
|
jobQueue: sub.queue,
|
|
50414
50560
|
platformClient,
|
|
50415
|
-
|
|
50561
|
+
checkRunReporter: sub.checkRunReporter,
|
|
50416
50562
|
coordinator: sub.coordinator,
|
|
50417
50563
|
secretResolver: sub.secretResolver,
|
|
50418
50564
|
eventRouter: sub.eventRouter,
|
|
@@ -50756,7 +50902,7 @@ await guardStartup(logger, async () => {
|
|
|
50756
50902
|
onStaleCheckrunCleanup: (msg) => {
|
|
50757
50903
|
for (const run of msg.runs) {
|
|
50758
50904
|
const [owner, repo] = run.repoIdentifier.split("/");
|
|
50759
|
-
sub.
|
|
50905
|
+
sub.checkRunReporter.cleanupStaleCheckRuns({
|
|
50760
50906
|
provider: run.provider,
|
|
50761
50907
|
routingKey: run.routingKey,
|
|
50762
50908
|
owner,
|
|
@@ -50908,7 +51054,7 @@ await guardStartup(logger, async () => {
|
|
|
50908
51054
|
pendingBuilds: sub.pendingBuilds,
|
|
50909
51055
|
pendingInits: sub.pendingInits,
|
|
50910
51056
|
pendingDynamics: sub.pendingDynamics,
|
|
50911
|
-
|
|
51057
|
+
checkRunReporter: sub.checkRunReporter,
|
|
50912
51058
|
executionTracker: sub.executionTracker,
|
|
50913
51059
|
coordinator: sub.coordinator,
|
|
50914
51060
|
secretResolver: sub.secretResolver ?? void 0,
|
|
@@ -50948,13 +51094,18 @@ await guardStartup(logger, async () => {
|
|
|
50948
51094
|
}
|
|
50949
51095
|
}
|
|
50950
51096
|
});
|
|
50951
|
-
sub.
|
|
51097
|
+
sub.checkRunReporter.setOrgPublicAliasResolver(() => platformClient.getOrgPublicAlias());
|
|
50952
51098
|
logPullSendFn = (msg) => platformClient.sendRaw(msg);
|
|
50953
51099
|
dashboardSendFn = (msg) => platformClient.sendRaw(msg);
|
|
50954
51100
|
dashboardEnvSendFn = (msg) => platformClient.sendRaw(msg);
|
|
50955
51101
|
dashboardRegSendFn = (msg) => platformClient.sendRaw(msg);
|
|
50956
51102
|
dashboardBackendsSendFn = (msg) => platformClient.sendRaw(msg);
|
|
50957
51103
|
dashboardGlobalWorkflowsSendFn = (msg) => platformClient.sendRaw(msg);
|
|
51104
|
+
const republishSources = () => {
|
|
51105
|
+
buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config).then((sources) => platformClient.updateSources(sources)).catch((err) => logger.warn("Failed to republish sources to Platform", { error: toErrorMessage(err) }));
|
|
51106
|
+
};
|
|
51107
|
+
sub.sourceManager.setOnSourcesChanged(() => republishSources());
|
|
51108
|
+
sub.genericSourcesChangeListener.setOnChange(() => republishSources());
|
|
50958
51109
|
const metricsReporter = new MetricsReporter({
|
|
50959
51110
|
send: (msg) => platformClient.send(msg),
|
|
50960
51111
|
intervalMs: 3e4,
|
|
@@ -50971,6 +51122,29 @@ await guardStartup(logger, async () => {
|
|
|
50971
51122
|
client.connect();
|
|
50972
51123
|
logger.info("Static peer client dialing", { rawUrl });
|
|
50973
51124
|
}
|
|
51125
|
+
const resolveSourceWebhookUrl = async (params) => {
|
|
51126
|
+
if (params.provider !== "github") return {
|
|
51127
|
+
webhookUrl: null,
|
|
51128
|
+
webhookNote: "unsupported-provider"
|
|
51129
|
+
};
|
|
51130
|
+
try {
|
|
51131
|
+
const fullSources = await buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config);
|
|
51132
|
+
const webhookUrl = await platformClient.registerSourceAndAwait(fullSources, params.routingKey);
|
|
51133
|
+
return webhookUrl ? { webhookUrl } : {
|
|
51134
|
+
webhookUrl: null,
|
|
51135
|
+
webhookNote: "platform-no-public-url"
|
|
51136
|
+
};
|
|
51137
|
+
} catch (err) {
|
|
51138
|
+
logger.warn("Failed to resolve GitHub webhook URL from Platform", {
|
|
51139
|
+
routingKey: params.routingKey,
|
|
51140
|
+
error: toErrorMessage(err)
|
|
51141
|
+
});
|
|
51142
|
+
return {
|
|
51143
|
+
webhookUrl: null,
|
|
51144
|
+
webhookNote: "platform-unavailable"
|
|
51145
|
+
};
|
|
51146
|
+
}
|
|
51147
|
+
};
|
|
50974
51148
|
return {
|
|
50975
51149
|
appDepsExtras: {
|
|
50976
51150
|
platformClient,
|
|
@@ -50978,14 +51152,15 @@ await guardStartup(logger, async () => {
|
|
|
50978
51152
|
variableStore,
|
|
50979
51153
|
heldRunStore,
|
|
50980
51154
|
globalWorkflowPolicy,
|
|
50981
|
-
contributorCache
|
|
51155
|
+
contributorCache,
|
|
51156
|
+
resolveSourceWebhookUrl
|
|
50982
51157
|
},
|
|
50983
51158
|
configReloaderExtras: {
|
|
50984
51159
|
onProviderChange: async (_newConfig, _oldConfig, s) => {
|
|
50985
51160
|
await s.sourceManager.reload();
|
|
50986
51161
|
const newRegistry = s.sourceManager.getRegistry();
|
|
50987
51162
|
s.providerRegistry = newRegistry;
|
|
50988
|
-
s.
|
|
51163
|
+
s.checkRunReporter.updateRegistry(newRegistry);
|
|
50989
51164
|
logger.info("Provider registry reloaded from sources", { routingKeys: newRegistry.getRoutingKeys() });
|
|
50990
51165
|
},
|
|
50991
51166
|
onPlatformReconnect: async (newConfig) => {
|