Checkpoint: Corrections multiples :
- 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
This commit is contained in:
141
scripts/create-package.sh
Executable file
141
scripts/create-package.sh
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
|
||||
#############################################################################
|
||||
# Script de création de package - Formation Manager Itinova
|
||||
# Version: 2.0
|
||||
#
|
||||
# Ce script crée un package tar.gz prêt pour le déploiement incluant:
|
||||
# - Le code compilé
|
||||
# - Les dépendances
|
||||
# - Les migrations SQL
|
||||
# - Les scripts de déploiement
|
||||
# - La documentation
|
||||
#############################################################################
|
||||
|
||||
set -e # Arrêter en cas d'erreur
|
||||
|
||||
# Couleurs
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Configuration
|
||||
PROJECT_DIR="/home/ubuntu/formation-manager-itinova"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
PACKAGE_NAME="formation-manager-itinova-${TIMESTAMP}.tar.gz"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
echo -e "${BLUE}=========================================${NC}"
|
||||
echo -e "${BLUE} Création du package de déploiement${NC}"
|
||||
echo -e "${BLUE}=========================================${NC}"
|
||||
echo ""
|
||||
|
||||
# 1. Vérifier que nous sommes dans le bon répertoire
|
||||
echo -e "${BLUE}[1/8]${NC} Vérification du répertoire..."
|
||||
cd "$PROJECT_DIR"
|
||||
if [ ! -f "package.json" ]; then
|
||||
echo -e "${YELLOW}Erreur: package.json non trouvé${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} Répertoire vérifié"
|
||||
|
||||
# 2. Compiler le projet
|
||||
echo -e "${BLUE}[2/8]${NC} Compilation du projet..."
|
||||
if command -v pnpm &> /dev/null; then
|
||||
pnpm build
|
||||
else
|
||||
npm run build
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} Projet compilé"
|
||||
|
||||
# 3. Créer la structure dans le répertoire temporaire
|
||||
echo -e "${BLUE}[3/8]${NC} Préparation de la structure..."
|
||||
mkdir -p "$TEMP_DIR"/{dist,migrations,scripts,node_modules}
|
||||
echo -e "${GREEN}✓${NC} Structure créée"
|
||||
|
||||
# 4. Copier les fichiers nécessaires
|
||||
echo -e "${BLUE}[4/8]${NC} Copie des fichiers..."
|
||||
|
||||
# Code compilé
|
||||
cp -r dist/* "$TEMP_DIR/dist/"
|
||||
|
||||
# Migrations SQL
|
||||
if [ -d "migrations" ]; then
|
||||
cp -r migrations/* "$TEMP_DIR/migrations/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Scripts de déploiement
|
||||
cp scripts/update-production.sh "$TEMP_DIR/scripts/"
|
||||
chmod +x "$TEMP_DIR/scripts/update-production.sh"
|
||||
|
||||
# Fichiers de configuration
|
||||
cp package.json "$TEMP_DIR/"
|
||||
cp pnpm-lock.yaml "$TEMP_DIR/" 2>/dev/null || cp package-lock.json "$TEMP_DIR/" 2>/dev/null || true
|
||||
|
||||
# Fichier .env.example (pas le .env réel pour la sécurité)
|
||||
if [ -f ".env.example" ]; then
|
||||
cp .env.example "$TEMP_DIR/"
|
||||
elif [ -f ".env" ]; then
|
||||
# Créer un .env.example depuis .env en masquant les valeurs sensibles
|
||||
sed 's/=.*/=/' .env > "$TEMP_DIR/.env.example"
|
||||
fi
|
||||
|
||||
# Documentation
|
||||
if [ -f "README.md" ]; then
|
||||
cp README.md "$TEMP_DIR/"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓${NC} Fichiers copiés"
|
||||
|
||||
# 5. Installer les dépendances de production
|
||||
echo -e "${BLUE}[5/8]${NC} Installation des dépendances de production..."
|
||||
cd "$TEMP_DIR"
|
||||
if command -v pnpm &> /dev/null; then
|
||||
pnpm install --prod --frozen-lockfile 2>/dev/null || pnpm install --prod
|
||||
else
|
||||
npm install --production
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} Dépendances installées"
|
||||
|
||||
# 6. Créer un fichier VERSION
|
||||
echo -e "${BLUE}[6/8]${NC} Création du fichier VERSION..."
|
||||
cat > "$TEMP_DIR/VERSION" << EOF
|
||||
Version: ${TIMESTAMP}
|
||||
Date: $(date '+%Y-%m-%d %H:%M:%S')
|
||||
Git commit: $(cd "$PROJECT_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "N/A")
|
||||
EOF
|
||||
echo -e "${GREEN}✓${NC} Fichier VERSION créé"
|
||||
|
||||
# 7. Créer le package tar.gz
|
||||
echo -e "${BLUE}[7/8]${NC} Création de l'archive..."
|
||||
cd "$TEMP_DIR"
|
||||
tar -czf "$PROJECT_DIR/$PACKAGE_NAME" .
|
||||
echo -e "${GREEN}✓${NC} Archive créée"
|
||||
|
||||
# 8. Nettoyer
|
||||
echo -e "${BLUE}[8/8]${NC} Nettoyage..."
|
||||
rm -rf "$TEMP_DIR"
|
||||
echo -e "${GREEN}✓${NC} Nettoyage terminé"
|
||||
|
||||
# Afficher les informations du package
|
||||
echo ""
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo -e "${GREEN} Package créé avec succès !${NC}"
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo ""
|
||||
echo -e "Nom du fichier: ${BLUE}$PACKAGE_NAME${NC}"
|
||||
echo -e "Emplacement: ${BLUE}$PROJECT_DIR/$PACKAGE_NAME${NC}"
|
||||
echo -e "Taille: ${BLUE}$(du -h "$PROJECT_DIR/$PACKAGE_NAME" | cut -f1)${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Contenu du package:${NC}"
|
||||
tar -tzf "$PROJECT_DIR/$PACKAGE_NAME" | head -20
|
||||
echo ""
|
||||
echo -e "${YELLOW}Instructions de déploiement:${NC}"
|
||||
echo -e "1. Transférer le package sur le serveur:"
|
||||
echo -e " ${BLUE}scp $PACKAGE_NAME user@serveur:/tmp/${NC}"
|
||||
echo ""
|
||||
echo -e "2. Se connecter au serveur et exécuter:"
|
||||
echo -e " ${BLUE}cd /var/www/formation-manager-itinova${NC}"
|
||||
echo -e " ${BLUE}./scripts/update-production.sh /tmp/$PACKAGE_NAME${NC}"
|
||||
echo ""
|
||||
242
scripts/update-from-package.sh
Executable file
242
scripts/update-from-package.sh
Executable file
@@ -0,0 +1,242 @@
|
||||
#!/bin/bash
|
||||
# Script de mise à jour depuis package tar.gz
|
||||
# Formation Manager Itinova
|
||||
# Ce script met à jour l'application depuis un package tar.gz (sans Git)
|
||||
|
||||
set -e # Arrêter en cas d'erreur
|
||||
|
||||
# Couleurs pour les messages
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo "========================================="
|
||||
echo "Mise à jour Formation Manager Itinova"
|
||||
echo "Depuis package tar.gz"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if [ ! -f "package.json" ]; then
|
||||
echo -e "${RED}Erreur: package.json non trouvé.${NC}"
|
||||
echo -e "${RED}Ce script doit être exécuté depuis /var/www/formation-manager-itinova${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier que le fichier .env existe
|
||||
if [ ! -f ".env" ]; then
|
||||
echo -e "${RED}Erreur: fichier .env non trouvé.${NC}"
|
||||
echo -e "${RED}La configuration de l'application est manquante.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Demander le chemin du package
|
||||
echo -e "${BLUE}Veuillez spécifier le chemin complet du package tar.gz :${NC}"
|
||||
read -p "Chemin du package (ex: /tmp/formation-manager-itinova-*.tar.gz): " PACKAGE_PATH
|
||||
|
||||
if [ ! -f "$PACKAGE_PATH" ]; then
|
||||
echo -e "${RED}Erreur: Le fichier $PACKAGE_PATH n'existe pas.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Package trouvé: $PACKAGE_PATH${NC}"
|
||||
echo ""
|
||||
|
||||
# Confirmation
|
||||
read -p "Voulez-vous continuer avec la mise à jour ? (oui/non): " CONFIRM
|
||||
if [ "$CONFIRM" != "oui" ]; then
|
||||
echo "Mise à jour annulée."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}1. Sauvegarde de la base de données...${NC}"
|
||||
|
||||
# Créer un répertoire de backup s'il n'existe pas
|
||||
mkdir -p backups
|
||||
BACKUP_FILE="backups/db-backup-$(date +%Y%m%d-%H%M%S).sql"
|
||||
|
||||
# Charger les variables d'environnement
|
||||
if [ -f .env ]; then
|
||||
export $(grep -v '^#' .env | xargs)
|
||||
fi
|
||||
|
||||
# Extraire les informations de connexion depuis DATABASE_URL
|
||||
if [ -z "$DATABASE_URL" ]; then
|
||||
echo -e "${RED}Erreur: DATABASE_URL n'est pas définie dans .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parser DATABASE_URL (format: mysql://user:password@host:port/database)
|
||||
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')
|
||||
|
||||
echo "Sauvegarde de la base de données $DB_NAME..."
|
||||
mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" --single-transaction --routines --triggers > "$BACKUP_FILE" 2>/dev/null || {
|
||||
echo -e "${YELLOW}Avertissement: Sauvegarde avec privilèges limités${NC}"
|
||||
mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_FILE" 2>/dev/null
|
||||
}
|
||||
|
||||
if [ -f "$BACKUP_FILE" ] && [ -s "$BACKUP_FILE" ]; then
|
||||
echo -e "${GREEN}✓ Sauvegarde créée: $BACKUP_FILE${NC}"
|
||||
else
|
||||
echo -e "${RED}Erreur: La sauvegarde a échoué${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}2. Sauvegarde des fichiers actuels...${NC}"
|
||||
|
||||
BACKUP_DIR="backups/files-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Sauvegarder les fichiers importants
|
||||
cp -r client "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp -r server "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp -r drizzle "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp -r shared "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp package.json "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp tsconfig.json "$BACKUP_DIR/" 2>/dev/null || true
|
||||
cp vite.config.ts "$BACKUP_DIR/" 2>/dev/null || true
|
||||
|
||||
echo -e "${GREEN}✓ Fichiers sauvegardés dans: $BACKUP_DIR${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}3. Arrêt du service...${NC}"
|
||||
|
||||
# Détecter le gestionnaire de processus (systemd ou PM2)
|
||||
if systemctl is-active --quiet formation-manager 2>/dev/null; then
|
||||
echo "Arrêt du service systemd..."
|
||||
sudo systemctl stop formation-manager
|
||||
SERVICE_MANAGER="systemd"
|
||||
echo -e "${GREEN}✓ Service systemd arrêté${NC}"
|
||||
elif pm2 list | grep -q "formation-manager" 2>/dev/null; then
|
||||
echo "Arrêt du processus PM2..."
|
||||
pm2 stop formation-manager
|
||||
SERVICE_MANAGER="pm2"
|
||||
echo -e "${GREEN}✓ Processus PM2 arrêté${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Aucun service en cours d'exécution détecté${NC}"
|
||||
SERVICE_MANAGER="none"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}4. Extraction du nouveau code...${NC}"
|
||||
|
||||
# Créer un répertoire temporaire
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
echo "Extraction dans $TEMP_DIR..."
|
||||
|
||||
# Extraire le package
|
||||
tar -xzf "$PACKAGE_PATH" -C "$TEMP_DIR"
|
||||
|
||||
if [ ! -d "$TEMP_DIR/source" ]; then
|
||||
echo -e "${RED}Erreur: Le répertoire 'source' n'a pas été trouvé dans le package${NC}"
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ Package extrait${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}5. Mise à jour des fichiers...${NC}"
|
||||
|
||||
# Sauvegarder le fichier .env actuel
|
||||
cp .env .env.backup
|
||||
|
||||
# Copier les nouveaux fichiers (en excluant certains répertoires)
|
||||
rsync -av --delete \
|
||||
--exclude='node_modules' \
|
||||
--exclude='dist' \
|
||||
--exclude='.env' \
|
||||
--exclude='.env.backup' \
|
||||
--exclude='backups' \
|
||||
--exclude='.manus' \
|
||||
"$TEMP_DIR/source/" ./
|
||||
|
||||
# Restaurer le .env
|
||||
mv .env.backup .env
|
||||
|
||||
# Nettoyer le répertoire temporaire
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
echo -e "${GREEN}✓ Fichiers mis à jour${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}6. Installation des dépendances...${NC}"
|
||||
|
||||
# Vérifier si pnpm est installé
|
||||
if ! command -v pnpm &> /dev/null; then
|
||||
echo -e "${RED}Erreur: pnpm n'est pas installé${NC}"
|
||||
echo "Installation de pnpm..."
|
||||
npm install -g pnpm
|
||||
fi
|
||||
|
||||
pnpm install
|
||||
|
||||
echo -e "${GREEN}✓ Dépendances installées${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}7. Application des migrations de base de données...${NC}"
|
||||
|
||||
# Utiliser drizzle-kit push pour les mises à jour (ne recrée pas les tables existantes)
|
||||
echo "Synchronisation du schéma avec la base de données..."
|
||||
pnpm exec drizzle-kit push || {
|
||||
echo -e "${YELLOW}Avertissement: La synchronisation a échoué, tentative avec generate...${NC}"
|
||||
pnpm exec drizzle-kit generate
|
||||
}
|
||||
|
||||
echo -e "${GREEN}✓ Schéma de base de données synchronisé${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}8. Compilation du projet...${NC}"
|
||||
|
||||
pnpm build
|
||||
|
||||
echo -e "${GREEN}✓ Projet compilé${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}9. Redémarrage du service...${NC}"
|
||||
|
||||
if [ "$SERVICE_MANAGER" = "systemd" ]; then
|
||||
sudo systemctl start formation-manager
|
||||
sleep 3
|
||||
if systemctl is-active --quiet formation-manager; then
|
||||
echo -e "${GREEN}✓ Service systemd redémarré avec succès${NC}"
|
||||
else
|
||||
echo -e "${RED}Erreur: Le service n'a pas pu démarrer${NC}"
|
||||
echo "Consultez les logs avec: sudo journalctl -u formation-manager -n 50"
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$SERVICE_MANAGER" = "pm2" ]; then
|
||||
pm2 start formation-manager
|
||||
echo -e "${GREEN}✓ Processus PM2 redémarré${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Aucun gestionnaire de service détecté.${NC}"
|
||||
echo -e "${YELLOW}Démarrez manuellement l'application avec: pnpm start${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo -e "${GREEN}Mise à jour terminée avec succès !${NC}"
|
||||
echo -e "${GREEN}=========================================${NC}"
|
||||
echo ""
|
||||
echo "Sauvegardes créées :"
|
||||
echo " - Base de données: $BACKUP_FILE"
|
||||
echo " - Fichiers: $BACKUP_DIR"
|
||||
echo ""
|
||||
echo "Pour vérifier le statut :"
|
||||
if [ "$SERVICE_MANAGER" = "systemd" ]; then
|
||||
echo " sudo systemctl status formation-manager"
|
||||
echo " sudo journalctl -u formation-manager -f"
|
||||
elif [ "$SERVICE_MANAGER" = "pm2" ]; then
|
||||
echo " pm2 status"
|
||||
echo " pm2 logs formation-manager"
|
||||
fi
|
||||
echo ""
|
||||
445
scripts/update-production.sh
Executable file
445
scripts/update-production.sh
Executable file
@@ -0,0 +1,445 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user