Files
roa2web-service-auto/scripts/rollback.sh
Marius Mutu 6b13ffa183 Initial commit: ROA2WEB - FastAPI + Vue.js + Telegram Bot
Modern ERP Reports Application with microservices architecture

Tech Stack:
- Backend: FastAPI + python-oracledb (Oracle DB integration)
- Frontend: Vue.js 3 + PrimeVue + Vite
- Telegram Bot: python-telegram-bot + SQLite
- Infrastructure: Shared database pool, JWT authentication, SSH tunnel

Features:
- FastAPI backend with async Oracle connection pool
- Vue.js 3 responsive frontend with PrimeVue components
- Telegram bot alternative interface
- Microservices architecture with shared components
- Complete deployment support (Linux Docker + Windows IIS)
- Comprehensive testing (Playwright E2E + pytest)

Repository Structure:
- reports-app/ - Main application (backend, frontend, telegram-bot)
- shared/ - Shared components (database pool, auth, utils)
- deployment/ - Deployment scripts (Linux & Windows)
- docs/ - Project documentation
- security/ - Security scanning and git hooks
2025-10-25 14:55:08 +03:00

342 lines
9.9 KiB
Bash

#!/bin/bash
# ROA2WEB Quick Rollback Script
# Fast rollback to previous deployment state
set -e
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BACKUP_DIR="$PROJECT_DIR/backups"
LOG_FILE="$PROJECT_DIR/rollback.log"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging function
log() {
local level=$1
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# Error handling
error_exit() {
log "ERROR" "$1"
exit 1
}
# Success message
success() {
log "SUCCESS" "$1"
}
# Warning message
warning() {
log "WARNING" "$1"
}
# Info message
info() {
log "INFO" "$1"
}
# Get last backup
get_last_backup() {
if [[ -f "$PROJECT_DIR/.last_backup" ]]; then
cat "$PROJECT_DIR/.last_backup"
else
# Find the most recent backup
find "$BACKUP_DIR" -name "backup_*" -type d -printf '%T+ %p\n' 2>/dev/null | sort -r | head -n1 | cut -d' ' -f2- | xargs basename 2>/dev/null || echo ""
fi
}
# List available deployments to rollback to
list_rollback_targets() {
info "Available rollback targets:"
echo ""
if [[ ! -d "$BACKUP_DIR" ]] || [[ -z "$(ls -A "$BACKUP_DIR" 2>/dev/null)" ]]; then
warning "No backups found"
return 1
fi
local current_backup=$(get_last_backup)
find "$BACKUP_DIR" -name "backup_*" -type d -printf '%T+ %p\n' | sort -r | head -n5 | while read -r line; do
local date_part=$(echo "$line" | cut -d' ' -f1 | cut -d+ -f1)
local backup_name=$(basename "$(echo "$line" | cut -d' ' -f2)")
local backup_path="$(echo "$line" | cut -d' ' -f2)"
local marker=""
if [[ "$backup_name" == "$current_backup" ]]; then
marker=" ${GREEN}(current)${NC}"
fi
echo -e "📦 ${BLUE}$backup_name${NC} ($date_part)$marker"
if [[ -f "$backup_path/backup_info.txt" ]]; then
grep -E "(Environment|Git)" "$backup_path/backup_info.txt" | sed 's/^/ /' | head -2
fi
echo ""
done
}
# Health check function
health_check() {
local service=$1
local url=$2
local timeout=${3:-30}
info "Performing health check for $service..."
local count=0
while [[ $count -lt $timeout ]]; do
if curl -f -s "$url" > /dev/null 2>&1; then
success "$service health check passed"
return 0
fi
sleep 1
((count++))
done
warning "$service health check failed after ${timeout}s"
return 1
}
# Check service health
check_services_health() {
info "Checking services health..."
local healthy=true
# Check backend health
if ! health_check "Backend API" "http://localhost/api/health" 30; then
healthy=false
fi
# Check frontend health
if ! health_check "Frontend" "http://localhost/health" 30; then
healthy=false
fi
# Check gateway health
if ! health_check "Gateway" "http://localhost/health" 30; then
healthy=false
fi
if [[ "$healthy" == "true" ]]; then
success "All services are healthy"
return 0
else
error_exit "Some services are not healthy"
fi
}
# Quick rollback without backup restore
quick_rollback() {
info "Performing quick rollback (restart with previous images)..."
cd "$PROJECT_DIR"
# Stop current services
info "Stopping current services..."
docker-compose -f docker-compose.yml -f docker-compose.production.yml down
# Get previous image versions
local backend_image=$(docker images roa2web/backend --format "{{.ID}}" | sed -n '2p')
local frontend_image=$(docker images roa2web/frontend --format "{{.ID}}" | sed -n '2p')
local gateway_image=$(docker images roa2web/nginx-gateway --format "{{.ID}}" | sed -n '2p')
if [[ -n "$backend_image" ]]; then
info "Rolling back to previous backend image: $backend_image"
docker tag "$backend_image" roa2web/backend:rollback
fi
if [[ -n "$frontend_image" ]]; then
info "Rolling back to previous frontend image: $frontend_image"
docker tag "$frontend_image" roa2web/frontend:rollback
fi
if [[ -n "$gateway_image" ]]; then
info "Rolling back to previous gateway image: $gateway_image"
docker tag "$gateway_image" roa2web/nginx-gateway:rollback
fi
# Start services with rollback images
info "Starting services with previous images..."
docker-compose -f docker-compose.yml -f docker-compose.production.yml up -d
# Wait for services to start
sleep 15
# Check health
if check_services_health; then
success "Quick rollback completed successfully!"
else
warning "Quick rollback completed but some services may not be healthy"
fi
}
# Full rollback using backup
full_rollback() {
local backup_name=$1
if [[ -z "$backup_name" ]]; then
backup_name=$(get_last_backup)
fi
if [[ -z "$backup_name" ]]; then
error_exit "No backup found for rollback"
fi
local backup_path="$BACKUP_DIR/$backup_name"
if [[ ! -d "$backup_path" ]]; then
error_exit "Backup not found: $backup_name"
fi
warning "Performing full rollback to backup: $backup_name"
warning "This will restore configuration and Docker volumes"
warning "Press Ctrl+C to cancel or wait 10 seconds to continue..."
sleep 10
cd "$PROJECT_DIR"
# Stop current services
info "Stopping current services..."
docker-compose -f docker-compose.yml -f docker-compose.production.yml down
# Restore Docker images
if [[ -f "$backup_path/images.tar" ]]; then
info "Restoring Docker images..."
docker load -i "$backup_path/images.tar"
fi
# Restore configuration files
if [[ -d "$backup_path/config" ]]; then
info "Restoring configuration files..."
# Backup current config before restore
local config_backup="config_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR/$config_backup"
cp -r .env* "$BACKUP_DIR/$config_backup/" 2>/dev/null || true
cp docker-compose*.yml "$BACKUP_DIR/$config_backup/"
# Restore from backup
cp "$backup_path"/.env* . 2>/dev/null || true
cp "$backup_path"/docker-compose*.yml .
if [[ -d "$backup_path/config/conf" && -d "nginx" ]]; then
cp -r "$backup_path/config/conf" nginx/
fi
fi
# Restore Docker volumes
if [[ -d "$backup_path/volumes" ]]; then
info "Restoring Docker volumes..."
for volume_backup in "$backup_path/volumes"/*.tar.gz; do
if [[ -f "$volume_backup" ]]; then
local volume_name=$(basename "$volume_backup" .tar.gz)
local full_volume_name="roa2web_$volume_name"
# Remove current volume
docker volume rm "$full_volume_name" 2>/dev/null || true
# Create new volume
docker volume create "$full_volume_name"
# Restore data
docker run --rm \
-v "$full_volume_name":/data \
-v "$backup_path/volumes":/backup \
alpine tar xzf "/backup/$(basename "$volume_backup")" -C /data
info "Restored volume: $volume_name"
fi
done
fi
# Start services
info "Starting services..."
docker-compose -f docker-compose.yml -f docker-compose.production.yml up -d
# Wait for services to start
sleep 20
# Check health
if check_services_health; then
success "Full rollback completed successfully!"
else
warning "Full rollback completed but some services may not be healthy"
warning "You may need to check logs: docker-compose logs"
fi
}
# Emergency stop
emergency_stop() {
warning "Performing emergency stop of all ROA2WEB services..."
cd "$PROJECT_DIR"
# Stop all compose services
docker-compose -f docker-compose.yml -f docker-compose.production.yml down -v 2>/dev/null || true
docker-compose -f docker-compose.yml down -v 2>/dev/null || true
# Stop any remaining ROA2WEB containers
docker ps -q --filter "name=roa-" | xargs -r docker stop
success "Emergency stop completed"
}
# Main function
main() {
local action=${1:-quick}
case $action in
"quick")
info "=== ROA2WEB Quick Rollback ==="
quick_rollback
;;
"full")
info "=== ROA2WEB Full Rollback ==="
full_rollback "$2"
;;
"list")
list_rollback_targets
;;
"emergency")
emergency_stop
;;
"health")
check_services_health
;;
*)
echo "Usage: $0 {quick|full [backup_name]|list|emergency|health}"
echo ""
echo "Commands:"
echo " quick - Quick rollback using previous Docker images"
echo " full - Full rollback using backup (restores config + volumes)"
echo " list - List available rollback targets"
echo " emergency - Emergency stop all services"
echo " health - Check current services health"
echo ""
echo "Examples:"
echo " $0 quick # Quick rollback"
echo " $0 full # Full rollback to last backup"
echo " $0 full backup_20240131_143022 # Full rollback to specific backup"
exit 1
;;
esac
}
# Run main function
main "$@"