ops: make production builds atomic

This commit is contained in:
134 2026-08-20 19:32:49 +08:00
parent 6180c5fc49
commit 88dec71a41

View File

@ -0,0 +1,52 @@
#!/bin/sh
set -eu
app_dir="/srv/ai-chatbot"
compose_dir="/srv/ai-chatbot-deploy"
candidate_dir="$(mktemp -d "${app_dir}/.next-candidate.XXXXXX")"
previous_dir="${app_dir}/.next-previous-$(date +%Y%m%dT%H%M%S)"
build_container="ai-chatbot-build-$(date +%s)"
cleanup_candidate() {
if [ -d "$candidate_dir" ]; then
rm -rf -- "$candidate_dir"
fi
}
trap cleanup_candidate EXIT INT TERM
docker run --rm \
--name "$build_container" \
--network host \
-e NODE_OPTIONS=--max-old-space-size=6144 \
-v "${app_dir}:/workspace" \
-v "${candidate_dir}:/workspace/.next" \
-w /workspace \
node:20.20.0-bookworm-slim \
sh -lc 'corepack enable && pnpm build'
test -s "${candidate_dir}/BUILD_ID"
docker stop ai-chatbot-app >/dev/null
if [ -d "${app_dir}/.next" ]; then
mv "${app_dir}/.next" "$previous_dir"
fi
mv "$candidate_dir" "${app_dir}/.next"
candidate_dir=""
docker compose -f "${compose_dir}/docker-compose.yml" up -d app
if ! curl -fsS --retry 12 --retry-delay 2 --max-time 10 \
http://127.0.0.1:3125/login >/dev/null; then
docker stop ai-chatbot-app >/dev/null 2>&1 || true
failed_dir="${app_dir}/.next-failed-$(date +%Y%m%dT%H%M%S)"
mv "${app_dir}/.next" "$failed_dir"
if [ -d "$previous_dir" ]; then
mv "$previous_dir" "${app_dir}/.next"
docker compose -f "${compose_dir}/docker-compose.yml" up -d app
fi
echo "Deployment health check failed; previous build restored." >&2
exit 1
fi
echo "Production build activated. Previous build: ${previous_dir}"