@feigi/fleet-ctl 3.23.26 → 3.23.28
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/package.json
CHANGED
package/scripts/recipe-prove.mjs
CHANGED
|
@@ -57,10 +57,11 @@
|
|
|
57
57
|
// repository, origin/main missing, the worktree could not be made), or
|
|
58
58
|
// a git or filesystem fault stopped it before the cache was settled
|
|
59
59
|
// (a git command could not be started, the reader's own git
|
|
60
|
-
// included; the reader's `sh`,
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// could not be written). The log
|
|
60
|
+
// included, or that git started and could not run; the reader's `sh`,
|
|
61
|
+
// `node`, `mktemp` or `cat` could not be started, or its `node` died
|
|
62
|
+
// mid-read — a `cat` that ran and failed stays the reader's refusal,
|
|
63
|
+
// exit 1; the cache or its temp file could not be written). The log
|
|
64
|
+
// directory under $TMPDIR is removed.
|
|
64
65
|
|
|
65
66
|
import { spawnSync } from "node:child_process";
|
|
66
67
|
import { closeSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
@@ -287,9 +288,12 @@ function prove(o, wt, logs) {
|
|
|
287
288
|
// cache is undone just the same when the read-back is no verdict: an `sh` that
|
|
288
289
|
// could not be started read nothing; a reader that exits READER_COULD_NOT_RUN
|
|
289
290
|
// could not start its `node`, `mktemp` or `cat`, or lost its `node` mid-read;
|
|
290
|
-
// and the reader runs git itself and reads a git that will not
|
|
291
|
+
// and the reader runs git itself and reads a git that will not run as no
|
|
291
292
|
// repository at all, so its refusal is a verdict on what was proven only while
|
|
292
|
-
// git still
|
|
293
|
+
// git still runs. `git --version` is the probe: a working git always passes
|
|
294
|
+
// it, so a git that cannot be started fails it, and so does one that starts
|
|
295
|
+
// and cannot run — a wrapper whose target is gone exits 126 or 127, a killed
|
|
296
|
+
// git has no exit status at all.
|
|
293
297
|
function writeCache(cache, recipe, repo) {
|
|
294
298
|
mkdirSync(dirname(cache), { recursive: true });
|
|
295
299
|
const prior = existsSync(cache) ? readFileSync(cache) : null;
|
|
@@ -308,12 +312,15 @@ function writeCache(cache, recipe, repo) {
|
|
|
308
312
|
else writeFileSync(cache, prior);
|
|
309
313
|
if (r.error && !r.pid) throw cannot(`could not start sh to read the Recipe cache back: ${r.error.message}`);
|
|
310
314
|
if (r.status === READER_COULD_NOT_RUN) throw cannot(`${r.stderr.trim()} — the Recipe cache reader could not run a tool it needs, so its refusal is no verdict on what was proven`);
|
|
315
|
+
const noVerdict = (why) => cannot(`${why} — the Recipe cache reader runs git, so its refusal is no verdict on what was proven`);
|
|
316
|
+
let probe;
|
|
311
317
|
try {
|
|
312
|
-
git(["--version"]);
|
|
318
|
+
probe = git(["--version"]);
|
|
313
319
|
} catch (e) {
|
|
314
320
|
if (!(e instanceof Refusal)) throw e;
|
|
315
|
-
throw
|
|
321
|
+
throw noVerdict(e.message);
|
|
316
322
|
}
|
|
323
|
+
if (!probe.ok) throw noVerdict(`git started but does not run: \`git --version\` did not exit 0${probe.err ? `: ${probe.err}` : " and wrote nothing to stderr"}`);
|
|
317
324
|
throw notProven(`the Recipe cache reader refuses what was proven: ${(r.stderr || r.stdout).trim()}`);
|
|
318
325
|
}
|
|
319
326
|
}
|
|
@@ -665,6 +665,35 @@ test("a git that stops starting before the cache is read back is no verdict, nev
|
|
|
665
665
|
assert.equal(readFileSync(cachePath(dir), "utf8"), "prior bytes", "a cache the reader never settled is rolled back");
|
|
666
666
|
});
|
|
667
667
|
|
|
668
|
+
// A git that starts and cannot run fails the reader's own `git rev-parse` just
|
|
669
|
+
// as a git that will not start does, so its refusal is no verdict either. Each
|
|
670
|
+
// stub stands in for one such git: a wrapper whose target is gone exits 126 or
|
|
671
|
+
// 127, and a killed git has no exit status at all. The stubs differ in what
|
|
672
|
+
// they write to stderr, which the message quotes when there is anything to
|
|
673
|
+
// quote. The control — the same PATH with git left in place proves — is the
|
|
674
|
+
// unstartable-git test's. The Test entrypoint rewrites the stub's body, never
|
|
675
|
+
// the stub: that is a hard link to exec-stub.mjs's shared, read-only
|
|
676
|
+
// trampoline.
|
|
677
|
+
const GIT_THAT_CANNOT_RUN = [
|
|
678
|
+
{ name: "exits 126 and writes nothing", body: "exit 126", cause: " and wrote nothing to stderr" },
|
|
679
|
+
{ name: "exits 127 and writes to stderr", body: "echo boom >&2; exit 127", cause: ": boom" },
|
|
680
|
+
{ name: "is killed by a signal", body: "kill -9 $$", cause: ": git was killed by SIGKILL" },
|
|
681
|
+
];
|
|
682
|
+
for (const c of GIT_THAT_CANNOT_RUN) {
|
|
683
|
+
test(`a git that starts but ${c.name} before the cache is read back is no verdict, never NOT PROVEN — and the prior cache is restored`, () => {
|
|
684
|
+
const { dir } = repo(MAVEN_FILES);
|
|
685
|
+
mkdirSync(join(dir, ".fleet"));
|
|
686
|
+
writeFileSync(cachePath(dir), "prior bytes");
|
|
687
|
+
const bin = readerPath();
|
|
688
|
+
const r = prove(dir, ["--install", "true", "--test", `printf '#!/bin/sh\\n${c.body}\\n' > '${join(bin, ".stub-git")}'; echo 'tests 1'`, "--count-line", "tests 1", "--test-count", "1"], { env: { PATH: bin } });
|
|
689
|
+
assert.equal(r.status, 2, r.err);
|
|
690
|
+
assert.ok(r.err.includes(`recipe-prove: git started but does not run: \`git --version\` did not exit 0${c.cause} — the Recipe cache reader runs git, so its refusal is no verdict on what was proven`), r.err);
|
|
691
|
+
assert.doesNotMatch(r.err, /NOT PROVEN/);
|
|
692
|
+
assert.doesNotMatch(r.err, /not a git repository/);
|
|
693
|
+
assert.equal(readFileSync(cachePath(dir), "utf8"), "prior bytes", "a cache the reader never settled is rolled back");
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
|
|
668
697
|
// The reader's own `sh`, taken away the same way: a read-back that never ran
|
|
669
698
|
// read nothing, so it is no verdict either.
|
|
670
699
|
test("an sh that stops starting before the cache is read back is no verdict, never NOT PROVEN — and no cache is left", () => {
|