@kici-dev/compiler 0.4.0 → 0.6.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 +37 -7
- package/dist/commands/approve.d.ts +12 -0
- package/dist/commands/approve.js +5 -2
- package/dist/commands/compile.js +5 -15
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/endpoints.js +4 -6
- package/dist/commands/held-run-client.d.ts +21 -1
- package/dist/commands/held-run-client.js +34 -15
- package/dist/commands/hook.js +22 -20
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -1
- package/dist/commands/init.d.ts +9 -2
- package/dist/commands/init.js +43 -16
- package/dist/commands/login.js +1 -1
- package/dist/commands/orchestrators.js +3 -2
- package/dist/commands/preview.js +1 -8
- package/dist/commands/reject.d.ts +12 -0
- package/dist/commands/reject.js +5 -2
- package/dist/commands/report/collect.d.ts +82 -0
- package/dist/commands/report/collect.js +234 -0
- package/dist/commands/report/identity.d.ts +48 -0
- package/dist/commands/report/identity.js +49 -0
- package/dist/commands/report/index.d.ts +63 -0
- package/dist/commands/report/index.js +119 -0
- package/dist/commands/report/upload.d.ts +38 -0
- package/dist/commands/report/upload.js +64 -0
- package/dist/commands/run-hold-watch.js +2 -2
- package/dist/commands/run.js +6 -3
- package/dist/commands/runs/show.js +80 -1
- package/dist/commands/types.js +51 -9
- 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/execution/sdk-alias.js +4 -2
- package/dist/fixtures/compiler.js +2 -1
- package/dist/format.js +3 -3
- package/dist/generators/secrets-dts.d.ts +8 -3
- package/dist/generators/secrets-dts.js +3 -3
- package/dist/hooks/installer.js +2 -1
- package/dist/llm-context/llms-architecture.txt +59 -23
- package/dist/llm-context/llms-cli.txt +168 -34
- package/dist/llm-context/llms-features-execution.txt +2017 -0
- package/dist/llm-context/llms-features.txt +96 -1100
- package/dist/llm-context/llms-full.txt +3131 -1407
- package/dist/llm-context/llms-getting-started.txt +164 -31
- package/dist/llm-context/llms-patterns.txt +186 -7
- package/dist/llm-context/llms-providers.txt +15 -33
- package/dist/llm-context/llms-sdk-runtime.txt +62 -40
- package/dist/llm-context/llms-sdk.txt +284 -58
- package/dist/llm-context/llms.txt +23 -15
- package/dist/local-plane/paths.d.ts +15 -0
- package/dist/local-plane/paths.js +22 -1
- package/dist/local-plane/plane-manager.js +2 -2
- package/dist/local-plane/port-holder.js +1 -1
- package/dist/local-plane/postgres.d.ts +3 -16
- package/dist/local-plane/postgres.js +10 -15
- package/dist/lockfile/generator.d.ts +12 -0
- package/dist/lockfile/generator.js +182 -54
- package/dist/lockfile/index.d.ts +0 -2
- package/dist/lockfile/index.js +1 -2
- package/dist/postinstall.js +2 -1
- package/dist/remote/config.d.ts +2 -15
- package/dist/remote/config.js +2 -16
- package/dist/remote/dashboard-client.d.ts +39 -0
- package/dist/remote/dashboard-client.js +41 -0
- package/dist/remote/oauth.js +7 -5
- package/dist/remote/uploader.js +2 -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 +5 -20
- package/dist/test-runner/git-detector.js +2 -1
- package/dist/test-runner/job-executor.js +2 -1
- package/dist/test-runner/payload-builder.js +11 -17
- package/dist/types.d.ts +64 -10
- package/dist/types.js +7 -1
- package/dist/validation/validator.js +63 -6
- package/package.json +16 -11
- package/sbom.spdx.json +957 -900
- 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
|
|
|
@@ -951,7 +961,7 @@ Source: https://docs.kici.dev/user/sdk/rules-matrix-dynamic/
|
|
|
951
961
|
|
|
952
962
|
Rules control conditional execution of workflows and jobs. A rule that returns `false` (or whose check function returns `false`) prevents execution.
|
|
953
963
|
|
|
954
|
-
A rule's check function that **returns `false`** cleanly skips the job or step. A check function that **throws**
|
|
964
|
+
A rule's check function that **returns `false`** cleanly skips the job or step. A check function that **throws** counts as an evaluation failure, not a skip. The job or step **fails** with the error surfaced (both on a remote run and when running locally with `kici run --local`), so a broken rule can never silently pass as a green run. For example, `rule('main only', (ctx) => ctx.event.ref.endsWith('main'))` throws on an event whose `ref` is undefined — that run fails with the error instead of quietly skipping every step. Fix the thrown error (guard the access) rather than relying on the skip.
|
|
955
965
|
|
|
956
966
|
### rule(label) / rule(label, check)
|
|
957
967
|
|
|
@@ -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`.
|
|
@@ -2239,6 +2435,36 @@ workflow('post-deploy', {
|
|
|
2239
2435
|
|
|
2240
2436
|
The orchestrator automatically emits system events for workflow and job completions. You do not need to call `ctx.emit()` for these -- they are generated by the orchestrator after execution. Listen for them with `workflowComplete()` and `jobComplete()` triggers.
|
|
2241
2437
|
|
|
2438
|
+
### Event scaler events
|
|
2439
|
+
|
|
2440
|
+
The [event scaler backend](https://docs.kici.dev/operator/orchestrator/event-scaler/) emits two reserved events that your provisioning and teardown workflows subscribe to. The SDK exports their names and payload schemas, so a workflow imports the contract instead of re-declaring it.
|
|
2441
|
+
|
|
2442
|
+
| Export | What it is |
|
|
2443
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
|
2444
|
+
| `SCALER_EVENT_NAMES` | The two reserved event names: `SCALER_EVENT_NAMES.scaleUp` and `SCALER_EVENT_NAMES.scaleDown`. |
|
|
2445
|
+
| `ScalerScaleUpPayload` | Schema of the scale-up payload. `.parse(ctx.rawPayload)` returns the typed payload and rejects a malformed one. |
|
|
2446
|
+
| `ScalerScaleDownPayload` | Schema of the scale-down payload, including the narrowed `reason`. |
|
|
2447
|
+
| `ScaleDownReason` | Why the scaler asked for a teardown: `idle`, `job-complete`, `heartbeat-timeout`, `spawn-timeout`, `drain`, `shutdown`. |
|
|
2448
|
+
|
|
2449
|
+
```ts
|
|
2450
|
+
import { workflow, job, kiciEvent, SCALER_EVENT_NAMES, ScalerScaleUpPayload } from '@kici-dev/sdk';
|
|
2451
|
+
|
|
2452
|
+
export default workflow('provision', {
|
|
2453
|
+
on: [kiciEvent({ name: SCALER_EVENT_NAMES.scaleUp, match: { '$.scalerName': 'hetzner' } })],
|
|
2454
|
+
jobs: [
|
|
2455
|
+
job('provision', {
|
|
2456
|
+
runsOn: ['kici:os:linux'],
|
|
2457
|
+
run: async (ctx) => {
|
|
2458
|
+
const payload = ScalerScaleUpPayload.parse(ctx.rawPayload);
|
|
2459
|
+
ctx.log.info(`provision agent ${payload.agentId}`);
|
|
2460
|
+
},
|
|
2461
|
+
}),
|
|
2462
|
+
],
|
|
2463
|
+
});
|
|
2464
|
+
```
|
|
2465
|
+
|
|
2466
|
+
These names are reserved. `ctx.emit()` rejects any event name that starts with `kici.`, so a workflow step cannot forge a scaler event. For every payload field, see the [event contract reference](https://docs.kici.dev/operator/orchestrator/event-scaler-events/). For complete provisioning and teardown workflows, see [autoscaling workflows](https://docs.kici.dev/user/workflows/autoscaling-workflows/).
|
|
2467
|
+
|
|
2242
2468
|
---
|
|
2243
2469
|
|
|
2244
2470
|
## SDK reference
|
|
@@ -8,19 +8,21 @@ The full markdown bundle of every page indexed here is available at https://docs
|
|
|
8
8
|
|
|
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
|
-
- [getting-started](https://docs.kici.dev/llms-getting-started.txt) (
|
|
12
|
-
- [patterns](https://docs.kici.dev/llms-patterns.txt) (
|
|
13
|
-
- [sdk](https://docs.kici.dev/llms-sdk.txt) (
|
|
14
|
-
- [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (
|
|
15
|
-
- [cli](https://docs.kici.dev/llms-cli.txt) (
|
|
16
|
-
- [features](https://docs.kici.dev/llms-features.txt) (
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
11
|
+
- [getting-started](https://docs.kici.dev/llms-getting-started.txt) (58 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) (57 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
|
|
13
|
+
- [sdk](https://docs.kici.dev/llms-sdk.txt) (127 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
|
|
14
|
+
- [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (114 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) (194 KB) — Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift
|
|
16
|
+
- [features](https://docs.kici.dev/llms-features.txt) (90 KB) — Deployment contexts, scoped secrets, private registries, approvals, provenance, dashboard and account access
|
|
17
|
+
- [features-execution](https://docs.kici.dev/llms-features-execution.txt) (120 KB) — Concurrency, dynamic values, events, container jobs, environment variables, global workflows, idempotent steps
|
|
18
|
+
- [providers](https://docs.kici.dev/llms-providers.txt) (35 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
|
|
19
|
+
- [architecture](https://docs.kici.dev/llms-architecture.txt) (99 KB) — How the runtime works: three-tier relay model, data flows, configuration
|
|
19
20
|
|
|
20
21
|
## Getting started
|
|
21
22
|
|
|
22
23
|
- [User guide](https://docs.kici.dev/user/): Writing and testing CI/CD workflows in TypeScript, running on infrastructure you control
|
|
23
24
|
- [How your workflow code executes](https://docs.kici.dev/user/execution-model/): When and where your workflow TypeScript runs — compile time, orchestrator time, and agent time
|
|
25
|
+
- [Getting help](https://docs.kici.dev/user/getting-help/): How to report a problem to KiCI and send the diagnostic context privately
|
|
24
26
|
- [Getting started with workflows](https://docs.kici.dev/user/getting-started/): Install the SDK, write your first workflow, compile and test locally
|
|
25
27
|
- [Migrating from GitHub Actions](https://docs.kici.dev/user/migrating-from-github-actions/): Map GitHub Actions concepts to KiCI, translate a real workflow side-by-side, and see what has no equivalent yet
|
|
26
28
|
- [5-minute quickstart](https://docs.kici.dev/user/quickstart/): Stand up a KiCI orchestrator + agent and run your first workflow
|
|
@@ -30,6 +32,7 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
30
32
|
|
|
31
33
|
- [Basic workflow patterns](https://docs.kici.dev/user/patterns/basic/): Basic CI, PR-only / push-only filters, multiple triggers, manual-only workflows
|
|
32
34
|
- [Conditionals & matrix patterns](https://docs.kici.dev/user/patterns/conditionals-matrix/): Conditional execution with rules, matrix builds (static + dynamic), dynamic job generation
|
|
35
|
+
- [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/): Authenticated git in a workflow — declaring credentials from the secrets backend, and pushing
|
|
33
36
|
- [Host restart & wait-for-alive](https://docs.kici.dev/user/patterns/host-restart/): Reboot the host a workflow runs on and continue after it comes back
|
|
34
37
|
- [Integration patterns](https://docs.kici.dev/user/patterns/integrations/): Workflow chaining, generic webhooks, Stripe, self-hosted git forges, plain GitHub repos
|
|
35
38
|
- [Pattern reference](https://docs.kici.dev/user/patterns/reference/): Step context, examples repository, GitHub check run output — cross-cutting reference for all patterns
|
|
@@ -59,7 +62,7 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
59
62
|
|
|
60
63
|
- [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/): Point a coding agent at KiCI's MCP server and let it trigger, read, and re-run your CI under your own identity.
|
|
61
64
|
- [CLI authentication](https://docs.kici.dev/user/cli-auth/): Authenticate the KiCI CLI with browser OAuth, device flow, or API key paste
|
|
62
|
-
- [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, preview, local, fixture, types, workflows, hook, docs, run, runs, approve, reject, login, logout, init, org, pat, secrets, admin, orchestrators, endpoints, notifications, verify-attestation, diagnostics, doctor
|
|
65
|
+
- [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, preview, local, fixture, types, workflows, hook, docs, run, runs, approve, reject, login, logout, init, org, pat, secrets, admin, orchestrators, endpoints, notifications, verify-attestation, diagnostics, doctor, report
|
|
63
66
|
- [Common failures](https://docs.kici.dev/user/common-failures/): Symptom-to-fix reference for the failures workflow authors hit most — no jobs dispatched, lock-file drift, missing webhooks, and agents that won't connect
|
|
64
67
|
- [Lifecycle hooks](https://docs.kici.dev/user/hooks/): SDK hook API for cancel, cleanup, success, failure, and step-level callbacks
|
|
65
68
|
- [Lock file and workflow drift](https://docs.kici.dev/user/lock-file-and-drift/): Keep the lock file in sync with your workflow source and avoid drift
|
|
@@ -70,21 +73,26 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
70
73
|
- [kici: notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/): Notification channels, attestation verification, and diagnostics
|
|
71
74
|
- [kici: runs & approvals](https://docs.kici.dev/user/cli/runs-and-approvals/): Run push and inspection plus approval / rejection of held runs
|
|
72
75
|
|
|
73
|
-
## Workflow features
|
|
76
|
+
## Workflow features: access and approval
|
|
74
77
|
|
|
75
78
|
- [Account and sign-in](https://docs.kici.dev/user/account-and-login/): How your KiCI account relates to sign-in methods, and how to change the way you sign in.
|
|
76
79
|
- [Approval gates](https://docs.kici.dev/user/approvals/): Pause a workflow for human sign-off at step, job, or workflow granularity with approval
|
|
77
|
-
- [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
|
|
78
80
|
- [Contexts](https://docs.kici.dev/user/contexts/): Configure deployment contexts with variables, secrets, and protection rules
|
|
79
81
|
- [Dashboard](https://docs.kici.dev/user/dashboard/): Web UI for monitoring workflow runs, managing sources, secrets, and organization settings.
|
|
80
|
-
- [
|
|
82
|
+
- [Private npm registries](https://docs.kici.dev/user/private-registries/): Authenticate `npm install` against private registries (CodeArtifact, GitHub Packages, Verdaccio, …) from a workflow's `.kici/package.json`
|
|
83
|
+
- [Build provenance and attestations](https://docs.kici.dev/user/provenance/): Generate and verify signed SLSA provenance for the artifacts your workflows build
|
|
84
|
+
- [Secrets](https://docs.kici.dev/user/secrets/): How to access secrets in KiCI workflow steps
|
|
85
|
+
|
|
86
|
+
## Workflow features: execution
|
|
87
|
+
|
|
88
|
+
- [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
|
|
89
|
+
- [Container jobs](https://docs.kici.dev/user/container-jobs/): Run a job inside any container image, including a private one, without that image shipping Node or git
|
|
90
|
+
- [Dynamic values](https://docs.kici.dev/user/dynamic-values/): Compute a job's context, env, and concurrencyGroup at runtime from the incoming event
|
|
81
91
|
- [Environment variables](https://docs.kici.dev/user/env-vars/): Environment variable reference for the CLI
|
|
82
92
|
- [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
93
|
- [Global workflows](https://docs.kici.dev/user/global-workflows/): Cross-repo workflows that run on events from any repo in the same org
|
|
84
94
|
- [Idempotent steps and check mode](https://docs.kici.dev/user/idempotent-steps/): Declare desired state with a step check facet, then run in apply or --check preview mode
|
|
85
|
-
- [
|
|
86
|
-
- [Build provenance and attestations](https://docs.kici.dev/user/provenance/): Generate and verify signed SLSA provenance for the artifacts your workflows build
|
|
87
|
-
- [Secrets](https://docs.kici.dev/user/secrets/): How to access secrets in KiCI workflow steps
|
|
95
|
+
- [Autoscaling workflows](https://docs.kici.dev/user/workflows/autoscaling-workflows/): Write TypeScript provisioning and teardown workflows that boot and delete ephemeral cloud agents in response to the event scaler
|
|
88
96
|
|
|
89
97
|
## Providers
|
|
90
98
|
|
|
@@ -7,6 +7,21 @@ export declare const PLANE_STAMP_VERSION = 3;
|
|
|
7
7
|
/**
|
|
8
8
|
* Root directory of the local dev plane's state, following the same
|
|
9
9
|
* `KICI_CONFIG_DIR` → `~/.kici` convention the rest of the CLI uses.
|
|
10
|
+
*
|
|
11
|
+
* RESOLVED THROUGH SYMLINKS, deliberately. The plane is a singleton on fixed
|
|
12
|
+
* ports, so a caller may reach it through a config dir that only symlinks
|
|
13
|
+
* `local` at the durable one — `pnpm deploy:stg` does exactly that, to run
|
|
14
|
+
* against a throwaway config dir carrying no credentials while still reusing
|
|
15
|
+
* the warm plane.
|
|
16
|
+
*
|
|
17
|
+
* Without resolving, the plane's Postgres is started with a data directory
|
|
18
|
+
* addressed through that ephemeral path and keeps it open. When the caller
|
|
19
|
+
* removes its temp dir, Postgres PANICs — `could not open file
|
|
20
|
+
* "<tmp>/local/pgdata/global/pg_control"` — and shuts the whole plane down,
|
|
21
|
+
* taking every later phase with it. Resolving first means Postgres only ever
|
|
22
|
+
* sees the durable path, so a caller's temp dir can come and go beneath it.
|
|
23
|
+
*
|
|
24
|
+
* A path that does not exist yet resolves to itself: a fresh plane creates it.
|
|
10
25
|
*/
|
|
11
26
|
export declare function planeRoot(): string;
|
|
12
27
|
/**
|