diff --git a/docker/Dockerfile.onboard-smoke b/docker/Dockerfile.onboard-smoke index 7b13756b81..63689c6c8a 100644 --- a/docker/Dockerfile.onboard-smoke +++ b/docker/Dockerfile.onboard-smoke @@ -37,4 +37,9 @@ WORKDIR /home/paperclip/workspace EXPOSE 3100 USER paperclip -CMD ["bash", "-lc", "set -euo pipefail; mkdir -p \"$PAPERCLIP_HOME\"; npx --yes \"paperclipai@${PAPERCLIPAI_VERSION}\" onboard --yes --data-dir \"$PAPERCLIP_HOME\""] +# --bind lan is required: `onboard --yes` without an explicit --bind prefers +# trusted-local defaults, which write a loopback bind into the instance config +# and ignore the deployment env vars. A loopback listener inside the container +# is unreachable through Docker's port mapping, so the smoke health check can +# never pass without this flag. +CMD ["bash", "-lc", "set -euo pipefail; mkdir -p \"$PAPERCLIP_HOME\"; npx --yes \"paperclipai@${PAPERCLIPAI_VERSION}\" onboard --yes --bind lan --data-dir \"$PAPERCLIP_HOME\""] diff --git a/scripts/__tests__/release-verify-workflow.test.mjs b/scripts/__tests__/release-verify-workflow.test.mjs index 841a002a28..d259376d23 100644 --- a/scripts/__tests__/release-verify-workflow.test.mjs +++ b/scripts/__tests__/release-verify-workflow.test.mjs @@ -27,6 +27,15 @@ test("release workflow delegates stable and canary verification to the reusable assert.doesNotMatch(releaseWorkflow, /verify_(?:canary|stable):[\s\S]*?pnpm test:run(?:\n|$)/); }); +test("onboard smoke container binds beyond loopback so the mapped port is reachable", () => { + const dockerfile = readFileSync(path.join(repoRoot, "docker/Dockerfile.onboard-smoke"), "utf8"); + + // `onboard --yes` without an explicit --bind prefers trusted-local + // defaults and writes a loopback bind, which Docker port mapping cannot + // reach. The smoke container must pin a non-loopback preset. + assert.match(dockerfile, /onboard --yes --bind lan/); +}); + test("release smoke workflow extends the container readiness budget for CI", () => { const smokeWorkflow = readWorkflow("release-smoke.yml"); const harness = readFileSync(path.join(repoRoot, "scripts/docker-onboard-smoke.sh"), "utf8");