Add self-hosted project folder
This commit is contained in:
115
rollback_postgres_upgrade.sh
Normal file
115
rollback_postgres_upgrade.sh
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
COMPOSE=./docker-compose.yaml
|
||||
SERVICE=postgres
|
||||
DATA_DIR=./database
|
||||
ROLLBACK_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
echo "🧪 Validating docker-compose config..."
|
||||
docker compose -f "$COMPOSE" config > /dev/null || {
|
||||
echo "❌ docker-compose config failed. Restore aborted."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract current Postgres image
|
||||
CURRENT_IMG=$(docker compose -f "$COMPOSE" config | grep "image:" | grep "$SERVICE" | awk '{print $2}' || true)
|
||||
|
||||
if [[ -z "$CURRENT_IMG" ]]; then
|
||||
echo "❌ Could not detect current image for service '$SERVICE'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT_TAG=$(basename "$CURRENT_IMG")
|
||||
CURRENT_VERSION=$(echo "$CURRENT_TAG" | cut -d'-' -f1) # e.g., 17.5
|
||||
|
||||
# Detect appropriate backup folder
|
||||
BACKUP_CANDIDATES=($(ls -td ./database_backup_* 2>/dev/null || true))
|
||||
|
||||
if [[ ${#BACKUP_CANDIDATES[@]} -eq 0 ]]; then
|
||||
echo "❌ No backup directory found. Cannot determine previous version."
|
||||
echo "ℹ️ Available folders:"
|
||||
ls -1d ./database_backup_* || true
|
||||
exit 1
|
||||
elif [[ ${#BACKUP_CANDIDATES[@]} -eq 1 ]]; then
|
||||
SELECTED_BACKUP="${BACKUP_CANDIDATES[0]}"
|
||||
echo "ℹ️ Only one backup found. Using: ${SELECTED_BACKUP}"
|
||||
else
|
||||
SELECTED_BACKUP="${BACKUP_CANDIDATES[1]}"
|
||||
echo "ℹ️ Multiple backups found. Using second latest: ${SELECTED_BACKUP}"
|
||||
fi
|
||||
|
||||
# Extract version from selected backup folder
|
||||
OLD_TAG=$(basename "$SELECTED_BACKUP" | sed -E 's/database_backup_(([^_]+)-alpine).*/\1/')
|
||||
OLD_IMG="postgres:${OLD_TAG}"
|
||||
|
||||
DELETED_UPGRADE_DIR=./database_upgraded_${CURRENT_VERSION}_${ROLLBACK_TIMESTAMP}
|
||||
|
||||
echo "⏪ Initiating rollback from Postgres ${CURRENT_TAG} to ${OLD_IMG}..."
|
||||
|
||||
# Step 1: Confirm backup exists
|
||||
if [ ! -d "$SELECTED_BACKUP" ]; then
|
||||
echo "❌ Backup folder '${SELECTED_BACKUP}' not found. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 2: Stop services
|
||||
echo "🛑 Stopping running services..."
|
||||
docker compose -f "$COMPOSE" down
|
||||
|
||||
# Step 3: Archive current (possibly broken) database
|
||||
echo "📦 Archiving current database directory as '${DELETED_UPGRADE_DIR}'..."
|
||||
mv "$DATA_DIR" "$DELETED_UPGRADE_DIR"
|
||||
|
||||
# Step 4: Restore previous version
|
||||
echo "♻️ Restoring from backup folder '${SELECTED_BACKUP}'..."
|
||||
cp -a "$SELECTED_BACKUP" "$DATA_DIR"
|
||||
|
||||
# Step 5: Restore image tag in docker-compose.yaml
|
||||
echo "🔁 Reverting docker-compose image tag to Postgres ${OLD_IMG}..."
|
||||
update_image_tag() {
|
||||
local svc="$1"
|
||||
local file="$2"
|
||||
local target_tag="$3"
|
||||
|
||||
echo "🔁 Reverting docker-compose image tag for service '$svc' to Postgres: ${target_tag}..."
|
||||
|
||||
# Use awk to scope updates within the service definition only
|
||||
awk -v service="$svc" -v new_tag="$target_tag" '
|
||||
BEGIN { in_service = 0 }
|
||||
/^[ ]{2}[a-zA-Z0-9_-]+:/ {
|
||||
in_service = ($1 == service ":") ? 1 : 0
|
||||
}
|
||||
in_service && /^\s*image:/ {
|
||||
sub(/postgres:[^"'"'"']+/, "postgres:" new_tag)
|
||||
}
|
||||
{ print }
|
||||
' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file"
|
||||
}
|
||||
update_image_tag "$SERVICE" "$COMPOSE" "$OLD_TAG"
|
||||
|
||||
# Step 6: Restart Postgres
|
||||
echo "🚀 Starting Postgres service with restored image..."
|
||||
docker compose -f "$COMPOSE" up -d "$SERVICE"
|
||||
|
||||
# Step 7: Final messages
|
||||
echo "✅ Rollback complete!"
|
||||
echo "🗃️ PostgreSQL downgraded to '${OLD_IMG}' and data restored from '${SELECTED_BACKUP}'."
|
||||
echo "📦 The faulty upgrade has been archived in '${DELETED_UPGRADE_DIR}'."
|
||||
echo " - To clean: rm -rf ${DELETED_UPGRADE_DIR}"
|
||||
echo " - To verify: docker compose logs -f $SERVICE"
|
||||
|
||||
# Step 8: Restart full application
|
||||
echo "🔄 Pulling latest images..."
|
||||
if ! docker compose pull; then
|
||||
echo "❌ Failed to pull images. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔄 Starting full application stack..."
|
||||
if ! docker compose up -d --force-recreate; then
|
||||
echo "❌ Failed to start application stack. Please check logs."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Deployment completed successfully."
|
||||
Reference in New Issue
Block a user