Skip to content

Commit 8688c16

Browse files
committed
test(selfhost): cover env_get and require_cmd in selfhost-deploy-common
selfhost-deploy-common.test.ts covered only maybe_infisical_run, env_put, and compose_file_args (the last two added by their own bug-fix PRs). env_get and require_cmd -- both sourced by 5 deploy/verify scripts -- had no test seam, the same structural gap that let two other bugs in this file ship unnoticed. Add tests following the file's existing source-and-invoke harness: - env_get: reads an existing key, strips surrounding quotes, ignores comment/blank lines and matches the key exactly (not as a prefix), and returns non-zero for a missing key or missing file. - require_cmd: succeeds silently for a command on PATH, and exits non-zero with an actionable 'required command not found' error otherwise. Test-only; no change to the shell library. Closes #7769
1 parent cf0cc6f commit 8688c16

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

test/unit/selfhost-deploy-common.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,89 @@ printf 'REACHED_END args=[%s]\\n' "\${compose_args[*]}"
227227
expect(result.stderr).toContain("compose file not found: missing.yml");
228228
});
229229
});
230+
231+
describe("env_get (#7769)", () => {
232+
// Source the lib and invoke env_get directly with (key, file) positional args.
233+
function runEnvGet(key: string, file: string) {
234+
const script = `set -euo pipefail; . "${libPath.replace(/\\/g, "/")}"; env_get "$1" "$2"`;
235+
return spawnSync("bash", ["-c", script, "bash", key, file], { encoding: "utf8" });
236+
}
237+
238+
function tempEnvFile(contents: string): { dir: string; file: string } {
239+
const dir = mkdtempSync(join(tmpdir(), "loopover-env-get-"));
240+
const file = join(dir, ".env");
241+
writeFileSync(file, contents);
242+
return { dir, file };
243+
}
244+
245+
it("prints the value of an existing key", () => {
246+
const { dir, file } = tempEnvFile("FOO=1\nBAR=hello\n");
247+
try {
248+
const r = runEnvGet("BAR", file);
249+
expect(r.status, r.stderr).toBe(0);
250+
expect(r.stdout.trim()).toBe("hello");
251+
} finally {
252+
rmSync(dir, { recursive: true, force: true });
253+
}
254+
});
255+
256+
it("strips surrounding single or double quotes from the value", () => {
257+
const { dir, file } = tempEnvFile('FOO="quoted value"\nBAR=\'single\'\n');
258+
try {
259+
expect(runEnvGet("FOO", file).stdout.trim()).toBe("quoted value");
260+
expect(runEnvGet("BAR", file).stdout.trim()).toBe("single");
261+
} finally {
262+
rmSync(dir, { recursive: true, force: true });
263+
}
264+
});
265+
266+
it("ignores comment/blank lines and matches the key exactly, not as a prefix", () => {
267+
const { dir, file } = tempEnvFile("# FOO = commented, not this\n\nFOOBAR=wrong\nFOO=right\n");
268+
try {
269+
const r = runEnvGet("FOO", file);
270+
expect(r.status, r.stderr).toBe(0);
271+
expect(r.stdout.trim()).toBe("right"); // not FOOBAR's value, not the comment
272+
} finally {
273+
rmSync(dir, { recursive: true, force: true });
274+
}
275+
});
276+
277+
it("returns non-zero for a key that is not present", () => {
278+
const { dir, file } = tempEnvFile("FOO=1\n");
279+
try {
280+
expect(runEnvGet("MISSING", file).status).not.toBe(0);
281+
} finally {
282+
rmSync(dir, { recursive: true, force: true });
283+
}
284+
});
285+
286+
it("returns non-zero when the file does not exist", () => {
287+
const dir = mkdtempSync(join(tmpdir(), "loopover-env-get-"));
288+
try {
289+
expect(runEnvGet("FOO", join(dir, "absent.env")).status).not.toBe(0);
290+
} finally {
291+
rmSync(dir, { recursive: true, force: true });
292+
}
293+
});
294+
});
295+
296+
describe("require_cmd (#7769)", () => {
297+
// `; echo REACHED_END` marks whether execution continued past require_cmd (it exits 1 on a missing command).
298+
function runRequireCmd(cmd: string) {
299+
const script = `set -euo pipefail; . "${libPath.replace(/\\/g, "/")}"; require_cmd "$1"; echo REACHED_END`;
300+
return spawnSync("bash", ["-c", script, "bash", cmd], { encoding: "utf8" });
301+
}
302+
303+
it("succeeds silently for a command that is on PATH", () => {
304+
const r = runRequireCmd("bash");
305+
expect(r.status, r.stderr).toBe(0);
306+
expect(r.stdout).toContain("REACHED_END");
307+
});
308+
309+
it("exits non-zero with an actionable error for a missing command", () => {
310+
const r = runRequireCmd("loopover-definitely-not-a-real-command-xyz");
311+
expect(r.status).not.toBe(0);
312+
expect(r.stdout).not.toContain("REACHED_END");
313+
expect(r.stderr).toContain("required command not found: loopover-definitely-not-a-real-command-xyz");
314+
});
315+
});

0 commit comments

Comments
 (0)