CI / build (pull_request) Successful in 1m6s
CI / lint (pull_request) Successful in 1m22s
CI / unit (pull_request) Successful in 1m24s
CI / frontend (pull_request) Successful in 3m12s
CI / mutation (pull_request) Successful in 6m20s
CI / verify-stack (pull_request) Failing after 5m43s
Bring-up timed out with TIMEOUT: 'objecten' not healthy (status=none) while the very `docker ps` it dumps showed infra-objecten-1 "Up 9 minutes (healthy)". `--filter name=` is a substring match, so `objecten` also matches objecten-db, objecten-redis and (since #152) objecten-celery. `head -1` took whichever docker listed first; the celery worker declares no healthcheck, so it inspected as status=none and the wait sat there until the deadline. Not objecten-specific — `objecttypen` matches objecttypen-db the same way. The bug has been latent since those services landed and was decided by listing order, which is why it only surfaced now. Anchored on the replica suffix, matching both docker compose and podman-compose naming — the same anchoring the verify check scripts already use.
41 lines
1.9 KiB
Bash
Executable File
41 lines
1.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Wait until the named compose services report a healthy healthcheck.
|
|
#
|
|
# Portable across `docker compose` (CI) and `podman-compose` (local dev): it uses
|
|
# plain `docker ps` + `docker inspect`, so it needs neither `docker compose
|
|
# up --wait` (podman-compose doesn't implement that flag) nor host port access
|
|
# (the containerized CI runner can't reach published ports). It also sidesteps the
|
|
# `--wait`-fails-when-a-one-shot-exits issue, since we only poll long-running
|
|
# services that declare a healthcheck. See docs/runbooks/gitea-actions-gotchas.md.
|
|
#
|
|
# Usage: WAIT_TIMEOUT=420 wait-healthy.sh <service> [<service> ...]
|
|
set -euo pipefail
|
|
|
|
timeout="${WAIT_TIMEOUT:-420}"
|
|
deadline=$(( $(date +%s) + timeout ))
|
|
|
|
# compose service name -> container id. `--filter name=` is a substring match, so it is anchored on
|
|
# the compose replica suffix — otherwise 'objecten' also matches objecten-db / objecten-redis /
|
|
# objecten-celery, and 'objecttypen' matches objecttypen-db. Whichever docker listed first won, so a
|
|
# service with a sibling that has no healthcheck timed out with status=none while it was in fact
|
|
# healthy. The pattern matches both docker compose ("infra-objecten-1") and podman-compose
|
|
# ("infra_objecten_1") naming; the same anchoring the verify check scripts use.
|
|
cid_for() { docker ps -aq --filter "name=$1[-_][0-9]+\$" | head -1; }
|
|
|
|
for svc in "$@"; do
|
|
echo "waiting for '$svc' to be healthy (timeout ${timeout}s)..."
|
|
while :; do
|
|
cid="$(cid_for "$svc")"
|
|
status=""
|
|
[ -n "$cid" ] && status="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$cid" 2>/dev/null || true)"
|
|
[ "$status" = "healthy" ] && { echo " '$svc' is healthy"; break; }
|
|
if [ "$(date +%s)" -ge "$deadline" ]; then
|
|
echo "TIMEOUT: '$svc' not healthy (status=${status:-no-container})" >&2
|
|
docker ps -a --filter "name=$svc" >&2 || true
|
|
exit 1
|
|
fi
|
|
sleep 3
|
|
done
|
|
done
|