@kici-dev/sdk 0.1.27 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/api-types.d.ts +28 -0
  2. package/dist/api-types.js +3 -1
  3. package/dist/approval.d.ts +3 -8
  4. package/dist/approval.js +9 -0
  5. package/dist/artifacts-types.d.ts +45 -0
  6. package/dist/artifacts-types.js +3 -0
  7. package/dist/context.d.ts +65 -15
  8. package/dist/events/define-event.d.ts +11 -3
  9. package/dist/events/define-event.js +14 -4
  10. package/dist/events/emit-typing.test-d.d.ts +2 -0
  11. package/dist/events/emit-typing.test-d.js +36 -0
  12. package/dist/events/event-payloads.d.ts +4 -0
  13. package/dist/events/index.d.ts +1 -1
  14. package/dist/events/index.js +2 -2
  15. package/dist/fleet/agent-version-converge.d.ts +23 -0
  16. package/dist/fleet/agent-version-converge.js +58 -0
  17. package/dist/index.d.ts +9 -3
  18. package/dist/index.js +6 -2
  19. package/dist/job-outputs.test-d.d.ts +2 -0
  20. package/dist/job-outputs.test-d.js +164 -0
  21. package/dist/job.d.ts +71 -9
  22. package/dist/job.js +14 -0
  23. package/dist/matrix/expand.d.ts +1 -1
  24. package/dist/matrix/expand.js +2 -2
  25. package/dist/needs-context.d.ts +13 -6
  26. package/dist/outputs.d.ts +19 -4
  27. package/dist/outputs.js +21 -7
  28. package/dist/parallel.d.ts +1 -1
  29. package/dist/parallel.js +1 -1
  30. package/dist/provenance-types.d.ts +3 -3
  31. package/dist/rules/context.d.ts +33 -0
  32. package/dist/rules/context.js +51 -0
  33. package/dist/rules/evaluator.d.ts +10 -0
  34. package/dist/rules/evaluator.js +9 -1
  35. package/dist/rules/index.d.ts +2 -0
  36. package/dist/rules/index.js +2 -1
  37. package/dist/rules/types.d.ts +11 -1
  38. package/dist/step.d.ts +6 -6
  39. package/dist/step.js +6 -3
  40. package/dist/testing/index.d.ts +2 -0
  41. package/dist/testing/index.js +3 -0
  42. package/dist/testing/step-context.d.ts +56 -0
  43. package/dist/testing/step-context.js +259 -0
  44. package/dist/triggers/index.d.ts +2 -1
  45. package/dist/triggers/index.js +2 -1
  46. package/dist/triggers/types.d.ts +23 -1
  47. package/dist/triggers/workflows-failed-batch.d.ts +20 -0
  48. package/dist/triggers/workflows-failed-batch.js +25 -0
  49. package/dist/types.d.ts +142 -9
  50. package/dist/validation/dag.js +11 -3
  51. package/package.json +10 -5
  52. package/sbom.spdx.json +192 -192
@@ -9,8 +9,18 @@ export type { EventPayload } from '../events/event-payloads.js';
9
9
  export interface RuleContext {
10
10
  /** The triggering event payload */
11
11
  event: EventPayload;
12
- /** List of files changed in this event (e.g., PR diff) */
12
+ /**
13
+ * Files changed in this event (PR diff / push diff). Available on push and
14
+ * pull_request events (the agent computes the diff from the checkout — no
15
+ * `paths:` trigger required). Accessing this throws
16
+ * `ChangedFilesUnavailableError` when the diff is not available
17
+ * (`changedFilesStatus !== 'fetched'`) — e.g. a schedule/tag/manual event.
18
+ * Guard with `changedFilesStatus` first when a rule runs on such events:
19
+ * `if (ctx.changedFilesStatus !== 'fetched') return true`.
20
+ */
13
21
  changedFiles: string[];
22
+ /** Availability of `changedFiles` (see `changedFiles`). */
23
+ changedFilesStatus: import('@kici-dev/engine').ChangedFilesStatus;
14
24
  /** Environment variables */
15
25
  env: Record<string, string | undefined>;
16
26
  /** Operator-supplied, validated + coerced workflow-dispatch inputs. Empty when none declared. */
package/dist/step.d.ts CHANGED
@@ -8,7 +8,7 @@ import type { Step, StepOptions, StepOptionsWithCheck, StepRunFn } from './types
8
8
  * await ctx.$`echo hello`;
9
9
  * });
