sharenet/scripts/migrate.sh
continuist 4988a397f1
Some checks are pending
CI/CD Pipeline / Test Backend (push) Waiting to run
CI/CD Pipeline / Test Frontend (push) Waiting to run
CI/CD Pipeline / Build and Push Docker Images (push) Blocked by required conditions
CI/CD Pipeline / Deploy to Production (push) Blocked by required conditions
Added deploy and migrate scripts and made sure they were consistent
2025-06-28 01:26:38 -04:00

317 lines
No EOL
8.6 KiB
Bash

#!/bin/bash
# Sharenet Database Migration Script
# This script handles database migrations in production environments
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
MIGRATIONS_DIR="backend/migrations"
BACKUP_DIR="backups"
DATABASE_URL="${DATABASE_URL:-}"
DRY_RUN="${DRY_RUN:-false}"
VERBOSE="${VERBOSE:-false}"
# Functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
show_help() {
cat << EOF
Sharenet Database Migration Script
Usage: $0 [COMMAND] [OPTIONS]
Commands:
run Run pending migrations
status Show migration status
create Create a new migration file
revert Revert the last migration
backup Create a backup before migration
restore Restore from backup
Options:
--dry-run Show what would be done without executing
--verbose Show detailed output
--help Show this help message
Environment Variables:
DATABASE_URL Database connection string
DRY_RUN Set to 'true' for dry run mode
VERBOSE Set to 'true' for verbose output
Examples:
$0 run # Run pending migrations
$0 status # Show migration status
$0 create add_user_table # Create new migration
DRY_RUN=true $0 run # Dry run migrations
EOF
}
check_dependencies() {
log_info "Checking dependencies..."
if ! command -v sqlx &> /dev/null; then
log_error "sqlx CLI not found. Install with: cargo install sqlx-cli"
exit 1
fi
if [ -z "$DATABASE_URL" ]; then
log_error "DATABASE_URL environment variable is required"
exit 1
fi
log_success "Dependencies check passed"
}
check_connection() {
log_info "Testing database connection..."
# Check if we're running in Docker environment
if [ -f /.dockerenv ] || [ -f /proc/1/cgroup ] && grep -q docker /proc/1/cgroup; then
log_info "Detected Docker environment"
# In Docker, use the service name as host
if [[ "$DATABASE_URL" == *"localhost"* ]] || [[ "$DATABASE_URL" == *"127.0.0.1"* ]]; then
log_info "Updating DATABASE_URL for Docker environment"
export DATABASE_URL=$(echo "$DATABASE_URL" | sed 's/localhost/postgres/g' | sed 's/127.0.0.1/postgres/g')
fi
fi
if ! sqlx database create --database-url "$DATABASE_URL" 2>/dev/null; then
log_warning "Database might already exist, continuing..."
fi
if ! sqlx migrate info --database-url "$DATABASE_URL" >/dev/null 2>&1; then
log_error "Cannot connect to database. Check DATABASE_URL and network connectivity"
log_error "DATABASE_URL: $DATABASE_URL"
exit 1
fi
log_success "Database connection successful"
}
run_migrations() {
log_info "Running database migrations..."
if [ "$DRY_RUN" = "true" ]; then
log_warning "DRY RUN MODE - No changes will be made"
sqlx migrate info --database-url "$DATABASE_URL"
return
fi
# Show current status
sqlx migrate info --database-url "$DATABASE_URL"
# Run migrations
if sqlx migrate run --database-url "$DATABASE_URL"; then
log_success "Migrations completed successfully"
# Show final status
log_info "Final migration status:"
sqlx migrate info --database-url "$DATABASE_URL"
else
log_error "Migration failed"
exit 1
fi
}
show_status() {
log_info "Migration status:"
sqlx migrate info --database-url "$DATABASE_URL"
}
create_migration() {
if [ $# -eq 0 ]; then
log_error "Migration name is required"
echo "Usage: $0 create <migration_name>"
exit 1
fi
local migration_name="$1"
log_info "Creating migration: $migration_name"
if [ "$DRY_RUN" = "true" ]; then
log_warning "DRY RUN MODE - Migration file would be created"
echo "sqlx migrate add $migration_name"
return
fi
if sqlx migrate add --database-url "$DATABASE_URL" "$migration_name"; then
log_success "Migration file created successfully"
log_info "Edit the generated file in $MIGRATIONS_DIR/"
else
log_error "Failed to create migration file"
exit 1
fi
}
revert_migration() {
log_warning "Reverting last migration..."
if [ "$DRY_RUN" = "true" ]; then
log_warning "DRY RUN MODE - No changes will be made"
return
fi
if sqlx migrate revert --database-url "$DATABASE_URL"; then
log_success "Migration reverted successfully"
else
log_error "Failed to revert migration"
exit 1
fi
}
backup_database() {
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
local backup_file="$BACKUP_DIR/backup_$(date +%Y%m%d_%H%M%S).sql"
log_info "Creating database backup: $backup_file"
if [ "$DRY_RUN" = "true" ]; then
log_warning "DRY RUN MODE - Backup would be created"
return
fi
# Extract connection details from DATABASE_URL
local db_host=$(echo "$DATABASE_URL" | sed -n 's/.*@\([^:]*\).*/\1/p')
local db_port=$(echo "$DATABASE_URL" | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
local db_name=$(echo "$DATABASE_URL" | sed -n 's/.*\/\([^?]*\).*/\1/p')
local db_user=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
local db_pass=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
# Set PGPASSWORD for pg_dump
export PGPASSWORD="$db_pass"
if pg_dump -h "$db_host" -p "$db_port" -U "$db_user" -d "$db_name" > "$backup_file"; then
log_success "Backup created: $backup_file"
else
log_error "Backup failed"
exit 1
fi
}
restore_database() {
if [ $# -eq 0 ]; then
log_error "Backup file is required"
echo "Usage: $0 restore <backup_file>"
exit 1
fi
local backup_file="$1"
# If backup file doesn't have a path, assume it's in BACKUP_DIR
if [[ "$backup_file" != */* ]]; then
backup_file="$BACKUP_DIR/$backup_file"
fi
if [ ! -f "$backup_file" ]; then
log_error "Backup file not found: $backup_file"
exit 1
fi
log_warning "Restoring database from: $backup_file"
log_warning "This will overwrite the current database!"
if [ "$DRY_RUN" = "true" ]; then
log_warning "DRY RUN MODE - No changes will be made"
return
fi
read -p "Are you sure you want to continue? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "Restore cancelled"
exit 0
fi
# Extract connection details from DATABASE_URL
local db_host=$(echo "$DATABASE_URL" | sed -n 's/.*@\([^:]*\).*/\1/p')
local db_port=$(echo "$DATABASE_URL" | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
local db_name=$(echo "$DATABASE_URL" | sed -n 's/.*\/\([^?]*\).*/\1/p')
local db_user=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
local db_pass=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
# Set PGPASSWORD for psql
export PGPASSWORD="$db_pass"
if psql -h "$db_host" -p "$db_port" -U "$db_user" -d "$db_name" < "$backup_file"; then
log_success "Database restored successfully"
else
log_error "Restore failed"
exit 1
fi
}
# Main script logic
main() {
local command="${1:-}"
case "$command" in
run)
check_dependencies
check_connection
run_migrations
;;
status)
check_dependencies
check_connection
show_status
;;
create)
check_dependencies
create_migration "${@:2}"
;;
revert)
check_dependencies
check_connection
revert_migration
;;
backup)
check_dependencies
check_connection
backup_database
;;
restore)
check_dependencies
check_connection
restore_database "${@:2}"
;;
help|--help|-h)
show_help
;;
"")
log_error "No command provided"
show_help
exit 1
;;
*)
log_error "Unknown command: $command"
show_help
exit 1
;;
esac
}
# Run main function with all arguments
main "$@"