Checkpoint: Correction du bug React #31 dans le calendrier - Erreur lors du survol des vignettes de séquences
Corrections apportées: - Utilisation de clés stables (format yyyy-MM-dd) au lieu de day.toISOString() pour éviter l'erreur React #31 - Gestion correcte des objets Date vs strings pour dateBloquage dans le modal - Gestion correcte du champ formateur qui peut être un objet ou une string - Ajout de clés uniques pour les dates de formation dans le modal Le calendrier fonctionne maintenant sans erreur lors du survol et de l'ouverture des modals de détails.
This commit is contained in:
273
deployment-package/deploy.sh
Executable file
273
deployment-package/deploy.sh
Executable file
@@ -0,0 +1,273 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user