@kici-dev/orchestrator 0.1.16 → 0.1.17
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/agent/dispatcher.d.ts +18 -1
- package/dist/approvals/apply-decision.d.ts +11 -1
- package/dist/cache/pending-inits.d.ts +5 -0
- package/dist/cli/api-client.d.ts +11 -0
- package/dist/cli/commands/local-hook.d.ts +15 -0
- package/dist/cli/commands/local-trigger.d.ts +24 -0
- package/dist/cli/commands/remote-source.d.ts +17 -0
- package/dist/cli/commands/shared/versioned-upgrade.d.ts +14 -0
- package/dist/cli/kici-admin.d.ts +13 -0
- package/dist/cli.js +726 -177
- package/dist/config.d.ts +0 -4
- package/dist/dashboard/handler.d.ts +26 -2
- package/dist/dashboard/needs-edges.d.ts +13 -0
- package/dist/db/migrations/035_pending_workflow_contexts.d.ts +11 -0
- package/dist/db/migrations/036_attestations.d.ts +15 -0
- package/dist/db/migrations/037_generic_sources_provider_type_local.d.ts +19 -0
- package/dist/db/migrations/038_remote_sources.d.ts +14 -0
- package/dist/db/types.d.ts +83 -10
- package/dist/diagnostics/fleet-collector.d.ts +1 -1
- package/dist/entry-helpers.d.ts +7 -29
- package/dist/environments/held-runs.d.ts +24 -0
- package/dist/index.js +1 -0
- package/dist/metrics/prometheus.d.ts +4 -2
- package/dist/orchestrator-core.d.ts +48 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +18 -1
- package/dist/pipeline/install-secrets-resolver.d.ts +32 -5
- package/dist/pipeline/needs-scheduler.d.ts +12 -10
- package/dist/pipeline/pending-workflow-context.d.ts +44 -0
- package/dist/pipeline/processor.d.ts +6 -4
- package/dist/pipeline/remote-source-store.d.ts +21 -0
- package/dist/pipeline/resume-workflow.d.ts +26 -0
- package/dist/providers/local/index.d.ts +33 -0
- package/dist/providers/local/local-source-config.d.ts +17 -0
- package/dist/providers/{internal → local}/lock-file-fetcher.d.ts +6 -6
- package/dist/providers/{internal → local}/normalizer.d.ts +28 -28
- package/dist/providers/{internal → local}/repo-url-builder.d.ts +6 -6
- package/dist/reporting/execution-tracker.d.ts +33 -0
- package/dist/routes/admin-events.d.ts +3 -4
- package/dist/routes/uploads.d.ts +36 -26
- package/dist/server.js +27910 -26483
- package/dist/sources/build-platform-sources.d.ts +4 -2
- package/dist/stale-detector/stale-run-detector.d.ts +14 -1
- package/dist/standalone.js +15708 -15619
- package/dist/webhook/generic-sources-listener.d.ts +4 -0
- package/dist/webhook/generic-sources.d.ts +37 -11
- package/dist/webhook/register-source-bundle.d.ts +14 -4
- package/dist/ws/agent-handler.d.ts +17 -0
- package/dist/ws/dashboard-dispatch-guard.d.ts +21 -0
- package/dist/ws/dashboard-env-handler.d.ts +13 -1
- package/dist/ws/oidc-token-relay.d.ts +59 -0
- package/dist/ws/platform-client.d.ts +30 -1
- package/dist/ws/test-relay-handlers.d.ts +112 -0
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +98 -48
- package/dist/providers/internal/index.d.ts +0 -32
- package/dist/routes/test-trigger.d.ts +0 -41
- package/dist/ws/observer-handler.d.ts +0 -42
package/dist/cli.js
CHANGED
|
@@ -3,9 +3,9 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import path, { join, resolve } from "node:path";
|
|
6
|
-
import { Command } from "commander";
|
|
7
6
|
import * as fs$1 from "node:fs";
|
|
8
|
-
import fs, { closeSync, createReadStream, createWriteStream, existsSync, openSync, promises, readFileSync, statSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
|
|
7
|
+
import fs, { chmodSync, closeSync, createReadStream, createWriteStream, existsSync, openSync, promises, readFileSync, realpathSync, statSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
|
|
8
|
+
import { Command } from "commander";
|
|
9
9
|
import { BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createDb, createDbRole, createEnvironmentTemplateDirect, createLogger, createPool, createReadOnlyDbUser, decodeChunk, deleteEnvironmentDirect, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, listEnvironmentsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, sha256, showEnvironmentDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
|
|
10
10
|
import crypto, { createDecipheriv, createHash, hkdfSync, randomBytes, randomUUID } from "node:crypto";
|
|
11
11
|
import { createInterface } from "node:readline";
|
|
@@ -52,6 +52,8 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
52
52
|
* error formatting, and URL construction.
|
|
53
53
|
*/
|
|
54
54
|
var AdminApiClient = class {
|
|
55
|
+
baseUrl;
|
|
56
|
+
token;
|
|
55
57
|
constructor(baseUrl, token) {
|
|
56
58
|
this.baseUrl = baseUrl;
|
|
57
59
|
this.token = token;
|
|
@@ -1548,8 +1550,8 @@ var init_client = __esmMin((() => {
|
|
|
1548
1550
|
//#region src/db/migrations/001_initial.ts
|
|
1549
1551
|
init_client();
|
|
1550
1552
|
var _001_initial_exports = /* @__PURE__ */ __exportAll({
|
|
1551
|
-
down: () => down$
|
|
1552
|
-
up: () => up$
|
|
1553
|
+
down: () => down$37,
|
|
1554
|
+
up: () => up$37
|
|
1553
1555
|
});
|
|
1554
1556
|
/**
|
|
1555
1557
|
* Squashed initial migration -- creates the complete Orchestrator database schema.
|
|
@@ -2241,7 +2243,7 @@ const DDL_STATEMENTS = [
|
|
|
2241
2243
|
`ALTER TABLE ONLY public.held_runs
|
|
2242
2244
|
ADD CONSTRAINT held_runs_environment_id_fkey FOREIGN KEY (environment_id) REFERENCES public.environments(id);`
|
|
2243
2245
|
];
|
|
2244
|
-
async function up$
|
|
2246
|
+
async function up$37(db) {
|
|
2245
2247
|
for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
|
|
2246
2248
|
await sql`
|
|
2247
2249
|
INSERT INTO cluster_meta (key, value)
|
|
@@ -2263,7 +2265,7 @@ async function up$33(db) {
|
|
|
2263
2265
|
* Rollback drops everything created above. Uses CASCADE on table drops to cut
|
|
2264
2266
|
* through the FK graph without relying on exact topological order.
|
|
2265
2267
|
*/
|
|
2266
|
-
async function down$
|
|
2268
|
+
async function down$37(db) {
|
|
2267
2269
|
for (const [trig, tbl] of [["source_secrets_change_trigger", "scoped_secrets"], ["sources_change_trigger", "sources"]]) await sql.raw(`DROP TRIGGER IF EXISTS ${trig} ON public.${tbl}`).execute(db);
|
|
2268
2270
|
for (const table of [
|
|
2269
2271
|
"workflow_registrations",
|
|
@@ -2310,8 +2312,8 @@ async function down$33(db) {
|
|
|
2310
2312
|
//#endregion
|
|
2311
2313
|
//#region src/db/migrations/002_config_versions_key_version.ts
|
|
2312
2314
|
var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
|
|
2313
|
-
down: () => down$
|
|
2314
|
-
up: () => up$
|
|
2315
|
+
down: () => down$36,
|
|
2316
|
+
up: () => up$36
|
|
2315
2317
|
});
|
|
2316
2318
|
/**
|
|
2317
2319
|
* Add key_version column to config_versions so that sensitive-field encryption
|
|
@@ -2325,13 +2327,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
|
|
|
2325
2327
|
* No index is needed: rotation does a full-table scan; reads are by
|
|
2326
2328
|
* `version` primary key and never filter on `key_version`.
|
|
2327
2329
|
*/
|
|
2328
|
-
async function up$
|
|
2330
|
+
async function up$36(db) {
|
|
2329
2331
|
await sql`
|
|
2330
2332
|
ALTER TABLE public.config_versions
|
|
2331
2333
|
ADD COLUMN key_version integer NOT NULL DEFAULT 1
|
|
2332
2334
|
`.execute(db);
|
|
2333
2335
|
}
|
|
2334
|
-
async function down$
|
|
2336
|
+
async function down$36(db) {
|
|
2335
2337
|
await sql`
|
|
2336
2338
|
ALTER TABLE public.config_versions
|
|
2337
2339
|
DROP COLUMN key_version
|
|
@@ -2340,8 +2342,8 @@ async function down$32(db) {
|
|
|
2340
2342
|
//#endregion
|
|
2341
2343
|
//#region src/db/migrations/003_access_log.ts
|
|
2342
2344
|
var _003_access_log_exports = /* @__PURE__ */ __exportAll({
|
|
2343
|
-
down: () => down$
|
|
2344
|
-
up: () => up$
|
|
2345
|
+
down: () => down$35,
|
|
2346
|
+
up: () => up$35
|
|
2345
2347
|
});
|
|
2346
2348
|
/**
|
|
2347
2349
|
* Access log: one row per read or orchestrator-admin mutation attributable
|
|
@@ -2365,7 +2367,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
|
|
|
2365
2367
|
* Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
|
|
2366
2368
|
* cleanup.ts picks up the prune pass.
|
|
2367
2369
|
*/
|
|
2368
|
-
async function up$
|
|
2370
|
+
async function up$35(db) {
|
|
2369
2371
|
await sql`
|
|
2370
2372
|
CREATE TABLE public.access_log (
|
|
2371
2373
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
@@ -2403,28 +2405,28 @@ async function up$31(db) {
|
|
|
2403
2405
|
ON public.access_log (actor_type, actor_id, created_at DESC)
|
|
2404
2406
|
`.execute(db);
|
|
2405
2407
|
}
|
|
2406
|
-
async function down$
|
|
2408
|
+
async function down$35(db) {
|
|
2407
2409
|
await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
|
|
2408
2410
|
}
|
|
2409
2411
|
//#endregion
|
|
2410
2412
|
//#region src/db/migrations/004_rename_bundle_to_source.ts
|
|
2411
2413
|
var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
|
|
2412
|
-
down: () => down$
|
|
2413
|
-
up: () => up$
|
|
2414
|
+
down: () => down$34,
|
|
2415
|
+
up: () => up$34
|
|
2414
2416
|
});
|
|
2415
|
-
async function up$
|
|
2417
|
+
async function up$34(db) {
|
|
2416
2418
|
await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
|
|
2417
2419
|
await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
|
|
2418
2420
|
}
|
|
2419
|
-
async function down$
|
|
2421
|
+
async function down$34(db) {
|
|
2420
2422
|
await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
|
|
2421
2423
|
await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
|
|
2422
2424
|
}
|
|
2423
2425
|
//#endregion
|
|
2424
2426
|
//#region src/db/migrations/005_cold_store_chunk_counter.ts
|
|
2425
2427
|
var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
|
|
2426
|
-
down: () => down$
|
|
2427
|
-
up: () => up$
|
|
2428
|
+
down: () => down$33,
|
|
2429
|
+
up: () => up$33
|
|
2428
2430
|
});
|
|
2429
2431
|
/**
|
|
2430
2432
|
* Cold-store chunk counter table.
|
|
@@ -2441,7 +2443,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
|
|
|
2441
2443
|
*
|
|
2442
2444
|
* sections 5 and 8.
|
|
2443
2445
|
*/
|
|
2444
|
-
async function up$
|
|
2446
|
+
async function up$33(db) {
|
|
2445
2447
|
await sql`
|
|
2446
2448
|
CREATE TABLE public.cold_store_chunk_counts (
|
|
2447
2449
|
db TEXT NOT NULL,
|
|
@@ -2459,14 +2461,14 @@ async function up$29(db) {
|
|
|
2459
2461
|
ON public.cold_store_chunk_counts (db, table_name)
|
|
2460
2462
|
`.execute(db);
|
|
2461
2463
|
}
|
|
2462
|
-
async function down$
|
|
2464
|
+
async function down$33(db) {
|
|
2463
2465
|
await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
|
|
2464
2466
|
}
|
|
2465
2467
|
//#endregion
|
|
2466
2468
|
//#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
|
|
2467
2469
|
var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2468
|
-
down: () => down$
|
|
2469
|
-
up: () => up$
|
|
2470
|
+
down: () => down$32,
|
|
2471
|
+
up: () => up$32
|
|
2470
2472
|
});
|
|
2471
2473
|
/**
|
|
2472
2474
|
* `execution_runs` / `execution_jobs` / `execution_steps` cold-store
|
|
@@ -2502,7 +2504,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2502
2504
|
* - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
|
|
2503
2505
|
* - `idx_execution_steps_routing_key_created (routing_key, created_at)`
|
|
2504
2506
|
*/
|
|
2505
|
-
async function up$
|
|
2507
|
+
async function up$32(db) {
|
|
2506
2508
|
await sql`
|
|
2507
2509
|
ALTER TABLE public.execution_runs
|
|
2508
2510
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2547,7 +2549,7 @@ async function up$28(db) {
|
|
|
2547
2549
|
ON public.execution_steps (routing_key, created_at)
|
|
2548
2550
|
`.execute(db);
|
|
2549
2551
|
}
|
|
2550
|
-
async function down$
|
|
2552
|
+
async function down$32(db) {
|
|
2551
2553
|
await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
|
|
2552
2554
|
await sql`
|
|
2553
2555
|
ALTER TABLE public.execution_steps
|
|
@@ -2572,8 +2574,8 @@ async function down$28(db) {
|
|
|
2572
2574
|
//#endregion
|
|
2573
2575
|
//#region src/db/migrations/007_audit_logs_archived_at.ts
|
|
2574
2576
|
var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2575
|
-
down: () => down$
|
|
2576
|
-
up: () => up$
|
|
2577
|
+
down: () => down$31,
|
|
2578
|
+
up: () => up$31
|
|
2577
2579
|
});
|
|
2578
2580
|
/**
|
|
2579
2581
|
* `secret_audit_log` and `access_log` cold-store schema additions, plus
|
|
@@ -2613,7 +2615,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2613
2615
|
* `down()` would not have meaningful retention bounds. Acceptable for
|
|
2614
2616
|
* staging.
|
|
2615
2617
|
*/
|
|
2616
|
-
async function up$
|
|
2618
|
+
async function up$31(db) {
|
|
2617
2619
|
await sql`
|
|
2618
2620
|
ALTER TABLE public.secret_audit_log
|
|
2619
2621
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2634,7 +2636,7 @@ async function up$27(db) {
|
|
|
2634
2636
|
DROP COLUMN IF EXISTS expires_at
|
|
2635
2637
|
`.execute(db);
|
|
2636
2638
|
}
|
|
2637
|
-
async function down$
|
|
2639
|
+
async function down$31(db) {
|
|
2638
2640
|
await sql`
|
|
2639
2641
|
ALTER TABLE public.access_log
|
|
2640
2642
|
ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
|
|
@@ -2662,8 +2664,8 @@ async function down$27(db) {
|
|
|
2662
2664
|
//#endregion
|
|
2663
2665
|
//#region src/db/migrations/008_event_log_archived_at.ts
|
|
2664
2666
|
var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2665
|
-
down: () => down$
|
|
2666
|
-
up: () => up$
|
|
2667
|
+
down: () => down$30,
|
|
2668
|
+
up: () => up$30
|
|
2667
2669
|
});
|
|
2668
2670
|
/**
|
|
2669
2671
|
* `event_log` cold-store schema additions plus removal of the
|
|
@@ -2701,7 +2703,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2701
2703
|
* — best effort; rows inserted between `up()` and a hypothetical
|
|
2702
2704
|
* `down()` would not have meaningful retention bounds.
|
|
2703
2705
|
*/
|
|
2704
|
-
async function up$
|
|
2706
|
+
async function up$30(db) {
|
|
2705
2707
|
await sql`
|
|
2706
2708
|
ALTER TABLE public.event_log
|
|
2707
2709
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2717,7 +2719,7 @@ async function up$26(db) {
|
|
|
2717
2719
|
DROP COLUMN IF EXISTS expires_at
|
|
2718
2720
|
`.execute(db);
|
|
2719
2721
|
}
|
|
2720
|
-
async function down$
|
|
2722
|
+
async function down$30(db) {
|
|
2721
2723
|
await sql`
|
|
2722
2724
|
ALTER TABLE public.event_log
|
|
2723
2725
|
ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
|
|
@@ -2736,8 +2738,8 @@ async function down$26(db) {
|
|
|
2736
2738
|
//#endregion
|
|
2737
2739
|
//#region src/db/migrations/009_access_log_trigram.ts
|
|
2738
2740
|
var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
|
|
2739
|
-
down: () => down$
|
|
2740
|
-
up: () => up$
|
|
2741
|
+
down: () => down$29,
|
|
2742
|
+
up: () => up$29
|
|
2741
2743
|
});
|
|
2742
2744
|
/**
|
|
2743
2745
|
* Trigram (pg_trgm) index on access_log.error_message for the federated
|
|
@@ -2750,7 +2752,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
|
|
|
2750
2752
|
* EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
|
|
2751
2753
|
* migrations inside a transaction; the lock is brief on a sampled table.
|
|
2752
2754
|
*/
|
|
2753
|
-
async function up$
|
|
2755
|
+
async function up$29(db) {
|
|
2754
2756
|
await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
|
|
2755
2757
|
await sql`
|
|
2756
2758
|
CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
|
|
@@ -2759,14 +2761,14 @@ async function up$25(db) {
|
|
|
2759
2761
|
WHERE error_message IS NOT NULL
|
|
2760
2762
|
`.execute(db);
|
|
2761
2763
|
}
|
|
2762
|
-
async function down$
|
|
2764
|
+
async function down$29(db) {
|
|
2763
2765
|
await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
|
|
2764
2766
|
}
|
|
2765
2767
|
//#endregion
|
|
2766
2768
|
//#region src/db/migrations/010_cold_store_chunks.ts
|
|
2767
2769
|
var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
|
|
2768
|
-
down: () => down$
|
|
2769
|
-
up: () => up$
|
|
2770
|
+
down: () => down$28,
|
|
2771
|
+
up: () => up$28
|
|
2770
2772
|
});
|
|
2771
2773
|
/**
|
|
2772
2774
|
* Cold-store chunk index — Phase 2 (cold-store purge).
|
|
@@ -2798,7 +2800,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
|
|
|
2798
2800
|
* forever. Adapters that don't opt into per-bucket archival via
|
|
2799
2801
|
* `coldTtlDays` don't insert here either.
|
|
2800
2802
|
*/
|
|
2801
|
-
async function up$
|
|
2803
|
+
async function up$28(db) {
|
|
2802
2804
|
await sql`
|
|
2803
2805
|
CREATE TABLE public.cold_store_chunks (
|
|
2804
2806
|
db TEXT NOT NULL,
|
|
@@ -2825,14 +2827,14 @@ async function up$24(db) {
|
|
|
2825
2827
|
ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
|
|
2826
2828
|
`.execute(db);
|
|
2827
2829
|
}
|
|
2828
|
-
async function down$
|
|
2830
|
+
async function down$28(db) {
|
|
2829
2831
|
await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
|
|
2830
2832
|
}
|
|
2831
2833
|
//#endregion
|
|
2832
2834
|
//#region src/db/migrations/011_drop_source_secrets_notify.ts
|
|
2833
2835
|
var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
|
|
2834
|
-
down: () => down$
|
|
2835
|
-
up: () => up$
|
|
2836
|
+
down: () => down$27,
|
|
2837
|
+
up: () => up$27
|
|
2836
2838
|
});
|
|
2837
2839
|
/**
|
|
2838
2840
|
* Drop the `source_secrets_change_trigger` and the
|
|
@@ -2851,11 +2853,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
|
|
|
2851
2853
|
* in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
|
|
2852
2854
|
* is restored, so this migration is safe to roll back.
|
|
2853
2855
|
*/
|
|
2854
|
-
async function up$
|
|
2856
|
+
async function up$27(db) {
|
|
2855
2857
|
await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
|
|
2856
2858
|
await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
|
|
2857
2859
|
}
|
|
2858
|
-
async function down$
|
|
2860
|
+
async function down$27(db) {
|
|
2859
2861
|
await sql`
|
|
2860
2862
|
CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
|
|
2861
2863
|
LANGUAGE plpgsql
|
|
@@ -2894,8 +2896,8 @@ async function down$23(db) {
|
|
|
2894
2896
|
//#endregion
|
|
2895
2897
|
//#region src/db/migrations/012_peer_credentials_active_uniq.ts
|
|
2896
2898
|
var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
|
|
2897
|
-
down: () => down$
|
|
2898
|
-
up: () => up$
|
|
2899
|
+
down: () => down$26,
|
|
2900
|
+
up: () => up$26
|
|
2899
2901
|
});
|
|
2900
2902
|
/**
|
|
2901
2903
|
* Add a partial unique index on `peer_credentials (instance_id) WHERE
|
|
@@ -2921,7 +2923,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
|
|
|
2921
2923
|
* `down()` only drops the index; it does NOT undo the dedupe (there's no
|
|
2922
2924
|
* safe way to recreate revoked rows, and the dedupe is monotonic).
|
|
2923
2925
|
*/
|
|
2924
|
-
async function up$
|
|
2926
|
+
async function up$26(db) {
|
|
2925
2927
|
await sql`
|
|
2926
2928
|
UPDATE public.peer_credentials
|
|
2927
2929
|
SET revoked_at = NOW()
|
|
@@ -2939,14 +2941,14 @@ async function up$22(db) {
|
|
|
2939
2941
|
WHERE revoked_at IS NULL
|
|
2940
2942
|
`.execute(db);
|
|
2941
2943
|
}
|
|
2942
|
-
async function down$
|
|
2944
|
+
async function down$26(db) {
|
|
2943
2945
|
await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
|
|
2944
2946
|
}
|
|
2945
2947
|
//#endregion
|
|
2946
2948
|
//#region src/db/migrations/013_execution_log_bytes.ts
|
|
2947
2949
|
var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
|
|
2948
|
-
down: () => down$
|
|
2949
|
-
up: () => up$
|
|
2950
|
+
down: () => down$25,
|
|
2951
|
+
up: () => up$25
|
|
2950
2952
|
});
|
|
2951
2953
|
/**
|
|
2952
2954
|
* Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
|
|
@@ -2965,7 +2967,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
|
|
|
2965
2967
|
*
|
|
2966
2968
|
* Idempotent (`ADD COLUMN IF NOT EXISTS`).
|
|
2967
2969
|
*/
|
|
2968
|
-
async function up$
|
|
2970
|
+
async function up$25(db) {
|
|
2969
2971
|
await sql`
|
|
2970
2972
|
ALTER TABLE public.execution_runs
|
|
2971
2973
|
ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
|
|
@@ -2975,15 +2977,15 @@ async function up$21(db) {
|
|
|
2975
2977
|
ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
|
|
2976
2978
|
`.execute(db);
|
|
2977
2979
|
}
|
|
2978
|
-
async function down$
|
|
2980
|
+
async function down$25(db) {
|
|
2979
2981
|
await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
|
|
2980
2982
|
await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
|
|
2981
2983
|
}
|
|
2982
2984
|
//#endregion
|
|
2983
2985
|
//#region src/db/migrations/014_kici_events_lease_retry.ts
|
|
2984
2986
|
var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
|
|
2985
|
-
down: () => down$
|
|
2986
|
-
up: () => up$
|
|
2987
|
+
down: () => down$24,
|
|
2988
|
+
up: () => up$24
|
|
2987
2989
|
});
|
|
2988
2990
|
/**
|
|
2989
2991
|
* Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
|
|
@@ -3017,7 +3019,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
|
|
|
3017
3019
|
*
|
|
3018
3020
|
* Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
|
|
3019
3021
|
*/
|
|
3020
|
-
async function up$
|
|
3022
|
+
async function up$24(db) {
|
|
3021
3023
|
await sql`
|
|
3022
3024
|
ALTER TABLE public.kici_events
|
|
3023
3025
|
ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
|
|
@@ -3048,7 +3050,7 @@ async function up$20(db) {
|
|
|
3048
3050
|
WHERE dlq_at IS NOT NULL
|
|
3049
3051
|
`.execute(db);
|
|
3050
3052
|
}
|
|
3051
|
-
async function down$
|
|
3053
|
+
async function down$24(db) {
|
|
3052
3054
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
|
|
3053
3055
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
|
|
3054
3056
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
|
|
@@ -3066,8 +3068,8 @@ async function down$20(db) {
|
|
|
3066
3068
|
//#endregion
|
|
3067
3069
|
//#region src/db/migrations/015_org_settings_customer_scoped.ts
|
|
3068
3070
|
var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
|
|
3069
|
-
down: () => down$
|
|
3070
|
-
up: () => up$
|
|
3071
|
+
down: () => down$23,
|
|
3072
|
+
up: () => up$23
|
|
3071
3073
|
});
|
|
3072
3074
|
/**
|
|
3073
3075
|
* Org-scope `org_settings` and qualify each glob entry by source.
|
|
@@ -3095,7 +3097,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
|
|
|
3095
3097
|
* Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
|
|
3096
3098
|
* and the list columns are already jsonb, so it is a no-op.
|
|
3097
3099
|
*/
|
|
3098
|
-
async function up$
|
|
3100
|
+
async function up$23(db) {
|
|
3099
3101
|
if ((await sql`
|
|
3100
3102
|
SELECT EXISTS (
|
|
3101
3103
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3220,7 +3222,7 @@ async function up$19(db) {
|
|
|
3220
3222
|
await sql`DROP TABLE _org_settings_merged`.execute(db);
|
|
3221
3223
|
await sql`DROP TABLE _org_settings_stage`.execute(db);
|
|
3222
3224
|
}
|
|
3223
|
-
async function down$
|
|
3225
|
+
async function down$23(db) {
|
|
3224
3226
|
if (!(await sql`
|
|
3225
3227
|
SELECT EXISTS (
|
|
3226
3228
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3245,8 +3247,8 @@ async function down$19(db) {
|
|
|
3245
3247
|
//#endregion
|
|
3246
3248
|
//#region src/db/migrations/016_org_settings_allow_http_npm.ts
|
|
3247
3249
|
var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
|
|
3248
|
-
down: () => down$
|
|
3249
|
-
up: () => up$
|
|
3250
|
+
down: () => down$22,
|
|
3251
|
+
up: () => up$22
|
|
3250
3252
|
});
|
|
3251
3253
|
/**
|
|
3252
3254
|
* Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
|
|
@@ -3259,7 +3261,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
|
|
|
3259
3261
|
*
|
|
3260
3262
|
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
3261
3263
|
*/
|
|
3262
|
-
async function up$
|
|
3264
|
+
async function up$22(db) {
|
|
3263
3265
|
if ((await sql`
|
|
3264
3266
|
SELECT EXISTS (
|
|
3265
3267
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3273,7 +3275,7 @@ async function up$18(db) {
|
|
|
3273
3275
|
ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
|
|
3274
3276
|
`.execute(db);
|
|
3275
3277
|
}
|
|
3276
|
-
async function down$
|
|
3278
|
+
async function down$22(db) {
|
|
3277
3279
|
await sql`
|
|
3278
3280
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
|
|
3279
3281
|
`.execute(db);
|
|
@@ -3281,8 +3283,8 @@ async function down$18(db) {
|
|
|
3281
3283
|
//#endregion
|
|
3282
3284
|
//#region src/db/migrations/017_org_id_widen.ts
|
|
3283
3285
|
var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
|
|
3284
|
-
down: () => down$
|
|
3285
|
-
up: () => up$
|
|
3286
|
+
down: () => down$21,
|
|
3287
|
+
up: () => up$21
|
|
3286
3288
|
});
|
|
3287
3289
|
/**
|
|
3288
3290
|
* Widen every orchestrator-side `org_id varchar(12)` column to
|
|
@@ -3322,17 +3324,17 @@ const ORG_ID_TABLES$1 = [
|
|
|
3322
3324
|
"held_runs",
|
|
3323
3325
|
"scoped_secrets"
|
|
3324
3326
|
];
|
|
3325
|
-
async function up$
|
|
3327
|
+
async function up$21(db) {
|
|
3326
3328
|
for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
|
|
3327
3329
|
}
|
|
3328
|
-
async function down$
|
|
3330
|
+
async function down$21(db) {
|
|
3329
3331
|
for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
|
|
3330
3332
|
}
|
|
3331
3333
|
//#endregion
|
|
3332
3334
|
//#region src/db/migrations/018_org_id_prefix_backfill.ts
|
|
3333
3335
|
var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
|
|
3334
|
-
down: () => down$
|
|
3335
|
-
up: () => up$
|
|
3336
|
+
down: () => down$20,
|
|
3337
|
+
up: () => up$20
|
|
3336
3338
|
});
|
|
3337
3339
|
/**
|
|
3338
3340
|
* Prefix every orchestrator-side tenant string with `org_` to align
|
|
@@ -3377,19 +3379,19 @@ const CUSTOMER_ID_TABLES = [
|
|
|
3377
3379
|
"workflow_registrations",
|
|
3378
3380
|
"org_settings"
|
|
3379
3381
|
];
|
|
3380
|
-
async function up$
|
|
3382
|
+
async function up$20(db) {
|
|
3381
3383
|
for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = 'org_' || org_id WHERE org_id <> 'kici-admin' AND org_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3382
3384
|
for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = 'org_' || customer_id WHERE customer_id <> 'kici-admin' AND customer_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3383
3385
|
}
|
|
3384
|
-
async function down$
|
|
3386
|
+
async function down$20(db) {
|
|
3385
3387
|
for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = substring(customer_id from 5) WHERE customer_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3386
3388
|
for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = substring(org_id from 5) WHERE org_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3387
3389
|
}
|
|
3388
3390
|
//#endregion
|
|
3389
3391
|
//#region src/db/migrations/019_generic_sources_change_notify.ts
|
|
3390
3392
|
var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
|
|
3391
|
-
down: () => down$
|
|
3392
|
-
up: () => up$
|
|
3393
|
+
down: () => down$19,
|
|
3394
|
+
up: () => up$19
|
|
3393
3395
|
});
|
|
3394
3396
|
/**
|
|
3395
3397
|
* Add a Postgres trigger on `generic_webhook_sources` that emits
|
|
@@ -3412,7 +3414,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
|
|
|
3412
3414
|
* (`notify_sources_change()` + `sources_change_trigger`, defined in
|
|
3413
3415
|
* `001_initial.ts`).
|
|
3414
3416
|
*/
|
|
3415
|
-
async function up$
|
|
3417
|
+
async function up$19(db) {
|
|
3416
3418
|
await sql`
|
|
3417
3419
|
CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
|
|
3418
3420
|
LANGUAGE plpgsql
|
|
@@ -3433,15 +3435,15 @@ async function up$15(db) {
|
|
|
3433
3435
|
FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
|
|
3434
3436
|
`.execute(db);
|
|
3435
3437
|
}
|
|
3436
|
-
async function down$
|
|
3438
|
+
async function down$19(db) {
|
|
3437
3439
|
await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
|
|
3438
3440
|
await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
|
|
3439
3441
|
}
|
|
3440
3442
|
//#endregion
|
|
3441
3443
|
//#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
|
|
3442
3444
|
var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
|
|
3443
|
-
down: () => down$
|
|
3444
|
-
up: () => up$
|
|
3445
|
+
down: () => down$18,
|
|
3446
|
+
up: () => up$18
|
|
3445
3447
|
});
|
|
3446
3448
|
/**
|
|
3447
3449
|
* Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
|
|
@@ -3456,7 +3458,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
|
|
|
3456
3458
|
*
|
|
3457
3459
|
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
3458
3460
|
*/
|
|
3459
|
-
async function up$
|
|
3461
|
+
async function up$18(db) {
|
|
3460
3462
|
if ((await sql`
|
|
3461
3463
|
SELECT EXISTS (
|
|
3462
3464
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3470,7 +3472,7 @@ async function up$14(db) {
|
|
|
3470
3472
|
ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
|
|
3471
3473
|
`.execute(db);
|
|
3472
3474
|
}
|
|
3473
|
-
async function down$
|
|
3475
|
+
async function down$18(db) {
|
|
3474
3476
|
await sql`
|
|
3475
3477
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
|
|
3476
3478
|
`.execute(db);
|
|
@@ -3478,8 +3480,8 @@ async function down$14(db) {
|
|
|
3478
3480
|
//#endregion
|
|
3479
3481
|
//#region src/db/migrations/021_check_run_tracking.ts
|
|
3480
3482
|
var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
|
|
3481
|
-
down: () => down$
|
|
3482
|
-
up: () => up$
|
|
3483
|
+
down: () => down$17,
|
|
3484
|
+
up: () => up$17
|
|
3483
3485
|
});
|
|
3484
3486
|
/**
|
|
3485
3487
|
* Add `check_run_tracking` table for HA-safe check-run state persistence.
|
|
@@ -3503,7 +3505,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
|
|
|
3503
3505
|
*
|
|
3504
3506
|
* Idempotent: a re-run on a DB that already has the table is a no-op.
|
|
3505
3507
|
*/
|
|
3506
|
-
async function up$
|
|
3508
|
+
async function up$17(db) {
|
|
3507
3509
|
if ((await sql`
|
|
3508
3510
|
SELECT EXISTS (
|
|
3509
3511
|
SELECT 1 FROM information_schema.tables
|
|
@@ -3534,14 +3536,14 @@ async function up$13(db) {
|
|
|
3534
3536
|
WHERE run_id IS NOT NULL
|
|
3535
3537
|
`.execute(db);
|
|
3536
3538
|
}
|
|
3537
|
-
async function down$
|
|
3539
|
+
async function down$17(db) {
|
|
3538
3540
|
await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
|
|
3539
3541
|
}
|
|
3540
3542
|
//#endregion
|
|
3541
3543
|
//#region src/db/migrations/022_scaler_manager_state.ts
|
|
3542
3544
|
var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
|
|
3543
|
-
down: () => down$
|
|
3544
|
-
up: () => up$
|
|
3545
|
+
down: () => down$16,
|
|
3546
|
+
up: () => up$16
|
|
3545
3547
|
});
|
|
3546
3548
|
/**
|
|
3547
3549
|
* Add three tables persisting `ScalerManager` per-coord state:
|
|
@@ -3568,7 +3570,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
|
|
|
3568
3570
|
* Idempotent: a re-run on a DB that already has any of these tables
|
|
3569
3571
|
* leaves the existing one alone.
|
|
3570
3572
|
*/
|
|
3571
|
-
async function up$
|
|
3573
|
+
async function up$16(db) {
|
|
3572
3574
|
const tableExists = async (name) => {
|
|
3573
3575
|
return (await sql`
|
|
3574
3576
|
SELECT EXISTS (
|
|
@@ -3618,7 +3620,7 @@ async function up$12(db) {
|
|
|
3618
3620
|
`.execute(db);
|
|
3619
3621
|
}
|
|
3620
3622
|
}
|
|
3621
|
-
async function down$
|
|
3623
|
+
async function down$16(db) {
|
|
3622
3624
|
await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
|
|
3623
3625
|
await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
|
|
3624
3626
|
await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
|
|
@@ -3626,8 +3628,8 @@ async function down$12(db) {
|
|
|
3626
3628
|
//#endregion
|
|
3627
3629
|
//#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
|
|
3628
3630
|
var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
|
|
3629
|
-
down: () => down$
|
|
3630
|
-
up: () => up$
|
|
3631
|
+
down: () => down$15,
|
|
3632
|
+
up: () => up$15
|
|
3631
3633
|
});
|
|
3632
3634
|
/**
|
|
3633
3635
|
* Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
|
|
@@ -3651,7 +3653,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
|
|
|
3651
3653
|
* Idempotent: re-running on a DB that already has either column is a
|
|
3652
3654
|
* no-op.
|
|
3653
3655
|
*/
|
|
3654
|
-
async function up$
|
|
3656
|
+
async function up$15(db) {
|
|
3655
3657
|
const colExists = async (name) => {
|
|
3656
3658
|
return (await sql`
|
|
3657
3659
|
SELECT EXISTS (
|
|
@@ -3676,7 +3678,7 @@ async function up$11(db) {
|
|
|
3676
3678
|
WHERE recovery_deadline IS NOT NULL
|
|
3677
3679
|
`.execute(db);
|
|
3678
3680
|
}
|
|
3679
|
-
async function down$
|
|
3681
|
+
async function down$15(db) {
|
|
3680
3682
|
await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
|
|
3681
3683
|
await sql`
|
|
3682
3684
|
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
|
|
@@ -3688,8 +3690,8 @@ async function down$11(db) {
|
|
|
3688
3690
|
//#endregion
|
|
3689
3691
|
//#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
|
|
3690
3692
|
var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
|
|
3691
|
-
down: () => down$
|
|
3692
|
-
up: () => up$
|
|
3693
|
+
down: () => down$14,
|
|
3694
|
+
up: () => up$14
|
|
3693
3695
|
});
|
|
3694
3696
|
/**
|
|
3695
3697
|
* Add `dispatch_queue.last_provisioning_error TEXT` recording the most
|
|
@@ -3705,7 +3707,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
|
|
|
3705
3707
|
*
|
|
3706
3708
|
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3707
3709
|
*/
|
|
3708
|
-
async function up$
|
|
3710
|
+
async function up$14(db) {
|
|
3709
3711
|
const colExists = async (name) => {
|
|
3710
3712
|
return (await sql`
|
|
3711
3713
|
SELECT EXISTS (
|
|
@@ -3721,7 +3723,7 @@ async function up$10(db) {
|
|
|
3721
3723
|
ADD COLUMN last_provisioning_error TEXT
|
|
3722
3724
|
`.execute(db);
|
|
3723
3725
|
}
|
|
3724
|
-
async function down$
|
|
3726
|
+
async function down$14(db) {
|
|
3725
3727
|
await sql`
|
|
3726
3728
|
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
|
|
3727
3729
|
`.execute(db);
|
|
@@ -3729,8 +3731,8 @@ async function down$10(db) {
|
|
|
3729
3731
|
//#endregion
|
|
3730
3732
|
//#region src/db/migrations/025_init_failure.ts
|
|
3731
3733
|
var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
|
|
3732
|
-
down: () => down$
|
|
3733
|
-
up: () => up$
|
|
3734
|
+
down: () => down$13,
|
|
3735
|
+
up: () => up$13
|
|
3734
3736
|
});
|
|
3735
3737
|
/**
|
|
3736
3738
|
* Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
|
|
@@ -3744,7 +3746,7 @@ var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
|
|
|
3744
3746
|
* Idempotent: re-running on a DB that already has either column is a no-op
|
|
3745
3747
|
* for that column.
|
|
3746
3748
|
*/
|
|
3747
|
-
async function up$
|
|
3749
|
+
async function up$13(db) {
|
|
3748
3750
|
const colExists = async (table, name) => {
|
|
3749
3751
|
return (await sql`
|
|
3750
3752
|
SELECT EXISTS (
|
|
@@ -3764,7 +3766,7 @@ async function up$9(db) {
|
|
|
3764
3766
|
ADD COLUMN init_failure JSONB DEFAULT NULL
|
|
3765
3767
|
`.execute(db);
|
|
3766
3768
|
}
|
|
3767
|
-
async function down$
|
|
3769
|
+
async function down$13(db) {
|
|
3768
3770
|
await sql`
|
|
3769
3771
|
ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
|
|
3770
3772
|
`.execute(db);
|
|
@@ -3775,8 +3777,8 @@ async function down$9(db) {
|
|
|
3775
3777
|
//#endregion
|
|
3776
3778
|
//#region src/db/migrations/026_event_log_lockfile_corrupt.ts
|
|
3777
3779
|
var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
|
|
3778
|
-
down: () => down$
|
|
3779
|
-
up: () => up$
|
|
3780
|
+
down: () => down$12,
|
|
3781
|
+
up: () => up$12
|
|
3780
3782
|
});
|
|
3781
3783
|
/**
|
|
3782
3784
|
* Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
|
|
@@ -3785,7 +3787,7 @@ var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
|
|
|
3785
3787
|
*
|
|
3786
3788
|
* Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
|
|
3787
3789
|
*/
|
|
3788
|
-
async function up$
|
|
3790
|
+
async function up$12(db) {
|
|
3789
3791
|
await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
|
|
3790
3792
|
await sql`
|
|
3791
3793
|
ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
|
|
@@ -3795,7 +3797,7 @@ async function up$8(db) {
|
|
|
3795
3797
|
])))
|
|
3796
3798
|
`.execute(db);
|
|
3797
3799
|
}
|
|
3798
|
-
async function down$
|
|
3800
|
+
async function down$12(db) {
|
|
3799
3801
|
await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
|
|
3800
3802
|
await sql`
|
|
3801
3803
|
ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
|
|
@@ -3808,8 +3810,8 @@ async function down$8(db) {
|
|
|
3808
3810
|
//#endregion
|
|
3809
3811
|
//#region src/db/migrations/027_workflow_timeout.ts
|
|
3810
3812
|
var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
|
|
3811
|
-
down: () => down$
|
|
3812
|
-
up: () => up$
|
|
3813
|
+
down: () => down$11,
|
|
3814
|
+
up: () => up$11
|
|
3813
3815
|
});
|
|
3814
3816
|
/**
|
|
3815
3817
|
* Add `workflow_timeout_ms integer` to `execution_runs`.
|
|
@@ -3827,13 +3829,13 @@ var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
|
|
|
3827
3829
|
*
|
|
3828
3830
|
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3829
3831
|
*/
|
|
3830
|
-
async function up$
|
|
3832
|
+
async function up$11(db) {
|
|
3831
3833
|
await sql`
|
|
3832
3834
|
ALTER TABLE public.execution_runs
|
|
3833
3835
|
ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
|
|
3834
3836
|
`.execute(db);
|
|
3835
3837
|
}
|
|
3836
|
-
async function down$
|
|
3838
|
+
async function down$11(db) {
|
|
3837
3839
|
await sql`
|
|
3838
3840
|
ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
|
|
3839
3841
|
`.execute(db);
|
|
@@ -3841,8 +3843,8 @@ async function down$7(db) {
|
|
|
3841
3843
|
//#endregion
|
|
3842
3844
|
//#region src/db/migrations/028_org_settings_user_cache.ts
|
|
3843
3845
|
var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
|
|
3844
|
-
down: () => down$
|
|
3845
|
-
up: () => up$
|
|
3846
|
+
down: () => down$10,
|
|
3847
|
+
up: () => up$10
|
|
3846
3848
|
});
|
|
3847
3849
|
/**
|
|
3848
3850
|
* Add `org_settings.user_cache_quota_bytes bigint` and
|
|
@@ -3871,7 +3873,7 @@ async function columnExists(db, column) {
|
|
|
3871
3873
|
) AS exists
|
|
3872
3874
|
`.execute(db)).rows[0]?.exists ?? false;
|
|
3873
3875
|
}
|
|
3874
|
-
async function up$
|
|
3876
|
+
async function up$10(db) {
|
|
3875
3877
|
if (!await columnExists(db, "user_cache_quota_bytes")) await sql`
|
|
3876
3878
|
ALTER TABLE public.org_settings
|
|
3877
3879
|
ADD COLUMN user_cache_quota_bytes bigint
|
|
@@ -3881,7 +3883,7 @@ async function up$6(db) {
|
|
|
3881
3883
|
ADD COLUMN user_cache_ttl_ms bigint
|
|
3882
3884
|
`.execute(db);
|
|
3883
3885
|
}
|
|
3884
|
-
async function down$
|
|
3886
|
+
async function down$10(db) {
|
|
3885
3887
|
await sql`
|
|
3886
3888
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
|
|
3887
3889
|
`.execute(db);
|
|
@@ -3892,8 +3894,8 @@ async function down$6(db) {
|
|
|
3892
3894
|
//#endregion
|
|
3893
3895
|
//#region src/db/migrations/029_dispatch_queue_attempts.ts
|
|
3894
3896
|
var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
|
|
3895
|
-
down: () => down$
|
|
3896
|
-
up: () => up$
|
|
3897
|
+
down: () => down$9,
|
|
3898
|
+
up: () => up$9
|
|
3897
3899
|
});
|
|
3898
3900
|
/**
|
|
3899
3901
|
* Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
|
|
@@ -3907,7 +3909,7 @@ var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
|
|
|
3907
3909
|
*
|
|
3908
3910
|
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3909
3911
|
*/
|
|
3910
|
-
async function up$
|
|
3912
|
+
async function up$9(db) {
|
|
3911
3913
|
if (!((await sql`
|
|
3912
3914
|
SELECT EXISTS (
|
|
3913
3915
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3920,7 +3922,7 @@ async function up$5(db) {
|
|
|
3920
3922
|
ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
|
|
3921
3923
|
`.execute(db);
|
|
3922
3924
|
}
|
|
3923
|
-
async function down$
|
|
3925
|
+
async function down$9(db) {
|
|
3924
3926
|
await sql`
|
|
3925
3927
|
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
|
|
3926
3928
|
`.execute(db);
|
|
@@ -3928,8 +3930,8 @@ async function down$5(db) {
|
|
|
3928
3930
|
//#endregion
|
|
3929
3931
|
//#region src/db/migrations/030_held_runs_env_set_null.ts
|
|
3930
3932
|
var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
|
|
3931
|
-
down: () => down$
|
|
3932
|
-
up: () => up$
|
|
3933
|
+
down: () => down$8,
|
|
3934
|
+
up: () => up$8
|
|
3933
3935
|
});
|
|
3934
3936
|
/**
|
|
3935
3937
|
* held_runs.environment_id becomes nullable with ON DELETE SET NULL so
|
|
@@ -3940,14 +3942,14 @@ var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
|
|
|
3940
3942
|
* Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
|
|
3941
3943
|
* re-run, and the constraint is re-created with the SET NULL action.
|
|
3942
3944
|
*/
|
|
3943
|
-
async function up$
|
|
3945
|
+
async function up$8(db) {
|
|
3944
3946
|
await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
|
|
3945
3947
|
await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
|
|
3946
3948
|
await sql`ALTER TABLE public.held_runs
|
|
3947
3949
|
ADD CONSTRAINT held_runs_environment_id_fkey
|
|
3948
3950
|
FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
|
|
3949
3951
|
}
|
|
3950
|
-
async function down$
|
|
3952
|
+
async function down$8(db) {
|
|
3951
3953
|
await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
|
|
3952
3954
|
await sql`ALTER TABLE public.held_runs
|
|
3953
3955
|
ADD CONSTRAINT held_runs_environment_id_fkey
|
|
@@ -3957,8 +3959,8 @@ async function down$4(db) {
|
|
|
3957
3959
|
//#endregion
|
|
3958
3960
|
//#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
|
|
3959
3961
|
var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
|
|
3960
|
-
down: () => down$
|
|
3961
|
-
up: () => up$
|
|
3962
|
+
down: () => down$7,
|
|
3963
|
+
up: () => up$7
|
|
3962
3964
|
});
|
|
3963
3965
|
/**
|
|
3964
3966
|
* Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
|
|
@@ -3975,7 +3977,7 @@ var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
|
|
|
3975
3977
|
*
|
|
3976
3978
|
* Idempotent: re-running on a DB that already has either column is a no-op.
|
|
3977
3979
|
*/
|
|
3978
|
-
async function up$
|
|
3980
|
+
async function up$7(db) {
|
|
3979
3981
|
const colExists = async (name) => {
|
|
3980
3982
|
return (await sql`
|
|
3981
3983
|
SELECT EXISTS (
|
|
@@ -4000,7 +4002,7 @@ async function up$3(db) {
|
|
|
4000
4002
|
WHERE ack_deadline IS NOT NULL
|
|
4001
4003
|
`.execute(db);
|
|
4002
4004
|
}
|
|
4003
|
-
async function down$
|
|
4005
|
+
async function down$7(db) {
|
|
4004
4006
|
await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
|
|
4005
4007
|
await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
|
|
4006
4008
|
await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
|
|
@@ -4008,8 +4010,8 @@ async function down$3(db) {
|
|
|
4008
4010
|
//#endregion
|
|
4009
4011
|
//#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
|
|
4010
4012
|
var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
|
|
4011
|
-
down: () => down$
|
|
4012
|
-
up: () => up$
|
|
4013
|
+
down: () => down$6,
|
|
4014
|
+
up: () => up$6
|
|
4013
4015
|
});
|
|
4014
4016
|
/**
|
|
4015
4017
|
* Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
|
|
@@ -4021,7 +4023,7 @@ var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll
|
|
|
4021
4023
|
*
|
|
4022
4024
|
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
4023
4025
|
*/
|
|
4024
|
-
async function up$
|
|
4026
|
+
async function up$6(db) {
|
|
4025
4027
|
if ((await sql`
|
|
4026
4028
|
SELECT EXISTS (
|
|
4027
4029
|
SELECT 1 FROM information_schema.columns
|
|
@@ -4035,7 +4037,7 @@ async function up$2(db) {
|
|
|
4035
4037
|
ADD COLUMN dispatch_ack_timeout_ms BIGINT
|
|
4036
4038
|
`.execute(db);
|
|
4037
4039
|
}
|
|
4038
|
-
async function down$
|
|
4040
|
+
async function down$6(db) {
|
|
4039
4041
|
await sql`
|
|
4040
4042
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
|
|
4041
4043
|
`.execute(db);
|
|
@@ -4043,8 +4045,8 @@ async function down$2(db) {
|
|
|
4043
4045
|
//#endregion
|
|
4044
4046
|
//#region src/db/migrations/033_org_settings_approval.ts
|
|
4045
4047
|
var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
|
|
4046
|
-
down: () => down$
|
|
4047
|
-
up: () => up$
|
|
4048
|
+
down: () => down$5,
|
|
4049
|
+
up: () => up$5
|
|
4048
4050
|
});
|
|
4049
4051
|
/**
|
|
4050
4052
|
* Add the two approval-policy columns to `org_settings`:
|
|
@@ -4061,7 +4063,7 @@ var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
|
|
|
4061
4063
|
* and the orchestrator admin route. Idempotent: a re-run on a DB that already
|
|
4062
4064
|
* has the columns is a no-op (each column is guarded independently).
|
|
4063
4065
|
*/
|
|
4064
|
-
async function up$
|
|
4066
|
+
async function up$5(db) {
|
|
4065
4067
|
const colExists = async (column) => {
|
|
4066
4068
|
return (await sql`
|
|
4067
4069
|
SELECT EXISTS (
|
|
@@ -4081,7 +4083,7 @@ async function up$1(db) {
|
|
|
4081
4083
|
ADD COLUMN allow_self_approval BOOLEAN NOT NULL DEFAULT true
|
|
4082
4084
|
`.execute(db);
|
|
4083
4085
|
}
|
|
4084
|
-
async function down$
|
|
4086
|
+
async function down$5(db) {
|
|
4085
4087
|
await sql`
|
|
4086
4088
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS approval_expiry_seconds
|
|
4087
4089
|
`.execute(db);
|
|
@@ -4092,8 +4094,8 @@ async function down$1(db) {
|
|
|
4092
4094
|
//#endregion
|
|
4093
4095
|
//#region src/db/migrations/034_held_runs_generalize.ts
|
|
4094
4096
|
var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
|
|
4095
|
-
down: () => down,
|
|
4096
|
-
up: () => up
|
|
4097
|
+
down: () => down$4,
|
|
4098
|
+
up: () => up$4
|
|
4097
4099
|
});
|
|
4098
4100
|
/**
|
|
4099
4101
|
* Generalize `held_runs` from an environment-only hold into the unified
|
|
@@ -4115,7 +4117,7 @@ var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
|
|
|
4115
4117
|
* New `held_run_approvals` table: one row per approver decision, FK to
|
|
4116
4118
|
* `held_runs.id` (uuid) with ON DELETE CASCADE.
|
|
4117
4119
|
*/
|
|
4118
|
-
async function up(db) {
|
|
4120
|
+
async function up$4(db) {
|
|
4119
4121
|
const colExists = async (column) => {
|
|
4120
4122
|
return (await sql`
|
|
4121
4123
|
SELECT EXISTS (
|
|
@@ -4148,7 +4150,7 @@ async function up(db) {
|
|
|
4148
4150
|
ON public.held_run_approvals USING btree (held_run_id)
|
|
4149
4151
|
`.execute(db);
|
|
4150
4152
|
}
|
|
4151
|
-
async function down(db) {
|
|
4153
|
+
async function down$4(db) {
|
|
4152
4154
|
await sql`DROP TABLE IF EXISTS public.held_run_approvals`.execute(db);
|
|
4153
4155
|
await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS approval_requirement`.execute(db);
|
|
4154
4156
|
await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS trigger_source`.execute(db);
|
|
@@ -4156,6 +4158,169 @@ async function down(db) {
|
|
|
4156
4158
|
await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS hold_scope`.execute(db);
|
|
4157
4159
|
}
|
|
4158
4160
|
//#endregion
|
|
4161
|
+
//#region src/db/migrations/035_pending_workflow_contexts.ts
|
|
4162
|
+
var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
|
|
4163
|
+
down: () => down$3,
|
|
4164
|
+
up: () => up$3
|
|
4165
|
+
});
|
|
4166
|
+
/**
|
|
4167
|
+
* Pending workflow dispatch context — backs resume of a workflow whose install
|
|
4168
|
+
* gate held. One row per held run: the serializable dispatch inputs needed to
|
|
4169
|
+
* rebuild the WorkflowDispatchContext when the hold releases (reviewer approve,
|
|
4170
|
+
* wait-timer expiry, concurrency slot free). The row is deleted once the resume
|
|
4171
|
+
* dispatch has been kicked off.
|
|
4172
|
+
*/
|
|
4173
|
+
async function up$3(db) {
|
|
4174
|
+
await sql`
|
|
4175
|
+
CREATE TABLE IF NOT EXISTS public.pending_workflow_contexts (
|
|
4176
|
+
run_id text PRIMARY KEY,
|
|
4177
|
+
org_id text NOT NULL,
|
|
4178
|
+
context jsonb NOT NULL,
|
|
4179
|
+
created_at timestamp with time zone DEFAULT now() NOT NULL
|
|
4180
|
+
)
|
|
4181
|
+
`.execute(db);
|
|
4182
|
+
}
|
|
4183
|
+
async function down$3(db) {
|
|
4184
|
+
await sql`DROP TABLE IF EXISTS public.pending_workflow_contexts`.execute(db);
|
|
4185
|
+
}
|
|
4186
|
+
//#endregion
|
|
4187
|
+
//#region src/db/migrations/036_attestations.ts
|
|
4188
|
+
var _036_attestations_exports = /* @__PURE__ */ __exportAll({
|
|
4189
|
+
down: () => down$2,
|
|
4190
|
+
up: () => up$2
|
|
4191
|
+
});
|
|
4192
|
+
/**
|
|
4193
|
+
* Add the `attestations` table for build-provenance bundles.
|
|
4194
|
+
*
|
|
4195
|
+
* When a workflow step calls `ctx.attestProvenance`, the agent uploads the
|
|
4196
|
+
* signed KiCI bundle to object storage under
|
|
4197
|
+
* `provenance/{run_id}/{job_id}/{subject_digest}.kici.json` and the
|
|
4198
|
+
* orchestrator records one row here so the dashboard can list and fetch
|
|
4199
|
+
* attestations per run/job.
|
|
4200
|
+
*
|
|
4201
|
+
* Idempotent: a re-run on a DB that already has the table is a no-op.
|
|
4202
|
+
*/
|
|
4203
|
+
async function up$2(db) {
|
|
4204
|
+
if ((await sql`
|
|
4205
|
+
SELECT EXISTS (
|
|
4206
|
+
SELECT 1 FROM information_schema.tables
|
|
4207
|
+
WHERE table_schema = 'public'
|
|
4208
|
+
AND table_name = 'attestations'
|
|
4209
|
+
) AS exists
|
|
4210
|
+
`.execute(db)).rows[0]?.exists) return;
|
|
4211
|
+
await sql`
|
|
4212
|
+
CREATE TABLE public.attestations (
|
|
4213
|
+
id TEXT PRIMARY KEY,
|
|
4214
|
+
run_id TEXT NOT NULL,
|
|
4215
|
+
job_id TEXT NOT NULL,
|
|
4216
|
+
subject_name TEXT NOT NULL,
|
|
4217
|
+
subject_digest TEXT NOT NULL,
|
|
4218
|
+
storage_key TEXT NOT NULL,
|
|
4219
|
+
mode TEXT NOT NULL,
|
|
4220
|
+
media_type TEXT NOT NULL,
|
|
4221
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
4222
|
+
)
|
|
4223
|
+
`.execute(db);
|
|
4224
|
+
await sql`
|
|
4225
|
+
CREATE INDEX idx_attestations_run_job
|
|
4226
|
+
ON public.attestations (run_id, job_id)
|
|
4227
|
+
`.execute(db);
|
|
4228
|
+
}
|
|
4229
|
+
async function down$2(db) {
|
|
4230
|
+
await sql`DROP TABLE IF EXISTS public.attestations`.execute(db);
|
|
4231
|
+
}
|
|
4232
|
+
//#endregion
|
|
4233
|
+
//#region src/db/migrations/037_generic_sources_provider_type_local.ts
|
|
4234
|
+
var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportAll({
|
|
4235
|
+
down: () => down$1,
|
|
4236
|
+
up: () => up$1
|
|
4237
|
+
});
|
|
4238
|
+
/**
|
|
4239
|
+
* Replace the `generic_webhook_sources.provider_type` CHECK constraint so it
|
|
4240
|
+
* permits `'local'` instead of `'internal'`, and migrate any carried-over
|
|
4241
|
+
* `'internal'` rows to `'local'`.
|
|
4242
|
+
*
|
|
4243
|
+
* The local filesystem (`file://`) provider is `provider_type='local'`; the
|
|
4244
|
+
* value used to be `'internal'`. The original CHECK constraint
|
|
4245
|
+
* (`generic_webhook_sources_provider_type_check`) allowed only
|
|
4246
|
+
* `{'generic','internal'}`, so writing a `'local'` row fails. Universal-git
|
|
4247
|
+
* sources keep `provider_type='generic'` (discriminated by `git_config`), so
|
|
4248
|
+
* the new allowed set is `{'generic','local'}`.
|
|
4249
|
+
*
|
|
4250
|
+
* Idempotent: the constraint is dropped IF EXISTS and recreated; the data
|
|
4251
|
+
* backfill is a plain UPDATE that is a no-op once no `'internal'` rows remain.
|
|
4252
|
+
*/
|
|
4253
|
+
async function up$1(db) {
|
|
4254
|
+
await sql`
|
|
4255
|
+
ALTER TABLE public.generic_webhook_sources
|
|
4256
|
+
DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
|
|
4257
|
+
`.execute(db);
|
|
4258
|
+
await sql`
|
|
4259
|
+
UPDATE public.generic_webhook_sources
|
|
4260
|
+
SET provider_type = 'local'
|
|
4261
|
+
WHERE provider_type = 'internal'
|
|
4262
|
+
`.execute(db);
|
|
4263
|
+
await sql`
|
|
4264
|
+
ALTER TABLE public.generic_webhook_sources
|
|
4265
|
+
ADD CONSTRAINT generic_webhook_sources_provider_type_check
|
|
4266
|
+
CHECK (provider_type = ANY (ARRAY['generic'::text, 'local'::text]))
|
|
4267
|
+
`.execute(db);
|
|
4268
|
+
}
|
|
4269
|
+
async function down$1(db) {
|
|
4270
|
+
await sql`
|
|
4271
|
+
ALTER TABLE public.generic_webhook_sources
|
|
4272
|
+
DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
|
|
4273
|
+
`.execute(db);
|
|
4274
|
+
await sql`
|
|
4275
|
+
UPDATE public.generic_webhook_sources
|
|
4276
|
+
SET provider_type = 'internal'
|
|
4277
|
+
WHERE provider_type = 'local'
|
|
4278
|
+
`.execute(db);
|
|
4279
|
+
await sql`
|
|
4280
|
+
ALTER TABLE public.generic_webhook_sources
|
|
4281
|
+
ADD CONSTRAINT generic_webhook_sources_provider_type_check
|
|
4282
|
+
CHECK (provider_type = ANY (ARRAY['generic'::text, 'internal'::text]))
|
|
4283
|
+
`.execute(db);
|
|
4284
|
+
}
|
|
4285
|
+
//#endregion
|
|
4286
|
+
//#region src/db/migrations/038_remote_sources.ts
|
|
4287
|
+
var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
|
|
4288
|
+
down: () => down,
|
|
4289
|
+
up: () => up
|
|
4290
|
+
});
|
|
4291
|
+
/**
|
|
4292
|
+
* `remote_sources` anchors a Platform-relayed `kici run remote` to its real
|
|
4293
|
+
* org. One row per org served by this orchestrator: routing key
|
|
4294
|
+
* `remote:<orgId>` maps to the canonical org id, so `resolveOrgId` resolves
|
|
4295
|
+
* the real tenant through the same local-source path a webhook takes — no
|
|
4296
|
+
* GitHub App, no webhook secret, no manual setup. The row is auto-provisioned
|
|
4297
|
+
* on Platform auth from the canonical org id carried on `auth.success`.
|
|
4298
|
+
*
|
|
4299
|
+
* Idempotent: a re-run on a DB that already has the table is a no-op.
|
|
4300
|
+
*/
|
|
4301
|
+
async function up(db) {
|
|
4302
|
+
if ((await sql`
|
|
4303
|
+
SELECT EXISTS (
|
|
4304
|
+
SELECT 1 FROM information_schema.tables
|
|
4305
|
+
WHERE table_schema = 'public' AND table_name = 'remote_sources'
|
|
4306
|
+
) AS exists
|
|
4307
|
+
`.execute(db)).rows[0]?.exists) return;
|
|
4308
|
+
await sql`
|
|
4309
|
+
CREATE TABLE public.remote_sources (
|
|
4310
|
+
customer_id VARCHAR(255) NOT NULL,
|
|
4311
|
+
routing_key VARCHAR(255) NOT NULL,
|
|
4312
|
+
cluster_id TEXT,
|
|
4313
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
4314
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
4315
|
+
CONSTRAINT remote_sources_customer_id_key UNIQUE (customer_id),
|
|
4316
|
+
CONSTRAINT remote_sources_routing_key_key UNIQUE (routing_key)
|
|
4317
|
+
)
|
|
4318
|
+
`.execute(db);
|
|
4319
|
+
}
|
|
4320
|
+
async function down(db) {
|
|
4321
|
+
await sql`DROP TABLE IF EXISTS public.remote_sources`.execute(db);
|
|
4322
|
+
}
|
|
4323
|
+
//#endregion
|
|
4159
4324
|
//#region src/db/migration-provider.ts
|
|
4160
4325
|
function createMigrationProvider() {
|
|
4161
4326
|
return { async getMigrations() {
|
|
@@ -4193,7 +4358,11 @@ function createMigrationProvider() {
|
|
|
4193
4358
|
"031_dispatch_queue_ack_deadline": _031_dispatch_queue_ack_deadline_exports,
|
|
4194
4359
|
"032_org_settings_dispatch_ack_timeout": _032_org_settings_dispatch_ack_timeout_exports,
|
|
4195
4360
|
"033_org_settings_approval": _033_org_settings_approval_exports,
|
|
4196
|
-
"034_held_runs_generalize": _034_held_runs_generalize_exports
|
|
4361
|
+
"034_held_runs_generalize": _034_held_runs_generalize_exports,
|
|
4362
|
+
"035_pending_workflow_contexts": _035_pending_workflow_contexts_exports,
|
|
4363
|
+
"036_attestations": _036_attestations_exports,
|
|
4364
|
+
"037_generic_sources_provider_type_local": _037_generic_sources_provider_type_local_exports,
|
|
4365
|
+
"038_remote_sources": _038_remote_sources_exports
|
|
4197
4366
|
};
|
|
4198
4367
|
} };
|
|
4199
4368
|
}
|
|
@@ -4260,7 +4429,7 @@ async function runMigrations(opts) {
|
|
|
4260
4429
|
* as `kici-admin peer create-token` — open a pool from KICI_DATABASE_URL /
|
|
4261
4430
|
* DATABASE_URL / --database-url.
|
|
4262
4431
|
*/
|
|
4263
|
-
function resolveDatabaseUrl$
|
|
4432
|
+
function resolveDatabaseUrl$2(explicit) {
|
|
4264
4433
|
const url = explicit ?? process.env.KICI_DATABASE_URL;
|
|
4265
4434
|
if (!url) throw new Error("Database URL required. Pass --database-url or set KICI_DATABASE_URL.");
|
|
4266
4435
|
return url;
|
|
@@ -4307,7 +4476,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4307
4476
|
});
|
|
4308
4477
|
db.command("fresh").description("DROP + CREATE the orchestrator DB, run migrations, record content hash").option("--database-url <url>", "Target database URL (else KICI_DATABASE_URL / DATABASE_URL)").requiredOption("--confirm", "Explicit confirmation (destructive)").option("--yes", "Skip interactive confirmation (for scripted use)").action(async (opts) => {
|
|
4309
4478
|
try {
|
|
4310
|
-
const url = resolveDatabaseUrl$
|
|
4479
|
+
const url = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4311
4480
|
const { dbName } = parseDatabaseUrl(url);
|
|
4312
4481
|
if (!opts.yes) {
|
|
4313
4482
|
if (!await confirmInteractive$1(`About to DROP + RECREATE database "${dbName}". Type "${dbName}" to confirm: `, dbName)) {
|
|
@@ -4338,7 +4507,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4338
4507
|
});
|
|
4339
4508
|
db.command("ensure <name>").description("CREATE DATABASE IF NOT EXISTS (idempotent)").option("--database-url <url>", "Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL)").option("--owner <role>", "DB owner role (default: URL user). Pass when the admin connection is privileged but the new DB should be owned by a separate non-privileged role.").option("--revoke-connect-public", "After ensure, REVOKE CONNECT ON DATABASE \"<name>\" FROM PUBLIC (recommended on shared clusters).").option("--grant-connect-role <role>", "After ensure (and any --revoke-connect-public), GRANT CONNECT ON DATABASE \"<name>\" TO \"<role>\". Repeatable.", (val, acc) => acc.concat([val]), []).action(async (name, opts) => {
|
|
4340
4509
|
try {
|
|
4341
|
-
const baseUrl = resolveDatabaseUrl$
|
|
4510
|
+
const baseUrl = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4342
4511
|
const url = new URL(baseUrl);
|
|
4343
4512
|
url.pathname = `/${name}`;
|
|
4344
4513
|
const targetUrl = url.toString();
|
|
@@ -4357,7 +4526,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4357
4526
|
});
|
|
4358
4527
|
db.command("create-role").description("CREATE / ALTER ROLE with LOGIN [+ CREATEDB] (idempotent)").option("--database-url <url>", "Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL)").requiredOption("--user <name>", "Role name to create or update").requiredOption("--password <password>", "Role password (raw — quote as needed)").option("--createdb", "Grant CREATEDB to the new role", false).action(async (opts) => {
|
|
4359
4528
|
try {
|
|
4360
|
-
const { adminUrl } = parseDatabaseUrl(resolveDatabaseUrl$
|
|
4529
|
+
const { adminUrl } = parseDatabaseUrl(resolveDatabaseUrl$2(opts.databaseUrl));
|
|
4361
4530
|
logInvocation(`create-role ${opts.user}`, adminUrl);
|
|
4362
4531
|
const outcome = await createDbRole(adminUrl, {
|
|
4363
4532
|
username: opts.user,
|
|
@@ -4372,7 +4541,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4372
4541
|
});
|
|
4373
4542
|
db.command("create-readonly-user").description("Create a read-only role with SELECT on all tables + default privileges").option("--database-url <url>", "Target DB URL (must connect as owner)").requiredOption("--user <name>", "Read-only role name").requiredOption("--password <password>", "Role password").action(async (opts) => {
|
|
4374
4543
|
try {
|
|
4375
|
-
const url = resolveDatabaseUrl$
|
|
4544
|
+
const url = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4376
4545
|
const { dbName } = parseDatabaseUrl(url);
|
|
4377
4546
|
logInvocation(`create-readonly-user ${opts.user}`, url);
|
|
4378
4547
|
const outcome = await createReadOnlyDbUser(url, {
|
|
@@ -4387,7 +4556,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4387
4556
|
});
|
|
4388
4557
|
db.command("check-schema").description("Compare bundled migrations vs live schema. Exit 2 on drift.").option("--database-url <url>", "Target DB URL (else KICI_DATABASE_URL / DATABASE_URL)").option("--json", "Emit JSON instead of a human-readable line", false).action(async (opts) => {
|
|
4389
4558
|
try {
|
|
4390
|
-
const pool = createPool(resolveDatabaseUrl$
|
|
4559
|
+
const pool = createPool(resolveDatabaseUrl$2(opts.databaseUrl));
|
|
4391
4560
|
try {
|
|
4392
4561
|
const status = await isSchemaCurrent(pool, createMigrationProvider());
|
|
4393
4562
|
if (opts.json) process.stdout.write(JSON.stringify(status) + "\n");
|
|
@@ -4404,7 +4573,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4404
4573
|
});
|
|
4405
4574
|
db.command("collation-check").description("Compare pg_database.datcollversion against the running libc collation version. Exit 2 on drift.").option("--database-url <url>", "Target DB URL (else KICI_DATABASE_URL / DATABASE_URL)").option("--json", "Emit JSON instead of a human-readable line", false).action(async (opts) => {
|
|
4406
4575
|
try {
|
|
4407
|
-
const url = resolveDatabaseUrl$
|
|
4576
|
+
const url = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4408
4577
|
const { dbName } = parseDatabaseUrl(url);
|
|
4409
4578
|
const pool = createPool(url);
|
|
4410
4579
|
try {
|
|
@@ -4434,7 +4603,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4434
4603
|
});
|
|
4435
4604
|
db.command("reindex").description("REINDEX DATABASE CONCURRENTLY <db>. Rebuilds every index under the running libc collation rules. Non-blocking but takes minutes + ~2× temp disk.").option("--database-url <url>", "Target DB URL (else KICI_DATABASE_URL / DATABASE_URL)").requiredOption("--confirm", "Explicit confirmation (destructive — long-running)").requiredOption("--reason <text>", "Reason (recorded in stderr banner)").action(async (opts) => {
|
|
4436
4605
|
try {
|
|
4437
|
-
const url = resolveDatabaseUrl$
|
|
4606
|
+
const url = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4438
4607
|
const { dbName } = parseDatabaseUrl(url);
|
|
4439
4608
|
logInvocation(`reindex ${dbName} (${opts.reason})`, url);
|
|
4440
4609
|
const pool = createPool(url);
|
|
@@ -4451,7 +4620,7 @@ function registerDbCommands(program, getClient) {
|
|
|
4451
4620
|
});
|
|
4452
4621
|
db.command("refresh-collation-version").description("ALTER DATABASE <db> REFRESH COLLATION VERSION. Metadata-only bump; pair with db reindex after a libc-base image rebuild.").option("--database-url <url>", "Target DB URL (else KICI_DATABASE_URL / DATABASE_URL)").requiredOption("--reason <text>", "Reason (recorded in stderr banner)").action(async (opts) => {
|
|
4453
4622
|
try {
|
|
4454
|
-
const url = resolveDatabaseUrl$
|
|
4623
|
+
const url = resolveDatabaseUrl$2(opts.databaseUrl);
|
|
4455
4624
|
const { dbName } = parseDatabaseUrl(url);
|
|
4456
4625
|
logInvocation(`refresh-collation-version ${dbName} (${opts.reason})`, url);
|
|
4457
4626
|
const pool = createPool(url);
|
|
@@ -4707,6 +4876,119 @@ promisify(execFile);
|
|
|
4707
4876
|
createLogger({ prefix: "universal-git:lock-file" });
|
|
4708
4877
|
createLogger({ prefix: "universal-git:clone-token" });
|
|
4709
4878
|
//#endregion
|
|
4879
|
+
//#region src/providers/local/local-source-config.ts
|
|
4880
|
+
/**
|
|
4881
|
+
* Configuration for a local filesystem (`file://`) source, stored as JSONB in
|
|
4882
|
+
* `generic_webhook_sources.git_config` and discriminated from universal-git
|
|
4883
|
+
* config by the row's `provider_type='local'`.
|
|
4884
|
+
*
|
|
4885
|
+
* A local source clones a git repository that already exists on the agent's
|
|
4886
|
+
* filesystem (host path for bare-metal scalers, image-bundled / rootfs /
|
|
4887
|
+
* bind-mounted path for container + Firecracker scalers). The orchestrator does
|
|
4888
|
+
* not verify in-agent reachability — that is the operator's responsibility.
|
|
4889
|
+
*/
|
|
4890
|
+
const LocalSourceConfigSchema = z.object({
|
|
4891
|
+
/** Absolute path to the repo (or base dir of repos) on the agent filesystem. */
|
|
4892
|
+
repoBasePath: z.string().min(1).refine((p) => path.isAbsolute(p), { message: "repoBasePath must be an absolute path" }),
|
|
4893
|
+
/** Optional network clone base (git:// / http://) for remote agents that do
|
|
4894
|
+
* not share the orchestrator's filesystem. When unset, file:// is used. */
|
|
4895
|
+
cloneUrlBase: z.string().min(1).optional()
|
|
4896
|
+
}).strict();
|
|
4897
|
+
//#endregion
|
|
4898
|
+
//#region src/cli/commands/local-trigger.ts
|
|
4899
|
+
/**
|
|
4900
|
+
* Build and send the synthetic webhook that triggers a run against a local
|
|
4901
|
+
* filesystem (`file://`) source. The orchestrator's provider-agnostic generic
|
|
4902
|
+
* webhook route (`POST /webhook/:orgId/generic/:sourceId`) dispatches it through
|
|
4903
|
+
* the local provider's normalizer. Shared by the `source trigger-local` CLI
|
|
4904
|
+
* command and the generated `post-receive` hook.
|
|
4905
|
+
*
|
|
4906
|
+
* A local repo has no remote forge to send webhooks, so this is the operator's
|
|
4907
|
+
* way to drive a run: either by hand (`trigger-local`) or on every push via an
|
|
4908
|
+
* installed `post-receive` hook (`install-hook`).
|
|
4909
|
+
*/
|
|
4910
|
+
/** Build the GitHub-shaped webhook request the local provider normalizer expects. */
|
|
4911
|
+
function buildLocalTriggerRequest(input) {
|
|
4912
|
+
const body = JSON.stringify({
|
|
4913
|
+
ref: input.ref,
|
|
4914
|
+
after: input.sha,
|
|
4915
|
+
repository: {
|
|
4916
|
+
full_name: input.repoFullName,
|
|
4917
|
+
default_branch: input.defaultBranch
|
|
4918
|
+
}
|
|
4919
|
+
});
|
|
4920
|
+
return {
|
|
4921
|
+
path: `/webhook/${input.orgId}/generic/${input.sourceId}`,
|
|
4922
|
+
headers: {
|
|
4923
|
+
"content-type": "application/json",
|
|
4924
|
+
"x-event-type": input.event,
|
|
4925
|
+
"x-delivery-id": randomUUID()
|
|
4926
|
+
},
|
|
4927
|
+
body
|
|
4928
|
+
};
|
|
4929
|
+
}
|
|
4930
|
+
/** Read HEAD ref + sha from a local git repo (used when the operator omits --ref/--sha). */
|
|
4931
|
+
function readRepoHead(repoPath) {
|
|
4932
|
+
const sha = execFileSync("git", [
|
|
4933
|
+
"-C",
|
|
4934
|
+
repoPath,
|
|
4935
|
+
"rev-parse",
|
|
4936
|
+
"HEAD"
|
|
4937
|
+
], { encoding: "utf8" }).trim();
|
|
4938
|
+
return {
|
|
4939
|
+
ref: `refs/heads/${execFileSync("git", [
|
|
4940
|
+
"-C",
|
|
4941
|
+
repoPath,
|
|
4942
|
+
"rev-parse",
|
|
4943
|
+
"--abbrev-ref",
|
|
4944
|
+
"HEAD"
|
|
4945
|
+
], { encoding: "utf8" }).trim()}`,
|
|
4946
|
+
sha
|
|
4947
|
+
};
|
|
4948
|
+
}
|
|
4949
|
+
/** POST the trigger request to the orchestrator base URL. Returns the HTTP status. */
|
|
4950
|
+
async function sendLocalTrigger(baseUrl, req) {
|
|
4951
|
+
return (await fetch(`${baseUrl.replace(/\/$/, "")}${req.path}`, {
|
|
4952
|
+
method: "POST",
|
|
4953
|
+
headers: req.headers,
|
|
4954
|
+
body: req.body
|
|
4955
|
+
})).status;
|
|
4956
|
+
}
|
|
4957
|
+
//#endregion
|
|
4958
|
+
//#region src/cli/commands/local-hook.ts
|
|
4959
|
+
/**
|
|
4960
|
+
* Render + install a git `post-receive` hook that triggers a KiCI run on every
|
|
4961
|
+
* push to a local filesystem (`file://`) source. The hook is a thin wrapper
|
|
4962
|
+
* around `kici-admin source trigger-local`; it carries no logic of its own.
|
|
4963
|
+
*/
|
|
4964
|
+
/**
|
|
4965
|
+
* Render the post-receive hook script. For each pushed ref the hook calls
|
|
4966
|
+
* `kici-admin source trigger-local <id> --ref <ref> --sha <new> --base-url <url>`,
|
|
4967
|
+
* so a push to any branch dispatches a run for that ref.
|
|
4968
|
+
*/
|
|
4969
|
+
function renderPostReceiveHook(opts) {
|
|
4970
|
+
return `#!/usr/bin/env bash
|
|
4971
|
+
# KiCI local-source post-receive hook (generated by 'kici-admin source install-hook').
|
|
4972
|
+
# Triggers a run for each pushed branch ref.
|
|
4973
|
+
set -euo pipefail
|
|
4974
|
+
while read -r _old _new ref; do
|
|
4975
|
+
kici-admin source trigger-local ${opts.sourceId} --ref "$ref" --sha "$_new" --base-url ${opts.baseUrl}
|
|
4976
|
+
done
|
|
4977
|
+
`;
|
|
4978
|
+
}
|
|
4979
|
+
/**
|
|
4980
|
+
* Write the rendered hook into the repo's `.git/hooks/post-receive` and make it
|
|
4981
|
+
* executable. Throws when the path is not a git repo (no `.git/hooks` dir).
|
|
4982
|
+
*/
|
|
4983
|
+
function installPostReceiveHook(repoPath, script) {
|
|
4984
|
+
const hooksDir = path.join(repoPath, ".git", "hooks");
|
|
4985
|
+
if (!existsSync(hooksDir)) throw new Error(`Not a git repo (no .git/hooks): ${repoPath}`);
|
|
4986
|
+
const hookPath = path.join(hooksDir, "post-receive");
|
|
4987
|
+
writeFileSync(hookPath, script, { mode: 493 });
|
|
4988
|
+
chmodSync(hookPath, 493);
|
|
4989
|
+
return hookPath;
|
|
4990
|
+
}
|
|
4991
|
+
//#endregion
|
|
4710
4992
|
//#region src/cli/commands/source.ts
|
|
4711
4993
|
/**
|
|
4712
4994
|
* Source management commands for kici-admin.
|
|
@@ -4728,6 +5010,24 @@ createLogger({ prefix: "universal-git:clone-token" });
|
|
|
4728
5010
|
* --from-env <VAR_NAME> Read from environment variable
|
|
4729
5011
|
* --stdin Read from stdin
|
|
4730
5012
|
*/
|
|
5013
|
+
/** Default orchestrator base URL for the webhook trigger route, matching the
|
|
5014
|
+
* kici-admin global `--url` default. */
|
|
5015
|
+
const DEFAULT_ORCH_URL = process.env.KICI_ADMIN_URL ?? "http://localhost:8080";
|
|
5016
|
+
/** Parse a generic source's git_config (string or object) into a LocalSourceConfig.
|
|
5017
|
+
* Returns null when the row is not a valid local source. */
|
|
5018
|
+
function parseLocalConfig(s) {
|
|
5019
|
+
if (s.provider_type !== "local" || !s.git_config) return null;
|
|
5020
|
+
const raw = typeof s.git_config === "string" ? safeParse(s.git_config) : s.git_config;
|
|
5021
|
+
const parsed = LocalSourceConfigSchema.safeParse(raw);
|
|
5022
|
+
return parsed.success ? parsed.data : null;
|
|
5023
|
+
}
|
|
5024
|
+
function safeParse(value) {
|
|
5025
|
+
try {
|
|
5026
|
+
return JSON.parse(value);
|
|
5027
|
+
} catch {
|
|
5028
|
+
return null;
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
4731
5031
|
/**
|
|
4732
5032
|
* Short reason shown in `(unavailable — <reason>)` when no webhook URL could be
|
|
4733
5033
|
* resolved for an added source.
|
|
@@ -4809,7 +5109,11 @@ function formatGenericSource(s) {
|
|
|
4809
5109
|
} catch {
|
|
4810
5110
|
gc = null;
|
|
4811
5111
|
}
|
|
4812
|
-
if (gc) {
|
|
5112
|
+
if (gc && s.provider_type === "local") {
|
|
5113
|
+
console.log(` Local (file://): yes`);
|
|
5114
|
+
if (typeof gc.repoBasePath === "string") console.log(` Repo base path: ${gc.repoBasePath}`);
|
|
5115
|
+
if (typeof gc.cloneUrlBase === "string") console.log(` Clone URL base: ${gc.cloneUrlBase}`);
|
|
5116
|
+
} else if (gc) {
|
|
4813
5117
|
console.log(` Universal-git: yes`);
|
|
4814
5118
|
if (typeof gc.preset === "string") console.log(` Preset: ${gc.preset}`);
|
|
4815
5119
|
if (typeof gc.gitUrlTemplate === "string") console.log(` Git URL template: ${gc.gitUrlTemplate}`);
|
|
@@ -4907,7 +5211,7 @@ function registerSourceCommands(program, getClient) {
|
|
|
4907
5211
|
process.exit(1);
|
|
4908
5212
|
}
|
|
4909
5213
|
});
|
|
4910
|
-
add.command("generic").description("Add a new generic webhook source").requiredOption("--org <orgId>", "Organization/customer ID").requiredOption("--name <name>", "Human-readable source name").option("--verification <method>", "Verification method: hmac_sha256, bearer_token, ip_allowlist, none").option("--secret <value>", "Verification secret (HMAC secret or bearer token, prefix with @ for file)").option("--from-env <varName>", "Read verification secret from environment variable").option("--stdin", "Read verification secret from stdin").option("--event-type-header <header>", "Header name for event type extraction").option("--event-type-path <jsonpath>", "JSONPath for event type extraction from body").option("--idempotency-key-header <header>", "Header name for idempotency key").option("--idempotency-key-path <jsonpath>", "JSONPath for idempotency key from body").option("--dedup-window <seconds>", "Dedup window in seconds (default: 300)", parseInt).option("--max-payload <bytes>", "Maximum payload size in bytes (default: 1048576)", parseInt).option("--allowed-events <events>", "Comma-separated list of allowed event types").option("--strip-headers <headers>", "Comma-separated list of headers to strip").option("--rate-limit <rpm>", "Rate limit in requests per minute (default: 600)", parseInt).option("--preset <name>", "Universal-git preset: forgejo, gitea, gogs, gitlab-repo, github-repo, custom").option("--git-url-template <url>", "Clone URL template with {owner}/{name}/{repo}").option("--credential-ref <key>", "Secret key name (under __source__/<id> scope)").option("--credential-store <backend>", "Secret backend name (default: pg)").option("--credential-type <type>", "Credential type: pat, basic, ssh").option("--credential-user <user>", "Username for PAT/basic auth (default: x-access-token)").option("--ssh-host-key-policy <policy>", "SSH host-key policy: accept-new, pinned").option("--ssh-known-hosts-pem <pathOrValue>", "Pinned SSH known_hosts (prefix with @ for file). Required when --ssh-host-key-policy=pinned").option("--provider-type <type>", "Provider implementation: generic (default) or
|
|
5214
|
+
add.command("generic").description("Add a new generic webhook source").requiredOption("--org <orgId>", "Organization/customer ID").requiredOption("--name <name>", "Human-readable source name").option("--verification <method>", "Verification method: hmac_sha256, bearer_token, ip_allowlist, none").option("--secret <value>", "Verification secret (HMAC secret or bearer token, prefix with @ for file)").option("--from-env <varName>", "Read verification secret from environment variable").option("--stdin", "Read verification secret from stdin").option("--event-type-header <header>", "Header name for event type extraction").option("--event-type-path <jsonpath>", "JSONPath for event type extraction from body").option("--idempotency-key-header <header>", "Header name for idempotency key").option("--idempotency-key-path <jsonpath>", "JSONPath for idempotency key from body").option("--dedup-window <seconds>", "Dedup window in seconds (default: 300)", parseInt).option("--max-payload <bytes>", "Maximum payload size in bytes (default: 1048576)", parseInt).option("--allowed-events <events>", "Comma-separated list of allowed event types").option("--strip-headers <headers>", "Comma-separated list of headers to strip").option("--rate-limit <rpm>", "Rate limit in requests per minute (default: 600)", parseInt).option("--preset <name>", "Universal-git preset: forgejo, gitea, gogs, gitlab-repo, github-repo, custom").option("--git-url-template <url>", "Clone URL template with {owner}/{name}/{repo}").option("--credential-ref <key>", "Secret key name (under __source__/<id> scope)").option("--credential-store <backend>", "Secret backend name (default: pg)").option("--credential-type <type>", "Credential type: pat, basic, ssh").option("--credential-user <user>", "Username for PAT/basic auth (default: x-access-token)").option("--ssh-host-key-policy <policy>", "SSH host-key policy: accept-new, pinned").option("--ssh-known-hosts-pem <pathOrValue>", "Pinned SSH known_hosts (prefix with @ for file). Required when --ssh-host-key-policy=pinned").option("--provider-type <type>", "Provider implementation: generic (default) or local (a git repo on the agent filesystem cloned via file://)").option("--json", "Emit raw JSON (the full source row) instead of formatted text").action(async (opts) => {
|
|
4911
5215
|
try {
|
|
4912
5216
|
const secret = await resolveSecret({
|
|
4913
5217
|
value: opts.secret,
|
|
@@ -4959,6 +5263,39 @@ function registerSourceCommands(program, getClient) {
|
|
|
4959
5263
|
process.exit(1);
|
|
4960
5264
|
}
|
|
4961
5265
|
});
|
|
5266
|
+
add.command("local").description("Register a git repo present on the agent filesystem as a file:// source").requiredOption("--org <orgId>", "Organization/customer ID").requiredOption("--path <dir>", "Absolute path to the repo (or base dir of repos) on the agent filesystem").option("--name <name>", "Human-readable source name", "local").option("--clone-url-base <url>", "Optional git://|http:// base for remote agents that do not share the orchestrator filesystem (default: file://)").option("--json", "Emit raw JSON (the full source row) instead of formatted text").action(async (opts) => {
|
|
5267
|
+
try {
|
|
5268
|
+
if (!path.isAbsolute(opts.path)) {
|
|
5269
|
+
console.error(`Error: --path must be an absolute path: ${opts.path}`);
|
|
5270
|
+
process.exit(1);
|
|
5271
|
+
}
|
|
5272
|
+
const localConfig = { repoBasePath: opts.path };
|
|
5273
|
+
if (opts.cloneUrlBase) localConfig.cloneUrlBase = opts.cloneUrlBase;
|
|
5274
|
+
const s = (await getClient().createGenericSource({
|
|
5275
|
+
orgId: opts.org,
|
|
5276
|
+
name: opts.name,
|
|
5277
|
+
providerType: "local",
|
|
5278
|
+
verificationMethod: "none",
|
|
5279
|
+
localConfig
|
|
5280
|
+
})).source;
|
|
5281
|
+
if (opts.json) {
|
|
5282
|
+
console.log(JSON.stringify(s, null, 2));
|
|
5283
|
+
return;
|
|
5284
|
+
}
|
|
5285
|
+
console.log(`Local source created:`);
|
|
5286
|
+
console.log(` ID: ${s.id}`);
|
|
5287
|
+
console.log(` Name: ${s.name}`);
|
|
5288
|
+
console.log(` Routing key: ${s.routing_key}`);
|
|
5289
|
+
console.log(` Org: ${s.customer_id}`);
|
|
5290
|
+
console.log(` Repo path: ${opts.path}`);
|
|
5291
|
+
console.log("");
|
|
5292
|
+
console.log(`Trigger runs with: kici-admin source trigger-local ${s.id}`);
|
|
5293
|
+
console.log(`Or install a push hook: kici-admin source install-hook ${s.id}`);
|
|
5294
|
+
} catch (err) {
|
|
5295
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5296
|
+
process.exit(1);
|
|
5297
|
+
}
|
|
5298
|
+
});
|
|
4962
5299
|
src.command("list-presets").description("List built-in universal-git presets (forge shapes supported out of the box)").option("--format <format>", "Output format: table|json", "table").action((opts) => {
|
|
4963
5300
|
const rows = Object.entries(UNIVERSAL_GIT_PRESETS).map(([name, def]) => ({
|
|
4964
5301
|
preset: name,
|
|
@@ -5070,7 +5407,7 @@ function registerSourceCommands(program, getClient) {
|
|
|
5070
5407
|
process.exit(1);
|
|
5071
5408
|
}
|
|
5072
5409
|
});
|
|
5073
|
-
src.command("update-generic <id>").description("Update a generic webhook source").option("--name <name>", "New name").option("--verification <method>", "Verification method: hmac_sha256, bearer_token, ip_allowlist, none").option("--secret <value>", "New verification secret (prefix with @ for file)").option("--from-env <varName>", "Read verification secret from environment variable").option("--stdin", "Read verification secret from stdin").option("--event-type-header <header>", "Header name for event type extraction").option("--event-type-path <jsonpath>", "JSONPath for event type extraction from body").option("--idempotency-key-header <header>", "Header name for idempotency key").option("--idempotency-key-path <jsonpath>", "JSONPath for idempotency key from body").option("--dedup-window <seconds>", "Dedup window in seconds", parseInt).option("--max-payload <bytes>", "Maximum payload size in bytes", parseInt).option("--allowed-events <events>", "Comma-separated list of allowed event types").option("--strip-headers <headers>", "Comma-separated list of headers to strip").option("--rate-limit <rpm>", "Rate limit in requests per minute", parseInt).option("--preset <name>", "Universal-git preset").option("--git-url-template <url>", "Clone URL template").option("--credential-ref <key>", "Secret key name").option("--credential-store <backend>", "Secret backend name").option("--credential-type <type>", "Credential type: pat, basic, ssh").option("--credential-user <user>", "Username for PAT/basic auth").option("--ssh-host-key-policy <policy>", "SSH host-key policy: accept-new, pinned").option("--ssh-known-hosts-pem <pathOrValue>", "Pinned SSH known_hosts (prefix with @ for file)").option("--clear-git-config", "Revert this source back to a payload-only generic webhook").option("--provider-type <type>", "Provider implementation: generic (default) or
|
|
5410
|
+
src.command("update-generic <id>").description("Update a generic webhook source").option("--name <name>", "New name").option("--verification <method>", "Verification method: hmac_sha256, bearer_token, ip_allowlist, none").option("--secret <value>", "New verification secret (prefix with @ for file)").option("--from-env <varName>", "Read verification secret from environment variable").option("--stdin", "Read verification secret from stdin").option("--event-type-header <header>", "Header name for event type extraction").option("--event-type-path <jsonpath>", "JSONPath for event type extraction from body").option("--idempotency-key-header <header>", "Header name for idempotency key").option("--idempotency-key-path <jsonpath>", "JSONPath for idempotency key from body").option("--dedup-window <seconds>", "Dedup window in seconds", parseInt).option("--max-payload <bytes>", "Maximum payload size in bytes", parseInt).option("--allowed-events <events>", "Comma-separated list of allowed event types").option("--strip-headers <headers>", "Comma-separated list of headers to strip").option("--rate-limit <rpm>", "Rate limit in requests per minute", parseInt).option("--preset <name>", "Universal-git preset").option("--git-url-template <url>", "Clone URL template").option("--credential-ref <key>", "Secret key name").option("--credential-store <backend>", "Secret backend name").option("--credential-type <type>", "Credential type: pat, basic, ssh").option("--credential-user <user>", "Username for PAT/basic auth").option("--ssh-host-key-policy <policy>", "SSH host-key policy: accept-new, pinned").option("--ssh-known-hosts-pem <pathOrValue>", "Pinned SSH known_hosts (prefix with @ for file)").option("--clear-git-config", "Revert this source back to a payload-only generic webhook").option("--provider-type <type>", "Provider implementation: generic (default) or local (a git repo on the agent filesystem cloned via file://)").option("--json", "Emit raw JSON (the full source row) instead of formatted text").action(async (id, opts) => {
|
|
5074
5411
|
try {
|
|
5075
5412
|
const secret = await resolveSecret({
|
|
5076
5413
|
value: opts.secret,
|
|
@@ -5117,7 +5454,32 @@ function registerSourceCommands(program, getClient) {
|
|
|
5117
5454
|
process.exit(1);
|
|
5118
5455
|
}
|
|
5119
5456
|
});
|
|
5120
|
-
src.command("
|
|
5457
|
+
src.command("update-local <id>").description("Update a local filesystem (file://) source").option("--name <name>", "New name").option("--path <dir>", "New absolute repo base path on the agent filesystem").option("--clone-url-base <url>", "New git://|http:// clone base (default: file://)").option("--json", "Emit raw JSON (the full source row) instead of formatted text").action(async (id, opts) => {
|
|
5458
|
+
try {
|
|
5459
|
+
const data = {};
|
|
5460
|
+
if (opts.name) data.name = opts.name;
|
|
5461
|
+
if (opts.path !== void 0) {
|
|
5462
|
+
if (!path.isAbsolute(opts.path)) {
|
|
5463
|
+
console.error(`Error: --path must be an absolute path: ${opts.path}`);
|
|
5464
|
+
process.exit(1);
|
|
5465
|
+
}
|
|
5466
|
+
const localConfig = { repoBasePath: opts.path };
|
|
5467
|
+
if (opts.cloneUrlBase) localConfig.cloneUrlBase = opts.cloneUrlBase;
|
|
5468
|
+
data.localConfig = localConfig;
|
|
5469
|
+
}
|
|
5470
|
+
if (Object.keys(data).length === 0) {
|
|
5471
|
+
console.error("Error: no fields to update. Provide --path and/or --name.");
|
|
5472
|
+
process.exit(1);
|
|
5473
|
+
}
|
|
5474
|
+
const result = await getClient().updateGenericSource(id, data);
|
|
5475
|
+
if (opts.json) console.log(JSON.stringify(result.source, null, 2));
|
|
5476
|
+
else console.log(`Local source updated: ${result.source.id} (${result.source.name})`);
|
|
5477
|
+
} catch (err) {
|
|
5478
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5479
|
+
process.exit(1);
|
|
5480
|
+
}
|
|
5481
|
+
});
|
|
5482
|
+
src.command("remove <routingKey>").description("Remove a source (GitHub, or generic/local with --generic / --local)").option("--yes", "Skip confirmation").option("--generic", "Remove a generic source (routingKey is treated as source ID)").option("--local", "Remove a local (file://) source (routingKey is treated as source ID)").option("--hard", "Permanently delete a generic/local source (requires --generic or --local)").action(async (routingKey, opts) => {
|
|
5121
5483
|
try {
|
|
5122
5484
|
if (!opts.yes) {
|
|
5123
5485
|
const rl = createInterface({
|
|
@@ -5133,12 +5495,13 @@ function registerSourceCommands(program, getClient) {
|
|
|
5133
5495
|
return;
|
|
5134
5496
|
}
|
|
5135
5497
|
}
|
|
5136
|
-
if (opts.generic) {
|
|
5498
|
+
if (opts.generic || opts.local) {
|
|
5137
5499
|
const mode = (await getClient().deleteGenericSource(routingKey, opts.hard)).hard ? "permanently deleted" : "soft-deleted";
|
|
5138
|
-
|
|
5500
|
+
const kind = opts.local ? "Local" : "Generic";
|
|
5501
|
+
console.log(`${kind} source ${mode}: ${routingKey}`);
|
|
5139
5502
|
} else {
|
|
5140
5503
|
if (opts.hard) {
|
|
5141
|
-
console.error("Error: --hard flag is only supported with --generic");
|
|
5504
|
+
console.error("Error: --hard flag is only supported with --generic / --local");
|
|
5142
5505
|
process.exit(1);
|
|
5143
5506
|
}
|
|
5144
5507
|
await getClient().delete(`/api/v1/admin/sources/${encodeURIComponent(routingKey)}`);
|
|
@@ -5167,6 +5530,106 @@ function registerSourceCommands(program, getClient) {
|
|
|
5167
5530
|
process.exit(1);
|
|
5168
5531
|
}
|
|
5169
5532
|
});
|
|
5533
|
+
src.command("trigger-local <id>").description("Trigger a run against a local source (reads HEAD when --ref/--sha omitted)").option("--event <event>", "push | pull_request", "push").option("--ref <ref>", "Git ref (default: repo HEAD branch)").option("--sha <sha>", "Commit SHA (default: repo HEAD)").option("--repo-full-name <name>", "owner/name identifier used in the payload", "local/repo").option("--base-url <url>", "Orchestrator base URL", DEFAULT_ORCH_URL).action(async (id, opts) => {
|
|
5534
|
+
try {
|
|
5535
|
+
const { source } = await getClient().getGenericSource(id);
|
|
5536
|
+
const cfg = parseLocalConfig(source);
|
|
5537
|
+
if (!cfg) {
|
|
5538
|
+
console.error(`Error: no local source with id ${id}`);
|
|
5539
|
+
process.exit(1);
|
|
5540
|
+
}
|
|
5541
|
+
const head = opts.ref && opts.sha ? {
|
|
5542
|
+
ref: opts.ref,
|
|
5543
|
+
sha: opts.sha
|
|
5544
|
+
} : readRepoHead(cfg.repoBasePath);
|
|
5545
|
+
const orgId = source.customer_id;
|
|
5546
|
+
const sourceId = source.name;
|
|
5547
|
+
const req = buildLocalTriggerRequest({
|
|
5548
|
+
orgId,
|
|
5549
|
+
sourceId,
|
|
5550
|
+
repoFullName: opts.repoFullName,
|
|
5551
|
+
event: opts.event === "pull_request" ? "pull_request" : "push",
|
|
5552
|
+
ref: head.ref,
|
|
5553
|
+
sha: head.sha,
|
|
5554
|
+
defaultBranch: head.ref.replace("refs/heads/", "")
|
|
5555
|
+
});
|
|
5556
|
+
const status = await sendLocalTrigger(opts.baseUrl, req);
|
|
5557
|
+
console.log(`Triggered local source ${id}: HTTP ${status}`);
|
|
5558
|
+
if (status >= 400) process.exit(1);
|
|
5559
|
+
} catch (err) {
|
|
5560
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5561
|
+
process.exit(1);
|
|
5562
|
+
}
|
|
5563
|
+
});
|
|
5564
|
+
src.command("install-hook <id>").description("Install a post-receive hook in the local source repo that triggers runs on push").option("--repo <path>", "Repo path (default: the source repoBasePath)").option("--base-url <url>", "Orchestrator base URL", DEFAULT_ORCH_URL).action(async (id, opts) => {
|
|
5565
|
+
try {
|
|
5566
|
+
const { source } = await getClient().getGenericSource(id);
|
|
5567
|
+
const cfg = parseLocalConfig(source);
|
|
5568
|
+
if (!cfg) {
|
|
5569
|
+
console.error(`Error: no local source with id ${id}`);
|
|
5570
|
+
process.exit(1);
|
|
5571
|
+
}
|
|
5572
|
+
const repoPath = opts.repo ?? cfg.repoBasePath;
|
|
5573
|
+
const hookPath = installPostReceiveHook(repoPath, renderPostReceiveHook({
|
|
5574
|
+
sourceId: id,
|
|
5575
|
+
baseUrl: opts.baseUrl
|
|
5576
|
+
}));
|
|
5577
|
+
console.log(`Installed post-receive hook: ${hookPath}`);
|
|
5578
|
+
console.log(`Every push to ${repoPath} will now trigger a run for source ${id}.`);
|
|
5579
|
+
} catch (err) {
|
|
5580
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5581
|
+
process.exit(1);
|
|
5582
|
+
}
|
|
5583
|
+
});
|
|
5584
|
+
}
|
|
5585
|
+
/** Read the auto-provisioned remote-source row for an org, if it exists. */
|
|
5586
|
+
async function getRemoteSource(db, orgId) {
|
|
5587
|
+
return db.selectFrom("remote_sources").selectAll().where("customer_id", "=", orgId).executeTakeFirst();
|
|
5588
|
+
}
|
|
5589
|
+
//#endregion
|
|
5590
|
+
//#region src/cli/commands/remote-source.ts
|
|
5591
|
+
init_client();
|
|
5592
|
+
function resolveDatabaseUrl$1(explicit) {
|
|
5593
|
+
const url = explicit ?? process.env.KICI_DATABASE_URL;
|
|
5594
|
+
if (!url) throw new Error("Database URL required. Pass --database-url or set KICI_DATABASE_URL.");
|
|
5595
|
+
return url;
|
|
5596
|
+
}
|
|
5597
|
+
function registerRemoteSourceCommands(program) {
|
|
5598
|
+
program.command("remote-source").description("Inspect the auto-provisioned remote-source org anchor").command("show <orgId>").description("Print the remote_sources anchor row for an org (routing key remote:<orgId>).").option("--database-url <url>", "Orchestrator DB URL (else KICI_DATABASE_URL)").option("--format <format>", "Output format: json|table", "table").action(async (orgId, opts) => {
|
|
5599
|
+
let url;
|
|
5600
|
+
try {
|
|
5601
|
+
url = resolveDatabaseUrl$1(opts.databaseUrl);
|
|
5602
|
+
} catch (err) {
|
|
5603
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5604
|
+
process.exit(1);
|
|
5605
|
+
return;
|
|
5606
|
+
}
|
|
5607
|
+
const pool = createPool$1(url);
|
|
5608
|
+
const db = createDb$1(pool);
|
|
5609
|
+
try {
|
|
5610
|
+
const row = await getRemoteSource(db, orgId);
|
|
5611
|
+
if (!row) {
|
|
5612
|
+
console.error(`No remote_sources anchor found for org ${orgId}.`);
|
|
5613
|
+
process.exit(1);
|
|
5614
|
+
return;
|
|
5615
|
+
}
|
|
5616
|
+
if (opts.format === "json") {
|
|
5617
|
+
console.log(JSON.stringify(row, null, 2));
|
|
5618
|
+
return;
|
|
5619
|
+
}
|
|
5620
|
+
console.log(`customer_id: ${row.customer_id}`);
|
|
5621
|
+
console.log(`routing_key: ${row.routing_key}`);
|
|
5622
|
+
console.log(`cluster_id: ${row.cluster_id ?? "(none)"}`);
|
|
5623
|
+
console.log(`created_at: ${new Date(row.created_at).toISOString()}`);
|
|
5624
|
+
console.log(`updated_at: ${new Date(row.updated_at).toISOString()}`);
|
|
5625
|
+
} catch (err) {
|
|
5626
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
5627
|
+
process.exit(1);
|
|
5628
|
+
} finally {
|
|
5629
|
+
await db.destroy();
|
|
5630
|
+
await pool.end().catch(() => void 0);
|
|
5631
|
+
}
|
|
5632
|
+
});
|
|
5170
5633
|
}
|
|
5171
5634
|
//#endregion
|
|
5172
5635
|
//#region src/cli/commands/workflow.ts
|
|
@@ -7452,61 +7915,61 @@ var init_registry = __esmMin((() => {
|
|
|
7452
7915
|
rolldown: {
|
|
7453
7916
|
"linux-x64": {
|
|
7454
7917
|
name: "rolldown",
|
|
7455
|
-
version: "1.
|
|
7918
|
+
version: "1.1.0",
|
|
7456
7919
|
platform: "linux",
|
|
7457
7920
|
arch: "x64",
|
|
7458
|
-
url: "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.
|
|
7459
|
-
sha256: "
|
|
7921
|
+
url: "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.0.tgz",
|
|
7922
|
+
sha256: "07ccc910deab806eae00c93cfa633eeedfe5df92cabd0fc92111dd982ab3c324",
|
|
7460
7923
|
extractPath: "package/",
|
|
7461
7924
|
archiveType: "tar.gz"
|
|
7462
7925
|
},
|
|
7463
7926
|
"linux-arm64": {
|
|
7464
7927
|
name: "rolldown",
|
|
7465
|
-
version: "1.
|
|
7928
|
+
version: "1.1.0",
|
|
7466
7929
|
platform: "linux",
|
|
7467
7930
|
arch: "arm64",
|
|
7468
|
-
url: "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.
|
|
7469
|
-
sha256: "
|
|
7931
|
+
url: "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.0.tgz",
|
|
7932
|
+
sha256: "e7e812642e292101c65703101e29622da59279c53cd68deefed2a356a76ceaf0",
|
|
7470
7933
|
extractPath: "package/",
|
|
7471
7934
|
archiveType: "tar.gz"
|
|
7472
7935
|
},
|
|
7473
7936
|
"darwin-x64": {
|
|
7474
7937
|
name: "rolldown",
|
|
7475
|
-
version: "1.
|
|
7938
|
+
version: "1.1.0",
|
|
7476
7939
|
platform: "darwin",
|
|
7477
7940
|
arch: "x64",
|
|
7478
|
-
url: "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.
|
|
7479
|
-
sha256: "
|
|
7941
|
+
url: "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.0.tgz",
|
|
7942
|
+
sha256: "48f52e0b62d87117f96c7660e2838dded1d6a99f45d56ae192ab49475a8fa9d1",
|
|
7480
7943
|
extractPath: "package/",
|
|
7481
7944
|
archiveType: "tar.gz"
|
|
7482
7945
|
},
|
|
7483
7946
|
"darwin-arm64": {
|
|
7484
7947
|
name: "rolldown",
|
|
7485
|
-
version: "1.
|
|
7948
|
+
version: "1.1.0",
|
|
7486
7949
|
platform: "darwin",
|
|
7487
7950
|
arch: "arm64",
|
|
7488
|
-
url: "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.
|
|
7489
|
-
sha256: "
|
|
7951
|
+
url: "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.0.tgz",
|
|
7952
|
+
sha256: "c798f79bbcc28079af101ca323c194f2ad6472da0ae80721cc3eaa370e753f6a",
|
|
7490
7953
|
extractPath: "package/",
|
|
7491
7954
|
archiveType: "tar.gz"
|
|
7492
7955
|
},
|
|
7493
7956
|
"win32-x64": {
|
|
7494
7957
|
name: "rolldown",
|
|
7495
|
-
version: "1.
|
|
7958
|
+
version: "1.1.0",
|
|
7496
7959
|
platform: "win32",
|
|
7497
7960
|
arch: "x64",
|
|
7498
|
-
url: "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.
|
|
7499
|
-
sha256: "
|
|
7961
|
+
url: "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.0.tgz",
|
|
7962
|
+
sha256: "3457d231d8dcce922bf1cb8f696f04600378ce8e88c0898dba9999239d64dd4a",
|
|
7500
7963
|
extractPath: "package/",
|
|
7501
7964
|
archiveType: "tar.gz"
|
|
7502
7965
|
},
|
|
7503
7966
|
"win32-arm64": {
|
|
7504
7967
|
name: "rolldown",
|
|
7505
|
-
version: "1.
|
|
7968
|
+
version: "1.1.0",
|
|
7506
7969
|
platform: "win32",
|
|
7507
7970
|
arch: "arm64",
|
|
7508
|
-
url: "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.
|
|
7509
|
-
sha256: "
|
|
7971
|
+
url: "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.0.tgz",
|
|
7972
|
+
sha256: "c8e9e9643f2e905ca0062d2e768c2966e48f0a47595c8c2b7658a085024c8ce3",
|
|
7510
7973
|
extractPath: "package/",
|
|
7511
7974
|
archiveType: "tar.gz"
|
|
7512
7975
|
}
|
|
@@ -8243,6 +8706,21 @@ function updateSymlinkAtomic(installBase, component, version) {
|
|
|
8243
8706
|
* 5. Update symlink (Unix) or service registration (Windows)
|
|
8244
8707
|
* 6. Start service
|
|
8245
8708
|
*/
|
|
8709
|
+
/**
|
|
8710
|
+
* Resolve the target version for an npm-source upgrade (no --from/--url).
|
|
8711
|
+
*
|
|
8712
|
+
* The npm-source flow assumes the operator already ran
|
|
8713
|
+
* `npm install -g @kici-dev/<pkg>@<version>`, which overwrites the global
|
|
8714
|
+
* package in place. The running `kici-admin` binary is therefore the new
|
|
8715
|
+
* version, and `running` is its self-reported version. We default the target
|
|
8716
|
+
* to it, or validate an explicitly-passed --version matches — a mismatch means
|
|
8717
|
+
* the npm install did not actually update the global binary.
|
|
8718
|
+
*/
|
|
8719
|
+
function resolveNpmSourceVersion(opts) {
|
|
8720
|
+
if (opts.running === "unknown" || opts.running.trim() === "") throw new Error("npm-source upgrade: could not determine the running package version. Pass --from <archive> / --url <url> + --version for an archive-based upgrade instead.");
|
|
8721
|
+
if (opts.requested && opts.requested !== opts.running) throw new Error(`npm-source upgrade: requested --version ${opts.requested} does not match the installed package version ${opts.running}. Run \`npm install -g @kici-dev/<pkg>@${opts.requested}\` first, then re-run the upgrade.`);
|
|
8722
|
+
return opts.running;
|
|
8723
|
+
}
|
|
8246
8724
|
async function performVersionedUpgrade(component, opts) {
|
|
8247
8725
|
try {
|
|
8248
8726
|
const platform = detectPlatform(opts.platform);
|
|
@@ -8272,8 +8750,8 @@ async function performVersionedUpgrade(component, opts) {
|
|
|
8272
8750
|
return;
|
|
8273
8751
|
}
|
|
8274
8752
|
if (!opts.from && !opts.url) {
|
|
8275
|
-
|
|
8276
|
-
|
|
8753
|
+
await performNpmSourceUpgrade(config, resolvedInstance, manager, opts);
|
|
8754
|
+
return;
|
|
8277
8755
|
}
|
|
8278
8756
|
if (!opts.version) {
|
|
8279
8757
|
console.error("Error: --version is required to specify the target version");
|
|
@@ -8375,6 +8853,41 @@ async function performVersionedUpgrade(component, opts) {
|
|
|
8375
8853
|
}
|
|
8376
8854
|
}
|
|
8377
8855
|
/**
|
|
8856
|
+
* npm-source upgrade (no --from/--url): the operator has already run
|
|
8857
|
+
* `npm install -g @kici-dev/<pkg>@<version>`, replacing the global package
|
|
8858
|
+
* in place. The systemd/launchd/Windows unit's ExecStart points at that global
|
|
8859
|
+
* package (see install.ts → import.meta.resolve), so a stop+start re-executes
|
|
8860
|
+
* the freshly-installed code. No archive, no versioned dir, no symlink.
|
|
8861
|
+
*/
|
|
8862
|
+
async function performNpmSourceUpgrade(config, resolvedInstance, manager, opts) {
|
|
8863
|
+
const running = readKiciVersion();
|
|
8864
|
+
const version = resolveNpmSourceVersion({
|
|
8865
|
+
requested: opts.version,
|
|
8866
|
+
running
|
|
8867
|
+
});
|
|
8868
|
+
if (!await manager.isInstalled(config)) {
|
|
8869
|
+
console.error(`Error: service "${config.name}" is not installed`);
|
|
8870
|
+
process.exit(1);
|
|
8871
|
+
}
|
|
8872
|
+
if (!opts.yes) {
|
|
8873
|
+
console.log(`This will restart "${config.name}" onto the npm-installed version ${version}.`);
|
|
8874
|
+
console.log(" The service will be stopped briefly during the restart.");
|
|
8875
|
+
console.log("");
|
|
8876
|
+
if (!await confirm$2("Proceed with upgrade?")) {
|
|
8877
|
+
console.log("Upgrade cancelled.");
|
|
8878
|
+
return;
|
|
8879
|
+
}
|
|
8880
|
+
}
|
|
8881
|
+
console.log("Restarting service onto the npm-installed package...");
|
|
8882
|
+
if ((await manager.status(config)).state === "running") await manager.stop(config);
|
|
8883
|
+
await manager.start(config);
|
|
8884
|
+
writeManifest(resolvedInstance.instanceDir, {
|
|
8885
|
+
...resolvedInstance.manifest,
|
|
8886
|
+
kiciVersion: version
|
|
8887
|
+
});
|
|
8888
|
+
console.log(`Upgrade complete: service "${config.name}" is now running version ${version}.`);
|
|
8889
|
+
}
|
|
8890
|
+
/**
|
|
8378
8891
|
* Handle --rollback: switch symlink to the previous version and restart.
|
|
8379
8892
|
*/
|
|
8380
8893
|
async function handleRollback(component, platform, installBase, config, manager, opts) {
|
|
@@ -9730,6 +10243,7 @@ const TOKEN_PREFIX = "kici_join_v1";
|
|
|
9730
10243
|
const DEFAULT_EXPIRY_MS = 36e5;
|
|
9731
10244
|
const TOKEN_ALREADY_USED_MESSAGE = "Join token has already been used. Generate a new token with: kici admin create-join-token";
|
|
9732
10245
|
var JoinTokenManager = class {
|
|
10246
|
+
deps;
|
|
9733
10247
|
constructor(deps) {
|
|
9734
10248
|
this.deps = deps;
|
|
9735
10249
|
}
|
|
@@ -9859,6 +10373,7 @@ const DEFAULT_EXPIRY_DAYS = 90;
|
|
|
9859
10373
|
* Used by the coordinator to manage credentials for all cluster members.
|
|
9860
10374
|
*/
|
|
9861
10375
|
var PeerCredentialStore = class {
|
|
10376
|
+
db;
|
|
9862
10377
|
constructor(db) {
|
|
9863
10378
|
this.db = db;
|
|
9864
10379
|
}
|
|
@@ -11448,6 +11963,8 @@ var init_execution_steps = __esmMin((() => {
|
|
|
11448
11963
|
enabled: true
|
|
11449
11964
|
};
|
|
11450
11965
|
ExecutionStepsAdapter = class {
|
|
11966
|
+
kdb;
|
|
11967
|
+
instanceId;
|
|
11451
11968
|
db = "orchestrator";
|
|
11452
11969
|
table = "execution_steps";
|
|
11453
11970
|
tenantColumn = "routing_key";
|
|
@@ -11603,6 +12120,8 @@ var init_execution_jobs = __esmMin((() => {
|
|
|
11603
12120
|
enabled: true
|
|
11604
12121
|
};
|
|
11605
12122
|
ExecutionJobsAdapter = class {
|
|
12123
|
+
kdb;
|
|
12124
|
+
instanceId;
|
|
11606
12125
|
db = "orchestrator";
|
|
11607
12126
|
table = "execution_jobs";
|
|
11608
12127
|
tenantColumn = "routing_key";
|
|
@@ -11771,6 +12290,8 @@ var init_execution_runs = __esmMin((() => {
|
|
|
11771
12290
|
enabled: true
|
|
11772
12291
|
};
|
|
11773
12292
|
ExecutionRunsAdapter = class {
|
|
12293
|
+
kdb;
|
|
12294
|
+
instanceId;
|
|
11774
12295
|
db = "orchestrator";
|
|
11775
12296
|
table = "execution_runs";
|
|
11776
12297
|
tenantColumn = "routing_key";
|
|
@@ -12002,6 +12523,8 @@ var init_secret_audit_log = __esmMin((() => {
|
|
|
12002
12523
|
enabled: true
|
|
12003
12524
|
};
|
|
12004
12525
|
SecretAuditLogAdapter = class {
|
|
12526
|
+
kdb;
|
|
12527
|
+
instanceId;
|
|
12005
12528
|
db = "orchestrator";
|
|
12006
12529
|
table = "secret_audit_log";
|
|
12007
12530
|
tenantColumn = "routing_key";
|
|
@@ -12255,6 +12778,8 @@ var init_access_log = __esmMin((() => {
|
|
|
12255
12778
|
enabled: true
|
|
12256
12779
|
};
|
|
12257
12780
|
AccessLogAdapter = class {
|
|
12781
|
+
kdb;
|
|
12782
|
+
instanceId;
|
|
12258
12783
|
db = "orchestrator";
|
|
12259
12784
|
table = "access_log";
|
|
12260
12785
|
tenantColumn = "org_id";
|
|
@@ -12510,6 +13035,8 @@ var init_event_log = __esmMin((() => {
|
|
|
12510
13035
|
enabled: true
|
|
12511
13036
|
};
|
|
12512
13037
|
EventLogAdapter = class {
|
|
13038
|
+
kdb;
|
|
13039
|
+
instanceId;
|
|
12513
13040
|
db = "orchestrator";
|
|
12514
13041
|
table = "event_log";
|
|
12515
13042
|
tenantColumn = "routing_key";
|
|
@@ -14590,6 +15117,7 @@ var FirecrackerApiError = class extends Error {
|
|
|
14590
15117
|
* the `socketPath` option for HTTP-over-Unix-socket communication.
|
|
14591
15118
|
*/
|
|
14592
15119
|
var FirecrackerApi = class {
|
|
15120
|
+
socketPath;
|
|
14593
15121
|
constructor(socketPath) {
|
|
14594
15122
|
this.socketPath = socketPath;
|
|
14595
15123
|
}
|
|
@@ -16577,6 +17105,7 @@ async function writeConfigFile(path, config) {
|
|
|
16577
17105
|
await writeFile(path, stringify(config), "utf-8");
|
|
16578
17106
|
}
|
|
16579
17107
|
var JoinClient = class {
|
|
17108
|
+
options;
|
|
16580
17109
|
constructor(options) {
|
|
16581
17110
|
this.options = options;
|
|
16582
17111
|
if (!options.platformUrl && !options.peerUrl) throw new Error("Either --platform or --peer must be specified");
|
|
@@ -16748,6 +17277,7 @@ function buildProgram() {
|
|
|
16748
17277
|
registerConfigCommands(program, getClient);
|
|
16749
17278
|
registerDbCommands(program, getClient);
|
|
16750
17279
|
registerSourceCommands(program, getClient);
|
|
17280
|
+
registerRemoteSourceCommands(program);
|
|
16751
17281
|
registerWorkflowCommands(program, getClient);
|
|
16752
17282
|
registerRunsCommands(program, getClient);
|
|
16753
17283
|
registerEventLogCommands(program, getClient);
|
|
@@ -16779,8 +17309,27 @@ function buildProgram() {
|
|
|
16779
17309
|
function runCli(argv = process.argv) {
|
|
16780
17310
|
buildProgram().parse(argv);
|
|
16781
17311
|
}
|
|
16782
|
-
|
|
17312
|
+
/**
|
|
17313
|
+
* Canonicalize a path through any symlinks, falling back to a plain `resolve`
|
|
17314
|
+
* when the target does not exist on disk. The entry-point guard compares the
|
|
17315
|
+
* invoked script path against this module's own path; both sides must be fully
|
|
17316
|
+
* canonicalized or a symlinked invocation path silently fails the match. The
|
|
17317
|
+
* canonical example is the light-package launcher running
|
|
17318
|
+
* `node /tmp/.../kici-admin.cjs` on macOS, where `/tmp` is a symlink to
|
|
17319
|
+
* `/private/tmp`: `process.argv[1]` keeps the `/tmp` form while the bundle's
|
|
17320
|
+
* `import.meta.url` resolves to the real `/private/tmp` path, so an
|
|
17321
|
+
* un-canonicalized comparison is always false and the CLI exits 0 without
|
|
17322
|
+
* running any command.
|
|
17323
|
+
*/
|
|
17324
|
+
function canonicalize(p) {
|
|
17325
|
+
try {
|
|
17326
|
+
return realpathSync(resolve(p));
|
|
17327
|
+
} catch {
|
|
17328
|
+
return resolve(p);
|
|
17329
|
+
}
|
|
17330
|
+
}
|
|
17331
|
+
if (canonicalize(process.argv[1] ?? "") === canonicalize(fileURLToPath(import.meta.url))) runCli();
|
|
16783
17332
|
//#endregion
|
|
16784
|
-
export { buildProgram, runCli };
|
|
17333
|
+
export { buildProgram, canonicalize, runCli };
|
|
16785
17334
|
|
|
16786
17335
|
//# sourceMappingURL=cli.js.map
|