@kici-dev/sdk 0.1.21 → 0.1.23
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/api-types.d.ts +54 -0
- package/dist/api-types.js +9 -1
- package/dist/approval.d.ts +25 -10
- package/dist/approval.js +18 -8
- package/dist/context.d.ts +22 -0
- package/dist/dynamic-group.d.ts +6 -4
- package/dist/dynamic-group.js +2 -12
- package/dist/fanout-context.d.ts +21 -0
- package/dist/fanout-context.js +2 -0
- package/dist/host-restart.d.ts +58 -0
- package/dist/host-restart.js +63 -0
- package/dist/idempotent.d.ts +32 -1
- package/dist/idempotent.js +26 -1
- package/dist/index.d.ts +13 -10
- package/dist/index.js +7 -5
- package/dist/job.js +3 -1
- package/dist/needs-context.d.ts +12 -5
- package/dist/needs-context.js +12 -4
- package/dist/rules/index.d.ts +1 -1
- package/dist/rules/index.js +2 -2
- package/dist/rules/rule.d.ts +20 -0
- package/dist/rules/rule.js +27 -1
- package/dist/rules/types.d.ts +9 -0
- package/dist/step.js +21 -1
- package/dist/triggers/dispatch-inputs.d.ts +32 -0
- package/dist/triggers/dispatch-inputs.js +21 -0
- package/dist/triggers/dispatch.js +5 -1
- package/dist/triggers/index.d.ts +3 -1
- package/dist/triggers/index.js +2 -1
- package/dist/triggers/types.d.ts +20 -0
- package/dist/types.d.ts +85 -17
- package/dist/workflow.js +1 -1
- package/package.json +3 -3
- package/sbom.spdx.json +24 -24
package/dist/job.js
CHANGED
|
@@ -35,12 +35,14 @@ function job(nameOrOptions, maybeOptions) {
|
|
|
35
35
|
if (options.runsOn !== void 0 && options.runsOnAll !== void 0) throw new Error(`job('${name}'): runsOn and runsOnAll are mutually exclusive`);
|
|
36
36
|
if (options.runsOn === void 0 && options.runsOnAll === void 0) throw new Error(`job('${name}'): one of runsOn or runsOnAll is required`);
|
|
37
37
|
if (options.onUnreachable !== void 0 && options.runsOnAll === void 0) console.warn(`[kici] job('${name}'): onUnreachable is ignored without runsOnAll`);
|
|
38
|
+
if (options.includeUninitialized !== void 0 && options.runsOnAll === void 0) console.warn(`[kici] job('${name}'): includeUninitialized is ignored without runsOnAll`);
|
|
38
39
|
return {
|
|
39
40
|
_tag: "Job",
|
|
40
41
|
name,
|
|
41
42
|
...options.runsOn !== void 0 && { runsOn: options.runsOn },
|
|
42
43
|
...options.runsOnAll !== void 0 && { runsOnAll: options.runsOnAll },
|
|
43
44
|
...options.onUnreachable !== void 0 && { onUnreachable: options.onUnreachable },
|
|
45
|
+
...options.includeUninitialized !== void 0 && { includeUninitialized: options.includeUninitialized },
|
|
44
46
|
...options.maxParallel !== void 0 && { maxParallel: options.maxParallel },
|
|
45
47
|
...options.failFast !== void 0 && { failFast: options.failFast },
|
|
46
48
|
steps,
|
|
@@ -66,7 +68,7 @@ function job(nameOrOptions, maybeOptions) {
|
|
|
66
68
|
resources: options.resources,
|
|
67
69
|
init: options.init,
|
|
68
70
|
...options.cache !== void 0 && { cache: options.cache },
|
|
69
|
-
...options.
|
|
71
|
+
...options.approval !== void 0 && { approval: options.approval },
|
|
70
72
|
result: createJobOutputProxy(name)
|
|
71
73
|
};
|
|
72
74
|
}
|
package/dist/needs-context.d.ts
CHANGED
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
import type { OutputProxy, DynamicJobNeed } from './types.js';
|
|
2
|
+
import type { ExecutionJobStatus } from '@kici-dev/engine';
|
|
2
3
|
/**
|
|
3
|
-
* Frozen snapshot of upstream outputs, captured once at first eval of
|
|
4
|
-
* result-aware dynamic generator and replayed unchanged on re-eval.
|
|
4
|
+
* Frozen snapshot of upstream outputs + statuses, captured once at first eval of
|
|
5
|
+
* a result-aware dynamic generator and replayed unchanged on re-eval.
|
|
5
6
|
*
|
|
6
7
|
* - `jobs` maps an upstream job name to its outputs record.
|
|
7
8
|
* - `groups` maps a dynamic group name to its ordered member job names.
|
|
9
|
+
* - `statuses` maps an upstream job name to its terminal status. Absent entries
|
|
10
|
+
* default to `success` (the only status that satisfies a default needs edge,
|
|
11
|
+
* so an upstream resolved into the snapshot is success unless told otherwise).
|
|
8
12
|
*/
|
|
9
13
|
export interface UpstreamSnapshot {
|
|
10
14
|
jobs: Record<string, Record<string, unknown>>;
|
|
11
15
|
groups: Record<string, string[]>;
|
|
16
|
+
statuses?: Record<string, ExecutionJobStatus>;
|
|
12
17
|
}
|
|
13
18
|
/** One entry in the array exposed for a `dynamicGroup(...)` need. */
|
|
14
19
|
export interface GroupNeedEntry {
|
|
15
20
|
name: string;
|
|
16
21
|
result: OutputProxy<any>;
|
|
22
|
+
status: ExecutionJobStatus;
|
|
17
23
|
}
|
|
18
|
-
/** A single-job need exposes `{ result }`; a group need exposes an ordered array. */
|
|
24
|
+
/** A single-job need exposes `{ result, status }`; a group need exposes an ordered array. */
|
|
19
25
|
export type NeedEntry = {
|
|
20
26
|
result: OutputProxy<any>;
|
|
27
|
+
status: ExecutionJobStatus;
|
|
21
28
|
} | GroupNeedEntry[];
|
|
22
29
|
/** The resolved `ctx.needs` map keyed by job name or group name. */
|
|
23
30
|
export type NeedsContext = Record<string, NeedEntry>;
|
|
24
31
|
/**
|
|
25
32
|
* Resolve declared needs against a frozen snapshot into the `ctx.needs` map.
|
|
26
33
|
*
|
|
27
|
-
* - A single static/named-job need resolves to `{ result: <proxy over jobs[name]
|
|
28
|
-
* - A `dynamicGroup(...)` need resolves to an ordered array of `{ name, result }`,
|
|
34
|
+
* - A single static/named-job need resolves to `{ result: <proxy over jobs[name]>, status }`.
|
|
35
|
+
* - A `dynamicGroup(...)` need resolves to an ordered array of `{ name, result, status }`,
|
|
29
36
|
* one entry per group member in the snapshot's deterministic eval order.
|
|
30
37
|
*/
|
|
31
38
|
export declare function buildNeedsContext(snapshot: UpstreamSnapshot, declaredNeeds: ReadonlyArray<DynamicJobNeed>): NeedsContext;
|
package/dist/needs-context.js
CHANGED
|
@@ -19,11 +19,15 @@ function needKey(need) {
|
|
|
19
19
|
key: need.name
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
/** Read an upstream's terminal status from the snapshot, defaulting to success. */
|
|
23
|
+
function statusFor(snapshot, name) {
|
|
24
|
+
return snapshot.statuses?.[name] ?? "success";
|
|
25
|
+
}
|
|
22
26
|
/**
|
|
23
27
|
* Resolve declared needs against a frozen snapshot into the `ctx.needs` map.
|
|
24
28
|
*
|
|
25
|
-
* - A single static/named-job need resolves to `{ result: <proxy over jobs[name]
|
|
26
|
-
* - A `dynamicGroup(...)` need resolves to an ordered array of `{ name, result }`,
|
|
29
|
+
* - A single static/named-job need resolves to `{ result: <proxy over jobs[name]>, status }`.
|
|
30
|
+
* - A `dynamicGroup(...)` need resolves to an ordered array of `{ name, result, status }`,
|
|
27
31
|
* one entry per group member in the snapshot's deterministic eval order.
|
|
28
32
|
*/
|
|
29
33
|
function buildNeedsContext(snapshot, declaredNeeds) {
|
|
@@ -32,9 +36,13 @@ function buildNeedsContext(snapshot, declaredNeeds) {
|
|
|
32
36
|
const { kind, key } = needKey(need);
|
|
33
37
|
if (kind === "group") out[key] = (snapshot.groups[key] ?? []).map((name) => ({
|
|
34
38
|
name,
|
|
35
|
-
result: createSnapshotOutputProxy(name, snapshot.jobs[name])
|
|
39
|
+
result: createSnapshotOutputProxy(name, snapshot.jobs[name]),
|
|
40
|
+
status: statusFor(snapshot, name)
|
|
36
41
|
}));
|
|
37
|
-
else out[key] = {
|
|
42
|
+
else out[key] = {
|
|
43
|
+
result: createSnapshotOutputProxy(key, snapshot.jobs[key]),
|
|
44
|
+
status: statusFor(snapshot, key)
|
|
45
|
+
};
|
|
38
46
|
}
|
|
39
47
|
return out;
|
|
40
48
|
}
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { rule, skip } from './rule.js';
|
|
1
|
+
export { rule, skip, onlyOnFirstHost, onlyOnLastHost, onlyOnFanoutIndex } from './rule.js';
|
|
2
2
|
export { evaluateRules, type RuleEvaluationResult } from './evaluator.js';
|
|
3
3
|
export type { Rule, RuleCheckFn, RuleContext, RuleResult, EventPayload } from './types.js';
|
|
4
4
|
export { isEventType } from '../events/event-payloads.js';
|
package/dist/rules/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../chunk-BTugEXQM.js";
|
|
2
|
-
import { rule, skip } from "./rule.js";
|
|
2
|
+
import { onlyOnFanoutIndex, onlyOnFirstHost, onlyOnLastHost, rule, skip } from "./rule.js";
|
|
3
3
|
import { evaluateRules } from "./evaluator.js";
|
|
4
4
|
import { isEventType } from "../events/event-payloads.js";
|
|
5
|
-
export { evaluateRules, isEventType, rule, skip };
|
|
5
|
+
export { evaluateRules, isEventType, onlyOnFanoutIndex, onlyOnFirstHost, onlyOnLastHost, rule, skip };
|
package/dist/rules/rule.d.ts
CHANGED
|
@@ -31,4 +31,24 @@ export declare function rule(label: string, check: RuleCheckFn): Rule;
|
|
|
31
31
|
* });
|
|
32
32
|
*/
|
|
33
33
|
export declare function skip(label: string, check: RuleCheckFn): Rule;
|
|
34
|
+
/**
|
|
35
|
+
* Run a step only on the first fan-out child (the lowest-`agentId` host, or the
|
|
36
|
+
* first matrix variant). KiCI's `run_once`-on-the-first-host primitive.
|
|
37
|
+
*
|
|
38
|
+
* A non-fan-out job is treated as a single implicit child at index 0, so a step
|
|
39
|
+
* gated this way runs normally there (there is exactly one host, which is first).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* step('enable sync mode', async (ctx) => { ... }, { rules: [onlyOnFirstHost()] })
|
|
43
|
+
*/
|
|
44
|
+
export declare function onlyOnFirstHost(): Rule;
|
|
45
|
+
/**
|
|
46
|
+
* Run a step only on the last fan-out child. Runs normally when not fanned out.
|
|
47
|
+
*/
|
|
48
|
+
export declare function onlyOnLastHost(): Rule;
|
|
49
|
+
/**
|
|
50
|
+
* Run a step only on the fan-out child at index `n`. A non-fan-out job is the
|
|
51
|
+
* implicit child at index 0, so `onlyOnFanoutIndex(0)` runs normally there.
|
|
52
|
+
*/
|
|
53
|
+
export declare function onlyOnFanoutIndex(n: number): Rule;
|
|
34
54
|
//# sourceMappingURL=rule.d.ts.map
|
package/dist/rules/rule.js
CHANGED
|
@@ -31,7 +31,33 @@ function skip(label, check) {
|
|
|
31
31
|
check: async (ctx) => !await check(ctx)
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Run a step only on the first fan-out child (the lowest-`agentId` host, or the
|
|
36
|
+
* first matrix variant). KiCI's `run_once`-on-the-first-host primitive.
|
|
37
|
+
*
|
|
38
|
+
* A non-fan-out job is treated as a single implicit child at index 0, so a step
|
|
39
|
+
* gated this way runs normally there (there is exactly one host, which is first).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* step('enable sync mode', async (ctx) => { ... }, { rules: [onlyOnFirstHost()] })
|
|
43
|
+
*/
|
|
44
|
+
function onlyOnFirstHost() {
|
|
45
|
+
return rule("fanout: first host only", (ctx) => ctx.fanout === void 0 || ctx.fanout.first);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run a step only on the last fan-out child. Runs normally when not fanned out.
|
|
49
|
+
*/
|
|
50
|
+
function onlyOnLastHost() {
|
|
51
|
+
return rule("fanout: last host only", (ctx) => ctx.fanout === void 0 || ctx.fanout.last);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run a step only on the fan-out child at index `n`. A non-fan-out job is the
|
|
55
|
+
* implicit child at index 0, so `onlyOnFanoutIndex(0)` runs normally there.
|
|
56
|
+
*/
|
|
57
|
+
function onlyOnFanoutIndex(n) {
|
|
58
|
+
return rule(`fanout: index ${n} only`, (ctx) => (ctx.fanout?.index ?? 0) === n);
|
|
59
|
+
}
|
|
34
60
|
//#endregion
|
|
35
|
-
export { rule, skip };
|
|
61
|
+
export { onlyOnFanoutIndex, onlyOnFirstHost, onlyOnLastHost, rule, skip };
|
|
36
62
|
|
|
37
63
|
//# sourceMappingURL=rule.js.map
|
package/dist/rules/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { $ as Shell } from 'zx';
|
|
2
2
|
import type { EventPayload } from '../events/event-payloads.js';
|
|
3
|
+
import type { FanoutPosition } from '../fanout-context.js';
|
|
3
4
|
export type { EventPayload } from '../events/event-payloads.js';
|
|
4
5
|
/**
|
|
5
6
|
* Context passed to rule check functions.
|
|
@@ -12,6 +13,14 @@ export interface RuleContext {
|
|
|
12
13
|
changedFiles: string[];
|
|
13
14
|
/** Environment variables */
|
|
14
15
|
env: Record<string, string | undefined>;
|
|
16
|
+
/** Operator-supplied, validated + coerced workflow-dispatch inputs. Empty when none declared. */
|
|
17
|
+
dispatchInputs: Readonly<Record<string, string | number | boolean | null>>;
|
|
18
|
+
/**
|
|
19
|
+
* Position of this child within its fan-out (a `runsOnAll` host or a matrix
|
|
20
|
+
* combination); undefined on a non-fan-out job. Read by the run-once rule
|
|
21
|
+
* helpers (`onlyOnFirstHost` / `onlyOnLastHost` / `onlyOnFanoutIndex`).
|
|
22
|
+
*/
|
|
23
|
+
fanout?: FanoutPosition;
|
|
15
24
|
/** zx shell executor for running commands */
|
|
16
25
|
$: typeof Shell;
|
|
17
26
|
}
|
package/dist/step.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import "./chunk-BTugEXQM.js";
|
|
2
|
+
import { normalizeApproval } from "./approval.js";
|
|
2
3
|
import { createStepOutputProxy } from "./outputs.js";
|
|
3
4
|
//#region src/step.ts
|
|
4
5
|
/**
|
|
6
|
+
* Fill retry defaults and expand the `retry: N` shorthand into a
|
|
7
|
+
* {@link NormalizedRetry}. `retryIf` is carried through unchanged (it is
|
|
8
|
+
* execution-only and never serialized).
|
|
9
|
+
*/
|
|
10
|
+
function normalizeRetry(retry) {
|
|
11
|
+
if (retry === void 0) return void 0;
|
|
12
|
+
const cfg = typeof retry === "number" ? { maxAttempts: retry } : retry;
|
|
13
|
+
return {
|
|
14
|
+
maxAttempts: cfg.maxAttempts,
|
|
15
|
+
delayMs: cfg.delayMs ?? 1e3,
|
|
16
|
+
backoff: cfg.backoff ?? "exponential",
|
|
17
|
+
maxDelayMs: cfg.maxDelayMs ?? 3e4,
|
|
18
|
+
...cfg.retryIf && { retryIf: cfg.retryIf }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
5
22
|
* Capture the call-site source location of step() using the V8 stack trace API.
|
|
6
23
|
* Uses Error.captureStackTrace with the `step` function as the constructor argument
|
|
7
24
|
* so the stack starts from step()'s caller.
|
|
@@ -59,6 +76,8 @@ function step(nameOrRunOrOptions, runOrOptions) {
|
|
|
59
76
|
options = nameOrRunOrOptions;
|
|
60
77
|
}
|
|
61
78
|
if (options.check && !options.summarize) throw new Error("summarize is required when check is set");
|
|
79
|
+
if (options.approval !== void 0 && normalizeApproval(options.approval).when === "drift" && !options.check) throw new Error("approval.when \"drift\" requires a check facet");
|
|
80
|
+
const retry = normalizeRetry(options.retry);
|
|
62
81
|
return {
|
|
63
82
|
_tag: "Step",
|
|
64
83
|
name,
|
|
@@ -70,11 +89,12 @@ function step(nameOrRunOrOptions, runOrOptions) {
|
|
|
70
89
|
...options.whenInSync !== void 0 && { whenInSync: options.whenInSync },
|
|
71
90
|
continueOnError: options.continueOnError,
|
|
72
91
|
timeout: options.timeout,
|
|
92
|
+
...retry !== void 0 && { retry },
|
|
73
93
|
...options.cache !== void 0 && { cache: options.cache },
|
|
74
94
|
rules: options.rules,
|
|
75
95
|
onCancel: options.onCancel,
|
|
76
96
|
cleanup: options.cleanup,
|
|
77
|
-
...options.
|
|
97
|
+
...options.approval !== void 0 && { approval: options.approval },
|
|
78
98
|
_sourceLocation,
|
|
79
99
|
result: createStepOutputProxy(name)
|
|
80
100
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { DispatchInputsMap } from './types.js';
|
|
3
|
+
/** The per-key inferred output type of a declared dispatch-inputs map. */
|
|
4
|
+
export type InferDispatchInputs<TMap extends DispatchInputsMap> = {
|
|
5
|
+
[K in keyof TMap]: z.infer<TMap[K]>;
|
|
6
|
+
};
|
|
7
|
+
/** A context that may carry validated, coerced dispatch inputs. */
|
|
8
|
+
interface DispatchInputsCarrier {
|
|
9
|
+
dispatchInputs?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A branded handle returned by `defineDispatchInputs`. It is accepted directly
|
|
13
|
+
* by `dispatch({ inputs })` and exposes typed `.from(ctx)` / `.fromRule(ctx)`
|
|
14
|
+
* readers over `ctx.dispatchInputs`, typed per declared key.
|
|
15
|
+
*/
|
|
16
|
+
export interface DefinedDispatchInputs<TMap extends DispatchInputsMap> {
|
|
17
|
+
readonly __kiciDispatchInputs: true;
|
|
18
|
+
readonly map: TMap;
|
|
19
|
+
/** Read the validated, coerced dispatch inputs from a step context, typed per declared key. */
|
|
20
|
+
from(ctx: DispatchInputsCarrier): InferDispatchInputs<TMap>;
|
|
21
|
+
/** Same, from a rule context. */
|
|
22
|
+
fromRule(ctx: DispatchInputsCarrier): InferDispatchInputs<TMap>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Declare a typed workflow-dispatch inputs map once and get back a handle that
|
|
26
|
+
* both `dispatch({ inputs })` accepts and exposes a typed `.from(ctx)` reader —
|
|
27
|
+
* no double type annotation. Type safety comes via Standard-Schema inference
|
|
28
|
+
* (Zod 4 implements `~standard`), without a builder-generics refactor.
|
|
29
|
+
*/
|
|
30
|
+
export declare function defineDispatchInputs<TMap extends DispatchInputsMap>(map: TMap): DefinedDispatchInputs<TMap>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=dispatch-inputs.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
|
+
//#region src/triggers/dispatch-inputs.ts
|
|
3
|
+
/**
|
|
4
|
+
* Declare a typed workflow-dispatch inputs map once and get back a handle that
|
|
5
|
+
* both `dispatch({ inputs })` accepts and exposes a typed `.from(ctx)` reader —
|
|
6
|
+
* no double type annotation. Type safety comes via Standard-Schema inference
|
|
7
|
+
* (Zod 4 implements `~standard`), without a builder-generics refactor.
|
|
8
|
+
*/
|
|
9
|
+
function defineDispatchInputs(map) {
|
|
10
|
+
const read = (ctx) => ctx.dispatchInputs ?? {};
|
|
11
|
+
return Object.freeze({
|
|
12
|
+
__kiciDispatchInputs: true,
|
|
13
|
+
map: Object.freeze({ ...map }),
|
|
14
|
+
from: read,
|
|
15
|
+
fromRule: read
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { defineDispatchInputs };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=dispatch-inputs.js.map
|
|
@@ -13,11 +13,15 @@ import { asArray, toBranchPattern } from "./types.js";
|
|
|
13
13
|
*/
|
|
14
14
|
function dispatch(config) {
|
|
15
15
|
const repos = config?.repos ? asArray(config.repos).map(toBranchPattern) : [];
|
|
16
|
+
const rawInputs = config?.inputs;
|
|
17
|
+
let inputsMap;
|
|
18
|
+
if (rawInputs) inputsMap = "__kiciDispatchInputs" in rawInputs ? rawInputs.map : rawInputs;
|
|
16
19
|
const result = {
|
|
17
20
|
_tag: "DispatchTrigger",
|
|
18
21
|
types: Object.freeze(config?.types ? [...config.types] : []),
|
|
19
22
|
repos: Object.freeze([...repos]),
|
|
20
|
-
...config?.description !== void 0 && { description: config.description }
|
|
23
|
+
...config?.description !== void 0 && { description: config.description },
|
|
24
|
+
...inputsMap && { inputs: Object.freeze({ ...inputsMap }) }
|
|
21
25
|
};
|
|
22
26
|
return Object.freeze(result);
|
|
23
27
|
}
|
package/dist/triggers/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export { jobComplete } from './job-complete.js';
|
|
|
23
23
|
export { genericWebhook } from './generic-webhook.js';
|
|
24
24
|
export { schedule } from './schedule.js';
|
|
25
25
|
export { lifecycle } from './lifecycle.js';
|
|
26
|
-
export
|
|
26
|
+
export { defineDispatchInputs } from './dispatch-inputs.js';
|
|
27
|
+
export type { DefinedDispatchInputs, InferDispatchInputs } from './dispatch-inputs.js';
|
|
28
|
+
export type { DispatchInputsMap, BranchPattern, BodyMatchPattern, PrEvent, PushEvent, PrTriggerConfig, PushTriggerConfig, TagTriggerConfig, CommentTriggerConfig, ReviewTriggerConfig, ReviewCommentTriggerConfig, ReleaseTriggerConfig, DispatchTriggerConfig, CreateTriggerConfig, DeleteTriggerConfig, StatusTriggerConfig, WorkflowRunTriggerConfig, ForkTriggerConfig, StarTriggerConfig, WatchTriggerConfig, WebhookTriggerConfig, TriggerConfig, PrConfigInput, PushConfigInput, TagConfigInput, CommentConfigInput, CommentAction, CommentSource, ReviewConfigInput, ReviewAction, ReviewState, ReviewCommentConfigInput, ReviewCommentAction, ReleaseConfigInput, ReleaseAction, DispatchConfigInput, CreateConfigInput, DeleteConfigInput, RefType, StatusConfigInput, StatusState, WorkflowRunConfigInput, WorkflowRunAction, ForkConfigInput, StarConfigInput, StarAction, WatchConfigInput, WatchAction, WebhookConfigInput, KiciEventConfigInput, KiciEventTriggerConfig, WorkflowCompleteConfigInput, WorkflowCompleteTriggerConfig, WorkflowCompleteStatus, JobCompleteConfigInput, JobCompleteTriggerConfig, JobCompleteStatus, GenericWebhookConfigInput, GenericWebhookTriggerConfig, GenericWebhookAuthMethod, GenericWebhookHmacAuth, GenericWebhookApiKeyAuth, GenericWebhookAuth, ScheduleConfigInput, ScheduleTriggerConfig, LifecycleEvent, LifecycleConfigInput, LifecycleTriggerConfig, } from './types.js';
|
|
27
29
|
export { DEFAULT_PR_EVENTS, toBranchPattern } from './types.js';
|
|
28
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/triggers/index.js
CHANGED
|
@@ -22,4 +22,5 @@ import { jobComplete } from "./job-complete.js";
|
|
|
22
22
|
import { genericWebhook } from "./generic-webhook.js";
|
|
23
23
|
import { schedule } from "./schedule.js";
|
|
24
24
|
import { lifecycle } from "./lifecycle.js";
|
|
25
|
-
|
|
25
|
+
import { defineDispatchInputs } from "./dispatch-inputs.js";
|
|
26
|
+
export { DEFAULT_PR_EVENTS, comment, create, defineDispatchInputs, del as delete, dispatch, fork, genericWebhook, jobComplete, kiciEvent, lifecycle, pr, push, release, review, reviewComment, schedule, star, status, tag, toBranchPattern, watch, webhook, workflowComplete, workflowRun };
|
package/dist/triggers/types.d.ts
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
* Trigger types and interfaces for pr() and push() trigger helpers.
|
|
3
3
|
* Supports both glob patterns and regex patterns for branch/path matching.
|
|
4
4
|
*/
|
|
5
|
+
import type { z } from 'zod';
|
|
6
|
+
/**
|
|
7
|
+
* A declared map of typed workflow-dispatch inputs: `{ name: ZodSchema }`.
|
|
8
|
+
* Each schema must fall within the closed dispatch-input subset (extracted by
|
|
9
|
+
* the compiler) — z.string/number/boolean/enum/literal plus
|
|
10
|
+
* .optional/.nullable/.default/.min/.max/.regex/.int.
|
|
11
|
+
*/
|
|
12
|
+
export type DispatchInputsMap = Record<string, z.ZodType>;
|
|
5
13
|
/**
|
|
6
14
|
* Branch pattern - discriminated union supporting both glob and regex patterns.
|
|
7
15
|
* Glob patterns use micromatch syntax, regex patterns use standard JS regex.
|
|
@@ -165,6 +173,8 @@ export interface DispatchTriggerConfig {
|
|
|
165
173
|
readonly types: readonly string[];
|
|
166
174
|
readonly repos: readonly BranchPattern[];
|
|
167
175
|
readonly description?: string;
|
|
176
|
+
/** Declared, typed workflow-dispatch inputs (frozen `{ name: ZodSchema }`). */
|
|
177
|
+
readonly inputs?: DispatchInputsMap;
|
|
168
178
|
}
|
|
169
179
|
/**
|
|
170
180
|
* Input configuration for dispatch() factory function.
|
|
@@ -173,6 +183,16 @@ export interface DispatchConfigInput {
|
|
|
173
183
|
readonly types?: string[];
|
|
174
184
|
readonly repos?: string | RegExp | (string | RegExp)[];
|
|
175
185
|
readonly description?: string;
|
|
186
|
+
/**
|
|
187
|
+
* Typed workflow-dispatch inputs. Accepts a bare `{ name: ZodSchema }` map or
|
|
188
|
+
* a `defineDispatchInputs(...)` branded handle (which also exposes a typed
|
|
189
|
+
* `.from(ctx)` accessor). The compiler validates each schema against the
|
|
190
|
+
* closed dispatch-input subset.
|
|
191
|
+
*/
|
|
192
|
+
readonly inputs?: DispatchInputsMap | {
|
|
193
|
+
readonly __kiciDispatchInputs: true;
|
|
194
|
+
readonly map: DispatchInputsMap;
|
|
195
|
+
};
|
|
176
196
|
}
|
|
177
197
|
export type RefType = 'branch' | 'tag';
|
|
178
198
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { z } from 'zod';
|
|
2
2
|
import type { $ as Shell } from 'zx';
|
|
3
|
-
import type {
|
|
3
|
+
import type { RetryBackoff } from '@kici-dev/core';
|
|
4
|
+
import type { ResourceRequest, RunsOnAllInput, OnUnreachableMode, NeedsWhen, ExecutionJobStatus } from '@kici-dev/engine';
|
|
4
5
|
import type { StepContext, Logger } from './context.js';
|
|
5
6
|
import type { TriggerConfig } from './triggers/types.js';
|
|
6
7
|
import type { Rule } from './rules/types.js';
|
|
@@ -9,8 +10,15 @@ import type { HookInput } from './hooks/types.js';
|
|
|
9
10
|
import type { KiciApi } from './api-types.js';
|
|
10
11
|
import type { DynamicGroupRef } from './dynamic-group.js';
|
|
11
12
|
import type { EventPayload } from './events/event-payloads.js';
|
|
12
|
-
import type {
|
|
13
|
-
export type { ResourceRequest, ResourceSpec, RunsOnAllInput, OnUnreachableMode, } from '@kici-dev/engine';
|
|
13
|
+
import type { ApprovalConfig } from './approval.js';
|
|
14
|
+
export type { ResourceRequest, ResourceSpec, RunsOnAllInput, OnUnreachableMode, NeedsWhen, } from '@kici-dev/engine';
|
|
15
|
+
/**
|
|
16
|
+
* Author-facing run condition for a `needs` edge: keyword sugar
|
|
17
|
+
* (`'on-success'` | `'always'` | `'on-skip'` | `'on-failure'`) or a raw set of
|
|
18
|
+
* upstream terminal statuses. Resolved to a normalized status-set at compile
|
|
19
|
+
* time; the downstream runs when the upstream's terminal status is a member.
|
|
20
|
+
*/
|
|
21
|
+
export type NeedsWhenInput = NeedsWhen | ExecutionJobStatus[];
|
|
14
22
|
/** Source location captured at a step() call site. */
|
|
15
23
|
export interface SourceLocation {
|
|
16
24
|
readonly file: string;
|
|
@@ -57,6 +65,8 @@ export interface Step<TResult = void> {
|
|
|
57
65
|
readonly continueOnError?: boolean;
|
|
58
66
|
/** Step-level timeout in milliseconds. Overrides the agent's default (30 minutes). */
|
|
59
67
|
readonly timeout?: number;
|
|
68
|
+
/** Normalized retry policy (defaults filled, shorthand expanded). `retryIf` is execution-only. */
|
|
69
|
+
readonly retry?: NormalizedRetry;
|
|
60
70
|
/** Declarative cache: restored before this step, saved after on key miss. */
|
|
61
71
|
readonly cache?: import('./cache-types.js').CacheInput;
|
|
62
72
|
/** Step-level conditional rules (evaluated agent-side). */
|
|
@@ -65,8 +75,8 @@ export interface Step<TResult = void> {
|
|
|
65
75
|
readonly onCancel?: HookInput;
|
|
66
76
|
/** Always runs after step (success, failure, or cancel). */
|
|
67
77
|
readonly cleanup?: HookInput;
|
|
68
|
-
/** Pause for a manual human approval before this step
|
|
69
|
-
readonly
|
|
78
|
+
/** Pause for a manual human approval (before this step, or on drift). */
|
|
79
|
+
readonly approval?: ApprovalConfig;
|
|
70
80
|
/** Internal: source location captured at step() call site. Not part of public API. */
|
|
71
81
|
readonly _sourceLocation?: SourceLocation;
|
|
72
82
|
/**
|
|
@@ -88,6 +98,33 @@ export type BareStepFn<TResult = void> = (ctx: StepContext) => Promise<TResult>;
|
|
|
88
98
|
export type StepInput = Step<any> | BareStepFn<any>;
|
|
89
99
|
/** Options for step() factory - simple form (just async function) */
|
|
90
100
|
export type StepRunFn = (ctx: StepContext) => Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Author-supplied retry policy for a step. A thrown attempt is re-run while
|
|
103
|
+
* attempts remain and `retryIf(err)` is true.
|
|
104
|
+
*/
|
|
105
|
+
export interface RetryConfig {
|
|
106
|
+
/** Total attempts incl. the first; `maxAttempts: 3` ⇒ up to 3 runs. Must be >= 1. */
|
|
107
|
+
maxAttempts: number;
|
|
108
|
+
/** Base delay between attempts, ms. Default 1000. */
|
|
109
|
+
delayMs?: number;
|
|
110
|
+
/** Delay growth. Default 'exponential'. */
|
|
111
|
+
backoff?: RetryBackoff;
|
|
112
|
+
/** Cap for exponential backoff, ms. Default 30000. */
|
|
113
|
+
maxDelayMs?: number;
|
|
114
|
+
/** Retry only when this returns true for the thrown error. Default: retry on any throw. */
|
|
115
|
+
retryIf?: (err: unknown) => boolean;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Retry policy with defaults filled in, carried on the built {@link Step}.
|
|
119
|
+
* `retryIf` rides along on the in-memory step (it is never serialized).
|
|
120
|
+
*/
|
|
121
|
+
export interface NormalizedRetry {
|
|
122
|
+
maxAttempts: number;
|
|
123
|
+
delayMs: number;
|
|
124
|
+
backoff: RetryBackoff;
|
|
125
|
+
maxDelayMs: number;
|
|
126
|
+
retryIf?: (err: unknown) => boolean;
|
|
127
|
+
}
|
|
91
128
|
/**
|
|
92
129
|
* Facets shared by both the plain and the check variant of {@link StepOptions}.
|
|
93
130
|
* These compose unchanged whether or not a step declares a `check` facet.
|
|
@@ -99,6 +136,8 @@ export interface StepOptionsBase {
|
|
|
99
136
|
continueOnError?: boolean;
|
|
100
137
|
/** Step-level timeout in milliseconds. Overrides the agent's default (30 minutes). */
|
|
101
138
|
timeout?: number;
|
|
139
|
+
/** Retry policy: re-run a thrown step with backoff. `retry: N` ⇒ `{ maxAttempts: N }`. */
|
|
140
|
+
retry?: number | RetryConfig;
|
|
102
141
|
/** Declarative cache: restored before this step, saved after on key miss. */
|
|
103
142
|
cache?: import('./cache-types.js').CacheInput;
|
|
104
143
|
/** Step-level conditional rules (evaluated agent-side). */
|
|
@@ -107,8 +146,8 @@ export interface StepOptionsBase {
|
|
|
107
146
|
onCancel?: HookInput;
|
|
108
147
|
/** Always runs after step (success, failure, or cancel). */
|
|
109
148
|
cleanup?: HookInput;
|
|
110
|
-
/** Pause for a manual human approval before this step
|
|
111
|
-
|
|
149
|
+
/** Pause for a manual human approval (before this step, or on drift). */
|
|
150
|
+
approval?: ApprovalConfig;
|
|
112
151
|
}
|
|
113
152
|
/**
|
|
114
153
|
* Plain step options: `run` takes only the context — the existing, fully
|
|
@@ -249,10 +288,10 @@ declare const DYNAMIC_JOB_NEEDS_TAG: unique symbol;
|
|
|
249
288
|
*/
|
|
250
289
|
export type DynamicJobNeed = Job | string | DynamicGroupRef | {
|
|
251
290
|
name: string;
|
|
252
|
-
|
|
291
|
+
when?: NeedsWhenInput;
|
|
253
292
|
} | {
|
|
254
293
|
group: string;
|
|
255
|
-
|
|
294
|
+
when?: NeedsWhenInput;
|
|
256
295
|
};
|
|
257
296
|
/**
|
|
258
297
|
* Options-object form of {@link dynamicJob}: a result-aware generator that is
|
|
@@ -354,7 +393,21 @@ export type InitConfig = InitItem | InitItem[] | 'auto' | false;
|
|
|
354
393
|
export interface RunsOnSelector {
|
|
355
394
|
labels: string | RegExp | (string | RegExp)[];
|
|
356
395
|
exclude?: string | RegExp | (string | RegExp)[];
|
|
396
|
+
/**
|
|
397
|
+
* How to pick the single agent when more than one matches.
|
|
398
|
+
*
|
|
399
|
+
* - `'deterministic'` (default) — sort matching candidates by `agentId` and
|
|
400
|
+
* pick the lowest, so a run-once-on-one-host job (a migration, a dump) lands
|
|
401
|
+
* on the same host across re-runs. Can hot-spot equivalent agents.
|
|
402
|
+
* - `'any'` — pick any available agent (load spread). Opt out of determinism
|
|
403
|
+
* for jobs that don't need a stable host.
|
|
404
|
+
*
|
|
405
|
+
* The string / array shorthand `runsOn` forms imply `'deterministic'` too.
|
|
406
|
+
*/
|
|
407
|
+
pick?: RunsOnPick;
|
|
357
408
|
}
|
|
409
|
+
/** Single-agent selection policy when multiple agents match a `runsOn` selector. */
|
|
410
|
+
export type RunsOnPick = 'deterministic' | 'any';
|
|
358
411
|
/**
|
|
359
412
|
* Polymorphic runsOn type: string shorthand, array shorthand, or full selector object.
|
|
360
413
|
* - `'kici:os:linux'` — single label shorthand (targets any linux agent)
|
|
@@ -384,6 +437,14 @@ export interface Job {
|
|
|
384
437
|
readonly runsOnAll?: RunsOnAllInput;
|
|
385
438
|
/** Failure policy for unreachable durable hosts when using `runsOnAll`. */
|
|
386
439
|
readonly onUnreachable?: OnUnreachableMode;
|
|
440
|
+
/**
|
|
441
|
+
* Widen a `runsOnAll` fan-out to declared-but-un-agented hosts: each matching
|
|
442
|
+
* host that has no live agent gets a temporary init-runner brought up over SSH
|
|
443
|
+
* and its steps run on it (fresh-box bootstrap convergence). Already-live hosts
|
|
444
|
+
* run on their own agent. Default `false` (only live hosts run). Only
|
|
445
|
+
* meaningful alongside `runsOnAll`.
|
|
446
|
+
*/
|
|
447
|
+
readonly includeUninitialized?: boolean;
|
|
387
448
|
/** Fan-out concurrency width (sliding window; `1` = serial). Applies to matrix and `runsOnAll`. */
|
|
388
449
|
readonly maxParallel?: number;
|
|
389
450
|
/** Halt the fan-out on first child failure, skipping the remainder. Default `false`. */
|
|
@@ -391,10 +452,10 @@ export interface Job {
|
|
|
391
452
|
readonly steps: readonly StepInput[];
|
|
392
453
|
readonly needs?: ReadonlyArray<Job | string | DynamicGroupRef | {
|
|
393
454
|
name: string;
|
|
394
|
-
|
|
455
|
+
when?: NeedsWhenInput;
|
|
395
456
|
} | {
|
|
396
457
|
group: string;
|
|
397
|
-
|
|
458
|
+
when?: NeedsWhenInput;
|
|
398
459
|
}>;
|
|
399
460
|
/** Rules for conditional execution */
|
|
400
461
|
readonly rules?: Rule[];
|
|
@@ -457,7 +518,7 @@ export interface Job {
|
|
|
457
518
|
/** Declarative cache: restored before steps, saved after the job on key miss. */
|
|
458
519
|
readonly cache?: import('./cache-types.js').CacheInput;
|
|
459
520
|
/** Pause for a manual human approval before this job dispatches. */
|
|
460
|
-
readonly
|
|
521
|
+
readonly approval?: ApprovalConfig;
|
|
461
522
|
/**
|
|
462
523
|
* Type-safe proxy for accessing this job's outputs.
|
|
463
524
|
* For multi-step jobs: jobRef.result.stepName.field
|
|
@@ -484,6 +545,13 @@ export interface JobOptions {
|
|
|
484
545
|
* pinned child and waits. Only meaningful alongside `runsOnAll`.
|
|
485
546
|
*/
|
|
486
547
|
onUnreachable?: OnUnreachableMode;
|
|
548
|
+
/**
|
|
549
|
+
* Widen a `runsOnAll` fan-out to declared-but-un-agented hosts: a matching host
|
|
550
|
+
* with no live agent gets a temporary init-runner brought up over SSH and its
|
|
551
|
+
* steps run on it (fresh-box bootstrap convergence); already-live hosts run on
|
|
552
|
+
* their own agent. Default `false`. Only meaningful alongside `runsOnAll`.
|
|
553
|
+
*/
|
|
554
|
+
includeUninitialized?: boolean;
|
|
487
555
|
/**
|
|
488
556
|
* Fan-out concurrency width: the maximum number of fan-out children (matrix
|
|
489
557
|
* combinations or `runsOnAll` hosts) that run at once. A sliding window —
|
|
@@ -510,10 +578,10 @@ export interface JobOptions {
|
|
|
510
578
|
run?: (ctx: StepContext) => Promise<any>;
|
|
511
579
|
needs?: Array<Job | string | DynamicGroupRef | {
|
|
512
580
|
name: string;
|
|
513
|
-
|
|
581
|
+
when?: NeedsWhenInput;
|
|
514
582
|
} | {
|
|
515
583
|
group: string;
|
|
516
|
-
|
|
584
|
+
when?: NeedsWhenInput;
|
|
517
585
|
}>;
|
|
518
586
|
/** Rules that must pass for job to execute */
|
|
519
587
|
rules?: Rule[];
|
|
@@ -591,7 +659,7 @@ export interface JobOptions {
|
|
|
591
659
|
/** Declarative cache: restored before steps, saved after the job on key miss. */
|
|
592
660
|
cache?: import('./cache-types.js').CacheInput;
|
|
593
661
|
/** Pause for a manual human approval before this job dispatches. */
|
|
594
|
-
|
|
662
|
+
approval?: ApprovalConfig;
|
|
595
663
|
}
|
|
596
664
|
/**
|
|
597
665
|
* Private npm registry declaration. Tells the agent to authenticate against
|
|
@@ -670,7 +738,7 @@ export interface Workflow {
|
|
|
670
738
|
readonly max?: number;
|
|
671
739
|
};
|
|
672
740
|
/** Pause for a manual human approval before the whole workflow dispatches. */
|
|
673
|
-
readonly
|
|
741
|
+
readonly approval?: ApprovalConfig;
|
|
674
742
|
}
|
|
675
743
|
/** Options for workflow() factory */
|
|
676
744
|
export interface WorkflowOptions {
|
|
@@ -723,7 +791,7 @@ export interface WorkflowOptions {
|
|
|
723
791
|
max?: number;
|
|
724
792
|
};
|
|
725
793
|
/** Pause for a manual human approval before the whole workflow dispatches. */
|
|
726
|
-
|
|
794
|
+
approval?: ApprovalConfig;
|
|
727
795
|
}
|
|
728
796
|
export type { TriggerConfig, PrTriggerConfig, PushTriggerConfig } from './triggers/types.js';
|
|
729
797
|
export type { Rule, RuleContext, RuleCheckFn, RuleResult } from './rules/types.js';
|
package/dist/workflow.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kici-dev/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "TypeScript SDK for defining KiCI workflows. Import into `.kici/workflows/*.ts` to declare workflows, jobs, steps, triggers, rules, and matrix configurations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ci",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"micromatch": "^4.0.8",
|
|
50
50
|
"zod": "^4.4.3",
|
|
51
51
|
"zx": "^8.8.5",
|
|
52
|
-
"@kici-dev/core": "0.1.
|
|
53
|
-
"@kici-dev/engine": "0.1.
|
|
52
|
+
"@kici-dev/core": "0.1.23",
|
|
53
|
+
"@kici-dev/engine": "0.1.23"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/micromatch": "^4.0.10"
|