diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 5d3398a..f0c2424 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -1213,6 +1213,14 @@ jobs: ENVOPTS="$ENVOPTS -e DB_PORT=5432 -e DB_NAME=$DB_NAME -e SECRET_KEY=$SECRET_KEY" ENVOPTS="$ENVOPTS -e CELERY_BROKER_URL=redis://$RD_IP:6379/0" ENVOPTS="$ENVOPTS -e CELERY_RESULT_BACKEND=redis://$RD_IP:6379/0" + # A throwaway CI instance IS first-time setup, which is the one case + # credential_crypto allows a key to be minted in. Without it the web + # role refuses to boot — deliberately, since silently generating a + # key on a restored-DB-but-lost-secrets deployment would leave every + # Credential row undecryptable (the 2026-06-02 audit). Discovered by + # this job on its first real run; see #3422 for the fact that no + # user-facing file mentions this variable at all. + ENVOPTS="$ENVOPTS -e CURATOR_BOOTSTRAP_NEW_KEY=1" # 1. The schema builds from empty, using the image's OWN libpq and # psycopg. This is the same call entrypoint.sh makes before it @@ -1247,12 +1255,26 @@ jobs: healthy=1 break fi + # A container that has EXITED will never answer, so stop asking. + # Without this the loop spent 3m35s polling a dead container on + # this job's first run, and — because docker recycles the IP — got + # a confusing mix of connection-refused and 5s timeouts from + # whatever took the address next. The trap's log dump had the real + # answer the whole time; this just stops burying it. + if [ "$(docker inspect -f '{{.State.Running}}' "$CID" 2>/dev/null)" != "true" ]; then + echo "smoke: FAILED — the web container exited during boot." >&2 + echo "smoke: its log follows; entrypoint runs alembic BEFORE" >&2 + echo "smoke: serving, so a startup exception lands here." >&2 + exit 1 + fi sleep 2 done if [ -z "$healthy" ]; then - echo "smoke: FAILED — web did not answer /api/health within 120s." >&2 - echo "smoke: entrypoint runs alembic BEFORE serving, and step 1" >&2 - echo "smoke: passed, so look at hypercorn and the python base." >&2 + # 60 iterations of (up to 5s connect + 2s sleep) — up to ~7min, not + # the 120s an earlier version of this message claimed. + echo "smoke: FAILED — web is running but never answered" >&2 + echo "smoke: /api/health. It is up, so look at hypercorn and the" >&2 + echo "smoke: python base rather than at startup." >&2 exit 1 fi curl -fsS --max-time 5 "http://$WEB_IP:8080/api/health"