- Renommage questionnaire.nom → questionnaire.titre dans QuestionnaireReponse.tsx, AdminQuestionnaireEdit.tsx, questionnaireScheduler.ts, questionnaireExport.ts - Correction des requêtes SQL dans questionnaireDb.ts (suppression de la condition complete inexistante) - Ajout des colonnes valeurMin et valeurMax dans la table questions - Renommage de la colonne nom en titre dans la table questionnaires
446 lines
12 KiB
Bash
Executable File
446 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#############################################################################
|
|
# Script de mise à jour production - Formation Manager Itinova
|
|
# Version: 2.0
|
|
#
|
|
# Ce script gère:
|
|
# - Sauvegarde automatique de la base de données
|
|
# - Sauvegarde des fichiers
|
|
# - Extraction du package
|
|
# - Application des migrations SQL versionnées
|
|
# - Redémarrage du service
|
|
# - Vérification post-déploiement
|
|
#############################################################################
|
|
|
|
set -e # Arrêter en cas d'erreur
|
|
set -u # Arrêter si variable non définie
|
|
|
|
# Couleurs pour les messages
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
APP_DIR="/var/www/formation-manager-itinova"
|
|
BACKUP_DIR="$APP_DIR/backups"
|
|
MIGRATIONS_DIR="$APP_DIR/migrations"
|
|
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
LOG_FILE="$APP_DIR/logs/update-$TIMESTAMP.log"
|
|
|
|
# Fonction pour afficher les messages
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[✓]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[⚠]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[✗]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
# Fonction pour vérifier les prérequis
|
|
check_prerequisites() {
|
|
log_info "Vérification des prérequis..."
|
|
|
|
# Vérifier que nous sommes dans le bon répertoire
|
|
if [ ! -f "$APP_DIR/package.json" ]; then
|
|
log_error "Erreur: package.json non trouvé dans $APP_DIR"
|
|
exit 1
|
|
fi
|
|
|
|
# Vérifier que le fichier .env existe
|
|
if [ ! -f "$APP_DIR/.env" ]; then
|
|
log_error "Erreur: fichier .env non trouvé"
|
|
exit 1
|
|
fi
|
|
|
|
# Créer les répertoires nécessaires
|
|
mkdir -p "$BACKUP_DIR" "$MIGRATIONS_DIR" "$(dirname "$LOG_FILE")"
|
|
|
|
log_success "Prérequis vérifiés"
|
|
}
|
|
|
|
# Fonction pour charger les variables d'environnement
|
|
load_env() {
|
|
log_info "Chargement des variables d'environnement..."
|
|
|
|
# Charger le .env
|
|
set -a
|
|
source "$APP_DIR/.env"
|
|
set +a
|
|
|
|
# Extraire les informations de connexion MySQL depuis DATABASE_URL
|
|
# Format: mysql://user:password@host:port/database
|
|
if [ -z "${DATABASE_URL:-}" ]; then
|
|
log_error "DATABASE_URL non définie dans .env"
|
|
exit 1
|
|
fi
|
|
|
|
# Parser DATABASE_URL
|
|
DB_USER=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
|
|
DB_PASS=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
|
|
DB_HOST=$(echo "$DATABASE_URL" | sed -n 's/.*@\([^:]*\):.*/\1/p')
|
|
DB_PORT=$(echo "$DATABASE_URL" | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
|
|
DB_NAME=$(echo "$DATABASE_URL" | sed -n 's/.*\/\([^?]*\).*/\1/p')
|
|
|
|
if [ -z "$DB_USER" ] || [ -z "$DB_NAME" ]; then
|
|
log_error "Impossible de parser DATABASE_URL"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Variables d'environnement chargées"
|
|
}
|
|
|
|
# Fonction pour sauvegarder la base de données
|
|
backup_database() {
|
|
log_info "Sauvegarde de la base de données..."
|
|
|
|
BACKUP_FILE="$BACKUP_DIR/db-backup-$TIMESTAMP.sql"
|
|
|
|
# Créer un fichier de configuration MySQL temporaire pour éviter le warning
|
|
MYSQL_CONFIG=$(mktemp)
|
|
cat > "$MYSQL_CONFIG" << EOF
|
|
[client]
|
|
user=$DB_USER
|
|
password=$DB_PASS
|
|
host=$DB_HOST
|
|
port=$DB_PORT
|
|
EOF
|
|
|
|
# Sauvegarder
|
|
if mysqldump --defaults-extra-file="$MYSQL_CONFIG" \
|
|
--single-transaction \
|
|
--routines \
|
|
--triggers \
|
|
"$DB_NAME" > "$BACKUP_FILE" 2>&1; then
|
|
log_success "Sauvegarde créée: $BACKUP_FILE"
|
|
else
|
|
log_warning "Sauvegarde partielle (certains privilèges manquants)"
|
|
# Ne pas arrêter le script, la sauvegarde partielle est acceptable
|
|
fi
|
|
|
|
# Nettoyer
|
|
rm -f "$MYSQL_CONFIG"
|
|
|
|
# Compresser la sauvegarde
|
|
gzip "$BACKUP_FILE"
|
|
log_success "Sauvegarde compressée: $BACKUP_FILE.gz"
|
|
|
|
# Garder seulement les 10 dernières sauvegardes
|
|
ls -t "$BACKUP_DIR"/db-backup-*.sql.gz | tail -n +11 | xargs -r rm
|
|
}
|
|
|
|
# Fonction pour sauvegarder les fichiers
|
|
backup_files() {
|
|
log_info "Sauvegarde des fichiers..."
|
|
|
|
BACKUP_FILE="$BACKUP_DIR/files-backup-$TIMESTAMP.tar.gz"
|
|
|
|
# Sauvegarder les fichiers importants (exclure node_modules et dist)
|
|
tar -czf "$BACKUP_FILE" \
|
|
--exclude='node_modules' \
|
|
--exclude='dist' \
|
|
--exclude='backups' \
|
|
--exclude='logs' \
|
|
-C "$APP_DIR" \
|
|
. 2>/dev/null || true
|
|
|
|
log_success "Fichiers sauvegardés: $BACKUP_FILE"
|
|
|
|
# Garder seulement les 5 dernières sauvegardes de fichiers
|
|
ls -t "$BACKUP_DIR"/files-backup-*.tar.gz | tail -n +6 | xargs -r rm
|
|
}
|
|
|
|
# Fonction pour détecter le gestionnaire de processus
|
|
detect_process_manager() {
|
|
if systemctl is-active --quiet formation-manager 2>/dev/null; then
|
|
echo "systemd"
|
|
elif pm2 list | grep -q "formation-manager"; then
|
|
echo "pm2"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# Fonction pour arrêter le service
|
|
stop_service() {
|
|
log_info "Arrêt du service..."
|
|
|
|
PROCESS_MANAGER=$(detect_process_manager)
|
|
|
|
case "$PROCESS_MANAGER" in
|
|
systemd)
|
|
sudo systemctl stop formation-manager
|
|
log_success "Service arrêté (systemd)"
|
|
;;
|
|
pm2)
|
|
pm2 stop formation-manager 2>/dev/null || true
|
|
log_success "Service arrêté (PM2)"
|
|
;;
|
|
*)
|
|
log_warning "Gestionnaire de processus non détecté, le service n'a pas été arrêté"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Fonction pour extraire le package
|
|
extract_package() {
|
|
local PACKAGE_PATH="$1"
|
|
|
|
log_info "Extraction du package..."
|
|
|
|
if [ ! -f "$PACKAGE_PATH" ]; then
|
|
log_error "Package non trouvé: $PACKAGE_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
# Créer un répertoire temporaire
|
|
TEMP_DIR=$(mktemp -d)
|
|
|
|
# Extraire dans le répertoire temporaire
|
|
tar -xzf "$PACKAGE_PATH" -C "$TEMP_DIR"
|
|
|
|
# Copier les nouveaux fichiers (préserver .env)
|
|
rsync -av --exclude='.env' --exclude='backups' --exclude='logs' "$TEMP_DIR/" "$APP_DIR/"
|
|
|
|
# Nettoyer
|
|
rm -rf "$TEMP_DIR"
|
|
|
|
log_success "Package extrait"
|
|
}
|
|
|
|
# Fonction pour obtenir la version actuelle de la base de données
|
|
get_current_db_version() {
|
|
MYSQL_CONFIG=$(mktemp)
|
|
cat > "$MYSQL_CONFIG" << EOF
|
|
[client]
|
|
user=$DB_USER
|
|
password=$DB_PASS
|
|
host=$DB_HOST
|
|
port=$DB_PORT
|
|
EOF
|
|
|
|
# Créer la table de versions si elle n'existe pas
|
|
mysql --defaults-extra-file="$MYSQL_CONFIG" "$DB_NAME" << 'EOF' 2>/dev/null
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
version VARCHAR(50) PRIMARY KEY,
|
|
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
description TEXT
|
|
);
|
|
EOF
|
|
|
|
# Obtenir la dernière version
|
|
VERSION=$(mysql --defaults-extra-file="$MYSQL_CONFIG" "$DB_NAME" -sN << 'EOF' 2>/dev/null
|
|
SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1;
|
|
EOF
|
|
)
|
|
|
|
rm -f "$MYSQL_CONFIG"
|
|
|
|
echo "${VERSION:-0}"
|
|
}
|
|
|
|
# Fonction pour appliquer les migrations
|
|
apply_migrations() {
|
|
log_info "Application des migrations..."
|
|
|
|
CURRENT_VERSION=$(get_current_db_version)
|
|
log_info "Version actuelle de la base de données: $CURRENT_VERSION"
|
|
|
|
# Créer un fichier de configuration MySQL
|
|
MYSQL_CONFIG=$(mktemp)
|
|
cat > "$MYSQL_CONFIG" << EOF
|
|
[client]
|
|
user=$DB_USER
|
|
password=$DB_PASS
|
|
host=$DB_HOST
|
|
port=$DB_PORT
|
|
EOF
|
|
|
|
# Appliquer chaque migration non appliquée
|
|
MIGRATIONS_APPLIED=0
|
|
|
|
for MIGRATION_FILE in "$MIGRATIONS_DIR"/*.sql; do
|
|
if [ ! -f "$MIGRATION_FILE" ]; then
|
|
continue
|
|
fi
|
|
|
|
MIGRATION_VERSION=$(basename "$MIGRATION_FILE" .sql)
|
|
|
|
# Vérifier si la migration a déjà été appliquée
|
|
ALREADY_APPLIED=$(mysql --defaults-extra-file="$MYSQL_CONFIG" "$DB_NAME" -sN << EOF
|
|
SELECT COUNT(*) FROM schema_migrations WHERE version = '$MIGRATION_VERSION';
|
|
EOF
|
|
)
|
|
|
|
if [ "$ALREADY_APPLIED" -eq 0 ]; then
|
|
log_info "Application de la migration: $MIGRATION_VERSION"
|
|
|
|
# Appliquer la migration
|
|
if mysql --defaults-extra-file="$MYSQL_CONFIG" "$DB_NAME" < "$MIGRATION_FILE" 2>&1 | tee -a "$LOG_FILE"; then
|
|
# Enregistrer la migration
|
|
mysql --defaults-extra-file="$MYSQL_CONFIG" "$DB_NAME" << EOF
|
|
INSERT INTO schema_migrations (version, description)
|
|
VALUES ('$MIGRATION_VERSION', 'Migration appliquée automatiquement');
|
|
EOF
|
|
log_success "Migration $MIGRATION_VERSION appliquée avec succès"
|
|
MIGRATIONS_APPLIED=$((MIGRATIONS_APPLIED + 1))
|
|
else
|
|
log_error "Échec de la migration $MIGRATION_VERSION"
|
|
rm -f "$MYSQL_CONFIG"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_info "Migration $MIGRATION_VERSION déjà appliquée (ignorée)"
|
|
fi
|
|
done
|
|
|
|
rm -f "$MYSQL_CONFIG"
|
|
|
|
if [ $MIGRATIONS_APPLIED -eq 0 ]; then
|
|
log_info "Aucune nouvelle migration à appliquer"
|
|
else
|
|
log_success "$MIGRATIONS_APPLIED migration(s) appliquée(s)"
|
|
fi
|
|
}
|
|
|
|
# Fonction pour installer les dépendances
|
|
install_dependencies() {
|
|
log_info "Installation des dépendances..."
|
|
|
|
cd "$APP_DIR"
|
|
|
|
if command -v pnpm &> /dev/null; then
|
|
pnpm install --prod 2>&1 | tee -a "$LOG_FILE"
|
|
else
|
|
npm install --production 2>&1 | tee -a "$LOG_FILE"
|
|
fi
|
|
|
|
log_success "Dépendances installées"
|
|
}
|
|
|
|
# Fonction pour démarrer le service
|
|
start_service() {
|
|
log_info "Démarrage du service..."
|
|
|
|
PROCESS_MANAGER=$(detect_process_manager)
|
|
|
|
case "$PROCESS_MANAGER" in
|
|
systemd)
|
|
sudo systemctl start formation-manager
|
|
sleep 3
|
|
if systemctl is-active --quiet formation-manager; then
|
|
log_success "Service démarré (systemd)"
|
|
else
|
|
log_error "Échec du démarrage du service"
|
|
exit 1
|
|
fi
|
|
;;
|
|
pm2)
|
|
pm2 restart formation-manager 2>&1 | tee -a "$LOG_FILE"
|
|
sleep 3
|
|
if pm2 list | grep -q "formation-manager.*online"; then
|
|
log_success "Service démarré (PM2)"
|
|
else
|
|
log_error "Échec du démarrage du service"
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
log_warning "Gestionnaire de processus non détecté, démarrage manuel requis"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Fonction pour vérifier le service
|
|
verify_service() {
|
|
log_info "Vérification du service..."
|
|
|
|
# Attendre que le service démarre
|
|
sleep 5
|
|
|
|
# Vérifier que le service répond
|
|
if curl -f http://localhost:3000/ &>/dev/null; then
|
|
log_success "Service opérationnel"
|
|
else
|
|
log_warning "Le service ne répond pas sur le port 3000"
|
|
fi
|
|
|
|
# Afficher les derniers logs
|
|
PROCESS_MANAGER=$(detect_process_manager)
|
|
|
|
case "$PROCESS_MANAGER" in
|
|
systemd)
|
|
log_info "Derniers logs:"
|
|
sudo journalctl -u formation-manager -n 20 --no-pager | tee -a "$LOG_FILE"
|
|
;;
|
|
pm2)
|
|
log_info "Derniers logs:"
|
|
pm2 logs formation-manager --lines 20 --nostream | tee -a "$LOG_FILE"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Fonction principale
|
|
main() {
|
|
echo ""
|
|
echo "========================================="
|
|
echo " Mise à jour Formation Manager Itinova"
|
|
echo "========================================="
|
|
echo ""
|
|
|
|
# Demander le chemin du package
|
|
if [ $# -eq 0 ]; then
|
|
read -p "Chemin du package tar.gz: " PACKAGE_PATH
|
|
else
|
|
PACKAGE_PATH="$1"
|
|
fi
|
|
|
|
# Vérifier les prérequis
|
|
check_prerequisites
|
|
|
|
# Charger les variables d'environnement
|
|
load_env
|
|
|
|
# Sauvegardes
|
|
backup_database
|
|
backup_files
|
|
|
|
# Arrêter le service
|
|
stop_service
|
|
|
|
# Extraire le package
|
|
extract_package "$PACKAGE_PATH"
|
|
|
|
# Appliquer les migrations
|
|
apply_migrations
|
|
|
|
# Installer les dépendances
|
|
install_dependencies
|
|
|
|
# Démarrer le service
|
|
start_service
|
|
|
|
# Vérifier le service
|
|
verify_service
|
|
|
|
echo ""
|
|
log_success "Mise à jour terminée avec succès!"
|
|
echo ""
|
|
log_info "Logs complets: $LOG_FILE"
|
|
log_info "Sauvegarde DB: $BACKUP_DIR/db-backup-$TIMESTAMP.sql.gz"
|
|
echo ""
|
|
}
|
|
|
|
# Exécuter
|
|
main "$@"
|