@intentius/chant 0.124.23 → 0.124.24
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/ci-jobs.d.ts +41 -1
- package/dist/ci-jobs.d.ts.map +1 -1
- package/dist/ci-jobs.js +48 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +14 -0
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +9 -0
- package/dist/cli/handlers/emulator.d.ts +13 -2
- package/dist/cli/handlers/emulator.d.ts.map +1 -1
- package/dist/cli/handlers/emulator.js +63 -3
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +7 -1
- package/dist/cli/handlers/run-wave.d.ts.map +1 -1
- package/dist/cli/handlers/run-wave.js +5 -4
- package/dist/cli/handlers/run.d.ts +4 -3
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +73 -9
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +17 -4
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +31 -0
- package/dist/cli/registry.d.ts +12 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +45 -6
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +97 -22
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +25 -10
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +24 -2
- package/dist/lifecycle/git.d.ts +11 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +62 -6
- package/dist/lifecycle/no-record.d.ts +59 -0
- package/dist/lifecycle/no-record.d.ts.map +1 -0
- package/dist/lifecycle/no-record.js +88 -0
- package/dist/op/activities/shell.d.ts.map +1 -1
- package/dist/op/activities/shell.js +30 -9
- package/dist/op/emulator-lifecycle.d.ts +23 -0
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/emulator-lifecycle.js +39 -2
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +3 -0
- package/dist/op/index.d.ts +1 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +10 -0
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +7 -2
- package/dist/op/op-waves-notify.d.ts +2 -0
- package/dist/op/op-waves-notify.d.ts.map +1 -1
- package/dist/op/op-waves-notify.js +9 -3
- package/dist/op/op-waves-run.d.ts +8 -2
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +36 -11
- package/dist/op/op-waves.d.ts +85 -1
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +153 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/runtimes/local.js +6 -0
- package/dist/op/step-console.d.ts +65 -0
- package/dist/op/step-console.d.ts.map +1 -0
- package/dist/op/step-console.js +140 -0
- package/dist/point-decision.d.ts.map +1 -1
- package/dist/point-decision.js +3 -0
- package/dist/wave-runtime.mjs +238 -238
- package/dist/workspace/compose-graph.d.ts +22 -3
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +18 -5
- package/dist/workspace/graph.schema.json +68 -1
- package/dist/workspace/nested-graph.d.ts +1 -1
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +5 -1
- package/dist/workspace/runs.d.ts.map +1 -1
- package/dist/workspace/runs.js +4 -2
- package/package.json +1 -1
- package/src/ci-jobs.ts +58 -1
- package/src/cli/commands/build.ts +18 -0
- package/src/cli/handlers/approve.ts +9 -0
- package/src/cli/handlers/emulator.test.ts +61 -1
- package/src/cli/handlers/emulator.ts +65 -4
- package/src/cli/handlers/promote.test.ts +7 -0
- package/src/cli/handlers/promote.ts +7 -1
- package/src/cli/handlers/run-no-record.e2e.test.ts +87 -0
- package/src/cli/handlers/run-wave.ts +5 -4
- package/src/cli/handlers/run.test.ts +126 -0
- package/src/cli/handlers/run.ts +69 -9
- package/src/cli/main.test.ts +24 -0
- package/src/cli/main.ts +17 -4
- package/src/cli/parse-args.ts +21 -0
- package/src/cli/registry.ts +12 -0
- package/src/components/cli-support.test.ts +75 -0
- package/src/components/cli-support.ts +130 -25
- package/src/components/driver.test.ts +28 -0
- package/src/components/driver.ts +23 -10
- package/src/components/generate-disabled.test.ts +56 -0
- package/src/graph-ci-edges.test.ts +50 -0
- package/src/graph-detail.ts +21 -2
- package/src/lifecycle/git.ts +61 -6
- package/src/lifecycle/no-record.test.ts +175 -0
- package/src/lifecycle/no-record.ts +108 -0
- package/src/op/activities/shell.ts +28 -6
- package/src/op/emulator-lifecycle.test.ts +24 -1
- package/src/op/emulator-lifecycle.ts +58 -2
- package/src/op/gate.ts +3 -0
- package/src/op/index.ts +1 -1
- package/src/op/local-executor.ts +20 -3
- package/src/op/op-waves-jobs.test.ts +213 -0
- package/src/op/op-waves-notify.ts +11 -5
- package/src/op/op-waves-run.ts +42 -11
- package/src/op/op-waves.ts +202 -2
- package/src/op/runtimes/local.ts +6 -0
- package/src/op/step-console.test.ts +150 -0
- package/src/op/step-console.ts +155 -0
- package/src/point-decision-bundle.test.ts +1 -0
- package/src/point-decision.ts +3 -0
- package/src/workspace/compose-graph.test.ts +55 -0
- package/src/workspace/compose-graph.ts +28 -6
- package/src/workspace/graph-contract.test.ts +26 -1
- package/src/workspace/graph.schema.json +68 -1
- package/src/workspace/nested-graph.test.ts +14 -0
- package/src/workspace/nested-graph.ts +7 -2
- package/src/workspace/runs.ts +4 -2
package/dist/lifecycle/git.d.ts
CHANGED
|
@@ -241,6 +241,10 @@ export type LifecyclePushStatus = {
|
|
|
241
241
|
commit: string;
|
|
242
242
|
} | {
|
|
243
243
|
status: "no-remote";
|
|
244
|
+
}
|
|
245
|
+
/** Recording is off for this process (#3955, ./no-record.ts): nothing was written to the branch, so nothing was pushed. */
|
|
246
|
+
| {
|
|
247
|
+
status: "not-recorded";
|
|
244
248
|
} | {
|
|
245
249
|
status: "stale";
|
|
246
250
|
remote: string;
|
|
@@ -578,6 +582,13 @@ export declare function fetchRef(ref: string, opts?: {
|
|
|
578
582
|
export declare function getHeadCommit(opts?: {
|
|
579
583
|
cwd?: string;
|
|
580
584
|
}): Promise<string>;
|
|
585
|
+
/**
|
|
586
|
+
* What a read names to see the ledger: `chant/lifecycle`, or, in a run that
|
|
587
|
+
* records nothing (#3955), the in-memory tip its own writes built, once it
|
|
588
|
+
* has written. Reads outside this module that name the branch themselves go
|
|
589
|
+
* through here so they see the run's writes too.
|
|
590
|
+
*/
|
|
591
|
+
export declare function ledgerRevision(cwd?: string): Promise<string>;
|
|
581
592
|
/**
|
|
582
593
|
* The branch's read side as a {@link LedgerReadPort} for the member `opts`
|
|
583
594
|
* names (#3865): what the bundle-safe readers (`./release-read.ts`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"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"}
|
package/dist/lifecycle/git.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { getRuntime } from "../runtime-adapter.js";
|
|
8
8
|
import { memberLedgerPrefix, resolveMemberLedger } from "./member-ledger.js";
|
|
9
9
|
import { LIFECYCLE_LOCAL_NOTE } from "./local-note.js";
|
|
10
|
+
import { ledgerRecordingOff, NO_RECORD_PUSH_NOTE, overlayTip, setOverlayTip } from "./no-record.js";
|
|
10
11
|
const STATE_BRANCH = "chant/lifecycle";
|
|
11
12
|
/**
|
|
12
13
|
* The branch path of `dir` for the project at `cwd` (#2538): `dir` itself at
|
|
@@ -288,6 +289,23 @@ export async function writeLedgerFiles(files, commitMessage, opts) {
|
|
|
288
289
|
// local race two concurrent writers used to hit silently (whoever called
|
|
289
290
|
// update-ref last simply overwrote the other's tree, no error). A
|
|
290
291
|
// conflict here throws RefCASConflictError instead of clobbering.
|
|
292
|
+
// #3955: a run that records nothing moves its in-memory tip instead of
|
|
293
|
+
// the branch, under the same compare-and-swap: nothing awaits between the
|
|
294
|
+
// read of the tip and the move, so two writes in this process cannot both
|
|
295
|
+
// parent on the same commit.
|
|
296
|
+
if (ledgerRecordingOff()) {
|
|
297
|
+
const key = await overlayKey(cwd);
|
|
298
|
+
const branch = overlayTip(key) === undefined ? await readRefSha(`refs/heads/${STATE_BRANCH}`, { cwd }) : null;
|
|
299
|
+
// Read again after the await: another write may have moved the tip meanwhile.
|
|
300
|
+
const moved = overlayTip(key);
|
|
301
|
+
const current = moved !== undefined ? moved : branch;
|
|
302
|
+
if (current === parentRef) {
|
|
303
|
+
setOverlayTip(key, commitSha, files.map((f) => f.path), commitMessage);
|
|
304
|
+
return commitSha;
|
|
305
|
+
}
|
|
306
|
+
lastErr = new RefCASConflictError(`refs/heads/${STATE_BRANCH}`, parentRef, `the run's unrecorded tip is ${current ?? "(none)"}`);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
291
309
|
try {
|
|
292
310
|
await updateRefCAS(`refs/heads/${STATE_BRANCH}`, commitSha, parentRef, { cwd });
|
|
293
311
|
return commitSha;
|
|
@@ -312,7 +330,7 @@ export async function writeLedgerFiles(files, commitMessage, opts) {
|
|
|
312
330
|
export async function readBlobFromPath(environment, filename, opts) {
|
|
313
331
|
const rt = getRuntime();
|
|
314
332
|
const dir = await ledgerDir(environment, opts);
|
|
315
|
-
const result = await rt.spawn(["git", "show", `${
|
|
333
|
+
const result = await rt.spawn(["git", "show", `${await ledgerRevision(opts?.cwd)}:${dir}/${filename}`], { cwd: opts?.cwd });
|
|
316
334
|
if (result.exitCode !== 0)
|
|
317
335
|
return null;
|
|
318
336
|
return result.stdout;
|
|
@@ -327,7 +345,7 @@ export async function readBlobFromPath(environment, filename, opts) {
|
|
|
327
345
|
export async function readPathSha(environment, filename, opts) {
|
|
328
346
|
const rt = getRuntime();
|
|
329
347
|
const dir = await ledgerDir(environment, opts);
|
|
330
|
-
const result = await rt.spawn(["git", "rev-parse", "--verify", `${
|
|
348
|
+
const result = await rt.spawn(["git", "rev-parse", "--verify", `${await ledgerRevision(opts?.cwd)}:${dir}/${filename}`], { cwd: opts?.cwd });
|
|
331
349
|
if (result.exitCode !== 0)
|
|
332
350
|
return null;
|
|
333
351
|
return result.stdout.trim() || null;
|
|
@@ -468,7 +486,7 @@ export async function listLedgerTrees(opts) {
|
|
|
468
486
|
const base = await ledgerDir("", opts);
|
|
469
487
|
// `--full-tree`: from a subdirectory, a bare `ls-tree` lists only that
|
|
470
488
|
// subdirectory's part of the tree (#2550).
|
|
471
|
-
const rootResult = await rt.spawn(["git", "ls-tree", "--full-tree", base === "" ?
|
|
489
|
+
const rootResult = await rt.spawn(["git", "ls-tree", "--full-tree", base === "" ? tip : `${tip}:${base}`], { cwd: opts?.cwd });
|
|
472
490
|
if (rootResult.exitCode !== 0)
|
|
473
491
|
return [];
|
|
474
492
|
const trees = [];
|
|
@@ -493,7 +511,7 @@ export async function listFilesInDir(dir, opts) {
|
|
|
493
511
|
return [];
|
|
494
512
|
const rt = getRuntime();
|
|
495
513
|
const path = await ledgerDir(dir, opts);
|
|
496
|
-
const lsResult = await rt.spawn(["git", "ls-tree", "--full-tree", "--name-only", `${
|
|
514
|
+
const lsResult = await rt.spawn(["git", "ls-tree", "--full-tree", "--name-only", `${tip}:${path}/`], { cwd: opts?.cwd });
|
|
497
515
|
if (lsResult.exitCode !== 0)
|
|
498
516
|
return [];
|
|
499
517
|
return lsResult.stdout.trim().split("\n").filter(Boolean);
|
|
@@ -506,7 +524,7 @@ export async function readEnvironmentSnapshots(environment, opts) {
|
|
|
506
524
|
const snapshots = new Map();
|
|
507
525
|
// List files in the environment directory
|
|
508
526
|
const dir = await ledgerDir(environment, opts);
|
|
509
|
-
const lsResult = await rt.spawn(["git", "ls-tree", "--full-tree", "--name-only", `${
|
|
527
|
+
const lsResult = await rt.spawn(["git", "ls-tree", "--full-tree", "--name-only", `${await ledgerRevision(opts?.cwd)}:${dir}/`], { cwd: opts?.cwd });
|
|
510
528
|
if (lsResult.exitCode !== 0)
|
|
511
529
|
return snapshots;
|
|
512
530
|
const files = lsResult.stdout.trim().split("\n").filter(Boolean);
|
|
@@ -530,7 +548,7 @@ export async function listSnapshots(opts) {
|
|
|
530
548
|
const base = await ledgerDir("", opts);
|
|
531
549
|
const result = await rt.spawn(
|
|
532
550
|
// `:(top)`: a pathspec is otherwise relative to the directory git runs in.
|
|
533
|
-
["git", "log", "--format=%H %aI %s",
|
|
551
|
+
["git", "log", "--format=%H %aI %s", await ledgerRevision(opts?.cwd), ...(base === "" ? [] : ["--", `:(top)${base}`])], { cwd: opts?.cwd });
|
|
534
552
|
if (result.exitCode !== 0)
|
|
535
553
|
return [];
|
|
536
554
|
return result.stdout
|
|
@@ -595,6 +613,8 @@ async function trackRemoteLifecycle(remote, sha, cwd) {
|
|
|
595
613
|
* is the throwing form most callers use.
|
|
596
614
|
*/
|
|
597
615
|
export async function pushLifecycleStatus(opts) {
|
|
616
|
+
if (ledgerRecordingOff())
|
|
617
|
+
return { status: "not-recorded" };
|
|
598
618
|
const rt = getRuntime();
|
|
599
619
|
const cwd = opts?.cwd;
|
|
600
620
|
const found = await ledgerRemote(cwd);
|
|
@@ -655,6 +675,8 @@ export function describeLifecyclePush(result) {
|
|
|
655
675
|
return null;
|
|
656
676
|
case "no-remote":
|
|
657
677
|
return `this repository has no remote, so ${STATE_BRANCH} stays local`;
|
|
678
|
+
case "not-recorded":
|
|
679
|
+
return NO_RECORD_PUSH_NOTE;
|
|
658
680
|
case "stale":
|
|
659
681
|
return `"${result.remote}" holds ${STATE_BRANCH} commits this checkout has not fetched, so the push was refused; fetch ${STATE_BRANCH} and write again${said(result.stderr)}`;
|
|
660
682
|
case "failed":
|
|
@@ -675,6 +697,8 @@ export async function pushLifecycleReport(opts) {
|
|
|
675
697
|
return { pushed: true };
|
|
676
698
|
case "no-remote":
|
|
677
699
|
return { pushed: false, pushWarning: LIFECYCLE_LOCAL_NOTE };
|
|
700
|
+
case "not-recorded":
|
|
701
|
+
return { pushed: false, pushWarning: NO_RECORD_PUSH_NOTE };
|
|
678
702
|
case "stale":
|
|
679
703
|
return { pushed: false, pushWarning: new StaleLifecycleBranchError(result.expected, result.stderr).message };
|
|
680
704
|
case "failed":
|
|
@@ -1039,6 +1063,10 @@ export async function pushRef(ref, opts) {
|
|
|
1039
1063
|
* `pushed`.
|
|
1040
1064
|
*/
|
|
1041
1065
|
export async function pushRefStatus(ref, opts) {
|
|
1066
|
+
// #3955: a run that records nothing pushes nothing, a lease ref included.
|
|
1067
|
+
// The lease still holds in this checkout, the way it does in one with no remote.
|
|
1068
|
+
if (ledgerRecordingOff())
|
|
1069
|
+
return "no-remote";
|
|
1042
1070
|
const rt = getRuntime();
|
|
1043
1071
|
const remoteResult = await rt.spawn(["git", "remote"], { cwd: opts?.cwd });
|
|
1044
1072
|
if (remoteResult.exitCode !== 0 || !remoteResult.stdout.trim())
|
|
@@ -1120,12 +1148,40 @@ export async function getHeadCommit(opts) {
|
|
|
1120
1148
|
return result.stdout.trim();
|
|
1121
1149
|
}
|
|
1122
1150
|
async function getStateBranchTip(cwd) {
|
|
1151
|
+
if (ledgerRecordingOff()) {
|
|
1152
|
+
const tip = overlayTip(await overlayKey(cwd));
|
|
1153
|
+
if (tip !== undefined)
|
|
1154
|
+
return tip;
|
|
1155
|
+
}
|
|
1123
1156
|
const rt = getRuntime();
|
|
1124
1157
|
const result = await rt.spawn(["git", "rev-parse", "--verify", `refs/heads/${STATE_BRANCH}`], { cwd });
|
|
1125
1158
|
if (result.exitCode !== 0)
|
|
1126
1159
|
return null;
|
|
1127
1160
|
return result.stdout.trim();
|
|
1128
1161
|
}
|
|
1162
|
+
/**
|
|
1163
|
+
* What a read names to see the ledger: `chant/lifecycle`, or, in a run that
|
|
1164
|
+
* records nothing (#3955), the in-memory tip its own writes built, once it
|
|
1165
|
+
* has written. Reads outside this module that name the branch themselves go
|
|
1166
|
+
* through here so they see the run's writes too.
|
|
1167
|
+
*/
|
|
1168
|
+
export async function ledgerRevision(cwd) {
|
|
1169
|
+
if (!ledgerRecordingOff())
|
|
1170
|
+
return STATE_BRANCH;
|
|
1171
|
+
return overlayTip(await overlayKey(cwd)) ?? STATE_BRANCH;
|
|
1172
|
+
}
|
|
1173
|
+
/** The repository a run's in-memory ledger tip belongs to (#3955): its common git directory, so worktrees and members share one. */
|
|
1174
|
+
const overlayKeys = new Map();
|
|
1175
|
+
async function overlayKey(cwd) {
|
|
1176
|
+
const from = cwd ?? process.cwd();
|
|
1177
|
+
const cached = overlayKeys.get(from);
|
|
1178
|
+
if (cached !== undefined)
|
|
1179
|
+
return cached;
|
|
1180
|
+
const result = await getRuntime().spawn(["git", "rev-parse", "--path-format=absolute", "--git-common-dir"], { cwd: from, env: C_LOCALE_ENV });
|
|
1181
|
+
const key = result.exitCode === 0 && result.stdout.trim() !== "" ? result.stdout.trim() : from;
|
|
1182
|
+
overlayKeys.set(from, key);
|
|
1183
|
+
return key;
|
|
1184
|
+
}
|
|
1129
1185
|
/**
|
|
1130
1186
|
* The entries of directory `dir` (branch-relative, `""` for the root) in
|
|
1131
1187
|
* commit `tip`, or an empty map when it does not exist. Always pinned to the
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A run that records nothing on `chant/lifecycle` (#3955): `chant run
|
|
3
|
+
* --no-record`, or `CHANT_NO_RECORD=1` in the environment.
|
|
4
|
+
*
|
|
5
|
+
* Test and claim runs used to leave real records on the ledger and push them
|
|
6
|
+
* to origin, because every write path in `./git.ts` appends and pushes. In
|
|
7
|
+
* this mode the run still executes every step, and every ledger write still
|
|
8
|
+
* builds its commit, but the commit goes onto an in-memory tip instead of the
|
|
9
|
+
* branch ref:
|
|
10
|
+
*
|
|
11
|
+
* - `refs/heads/chant/lifecycle` is never updated, so the branch is exactly
|
|
12
|
+
* what it was before the run.
|
|
13
|
+
* - Nothing is pushed: neither the ledger branch nor a lease ref.
|
|
14
|
+
* - Reads in the same process see the run's own writes, so a step that reads
|
|
15
|
+
* back what an earlier step wrote (an effect receipt, a work lease) behaves
|
|
16
|
+
* as it would in a recorded run. The tip is dropped when the process exits.
|
|
17
|
+
*
|
|
18
|
+
* A gate cannot be passed in this mode ({@link GateNotRecordableError}). An
|
|
19
|
+
* approval lives on the ledger, and passing a gate spends it: a run that
|
|
20
|
+
* passed a gate here would apply under an approval while leaving it unspent
|
|
21
|
+
* for the next run, and a pending fact it wrote could never be approved.
|
|
22
|
+
*
|
|
23
|
+
* The state is per process and keyed by the repository's git directory, so a
|
|
24
|
+
* workspace member and the root share one tip. A child `chant` process gets
|
|
25
|
+
* the mode through the environment and keeps its own tip.
|
|
26
|
+
*
|
|
27
|
+
* Kept free of git and the runtime adapter so the gate deciders and the run
|
|
28
|
+
* renderers can import it without loading `./git.ts`.
|
|
29
|
+
*/
|
|
30
|
+
/** The environment variable that turns recording off for every chant process that inherits it. */
|
|
31
|
+
export declare const NO_RECORD_ENV = "CHANT_NO_RECORD";
|
|
32
|
+
/** Whether this process records nothing on `chant/lifecycle`: `CHANT_NO_RECORD` set to anything but empty, `0` or `false`. */
|
|
33
|
+
export declare function ledgerRecordingOff(env?: NodeJS.ProcessEnv): boolean;
|
|
34
|
+
/** The line a run prints before its first step when it records nothing. `source` is what turned recording off. */
|
|
35
|
+
export declare function noRecordStartNote(source: string): string;
|
|
36
|
+
/** The push warning a ledger write reports in this mode, in place of a push. */
|
|
37
|
+
export declare const NO_RECORD_PUSH_NOTE = "not recorded (--no-record): chant/lifecycle was not written or pushed";
|
|
38
|
+
/** The tip this process's writes have built for the repository at `key`, or `undefined` before its first write. */
|
|
39
|
+
export declare function overlayTip(key: string): string | null | undefined;
|
|
40
|
+
/** Move the in-memory tip for `key` to `commit`, noting what the commit wrote. */
|
|
41
|
+
export declare function setOverlayTip(key: string, commit: string, paths: readonly string[], message: string): void;
|
|
42
|
+
/** Every ledger file this process wrote and did not record, in write order, across repositories. */
|
|
43
|
+
export declare function unrecordedWrites(): {
|
|
44
|
+
path: string;
|
|
45
|
+
message: string;
|
|
46
|
+
}[];
|
|
47
|
+
/** The line a run prints after its last step: that nothing was recorded, and how many ledger writes it dropped. */
|
|
48
|
+
export declare function noRecordEndNote(source: string): string;
|
|
49
|
+
/** Forget every in-memory tip. For tests, and for an in-process caller that runs twice. */
|
|
50
|
+
export declare function resetNoRecordLedger(): void;
|
|
51
|
+
/** Thrown when a run that records nothing reaches a gate. The executor turns it into a failing gate step. */
|
|
52
|
+
export declare class GateNotRecordableError extends Error {
|
|
53
|
+
readonly op: string;
|
|
54
|
+
readonly gate: string;
|
|
55
|
+
constructor(op: string, gate: string);
|
|
56
|
+
}
|
|
57
|
+
/** Throw {@link GateNotRecordableError} when recording is off. Called by every gate decider before it reads the ledger. */
|
|
58
|
+
export declare function refuseGateWithoutRecording(op: string, gate: string): void;
|
|
59
|
+
//# sourceMappingURL=no-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-record.d.ts","sourceRoot":"","sources":["../../src/lifecycle/no-record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,kGAAkG;AAClG,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C,8HAA8H;AAC9H,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAGhF;AAED,kHAAkH;AAClH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,0EAA0E,CAAC;AAU3G,mHAAmH;AACnH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAEjE;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK1G;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAEtE;AAED,mHAAmH;AACnH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,6GAA6G;AAC7G,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,EAAE,EAAE,MAAM;aACV,IAAI,EAAE,MAAM;IAF9B,YACkB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EAQ7B;CACF;AAED,2HAA2H;AAC3H,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEzE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A run that records nothing on `chant/lifecycle` (#3955): `chant run
|
|
3
|
+
* --no-record`, or `CHANT_NO_RECORD=1` in the environment.
|
|
4
|
+
*
|
|
5
|
+
* Test and claim runs used to leave real records on the ledger and push them
|
|
6
|
+
* to origin, because every write path in `./git.ts` appends and pushes. In
|
|
7
|
+
* this mode the run still executes every step, and every ledger write still
|
|
8
|
+
* builds its commit, but the commit goes onto an in-memory tip instead of the
|
|
9
|
+
* branch ref:
|
|
10
|
+
*
|
|
11
|
+
* - `refs/heads/chant/lifecycle` is never updated, so the branch is exactly
|
|
12
|
+
* what it was before the run.
|
|
13
|
+
* - Nothing is pushed: neither the ledger branch nor a lease ref.
|
|
14
|
+
* - Reads in the same process see the run's own writes, so a step that reads
|
|
15
|
+
* back what an earlier step wrote (an effect receipt, a work lease) behaves
|
|
16
|
+
* as it would in a recorded run. The tip is dropped when the process exits.
|
|
17
|
+
*
|
|
18
|
+
* A gate cannot be passed in this mode ({@link GateNotRecordableError}). An
|
|
19
|
+
* approval lives on the ledger, and passing a gate spends it: a run that
|
|
20
|
+
* passed a gate here would apply under an approval while leaving it unspent
|
|
21
|
+
* for the next run, and a pending fact it wrote could never be approved.
|
|
22
|
+
*
|
|
23
|
+
* The state is per process and keyed by the repository's git directory, so a
|
|
24
|
+
* workspace member and the root share one tip. A child `chant` process gets
|
|
25
|
+
* the mode through the environment and keeps its own tip.
|
|
26
|
+
*
|
|
27
|
+
* Kept free of git and the runtime adapter so the gate deciders and the run
|
|
28
|
+
* renderers can import it without loading `./git.ts`.
|
|
29
|
+
*/
|
|
30
|
+
/** The environment variable that turns recording off for every chant process that inherits it. */
|
|
31
|
+
export const NO_RECORD_ENV = "CHANT_NO_RECORD";
|
|
32
|
+
/** Whether this process records nothing on `chant/lifecycle`: `CHANT_NO_RECORD` set to anything but empty, `0` or `false`. */
|
|
33
|
+
export function ledgerRecordingOff(env = process.env) {
|
|
34
|
+
const value = env[NO_RECORD_ENV]?.trim().toLowerCase();
|
|
35
|
+
return value !== undefined && value !== "" && value !== "0" && value !== "false";
|
|
36
|
+
}
|
|
37
|
+
/** The line a run prints before its first step when it records nothing. `source` is what turned recording off. */
|
|
38
|
+
export function noRecordStartNote(source) {
|
|
39
|
+
return `not recording (${source}): nothing this run writes goes on chant/lifecycle, and nothing is pushed. A gate step fails.`;
|
|
40
|
+
}
|
|
41
|
+
/** The push warning a ledger write reports in this mode, in place of a push. */
|
|
42
|
+
export const NO_RECORD_PUSH_NOTE = "not recorded (--no-record): chant/lifecycle was not written or pushed";
|
|
43
|
+
const overlays = new Map();
|
|
44
|
+
/** The tip this process's writes have built for the repository at `key`, or `undefined` before its first write. */
|
|
45
|
+
export function overlayTip(key) {
|
|
46
|
+
return overlays.get(key)?.tip;
|
|
47
|
+
}
|
|
48
|
+
/** Move the in-memory tip for `key` to `commit`, noting what the commit wrote. */
|
|
49
|
+
export function setOverlayTip(key, commit, paths, message) {
|
|
50
|
+
const overlay = overlays.get(key) ?? { tip: null, writes: [] };
|
|
51
|
+
overlay.tip = commit;
|
|
52
|
+
for (const path of paths)
|
|
53
|
+
overlay.writes.push({ path, message });
|
|
54
|
+
overlays.set(key, overlay);
|
|
55
|
+
}
|
|
56
|
+
/** Every ledger file this process wrote and did not record, in write order, across repositories. */
|
|
57
|
+
export function unrecordedWrites() {
|
|
58
|
+
return [...overlays.values()].flatMap((o) => o.writes);
|
|
59
|
+
}
|
|
60
|
+
/** The line a run prints after its last step: that nothing was recorded, and how many ledger writes it dropped. */
|
|
61
|
+
export function noRecordEndNote(source) {
|
|
62
|
+
const writes = unrecordedWrites();
|
|
63
|
+
const files = new Set(writes.map((w) => w.path)).size;
|
|
64
|
+
const dropped = writes.length === 0
|
|
65
|
+
? "the run made no ledger writes"
|
|
66
|
+
: `${writes.length} ledger write${writes.length === 1 ? " was" : "s were"} dropped (${files} file${files === 1 ? "" : "s"})`;
|
|
67
|
+
return `not recorded (${source}): nothing went on chant/lifecycle and nothing was pushed; ${dropped}.`;
|
|
68
|
+
}
|
|
69
|
+
/** Forget every in-memory tip. For tests, and for an in-process caller that runs twice. */
|
|
70
|
+
export function resetNoRecordLedger() {
|
|
71
|
+
overlays.clear();
|
|
72
|
+
}
|
|
73
|
+
/** Thrown when a run that records nothing reaches a gate. The executor turns it into a failing gate step. */
|
|
74
|
+
export class GateNotRecordableError extends Error {
|
|
75
|
+
constructor(op, gate) {
|
|
76
|
+
super(`gate "${gate}" of "${op}" cannot be passed under --no-record: a gate is decided and approved on ` +
|
|
77
|
+
"chant/lifecycle, which this run does not write. " +
|
|
78
|
+
"Run without --no-record (and without CHANT_NO_RECORD) to stop at the gate for approval.");
|
|
79
|
+
this.op = op;
|
|
80
|
+
this.gate = gate;
|
|
81
|
+
this.name = "GateNotRecordableError";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Throw {@link GateNotRecordableError} when recording is off. Called by every gate decider before it reads the ledger. */
|
|
85
|
+
export function refuseGateWithoutRecording(op, gate) {
|
|
86
|
+
if (ledgerRecordingOff())
|
|
87
|
+
throw new GateNotRecordableError(op, gate);
|
|
88
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/op/activities/shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/op/activities/shell.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAgBD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAuBD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CA0DhG"}
|
|
@@ -2,6 +2,7 @@ import { exec } from "node:child_process";
|
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
3
|
import { GateWait, asPendingGate } from "../gate-wait.js";
|
|
4
4
|
import { liveRunEnv } from "../run-live.js";
|
|
5
|
+
import { hasStepConsole, stepLineSplitter } from "../step-console.js";
|
|
5
6
|
const execAsync = promisify(exec);
|
|
6
7
|
/**
|
|
7
8
|
* How much stdout a command may produce, matching every other exec site in
|
|
@@ -38,8 +39,18 @@ function withJson(result, args) {
|
|
|
38
39
|
*/
|
|
39
40
|
export async function shellCmd(args, signal) {
|
|
40
41
|
const okExit = args.okExit ?? [0];
|
|
42
|
+
// #3956: under a step console (../step-console.ts) every line the command
|
|
43
|
+
// writes, stdout and stderr, is printed as it arrives; the result still
|
|
44
|
+
// carries both whole. Without one, stderr is printed when the command ends.
|
|
45
|
+
const streamed = hasStepConsole();
|
|
46
|
+
const printStderr = (text) => {
|
|
47
|
+
if (text && !streamed)
|
|
48
|
+
console.error(text);
|
|
49
|
+
};
|
|
50
|
+
const out = stepLineSplitter();
|
|
51
|
+
const err = stepLineSplitter();
|
|
41
52
|
try {
|
|
42
|
-
const
|
|
53
|
+
const running = execAsync(args.cmd, {
|
|
43
54
|
cwd: args.cwd,
|
|
44
55
|
// In a run that keeps an in-flight record, CHANT_RUN_ACTIVITY names the
|
|
45
56
|
// file the command appends activity lines to (../run-live.ts).
|
|
@@ -47,12 +58,24 @@ export async function shellCmd(args, signal) {
|
|
|
47
58
|
maxBuffer: MAX_STDOUT_BYTES,
|
|
48
59
|
signal,
|
|
49
60
|
});
|
|
50
|
-
if (
|
|
51
|
-
|
|
61
|
+
if (streamed) {
|
|
62
|
+
running.child.stdout?.on("data", (chunk) => out.push(chunk));
|
|
63
|
+
running.child.stderr?.on("data", (chunk) => err.push(chunk));
|
|
64
|
+
}
|
|
65
|
+
let settled;
|
|
66
|
+
try {
|
|
67
|
+
settled = await running;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
out.end();
|
|
71
|
+
err.end();
|
|
72
|
+
}
|
|
73
|
+
const { stdout, stderr } = settled;
|
|
74
|
+
printStderr(stderr);
|
|
52
75
|
return withJson({ stdout: stdout.trim(), stderr: stderr.trim(), exitCode: 0 }, args);
|
|
53
76
|
}
|
|
54
|
-
catch (
|
|
55
|
-
const failure =
|
|
77
|
+
catch (caught) {
|
|
78
|
+
const failure = caught;
|
|
56
79
|
const exitCode = typeof failure.code === "number" ? failure.code : undefined;
|
|
57
80
|
// A signal kill (Ctrl-C, the profile's timeout, a maxBuffer overflow) is
|
|
58
81
|
// not an exit status the author declared anything about, so it rethrows
|
|
@@ -60,14 +83,12 @@ export async function shellCmd(args, signal) {
|
|
|
60
83
|
const died = failure.killed === true || typeof failure.signal === "string" || signal?.aborted === true;
|
|
61
84
|
if (exitCode !== undefined && !died && args.gatedExit !== undefined && exitCode === args.gatedExit) {
|
|
62
85
|
const stderrText = (failure.stderr ?? "").trim();
|
|
63
|
-
|
|
64
|
-
console.error(stderrText);
|
|
86
|
+
printStderr(stderrText);
|
|
65
87
|
throw new GateWait(await commandGate(args, (failure.stdout ?? "").trim(), exitCode));
|
|
66
88
|
}
|
|
67
89
|
if (exitCode !== undefined && !died && okExit.includes(exitCode)) {
|
|
68
90
|
const stderrText = (failure.stderr ?? "").trim();
|
|
69
|
-
|
|
70
|
-
console.error(stderrText);
|
|
91
|
+
printStderr(stderrText);
|
|
71
92
|
return withJson({ stdout: (failure.stdout ?? "").trim(), stderr: stderrText, exitCode }, args);
|
|
72
93
|
}
|
|
73
94
|
if (exitCode !== undefined && !died) {
|
|
@@ -33,6 +33,13 @@ export interface EmulatorSpec {
|
|
|
33
33
|
ready?: (healthBody: string) => boolean;
|
|
34
34
|
/** Extra `docker run` args inserted before the image (e.g. a socket mount). */
|
|
35
35
|
runArgs?: readonly string[];
|
|
36
|
+
/**
|
|
37
|
+
* The prefix every key of {@link EmulatorUpArgs.settings} must start with,
|
|
38
|
+
* e.g. `FLOCI_` (#3952). Settings reach the container as `-e KEY=VALUE`, and
|
|
39
|
+
* the prefix keeps them to the emulator's own configuration instead of
|
|
40
|
+
* arbitrary env. An emulator without one takes no settings.
|
|
41
|
+
*/
|
|
42
|
+
settingsPrefix?: string;
|
|
36
43
|
/**
|
|
37
44
|
* Where {@link image} is published, so how far behind the pin is can be
|
|
38
45
|
* answered (#1345).
|
|
@@ -168,7 +175,23 @@ export interface EmulatorUpArgs {
|
|
|
168
175
|
intervalMs?: number;
|
|
169
176
|
/** Additional `docker run` args for this call (after `spec.runArgs`, before the image). */
|
|
170
177
|
extraArgs?: readonly string[];
|
|
178
|
+
/** Docker network the container joins (`--network <name>`) (#3952). */
|
|
179
|
+
network?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Emulator settings passed as `-e KEY=VALUE` (#3952). Every key must start
|
|
182
|
+
* with the spec's {@link EmulatorSpec.settingsPrefix}; see {@link checkSettings}.
|
|
183
|
+
*/
|
|
184
|
+
settings?: Record<string, string>;
|
|
185
|
+
/** Publish the port on 127.0.0.1 only, instead of every host interface (#3952). */
|
|
186
|
+
loopback?: boolean;
|
|
171
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Refuse settings an emulator does not take (#3952): a key outside the spec's
|
|
190
|
+
* {@link EmulatorSpec.settingsPrefix}, a key that is not an env-var name, or
|
|
191
|
+
* any setting at all for an emulator that declares no prefix. Throws with the
|
|
192
|
+
* first problem found.
|
|
193
|
+
*/
|
|
194
|
+
export declare function checkSettings(spec: EmulatorSpec, settings: Record<string, string> | undefined): void;
|
|
172
195
|
/** The shared lifecycle a per-cloud wrapper adapts. */
|
|
173
196
|
export interface EmulatorLifecycle {
|
|
174
197
|
runCommand(args?: EmulatorUpArgs): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emulator-lifecycle.d.ts","sourceRoot":"","sources":["../../src/op/emulator-lifecycle.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"emulator-lifecycle.d.ts","sourceRoot":"","sources":["../../src/op/emulator-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -122,6 +122,33 @@ export function endpointEnvVars(capability) {
|
|
|
122
122
|
.filter(([, value]) => value === ENDPOINT_PROBE)
|
|
123
123
|
.map(([key]) => key);
|
|
124
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Refuse settings an emulator does not take (#3952): a key outside the spec's
|
|
127
|
+
* {@link EmulatorSpec.settingsPrefix}, a key that is not an env-var name, or
|
|
128
|
+
* any setting at all for an emulator that declares no prefix. Throws with the
|
|
129
|
+
* first problem found.
|
|
130
|
+
*/
|
|
131
|
+
export function checkSettings(spec, settings) {
|
|
132
|
+
const keys = Object.keys(settings ?? {});
|
|
133
|
+
if (keys.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
const prefix = spec.settingsPrefix;
|
|
136
|
+
if (!prefix) {
|
|
137
|
+
throw new Error(`emulator "${spec.name}" takes no settings; got ${keys.join(", ")}`);
|
|
138
|
+
}
|
|
139
|
+
for (const key of keys) {
|
|
140
|
+
if (!key.startsWith(prefix) || key.length === prefix.length || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
141
|
+
throw new Error(`emulator "${spec.name}": setting ${key} is not a ${prefix}* variable; only ${prefix}<NAME> keys reach the container`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Quote one `docker run` word for the shell `up` runs it through: a setting's
|
|
147
|
+
* value or a network name can hold spaces or shell syntax.
|
|
148
|
+
*/
|
|
149
|
+
function shellWord(word) {
|
|
150
|
+
return /^[A-Za-z0-9_@%+=:,./-]+$/.test(word) ? word : `'${word.replace(/'/g, `'\\''`)}'`;
|
|
151
|
+
}
|
|
125
152
|
/**
|
|
126
153
|
* Build a Docker-lifecycle for a local emulator: an idempotent `up` (reuse a
|
|
127
154
|
* running container, else `docker run`, then poll health until ready), a `down`
|
|
@@ -138,10 +165,14 @@ export function emulatorLifecycle(spec) {
|
|
|
138
165
|
const name = args.name ?? spec.name;
|
|
139
166
|
const port = args.port ?? spec.containerPort;
|
|
140
167
|
const image = args.image ?? spec.image;
|
|
168
|
+
checkSettings(spec, args.settings);
|
|
169
|
+
const bind = args.loopback ? `127.0.0.1:${port}:${spec.containerPort}` : `${port}:${spec.containerPort}`;
|
|
141
170
|
return [
|
|
142
|
-
"docker", "run", "-d", "--rm", "--name", name, "-p",
|
|
171
|
+
"docker", "run", "-d", "--rm", "--name", name, "-p", bind,
|
|
172
|
+
...(args.network ? ["--network", args.network] : []),
|
|
173
|
+
...Object.entries(args.settings ?? {}).flatMap(([k, v]) => ["-e", `${k}=${v}`]),
|
|
143
174
|
...(spec.runArgs ?? []), ...(args.extraArgs ?? []), image,
|
|
144
|
-
].join(" ");
|
|
175
|
+
].map(shellWord).join(" ");
|
|
145
176
|
};
|
|
146
177
|
const existsCommand = (name) => `docker ps -q -f name=${name}`;
|
|
147
178
|
const rmCommand = (name) => `docker rm -f ${name}`;
|
|
@@ -174,6 +205,8 @@ export function emulatorLifecycle(spec) {
|
|
|
174
205
|
const port = args.port ?? spec.containerPort;
|
|
175
206
|
const timeoutMs = args.timeoutMs ?? 60000;
|
|
176
207
|
const intervalMs = args.intervalMs ?? 2000;
|
|
208
|
+
// Before the reuse check, so a bad key is refused whether or not a container runs.
|
|
209
|
+
checkSettings(spec, args.settings);
|
|
177
210
|
let running = false;
|
|
178
211
|
try {
|
|
179
212
|
const { stdout } = await execAsync(existsCommand(name), { signal });
|
|
@@ -189,6 +222,10 @@ export function emulatorLifecycle(spec) {
|
|
|
189
222
|
// Progress → stderr, so a `--json` consumer (chant emulator, behold) reads
|
|
190
223
|
// clean JSON on stdout. runOp/Op activities capture both streams regardless.
|
|
191
224
|
console.error(`emulator container "${name}" already running — reusing`);
|
|
225
|
+
if (args.image || args.network || args.loopback || Object.keys(args.settings ?? {}).length) {
|
|
226
|
+
console.error(`emulator "${name}": the image, network, settings and loopback options apply when a container starts, not to this running one. ` +
|
|
227
|
+
`Run \`chant emulator down\` first to start it with them.`);
|
|
228
|
+
}
|
|
192
229
|
let published = [];
|
|
193
230
|
try {
|
|
194
231
|
const { stdout } = await execFileAsync("docker", ["port", name, `${spec.containerPort}/tcp`], { signal });
|
package/dist/op/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/op/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EASL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAA2D,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE5H,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/op/gate.ts"],"names":[],"mappings":"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"}
|
package/dist/op/gate.js
CHANGED
|
@@ -40,6 +40,7 @@ import { gateContextDigest } from "./gate-approval.js";
|
|
|
40
40
|
import { pushLifecycleReport, readBlobBySha, readBlobFromPath, readPathSha, requireLifecycleLedger, writeBlobToPath, RefCASConflictError } from "../lifecycle/git.js";
|
|
41
41
|
import { parseDuration } from "./duration.js";
|
|
42
42
|
import { resolveGateRunLocator } from "./gate-run-locator.js";
|
|
43
|
+
import { refuseGateWithoutRecording } from "../lifecycle/no-record.js";
|
|
43
44
|
/**
|
|
44
45
|
* The real port: the `chant/lifecycle` orphan branch.
|
|
45
46
|
*
|
|
@@ -307,6 +308,8 @@ const EPOCH = new Date(0).toISOString();
|
|
|
307
308
|
* recorded" from "still standing".
|
|
308
309
|
*/
|
|
309
310
|
export async function evaluateGate(port, input) {
|
|
311
|
+
// #3955: a run that records nothing cannot be approved or spend an approval.
|
|
312
|
+
refuseGateWithoutRecording(input.op, input.gate);
|
|
310
313
|
const now = input.now ?? new Date().toISOString();
|
|
311
314
|
const ledger = await port.read(input.op);
|
|
312
315
|
// #2574: a component's ledger holds every environment's facts. This run
|