import { describe, it, expect } from "bun:test";
import { readFileSync } from "node:fs";
import { join } from "node:path";
const src = (() => {
const raw = readFileSync(
join(import.meta.dir, "..", "..", "scripts", "self-deploy.sh"),
"utf8"
);
expect(raw.length).toBeGreaterThan(0);
return raw;
})();
function slice(startAnchor: string, endAnchor: string): string {
const start = src.indexOf(startAnchor);
expect(start).toBeGreaterThan(-1);
const end = src.indexOf(endAnchor, start + startAnchor.length);
expect(end).toBeGreaterThan(start);
const body = src.slice(start, end);
expect(body.length).toBeGreaterThan(0);
return body;
}
describe("self-deploy.sh keeps xtrace on for debuggability", () => {
it("still traces by default — the fix must not blind the deploy", () => {
expect(src).toContain("set -Eeuxo pipefail");
});
});
describe("secrets are not traced", () => {
it("disables xtrace across the env-file source", () => {
const body = slice('if [ -f "$ENV_FILE" ]; then', "log \" v sourced");
const offAt = body.indexOf("set +x");
const sourceAt = body.indexOf('source "$ENV_FILE"');
expect(offAt).toBeGreaterThan(-1);
expect(sourceAt).toBeGreaterThan(-1);
expect(offAt).toBeLessThan(sourceAt);
});
it("re-enables xtrace after the source, so later steps stay traced", () => {
const body = slice('if [ -f "$ENV_FILE" ]; then', "log \" v sourced");
const sourceAt = body.indexOf('source "$ENV_FILE"');
const onAt = body.lastIndexOf("set -x");
expect(onAt).toBeGreaterThan(sourceAt);
});
it("has xtrace OFF at every bearer-token curl", () => {
const lines = src.split("\n");
let tracing = false;
let tokenLines = 0;
for (const line of lines) {
const t = line.trim();
if (t === "set -Eeuxo pipefail" || t === "set -x") tracing = true;
else if (t === "set +x") tracing = false;
if (line.includes("Bearer $DEPLOY_EVENT_TOKEN")) {
tokenLines++;
expect(tracing).toBe(false);
}
}
expect(tokenLines).toBeGreaterThanOrEqual(4);
});
it("has xtrace OFF at the env-file source", () => {
const lines = src.split("\n");
let tracing = false;
let sourceSeen = 0;
for (const line of lines) {
const t = line.trim();
if (t === "set -Eeuxo pipefail" || t === "set -x") tracing = true;
else if (t === "set +x") tracing = false;
if (line.includes('source "$ENV_FILE"')) {
sourceSeen++;
expect(tracing).toBe(false);
}
}
expect(sourceSeen).toBe(1);
});
it("balances every suppression with a re-enable", () => {
const off = (src.match(/^\s*set \+x\s*$/gm) || []).length;
const on = (src.match(/^\s*set -x\s*$/gm) || []).length;
expect(off).toBeGreaterThan(0);
expect(on).toBe(off);
});
});
describe("the trace destination is not world-readable", () => {
it("creates the log 0600 before anything writes to it", () => {
expect(src).toContain("umask 077");
expect(src).toContain('chmod 600 "$LOG"');
const chmodAt = src.indexOf('chmod 600 "$LOG"');
const firstLogAt = src.indexOf('log "==> gluecron self-deploy starting');
expect(chmodAt).toBeGreaterThan(-1);
expect(firstLogAt).toBeGreaterThan(chmodAt);
});
});
describe("reachability is documented", () => {
it("records that the hook does not currently fire this script", () => {
expect(src).toContain("SELF_HOST_REPO");
expect(src).toContain("auto-update.sh");
});
});
|