0c26e7a41c
Co-authored-by: Copilot <copilot@github.com>
61 lines
1.9 KiB
Bash
61 lines
1.9 KiB
Bash
#!/usr/bin/env bash
|
|
# wait-healthy.sh — poll docker compose services until all are healthy/running.
|
|
# Invoked by the compose-wait-healthy composite action. Configure via env vars:
|
|
# WAIT_HEALTHY_SERVICES whitespace-separated list of service names (required)
|
|
# WAIT_HEALTHY_DEADLINE seconds before the script fails (default: 600)
|
|
# WAIT_HEALTHY_POLL seconds between polls (default: 5)
|
|
# COMPOSE_PROJECT compose project name passed via -p (optional)
|
|
set -euo pipefail
|
|
|
|
compose() {
|
|
if [[ -n "${COMPOSE_PROJECT:-}" ]]; then
|
|
docker compose -p "${COMPOSE_PROJECT}" "$@"
|
|
else
|
|
docker compose "$@"
|
|
fi
|
|
}
|
|
|
|
read -r -a services <<< "${WAIT_HEALTHY_SERVICES}"
|
|
if [[ ${#services[@]} -eq 0 ]]; then
|
|
echo "ERROR: WAIT_HEALTHY_SERVICES is empty" >&2
|
|
exit 64
|
|
fi
|
|
|
|
deadline="${WAIT_HEALTHY_DEADLINE:-600}"
|
|
poll="${WAIT_HEALTHY_POLL:-5}"
|
|
start="$(date +%s)"
|
|
|
|
while :; do
|
|
pending=()
|
|
for svc in "${services[@]}"; do
|
|
cid="$(compose ps -q "${svc}" || true)"
|
|
if [[ -z "${cid}" ]]; then
|
|
pending+=("${svc}(no container)")
|
|
continue
|
|
fi
|
|
status="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "${cid}" 2>/dev/null || echo unknown)"
|
|
case "${status}" in
|
|
healthy|running) ;;
|
|
*) pending+=("${svc}=${status}") ;;
|
|
esac
|
|
done
|
|
|
|
if [[ ${#pending[@]} -eq 0 ]]; then
|
|
echo "all services healthy: ${services[*]}"
|
|
exit 0
|
|
fi
|
|
|
|
elapsed=$(( $(date +%s) - start ))
|
|
if (( elapsed > deadline )); then
|
|
echo "FAIL: timeout after ${elapsed}s waiting on: ${pending[*]}" >&2
|
|
for svc in "${services[@]}"; do
|
|
echo "----- ${svc} (last 50 log lines) -----" >&2
|
|
compose logs --no-color --tail=50 "${svc}" >&2 || true
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
printf '[%4ds] waiting on: %s\n' "${elapsed}" "${pending[*]}"
|
|
sleep "${poll}"
|
|
done
|