@kici-dev/compiler 0.4.0 → 0.5.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.
- package/dist/cli.js +1 -1
- package/dist/commands/compile.js +1 -13
- package/dist/commands/preview.js +1 -8
- package/dist/commands/types.js +1 -2
- package/dist/errors/formatter.d.ts +2 -4
- package/dist/errors/formatter.js +1 -3
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +2 -2
- package/dist/generators/secrets-dts.d.ts +0 -1
- package/dist/generators/secrets-dts.js +1 -2
- package/dist/llm-context/llms-architecture.txt +27 -13
- package/dist/llm-context/llms-cli.txt +26 -6
- package/dist/llm-context/llms-features.txt +272 -91
- package/dist/llm-context/llms-full.txt +649 -235
- package/dist/llm-context/llms-getting-started.txt +20 -20
- package/dist/llm-context/llms-patterns.txt +10 -6
- package/dist/llm-context/llms-providers.txt +4 -6
- package/dist/llm-context/llms-sdk-runtime.txt +37 -36
- package/dist/llm-context/llms-sdk.txt +253 -57
- package/dist/llm-context/llms.txt +6 -6
- package/dist/local-plane/plane-manager.js +2 -2
- package/dist/lockfile/generator.js +137 -42
- package/dist/lockfile/index.d.ts +0 -2
- package/dist/lockfile/index.js +1 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/dry-run.d.ts +1 -2
- package/dist/test-runner/dry-run.js +1 -18
- package/dist/types.d.ts +32 -8
- package/dist/types.js +7 -1
- package/dist/validation/validator.js +40 -0
- package/package.json +6 -6
- package/sbom.spdx.json +126 -121
- package/dist/lockfile/purity-analyzer.d.ts +0 -25
- package/dist/lockfile/purity-analyzer.js +0 -204
- package/dist/lockfile/purity-diagnostics.d.ts +0 -31
- package/dist/lockfile/purity-diagnostics.js +0 -52
|
@@ -18,22 +18,24 @@ function workflow(name: string, options: WorkflowOptions): Workflow;
|
|
|
18
18
|
|
|
19
19
|
**Parameters:**
|
|
20
20
|
|
|
21
|
-
| Parameter | Type | Required | Description
|
|
22
|
-
| --------------------- | ---------------------------------------------------------------------- | -------- |
|
|
23
|
-
| `name` | `string` | yes | Unique workflow name
|
|
24
|
-
| `options.jobs` | `JobOrFactory[]` | yes | Static jobs and/or dynamic job generators
|
|
25
|
-
| `options.on` | `Trigger \| Trigger[]` | no | When the workflow should trigger
|
|
26
|
-
| `options.rules` | `Rule[]` | no | Conditions that must pass for execution
|
|
27
|
-
| `options.
|
|
28
|
-
| `options.
|
|
29
|
-
| `options.
|
|
30
|
-
| `options.
|
|
31
|
-
| `options.
|
|
32
|
-
| `options.
|
|
33
|
-
| `options.
|
|
34
|
-
| `options.
|
|
35
|
-
| `options.
|
|
36
|
-
| `options.
|
|
21
|
+
| Parameter | Type | Required | Description |
|
|
22
|
+
| --------------------- | ---------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `name` | `string` | yes | Unique workflow name |
|
|
24
|
+
| `options.jobs` | `JobOrFactory[]` | yes | Static jobs and/or dynamic job generators |
|
|
25
|
+
| `options.on` | `Trigger \| Trigger[]` | no | When the workflow should trigger |
|
|
26
|
+
| `options.rules` | `Rule[]` | no | Conditions that must pass for execution |
|
|
27
|
+
| `options.filter` | `FilterFn` | no | Pre-dispatch predicate deciding whether the workflow applies to the event's source repo. A `false` result suppresses the workflow's jobs -- none is dispatched and none is reported as skipped. See [Global workflows](https://docs.kici.dev/user/global-workflows/). |
|
|
28
|
+
| `options.description` | `string` | no | Human-readable description |
|
|
29
|
+
| `options.hashFiles` | `string[]` | no | Extra repo-relative paths or globs mixed into the workflow content hash. Changes invalidate the source cache. |
|
|
30
|
+
| `options.registries` | `Registry[]` | no | Private npm registries the agent authenticates against before `npm install`. Each `tokenSecret` uses qualified `<context>:<secret>` syntax. |
|
|
31
|
+
| `options.installEnv` | `string[]` | no | Qualified `<context>:<secret>` refs projected as env vars onto the install subprocess (used with a customer-committed `.kici/.npmrc`). |
|
|
32
|
+
| `options.onCancel` | `HookInput` | no | Runs when the workflow is cancelled |
|
|
33
|
+
| `options.cleanup` | `HookInput` | no | Always runs after the workflow (success, failure, or cancel) |
|
|
34
|
+
| `options.onSuccess` | `HookInput` | no | Runs on workflow success |
|
|
35
|
+
| `options.onFailure` | `HookInput` | no | Runs on workflow failure |
|
|
36
|
+
| `options.concurrency` | `{ group: (ctx) => string; cancelInProgress?: boolean; max?: number }` | no | Workflow-scoped concurrency. See [Concurrency](https://docs.kici.dev/user/concurrency/). |
|
|
37
|
+
| `options.timeout` | `number` | no | Whole-run wall-clock timeout in milliseconds across all jobs. On breach the orchestrator cancels the run and marks it timed out. See [Timeouts](https://docs.kici.dev/user/sdk/core/#timeouts). |
|
|
38
|
+
| `options.approval` | `ApprovalConfig` | no | Pause for a manual human approval before the whole workflow dispatches. See [Approval gates](https://docs.kici.dev/user/approvals/). |
|
|
37
39
|
|
|
38
40
|
**Returns:** `Workflow` -- an immutable workflow definition.
|
|
39
41
|
|
|
@@ -59,34 +61,42 @@ function job(options: JobOptions): Job;
|
|
|
59
61
|
|
|
60
62
|
**Parameters:**
|
|
61
63
|
|
|
62
|
-
| Parameter
|
|
63
|
-
|
|
|
64
|
-
| `name`
|
|
65
|
-
| `options.runsOn`
|
|
66
|
-
| `options.
|
|
67
|
-
| `options.
|
|
68
|
-
| `options.
|
|
69
|
-
| `options.
|
|
70
|
-
| `options.
|
|
71
|
-
| `options.
|
|
72
|
-
| `options.
|
|
73
|
-
| `options.
|
|
74
|
-
| `options.
|
|
75
|
-
| `options.
|
|
76
|
-
| `options.
|
|
77
|
-
| `options.
|
|
78
|
-
| `options.
|
|
79
|
-
| `options.
|
|
80
|
-
| `options.
|
|
81
|
-
| `options.
|
|
82
|
-
| `options.
|
|
83
|
-
| `options.
|
|
84
|
-
| `options.
|
|
85
|
-
| `options.
|
|
86
|
-
| `options.
|
|
87
|
-
| `options.
|
|
88
|
-
| `options.
|
|
89
|
-
| `options.
|
|
64
|
+
| Parameter | Type | Required | Description |
|
|
65
|
+
| ------------------------------ | -------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
66
|
+
| `name` | `string` | no | Job name (auto-generated UUID if omitted) |
|
|
67
|
+
| `options.runsOn` | `RunsOn` | yes (or `runsOnAll`) | Single-agent targeting -- runner label(s) and optional exclusions (see below). Mutually exclusive with `runsOnAll`. |
|
|
68
|
+
| `options.runsOnAll` | `RunsOnAllInput` | yes (or `runsOn`) | Host fan-out -- one pinned execution per roster host matching the predicate. Mutually exclusive with `runsOn`. See [runsOnAll host fan-out](https://docs.kici.dev/user/sdk/runs-on-all/). |
|
|
69
|
+
| `options.onUnreachable` | `'skip' \| 'fail' \| 'hold'` | no (default: `hold`) | Failure policy for unreachable durable hosts. `skip` omits them, `fail` fails the run, `hold` queues a pinned child and waits. Only meaningful alongside `runsOnAll`. |
|
|
70
|
+
| `options.includeUninitialized` | `boolean` | no (default: `false`) | Widen a `runsOnAll` fan-out to declared-but-un-agented hosts -- a matching host with no live agent gets a temporary init-runner brought up over SSH. Only meaningful alongside `runsOnAll`. |
|
|
71
|
+
| `options.steps` | `StepInput[]` | yes (or use `run`) | Steps to execute in order. Mutually exclusive with `run`. |
|
|
72
|
+
| `options.run` | `(ctx) => Promise<unknown>` | yes (or use `steps`) | Single-step shorthand -- see [Single-step job shorthand](https://docs.kici.dev/user/sdk/core/#single-step-job-shorthand). Mutually exclusive with `steps`. |
|
|
73
|
+
| `options.needs` | `Array<Job \| string \| DynamicGroupRef \| { name; when? } \| { group; when? }>` | no | Job dependencies (must complete first) -- see [Job dependencies (`needs`)](https://docs.kici.dev/user/sdk/core/#job-dependencies-needs) |
|
|
74
|
+
| `options.rules` | `Rule[]` | no | Conditions for conditional execution |
|
|
75
|
+
| `options.description` | `string` | no | Human-readable description |
|
|
76
|
+
| `options.matrix` | `Matrix` | no | Matrix configuration for job expansion |
|
|
77
|
+
| `options.include` | `MatrixInclude[]` | no | Additional matrix combinations |
|
|
78
|
+
| `options.exclude` | `MatrixExclude[]` | no | Matrix combinations to remove |
|
|
79
|
+
| `options.maxParallel` | `number` | no | Fan-out concurrency width -- the maximum number of fan-out children (matrix combinations or `runsOnAll` hosts) running at once. A sliding window; `1` is strictly serial. Must be `>= 1`. |
|
|
80
|
+
| `options.failFast` | `boolean` | no (default: `false`) | Halt the fan-out on the first child failure: stop releasing new children and skip the ones still held. Applies to both matrix and `runsOnAll` fan-out. |
|
|
81
|
+
| `options.checkout` | `boolean` | no (default: `true`) | When `false`, agent skips git clone. Useful for deploy/notify jobs. |
|
|
82
|
+
| `options.container` | `string \| ContainerConfig` | no | Docker image for job execution. String form is the image name; object form adds `env`. All steps run inside the container. |
|
|
83
|
+
| `options.sandbox` | `{ capabilities?: string[]; network?: 'default' \| 'none' \| 'host' }` | no | Per-job container sandbox escape hatch (container jobs only). Request extra Linux capabilities / host networking; granted only within your operator's allow-list, else the run fails at dispatch. See below. |
|
|
84
|
+
| `options.context` | `string \| ((event) => string \| Promise<string>)` | no | Bound context for this job -- the secret / variable scope it resolves against. Static string or async/dynamic function -- see [Contexts](https://docs.kici.dev/user/contexts/) and [Dynamic values](https://docs.kici.dev/user/dynamic-values/). |
|
|
85
|
+
| `options.contexts` | `(string \| ((event) => string \| Promise<string>))[]` | no | Bound contexts in merge order (later entries override earlier on name collisions). Mutually exclusive with `context`. |
|
|
86
|
+
| `options.env` | `Record<string, string> \| ((event) => Record<string, string>)` | no | Environment variables. Static object or async/dynamic function -- see [Dynamic values](https://docs.kici.dev/user/dynamic-values/). |
|
|
87
|
+
| `options.concurrencyGroup` | `string \| ((event) => string \| Promise<string>)` | no | Concurrency group name. Defaults to the first bound context's name -- see [Concurrency](https://docs.kici.dev/user/concurrency/). |
|
|
88
|
+
| `options.onCancel` | `HookInput` | no | Hook that runs when the job is cancelled |
|
|
89
|
+
| `options.cleanup` | `HookInput` | no | Hook that always runs after completion |
|
|
90
|
+
| `options.onSuccess` | `HookInput` | no | Hook that runs when the job succeeds |
|
|
91
|
+
| `options.onFailure` | `HookInput` | no | Hook that runs when the job fails |
|
|
92
|
+
| `options.beforeStep` | `HookInput` | no | Hook that runs before each step |
|
|
93
|
+
| `options.afterStep` | `HookInput` | no | Hook that runs after each step |
|
|
94
|
+
| `options.gracePeriod` | `number` | no | Seconds before SIGKILL after SIGTERM during cancellation -- see [Hooks](https://docs.kici.dev/user/hooks/#hook-timeout). |
|
|
95
|
+
| `options.timeout` | `number` | no | Total job wall-clock timeout in milliseconds (init + all steps + hooks). On breach the job is aborted and reported timed out. See [Timeouts](https://docs.kici.dev/user/sdk/core/#timeouts). |
|
|
96
|
+
| `options.resources` | `ResourceRequest` | no | Per-job CPU / memory request and limit. See [Per-job resources](https://docs.kici.dev/user/sdk/core/#per-job-resources) below. |
|
|
97
|
+
| `options.init` | `InitConfig` | no | Per-job initialization run after clone, before steps -- provisions a toolchain. A generic config, a typed preset (`'mise'` / `{ mise }`), `'auto'`, or `false`. See [Per-job init](https://docs.kici.dev/user/sdk/core/#per-job-init) below. |
|
|
98
|
+
| `options.cache` | `CacheInput` | no | Declarative cache: restored before steps, saved after the job on a key miss. See [Caching](https://docs.kici.dev/user/sdk/caching/). |
|
|
99
|
+
| `options.approval` | `ApprovalConfig` | no | Pause for a manual human approval before this job dispatches. See [Approval gates](https://docs.kici.dev/user/approvals/). |
|
|
90
100
|
|
|
91
101
|
**Returns:** `Job` -- an immutable job definition.
|
|
92
102
|
|
|
@@ -1002,13 +1012,15 @@ type RuleCheckFn = (ctx: RuleContext) => Promise<boolean> | boolean;
|
|
|
1002
1012
|
|
|
1003
1013
|
Can be sync or async. Receives a `RuleContext`:
|
|
1004
1014
|
|
|
1005
|
-
| Property | Type | Description
|
|
1006
|
-
| -------------------- | ----------------------------------------- |
|
|
1007
|
-
| `event` | `EventPayload` | The triggering event payload (discriminated union — narrow on `type`)
|
|
1008
|
-
| `changedFiles` | `string[]` | Files changed in this event (see availability note below)
|
|
1009
|
-
| `changedFilesStatus` | `'fetched' \| 'unavailable' \| 'skipped'` | Whether `changedFiles` is available
|
|
1010
|
-
| `
|
|
1011
|
-
|
|
|
1015
|
+
| Property | Type | Description |
|
|
1016
|
+
| -------------------- | ----------------------------------------- | ----------------------------------------------------------------------- |
|
|
1017
|
+
| `event` | `EventPayload` | The triggering event payload (discriminated union — narrow on `type`) |
|
|
1018
|
+
| `changedFiles` | `string[]` | Files changed in this event (see availability note below) |
|
|
1019
|
+
| `changedFilesStatus` | `'fetched' \| 'unavailable' \| 'skipped'` | Whether `changedFiles` is available |
|
|
1020
|
+
| `sourceRepo` | `RepoInfo \| undefined` | Repo whose event triggered the run, when the evaluation has a checkout |
|
|
1021
|
+
| `workflowRepo` | `RepoInfo \| undefined` | Repo that registered the workflow (same repo outside a global workflow) |
|
|
1022
|
+
| `env` | `Record<string, string\|undefined>` | Environment variables |
|
|
1023
|
+
| `$` | zx shell | Shell executor for running commands |
|
|
1012
1024
|
|
|
1013
1025
|
`changedFiles` is available on `push` and `pull_request` events — the agent computes the diff from its checkout, so no `paths:` trigger is required. It is `unavailable` for events with no diff (`schedule`, `tag`, `manual_schedule`), and in the rare case where the diff cannot be computed (e.g. a history deeper than the agent's bounded fetch). Reading `changedFiles` when it is unavailable throws and fails the job, so guard with `changedFilesStatus` first when a rule can run on such events:
|
|
1014
1026
|
|
|
@@ -1019,6 +1031,8 @@ rule('has source changes', (ctx) => {
|
|
|
1019
1031
|
});
|
|
1020
1032
|
```
|
|
1021
1033
|
|
|
1034
|
+
The throw is a `ChangedFilesUnavailableError` (exported from `@kici-dev/sdk`, carrying the `changedFilesStatus` and `eventType` that produced it). `evaluateRules()` deliberately re-throws it rather than folding it into a `passed=false` skip, so a path-based gate fails loudly instead of silently mis-evaluating.
|
|
1035
|
+
|
|
1022
1036
|
### evaluateRules(rules, context, label, onRuleResult?)
|
|
1023
1037
|
|
|
1024
1038
|
Evaluate an array of rules sequentially with fail-fast behavior. Stops on the first failure.
|
|
@@ -1291,12 +1305,18 @@ type DynamicJobFn = (context: DynamicJobContext) => Promise<Job[]>;
|
|
|
1291
1305
|
|
|
1292
1306
|
Receives a `DynamicJobContext`:
|
|
1293
1307
|
|
|
1294
|
-
| Property
|
|
1295
|
-
|
|
|
1296
|
-
| `$`
|
|
1297
|
-
| `ctx`
|
|
1298
|
-
| `log`
|
|
1299
|
-
| `env`
|
|
1308
|
+
| Property | Type | Description |
|
|
1309
|
+
| -------------- | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
1310
|
+
| `$` | zx shell | Shell executor |
|
|
1311
|
+
| `ctx` | `{ workflow, event? }` | Workflow metadata and event |
|
|
1312
|
+
| `log` | `Logger` | Structured logger |
|
|
1313
|
+
| `env` | `Record<string, string\|undefined>` | Environment variables |
|
|
1314
|
+
| `sourceRepo` | `RepoInfo \| undefined` | Repo whose event triggered the run, when the evaluation has a checkout |
|
|
1315
|
+
| `workflowRepo` | `RepoInfo \| undefined` | Repo that registered the workflow (same repo outside a global workflow) |
|
|
1316
|
+
|
|
1317
|
+
`RepoInfo` carries `path` — an absolute path to that repo's checkout — plus optional `ref` and `sha`; guard before reading either, since an event that carries no single ref leaves them undefined. In a [global workflow](https://docs.kici.dev/user/global-workflows/) `sourceRepo` and `workflowRepo` are different repos, so one generator can produce a different job set per source repo.
|
|
1318
|
+
|
|
1319
|
+
**`sourceRepo.path` is not stable across calls.** A generator is invoked once to discover the job set and again to extract the step closures of the job being run; both see the same tree at the same commit, but not necessarily the same path or even the same machine. Read _through_ it, and derive job names from what the tree contains — never from the path itself, or the second call produces different names and the run fails the determinism check.
|
|
1300
1320
|
|
|
1301
1321
|
```typescript
|
|
1302
1322
|
const discoverJobs: DynamicJobFn = async ({ $ }) => {
|
|
@@ -1489,6 +1509,182 @@ workflow runs rather than being silently dropped, and the delivery is recorded
|
|
|
1489
1509
|
as degraded. GitHub always provides an exact list; a transient API error fails
|
|
1490
1510
|
loudly, not as empty.
|
|
1491
1511
|
|
|
1512
|
+
### Content requirements (`requires`)
|
|
1513
|
+
|
|
1514
|
+
Where `paths` filters on **which files changed**, `requires` filters on **what
|
|
1515
|
+
those files contain**. It is a declarative filter on the `pr()`, `push()`, and
|
|
1516
|
+
`tag()` triggers: a list of queries over the bytes of named source files, read
|
|
1517
|
+
at the event's commit. The orchestrator evaluates it as pure data before
|
|
1518
|
+
dispatching — it reads only the referenced files, never clones the whole
|
|
1519
|
+
repository, and never runs any of your workflow code. A workflow whose `requires`
|
|
1520
|
+
does not pass is simply not dispatched.
|
|
1521
|
+
|
|
1522
|
+
Each entry is a `ContentRequirement`:
|
|
1523
|
+
|
|
1524
|
+
```typescript
|
|
1525
|
+
interface ContentRequirement {
|
|
1526
|
+
file: string; // repo-relative path to query
|
|
1527
|
+
format?: 'auto' | 'json' | 'yaml' | 'text'; // how to parse the file (default: 'auto')
|
|
1528
|
+
exists?: string[]; // JSONPath expressions that must each resolve to ≥1 node (json/yaml)
|
|
1529
|
+
match?: Record<string, unknown>; // JSONPath → expected value; every one must match (json/yaml)
|
|
1530
|
+
not?: Record<string, unknown>; // JSONPath → value; passes only when NONE match (json/yaml)
|
|
1531
|
+
contains?: string | string[]; // literal substrings, all of which must appear (text only)
|
|
1532
|
+
notContains?: string | string[]; // literal substrings, none of which may appear (text only)
|
|
1533
|
+
matches?: string | RegExp | (string | RegExp)[]; // regexes, all of which must match (text only)
|
|
1534
|
+
notMatches?: string | RegExp | (string | RegExp)[]; // regexes, none of which may match (text only)
|
|
1535
|
+
ignoreCase?: boolean; // applies to contains/notContains only (default: false)
|
|
1536
|
+
absent?: boolean; // passes only when the file does NOT exist
|
|
1537
|
+
}
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
**Format.** `format: 'auto'` (the default) picks the parser by extension:
|
|
1541
|
+
`.json` → JSON, `.yaml` / `.yml` → YAML, everything else → text. Set `format`
|
|
1542
|
+
explicitly to override — e.g. treat an extensionless file as JSON, or read a
|
|
1543
|
+
`.json` file as raw text. JSON and YAML both parse to an object, so the JSONPath
|
|
1544
|
+
keys (`exists` / `match` / `not`) work identically over either; `text` files are
|
|
1545
|
+
queried by `contains`, `notContains`, `matches`, and `notMatches` over the raw
|
|
1546
|
+
bytes.
|
|
1547
|
+
|
|
1548
|
+
**Query keys.**
|
|
1549
|
+
|
|
1550
|
+
- **`exists`** — an array of JSONPath expressions; each must resolve to at least
|
|
1551
|
+
one node in the parsed document.
|
|
1552
|
+
- **`match`** — a JSONPath → expected-value map; every expression must match. An
|
|
1553
|
+
expected value is an exact value, a regex string in `/pattern/flags` form
|
|
1554
|
+
(against a string node), or an array of acceptable values (any one matches).
|
|
1555
|
+
- **`not`** — the same map shape, inverted: the entry passes only when **none** of
|
|
1556
|
+
the expressions match.
|
|
1557
|
+
- **`contains` / `notContains`** — literal substrings tested against the raw file
|
|
1558
|
+
text. Every entry must be present (`contains`) or absent (`notContains`). No
|
|
1559
|
+
escaping needed (text format only).
|
|
1560
|
+
- **`matches`** — one or several regexes (a `RegExp` or `/pattern/flags` string),
|
|
1561
|
+
each of which must match the raw file text (text format only).
|
|
1562
|
+
- **`notMatches`** — the inverse of `matches`: the entry passes only when none of
|
|
1563
|
+
the regexes match (text format only).
|
|
1564
|
+
- **`ignoreCase`** — case-insensitive `contains` / `notContains` only; a regex
|
|
1565
|
+
carries its own flags. Default false.
|
|
1566
|
+
- **`absent: true`** — passes only when the file does **not** exist at the event's
|
|
1567
|
+
commit. It is mutually exclusive with the query keys above.
|
|
1568
|
+
- A bare `{ file }` with no query key requires the file to **exist**.
|
|
1569
|
+
|
|
1570
|
+
The keys inside one entry are AND-ed, and the entries in a `requires` list are
|
|
1571
|
+
AND-ed with each other. An empty or absent `requires` matches everything, exactly
|
|
1572
|
+
like `paths`.
|
|
1573
|
+
|
|
1574
|
+
**Examples:**
|
|
1575
|
+
|
|
1576
|
+
```typescript
|
|
1577
|
+
// Only run CI when package.json declares a `ci` script.
|
|
1578
|
+
push({ branches: 'main', requires: [{ file: 'package.json', exists: ['$.scripts.ci'] }] });
|
|
1579
|
+
|
|
1580
|
+
// Deploy only when the service config enables it (YAML, matched by value).
|
|
1581
|
+
push({
|
|
1582
|
+
branches: 'main',
|
|
1583
|
+
requires: [{ file: 'service.yaml', match: { '$.deploy.enabled': true } }],
|
|
1584
|
+
});
|
|
1585
|
+
|
|
1586
|
+
// Only run when the Dockerfile builds from a Node base image (raw-text regex).
|
|
1587
|
+
pr({ requires: [{ file: 'Dockerfile', format: 'text', matches: '/^FROM node:/m' }] });
|
|
1588
|
+
|
|
1589
|
+
// Skip the workflow whenever a repo carries an opt-out marker file.
|
|
1590
|
+
push({ requires: [{ file: '.skip-ci', absent: true }] });
|
|
1591
|
+
|
|
1592
|
+
// Combine filters: a tag build that requires a version file AND forbids a draft flag.
|
|
1593
|
+
tag({
|
|
1594
|
+
patterns: ['v*'],
|
|
1595
|
+
requires: [
|
|
1596
|
+
{ file: 'VERSION', matches: '/^\\d+\\.\\d+\\.\\d+$/' },
|
|
1597
|
+
{ file: 'release.json', not: { '$.draft': true } },
|
|
1598
|
+
],
|
|
1599
|
+
});
|
|
1600
|
+
```
|
|
1601
|
+
|
|
1602
|
+
**Fail-visible evaluation.** Files are read at the event's commit. If a
|
|
1603
|
+
referenced file is larger than **1 MiB**, or fails to parse for its format, the
|
|
1604
|
+
requirement is **indeterminate** — the candidate workflow is dropped and does
|
|
1605
|
+
**not** run. A `requires` that cannot be evaluated never silently passes.
|
|
1606
|
+
|
|
1607
|
+
**Compile-time validation.** `kici compile` rejects a malformed requirement before
|
|
1608
|
+
it ever reaches the orchestrator: a raw-text key that is invalid or catastrophic
|
|
1609
|
+
(ReDoS-prone) is rejected by a safe-regex check; a text file cannot carry a
|
|
1610
|
+
JSON/YAML query key (`exists` / `match` / `not`) and a JSON/YAML file cannot carry a
|
|
1611
|
+
raw-text key; `absent` cannot be combined with a query key; and an explicit
|
|
1612
|
+
`format` with no query key is rejected as having nothing to check.
|
|
1613
|
+
|
|
1614
|
+
### Commit-message filters (`commitMessage`)
|
|
1615
|
+
|
|
1616
|
+
Where `requires` filters on what the repository's **files** contain,
|
|
1617
|
+
`commitMessage` filters on what the **event** says. It is a declarative filter on
|
|
1618
|
+
the `pr()`, `push()`, and `tag()` triggers. The orchestrator evaluates it
|
|
1619
|
+
directly from the webhook payload: no file is fetched, and no repository is
|
|
1620
|
+
cloned. For an organization-wide workflow it dispatches no evaluation job. It is
|
|
1621
|
+
the cheapest gate available.
|
|
1622
|
+
|
|
1623
|
+
The text it tests is the **full head-commit message** — subject and body — for
|
|
1624
|
+
`push` and `tag`, and the **title plus body** for pull-request events.
|
|
1625
|
+
|
|
1626
|
+
```typescript
|
|
1627
|
+
interface TextMatch {
|
|
1628
|
+
contains?: string | string[]; // every needle must be present
|
|
1629
|
+
notContains?: string | string[]; // no needle may be present
|
|
1630
|
+
matches?: string | RegExp | (string | RegExp)[]; // every regex must match
|
|
1631
|
+
notMatches?: string | RegExp | (string | RegExp)[]; // no regex may match
|
|
1632
|
+
ignoreCase?: boolean; // applies to contains/notContains only (default: false)
|
|
1633
|
+
}
|
|
1634
|
+
```
|
|
1635
|
+
|
|
1636
|
+
**Every entry in a list is a conjunct.** `contains: ['a', 'b']` passes only when
|
|
1637
|
+
the text contains both, and the keys AND together. To express OR, declare two
|
|
1638
|
+
triggers — a workflow's trigger list already matches on the first one that fits:
|
|
1639
|
+
|
|
1640
|
+
```typescript
|
|
1641
|
+
// AND — one trigger.
|
|
1642
|
+
push({ commitMessage: { contains: ['release:', 'approved'] } });
|
|
1643
|
+
|
|
1644
|
+
// OR — two triggers.
|
|
1645
|
+
on: [
|
|
1646
|
+
push({ branches: 'main', commitMessage: { contains: 'deploy:' } }),
|
|
1647
|
+
push({ branches: 'main', commitMessage: { contains: 'release:' } }),
|
|
1648
|
+
];
|
|
1649
|
+
```
|
|
1650
|
+
|
|
1651
|
+
Needles are **literal substrings** — no glob, no regex, no escaping, so a needle
|
|
1652
|
+
containing `.*` matches only the literal `.*`. Use `matches` / `notMatches` for a
|
|
1653
|
+
pattern; both accept a `RegExp` literal, and the `m` flag reaches the body:
|
|
1654
|
+
|
|
1655
|
+
```typescript
|
|
1656
|
+
// The single most common use: skip marker commits.
|
|
1657
|
+
push({ branches: 'main', commitMessage: { notContains: ['[skip ci]', '[ci skip]'] } });
|
|
1658
|
+
|
|
1659
|
+
// Ignore dependency-bump noise across an organization.
|
|
1660
|
+
push({ commitMessage: { notMatches: /^chore\(deps\):/ } });
|
|
1661
|
+
|
|
1662
|
+
// Require a conventional-commit prefix and forbid a WIP marker.
|
|
1663
|
+
pr({ target: 'main', commitMessage: { matches: /^(feat|fix)\(/, notContains: 'WIP' } });
|
|
1664
|
+
|
|
1665
|
+
// Match a trailer in the commit body.
|
|
1666
|
+
push({ commitMessage: { matches: /^Fixes: #\d+$/m } });
|
|
1667
|
+
```
|
|
1668
|
+
|
|
1669
|
+
`ignoreCase` affects `contains` and `notContains` only — a regex already carries
|
|
1670
|
+
its own flags, so write `/^feat:/i` rather than expecting `ignoreCase` to reach
|
|
1671
|
+
it.
|
|
1672
|
+
|
|
1673
|
+
**Fail-visible evaluation.** Some events carry no message at all. A
|
|
1674
|
+
branch-deletion push has no head commit, and a self-hosted forge may publish
|
|
1675
|
+
none. The trigger then does **not** match, and the decision trace records it as
|
|
1676
|
+
`indeterminate` rather than as an exclusion. A `commitMessage` filter that cannot
|
|
1677
|
+
be evaluated never silently passes.
|
|
1678
|
+
|
|
1679
|
+
**Compile-time validation.** `kici compile` rejects a malformed matcher. It
|
|
1680
|
+
refuses:
|
|
1681
|
+
|
|
1682
|
+
- a matcher with no query key;
|
|
1683
|
+
- an `ignoreCase` that would affect nothing;
|
|
1684
|
+
- an empty needle list;
|
|
1685
|
+
- an empty-string needle (it would match every text);
|
|
1686
|
+
- a regex that is invalid or catastrophic (ReDoS-prone).
|
|
1687
|
+
|
|
1492
1688
|
### tag()
|
|
1493
1689
|
|
|
1494
1690
|
Create a tag trigger. Returns a frozen `TagTriggerConfig`.
|
|
@@ -9,13 +9,13 @@ The full markdown bundle of every page indexed here is available at https://docs
|
|
|
9
9
|
Each bundle below is a self-contained markdown file for one authoring task. Fetch only the one your task needs instead of the full bundle:
|
|
10
10
|
|
|
11
11
|
- [getting-started](https://docs.kici.dev/llms-getting-started.txt) (51 KB) — Adopt KiCI: why it exists, how workflows execute, migrating from GitHub Actions, installing the SDK, and writing/compiling/testing your first workflow
|
|
12
|
-
- [patterns](https://docs.kici.dev/llms-patterns.txt) (
|
|
13
|
-
- [sdk](https://docs.kici.dev/llms-sdk.txt) (
|
|
12
|
+
- [patterns](https://docs.kici.dev/llms-patterns.txt) (50 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
|
|
13
|
+
- [sdk](https://docs.kici.dev/llms-sdk.txt) (125 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
|
|
14
14
|
- [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (112 KB) — Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
|
|
15
|
-
- [cli](https://docs.kici.dev/llms-cli.txt) (
|
|
16
|
-
- [features](https://docs.kici.dev/llms-features.txt) (
|
|
15
|
+
- [cli](https://docs.kici.dev/llms-cli.txt) (187 KB) — Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift
|
|
16
|
+
- [features](https://docs.kici.dev/llms-features.txt) (158 KB) — Workflow features: concurrency, contexts, secrets, approvals, provenance, events
|
|
17
17
|
- [providers](https://docs.kici.dev/llms-providers.txt) (37 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
|
|
18
|
-
- [architecture](https://docs.kici.dev/llms-architecture.txt) (
|
|
18
|
+
- [architecture](https://docs.kici.dev/llms-architecture.txt) (95 KB) — How the runtime works: three-tier relay model, data flows, configuration
|
|
19
19
|
|
|
20
20
|
## Getting started
|
|
21
21
|
|
|
@@ -77,7 +77,7 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
77
77
|
- [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
|
|
78
78
|
- [Contexts](https://docs.kici.dev/user/contexts/): Configure deployment contexts with variables, secrets, and protection rules
|
|
79
79
|
- [Dashboard](https://docs.kici.dev/user/dashboard/): Web UI for monitoring workflow runs, managing sources, secrets, and organization settings.
|
|
80
|
-
- [Dynamic values](https://docs.kici.dev/user/dynamic-values/)
|
|
80
|
+
- [Dynamic values](https://docs.kici.dev/user/dynamic-values/): Compute a job's context, env, and concurrencyGroup at runtime from the incoming event
|
|
81
81
|
- [Environment variables](https://docs.kici.dev/user/env-vars/): Environment variable reference for the CLI
|
|
82
82
|
- [Event system](https://docs.kici.dev/user/events/): How KiCI's event model works -- event types, the registration model, event matching, and circuit breaker protection
|
|
83
83
|
- [Global workflows](https://docs.kici.dev/user/global-workflows/): Cross-repo workflows that run on events from any repo in the same org
|