Files
OmniRoute/tests/unit/check-pack-boot.test.ts
Diego Rodrigues de Sa e Souza 405feee806 feat(ci): boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) (#7086)
Three releases shipped a tarball that crashed on every boot (tls-options/3.8.41,
head-response-guard #7040/#7065) because no gate ever EXECUTED the artifact.
check:pack-boot packs the tree, installs the tarball into a clean prefix
(postinstall runs for real), boots the installed CLI on a reserved port with an
isolated DATA_DIR and polls /api/monitoring/health until it returns 200 with
the packed version — failing loudly with the server's last output otherwise.
Wired into the CI package-artifact job (reuses the dist/ the job already
assembles) and into check:release-green --with-build (parallel slow wave).
Live evidence: packed v3.8.49, installed and booted in 16.6s, health 200.
2026-07-14 05:23:34 -03:00

58 lines
2.5 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { pickTarball, evaluateBoot, pickPort } from "../../scripts/check/check-pack-boot.mjs";
// WS1.2 (T1, v3.8.49 quality plan) — pure-function guards for the tarball boot-smoke
// gate that kills the #7065 class (published artifact crashes on every boot because a
// packaging list drifted; 3rd recurrence). The end-to-end path runs in CI's
// package-artifact job; these tests pin the decision logic.
const SCRIPT_PATH = path.join(
path.dirname(fileURLToPath(import.meta.url)),
"../../scripts/check/check-pack-boot.mjs"
);
test("pickTarball extracts the filename from npm pack --json output", () => {
assert.equal(pickTarball('[{"filename":"omniroute-3.8.49.tgz","size":1}]'), "omniroute-3.8.49.tgz");
});
test("pickTarball normalizes scoped slashes to the on-disk dash form", () => {
assert.equal(pickTarball('[{"filename":"@scope/pkg-1.0.0.tgz"}]'), "@scope-pkg-1.0.0.tgz");
});
test("pickTarball throws on empty/odd npm output instead of booting garbage", () => {
assert.throws(() => pickTarball("[]"));
assert.throws(() => pickTarball("{}"));
});
test("evaluateBoot passes on HTTP 200 + matching version, whatever the health status", () => {
const r = evaluateBoot(200, { version: "3.8.49", status: "warning" }, "3.8.49");
assert.equal(r.ok, true);
assert.deepEqual(r.failures, []);
});
test("evaluateBoot fails on non-200, non-JSON body, and version mismatch", () => {
assert.equal(evaluateBoot(503, { version: "3.8.49" }, "3.8.49").ok, false);
assert.equal(evaluateBoot(200, null, "3.8.49").ok, false);
const wrong = evaluateBoot(200, { version: "3.8.48" }, "3.8.49");
assert.equal(wrong.ok, false);
assert.match(wrong.failures[0], /3\.8\.48/);
});
test("pickPort stays inside the reserved smoke range for any pid", () => {
for (const seed of [0, 1, 4000, 65535, 123456]) {
const p = pickPort(seed);
assert.ok(p >= 23000 && p < 27000, `port ${p} out of range for seed ${seed}`);
}
});
test("source guard: the gate polls the real health endpoint of the INSTALLED binary", () => {
const src = readFileSync(SCRIPT_PATH, "utf8");
assert.ok(src.includes('"install", "-g", "--prefix"'), "must install the packed tarball into a clean prefix");
assert.ok(src.includes("/api/monitoring/health"), "must poll the health endpoint");
assert.ok(src.indexOf("npm") < src.indexOf("spawn"), "pack+install must precede the boot spawn");
});