fix(backend): Improve migration script with nuke step and table exclusions

- Add Step 0 to nuke destination database with confirmation (type 'NUKE')
- Exclude large execution tables to speed up migration:
  - AgentGraphExecution (1.3 GB)
  - AgentNodeExecution (6 GB)
  - AgentNodeExecutionInputOutput (30 GB)
  - AgentNodeExecutionKeyValueData
  - NotificationEvent (94 MB)
- Fix set -e issue with parse_args validation
- Clean up script structure and documentation

Reduces migration from ~37 GB to ~544 MB for initial cutover.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Swifty
2025-12-19 21:29:20 +01:00
parent f6af700f1a
commit e92459fc5f

634
autogpt_platform/backend/scripts/migrate_to_gcp.sh Normal file → Executable file
View File

@@ -2,31 +2,25 @@
#
# Database Migration Script: Supabase to GCP Cloud SQL
#
# This script automates the migration of the AutoGPT Platform database
# from a source PostgreSQL database to a destination PostgreSQL database.
# This script migrates the AutoGPT Platform database from Supabase to a new PostgreSQL instance.
#
# Migration Steps:
# 0. Nuke destination database (drop schema, recreate, apply migrations)
# 1. Export platform schema data from source
# 2. Export auth.users data from source (for password hashes, OAuth IDs)
# 3. Import platform schema data to destination
# 4. Update User table in destination with auth data
# 5. Refresh materialized views
#
# Prerequisites:
# - pg_dump and psql (PostgreSQL 15+)
# - poetry installed for Python scripts
# - poetry installed (for Prisma migrations)
# - Source and destination databases accessible
#
# Usage:
# cd backend
# chmod +x scripts/migrate_to_gcp.sh
# ./scripts/migrate_to_gcp.sh \
# --source "postgresql://user:pass@host:5432/db?schema=platform" \
# --dest "postgresql://user:pass@host:5433/db?schema=platform"
#
# Examples:
# # Full migration
# ./scripts/migrate_to_gcp.sh \
# --source "postgresql://postgres.xxx:password@aws-0-us-east-1.pooler.supabase.com:5432/postgres?schema=platform" \
# --dest "postgresql://postgres:password@127.0.0.1:5433/postgres?schema=platform"
#
# # Dry run (preview only)
# ./scripts/migrate_to_gcp.sh \
# --source "postgresql://..." \
# --dest "postgresql://..." \
# --dry-run
# --source 'postgresql://user:pass@host:5432/db?schema=platform' \
# --dest 'postgresql://user:pass@host:5432/db?schema=platform'
#
set -euo pipefail
@@ -36,13 +30,10 @@ RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
NC='\033[0m'
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$(dirname "$SCRIPT_DIR")"
# Configuration
BACKUP_DIR="${BACKEND_DIR}/migration_backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
@@ -50,308 +41,350 @@ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
SOURCE_URL=""
DEST_URL=""
DRY_RUN=false
SKIP_AUTH_MIGRATION=false
# Logging
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Usage help
usage() {
cat << EOF
Usage: $(basename "$0") --source <url> --dest <url> [options]
Required:
--source <url> Source database URL (e.g., postgresql://user:pass@host:5432/db?schema=platform)
--dest <url> Destination database URL (e.g., postgresql://user:pass@host:5433/db?schema=platform)
--source <url> Source database URL with ?schema=platform
--dest <url> Destination database URL with ?schema=platform
Options:
--dry-run Preview migration without making changes
--skip-auth Skip the Supabase auth migration step (if already done)
--help Show this help message
--dry-run Preview without making changes
--help Show this help
Examples:
# Migrate from Supabase to GCP
$(basename "$0") \\
--source "postgresql://postgres.xxx:pass@supabase.com:5432/postgres?schema=platform" \\
--dest "postgresql://postgres:pass@127.0.0.1:5433/postgres?schema=platform"
# Dry run to preview
$(basename "$0") --source "..." --dest "..." --dry-run
Migration Steps:
0. Nuke destination database (DROP SCHEMA, recreate, apply Prisma migrations)
1. Export platform schema data from source (READ-ONLY)
2. Export auth.users data from source (READ-ONLY)
3. Import platform data to destination
4. Update User table with auth data (passwords, OAuth IDs)
5. Refresh materialized views
EOF
exit 1
}
# Parse command line arguments
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--source)
SOURCE_URL="$2"
shift 2
;;
--dest)
DEST_URL="$2"
shift 2
;;
--dry-run)
DRY_RUN=true
shift
;;
--skip-auth)
SKIP_AUTH_MIGRATION=true
shift
;;
--help|-h)
usage
;;
*)
log_error "Unknown option: $1"
usage
;;
--source) SOURCE_URL="$2"; shift 2 ;;
--dest) DEST_URL="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
--help|-h) usage ;;
*) log_error "Unknown option: $1"; usage ;;
esac
done
# Validate required arguments
if [[ -z "$SOURCE_URL" ]]; then
log_error "Missing required argument: --source"
log_error "Missing --source"
usage
fi
if [[ -z "$DEST_URL" ]]; then
log_error "Missing required argument: --dest"
log_error "Missing --dest"
usage
fi
}
# Extract schema from URL (default to 'platform' if not specified)
get_schema_from_url() {
local url="$1"
local schema=$(echo "$url" | grep -oP 'schema=\K[^&]+' || echo "platform")
echo "$schema"
local schema=$(echo "$url" | sed -n 's/.*schema=\([^&]*\).*/\1/p')
echo "${schema:-platform}"
}
# Get URL without query params (for pg_dump/pg_restore)
get_base_url() {
local url="$1"
echo "${url%%\?*}"
}
# Check prerequisites
check_prerequisites() {
log_info "Checking prerequisites..."
local missing=()
if ! command -v pg_dump &> /dev/null; then
missing+=("pg_dump")
fi
if ! command -v psql &> /dev/null; then
missing+=("psql")
fi
if ! command -v poetry &> /dev/null; then
missing+=("poetry")
fi
if [ ${#missing[@]} -ne 0 ]; then
log_error "Missing required tools: ${missing[*]}"
log_error "Please install them before continuing."
exit 1
fi
# Check PostgreSQL version
local pg_version=$(pg_dump --version | grep -oE '[0-9]+' | head -1)
if [ "$pg_version" -lt 15 ]; then
log_warn "PostgreSQL version $pg_version detected. Version 15+ recommended."
fi
log_success "All prerequisites satisfied"
}
# Test database connections
test_connections() {
log_info "Testing source database connection..."
if ! psql "${SOURCE_URL}" -c "SELECT 1" &> /dev/null; then
log_error "Cannot connect to source database"
log_error "URL: ${SOURCE_URL%%:*}:****@${SOURCE_URL#*@}"
exit 1
fi
log_success "Source database connection OK"
local source_base=$(get_base_url "$SOURCE_URL")
local dest_base=$(get_base_url "$DEST_URL")
log_info "Testing destination database connection..."
if ! psql "${DEST_URL}" -c "SELECT 1" &> /dev/null; then
log_error "Cannot connect to destination database"
log_error "URL: ${DEST_URL%%:*}:****@${DEST_URL#*@}"
log_info "Testing source connection..."
if ! psql "${source_base}" -c "SELECT 1" > /dev/null 2>&1; then
log_error "Cannot connect to source database"
psql "${source_base}" -c "SELECT 1" 2>&1 || true
exit 1
fi
log_success "Destination database connection OK"
log_success "Source connection OK"
log_info "Testing destination connection..."
if ! psql "${dest_base}" -c "SELECT 1" > /dev/null 2>&1; then
log_error "Cannot connect to destination database"
psql "${dest_base}" -c "SELECT 1" 2>&1 || true
exit 1
fi
log_success "Destination connection OK"
}
# Run auth migration on source database
run_auth_migration() {
if [[ "$SKIP_AUTH_MIGRATION" == true ]]; then
log_info "Skipping auth migration (--skip-auth flag set)"
return
fi
# ============================================
# STEP 0: Nuke destination database
# ============================================
nuke_destination() {
local schema=$(get_schema_from_url "$DEST_URL")
local dest_base=$(get_base_url "$DEST_URL")
log_info "Running auth migration on source database..."
cd "${BACKEND_DIR}"
# Check if auth.users table exists
local auth_exists=$(psql "${SOURCE_URL}" -t -c "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'auth' AND table_name = 'users')" 2>/dev/null | tr -d ' ')
if [[ "$auth_exists" != "t" ]]; then
log_warn "No auth.users table found in source database"
log_warn "Skipping Supabase auth migration (may not be a Supabase database)"
return
fi
log_info "=== STEP 0: Nuking destination database ==="
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would run auth migration script"
DATABASE_URL="${SOURCE_URL}" \
DIRECT_URL="${SOURCE_URL}" \
poetry run python scripts/migrate_supabase_users.py --dry-run
else
# Apply Prisma migrations first
log_info "Applying Prisma migrations to source..."
DATABASE_URL="${SOURCE_URL}" \
DIRECT_URL="${SOURCE_URL}" \
poetry run prisma migrate deploy
# Run the Supabase user migration script
log_info "Migrating auth data from Supabase auth.users..."
DATABASE_URL="${SOURCE_URL}" \
DIRECT_URL="${SOURCE_URL}" \
poetry run python scripts/migrate_supabase_users.py
log_info "DRY RUN: Would drop and recreate schema '${schema}' in destination"
return
fi
log_success "Auth migration completed"
# Show what exists in destination
log_info "Current destination state:"
local user_count=$(psql "${dest_base}" -t -c "SELECT COUNT(*) FROM ${schema}.\"User\"" 2>/dev/null | tr -d ' ' || echo "0")
local graph_count=$(psql "${dest_base}" -t -c "SELECT COUNT(*) FROM ${schema}.\"AgentGraph\"" 2>/dev/null | tr -d ' ' || echo "0")
echo " - Users: ${user_count}"
echo " - AgentGraphs: ${graph_count}"
echo ""
log_warn "⚠️ WARNING: This will PERMANENTLY DELETE all data in the destination database!"
log_warn "Schema '${schema}' will be dropped and recreated."
echo ""
read -p "Type 'NUKE' to confirm deletion: " -r
echo ""
if [[ "$REPLY" != "NUKE" ]]; then
log_info "Cancelled - destination not modified"
exit 0
fi
log_info "Dropping schema '${schema}'..."
psql "${dest_base}" -c "DROP SCHEMA IF EXISTS ${schema} CASCADE;"
log_info "Recreating schema '${schema}'..."
psql "${dest_base}" -c "CREATE SCHEMA ${schema};"
log_info "Applying Prisma migrations..."
cd "${BACKEND_DIR}"
DATABASE_URL="${DEST_URL}" DIRECT_URL="${DEST_URL}" poetry run prisma migrate deploy
log_success "Destination database reset complete"
}
# Export database from source
export_database() {
# ============================================
# STEP 1: Export platform schema data
# ============================================
export_platform_data() {
local schema=$(get_schema_from_url "$SOURCE_URL")
local base_url=$(get_base_url "$SOURCE_URL")
local backup_file="${BACKUP_DIR}/platform_backup_${TIMESTAMP}.dump"
log_info "Exporting database from source (schema: ${schema})..."
local output_file="${BACKUP_DIR}/platform_data_${TIMESTAMP}.sql"
log_info "=== STEP 1: Exporting platform schema data ==="
mkdir -p "${BACKUP_DIR}"
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would export schema '${schema}' to ${backup_file}"
# Create empty file for dry run
touch "${backup_file}"
echo "$backup_file"
log_info "DRY RUN: Would export schema '${schema}' to ${output_file}"
log_info "DRY RUN: Excluding large execution tables"
touch "$output_file"
echo "$output_file"
return
fi
log_info "This may take a while depending on database size..."
log_info "Exporting from schema: ${schema}"
log_info "EXCLUDING: AgentGraphExecution, AgentNodeExecution, AgentNodeExecutionInputOutput, AgentNodeExecutionKeyValueData, NotificationEvent"
pg_dump "${base_url}" \
--schema="${schema}" \
--format=custom \
--format=plain \
--no-owner \
--no-privileges \
--verbose \
--file="${backup_file}" 2>&1 | while read line; do
echo -e "${BLUE}[pg_dump]${NC} $line"
done
local file_size=$(du -h "${backup_file}" | cut -f1)
log_success "Database exported to ${backup_file} (${file_size})"
echo "$backup_file"
}
# Set up schema on destination
setup_dest_schema() {
log_info "Setting up schema on destination database..."
cd "${BACKEND_DIR}"
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would deploy Prisma schema to destination"
return
fi
# Deploy Prisma schema to destination
DATABASE_URL="${DEST_URL}" \
DIRECT_URL="${DEST_URL}" \
poetry run prisma migrate deploy
log_success "Destination schema created via Prisma migrations"
}
# Import data to destination
import_database() {
local backup_file="$1"
local schema=$(get_schema_from_url "$DEST_URL")
local base_url=$(get_base_url "$DEST_URL")
log_info "Importing data to destination database..."
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would import ${backup_file} to destination"
return
fi
log_info "This may take a while..."
pg_restore \
--dbname="${base_url}" \
--schema="${schema}" \
--no-owner \
--no-privileges \
--verbose \
--data-only \
--disable-triggers \
"${backup_file}" 2>&1 | while read line; do
echo -e "${BLUE}[pg_restore]${NC} $line"
done || true # pg_restore returns non-zero on warnings
--exclude-table="${schema}.AgentGraphExecution" \
--exclude-table="${schema}.AgentNodeExecution" \
--exclude-table="${schema}.AgentNodeExecutionInputOutput" \
--exclude-table="${schema}.AgentNodeExecutionKeyValueData" \
--exclude-table="${schema}.NotificationEvent" \
--file="${output_file}" 2>&1
log_success "Data import completed"
# Remove Supabase-specific commands that break import
sed -i.bak '/\\restrict/d' "${output_file}"
rm -f "${output_file}.bak"
local size=$(du -h "${output_file}" | cut -f1)
log_success "Platform data exported: ${output_file} (${size})"
echo "$output_file"
}
# Refresh materialized views
# ============================================
# STEP 2: Export auth.users data
# ============================================
export_auth_data() {
local base_url=$(get_base_url "$SOURCE_URL")
local output_file="${BACKUP_DIR}/auth_users_${TIMESTAMP}.csv"
log_info "=== STEP 2: Exporting auth.users data ==="
# Check if auth.users exists
local auth_exists=$(psql "${base_url}" -t -c "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'auth' AND table_name = 'users')" 2>/dev/null | tr -d ' ')
if [[ "$auth_exists" != "t" ]]; then
log_warn "No auth.users table found - skipping auth export"
echo ""
return
fi
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would export auth.users to ${output_file}"
touch "$output_file"
echo "$output_file"
return
fi
log_info "Extracting auth data (passwords, OAuth IDs, email verification)..."
psql "${base_url}" -c "\COPY (
SELECT
id,
encrypted_password,
(email_confirmed_at IS NOT NULL) as email_verified,
CASE
WHEN raw_app_meta_data->>'provider' = 'google'
THEN raw_app_meta_data->>'provider_id'
ELSE NULL
END as google_id
FROM auth.users
WHERE encrypted_password IS NOT NULL
OR raw_app_meta_data->>'provider' = 'google'
) TO '${output_file}' WITH CSV HEADER"
local count=$(wc -l < "${output_file}" | tr -d ' ')
log_success "Auth data exported: ${output_file} (${count} rows including header)"
echo "$output_file"
}
# ============================================
# STEP 3: Import platform data to destination
# ============================================
import_platform_data() {
local platform_file="$1"
local dest_base=$(get_base_url "$DEST_URL")
log_info "=== STEP 3: Importing platform data to destination ==="
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would import ${platform_file} to destination"
return
fi
if [[ ! -f "$platform_file" ]]; then
log_error "Platform data file not found: ${platform_file}"
exit 1
fi
log_info "Importing platform data (this may take a while)..."
# Import with error logging
psql "${dest_base}" -f "${platform_file}" 2>&1 | tee "${BACKUP_DIR}/import_log_${TIMESTAMP}.txt" | head -100
log_success "Platform data import completed"
}
# ============================================
# STEP 4: Update User table with auth data
# ============================================
update_user_auth_data() {
local auth_file="$1"
local schema=$(get_schema_from_url "$DEST_URL")
local dest_base=$(get_base_url "$DEST_URL")
log_info "=== STEP 4: Updating User table with auth data ==="
if [[ -z "$auth_file" || ! -f "$auth_file" ]]; then
log_warn "No auth data file - skipping User auth update"
return
fi
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would update User table with auth data"
return
fi
log_info "Creating temporary table for auth data..."
psql "${dest_base}" << EOF
-- Create temp table for auth data
CREATE TEMP TABLE temp_auth_users (
id UUID,
encrypted_password TEXT,
email_verified BOOLEAN,
google_id TEXT
);
-- Import CSV
\COPY temp_auth_users FROM '${auth_file}' WITH CSV HEADER;
-- Update User table with password hashes
UPDATE ${schema}."User" u
SET "passwordHash" = t.encrypted_password
FROM temp_auth_users t
WHERE u.id = t.id
AND t.encrypted_password IS NOT NULL
AND u."passwordHash" IS NULL;
-- Update User table with email verification
UPDATE ${schema}."User" u
SET "emailVerified" = t.email_verified
FROM temp_auth_users t
WHERE u.id = t.id
AND t.email_verified = true;
-- Update User table with Google OAuth IDs
UPDATE ${schema}."User" u
SET "googleId" = t.google_id
FROM temp_auth_users t
WHERE u.id = t.id
AND t.google_id IS NOT NULL
AND u."googleId" IS NULL;
-- Show results
SELECT
'Total Users' as metric, COUNT(*)::text as value FROM ${schema}."User"
UNION ALL
SELECT 'With Password', COUNT(*)::text FROM ${schema}."User" WHERE "passwordHash" IS NOT NULL
UNION ALL
SELECT 'With Google OAuth', COUNT(*)::text FROM ${schema}."User" WHERE "googleId" IS NOT NULL
UNION ALL
SELECT 'Email Verified', COUNT(*)::text FROM ${schema}."User" WHERE "emailVerified" = true;
DROP TABLE temp_auth_users;
EOF
log_success "User auth data updated"
}
# ============================================
# STEP 5: Refresh materialized views
# ============================================
refresh_views() {
local schema=$(get_schema_from_url "$DEST_URL")
local dest_base=$(get_base_url "$DEST_URL")
log_info "Refreshing materialized views..."
log_info "=== STEP 5: Refreshing materialized views ==="
if [[ "$DRY_RUN" == true ]]; then
log_info "DRY RUN: Would refresh materialized views"
return
fi
psql "${DEST_URL}" <<EOF
psql "${dest_base}" << EOF
SET search_path TO ${schema};
-- Refresh materialized views
REFRESH MATERIALIZED VIEW "mv_agent_run_counts";
REFRESH MATERIALIZED VIEW "mv_review_stats";
-- Reset sequences
SELECT setval(
pg_get_serial_sequence('${schema}."SearchTerms"', 'id'),
COALESCE((SELECT MAX(id) FROM "${schema}"."SearchTerms"), 0) + 1,
COALESCE((SELECT MAX(id) FROM ${schema}."SearchTerms"), 0) + 1,
false
);
EOF
@@ -359,116 +392,91 @@ EOF
log_success "Materialized views refreshed"
}
# Verify migration
# ============================================
# Verification
# ============================================
verify_migration() {
log_info "Verifying migration..."
local source_base=$(get_base_url "$SOURCE_URL")
local dest_base=$(get_base_url "$DEST_URL")
local schema=$(get_schema_from_url "$SOURCE_URL")
log_info "=== VERIFICATION ==="
echo ""
echo "====== SOURCE DATABASE ROW COUNTS ======"
psql "${SOURCE_URL}" -f "${SCRIPT_DIR}/verify_migration.sql"
echo "Source counts:"
psql "${source_base}" -c "SELECT 'User' as table_name, COUNT(*) FROM ${schema}.\"User\" UNION ALL SELECT 'AgentGraph', COUNT(*) FROM ${schema}.\"AgentGraph\" UNION ALL SELECT 'Profile', COUNT(*) FROM ${schema}.\"Profile\""
echo ""
echo "====== DESTINATION DATABASE ROW COUNTS ======"
psql "${DEST_URL}" -f "${SCRIPT_DIR}/verify_migration.sql"
echo ""
log_info "Compare the counts above to verify migration success"
echo "Destination counts:"
psql "${dest_base}" -c "SELECT 'User' as table_name, COUNT(*) FROM ${schema}.\"User\" UNION ALL SELECT 'AgentGraph', COUNT(*) FROM ${schema}.\"AgentGraph\" UNION ALL SELECT 'Profile', COUNT(*) FROM ${schema}.\"Profile\""
}
# Print summary
print_summary() {
local backup_file="$1"
echo ""
echo "========================================"
echo " MIGRATION COMPLETE"
echo "========================================"
echo ""
log_success "Database has been migrated successfully"
echo ""
echo "Backup file: ${backup_file}"
echo ""
echo "Next steps:"
echo " 1. Verify the row counts above match"
echo " 2. Update your application's DATABASE_URL to point to destination"
echo " 3. Restart your application services"
echo " 4. Test login with existing user credentials"
echo " 5. Keep source database available for 48 hours as backup"
echo ""
}
# Main execution
# ============================================
# Main
# ============================================
main() {
echo ""
echo "========================================"
echo " Database Migration Script"
echo " Database Migration Script"
echo "========================================"
echo ""
parse_args "$@"
# Mask passwords in output
local source_display="${SOURCE_URL%%:*}://****@${SOURCE_URL#*@}"
local dest_display="${DEST_URL%%:*}://****@${DEST_URL#*@}"
log_info "Source: ${source_display}"
log_info "Destination: ${dest_display}"
if [[ "$DRY_RUN" == true ]]; then
log_warn "DRY RUN MODE - No changes will be made"
fi
log_info "Source: $(get_base_url "$SOURCE_URL")"
log_info "Destination: $(get_base_url "$DEST_URL")"
[[ "$DRY_RUN" == true ]] && log_warn "DRY RUN MODE"
echo ""
check_prerequisites
test_connections
echo ""
# Step 0: Nuke destination database (with confirmation)
nuke_destination
echo ""
if [[ "$DRY_RUN" != true ]]; then
echo ""
log_warn "This will perform a database migration."
log_warn "Ensure application services are stopped to prevent data loss."
echo ""
log_warn "This will migrate data to the destination database."
read -p "Continue with migration? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "Migration cancelled"
exit 0
fi
[[ ! $REPLY =~ ^[Yy]$ ]] && { log_info "Cancelled"; exit 0; }
fi
echo ""
log_info "Starting migration at $(date)"
echo ""
# Step 1: Auth migration on source
run_auth_migration
# Step 1: Export platform data (READ-ONLY on source)
platform_file=$(export_platform_data)
echo ""
# Step 2: Export from source
backup_file=$(export_database)
# Step 2: Export auth data (READ-ONLY on source)
auth_file=$(export_auth_data)
echo ""
# Step 3: Set up destination schema
setup_dest_schema
# Step 3: Import platform data to destination
import_platform_data "$platform_file"
echo ""
# Step 4: Import to destination
import_database "$backup_file"
# Step 4: Update User table with auth data
update_user_auth_data "$auth_file"
echo ""
# Step 5: Post-import tasks
# Step 5: Refresh materialized views
refresh_views
echo ""
# Step 6: Verify
# Verification
verify_migration
# Summary
if [[ "$DRY_RUN" != true ]]; then
print_summary "$backup_file"
else
echo ""
log_info "DRY RUN COMPLETE - No changes were made"
echo ""
fi
log_info "Finished at $(date)"
echo ""
log_success "Migration completed at $(date)"
echo ""
echo "Files created:"
echo " - Platform data: ${platform_file}"
[[ -n "$auth_file" ]] && echo " - Auth data: ${auth_file}"
echo ""
}
# Run main function
main "$@"