@kici-dev/compiler 0.1.25 → 0.1.27
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/cli-banner.d.ts +6 -3
- package/dist/cli-banner.js +13 -5
- package/dist/cli.js +66 -43
- package/dist/commands/check-mode.d.ts +1 -1
- package/dist/commands/compile.js +3 -3
- package/dist/commands/index.d.ts +5 -1
- package/dist/commands/index.js +6 -3
- package/dist/commands/init.js +1 -1
- package/dist/commands/local-trust-root.d.ts +6 -0
- package/dist/commands/local-trust-root.js +52 -0
- package/dist/commands/local.d.ts +39 -0
- package/dist/commands/local.js +137 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +40 -0
- package/dist/commands/logout.js +7 -0
- package/dist/commands/preview.js +1 -1
- package/dist/commands/run-banner.d.ts +31 -0
- package/dist/commands/run-banner.js +25 -0
- package/dist/commands/run-routed.d.ts +53 -0
- package/dist/commands/run-routed.js +176 -0
- package/dist/commands/run.d.ts +0 -17
- package/dist/commands/run.js +7 -50
- package/dist/commands/secrets-list.d.ts +2 -2
- package/dist/commands/secrets-list.js +4 -4
- package/dist/commands/types.d.ts +3 -3
- package/dist/commands/types.js +4 -4
- package/dist/execution/executor.js +7 -7
- package/dist/generators/secrets-dts.d.ts +9 -9
- package/dist/generators/secrets-dts.js +12 -12
- package/dist/llm-context/llms-architecture.txt +2 -2
- package/dist/llm-context/llms-cli.txt +674 -340
- package/dist/llm-context/llms-features.txt +334 -336
- package/dist/llm-context/llms-full.txt +1207 -892
- package/dist/llm-context/llms-getting-started.txt +7 -15
- package/dist/llm-context/llms-patterns.txt +5 -23
- package/dist/llm-context/llms-providers.txt +10 -1
- package/dist/llm-context/llms-sdk.txt +12 -12
- package/dist/llm-context/llms.txt +5 -5
- package/dist/local-executor/secret-loader.d.ts +1 -1
- package/dist/local-plane/orchestrator-process.d.ts +65 -0
- package/dist/local-plane/orchestrator-process.js +115 -0
- package/dist/local-plane/paths.d.ts +39 -0
- package/dist/local-plane/paths.js +54 -0
- package/dist/local-plane/plane-manager.d.ts +151 -0
- package/dist/local-plane/plane-manager.js +340 -0
- package/dist/local-plane/plane-seed.d.ts +76 -0
- package/dist/local-plane/plane-seed.js +59 -0
- package/dist/local-plane/plane-trigger.d.ts +62 -0
- package/dist/local-plane/plane-trigger.js +97 -0
- package/dist/local-plane/platform-attach.d.ts +53 -0
- package/dist/local-plane/platform-attach.js +111 -0
- package/dist/local-plane/postgres.d.ts +44 -0
- package/dist/local-plane/postgres.js +165 -0
- package/dist/local-plane/resolve-plane.d.ts +37 -0
- package/dist/local-plane/resolve-plane.js +76 -0
- package/dist/local-plane/run-follow.d.ts +41 -0
- package/dist/local-plane/run-follow.js +104 -0
- package/dist/local-plane/scaler-config.d.ts +54 -0
- package/dist/local-plane/scaler-config.js +114 -0
- package/dist/local-plane/secret-seed.d.ts +59 -0
- package/dist/local-plane/secret-seed.js +112 -0
- package/dist/local-plane/source-provider.d.ts +43 -0
- package/dist/local-plane/source-provider.js +165 -0
- package/dist/local-plane/trusted-routing.d.ts +32 -0
- package/dist/local-plane/trusted-routing.js +47 -0
- package/dist/lockfile/generator.js +7 -7
- package/dist/remote/dashboard-client.d.ts +7 -7
- package/dist/remote/dashboard-client.js +7 -7
- package/dist/remote/platform-client.d.ts +1 -1
- package/dist/remote/secret-loader.d.ts +18 -0
- package/dist/{local-executor → remote}/secret-loader.js +4 -4
- package/dist/remote/secret-upload.d.ts +1 -1
- package/dist/remote/secret-upload.js +2 -2
- package/dist/remote/uploader.d.ts +1 -1
- package/dist/remote/uploader.js +2 -2
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/job-executor.js +1 -1
- package/dist/test-runner/runs-on-display.d.ts +9 -0
- package/dist/{local-executor → test-runner}/runs-on-display.js +1 -1
- package/dist/test-runner/step-context.d.ts +1 -1
- package/dist/test-runner/step-context.js +2 -2
- package/dist/types.d.ts +6 -6
- package/package.json +7 -4
- package/sbom.spdx.json +9884 -1459
- package/dist/local-executor/dag-scheduler.js +0 -183
- package/dist/local-executor/index.js +0 -378
- package/dist/local-executor/job-runner.js +0 -411
- package/dist/local-executor/materializer.js +0 -132
- package/dist/local-executor/output-streamer.js +0 -168
- package/dist/local-executor/payload-generator.js +0 -138
- package/dist/local-executor/picker.js +0 -109
- package/dist/local-executor/to-event-payload.js +0 -21
- package/dist/local-executor/types.js +0 -2
- package/dist/local-executor/workflow-lock.js +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Always-on startup banner for a routed `kici run --local` invocation. States
|
|
3
|
+
* the selected plane, where the agent runs, the secret + identity source, the
|
|
4
|
+
* control commands, and the flags that force a different behavior — so a
|
|
5
|
+
* developer always knows which plane a run used and why (design §5).
|
|
6
|
+
*
|
|
7
|
+
* Three variants:
|
|
8
|
+
* - `offline` — independent plane, local secrets, dev-signed identity.
|
|
9
|
+
* - `attached` — hybrid plane, real Platform-minted OIDC + attestation.
|
|
10
|
+
* - `fallback` — wanted attached but the Platform was unreachable, so the run
|
|
11
|
+
* fell back to offline; a LOUD first line makes the degradation obvious.
|
|
12
|
+
*/
|
|
13
|
+
export type RunBannerMode = 'offline' | 'attached' | 'fallback';
|
|
14
|
+
export interface RunBannerInput {
|
|
15
|
+
mode: RunBannerMode;
|
|
16
|
+
/** Plane orchestrator URL (surfaced on the control line). */
|
|
17
|
+
planeUrl: string;
|
|
18
|
+
/** Org id (attached variant). */
|
|
19
|
+
orgId?: string;
|
|
20
|
+
/** Why the run fell back to offline (fallback variant). */
|
|
21
|
+
fallbackReason?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Trusted fleet-agent profile (`--trusted`): the run routes to the trusted
|
|
24
|
+
* label set, so steps see the ambient host env (minus the agent's own KiCI
|
|
25
|
+
* identity secrets). Surfaced as a loud line so a trusted run is never silent.
|
|
26
|
+
*/
|
|
27
|
+
trusted?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Render the boxed run banner as a plain (uncolored) multi-line string. */
|
|
30
|
+
export declare function renderRunBanner(input: RunBannerInput): string;
|
|
31
|
+
//# sourceMappingURL=run-banner.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
//#region src/commands/run-banner.ts
|
|
3
|
+
/** Render the boxed run banner as a plain (uncolored) multi-line string. */
|
|
4
|
+
function renderRunBanner(input) {
|
|
5
|
+
const title = input.mode === "attached" ? "kici run --local (connected)" : "kici run --local";
|
|
6
|
+
const rows = [];
|
|
7
|
+
if (input.mode === "fallback") rows.push(["⚠", `Platform unreachable — fell back to OFFLINE${input.fallbackReason ? ` (${input.fallbackReason})` : ""}`]);
|
|
8
|
+
if (input.mode === "attached") rows.push(["plane", "local dev orchestrator (hybrid, attached)"], ["agent", "this machine (bare-metal)"], ["secrets", `REAL scoped${input.orgId ? ` (org: ${input.orgId})` : ""}`], ["identity", "real Platform OIDC + attestation"], ["control", `kici local status | logs | detach (${input.planeUrl})`], ["force", "--offline (local plane) · --in-place (ambient)"]);
|
|
9
|
+
else rows.push(["plane", "local dev orchestrator (independent, offline)"], ["agent", "this machine (bare-metal)"], ["secrets", "LOCAL files (.kici/.secrets, .env.local, --env)"], ["identity", "DEV-SIGNED (iss=kici-local — NOT prod)"], ["control", `kici local status | logs | down (${input.planeUrl})`], ["force", "--connected (attach to Platform) · --in-place (ambient)"]);
|
|
10
|
+
if (input.trusted) rows.push(["execution", "TRUSTED — host env passthrough (NOT sandboxed)"]);
|
|
11
|
+
const labelWidth = Math.max(...rows.map(([label]) => label.length));
|
|
12
|
+
const bodyLines = rows.map(([label, value]) => `${(label + ":").padEnd(labelWidth + 1)} ${value}`);
|
|
13
|
+
const contentWidth = Math.max(title.length + 2, ...bodyLines.map((l) => l.length));
|
|
14
|
+
const top = `┌ ${title} ${"─".repeat(Math.max(0, contentWidth - title.length))}┐`;
|
|
15
|
+
const bottom = `└${"─".repeat(contentWidth + 2)}┘`;
|
|
16
|
+
return [
|
|
17
|
+
top,
|
|
18
|
+
...bodyLines.map((l) => `│ ${l.padEnd(contentWidth)} │`),
|
|
19
|
+
bottom
|
|
20
|
+
].join("\n");
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { renderRunBanner };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=run-banner.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kici run --local [event]` — a real routed dispatch with this machine as the
|
|
3
|
+
* ephemeral agent, through the warm local dev plane. In this phase only the
|
|
4
|
+
* offline (independent) plane is wired; Platform attachment (`--connected` /
|
|
5
|
+
* auto-select hybrid) lands with the attachment work.
|
|
6
|
+
*
|
|
7
|
+
* The offline path reuses the real orchestrator + agent pipeline end-to-end, so
|
|
8
|
+
* the execution parity dividend (emit / cache / needs / parallel / `KICI_SOURCE_*`)
|
|
9
|
+
* holds by construction — there is no second engine.
|
|
10
|
+
*/
|
|
11
|
+
export interface RunRoutedOptions {
|
|
12
|
+
event?: string;
|
|
13
|
+
local?: boolean;
|
|
14
|
+
offline?: boolean;
|
|
15
|
+
connected?: boolean;
|
|
16
|
+
inPlace?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Trusted fleet-agent profile: route this run to the plane's trusted label
|
|
19
|
+
* set so steps run with the ambient host env passed through (minus the
|
|
20
|
+
* agent's own KiCI identity secrets). Selects a PRE-CONFIGURED trusted scaler
|
|
21
|
+
* label set by appending the `self-hosted` routing label to the run's job
|
|
22
|
+
* `runsOn` — it never injects `KICI_TRUSTED_ENV` onto a dispatch payload.
|
|
23
|
+
*/
|
|
24
|
+
trusted?: boolean;
|
|
25
|
+
/** Flat per-run secrets (`--env KEY=VALUE`); delivery lands with the secret path. */
|
|
26
|
+
env?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Path to a dispatch payload JSON `{ action?, client_payload? }`. Only read
|
|
29
|
+
* when the event is `dispatch`: `action` becomes the dispatch `types` matcher
|
|
30
|
+
* key and `client_payload` reaches the workflow. This is how `packages/ci`
|
|
31
|
+
* targets a single `dispatch()` workflow (e.g. deploy-stg) on the routed path.
|
|
32
|
+
*/
|
|
33
|
+
payload?: string;
|
|
34
|
+
kiciDir?: string;
|
|
35
|
+
quiet?: boolean;
|
|
36
|
+
debug?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Entry point for the action-bearing `kici run`. Validates the routing flags and
|
|
40
|
+
* drives the offline routed run. Returns true on run success.
|
|
41
|
+
*/
|
|
42
|
+
export declare function runRoutedCommand(options: RunRoutedOptions): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Read a dispatch payload file `{ action?, client_payload? }`. Returns the
|
|
45
|
+
* action + client_payload the routed dispatch trigger carries. An absent
|
|
46
|
+
* `--payload` yields an empty action (a bare `dispatch()` workflow still
|
|
47
|
+
* matches); a present file is parsed as JSON.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readDispatchPayload(payloadPath?: string): {
|
|
50
|
+
action?: string;
|
|
51
|
+
clientPayload?: unknown;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=run-routed.d.ts.map
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import { resolveKiciDir } from "../execution/executor.js";
|
|
3
|
+
import "../execution/index.js";
|
|
4
|
+
import { formatSummary } from "../remote/output/summary.js";
|
|
5
|
+
import { IN_PLACE_ROUTING_LABEL, TRUSTED_ROUTING_LABEL } from "../local-plane/scaler-config.js";
|
|
6
|
+
import { ensureLocalSource } from "../local-plane/plane-seed.js";
|
|
7
|
+
import { triggerRun } from "../local-plane/plane-trigger.js";
|
|
8
|
+
import { resolvePlaneForRun } from "../local-plane/resolve-plane.js";
|
|
9
|
+
import { followRun } from "../local-plane/run-follow.js";
|
|
10
|
+
import { seedLocalSecrets } from "../local-plane/secret-seed.js";
|
|
11
|
+
import { resolveWorkdir } from "../local-plane/source-provider.js";
|
|
12
|
+
import { injectRunsOnLabel } from "../local-plane/trusted-routing.js";
|
|
13
|
+
import { compileCommand } from "./compile.js";
|
|
14
|
+
import { withStdoutOnStderr } from "./run.js";
|
|
15
|
+
import { renderRunBanner } from "./run-banner.js";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
import pc from "picocolors";
|
|
19
|
+
import { logger, toErrorMessage } from "@kici-dev/core";
|
|
20
|
+
//#region src/commands/run-routed.ts
|
|
21
|
+
/**
|
|
22
|
+
* `kici run --local [event]` — a real routed dispatch with this machine as the
|
|
23
|
+
* ephemeral agent, through the warm local dev plane. In this phase only the
|
|
24
|
+
* offline (independent) plane is wired; Platform attachment (`--connected` /
|
|
25
|
+
* auto-select hybrid) lands with the attachment work.
|
|
26
|
+
*
|
|
27
|
+
* The offline path reuses the real orchestrator + agent pipeline end-to-end, so
|
|
28
|
+
* the execution parity dividend (emit / cache / needs / parallel / `KICI_SOURCE_*`)
|
|
29
|
+
* holds by construction — there is no second engine.
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Entry point for the action-bearing `kici run`. Validates the routing flags and
|
|
33
|
+
* drives the offline routed run. Returns true on run success.
|
|
34
|
+
*/
|
|
35
|
+
async function runRoutedCommand(options) {
|
|
36
|
+
if (options.debug) process.env.KICI_DEBUG = "true";
|
|
37
|
+
if (!options.local) {
|
|
38
|
+
logger.error(pc.red("kici run (connected cloud run) is not yet available. Use `kici run --local` for a routed run on this machine, or `kici run remote <fixture>` for the fixture path."));
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (!options.event) {
|
|
42
|
+
logger.error(pc.red("Provide an event to run, e.g. `kici run --local push`."));
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return runRouted({
|
|
46
|
+
...options,
|
|
47
|
+
event: options.event
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Read a dispatch payload file `{ action?, client_payload? }`. Returns the
|
|
52
|
+
* action + client_payload the routed dispatch trigger carries. An absent
|
|
53
|
+
* `--payload` yields an empty action (a bare `dispatch()` workflow still
|
|
54
|
+
* matches); a present file is parsed as JSON.
|
|
55
|
+
*/
|
|
56
|
+
function readDispatchPayload(payloadPath) {
|
|
57
|
+
if (!payloadPath) return {};
|
|
58
|
+
const raw = JSON.parse(readFileSync(payloadPath, "utf-8"));
|
|
59
|
+
return {
|
|
60
|
+
action: raw.action,
|
|
61
|
+
clientPayload: raw.client_payload
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Drive the full routed run against the warm local plane (offline or attached). */
|
|
65
|
+
async function runRouted(options) {
|
|
66
|
+
const quiet = Boolean(options.quiet);
|
|
67
|
+
const kiciDir = resolveKiciDir(options.kiciDir);
|
|
68
|
+
const repoRoot = path.resolve(kiciDir, "..");
|
|
69
|
+
if (!(quiet ? await withStdoutOnStderr(() => compileCommand({
|
|
70
|
+
kiciDir,
|
|
71
|
+
check: false,
|
|
72
|
+
verbose: options.debug ?? false,
|
|
73
|
+
quiet: true
|
|
74
|
+
})) : await compileCommand({
|
|
75
|
+
kiciDir,
|
|
76
|
+
check: false,
|
|
77
|
+
verbose: options.debug ?? false
|
|
78
|
+
}))) return false;
|
|
79
|
+
let cleanup;
|
|
80
|
+
const restoreLocks = [];
|
|
81
|
+
try {
|
|
82
|
+
if (!quiet) logger.info(pc.dim("Starting the local dev plane…"));
|
|
83
|
+
const resolved = await resolvePlaneForRun({
|
|
84
|
+
offline: options.offline,
|
|
85
|
+
connected: options.connected
|
|
86
|
+
});
|
|
87
|
+
if ("error" in resolved) {
|
|
88
|
+
logger.error(pc.red(resolved.error));
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
const plane = resolved.plane;
|
|
92
|
+
if (!plane.url || !plane.adminToken) {
|
|
93
|
+
logger.error(pc.red("Local dev plane did not report a URL + admin token."));
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const trusted = Boolean(options.trusted);
|
|
97
|
+
if (!quiet) logger.info(renderRunBanner(resolved.kind === "attached" ? {
|
|
98
|
+
mode: "attached",
|
|
99
|
+
planeUrl: plane.url,
|
|
100
|
+
orgId: resolved.orgId,
|
|
101
|
+
trusted
|
|
102
|
+
} : resolved.kind === "fallback" ? {
|
|
103
|
+
mode: "fallback",
|
|
104
|
+
planeUrl: plane.url,
|
|
105
|
+
fallbackReason: resolved.reason,
|
|
106
|
+
trusted
|
|
107
|
+
} : {
|
|
108
|
+
mode: "offline",
|
|
109
|
+
planeUrl: plane.url,
|
|
110
|
+
trusted
|
|
111
|
+
}));
|
|
112
|
+
const workdir = await resolveWorkdir({
|
|
113
|
+
inPlace: Boolean(options.inPlace),
|
|
114
|
+
repoRoot
|
|
115
|
+
});
|
|
116
|
+
cleanup = workdir.cleanup;
|
|
117
|
+
if (trusted) {
|
|
118
|
+
const lockPath = path.join(workdir.dir, ".kici", "kici.lock.json");
|
|
119
|
+
restoreLocks.push(injectRunsOnLabel(lockPath, TRUSTED_ROUTING_LABEL).restore);
|
|
120
|
+
if (options.inPlace) restoreLocks.push(injectRunsOnLabel(lockPath, IN_PLACE_ROUTING_LABEL).restore);
|
|
121
|
+
}
|
|
122
|
+
const seeded = await ensureLocalSource(plane.url, plane.adminToken, {
|
|
123
|
+
repoDir: workdir.dir,
|
|
124
|
+
inPlace: Boolean(options.inPlace)
|
|
125
|
+
});
|
|
126
|
+
const seededSecrets = await seedLocalSecrets(plane.url, plane.adminToken, {
|
|
127
|
+
orgId: seeded.orgId,
|
|
128
|
+
kiciDir
|
|
129
|
+
});
|
|
130
|
+
if (!quiet && seededSecrets.contexts.length > 0) logger.info(pc.dim(`Seeded ${seededSecrets.secretCount} local secret(s) across ${seededSecrets.contexts.length} context(s): ${seededSecrets.contexts.join(", ")}`));
|
|
131
|
+
if (!quiet) logger.info(pc.dim(`Triggering ${options.event} …`));
|
|
132
|
+
const dispatch = options.event === "dispatch" ? readDispatchPayload(options.payload) : void 0;
|
|
133
|
+
const runId = await triggerRun(plane.url, plane.adminToken, {
|
|
134
|
+
orgId: seeded.orgId,
|
|
135
|
+
sourceId: seeded.sourceName,
|
|
136
|
+
repoFullName: ".",
|
|
137
|
+
event: options.event === "dispatch" ? "dispatch" : options.event === "pull_request" ? "pull_request" : "push",
|
|
138
|
+
ref: workdir.ref,
|
|
139
|
+
sha: workdir.sha,
|
|
140
|
+
defaultBranch: workdir.branch,
|
|
141
|
+
...dispatch && {
|
|
142
|
+
action: dispatch.action,
|
|
143
|
+
clientPayload: dispatch.clientPayload
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
if (!quiet) logger.info(pc.green(`Run started: ${runId}`));
|
|
147
|
+
const outcome = await followRun(plane.url, plane.adminToken, runId, {
|
|
148
|
+
quiet,
|
|
149
|
+
onLine: (line) => process.stdout.write(line + "\n")
|
|
150
|
+
});
|
|
151
|
+
if (!quiet) {
|
|
152
|
+
const result = {
|
|
153
|
+
fixtureId: options.event,
|
|
154
|
+
runId,
|
|
155
|
+
status: outcome.status === "success" ? "success" : "failed",
|
|
156
|
+
totalDurationMs: 0,
|
|
157
|
+
jobs: outcome.jobs
|
|
158
|
+
};
|
|
159
|
+
process.stdout.write("\n" + formatSummary(result) + "\n");
|
|
160
|
+
}
|
|
161
|
+
return outcome.status === "success";
|
|
162
|
+
} catch (error) {
|
|
163
|
+
logger.error(pc.red(`\nError: ${toErrorMessage(error)}\n`));
|
|
164
|
+
if (options.debug && error instanceof Error && error.stack) logger.error(pc.gray(error.stack));
|
|
165
|
+
return false;
|
|
166
|
+
} finally {
|
|
167
|
+
for (const restore of restoreLocks.reverse()) try {
|
|
168
|
+
restore();
|
|
169
|
+
} catch {}
|
|
170
|
+
if (cleanup) await cleanup().catch(() => void 0);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
export { readDispatchPayload, runRoutedCommand };
|
|
175
|
+
|
|
176
|
+
//# sourceMappingURL=run-routed.js.map
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
import { type HostTargetSelector, type InputsDescriptorMap } from '@kici-dev/engine';
|
|
2
|
-
import type { RunLocalOptions } from '../local-executor/types.js';
|
|
3
2
|
import type { RemoteRunOptions } from './preview.js';
|
|
4
|
-
/**
|
|
5
|
-
* Print a usage block for `kici run local` when the event argument is missing.
|
|
6
|
-
*
|
|
7
|
-
* Mirrors the discoverable help `kici preview` prints for a missing event: a
|
|
8
|
-
* bold synopsis line, a one-line description, and a few concrete event
|
|
9
|
-
* examples. The caller exits non-zero after printing — a missing event is a
|
|
10
|
-
* usage error, unlike `kici preview` which treats no-event as help.
|
|
11
|
-
*/
|
|
12
|
-
export declare function printRunLocalUsage(): void;
|
|
13
3
|
/**
|
|
14
4
|
* Compile `--target` selector strings into a {@link HostTargetSelector}. Each
|
|
15
5
|
* string becomes one AND value (its own include set); repeated values
|
|
@@ -42,13 +32,6 @@ export declare function buildDispatchInputs(pairs: string[], descriptor: InputsD
|
|
|
42
32
|
* stderr regardless.
|
|
43
33
|
*/
|
|
44
34
|
export declare function withStdoutOnStderr<T>(fn: () => Promise<T>): Promise<T>;
|
|
45
|
-
/**
|
|
46
|
-
* Run a workflow locally using the local executor.
|
|
47
|
-
* Thin wrapper that delegates to executeLocal from local-executor.
|
|
48
|
-
*
|
|
49
|
-
* Exit codes: 0 = success, 1 = job failure, 2 = config/compilation error
|
|
50
|
-
*/
|
|
51
|
-
export declare function runLocalCommand(options: RunLocalOptions): Promise<boolean>;
|
|
52
35
|
/**
|
|
53
36
|
* Run fixtures remotely, routed through the Platform.
|
|
54
37
|
*/
|
package/dist/commands/run.js
CHANGED
|
@@ -10,11 +10,11 @@ import { createOverlayTarball, getSizeWarning, uploadTarball } from "../remote/u
|
|
|
10
10
|
import { formatJsonResult } from "../remote/output/json.js";
|
|
11
11
|
import { formatJunitResult } from "../remote/output/junit.js";
|
|
12
12
|
import { formatErrorHighlight, formatMultiFixtureSummary, formatSummary } from "../remote/output/summary.js";
|
|
13
|
-
import { compileCommand } from "./compile.js";
|
|
14
13
|
import { compileFixtures, filterFixtures } from "../fixtures/compiler.js";
|
|
15
14
|
import { describeEvent } from "../fixtures/describe-event.js";
|
|
16
15
|
import { FixturePickerCancelledError, runFixturePicker } from "../fixtures/picker.js";
|
|
17
16
|
import { listHeldRunsForRun, resolveHeldRunContext } from "./held-run-client.js";
|
|
17
|
+
import { compileCommand } from "./compile.js";
|
|
18
18
|
import { handleNewHolds } from "./run-hold-watch.js";
|
|
19
19
|
import path from "node:path";
|
|
20
20
|
import pc from "picocolors";
|
|
@@ -24,24 +24,6 @@ import { coerceDispatchInputs, parseInputPairs } from "@kici-dev/engine";
|
|
|
24
24
|
import { normalizeRunsOnToMatchers } from "@kici-dev/engine/labels/compile";
|
|
25
25
|
import { confirm } from "@inquirer/prompts";
|
|
26
26
|
//#region src/commands/run.ts
|
|
27
|
-
/**
|
|
28
|
-
* Print a usage block for `kici run local` when the event argument is missing.
|
|
29
|
-
*
|
|
30
|
-
* Mirrors the discoverable help `kici preview` prints for a missing event: a
|
|
31
|
-
* bold synopsis line, a one-line description, and a few concrete event
|
|
32
|
-
* examples. The caller exits non-zero after printing — a missing event is a
|
|
33
|
-
* usage error, unlike `kici preview` which treats no-event as help.
|
|
34
|
-
*/
|
|
35
|
-
function printRunLocalUsage() {
|
|
36
|
-
logger.info(pc.bold("\nUsage: kici run local <event> [options]\n"));
|
|
37
|
-
logger.info(pc.gray("Execute workflows locally for a given event, without orchestrator infrastructure.\n"));
|
|
38
|
-
logger.info(pc.gray("Examples:"));
|
|
39
|
-
logger.info(pc.gray(" kici run local push"));
|
|
40
|
-
logger.info(pc.gray(" kici run local pr:open"));
|
|
41
|
-
logger.info(pc.gray(" kici run local schedule"));
|
|
42
|
-
logger.info(pc.gray(" kici run local lifecycle:workflow_complete\n"));
|
|
43
|
-
logger.info(pc.gray("Or pick a workflow interactively: kici run local --pick\n"));
|
|
44
|
-
}
|
|
45
27
|
/** Terminal run statuses returned by the Platform run-status snapshot. */
|
|
46
28
|
const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
47
29
|
"success",
|
|
@@ -127,11 +109,11 @@ async function withStdoutOnStderr(fn) {
|
|
|
127
109
|
}
|
|
128
110
|
}
|
|
129
111
|
/**
|
|
130
|
-
* Recompile `.kici/workflows` → `kici.lock.json` before a remote run
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
112
|
+
* Recompile `.kici/workflows` → `kici.lock.json` before a remote run. The
|
|
113
|
+
* orchestrator matches triggers and dispatches against the inline lock, so a
|
|
114
|
+
* stale lock would route an edited or newly-added workflow incorrectly. Returns
|
|
115
|
+
* false on a compile/validation error so the caller can abort before any upload
|
|
116
|
+
* or dispatch.
|
|
135
117
|
*/
|
|
136
118
|
async function compileBeforeRemoteRun(options) {
|
|
137
119
|
const pureStdout = Boolean(options.json || options.quiet);
|
|
@@ -144,31 +126,6 @@ async function compileBeforeRemoteRun(options) {
|
|
|
144
126
|
return pureStdout ? withStdoutOnStderr(compile) : compile();
|
|
145
127
|
}
|
|
146
128
|
/**
|
|
147
|
-
* Run a workflow locally using the local executor.
|
|
148
|
-
* Thin wrapper that delegates to executeLocal from local-executor.
|
|
149
|
-
*
|
|
150
|
-
* Exit codes: 0 = success, 1 = job failure, 2 = config/compilation error
|
|
151
|
-
*/
|
|
152
|
-
async function runLocalCommand(options) {
|
|
153
|
-
if (options.debug) {
|
|
154
|
-
process.env.KICI_DEBUG = "true";
|
|
155
|
-
if (!options.quiet) logger.info(pc.gray("Debug mode enabled"));
|
|
156
|
-
}
|
|
157
|
-
try {
|
|
158
|
-
const { executeLocal } = await import("../local-executor/index.js");
|
|
159
|
-
return await executeLocal(options);
|
|
160
|
-
} catch (error) {
|
|
161
|
-
if (error instanceof Error && (error.message.includes("Cannot find module") || error.message.includes("ERR_MODULE_NOT_FOUND"))) {
|
|
162
|
-
logger.error(pc.red("Local executor not yet available. The local execution engine is under development."));
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
const message = toErrorMessage(error);
|
|
166
|
-
logger.error(pc.red(`\nError: ${message}\n`));
|
|
167
|
-
if (options.debug && error instanceof Error && error.stack) logger.error(pc.gray(error.stack));
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
129
|
* Run fixtures remotely, routed through the Platform.
|
|
173
130
|
*/
|
|
174
131
|
async function runRemoteCommand(fixture, options) {
|
|
@@ -694,6 +651,6 @@ function displayRemoteResults(results) {
|
|
|
694
651
|
logger.info("");
|
|
695
652
|
}
|
|
696
653
|
//#endregion
|
|
697
|
-
export { buildDispatchInputs, buildTargetSelector, lookupDispatchInputsDescriptor,
|
|
654
|
+
export { buildDispatchInputs, buildTargetSelector, lookupDispatchInputsDescriptor, runRemoteCommand, withStdoutOnStderr };
|
|
698
655
|
|
|
699
656
|
//# sourceMappingURL=run.js.map
|
|
@@ -5,8 +5,8 @@ export interface SecretsListOptions {
|
|
|
5
5
|
/**
|
|
6
6
|
* List test-available secret contexts through the Platform.
|
|
7
7
|
*
|
|
8
|
-
* Calls GET /api/v1/orgs/:orgId/
|
|
9
|
-
* the org's orchestrator), filters to
|
|
8
|
+
* Calls GET /api/v1/orgs/:orgId/contexts?includeSecrets=true (relayed to
|
|
9
|
+
* the org's orchestrator), filters to contexts with
|
|
10
10
|
* allowLocalExecution=true, and displays a table of names, key names, and
|
|
11
11
|
* flags. Values are never exposed -- only key names.
|
|
12
12
|
*/
|
|
@@ -6,17 +6,17 @@ import { toErrorMessage } from "@kici-dev/core";
|
|
|
6
6
|
/**
|
|
7
7
|
* List test-available secret contexts through the Platform.
|
|
8
8
|
*
|
|
9
|
-
* Calls GET /api/v1/orgs/:orgId/
|
|
10
|
-
* the org's orchestrator), filters to
|
|
9
|
+
* Calls GET /api/v1/orgs/:orgId/contexts?includeSecrets=true (relayed to
|
|
10
|
+
* the org's orchestrator), filters to contexts with
|
|
11
11
|
* allowLocalExecution=true, and displays a table of names, key names, and
|
|
12
12
|
* flags. Values are never exposed -- only key names.
|
|
13
13
|
*/
|
|
14
14
|
async function secretsListCommand(_options = {}) {
|
|
15
15
|
try {
|
|
16
|
-
const contexts = (await (await DashboardClient.load()).
|
|
16
|
+
const contexts = (await (await DashboardClient.load()).listContexts(true)).filter((e) => e.allowLocalExecution);
|
|
17
17
|
if (contexts.length === 0) {
|
|
18
18
|
console.log(pc.yellow("No test-available secret contexts found."));
|
|
19
|
-
console.log(pc.gray("Enable test runs (allowLocalExecution) on
|
|
19
|
+
console.log(pc.gray("Enable test runs (allowLocalExecution) on a context to make its secrets available for test runs."));
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
22
|
renderContextTable(contexts);
|
package/dist/commands/types.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ export interface TypesOptions {
|
|
|
5
5
|
quiet?: boolean;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Generate TypeScript declarations for
|
|
8
|
+
* Generate TypeScript declarations for context secrets.
|
|
9
9
|
*
|
|
10
|
-
* Fetches
|
|
10
|
+
* Fetches context metadata (with secret key names) through the Platform
|
|
11
11
|
* and generates .kici/types/secrets.d.ts with module augmentation for
|
|
12
|
-
* KnownSecretKeys and
|
|
12
|
+
* KnownSecretKeys and ContextSecrets.
|
|
13
13
|
*
|
|
14
14
|
* @param options - Command options
|
|
15
15
|
* @returns true on success, false on error
|
package/dist/commands/types.js
CHANGED
|
@@ -8,11 +8,11 @@ import fs from "node:fs/promises";
|
|
|
8
8
|
import { toErrorMessage } from "@kici-dev/core";
|
|
9
9
|
//#region src/commands/types.ts
|
|
10
10
|
/**
|
|
11
|
-
* Generate TypeScript declarations for
|
|
11
|
+
* Generate TypeScript declarations for context secrets.
|
|
12
12
|
*
|
|
13
|
-
* Fetches
|
|
13
|
+
* Fetches context metadata (with secret key names) through the Platform
|
|
14
14
|
* and generates .kici/types/secrets.d.ts with module augmentation for
|
|
15
|
-
* KnownSecretKeys and
|
|
15
|
+
* KnownSecretKeys and ContextSecrets.
|
|
16
16
|
*
|
|
17
17
|
* @param options - Command options
|
|
18
18
|
* @returns true on success, false on error
|
|
@@ -21,7 +21,7 @@ async function typesCommand(options = {}) {
|
|
|
21
21
|
try {
|
|
22
22
|
const config = await loadGlobalConfig();
|
|
23
23
|
const dtsContent = generateSecretsDts({
|
|
24
|
-
|
|
24
|
+
contexts: (await DashboardClient.fromConfig(config).listContexts(true)).map((e) => ({
|
|
25
25
|
name: e.name,
|
|
26
26
|
keys: e.secretKeys ?? []
|
|
27
27
|
})),
|
|
@@ -5,7 +5,7 @@ import { ensureTsLoaderHook } from "./ts-loader.js";
|
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
8
|
-
import fs from "node:fs/promises";
|
|
8
|
+
import fs$1 from "node:fs/promises";
|
|
9
9
|
//#region src/execution/executor.ts
|
|
10
10
|
/**
|
|
11
11
|
* Load a TypeScript workflow/config module by direct dynamic import.
|
|
@@ -23,7 +23,7 @@ import fs from "node:fs/promises";
|
|
|
23
23
|
async function loadModule(entryPoint, errorContext) {
|
|
24
24
|
let hashBundleSource;
|
|
25
25
|
try {
|
|
26
|
-
hashBundleSource = await fs.readFile(entryPoint, "utf-8");
|
|
26
|
+
hashBundleSource = await fs$1.readFile(entryPoint, "utf-8");
|
|
27
27
|
} catch {}
|
|
28
28
|
try {
|
|
29
29
|
ensureTsLoaderHook();
|
|
@@ -60,12 +60,12 @@ async function loadModule(entryPoint, errorContext) {
|
|
|
60
60
|
async function executeConfig(configPath) {
|
|
61
61
|
const absolutePath = path.resolve(configPath);
|
|
62
62
|
try {
|
|
63
|
-
await fs.access(absolutePath);
|
|
63
|
+
await fs$1.access(absolutePath);
|
|
64
64
|
} catch {
|
|
65
65
|
throw compilerError("E001", `Config file not found: ${absolutePath}`, { suggestion: "Ensure workflow files exist in .kici/workflows/" });
|
|
66
66
|
}
|
|
67
67
|
try {
|
|
68
|
-
await fs.readFile(absolutePath, "utf-8");
|
|
68
|
+
await fs$1.readFile(absolutePath, "utf-8");
|
|
69
69
|
} catch {
|
|
70
70
|
throw compilerError("E001", `Failed to read config file: ${absolutePath}`, { suggestion: "Check file permissions" });
|
|
71
71
|
}
|
|
@@ -180,14 +180,14 @@ async function discoverWorkflows(kiciDir) {
|
|
|
180
180
|
const absoluteKiciDir = resolveKiciDir(kiciDir);
|
|
181
181
|
const workflowDir = path.join(absoluteKiciDir, "workflows");
|
|
182
182
|
try {
|
|
183
|
-
if (!(await fs.stat(workflowDir)).isDirectory()) throw compilerError("E001", `.kici/workflows/ is not a directory: ${workflowDir}`, { suggestion: "Run \"kici init\" to create the .kici/workflows/ directory" });
|
|
183
|
+
if (!(await fs$1.stat(workflowDir)).isDirectory()) throw compilerError("E001", `.kici/workflows/ is not a directory: ${workflowDir}`, { suggestion: "Run \"kici init\" to create the .kici/workflows/ directory" });
|
|
184
184
|
} catch (err) {
|
|
185
185
|
if (err.code === "ENOENT") throw compilerError("E001", `.kici/workflows/ directory not found: ${workflowDir}`, { suggestion: "Run \"kici init\" to create the .kici/workflows/ directory" });
|
|
186
186
|
throw err;
|
|
187
187
|
}
|
|
188
188
|
let files;
|
|
189
189
|
try {
|
|
190
|
-
files = (await fs.readdir(workflowDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => path.join(workflowDir, entry.name));
|
|
190
|
+
files = (await fs$1.readdir(workflowDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => path.join(workflowDir, entry.name));
|
|
191
191
|
} catch {
|
|
192
192
|
throw compilerError("E001", `Failed to read .kici/workflows/ directory: ${workflowDir}`, { suggestion: "Check directory permissions" });
|
|
193
193
|
}
|
|
@@ -213,7 +213,7 @@ async function discoverWorkflows(kiciDir) {
|
|
|
213
213
|
*/
|
|
214
214
|
async function executeWorkflowFile(filePath) {
|
|
215
215
|
try {
|
|
216
|
-
await fs.access(filePath);
|
|
216
|
+
await fs$1.access(filePath);
|
|
217
217
|
} catch {
|
|
218
218
|
throw compilerError("E001", `Failed to read workflow file: ${filePath}`, { suggestion: "Check file permissions" });
|
|
219
219
|
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* .d.ts generator for
|
|
2
|
+
* .d.ts generator for context secret type augmentation.
|
|
3
3
|
*
|
|
4
4
|
* Produces a TypeScript declaration file that augments @kici-dev/sdk's
|
|
5
|
-
* KnownSecretKeys and
|
|
5
|
+
* KnownSecretKeys and ContextSecrets interfaces, enabling compile-time
|
|
6
6
|
* autocomplete and type checking for `ctx.secrets.get()` and `ctx.secrets.expose()`
|
|
7
|
-
* key names per
|
|
7
|
+
* key names per context.
|
|
8
8
|
*/
|
|
9
|
-
export interface
|
|
9
|
+
export interface ContextMetadata {
|
|
10
10
|
name: string;
|
|
11
11
|
keys: string[];
|
|
12
12
|
}
|
|
13
13
|
interface GenerateSecretsDtsOptions {
|
|
14
|
-
|
|
14
|
+
contexts: ContextMetadata[];
|
|
15
15
|
endpoint: string;
|
|
16
16
|
generatedAt: Date;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Generate a .d.ts string from
|
|
19
|
+
* Generate a .d.ts string from context metadata.
|
|
20
20
|
*
|
|
21
|
-
* The output augments @kici-dev/sdk's KnownSecretKeys and
|
|
22
|
-
* interfaces, enabling compile-time autocomplete for secret keys per
|
|
21
|
+
* The output augments @kici-dev/sdk's KnownSecretKeys and ContextSecrets
|
|
22
|
+
* interfaces, enabling compile-time autocomplete for secret keys per context.
|
|
23
23
|
*
|
|
24
|
-
* @param options -
|
|
24
|
+
* @param options - Context metadata, endpoint URL, and generation timestamp
|
|
25
25
|
* @returns The .d.ts file content as a string
|
|
26
26
|
*/
|
|
27
27
|
export declare function generateSecretsDts(options: GenerateSecretsDtsOptions): string;
|
|
@@ -13,11 +13,11 @@ function formatProperty(name) {
|
|
|
13
13
|
return isValidIdentifier(name) ? name : `'${escapeQuotes(name)}'`;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Build a map of key -> list of
|
|
16
|
+
* Build a map of key -> list of context names that provide it.
|
|
17
17
|
*/
|
|
18
|
-
function buildKeySourceMap(
|
|
18
|
+
function buildKeySourceMap(contexts) {
|
|
19
19
|
const map = /* @__PURE__ */ new Map();
|
|
20
|
-
for (const env of
|
|
20
|
+
for (const env of contexts) for (const key of env.keys) {
|
|
21
21
|
const sources = map.get(key);
|
|
22
22
|
if (sources) sources.push(env.name);
|
|
23
23
|
else map.set(key, [env.name]);
|
|
@@ -25,16 +25,16 @@ function buildKeySourceMap(environments) {
|
|
|
25
25
|
return map;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Generate a .d.ts string from
|
|
28
|
+
* Generate a .d.ts string from context metadata.
|
|
29
29
|
*
|
|
30
|
-
* The output augments @kici-dev/sdk's KnownSecretKeys and
|
|
31
|
-
* interfaces, enabling compile-time autocomplete for secret keys per
|
|
30
|
+
* The output augments @kici-dev/sdk's KnownSecretKeys and ContextSecrets
|
|
31
|
+
* interfaces, enabling compile-time autocomplete for secret keys per context.
|
|
32
32
|
*
|
|
33
|
-
* @param options -
|
|
33
|
+
* @param options - Context metadata, endpoint URL, and generation timestamp
|
|
34
34
|
* @returns The .d.ts file content as a string
|
|
35
35
|
*/
|
|
36
36
|
function generateSecretsDts(options) {
|
|
37
|
-
const {
|
|
37
|
+
const { contexts, endpoint, generatedAt } = options;
|
|
38
38
|
const lines = [];
|
|
39
39
|
lines.push("// @generated by kici types -- DO NOT EDIT");
|
|
40
40
|
lines.push(`// Source: ${endpoint}`);
|
|
@@ -42,16 +42,16 @@ function generateSecretsDts(options) {
|
|
|
42
42
|
lines.push("// Run `kici types` to refresh");
|
|
43
43
|
lines.push("");
|
|
44
44
|
lines.push("declare module '@kici-dev/sdk' {");
|
|
45
|
-
const keySourceMap = buildKeySourceMap(
|
|
45
|
+
const keySourceMap = buildKeySourceMap(contexts);
|
|
46
46
|
lines.push(" interface KnownSecretKeys {");
|
|
47
47
|
for (const [key, sources] of keySourceMap) {
|
|
48
|
-
lines.push(` /** From
|
|
48
|
+
lines.push(` /** From context: ${sources.join(", ")} */`);
|
|
49
49
|
lines.push(` ${formatProperty(key)}: string;`);
|
|
50
50
|
}
|
|
51
51
|
lines.push(" }");
|
|
52
52
|
lines.push("");
|
|
53
|
-
lines.push(" interface
|
|
54
|
-
for (const env of
|
|
53
|
+
lines.push(" interface ContextSecrets {");
|
|
54
|
+
for (const env of contexts) if (env.keys.length === 0) lines.push(` ${formatProperty(env.name)}: never;`);
|
|
55
55
|
else {
|
|
56
56
|
const keyUnion = env.keys.map((k) => `'${escapeQuotes(k)}'`).join(" | ");
|
|
57
57
|
lines.push(` ${formatProperty(env.name)}: ${keyUnion};`);
|