import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { accessSync, constants, readFileSync } from "node:fs"; import { join } from "node:path"; import test from "node:test"; // Pins the wiring that makes the background-service smoke an effective gate. // The service leg exists because v2026.824.0 shipped a service install that // crash-looped on a missing shim while the Docker smoke stayed green; these // assertions keep the job from being silently disconnected or weakened. const repoRoot = new URL("..", import.meta.url).pathname.replace(/\/$/, ""); const scriptPath = join(repoRoot, "scripts", "service-onboard-smoke.sh"); const script = readFileSync(scriptPath, "utf8"); const smokeWorkflow = readFileSync(join(repoRoot, ".github", "workflows", "release-smoke.yml"), "utf8"); const releaseWorkflow = readFileSync(join(repoRoot, ".github", "workflows", "release.yml"), "utf8"); test("smoke script is executable and parses", () => { accessSync(scriptPath, constants.X_OK); execFileSync("bash", ["-n", scriptPath]); }); test("smoke script keeps its load-bearing assertions", () => { assert.match(script, /^set -euo pipefail$/m); // Onboards the published artifact with the service leg forced on. assert.match(script, /onboard --yes --install-service/); // Fails when the shim never materialized. assert.match(script, /no executable shim at .*after onboarding/); // Fails when the unit dies instead of serving. assert.match(script, /entered the failed state/); // Fails when health answers but the service is not what is serving -- // the exact signature of the v2026.824.0 defect. assert.match(script, /something other than the service is serving/); // Refuses to smoke over a real install unless forced. assert.match(script, /SMOKE_FORCE/); }); test("release-smoke workflow runs the service leg against the input version", () => { assert.match(smokeWorkflow, /^ smoke_service:$/m); assert.match(smokeWorkflow, /scripts\/service-onboard-smoke\.sh/); const serviceJob = smokeWorkflow.split(/^ smoke:$/m)[0]; assert.match(serviceJob, /PAPERCLIPAI_VERSION: \$\{\{ inputs\.paperclip_version \}\}/); // Diagnostics must survive the run: cleanup stays off in CI and the // artifact name cannot collide with the Docker job's upload. assert.match(serviceJob, /SMOKE_CLEANUP: "false"/); assert.match(serviceJob, /\$\{\{ inputs\.artifact_name \}\}-service/); }); test("nightly and beta smokes still route through the reusable workflow", () => { const calls = releaseWorkflow.match(/uses: \.\/\.github\/workflows\/release-smoke\.yml/g) ?? []; assert.ok(calls.length >= 2, "smoke_nightly and smoke_beta must call release-smoke.yml so smoke_service gates them"); });