README: document today's shipped work (story reactions/comments, per-pet insights dashboard, DESIGN.md/PRODUCT.md design system, admin panel visual pass) in "What's Shipped" and the admin panel section. docker/rolling-deploy.sh and start.sh were tracked as 100644 (no executable bit) since this repo is worked from Windows, which never records it — every fresh git pull onto the Linux NAS made them non-executable again. Fixed via git update-index --chmod=+x so this doesn't recur.
60 lines
1.9 KiB
Bash
Executable File
60 lines
1.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# Zero-downtime rolling deploy for the pawfeed-1/2/3 replicas.
|
|
#
|
|
# Builds the shared image once, then restarts each replica one at a time,
|
|
# waiting for the Docker healthcheck (GET /api/health, see
|
|
# docker-compose.yml) to report "healthy" before moving to the next one.
|
|
# At every point at least 2 of 3 replicas are serving traffic, so NPM's
|
|
# least_conn upstream (docker/npm-upstream.conf) never has fewer than 2
|
|
# healthy backends. `docker compose up -d --build` (start.sh) still works
|
|
# for a first-time deploy or when downtime doesn't matter — use this
|
|
# script for routine deploys against a live site instead.
|
|
set -e
|
|
cd "$(dirname "$0")"
|
|
|
|
if [ ! -f .env ]; then
|
|
echo "ERROR: docker/.env not found."
|
|
echo "Copy .env.example to docker/.env and fill in your values."
|
|
exit 1
|
|
fi
|
|
|
|
export SENTRY_RELEASE="$(git -C .. rev-parse --short HEAD)"
|
|
|
|
REPLICAS="pawfeed-1 pawfeed-2 pawfeed-3"
|
|
TIMEOUT_SECS=60
|
|
|
|
echo "Building shared image..."
|
|
docker compose build pawfeed-1
|
|
|
|
wait_healthy() {
|
|
replica="$1"
|
|
elapsed=0
|
|
while [ "$elapsed" -lt "$TIMEOUT_SECS" ]; do
|
|
status="$(docker inspect --format='{{.State.Health.Status}}' "$replica" 2>/dev/null || echo "starting")"
|
|
if [ "$status" = "healthy" ]; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
elapsed=$((elapsed + 2))
|
|
done
|
|
return 1
|
|
}
|
|
|
|
for replica in $REPLICAS; do
|
|
echo "--- Redeploying $replica ---"
|
|
docker compose up -d --no-deps "$replica"
|
|
|
|
echo "Waiting for $replica to report healthy (up to ${TIMEOUT_SECS}s)..."
|
|
if wait_healthy "$replica"; then
|
|
echo "$replica is healthy."
|
|
else
|
|
echo "ERROR: $replica did not become healthy within ${TIMEOUT_SECS}s."
|
|
echo "Check: docker logs $replica"
|
|
echo "Aborting before touching the remaining replicas — the ones already"
|
|
echo "redeployed keep running, the rest are untouched and still on the old image."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
echo "Rolling deploy complete — all 3 replicas updated with zero downtime."
|