274 lines
8.6 KiB
Bash
Executable File
274 lines
8.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
###############################################################################
|
|
# Script de déploiement - Gestion des Formations Manager Itinova
|
|
# Version: 1.0.0
|
|
# Description: Script automatisé pour déployer l'application en production
|
|
###############################################################################
|
|
|
|
set -e # Arrêter en cas d'erreur
|
|
|
|
# Couleurs pour les messages
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Fonction pour afficher les messages
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Fonction pour vérifier les prérequis
|
|
check_prerequisites() {
|
|
log_info "Vérification des prérequis..."
|
|
|
|
# Vérifier Node.js
|
|
if ! command -v node &> /dev/null; then
|
|
log_error "Node.js n'est pas installé"
|
|
exit 1
|
|
fi
|
|
|
|
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
|
|
if [ "$NODE_VERSION" -lt 18 ]; then
|
|
log_error "Node.js version 18+ est requis (version actuelle: $(node -v))"
|
|
exit 1
|
|
fi
|
|
log_info "Node.js version: $(node -v) ✓"
|
|
|
|
# Vérifier pnpm
|
|
if ! command -v pnpm &> /dev/null; then
|
|
log_warn "pnpm n'est pas installé. Installation..."
|
|
npm install -g pnpm
|
|
fi
|
|
log_info "pnpm version: $(pnpm -v) ✓"
|
|
|
|
# Vérifier MySQL
|
|
if ! command -v mysql &> /dev/null; then
|
|
log_warn "MySQL client n'est pas installé"
|
|
else
|
|
log_info "MySQL client: ✓"
|
|
fi
|
|
}
|
|
|
|
# Fonction pour créer le fichier .env si nécessaire
|
|
setup_env() {
|
|
log_info "Configuration des variables d'environnement..."
|
|
|
|
if [ ! -f .env ]; then
|
|
log_warn "Fichier .env non trouvé. Création à partir du template..."
|
|
|
|
cat > .env << 'EOF'
|
|
# Base de données
|
|
DATABASE_URL=mysql://user:password@localhost:3306/formation_manager
|
|
|
|
# JWT Secret (IMPORTANT: Générer une clé aléatoire sécurisée)
|
|
JWT_SECRET=changez_cette_cle_secrete_par_une_valeur_aleatoire_tres_longue
|
|
|
|
# OAuth Manus
|
|
OAUTH_SERVER_URL=https://api.manus.im
|
|
VITE_OAUTH_PORTAL_URL=https://login.manus.im
|
|
VITE_APP_ID=
|
|
|
|
# Propriétaire
|
|
OWNER_OPEN_ID=
|
|
OWNER_NAME=
|
|
|
|
# Application
|
|
VITE_APP_TITLE=Gestion des Formations Manager Itinova
|
|
VITE_APP_LOGO=/logo.svg
|
|
|
|
# APIs Manus (optionnel)
|
|
BUILT_IN_FORGE_API_URL=https://forge.manus.im
|
|
BUILT_IN_FORGE_API_KEY=
|
|
VITE_FRONTEND_FORGE_API_KEY=
|
|
VITE_FRONTEND_FORGE_API_URL=https://forge.manus.im
|
|
|
|
# Analytics (optionnel)
|
|
VITE_ANALYTICS_ENDPOINT=
|
|
VITE_ANALYTICS_WEBSITE_ID=
|
|
|
|
# Environnement
|
|
NODE_ENV=production
|
|
EOF
|
|
|
|
log_warn "Fichier .env créé. IMPORTANT: Modifiez les valeurs avant de continuer!"
|
|
log_warn "Éditez le fichier .env avec vos paramètres de production"
|
|
read -p "Appuyez sur Entrée après avoir configuré le fichier .env..."
|
|
else
|
|
log_info "Fichier .env trouvé ✓"
|
|
fi
|
|
}
|
|
|
|
# Fonction pour installer les dépendances
|
|
install_dependencies() {
|
|
log_info "Installation des dépendances..."
|
|
pnpm install --frozen-lockfile
|
|
log_info "Dépendances installées ✓"
|
|
}
|
|
|
|
# Fonction pour sauvegarder la base de données
|
|
backup_database() {
|
|
if [ -z "$DATABASE_URL" ]; then
|
|
log_warn "DATABASE_URL non définie, sauvegarde de la base de données ignorée"
|
|
return
|
|
fi
|
|
|
|
log_info "Sauvegarde de la base de données..."
|
|
|
|
BACKUP_DIR="./backups"
|
|
mkdir -p $BACKUP_DIR
|
|
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
BACKUP_FILE="$BACKUP_DIR/db_backup_$TIMESTAMP.sql"
|
|
|
|
# Extraire les informations de connexion de 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')
|
|
|
|
if command -v mysqldump &> /dev/null; then
|
|
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE 2>/dev/null || {
|
|
log_warn "Impossible de créer la sauvegarde de la base de données"
|
|
return
|
|
}
|
|
|
|
gzip $BACKUP_FILE
|
|
log_info "Sauvegarde créée: $BACKUP_FILE.gz ✓"
|
|
|
|
# Supprimer les sauvegardes de plus de 30 jours
|
|
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +30 -delete
|
|
else
|
|
log_warn "mysqldump non disponible, sauvegarde ignorée"
|
|
fi
|
|
}
|
|
|
|
# Fonction pour appliquer les migrations
|
|
run_migrations() {
|
|
log_info "Application des migrations de base de données..."
|
|
pnpm db:push
|
|
log_info "Migrations appliquées ✓"
|
|
}
|
|
|
|
# Fonction pour build l'application
|
|
build_app() {
|
|
log_info "Build de l'application..."
|
|
pnpm build
|
|
log_info "Build terminé ✓"
|
|
}
|
|
|
|
# Fonction pour redémarrer le service
|
|
restart_service() {
|
|
if command -v systemctl &> /dev/null; then
|
|
SERVICE_NAME="formation-manager"
|
|
|
|
if systemctl is-active --quiet $SERVICE_NAME; then
|
|
log_info "Redémarrage du service $SERVICE_NAME..."
|
|
sudo systemctl restart $SERVICE_NAME
|
|
|
|
# Attendre que le service soit actif
|
|
sleep 3
|
|
|
|
if systemctl is-active --quiet $SERVICE_NAME; then
|
|
log_info "Service redémarré avec succès ✓"
|
|
else
|
|
log_error "Échec du redémarrage du service"
|
|
sudo systemctl status $SERVICE_NAME
|
|
exit 1
|
|
fi
|
|
else
|
|
log_warn "Le service $SERVICE_NAME n'est pas actif"
|
|
log_info "Démarrage du service..."
|
|
sudo systemctl start $SERVICE_NAME
|
|
fi
|
|
else
|
|
log_warn "systemctl non disponible. Redémarrage manuel requis."
|
|
fi
|
|
}
|
|
|
|
# Fonction pour vérifier le déploiement
|
|
verify_deployment() {
|
|
log_info "Vérification du déploiement..."
|
|
|
|
# Vérifier que le serveur répond
|
|
if command -v curl &> /dev/null; then
|
|
sleep 2
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || echo "000")
|
|
|
|
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
|
|
log_info "Application accessible ✓"
|
|
else
|
|
log_warn "L'application ne répond pas correctement (HTTP $HTTP_CODE)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Fonction principale
|
|
main() {
|
|
echo "╔════════════════════════════════════════════════════════════════╗"
|
|
echo "║ Déploiement - Gestion des Formations Manager Itinova ║"
|
|
echo "╚════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
|
|
# Vérifier que nous sommes dans le bon répertoire
|
|
if [ ! -f "package.json" ]; then
|
|
log_error "Ce script doit être exécuté depuis la racine du projet"
|
|
exit 1
|
|
fi
|
|
|
|
# Étapes de déploiement
|
|
check_prerequisites
|
|
setup_env
|
|
|
|
# Charger les variables d'environnement
|
|
if [ -f .env ]; then
|
|
export $(cat .env | grep -v '^#' | xargs)
|
|
fi
|
|
|
|
# Demander confirmation avant de continuer
|
|
echo ""
|
|
log_warn "Le déploiement va:"
|
|
echo " 1. Sauvegarder la base de données"
|
|
echo " 2. Installer les dépendances"
|
|
echo " 3. Appliquer les migrations"
|
|
echo " 4. Builder l'application"
|
|
echo " 5. Redémarrer le service"
|
|
echo ""
|
|
read -p "Continuer? (y/N) " -n 1 -r
|
|
echo ""
|
|
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
log_info "Déploiement annulé"
|
|
exit 0
|
|
fi
|
|
|
|
backup_database
|
|
install_dependencies
|
|
run_migrations
|
|
build_app
|
|
restart_service
|
|
verify_deployment
|
|
|
|
echo ""
|
|
echo "╔════════════════════════════════════════════════════════════════╗"
|
|
echo "║ Déploiement terminé avec succès! ✓ ║"
|
|
echo "╚════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
log_info "L'application est maintenant accessible"
|
|
log_info "Vérifiez les logs avec: sudo journalctl -u formation-manager -f"
|
|
}
|
|
|
|
# Exécuter le script
|
|
main "$@"
|