Import approved PostgreSQL snapshot into dev
Unified application CI and deployment / static-checks (push) Successful in 5s
Remote development preview source sync / sync-source (push) Successful in 50s
Unified application CI and deployment / verify-and-release (push) Has been skipped

This commit is contained in:
2026-11-04 16:34:17 +08:00
parent 95df8df552
commit 8d37fabe58
2 changed files with 84 additions and 0 deletions
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -Eeuo pipefail
root=/opt/prompt-preview
test -f "$root/ready"
exec 8>/var/lock/prompt-preview-sync.lock
flock -w 30 8
container() {
local id
id=$(docker ps -q --filter "label=com.docker.compose.project=$1" --filter "label=com.docker.compose.service=$2")
[[ "$id" =~ ^[0-9a-f]{12}$ ]]
printf '%s\n' "$id"
}
production=$(container prompt postgres)
preview=$(container prompt-preview postgres)
web=$(container prompt-preview waterfall-wiki)
test "$production" != "$preview"
suffix=$(date -u +%Y%m%d%H%M%S)
incoming="prompt_import_$suffix"
backup="prompt_before_$suffix"
port=$(docker port "$web" 3000/tcp | awk -F: 'NR==1 {print $NF}')
[[ "$port" =~ ^[0-9]+$ ]]
sql() {
docker exec -i "$preview" psql -X -q -v ON_ERROR_STOP=1 -U prompt "$@"
}
ready() {
for attempt in {1..24}; do
if curl --noproxy '*' -fsS --max-time 5 "http://127.0.0.1:$port/api/health" >/dev/null 2>&1; then return; fi
sleep 2
done
return 1
}
# Keep the dump in a pipe on ces-control. Do not export active credentials.
docker exec "$preview" createdb -U prompt -T template0 "$incoming"
docker exec "$production" pg_dump -U prompt -d prompt -Fc \
--exclude-table-data=public.account_tokens \
--exclude-table-data=public.canvas_agent_links \
--exclude-table-data=public.account_limits |
docker exec -i "$preview" pg_restore -U prompt -d "$incoming" --no-owner --no-privileges --exit-on-error
existing_schema=$(sql -At -d prompt -c 'SELECT version FROM schema_migrations ORDER BY version')
incoming_schema=$(sql -At -d "$incoming" -c 'SELECT version FROM schema_migrations ORDER BY version')
test -n "$existing_schema"
if [[ "$existing_schema" != "$incoming_schema" ]]; then
echo 'Preview and production migration sets differ. Preview was not switched.' >&2
exit 1
fi
test "$(sql -At -d "$incoming" -c 'SELECT count(*) FROM account_tokens')" = 0
test "$(sql -At -d "$incoming" -c 'SELECT count(*) FROM canvas_agent_links')" = 0
verified=$(sql -At -d "$incoming" -c 'SELECT count(*) FROM account_users WHERE verified_at IS NOT NULL')
test "$verified" -gt 0
echo "Snapshot validated: $verified verified accounts, matching migrations, no live account or canvas tokens."
docker stop "$web" >/dev/null
if ! sql -d postgres <<SQL
BEGIN;
ALTER DATABASE prompt RENAME TO $backup;
ALTER DATABASE $incoming RENAME TO prompt;
COMMIT;
SQL
then
docker start "$web" >/dev/null
exit 1
fi
if docker start "$web" >/dev/null && ready; then
echo "Preview is healthy. Original preview retained as $backup."
else
docker stop "$web" >/dev/null
sql -d postgres <<SQL
BEGIN;
ALTER DATABASE prompt RENAME TO $incoming;
ALTER DATABASE $backup RENAME TO prompt;
COMMIT;
SQL
docker start "$web" >/dev/null
ready
echo 'Snapshot failed the health check. Original preview restored.' >&2
exit 1
fi