fix: I dunno, I'm making git server changes

This commit is contained in:
Eric Gullickson
2025-12-29 08:44:49 -06:00
parent 57d2c43da7
commit 9b0de6a5b8
18 changed files with 2584 additions and 512 deletions

220
scripts/ci/maintenance-migrate.sh Executable file
View File

@@ -0,0 +1,220 @@
#!/bin/bash
# Maintenance mode migration script
# Enables maintenance mode, runs migrations, then restores service
#
# Usage: ./maintenance-migrate.sh [backup]
# backup: If set, creates a database backup before migration
#
# This script is for BREAKING migrations that require downtime.
# Non-breaking migrations run automatically on container start.
#
# Exit codes:
# 0 - Migration successful
# 1 - Migration failed (maintenance mode will remain active)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CREATE_BACKUP="${1:-}"
COMPOSE_FILE="$PROJECT_ROOT/docker-compose.yml"
COMPOSE_BLUE_GREEN="$PROJECT_ROOT/docker-compose.blue-green.yml"
STATE_FILE="$PROJECT_ROOT/config/deployment/state.json"
NOTIFY_SCRIPT="$SCRIPT_DIR/notify.sh"
TRAEFIK_CONFIG="$PROJECT_ROOT/config/traefik/dynamic/blue-green.yml"
BACKUP_DIR="$PROJECT_ROOT/data/backups"
echo "========================================"
echo "MAINTENANCE MODE MIGRATION"
echo "Time: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
echo "========================================"
# Determine active stack
if [[ -f "$STATE_FILE" ]] && command -v jq &> /dev/null; then
ACTIVE_STACK=$(jq -r '.active_stack // "blue"' "$STATE_FILE")
else
ACTIVE_STACK="blue"
fi
BACKEND_CONTAINER="mvp-backend-$ACTIVE_STACK"
echo ""
echo "Configuration:"
echo " Active stack: $ACTIVE_STACK"
echo " Backend container: $BACKEND_CONTAINER"
echo " Create backup: ${CREATE_BACKUP:-no}"
echo ""
# Step 1: Send maintenance notification
echo "Step 1/6: Sending maintenance notification..."
echo "----------------------------------------"
if [[ -x "$NOTIFY_SCRIPT" ]]; then
"$NOTIFY_SCRIPT" "maintenance_start" "Starting maintenance window for database migration" || true
fi
echo " OK"
# Step 2: Enable maintenance mode
echo ""
echo "Step 2/6: Enabling maintenance mode..."
echo "----------------------------------------"
# Update state file
if [[ -f "$STATE_FILE" ]] && command -v jq &> /dev/null; then
jq '.maintenance_mode = true' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
fi
# Stop traffic to both stacks (weight 0)
echo " Stopping traffic to application stacks..."
# Set both stacks to weight 0 - Traefik will return 503
sed -i.bak -E "s/(name: mvp-frontend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 0/" "$TRAEFIK_CONFIG"
sed -i.bak -E "s/(name: mvp-frontend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 0/" "$TRAEFIK_CONFIG"
sed -i.bak -E "s/(name: mvp-backend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 0/" "$TRAEFIK_CONFIG"
sed -i.bak -E "s/(name: mvp-backend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 0/" "$TRAEFIK_CONFIG"
rm -f "${TRAEFIK_CONFIG}.bak"
# Wait for Traefik to pick up changes
sleep 3
echo " OK: Maintenance mode active"
# Step 3: Create database backup (if requested)
if [[ -n "$CREATE_BACKUP" ]]; then
echo ""
echo "Step 3/6: Creating database backup..."
echo "----------------------------------------"
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="$BACKUP_DIR/pre-migration-$(date +%Y%m%d-%H%M%S).sql"
if docker exec mvp-postgres pg_dump -U postgres motovaultpro > "$BACKUP_FILE"; then
echo " OK: Backup created: $BACKUP_FILE"
ls -lh "$BACKUP_FILE"
else
echo " ERROR: Backup failed"
echo ""
echo "Aborting migration. Restoring traffic..."
# Restore traffic
if [[ "$ACTIVE_STACK" == "blue" ]]; then
sed -i -E "s/(name: mvp-frontend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
sed -i -E "s/(name: mvp-backend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
else
sed -i -E "s/(name: mvp-frontend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
sed -i -E "s/(name: mvp-backend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
fi
if [[ -f "$STATE_FILE" ]] && command -v jq &> /dev/null; then
jq '.maintenance_mode = false' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
fi
exit 1
fi
else
echo ""
echo "Step 3/6: Skipping backup (not requested)..."
echo "----------------------------------------"
echo " OK"
fi
# Step 4: Run migrations
echo ""
echo "Step 4/6: Running database migrations..."
echo "----------------------------------------"
# Flush Redis cache before migration
echo " Flushing Redis cache..."
docker exec mvp-redis redis-cli FLUSHALL > /dev/null 2>&1 || true
# Run migrations
echo " Running migrations..."
if docker exec "$BACKEND_CONTAINER" npm run migrate; then
echo " OK: Migrations completed"
else
echo " ERROR: Migration failed"
echo ""
echo "Migration failed. Maintenance mode remains active."
echo "To restore:"
echo " 1. Fix migration issues"
echo " 2. Re-run migrations: docker exec $BACKEND_CONTAINER npm run migrate"
echo " 3. Run: $0 to retry, or manually restore traffic"
if [[ -x "$NOTIFY_SCRIPT" ]]; then
"$NOTIFY_SCRIPT" "failure" "Database migration failed during maintenance window. Manual intervention required." || true
fi
exit 1
fi
# Step 5: Restart backend containers
echo ""
echo "Step 5/6: Restarting backend containers..."
echo "----------------------------------------"
# Restart both backends to pick up any schema changes
docker restart mvp-backend-blue mvp-backend-green 2>/dev/null || true
# Wait for backends to be healthy
echo " Waiting for backends to be healthy..."
sleep 10
for container in mvp-backend-blue mvp-backend-green; do
for i in {1..12}; do
health=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "unknown")
if [[ "$health" == "healthy" ]]; then
echo " OK: $container is healthy"
break
fi
if [[ $i -eq 12 ]]; then
echo " WARNING: $container health check timeout"
fi
sleep 5
done
done
# Step 6: Disable maintenance mode
echo ""
echo "Step 6/6: Restoring traffic..."
echo "----------------------------------------"
# Restore traffic to active stack
if [[ "$ACTIVE_STACK" == "blue" ]]; then
sed -i -E "s/(name: mvp-frontend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
sed -i -E "s/(name: mvp-backend-blue-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
else
sed -i -E "s/(name: mvp-frontend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
sed -i -E "s/(name: mvp-backend-green-svc[[:space:]]+weight:)[[:space:]]+[0-9]+/\1 100/" "$TRAEFIK_CONFIG"
fi
# Update state file
if [[ -f "$STATE_FILE" ]] && command -v jq &> /dev/null; then
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
jq --arg ts "$TIMESTAMP" '.maintenance_mode = false | .last_migration = $ts' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
fi
# Wait for Traefik to pick up changes
sleep 3
echo " OK: Traffic restored"
# Send completion notification
if [[ -x "$NOTIFY_SCRIPT" ]]; then
"$NOTIFY_SCRIPT" "maintenance_end" "Maintenance window complete. Database migration successful." || true
fi
echo ""
echo "========================================"
echo "MAINTENANCE MIGRATION COMPLETE"
echo "========================================"
echo ""
echo "Summary:"
echo " - Migrations: Successful"
echo " - Active stack: $ACTIVE_STACK"
echo " - Maintenance mode: Disabled"
if [[ -n "$CREATE_BACKUP" ]]; then
echo " - Backup: $BACKUP_FILE"
fi
echo ""
exit 0