pelagia-portal/automation/refresh-test-db.sh
Hardik 4da39fe5d1 fix(automation): apply master migrations to the test DB
The test DB mirrors prod, which can be behind master, so the latest code 500s on
columns prod doesn't have yet (e.g. poDate from the optional-PO-date feature).

- staging-up.sh runs prisma migrate deploy after install.
- refresh-test-db.sh re-applies master migrations after each nightly data copy,
  so the running staging/autofix DB stays at the schema of the code under test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:51:59 +05:30

65 lines
2.9 KiB
Bash

#!/usr/bin/env bash
# Refresh the test database from production. Runs daily via cron on pms1.
#
# pelagia_test is a throwaway mirror of prod (pelagia) so the autofix Claude can
# run integration tests / a dev server against realistic data WITHOUT touching
# production. The test DB is owned by pelagia_user (created once as superuser);
# this refresh runs purely as pelagia_user using the prod connection string.
set -uo pipefail
ENV_FILE="${1:-/home/shad0w/pms/App/.env}"
PROD_DB="pelagia"
TEST_DB="pelagia_test"
log() { echo "$(date '+%F %T') $*"; }
PROD_URL=$(grep -E '^DATABASE_URL' "$ENV_FILE" | sed -E 's/^DATABASE_URL=//; s/^"//; s/"$//')
[ -n "$PROD_URL" ] || { log "ERROR: no DATABASE_URL in $ENV_FILE"; exit 1; }
# Derive the test URL by swapping ONLY the database-name path segment (anchored on
# @host/ so the 'pelagia' inside the username is never touched).
TEST_URL=$(printf '%s' "$PROD_URL" | sed -E "s#(@[^/]+/)$PROD_DB([?]|\$)#\1$TEST_DB\2#")
if [ "$TEST_URL" = "$PROD_URL" ]; then
log "ERROR: failed to derive test URL (db name not found in connection string)"; exit 1
fi
log "Refreshing $TEST_DB from $PROD_DB ..."
# --clean --if-exists drops+recreates each object in place (first run on an empty
# DB is a no-op for the DROPs). --no-owner/--no-privileges keep it portable.
errfile=$(mktemp)
pg_dump --clean --if-exists --no-owner --no-privileges "$PROD_URL" \
| psql "$TEST_URL" >/dev/null 2>"$errfile"
prod_tables=$(psql -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';" "$PROD_URL")
test_tables=$(psql -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';" "$TEST_URL")
if [ "$test_tables" = "$prod_tables" ] && [ "$test_tables" -gt 0 ]; then
log "Data copied. $TEST_DB has $test_tables public tables (prod has $prod_tables)."
rm -f "$errfile"
else
log "WARNING: table counts differ (test=$test_tables prod=$prod_tables). Recent errors:"
tail -8 "$errfile"
rm -f "$errfile"
exit 1
fi
# The test DB now has PROD's schema, which may be behind master. Apply master's
# unreleased migrations so the code under test (staging + autofix) doesn't 500 on
# columns prod doesn't have yet (e.g. poDate). Uses a stable master checkout.
MIG_DIR=""
for d in "$HOME/pelagia-staging/App" "$HOME/pelagia-autofix/App"; do
[ -d "$d/prisma/migrations" ] && { MIG_DIR="$d"; break; }
done
if [ -n "$MIG_DIR" ]; then
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh" 2>/dev/null || true
log "Applying master migrations from $MIG_DIR ..."
if ( cd "$MIG_DIR" && DATABASE_URL="$TEST_URL" pnpm db:migrate:deploy ) >/tmp/migrate-test-db.log 2>&1; then
log "Migrations applied."
else
log "WARNING: migrate deploy failed; see /tmp/migrate-test-db.log"; tail -5 /tmp/migrate-test-db.log
fi
else
log "No master checkout with migrations found; skipping migrate (test DB has prod schema only)."
fi