This commit is contained in:
@@ -12,22 +12,33 @@ for key in WQ_EMAIL WQ_PASSWORD DATABASE_URL ADMIN_PASSWORD ENCRYPTION_KEY DATAB
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
state_dir="${DEPLOY_STATE_DIR:-/opt/wq-alpha}"
|
||||
if [[ "$state_dir" != /* || ! -d "$state_dir" || ! -w "$state_dir" ]]; then
|
||||
echo 'DEPLOY_STATE_DIR must be an existing writable absolute directory.' >&2
|
||||
exit 1
|
||||
fi
|
||||
command -v flock >/dev/null
|
||||
# Stable across checkouts; stores only a lock and release metadata, never credentials.
|
||||
exec 9>"$state_dir/deploy.lock"
|
||||
flock -n 9 || { echo 'Another production deployment is running.' >&2; exit 1; }
|
||||
export DEPLOY_TAG="${DEPLOY_TAG:-$(git rev-parse HEAD)}"
|
||||
compose=(docker compose --env-file /dev/null -p wq-alpha-production -f compose.production.yaml)
|
||||
trap 'rc=$?; "${compose[@]}" --profile jobs ps -a || true; exit "$rc"' EXIT
|
||||
lock_id=""
|
||||
cleanup() {
|
||||
local rc=$?
|
||||
"${compose[@]}" --profile jobs ps -a || true
|
||||
# Remove only the lock acquired by this process, never another deployment's lock.
|
||||
if [[ -n "$lock_id" ]]; then
|
||||
docker rm "$lock_id" >/dev/null || true
|
||||
fi
|
||||
exit "$rc"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
|
||||
"${compose[@]}" config --quiet
|
||||
"${compose[@]}" --profile jobs config --quiet
|
||||
"${compose[@]}" build backend web
|
||||
# Docker enforces unique container names across runner jobs and checkout paths.
|
||||
# The lock container is never started and receives no deployment credentials.
|
||||
if ! lock_id=$(docker create --name wq-alpha-production-deploy-lock \
|
||||
--label "wq.deploy.commit=$DEPLOY_TAG" \
|
||||
--network none --entrypoint /bin/true "wq-alpha-production-backend:$DEPLOY_TAG"); then
|
||||
echo 'Cannot acquire deployment lock; check Docker and other active deployments.' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Validate secrets and DB connectivity before interrupting the running version.
|
||||
"${compose[@]}" run --rm --no-deps backend python -c '
|
||||
import asyncio
|
||||
@@ -51,10 +62,10 @@ except Exception:
|
||||
# Record immutable image references before switching; do not prune old images.
|
||||
previous_images=$("${compose[@]}" images --quiet)
|
||||
if [[ -n "$previous_images" ]]; then
|
||||
docker image inspect --format '{{.Id}} {{json .RepoTags}}' $previous_images > "$state_dir/previous-images.txt"
|
||||
echo "Previous deployment images (retain for rollback):"
|
||||
docker image inspect --format '{{.Id}} {{json .RepoTags}}' $previous_images
|
||||
fi
|
||||
"${compose[@]}" stop web backend
|
||||
"${compose[@]}" --profile jobs run --rm --no-deps migrate
|
||||
"${compose[@]}" up -d --no-build --remove-orphans --wait --wait-timeout 180 backend web
|
||||
printf '%s\n' "$DEPLOY_TAG" > "$state_dir/current-release.txt"
|
||||
echo "Production is healthy; release $DEPLOY_TAG"
|
||||
|
||||
Reference in New Issue
Block a user