10
10
  */
11
- export declare function step<TResult = void>(run: (ctx: import('./context.js').StepContext) => Promise<TResult>): Step<TResult>;
11
+ export declare function step<TResult = void>(run: (ctx: import('./context.js').StepContext) => Promise<TResult>): Step<TResult, ''>;
12
12
  /**
13
13
  * Create an id-less step with full options.
14
14
  * The compiler assigns a counter-based ID at lock file generation.
@@ -21,7 +21,7 @@ export declare function step<TResult = void>(run: (ctx: import('./context.js').S
21
21
  * timeout: 60000,
22
22
  * });
23
23
  */
24
- export declare function step<TResult = void>(options: StepOptions<TResult>): Step<TResult>;
24
+ export declare function step<TResult = void>(options: StepOptions<TResult>): Step<TResult, ''>;
25
25
  /**
26
26
  * Create a named step with just a run function (no outputs).
27
27
  *
@@ -30,7 +30,7 @@ export declare function step<TResult = void>(options: StepOptions<TResult>): Ste
30
30
  * await ctx.$`git checkout`;
31
31
  * });
32
32
  */
33
- export declare function step(name: string, run: StepRunFn): Step<void>;
33
+ export declare function step<TName extends string>(name: TName, run: StepRunFn): Step<void, TName>;
34
34
  /**
35
35
  * Create a named step with full options and generic return type.
36
36
  *
@@ -46,7 +46,7 @@ export declare function step(name: string, run: StepRunFn): Step<void>;
46
46
  * }
47
47
  * });
48
48
  */
49
- export declare function step<TResult = void>(name: string, options: StepOptions<TResult>): Step<TResult>;
49
+ export declare function step<TResult = void, TName extends string = string>(name: TName, options: StepOptions<TResult>): Step<TResult, TName>;
50
50
  /**
51
51
  * Create a named idempotent step with a check facet.
52
52
  *
@@ -62,9 +62,9 @@ export declare function step<TResult = void>(name: string, options: StepOptions<
62
62
  * whenInSync: async () => ({ reloaded: false }),
63
63
  * });
64
64
  */
65
- export declare function step<TResult = void, TDrift = unknown>(name: string, options: StepOptionsWithCheck<TResult, TDrift>): Step<TResult>;
65
+ export declare function step<TResult = void, TDrift = unknown, TName extends string = string>(name: TName, options: StepOptionsWithCheck<TResult, TDrift>): Step<TResult, TName>;
66
66
  /**
67
67
  * Create an id-less idempotent step with a check facet.
68
68
  */
69
- export declare function step<TResult = void, TDrift = unknown>(options: StepOptionsWithCheck<TResult, TDrift>): Step<TResult>;
69
+ export declare function step<TResult = void, TDrift = unknown>(options: StepOptionsWithCheck<TResult, TDrift>): Step<TResult, ''>;
70
70
  //# sourceMappingURL=step.d.ts.map
