Files
secrets/scripts/migrate-db-prod-to-nn-test.sh
王松 c6fb457734
Some checks failed
Secrets MCP — Build & Release / 检查 / 构建 / 发版 (push) Failing after 2m37s
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been skipped
feat(nn): entry–secret N:N, unique secret names, web unlink
Bump secrets-mcp to 0.3.8 (tag 0.3.7 already used).

- Junction table entry_secrets; secrets user-scoped with type
- Per-user unique secrets.name; link_secret_names on add
- Manual migrations + migrate script; MCP/tool and Web updates

Made-with: Cursor
2026-04-03 17:37:04 +08:00

82 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Migrate PostgreSQL data from secrets-mcp-prod to secrets-nn-test.
#
# Prereqs: pg_dump and pg_restore (PostgreSQL client tools) on PATH.
# TLS: Use the same connection parameters as your MCP / app (e.g. sslmode=verify-full
# and PGSSLROOTCERT if needed). If local psql fails with "certificate verify failed",
# run this script from a host that trusts the server CA, or set PGSSLROOTCERT.
#
# Usage:
# export SOURCE_DATABASE_URL='postgres://USER:PASS@host:5432/secrets-mcp-prod?sslmode=verify-full'
# export TARGET_DATABASE_URL='postgres://USER:PASS@host:5432/secrets-nn-test?sslmode=verify-full'
# ./scripts/migrate-db-prod-to-nn-test.sh
#
# Options (env):
# BACKUP_TARGET_FIRST=1 # default: dump target to ./backup-secrets-nn-test-<timestamp>.dump before restore
# RUN_NN_SQL=1 # default: run migrations/001_nn_schema.sql then 002_data_cleanup.sql on target after restore
# SKIP_TARGET_BACKUP=1 # skip target backup
#
# WARNINGS:
# - pg_restore with --clean --if-exists drops objects that exist in the dump; target DB is replaced
# to match the logical content of the source dump (same as typical full restore).
# - Optionally keep a manual dump of the target before proceeding.
# - 001_nn_schema.sql will fail if secrets has duplicate (user_id, name) after backfill; fix data first.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
SOURCE_URL="${SOURCE_DATABASE_URL:-}"
TARGET_URL="${TARGET_DATABASE_URL:-}"
if [[ -z "$SOURCE_URL" || -z "$TARGET_URL" ]]; then
echo "Set SOURCE_DATABASE_URL and TARGET_DATABASE_URL (postgres URLs)." >&2
exit 1
fi
if ! command -v pg_dump >/dev/null || ! command -v pg_restore >/dev/null; then
echo "pg_dump and pg_restore are required." >&2
exit 1
fi
TS="$(date +%Y%m%d%H%M%S)"
DUMP_FILE="${DUMP_FILE:-$ROOT/tmp/secrets-mcp-prod-${TS}.dump}"
mkdir -p "$(dirname "$DUMP_FILE")"
if [[ "${EXCLUDE_TOWER_SESSIONS:-}" == "1" ]]; then
echo "==> Excluding schema tower_sessions from dump"
pg_dump "$SOURCE_URL" -Fc --no-owner --no-acl --exclude-schema=tower_sessions -f "$DUMP_FILE"
else
echo "==> Dumping source (custom format) -> $DUMP_FILE"
pg_dump "$SOURCE_URL" -Fc --no-owner --no-acl -f "$DUMP_FILE"
fi
if [[ "${SKIP_TARGET_BACKUP:-}" != "1" && "${BACKUP_TARGET_FIRST:-1}" == "1" ]]; then
BACKUP_FILE="$ROOT/tmp/secrets-nn-test-before-${TS}.dump"
echo "==> Backing up target -> $BACKUP_FILE"
pg_dump "$TARGET_URL" -Fc --no-owner --no-acl -f "$BACKUP_FILE" || {
echo "Target backup failed (empty DB is OK). Continuing." >&2
}
fi
echo "==> Restoring into target (--clean --if-exists)"
pg_restore -d "$TARGET_URL" --no-owner --no-acl --clean --if-exists --verbose "$DUMP_FILE"
if [[ "${RUN_NN_SQL:-1}" == "1" ]]; then
if [[ ! -f "$ROOT/migrations/001_nn_schema.sql" ]]; then
echo "migrations/001_nn_schema.sql not found; skip NN SQL." >&2
else
echo "==> Applying migrations/001_nn_schema.sql on target"
psql "$TARGET_URL" -v ON_ERROR_STOP=1 -f "$ROOT/migrations/001_nn_schema.sql"
fi
if [[ -f "$ROOT/migrations/002_data_cleanup.sql" ]]; then
echo "==> Applying migrations/002_data_cleanup.sql on target"
psql "$TARGET_URL" -v ON_ERROR_STOP=1 -f "$ROOT/migrations/002_data_cleanup.sql"
fi
fi
echo "==> Done. Suggested verification:"
echo " psql \"\$TARGET_DATABASE_URL\" -c \"SELECT COUNT(*) FROM entries; SELECT COUNT(*) FROM secrets; SELECT COUNT(*) FROM entry_secrets;\""
echo " ./scripts/release-check.sh # optional app-side sanity"