All checks were successful
Deploy to Staging / Build Images (push) Successful in 3m28s
Deploy to Staging / Deploy to Staging (push) Successful in 27s
Deploy to Staging / Verify Staging (push) Successful in 5s
Deploy to Staging / Notify Staging Ready (push) Successful in 5s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
443 lines
13 KiB
Bash
Executable File
443 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
# Database Export Script for MotoVaultPro
|
|
# Exports PostgreSQL database for deployment migration
|
|
# Usage: ./scripts/export-database.sh [options]
|
|
|
|
# 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
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
EXPORT_DIR="${PROJECT_ROOT}/database-exports"
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
|
|
# Environment-based container names
|
|
CONTAINER_NAME="" # Will be set based on environment selection
|
|
ENVIRONMENT="" # production or staging
|
|
|
|
# Default values
|
|
EXPORT_FORMAT="sql"
|
|
COMPRESS=true
|
|
INCLUDE_SCHEMA=true
|
|
INCLUDE_DATA=true
|
|
EXPORT_NAME="" # Will be set after environment selection
|
|
|
|
# Function to print colored output
|
|
print_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
print_env() {
|
|
echo -e "${BLUE}[ENV]${NC} $1"
|
|
}
|
|
|
|
# Function to select environment
|
|
select_environment() {
|
|
if [ -n "$ENVIRONMENT" ]; then
|
|
# Environment already set via command line
|
|
return
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE} MotoVaultPro Database Export${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo ""
|
|
echo "Select environment to export from:"
|
|
echo ""
|
|
echo " 1) Production (mvp-postgres)"
|
|
echo " 2) Staging (mvp-postgres-staging)"
|
|
echo ""
|
|
read -p "Enter choice [1-2]: " ENV_CHOICE
|
|
|
|
case $ENV_CHOICE in
|
|
1)
|
|
ENVIRONMENT="production"
|
|
CONTAINER_NAME="mvp-postgres"
|
|
;;
|
|
2)
|
|
ENVIRONMENT="staging"
|
|
CONTAINER_NAME="mvp-postgres-staging"
|
|
;;
|
|
*)
|
|
print_error "Invalid choice. Please enter 1 or 2."
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo ""
|
|
print_env "Selected environment: ${ENVIRONMENT}"
|
|
print_env "Container: ${CONTAINER_NAME}"
|
|
echo ""
|
|
}
|
|
|
|
# Function to set container name based on environment
|
|
set_container_from_environment() {
|
|
case $ENVIRONMENT in
|
|
production|prod)
|
|
ENVIRONMENT="production"
|
|
CONTAINER_NAME="mvp-postgres"
|
|
;;
|
|
staging|stage)
|
|
ENVIRONMENT="staging"
|
|
CONTAINER_NAME="mvp-postgres-staging"
|
|
;;
|
|
*)
|
|
print_error "Invalid environment: $ENVIRONMENT"
|
|
print_error "Valid options: production, staging"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to show usage
|
|
show_usage() {
|
|
cat << EOF
|
|
Database Export Script for MotoVaultPro
|
|
|
|
Usage: $0 [options]
|
|
|
|
Options:
|
|
-h, --help Show this help message
|
|
-e, --env ENV Environment: production or staging (prompts if not specified)
|
|
-f, --format FORMAT Export format: sql, custom, directory (default: sql)
|
|
-o, --output NAME Custom export filename (without extension)
|
|
-n, --no-compress Don't compress the export
|
|
--schema-only Export schema only (no data)
|
|
--data-only Export data only (no schema)
|
|
--exclude-table TABLE Exclude specific table(s) (can be used multiple times)
|
|
--include-table TABLE Include only specific table(s) (can be used multiple times)
|
|
-c, --container NAME Override container name (ignores environment selection)
|
|
|
|
Environments:
|
|
production (prod) Uses container: mvp-postgres
|
|
staging (stage) Uses container: mvp-postgres-staging
|
|
|
|
Examples:
|
|
# Interactive environment selection
|
|
$0
|
|
|
|
# Export from production
|
|
$0 --env production
|
|
|
|
# Export from staging
|
|
$0 --env staging
|
|
|
|
# Schema only export from production
|
|
$0 --env prod --schema-only
|
|
|
|
# Export specific tables from staging
|
|
$0 -e staging --include-table vehicles --include-table fuel_logs
|
|
|
|
# Custom format for pg_restore
|
|
$0 --env production --format custom --output my_backup
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
# Parse command line arguments
|
|
EXCLUDE_TABLES=()
|
|
INCLUDE_TABLES=()
|
|
CONTAINER_OVERRIDE=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
show_usage
|
|
;;
|
|
-e|--env)
|
|
ENVIRONMENT="$2"
|
|
shift 2
|
|
;;
|
|
-f|--format)
|
|
EXPORT_FORMAT="$2"
|
|
shift 2
|
|
;;
|
|
-o|--output)
|
|
EXPORT_NAME="$2"
|
|
shift 2
|
|
;;
|
|
-n|--no-compress)
|
|
COMPRESS=false
|
|
shift
|
|
;;
|
|
--schema-only)
|
|
INCLUDE_DATA=false
|
|
shift
|
|
;;
|
|
--data-only)
|
|
INCLUDE_SCHEMA=false
|
|
shift
|
|
;;
|
|
--exclude-table)
|
|
EXCLUDE_TABLES+=("$2")
|
|
shift 2
|
|
;;
|
|
--include-table)
|
|
INCLUDE_TABLES+=("$2")
|
|
shift 2
|
|
;;
|
|
-c|--container)
|
|
CONTAINER_OVERRIDE="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
print_error "Unknown option: $1"
|
|
show_usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Handle environment selection
|
|
if [ -n "$CONTAINER_OVERRIDE" ]; then
|
|
# Container explicitly specified, use it directly
|
|
CONTAINER_NAME="$CONTAINER_OVERRIDE"
|
|
ENVIRONMENT="custom"
|
|
print_info "Using custom container: $CONTAINER_NAME"
|
|
elif [ -n "$ENVIRONMENT" ]; then
|
|
# Environment specified via command line
|
|
set_container_from_environment
|
|
else
|
|
# No environment specified, prompt user
|
|
select_environment
|
|
fi
|
|
|
|
# Set default export name with environment prefix
|
|
if [ -z "$EXPORT_NAME" ]; then
|
|
EXPORT_NAME="motovaultpro_${ENVIRONMENT}_export_${TIMESTAMP}"
|
|
fi
|
|
|
|
# Create export directory if it doesn't exist
|
|
mkdir -p "${EXPORT_DIR}"
|
|
|
|
# Check if container is running
|
|
print_info "Checking if PostgreSQL container is running..."
|
|
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
print_error "PostgreSQL container '${CONTAINER_NAME}' is not running"
|
|
print_info "Start it with: docker compose up -d mvp-postgres"
|
|
exit 1
|
|
fi
|
|
|
|
# Build pg_dump options
|
|
PG_DUMP_OPTS=""
|
|
|
|
# Schema/Data options
|
|
if [ "$INCLUDE_SCHEMA" = false ]; then
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --data-only"
|
|
fi
|
|
|
|
if [ "$INCLUDE_DATA" = false ]; then
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --schema-only"
|
|
fi
|
|
|
|
# Format options
|
|
case $EXPORT_FORMAT in
|
|
sql)
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --format=plain"
|
|
EXPORT_EXT="sql"
|
|
;;
|
|
custom)
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --format=custom"
|
|
EXPORT_EXT="dump"
|
|
COMPRESS=false # Custom format is already compressed
|
|
;;
|
|
directory)
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --format=directory"
|
|
EXPORT_EXT="dir"
|
|
COMPRESS=false # Directory format doesn't need compression
|
|
;;
|
|
*)
|
|
print_error "Invalid format: $EXPORT_FORMAT"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Exclude tables
|
|
for table in "${EXCLUDE_TABLES[@]}"; do
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --exclude-table=$table"
|
|
done
|
|
|
|
# Include tables
|
|
for table in "${INCLUDE_TABLES[@]}"; do
|
|
PG_DUMP_OPTS="$PG_DUMP_OPTS --table=$table"
|
|
done
|
|
|
|
# Set output file path
|
|
if [ "$EXPORT_FORMAT" = "directory" ]; then
|
|
OUTPUT_PATH="${EXPORT_DIR}/${EXPORT_NAME}.${EXPORT_EXT}"
|
|
mkdir -p "${OUTPUT_PATH}"
|
|
else
|
|
OUTPUT_PATH="${EXPORT_DIR}/${EXPORT_NAME}.${EXPORT_EXT}"
|
|
fi
|
|
|
|
# Export database
|
|
print_info "Starting database export..."
|
|
print_info "Environment: ${ENVIRONMENT}"
|
|
print_info "Container: ${CONTAINER_NAME}"
|
|
print_info "Format: ${EXPORT_FORMAT}"
|
|
print_info "Output: ${OUTPUT_PATH}"
|
|
|
|
if [ "$EXPORT_FORMAT" = "directory" ]; then
|
|
# For directory format, we need to export inside container then copy out
|
|
docker exec "$CONTAINER_NAME" sh -c "pg_dump -U postgres -d motovaultpro $PG_DUMP_OPTS -f /tmp/export_dir" || {
|
|
print_error "Database export failed"
|
|
exit 1
|
|
}
|
|
docker cp "${CONTAINER_NAME}:/tmp/export_dir/." "${OUTPUT_PATH}/"
|
|
docker exec "$CONTAINER_NAME" rm -rf /tmp/export_dir
|
|
else
|
|
# For SQL and custom formats
|
|
docker exec "$CONTAINER_NAME" pg_dump -U postgres -d motovaultpro $PG_DUMP_OPTS > "${OUTPUT_PATH}" || {
|
|
print_error "Database export failed"
|
|
exit 1
|
|
}
|
|
fi
|
|
|
|
print_info "Database exported successfully"
|
|
|
|
# Compress if requested and format is SQL
|
|
if [ "$COMPRESS" = true ] && [ "$EXPORT_FORMAT" = "sql" ]; then
|
|
print_info "Compressing export..."
|
|
gzip "${OUTPUT_PATH}"
|
|
OUTPUT_PATH="${OUTPUT_PATH}.gz"
|
|
print_info "Compressed to: ${OUTPUT_PATH}"
|
|
fi
|
|
|
|
# Create metadata file
|
|
METADATA_FILE="${EXPORT_DIR}/${EXPORT_NAME}_metadata.json"
|
|
cat > "${METADATA_FILE}" << EOF
|
|
{
|
|
"export_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
"environment": "${ENVIRONMENT}",
|
|
"container_name": "${CONTAINER_NAME}",
|
|
"database_name": "motovaultpro",
|
|
"export_format": "${EXPORT_FORMAT}",
|
|
"compressed": ${COMPRESS},
|
|
"schema_included": ${INCLUDE_SCHEMA},
|
|
"data_included": ${INCLUDE_DATA},
|
|
"postgresql_version": "$(docker exec "$CONTAINER_NAME" psql -U postgres -t -c 'SELECT version();' | xargs)",
|
|
"file_path": "${OUTPUT_PATH}",
|
|
"file_size": "$(du -h "${OUTPUT_PATH}" | cut -f1)"
|
|
}
|
|
EOF
|
|
|
|
print_info "Metadata saved to: ${METADATA_FILE}"
|
|
|
|
# Generate import instructions
|
|
IMPORT_INSTRUCTIONS="${EXPORT_DIR}/${EXPORT_NAME}_import_instructions.txt"
|
|
cat > "${IMPORT_INSTRUCTIONS}" << EOF
|
|
===========================================
|
|
MotoVaultPro Database Import Instructions
|
|
===========================================
|
|
|
|
Export Details:
|
|
- Export Date: $(date)
|
|
- Format: ${EXPORT_FORMAT}
|
|
- Compressed: ${COMPRESS}
|
|
- File: ${OUTPUT_PATH}
|
|
|
|
Import Instructions:
|
|
--------------------
|
|
|
|
1. Copy the export file to your target server:
|
|
scp ${OUTPUT_PATH} user@server:/path/to/import/
|
|
|
|
EOF
|
|
|
|
if [ "$EXPORT_FORMAT" = "sql" ]; then
|
|
if [ "$COMPRESS" = true ]; then
|
|
cat >> "${IMPORT_INSTRUCTIONS}" << EOF
|
|
2. Import the database (compressed SQL):
|
|
# Using Docker:
|
|
gunzip -c /path/to/import/$(basename "${OUTPUT_PATH}") | docker exec -i mvp-postgres psql -U postgres -d motovaultpro
|
|
|
|
# Direct PostgreSQL:
|
|
gunzip -c /path/to/import/$(basename "${OUTPUT_PATH}") | psql -U postgres -d motovaultpro
|
|
EOF
|
|
else
|
|
cat >> "${IMPORT_INSTRUCTIONS}" << EOF
|
|
2. Import the database (SQL):
|
|
# Using Docker:
|
|
docker exec -i mvp-postgres psql -U postgres -d motovaultpro < /path/to/import/$(basename "${OUTPUT_PATH}")
|
|
|
|
# Direct PostgreSQL:
|
|
psql -U postgres -d motovaultpro < /path/to/import/$(basename "${OUTPUT_PATH}")
|
|
EOF
|
|
fi
|
|
elif [ "$EXPORT_FORMAT" = "custom" ]; then
|
|
cat >> "${IMPORT_INSTRUCTIONS}" << EOF
|
|
2. Import the database (custom format):
|
|
# Using Docker:
|
|
docker cp /path/to/import/$(basename "${OUTPUT_PATH}") mvp-postgres:/tmp/restore.dump
|
|
docker exec mvp-postgres pg_restore -U postgres -d motovaultpro -c /tmp/restore.dump
|
|
|
|
# Direct PostgreSQL:
|
|
pg_restore -U postgres -d motovaultpro -c /path/to/import/$(basename "${OUTPUT_PATH}")
|
|
EOF
|
|
elif [ "$EXPORT_FORMAT" = "directory" ]; then
|
|
cat >> "${IMPORT_INSTRUCTIONS}" << EOF
|
|
2. Import the database (directory format):
|
|
# Using Docker:
|
|
docker cp /path/to/import/$(basename "${OUTPUT_PATH}") mvp-postgres:/tmp/restore_dir
|
|
docker exec mvp-postgres pg_restore -U postgres -d motovaultpro -c /tmp/restore_dir
|
|
|
|
# Direct PostgreSQL:
|
|
pg_restore -U postgres -d motovaultpro -c /path/to/import/$(basename "${OUTPUT_PATH}")
|
|
EOF
|
|
fi
|
|
|
|
cat >> "${IMPORT_INSTRUCTIONS}" << EOF
|
|
|
|
Notes:
|
|
------
|
|
- The -c flag drops existing database objects before recreating them
|
|
- Ensure the target database exists before importing
|
|
- For production imports, always test on a staging environment first
|
|
- Consider creating a backup of the target database before importing
|
|
|
|
Create target database:
|
|
-----------------------
|
|
docker exec -i mvp-postgres psql -U postgres -c "CREATE DATABASE motovaultpro;"
|
|
|
|
Or if database exists and you want to start fresh:
|
|
--------------------------------------------------
|
|
docker exec -i mvp-postgres psql -U postgres -c "DROP DATABASE IF EXISTS motovaultpro;"
|
|
docker exec -i mvp-postgres psql -U postgres -c "CREATE DATABASE motovaultpro;"
|
|
|
|
EOF
|
|
|
|
print_info "Import instructions saved to: ${IMPORT_INSTRUCTIONS}"
|
|
|
|
# Summary
|
|
echo ""
|
|
print_info "==============================================="
|
|
print_info "Database Export Complete!"
|
|
print_info "==============================================="
|
|
print_info "Environment: ${ENVIRONMENT}"
|
|
print_info "Container: ${CONTAINER_NAME}"
|
|
print_info "Export file: ${OUTPUT_PATH}"
|
|
print_info "Metadata: ${METADATA_FILE}"
|
|
print_info "Instructions: ${IMPORT_INSTRUCTIONS}"
|
|
print_info "Size: $(du -h "${OUTPUT_PATH}" | cut -f1)"
|
|
echo ""
|
|
print_info "To import this database on another deployment:"
|
|
print_info "1. Copy the export file to the target server"
|
|
print_info "2. Follow the instructions in ${IMPORT_INSTRUCTIONS}"
|
|
echo ""
|