@norskvideo/ctl-test-harness 0.1.36 → 0.1.38
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/demo/dev-loop.js +12 -1
- package/demo/run.js +13 -2
- package/package.json +1 -1
- package/root-nuke.d.ts +8 -3
- package/root-nuke.js +11 -4
package/demo/dev-loop.js
CHANGED
|
@@ -199,7 +199,18 @@ export async function devLoopDown(product, deps = defaultDemoDeps(process.cwd())
|
|
|
199
199
|
}
|
|
200
200
|
if (state.devPid !== undefined)
|
|
201
201
|
deps.killPid?.(state.devPid);
|
|
202
|
-
|
|
202
|
+
// Never let the nuke strand the state record: it sits one line before
|
|
203
|
+
// state.remove, and the containment guard throws for a store outside THIS
|
|
204
|
+
// process's temp base -- which is a cross-process fact (the `up` shell's
|
|
205
|
+
// NORSK_CTL_TEST_TMP need not be the `down` shell's), not a bug in the run
|
|
206
|
+
// being torn down. Refusing to delete it is right; failing to forget it
|
|
207
|
+
// means `down` breaks identically on every retry.
|
|
208
|
+
try {
|
|
209
|
+
deps.nukeStoreAsRoot(state.storeDir);
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
deps.log(`nuke skipped: ${e instanceof Error ? e.message : String(e)}`);
|
|
213
|
+
}
|
|
203
214
|
deps.state.remove(product, "dev-loop");
|
|
204
215
|
deps.log(`${product} dev-loop torn down (the workdir ${state.workdir ?? ""} is untouched)`);
|
|
205
216
|
}
|
package/demo/run.js
CHANGED
|
@@ -733,8 +733,19 @@ export async function demoDown(product, deps = defaultDemoDeps(process.cwd())) {
|
|
|
733
733
|
deps.docker(["rm", "-f", name]);
|
|
734
734
|
if (state.devPid !== undefined)
|
|
735
735
|
deps.killPid?.(state.devPid);
|
|
736
|
-
|
|
737
|
-
|
|
736
|
+
// Never let the nuke strand the state record: it sits one line before
|
|
737
|
+
// state.remove, and the containment guard throws for a store outside THIS
|
|
738
|
+
// process's temp base -- which is a cross-process fact (the `up` shell's
|
|
739
|
+
// NORSK_CTL_TEST_TMP need not be the `down` shell's), not a bug in the run
|
|
740
|
+
// being torn down. Refusing to delete it is right; failing to forget it
|
|
741
|
+
// means `down` breaks identically on every retry.
|
|
742
|
+
try {
|
|
743
|
+
if (state.daemon !== "reuse")
|
|
744
|
+
deps.nukeStoreAsRoot(state.storeDir);
|
|
745
|
+
}
|
|
746
|
+
catch (e) {
|
|
747
|
+
deps.log(`nuke skipped: ${e instanceof Error ? e.message : String(e)}`);
|
|
748
|
+
}
|
|
738
749
|
deps.state.remove(product);
|
|
739
750
|
deps.log(`${product} demo torn down${state.daemon === "reuse" ? " (your daemon and its registration are untouched)" : ""}`);
|
|
740
751
|
}
|
package/package.json
CHANGED
package/root-nuke.d.ts
CHANGED
|
@@ -27,9 +27,14 @@ export declare function assertNukeTarget(target: string, allowedBase: string): v
|
|
|
27
27
|
* directory called `x; rm -rf /base` would otherwise wipe every sibling --
|
|
28
28
|
* including a live sibling run -- from inside a root container. */
|
|
29
29
|
export declare function nukeArgv(target: string): string[];
|
|
30
|
-
/** Remove `target` as root. Returns whether the nuke actually
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
/** Remove `target` as root. Returns whether the nuke actually SUCCEEDED.
|
|
31
|
+
*
|
|
32
|
+
* Both halves matter. `spawnSync` reports a missing docker in its RESULT
|
|
33
|
+
* rather than throwing, and a docker that is present but failing -- daemon
|
|
34
|
+
* stopped, image unpullable, mount refused -- reports only a non-zero status
|
|
35
|
+
* with no `error` at all. Reading `error` alone calls that a success, so a
|
|
36
|
+
* caller latching on the return value never latches and re-spawns a doomed
|
|
37
|
+
* 60-second docker on every attempt, forever and silently.
|
|
33
38
|
* Throws only for an unsafe target -- see {@link assertNukeTarget}. */
|
|
34
39
|
export declare function nukePathAsRoot(target: string, allowedBase: string, spawn?: NukeSpawn): boolean;
|
|
35
40
|
export interface OwnerScanDeps {
|
package/root-nuke.js
CHANGED
|
@@ -72,14 +72,21 @@ export function nukeArgv(target) {
|
|
|
72
72
|
basename(target),
|
|
73
73
|
];
|
|
74
74
|
}
|
|
75
|
-
/** Remove `target` as root. Returns whether the nuke actually
|
|
76
|
-
*
|
|
77
|
-
*
|
|
75
|
+
/** Remove `target` as root. Returns whether the nuke actually SUCCEEDED.
|
|
76
|
+
*
|
|
77
|
+
* Both halves matter. `spawnSync` reports a missing docker in its RESULT
|
|
78
|
+
* rather than throwing, and a docker that is present but failing -- daemon
|
|
79
|
+
* stopped, image unpullable, mount refused -- reports only a non-zero status
|
|
80
|
+
* with no `error` at all. Reading `error` alone calls that a success, so a
|
|
81
|
+
* caller latching on the return value never latches and re-spawns a doomed
|
|
82
|
+
* 60-second docker on every attempt, forever and silently.
|
|
78
83
|
* Throws only for an unsafe target -- see {@link assertNukeTarget}. */
|
|
79
84
|
export function nukePathAsRoot(target, allowedBase, spawn = spawnSync) {
|
|
80
85
|
assertNukeTarget(target, allowedBase);
|
|
81
86
|
const r = spawn("docker", nukeArgv(target), { timeout: NUKE_TIMEOUT_MS });
|
|
82
|
-
|
|
87
|
+
if (r?.error)
|
|
88
|
+
return false;
|
|
89
|
+
return r?.status === 0 || r?.status === undefined;
|
|
83
90
|
}
|
|
84
91
|
/** Paths under `dir` owned by a uid that is not `selfUid`, with the owning uid.
|
|
85
92
|
*
|