test: lock in the app readiness gate with static, deterministic and real-stack probes (E00-S03-T06)

This commit is contained in:
implementer
2026-08-30 01:56:22 +00:00
parent ebdee5daa5
commit c20110be15
4 changed files with 807 additions and 5 deletions
+9 -4
View File
@@ -509,15 +509,20 @@ test('docker compose up -d starts the database and application containers', { sk
`the "app" container must stay running after "docker compose up -d" (state: "${appState}") — since T03 the server serves the health endpoint and must not exit`,
);
// T03: the app serves the health endpoint — HTTP smoke test against the
// endpoint inside the app container (no host-port dependency), polling
// until it answers or times out.
// T03 + E00-S03-T06: the app serves the health endpoint — HTTP smoke test
// against the endpoint inside the app container (no host-port dependency),
// polling until it answers or times out. Since T06 the endpoint is the
// readiness probe: it answers 503 {"status":"not ready"} while the startup
// migration run is in flight and 200 {"status":"ok"} only after it
// completes, so the probe treats a 503 (and a connection failure) as
// "still starting — retry" and fail-fasts only on a definitive non-2xx
// answer.
let healthOutput = '';
let healthOk = false;
for (let attempt = 0; attempt < 30 && !healthOk; attempt += 1) {
const probe = run('docker', ['compose', 'exec', '-T', 'app', 'node', '-e', `
fetch('http://127.0.0.1:3000/health')
.then(async (res) => { console.log(res.status, await res.text()); process.exit(res.ok ? 0 : 1); })
.then(async (res) => { console.log(res.status, await res.text()); process.exit(res.ok ? 0 : res.status === 503 ? 2 : 1); })
.catch(() => process.exit(2));
`], { cwd: REPO_ROOT, timeout: 15_000 });
const output = String(probe.stdout ?? '') + String(probe.stderr ?? '');