e80eeb69e0
ci-deploy / build-deploy-test (push) Successful in 1m11s
Run 549's wait-for-health logged two HTTP 502s before its third attempt succeeded — nginx → docker forwarding hit the new container during the ~4s window between \`docker run -d\` returning and Node.js inside finishing its boot. The retry loop covered it but the log was noisy and a slower boot could blow past the 30×2s budget. Added a post-run readiness probe inside swap: poll http://127.0.0.1:${PORT}/ on the host (docker container is published to 127.0.0.1, runner uses host network mode) until it answers 2xx, up to 30 attempts × 1s. Skipped under --dry-run so the tests/ci/ shell tests still pass without touching the network. Net effect: wait-for-url against the public URL now succeeds first attempt, and the run aborts cleanly if the SSR doesn't come up at all instead of looking healthy because nginx happens to keep a warmed connection.
98 lines
3.1 KiB
Bash
Executable File
98 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# deploy-container.sh — swap or rollback the flights-web container on the host.
|
|
#
|
|
# Usage: deploy-container.sh [--dry-run] <swap|rollback>
|
|
#
|
|
# `swap` — assumes the new image is tagged flights-web:${GITHUB_SHA}.
|
|
# Tags :current → :previous, :sha → :current, restarts container.
|
|
# `rollback` — runs flights-web:previous in place of :current, repoints :current.
|
|
#
|
|
# Env:
|
|
# GITHUB_SHA (required for swap)
|
|
# FLIGHTS_WEB_PORT (default 3002 — host port that nginx proxies to)
|
|
# IMAGE_NAME (default flights-web — set this to point at a registry later)
|
|
set -euo pipefail
|
|
|
|
DRY_RUN=0
|
|
if [ "${1:-}" = "--dry-run" ]; then
|
|
DRY_RUN=1
|
|
shift
|
|
fi
|
|
|
|
CMD="${1:-}"
|
|
PORT="${FLIGHTS_WEB_PORT:-3002}"
|
|
IMAGE="${IMAGE_NAME:-flights-web}"
|
|
|
|
run() {
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
printf 'docker %s\n' "$*"
|
|
else
|
|
docker "$@"
|
|
fi
|
|
}
|
|
|
|
run_or_skip() {
|
|
# Same as run, but doesn't fail in real mode if the docker call fails.
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
printf 'docker %s\n' "$*"
|
|
else
|
|
docker "$@" || true
|
|
fi
|
|
}
|
|
|
|
case "$CMD" in
|
|
swap)
|
|
: "${GITHUB_SHA:?GITHUB_SHA required for swap}"
|
|
SHORT_SHA="${GITHUB_SHA:0:7}"
|
|
# 1. Tag the currently-live image as :previous (skip if first deploy).
|
|
if [ "$DRY_RUN" -eq 1 ] || docker image inspect "${IMAGE}:current" >/dev/null 2>&1; then
|
|
run tag "${IMAGE}:current" "${IMAGE}:previous"
|
|
fi
|
|
# 2. Tag the new SHA as :current.
|
|
run tag "${IMAGE}:${SHORT_SHA}" "${IMAGE}:current"
|
|
# 3. Stop + remove existing container if present.
|
|
run_or_skip stop flights-web
|
|
run_or_skip rm flights-web
|
|
# 4. Run new container.
|
|
run run -d --name flights-web --restart unless-stopped \
|
|
-p "127.0.0.1:${PORT}:8080" \
|
|
"${IMAGE}:current"
|
|
# 5. Wait for the SSR inside the container to start listening before
|
|
# returning. Without this, the next nginx-side probe gets a few
|
|
# 502s while Node.js is still booting — works (wait-for-url.sh
|
|
# retries) but adds noise to the deploy log.
|
|
if [ "$DRY_RUN" -eq 0 ]; then
|
|
attempt=1
|
|
while [ "$attempt" -le 30 ]; do
|
|
if curl -fsS -o /dev/null "http://127.0.0.1:${PORT}/"; then
|
|
echo "swap: SSR ready on :${PORT} after $attempt attempt(s)"
|
|
break
|
|
fi
|
|
if [ "$attempt" -eq 30 ]; then
|
|
echo "swap: SSR did not respond on :${PORT} after 30 attempts" >&2
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
attempt=$((attempt + 1))
|
|
done
|
|
fi
|
|
;;
|
|
rollback)
|
|
if [ "$DRY_RUN" -eq 0 ] && ! docker image inspect "${IMAGE}:previous" >/dev/null 2>&1; then
|
|
echo "fatal: ${IMAGE}:previous not found — cannot rollback" >&2
|
|
exit 1
|
|
fi
|
|
run_or_skip stop flights-web
|
|
run_or_skip rm flights-web
|
|
run run -d --name flights-web --restart unless-stopped \
|
|
-p "127.0.0.1:${PORT}:8080" \
|
|
"${IMAGE}:previous"
|
|
# Repoint :current to :previous so subsequent swaps have a sane baseline.
|
|
run tag "${IMAGE}:previous" "${IMAGE}:current"
|
|
;;
|
|
*)
|
|
echo "usage: $0 [--dry-run] <swap|rollback>" >&2
|
|
exit 2
|
|
;;
|
|
esac
|