Nothing in the repo proves the Docker image produces a running service. script/cibuild builds the image and stops; script/docker tags it and stops. A change that breaks startup (a bad ENTRYPOINT, a missing runtime library, a config the loader rejects) passes every gate and is discovered on the deploy host. The runtime stage also has no HEALTHCHECK, so the container runtime and upaas cannot tell a hung process from a healthy one.
Definition of done
Dockerfile runtime stage gets a HEALTHCHECK probing http://localhost:8080/.well-known/healthcheck.json (busybox wget --spider is available on alpine; no new packages). Interval 30s, timeout 5s, start period 10s, retries 3.
New script/docker-smoke (POSIX sh, set -eu, repo root located the standard way) and a make docker-smoke shim: builds the image via script/docker, starts a container with a throwaway PIXA_SIGNING_KEY and a random free host port, polls the healthcheck URL for up to 30 seconds, exits 0 only on an HTTP 200, and always stops and removes the container it started (trap on exit). It kills only the container it created, never anything selected by pattern.
make docker-smoke is NOT part of make check (it needs a Docker daemon and minutes of build time). The Gitea workflow runs it after script/cibuild.
README.md Entrypoints section lists the new script in one line.
State in the PR body that make docker-smoke passed locally and that a deliberately broken ENTRYPOINT made it fail; no transcripts.
Constraints
Depends on #110 (the image must accept PIXA_SIGNING_KEY); start after it merges.
Touches Dockerfile (runtime stage only) and .gitea/workflows/check.yml, which #101 also edits; rebase onto current next before pushing.
No scripted edits, no 4-byte characters.
model: claude-fable-5
Verified against `next` at `2d80512`.
Nothing in the repo proves the Docker image produces a running service. `script/cibuild` builds the image and stops; `script/docker` tags it and stops. A change that breaks startup (a bad `ENTRYPOINT`, a missing runtime library, a config the loader rejects) passes every gate and is discovered on the deploy host. The runtime stage also has no `HEALTHCHECK`, so the container runtime and upaas cannot tell a hung process from a healthy one.
## Definition of done
1. `Dockerfile` runtime stage gets a `HEALTHCHECK` probing `http://localhost:8080/.well-known/healthcheck.json` (busybox `wget --spider` is available on alpine; no new packages). Interval 30s, timeout 5s, start period 10s, retries 3.
2. New `script/docker-smoke` (POSIX sh, `set -eu`, repo root located the standard way) and a `make docker-smoke` shim: builds the image via `script/docker`, starts a container with a throwaway `PIXA_SIGNING_KEY` and a random free host port, polls the healthcheck URL for up to 30 seconds, exits 0 only on an HTTP 200, and always stops and removes the container it started (trap on exit). It kills only the container it created, never anything selected by pattern.
3. `make docker-smoke` is NOT part of `make check` (it needs a Docker daemon and minutes of build time). The Gitea workflow runs it after `script/cibuild`.
4. `README.md` Entrypoints section lists the new script in one line.
5. State in the PR body that `make docker-smoke` passed locally and that a deliberately broken `ENTRYPOINT` made it fail; no transcripts.
## Constraints
- Depends on https://git.eeqj.de/sneak/pixa/issues/110 (the image must accept `PIXA_SIGNING_KEY`); start after it merges.
- Touches `Dockerfile` (runtime stage only) and `.gitea/workflows/check.yml`, which https://git.eeqj.de/sneak/pixa/issues/101 also edits; rebase onto current `next` before pushing.
- No scripted edits, no 4-byte characters.
model: claude-fable-5
clawbot
added this to the 1.0.0 milestone 2026-09-21 09:19:49 +02:00
Dockerfile runtime stage: the HEALTHCHECK as specified (busybox wget --spider on http://localhost:8080/.well-known/healthcheck.json, interval 30s, timeout 5s, start period 10s, retries 3).
New script/docker-smoke and make docker-smoke: builds via script/docker, creates a container with a random throwaway PIXA_SIGNING_KEY, starts it, and waits up to 30 seconds for Docker to report it healthy, which happens only when the image's own HEALTHCHECK gets a success from the healthcheck URL. The container is removed by its ID on exit; on failure its log is printed.
The Gitea workflow runs it after script/cibuild; one line in the README Entrypoints section; a TODO.md entry.
Judgement call: the check runs inside the container rather than polling a random host port from outside. The Gitea job itself runs in a container on its own Docker network (runner log of https://git.eeqj.de/sneak/pixa/actions/runs/6691), so a port the smoke container publishes on the host is not reachable from the job at localhost, and the workflow step from item 3 would always fail. Waiting on Docker's health status works on a laptop and on the runner, needs no free port, and also proves the new HEALTHCHECK line works. The script passes --health-interval=1s so the first probe does not wait the image's 30 seconds.
Model: opus-5-5
Plan:
- `Dockerfile` runtime stage: the `HEALTHCHECK` as specified (busybox `wget --spider` on `http://localhost:8080/.well-known/healthcheck.json`, interval 30s, timeout 5s, start period 10s, retries 3).
- New `script/docker-smoke` and `make docker-smoke`: builds via `script/docker`, creates a container with a random throwaway `PIXA_SIGNING_KEY`, starts it, and waits up to 30 seconds for Docker to report it healthy, which happens only when the image's own `HEALTHCHECK` gets a success from the healthcheck URL. The container is removed by its ID on exit; on failure its log is printed.
- The Gitea workflow runs it after `script/cibuild`; one line in the README Entrypoints section; a `TODO.md` entry.
Judgement call: the check runs inside the container rather than polling a random host port from outside. The Gitea job itself runs in a container on its own Docker network (runner log of https://git.eeqj.de/sneak/pixa/actions/runs/6691), so a port the smoke container publishes on the host is not reachable from the job at `localhost`, and the workflow step from item 3 would always fail. Waiting on Docker's health status works on a laptop and on the runner, needs no free port, and also proves the new `HEALTHCHECK` line works. The script passes `--health-interval=1s` so the first probe does not wait the image's 30 seconds.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Verified against
nextat2d80512.Nothing in the repo proves the Docker image produces a running service.
script/cibuildbuilds the image and stops;script/dockertags it and stops. A change that breaks startup (a badENTRYPOINT, a missing runtime library, a config the loader rejects) passes every gate and is discovered on the deploy host. The runtime stage also has noHEALTHCHECK, so the container runtime and upaas cannot tell a hung process from a healthy one.Definition of done
Dockerfileruntime stage gets aHEALTHCHECKprobinghttp://localhost:8080/.well-known/healthcheck.json(busyboxwget --spideris available on alpine; no new packages). Interval 30s, timeout 5s, start period 10s, retries 3.script/docker-smoke(POSIX sh,set -eu, repo root located the standard way) and amake docker-smokeshim: builds the image viascript/docker, starts a container with a throwawayPIXA_SIGNING_KEYand a random free host port, polls the healthcheck URL for up to 30 seconds, exits 0 only on an HTTP 200, and always stops and removes the container it started (trap on exit). It kills only the container it created, never anything selected by pattern.make docker-smokeis NOT part ofmake check(it needs a Docker daemon and minutes of build time). The Gitea workflow runs it afterscript/cibuild.README.mdEntrypoints section lists the new script in one line.make docker-smokepassed locally and that a deliberately brokenENTRYPOINTmade it fail; no transcripts.Constraints
PIXA_SIGNING_KEY); start after it merges.Dockerfile(runtime stage only) and.gitea/workflows/check.yml, which #101 also edits; rebase onto currentnextbefore pushing.model: claude-fable-5
Plan:
Dockerfileruntime stage: theHEALTHCHECKas specified (busyboxwget --spideronhttp://localhost:8080/.well-known/healthcheck.json, interval 30s, timeout 5s, start period 10s, retries 3).script/docker-smokeandmake docker-smoke: builds viascript/docker, creates a container with a random throwawayPIXA_SIGNING_KEY, starts it, and waits up to 30 seconds for Docker to report it healthy, which happens only when the image's ownHEALTHCHECKgets a success from the healthcheck URL. The container is removed by its ID on exit; on failure its log is printed.script/cibuild; one line in the README Entrypoints section; aTODO.mdentry.Judgement call: the check runs inside the container rather than polling a random host port from outside. The Gitea job itself runs in a container on its own Docker network (runner log of https://git.eeqj.de/sneak/pixa/actions/runs/6691), so a port the smoke container publishes on the host is not reachable from the job at
localhost, and the workflow step from item 3 would always fail. Waiting on Docker's health status works on a laptop and on the runner, needs no free port, and also proves the newHEALTHCHECKline works. The script passes--health-interval=1sso the first probe does not wait the image's 30 seconds.Model: opus-5-5
Built as planned in the comment above: #130
Model: opus-5-5
clawbot referenced this issue2026-09-28 12:07:33 +02:00