package/dist/step.js CHANGED
@@ -40,6 +40,8 @@ function captureCallSite() {
40
40
  if (match) {
41
41
  let file = match[1];
42
42
  if (file.startsWith("file://")) file = file.slice(7);
43
+ const queryIndex = file.indexOf("?");
44
+ if (queryIndex !== -1) file = file.slice(0, queryIndex);
43
45
  return {
44
46
  file,
45
47
  line: parseInt(match[2], 10),
@@ -78,7 +80,7 @@ function step(nameOrRunOrOptions, runOrOptions) {
78
80
  if (options.check && !options.summarize) throw new Error("summarize is required when check is set");
79
81
  if (options.approval !== void 0 && normalizeApproval(options.approval).when === "drift" && !options.check) throw new Error("approval.when \"drift\" requires a check facet");
80
82
  const retry = normalizeRetry(options.retry);
81
- return {
83
+ const stepObj = {
82
84
  _tag: "Step",
83
85
  name,
84
86
  outputs: options.outputs,
@@ -95,9 +97,10 @@ function step(nameOrRunOrOptions, runOrOptions) {
95
97
  onCancel: options.onCancel,
96
98
  cleanup: options.cleanup,
97
99
  ...options.approval !== void 0 && { approval: options.approval },
98
- _sourceLocation,
99
- result: createStepOutputProxy(name)
100
+ _sourceLocation
100
101
  };
102
+ stepObj.result = createStepOutputProxy(stepObj);
103
+ return stepObj;
101
104
  }
102
105
  //#endregion
103
106
  export { step };
@@ -0,0 +1,2 @@
1
+ export { createTestStepContext, type TestStepContextOptions, type TestStepContext, type RecordedEmit, } from './step-context.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { createTestStepContext } from "./step-context.js";
3
+ export { createTestStepContext };
@@ -0,0 +1,56 @@
1
+ import { type TempScope } from '@kici-dev/core/tmp';
2
+ import type { StepContext, Logger } from '../context.js';
3
+ import type { EventEmitOptions } from '../events/types.js';
4
+ /** A single recorded `ctx.emit(...)` invocation, for assertion in tests. */
5
+ export interface RecordedEmit {
6
+ eventName: string;
7
+ payload?: Record<string, unknown>;
8
+ options?: EventEmitOptions;
9
+ }
10
+ /**
11
+ * Options for {@link createTestStepContext}. Every field is optional — call it
12
+ * with no arguments for a fully-defaulted context. Convenience seed fields
13
+ * (`repoRoot`, `secrets`) sit alongside direct `StepContext` member overrides
14
+ * (everything else), which are shallow-merged on top of the defaults.
15
+ */
16
+ export interface TestStepContextOptions extends Partial<Omit<StepContext, 'secrets' | 'log'>> {
17
+ /** Working directory `ctx.$` is pinned to. Defaults to `process.cwd()`. */
18
+ repoRoot?: string;
19
+ /**
20
+ * Seed secrets for `ctx.secrets`. `flat` keys are global; `contexts` values are
21
+ * flattened into the flat map (last-write-wins), matching the local runner.
22
+ */
23
+ secrets?: {
24
+ flat?: Record<string, string>;
25
+ contexts?: Record<string, Record<string, string>>;
26
+ };
27
+ /** Logger override. Defaults to a console-backed logger. */
28
+ log?: Logger;
29
+ }
30
+ /** Handle returned by {@link createTestStepContext}. */
31
+ export interface TestStepContext {
32
+ /** The built step context to pass into your step function. */
33
+ ctx: StepContext;
34
+ /** Every `ctx.emit(...)` call, in order — assert against this in tests. */
35
+ emitCalls: ReadonlyArray<RecordedEmit>;
36
+ /**
37
+ * The job-scoped temp allocator backing `ctx.mktemp`/`ctx.mktempFile`. Call
38
+ * `tempScope.disposeAll()` to drain every still-live temp dir/file manually;
39
+ * `dispose()` also drains it.
40
+ */
41
+ tempScope: TempScope;
42
+ /** Tear down secrets state + the per-context tmpdir + temp scope. Call in `afterEach`. */
43
+ dispose: () => Promise<void>;
44
+ }
45
+ /**
46
+ * Build a real {@link StepContext} for unit-testing a step function in vitest.
47
+ *
48
+ * `ctx.$` is real zx pinned to `repoRoot`, `ctx.secrets` is real
49
+ * (`createStepSecrets` seeded from `options.secrets`), and `ctx.emit` records
50
+ * each call on `emitCalls` while returning the local delivery receipt.
51
+ * Orchestrator-backed APIs (`ctx.kici.*`, `ctx.attestProvenance`,
52
+ * `ctx.artifacts.*`) reject, and `ctx.cache` no-ops — override any of them via
53
+ * the options object.
54
+ */
55
+ export declare function createTestStepContext(options?: TestStepContextOptions): TestStepContext;
56
+ //# sourceMappingURL=step-context.d.ts.map
@@ -0,0 +1,259 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { resolveJobOutputs, resolveStepOutputs } from "../outputs.js";
3
+ import { createStepSecrets } from "../secrets.js";
4
+ import { isEventDefinition } from "../events/define-event.js";
5
+ import { initZx } from "@kici-dev/core";
6
+ import { $ } from "zx";
7
+ import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { dirname, join } from "node:path";
10
+ import { createTempScope } from "@kici-dev/core/tmp";
11
+ //#region src/testing/step-context.ts
12
+ initZx();
13
+ const DEFAULT_WORKFLOW = { name: "test-workflow" };
14
+ const DEFAULT_JOB = {
15
+ name: "test-job",
16
+ runsOn: "local"
17
+ };
18
+ const NOOP_DELIVERY_ID = "local-test-noop";
19
+ function createConsoleLogger() {
20
+ return {
21
+ info: (message, ...args) => console.log(message, ...args),
22
+ warn: (message, ...args) => console.warn(`⚠ ${message}`, ...args),
23
+ error: (message, ...args) => console.error(`✗ ${message}`, ...args),
24
+ debug: (message, ...args) => {
25
+ if (process.env.KICI_DEBUG === "true") console.debug(`[debug] ${message}`, ...args);
26
+ }
27
+ };
28
+ }
29
+ /**
30
+ * Wire a real secrets surface backed by an on-demand tmpdir file host.
31
+ *
32
+ * The tmpdir is allocated lazily on first `mountFile`/`exposeFile` so steps that
33
+ * never mount pay nothing, and the `process.on('exit')` cleanup handler is
34
+ * registered lazily too (to avoid Node's MaxListeners warning at scale).
35
+ */
36
+ function createTestSecrets(mergedFlat, env) {
37
+ let tmpdirPath = null;
38
+ const exposedEnvVars = /* @__PURE__ */ new Set();
39
+ let mountCounter = 0;
40
+ let exitHandlerRegistered = false;
41
+ const onProcessExit = () => {
42
+ for (const envVar of exposedEnvVars) delete env[envVar];
43
+ exposedEnvVars.clear();
44
+ if (tmpdirPath !== null) {
45
+ try {
46
+ rmSync(tmpdirPath, {
47
+ recursive: true,
48
+ force: true
49
+ });
50
+ } catch {}
51
+ tmpdirPath = null;
52
+ }
53
+ };
54
+ const handle = createStepSecrets(mergedFlat, env, void 0, {
55
+ host: {
56
+ async writeMountedFile(args) {
57
+ if (tmpdirPath === null) tmpdirPath = mkdtempSync(join(tmpdir(), "kici-secret-files-"));
58
+ if (!exitHandlerRegistered) {
59
+ process.once("exit", onProcessExit);
60
+ exitHandlerRegistered = true;
61
+ }
62
+ mountCounter += 1;
63
+ const filename = args.name ?? `secret-${mountCounter}`;
64
+ const filePath = join(tmpdirPath, filename);
65
+ writeFileSync(filePath, args.content);
66
+ chmodSync(filePath, args.mode);
67
+ return filePath;
68
+ },
69
+ trackExposedEnv(envVar) {
70
+ exposedEnvVars.add(envVar);
71
+ }
72
+ },
73
+ cleanup: async () => {
74
+ if (exitHandlerRegistered) {
75
+ process.off("exit", onProcessExit);
76
+ exitHandlerRegistered = false;
77
+ }
78
+ onProcessExit();
79
+ }
80
+ });
81
+ return {
82
+ secrets: handle.secrets,
83
+ dispose: handle.dispose
84
+ };
85
+ }
86
+ /**
87
+ * Sanitize a raw identifier into a valid temp label: lowercase, every
88
+ * non-`[a-z0-9-]` char to `-`, falling back to `'step'` when the result is
89
+ * empty. Applied to both the caller-supplied label and the default step id so
90
+ * `ctx.mktemp(...)` never rejects a friendly-but-irregular label.
91
+ */
92
+ function sanitizeTempLabel(raw) {
93
+ const cleaned = raw.toLowerCase().replace(/[^a-z0-9-]/g, "-");
94
+ return cleaned.length > 0 ? cleaned : "step";
95
+ }
96
+ /**
97
+ * Wire a job-scoped temp allocator for the test step context.
98
+ *
99
+ * `mktemp`/`mktempFile` delegate to a {@link createTempScope} instance and track
100
+ * each allocated root so an exit backstop can reclaim it. The `process.once('exit')`
101
+ * handler is registered lazily on first allocation (to avoid Node's MaxListeners
102
+ * warning at scale) and synchronously removes any still-live temp paths — mirroring
103
+ * the secrets-tmpdir exit cleanup. `dispose()` drains the scope and removes the
104
+ * handler; the scope is exposed for manual drain in tests.
105
+ */
106
+ function createTestTempScope(defaultLabel) {
107
+ const scope = createTempScope();
108
+ const liveRoots = [];
109
+ let exitHandlerRegistered = false;
110
+ const onProcessExit = () => {
111
+ for (const root of liveRoots) try {
112
+ rmSync(root, {
113
+ recursive: true,
114
+ force: true
115
+ });
116
+ } catch {}
117
+ liveRoots.length = 0;
118
+ };
119
+ const ensureExitHandler = () => {
120
+ if (!exitHandlerRegistered) {
121
+ process.once("exit", onProcessExit);
122
+ exitHandlerRegistered = true;
123
+ }
124
+ };
125
+ return {
126
+ async mktemp(label) {
127
+ ensureExitHandler();
128
+ const handle = await scope.mktemp(sanitizeTempLabel(label ?? defaultLabel));
129
+ liveRoots.push(handle.path);
130
+ return handle;
131
+ },
132
+ async mktempFile(label, opts) {
133
+ ensureExitHandler();
134
+ const handle = await scope.mktempFile(sanitizeTempLabel(label ?? defaultLabel), opts);
135
+ liveRoots.push(dirname(handle.path));
136
+ return handle;
137
+ },
138
+ scope,
139
+ async dispose() {
140
+ if (exitHandlerRegistered) {
141
+ process.off("exit", onProcessExit);
142
+ exitHandlerRegistered = false;
143
+ }
144
+ await scope.disposeAll();
145
+ liveRoots.length = 0;
146
+ }
147
+ };
148
+ }
149
+ /**
150
+ * Build a real {@link StepContext} for unit-testing a step function in vitest.
151
+ *
152
+ * `ctx.$` is real zx pinned to `repoRoot`, `ctx.secrets` is real
153
+ * (`createStepSecrets` seeded from `options.secrets`), and `ctx.emit` records
154
+ * each call on `emitCalls` while returning the local delivery receipt.
155
+ * Orchestrator-backed APIs (`ctx.kici.*`, `ctx.attestProvenance`,
156
+ * `ctx.artifacts.*`) reject, and `ctx.cache` no-ops — override any of them via
157
+ * the options object.
158
+ */
159
+ function createTestStepContext(options = {}) {
160
+ const { repoRoot = process.cwd(), secrets: seed, log, ...overrides } = options;
161
+ const flat = seed?.flat ?? {};
162
+ const namespaced = seed?.contexts ?? {};
163
+ const mergedFlat = { ...flat };
164
+ for (const contextSecrets of Object.values(namespaced)) Object.assign(mergedFlat, contextSecrets);
165
+ const env = overrides.env ?? { ...process.env };
166
+ const processEnvRestores = /* @__PURE__ */ new Map();
167
+ const recordProcessEnvOriginal = (key) => {
168
+ if (!processEnvRestores.has(key)) processEnvRestores.set(key, process.env[key]);
169
+ };
170
+ const scoped$ = $({ cwd: repoRoot });
171
+ const { secrets, dispose: disposeSecrets } = createTestSecrets(mergedFlat, env);
172
+ const temp = createTestTempScope((overrides.job ?? DEFAULT_JOB).name);
173
+ const emitCalls = [];
174
+ const emit = (async (nameOrDefinition, payload, opts) => {
175
+ const eventName = isEventDefinition(nameOrDefinition) ? nameOrDefinition.name : nameOrDefinition;
176
+ emitCalls.push({
177
+ eventName,
178
+ payload,
179
+ options: opts
180
+ });
181
+ return { deliveryId: NOOP_DELIVERY_ID };
182
+ });
183
+ const ctx = {
184
+ $: scoped$,
185
+ log: log ?? createConsoleLogger(),
186
+ signal: overrides.signal ?? new AbortController().signal,
187
+ env,
188
+ setEnv: (key, value) => {
189
+ env[key] = value;
190
+ recordProcessEnvOriginal(key);
191
+ process.env[key] = value;
192
+ },
193
+ addPath: (dir) => {
194
+ const updated = `${dir}:${env.PATH ?? process.env.PATH ?? ""}`;
195
+ env.PATH = updated;
196
+ recordProcessEnvOriginal("PATH");
197
+ process.env.PATH = updated;
198
+ },
199
+ inputs: {},
200
+ dispatchInputs: {},
201
+ workflow: DEFAULT_WORKFLOW,
202
+ job: DEFAULT_JOB,
203
+ isTestRun: false,
204
+ secrets,
205
+ emit,
206
+ outputsOf: (ref) => resolveStepOutputs(ref),
207
+ jobOutputs: (ref) => resolveJobOutputs(ref),
208
+ setSecretOutput: () => {},
209
+ mktemp: (label) => temp.mktemp(label),
210
+ mktempFile: (label, opts) => temp.mktempFile(label, opts),
211
+ kici: {
212
+ infrastructure: { list: () => Promise.resolve({
213
+ scalers: [],
214
+ agents: []
215
+ }) },
216
+ inventory: {
217
+ query: () => Promise.resolve([]),
218
+ get: () => Promise.resolve(null)
219
+ },
220
+ oidc: { token: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.oidc.token() is not available in a test step context")) },
221
+ host: { requestReboot: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.host.requestReboot() is not available in a test step context")) },
222
+ bootstrap: {
223
+ ensureInitRunner: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.ensureInitRunner() is not available in a test step context")),
224
+ preBootSend: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.preBootSend() is not available in a test step context")),
225
+ agentVersionStatus: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.agentVersionStatus() is not available in a test step context")),
226
+ restageAgent: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.restageAgent() is not available in a test step context"))
227
+ }
228
+ },
229
+ cache: {
230
+ restore: async () => ({ hit: false }),
231
+ save: async () => {}
232
+ },
233
+ artifacts: {
234
+ upload: () => Promise.reject(/* @__PURE__ */ new Error("ctx.artifacts.upload() is not available in a test step context")),
235
+ download: () => Promise.reject(/* @__PURE__ */ new Error("ctx.artifacts.download() is not available in a test step context"))
236
+ },
237
+ attestProvenance: () => Promise.reject(/* @__PURE__ */ new Error("ctx.attestProvenance() is not available in a test step context")),
238
+ ...overrides,
239
+ env,
240
+ $: overrides.$ ?? scoped$
241
+ };
242
+ const dispose = async () => {
243
+ await disposeSecrets();
244
+ await temp.dispose();
245
+ for (const [key, original] of processEnvRestores) if (original === void 0) delete process.env[key];
246
+ else process.env[key] = original;
247
+ processEnvRestores.clear();
248
+ };
249
+ return {
250
+ ctx,
251
+ emitCalls,
252
+ tempScope: temp.scope,
253
+ dispose
254
+ };
255
+ }
256
+ //#endregion
257
+ export { createTestStepContext };
258
+
259
+ //# sourceMappingURL=step-context.js.map
@@ -19,12 +19,13 @@ export { watch } from './watch.js';
19
19
  export { webhook } from './webhook.js';
20
20
  export { kiciEvent } from './kici-event.js';
21
21
  export { workflowComplete } from './workflow-complete.js';
22
+ export { workflowsFailedBatch } from './workflows-failed-batch.js';
22
23
  export { jobComplete } from './job-complete.js';
23
24
  export { genericWebhook } from './generic-webhook.js';
24
25
  export { schedule } from './schedule.js';
25
26
  export { lifecycle } from './lifecycle.js';
26
27
  export { defineDispatchInputs } from './dispatch-inputs.js';
27
28
  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';
29
+ 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, WorkflowsFailedBatchConfigInput, WorkflowsFailedBatchTriggerConfig, JobCompleteConfigInput, JobCompleteTriggerConfig, JobCompleteStatus, GenericWebhookConfigInput, GenericWebhookTriggerConfig, GenericWebhookAuthMethod, GenericWebhookHmacAuth, GenericWebhookApiKeyAuth, GenericWebhookAuth, ScheduleConfigInput, ScheduleTriggerConfig, LifecycleEvent, LifecycleConfigInput, LifecycleTriggerConfig, } from './types.js';
29
30
  export { DEFAULT_PR_EVENTS, toBranchPattern } from './types.js';
30
31
  //# sourceMappingURL=index.d.ts.map
@@ -18,9 +18,10 @@ import { watch } from "./watch.js";
18
18
  import { webhook } from "./webhook.js";
19
19
  import { kiciEvent } from "./kici-event.js";
20
20
  import { workflowComplete } from "./workflow-complete.js";
21
+ import { workflowsFailedBatch } from "./workflows-failed-batch.js";
21
22
  import { jobComplete } from "./job-complete.js";
22
23
  import { genericWebhook } from "./generic-webhook.js";
23
24
  import { schedule } from "./schedule.js";
24
25
  import { lifecycle } from "./lifecycle.js";
25
26
  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 };
27
+ 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, workflowsFailedBatch };
@@ -371,6 +371,28 @@ export interface WorkflowCompleteTriggerConfig {
371
371
  readonly source?: string;
372
372
  readonly description?: string;
373
373
  }
374
+ /**
375
+ * Input configuration for workflowsFailedBatch() factory function.
376
+ * Accumulate failed workflow completions over a window, notify once.
377
+ */
378
+ export interface WorkflowsFailedBatchConfigInput {
379
+ /** Accumulation window in milliseconds; the window opens on the first failure. */
380
+ readonly accumulateFor: number;
381
+ readonly name?: string;
382
+ readonly source?: string;
383
+ readonly description?: string;
384
+ }
385
+ /**
386
+ * Configuration for a workflows-failed-batch trigger.
387
+ */
388
+ export interface WorkflowsFailedBatchTriggerConfig {
389
+ readonly _tag: 'WorkflowsFailedBatchTrigger';
390
+ /** Accumulation window in milliseconds; the window opens on the first failure. */
391
+ readonly accumulateFor: number;
392
+ readonly name?: string;
393
+ readonly source?: string;
394
+ readonly description?: string;
395
+ }
374
396
  /**
375
397
  * Valid job completion statuses.
376
398
  */
@@ -525,7 +547,7 @@ export interface WebhookConfigInput {
525
547
  /**
526
548
  * Union type for all trigger configurations (21 types).
527
549
  */
528
- export type TriggerConfig = PrTriggerConfig | PushTriggerConfig | TagTriggerConfig | CommentTriggerConfig | ReviewTriggerConfig | ReviewCommentTriggerConfig | ReleaseTriggerConfig | DispatchTriggerConfig | CreateTriggerConfig | DeleteTriggerConfig | StatusTriggerConfig | WorkflowRunTriggerConfig | ForkTriggerConfig | StarTriggerConfig | WatchTriggerConfig | WebhookTriggerConfig | KiciEventTriggerConfig | WorkflowCompleteTriggerConfig | JobCompleteTriggerConfig | GenericWebhookTriggerConfig | ScheduleTriggerConfig | LifecycleTriggerConfig;
550
+ export type TriggerConfig = PrTriggerConfig | PushTriggerConfig | TagTriggerConfig | CommentTriggerConfig | ReviewTriggerConfig | ReviewCommentTriggerConfig | ReleaseTriggerConfig | DispatchTriggerConfig | CreateTriggerConfig | DeleteTriggerConfig | StatusTriggerConfig | WorkflowRunTriggerConfig | ForkTriggerConfig | StarTriggerConfig | WatchTriggerConfig | WebhookTriggerConfig | KiciEventTriggerConfig | WorkflowCompleteTriggerConfig | WorkflowsFailedBatchTriggerConfig | JobCompleteTriggerConfig | GenericWebhookTriggerConfig | ScheduleTriggerConfig | LifecycleTriggerConfig;
529
551
  /**
530
552
  * Input configuration for pr() factory function.
531
553
  * All fields optional - sensible defaults applied.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Workflows-failed-batch trigger helper.
3
+ *
4
+ * Accumulates failed workflow completions over a time window and fires the
5
+ * subscribing global workflow once per window with the batched run list, so a
6
+ * mass incident notifies a single time instead of once per failed run.
7
+ */
8
+ import type { WorkflowsFailedBatchConfigInput, WorkflowsFailedBatchTriggerConfig } from './types.js';
9
+ /**
10
+ * Create a workflows-failed-batch trigger configuration.
11
+ *
12
+ * @example
13
+ * // Notify once for every burst of failures within a 10s window
14
+ * workflowsFailedBatch({ accumulateFor: 10000 })
15
+ *
16
+ * // Scope the batch to a named workflow and a specific source repo
17
+ * workflowsFailedBatch({ accumulateFor: 10000, name: 'CI', source: 'org/repo' })
18
+ */
19
+ export declare function workflowsFailedBatch(config: WorkflowsFailedBatchConfigInput): WorkflowsFailedBatchTriggerConfig;
20
+ //# sourceMappingURL=workflows-failed-batch.d.ts.map
@@ -0,0 +1,25 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ //#region src/triggers/workflows-failed-batch.ts
3
+ /**
4
+ * Create a workflows-failed-batch trigger configuration.
5
+ *
6
+ * @example
7
+ * // Notify once for every burst of failures within a 10s window
8
+ * workflowsFailedBatch({ accumulateFor: 10000 })
9
+ *
10
+ * // Scope the batch to a named workflow and a specific source repo
11
+ * workflowsFailedBatch({ accumulateFor: 10000, name: 'CI', source: 'org/repo' })
12
+ */
13
+ function workflowsFailedBatch(config) {
14
+ return Object.freeze({
15
+ _tag: "WorkflowsFailedBatchTrigger",
16
+ accumulateFor: config.accumulateFor,
17
+ ...config.name !== void 0 && { name: config.name },
18
+ ...config.source !== void 0 && { source: config.source },
19
+ ...config.description !== void 0 && { description: config.description }
20
+ });
21
+ }
22
+ //#endregion
23
+ export { workflowsFailedBatch };
24
+
25
+ //# sourceMappingURL=workflows-failed-batch.js.map