#!/bin/bash set -e # Script di deployment automatico per VigilanzaTurni # Uso: # bash deploy/deploy.sh → deployment normale # bash deploy/deploy.sh db → deployment + importa backup database da Git APP_DIR="/var/www/vigilanza-turni" APP_NAME="vigilanza-turni" BACKUP_DIR="/var/backups/vigilanza-turni" GIT_BACKUP_DIR="$APP_DIR/database-backups" # Verifica parametro per import database IMPORT_DB=false if [ "$1" == "db" ]; then IMPORT_DB=true echo "🔄 Modalità: Deployment con import database da Git" fi echo "🚀 Deployment VigilanzaTurni - $(date)" # Vai alla directory applicazione cd $APP_DIR # Pull ultime modifiche (se eseguito manualmente) if [ -d .git ]; then echo "📥 Pull ultime modifiche da GitLab..." git pull origin main || true fi # Load env vars if [ -f .env ]; then source .env fi # =================== BACKUP DATABASE NORMALE (se non import) =================== if [ "$IMPORT_DB" != true ]; then echo "💾 Backup database pre-deployment..." mkdir -p $BACKUP_DIR BACKUP_FILE="$BACKUP_DIR/backup_$(date +%Y%m%d_%H%M%S).sql" # Esegui backup PostgreSQL if command -v pg_dump &> /dev/null; then # Controlla che le variabili siano definite if [ -z "$PGDATABASE" ] || [ -z "$PGUSER" ]; then echo "⚠️ Variabili DB non trovate nel .env, skip backup" else PGPASSWORD=$PGPASSWORD pg_dump -h ${PGHOST:-localhost} -U $PGUSER --dbname=$PGDATABASE > $BACKUP_FILE echo "✅ Backup salvato: $BACKUP_FILE" # Comprimi backup gzip $BACKUP_FILE echo "✅ Backup compresso: ${BACKUP_FILE}.gz" # Pulisci backup vecchi (> 30 giorni) find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +30 -delete echo "🧹 Backup vecchi eliminati (retention: 30 giorni)" fi else echo "⚠️ pg_dump non trovato, skip backup" fi fi # =================== BUILD & DEPLOY =================== # Installa TUTTE le dipendenze (serve per build e migrations) echo "📥 Installazione dipendenze (include devDependencies)..." npm ci --include=dev # Build frontend echo "🏗️ Build frontend Vite..." export NODE_ENV=production npm run build # Database migrations (serve Drizzle che è devDependency) # IMPORTANTE: Le migrazioni devono essere eseguite PRIMA dell'import dei dati echo "🗄️ Aggiornamento schema database..." npm run db:push || echo "⚠️ Schema push skipped (database già aggiornato)" # =================== IMPORT DATABASE DA GIT (dopo le migrazioni) =================== if [ "$IMPORT_DB" = true ]; then echo "📦 Import dati da backup Git..." # Trova l'ultimo backup nella directory git LATEST_GIT_BACKUP=$(ls -t $GIT_BACKUP_DIR/*.sql.gz 2>/dev/null | head -1) if [ -f "$LATEST_GIT_BACKUP" ]; then echo "📥 Trovato backup: $LATEST_GIT_BACKUP" # Controlla che le variabili siano definite if [ -z "$PGDATABASE" ] || [ -z "$PGUSER" ]; then echo "❌ Variabili DB non trovate nel .env, impossibile importare" exit 1 fi # Chiedi conferma echo "⚠️ ATTENZIONE: Questo sovrascriverà i dati correnti del database!" echo "Lo schema è già stato aggiornato con le migrazioni." echo "Backup da importare: $(basename $LATEST_GIT_BACKUP)" read -p "Continuare? (s/n): " -n 1 -r echo if [[ $REPLY =~ ^[Ss]$ ]]; then # NOTA: Il backup contiene --clean e ricreerà le tabelle # Questo va bene perché contiene anche lo schema della versione corrente echo "🔄 Importazione database completo (schema + dati)..." gunzip -c "$LATEST_GIT_BACKUP" | PGPASSWORD=$PGPASSWORD psql -h ${PGHOST:-localhost} -U $PGUSER --dbname=$PGDATABASE # Ri-esegui le migrazioni per sincronizzare eventuali differenze echo "🔄 Sincronizzazione schema dopo import..." npm run db:push || echo "⚠️ Schema già sincronizzato" echo "✅ Database importato con successo da Git!" else echo "❌ Import annullato dall'utente" exit 1 fi else echo "❌ Nessun backup trovato in $GIT_BACKUP_DIR" exit 1 fi fi # NOTA: NON facciamo npm prune perché Vite serve a runtime per il middleware # Il server Express usa Vite per servire il frontend anche in produzione # =================== RESTART APPLICATION =================== # Trova PM2 (potrebbe essere in vari percorsi) PM2_CMD=$(which pm2 2>/dev/null || echo "/usr/local/bin/pm2") if [ ! -x "$PM2_CMD" ]; then PM2_CMD="/usr/bin/pm2" fi if [ ! -x "$PM2_CMD" ]; then PM2_CMD="$(npm root -g)/pm2/bin/pm2" fi echo "🔍 Usando PM2: $PM2_CMD" # Carica variabili .env per PM2 if [ -f .env ]; then source .env export DATABASE_URL PGDATABASE PGUSER PGPASSWORD PGHOST PGPORT SESSION_SECRET NODE_ENV PORT fi # Restart applicazione con PM2 echo "🔄 Restart applicazione..." if $PM2_CMD show $APP_NAME > /dev/null 2>&1; then $PM2_CMD delete $APP_NAME fi # Start con comando diretto (più affidabile) $PM2_CMD start npm --name $APP_NAME -- start $PM2_CMD save # Health check echo "🏥 Health check..." sleep 5 if $PM2_CMD show $APP_NAME | grep -q "online"; then echo "✅ Deployment completato con successo!" $PM2_CMD logs $APP_NAME --lines 20 --nostream else echo "❌ Errore: applicazione non online" $PM2_CMD logs $APP_NAME --lines 50 --nostream # Rollback: ripristina ultimo backup echo "🔄 Tentativo rollback backup..." LATEST_BACKUP=$(ls -t $BACKUP_DIR/backup_*.sql.gz 2>/dev/null | head -1) if [ -f "$LATEST_BACKUP" ]; then echo "📦 Ripristino da: $LATEST_BACKUP" gunzip -c $LATEST_BACKUP | PGPASSWORD=$PGPASSWORD psql -h ${PGHOST:-localhost} -U $PGUSER --dbname=$PGDATABASE echo "✅ Database ripristinato" fi exit 1 fi # =================== STATUS =================== echo "" echo "📊 Status PM2:" $PM2_CMD status echo "" echo "📈 Ultimi backup disponibili:" ls -lht $BACKUP_DIR/*.gz 2>/dev/null | head -5 || echo "Nessun backup trovato" echo "" echo "🌐 Applicazione disponibile su: https://vt.alfacom.it"