#!/bin/bash # Script de déploiement unifié pour GEOSECTOR Web (Svelte) # Version: 4.0 (Janvier 2025) # Auteur: Pierre (avec l'aide de Claude) # # Usage: # ./deploy-web.sh # Déploiement local DEV (build → container geo) # ./deploy-web.sh rca # Livraison RECETTE (container geo → rca-geo) # ./deploy-web.sh pra # Livraison PRODUCTION (rca-geo → pra-geo) set -euo pipefail cd /home/pierre/dev/geosector/web # ===================================== # Configuration générale # ===================================== # Paramètre optionnel pour l'environnement cible TARGET_ENV=${1:-dev} # Configuration SSH HOST_KEY="/home/pierre/.ssh/id_rsa_mbpi" HOST_PORT="22" HOST_USER="root" # Configuration des serveurs RCA_HOST="195.154.80.116" # Serveur de recette PRA_HOST="51.159.7.190" # Serveur de production # Configuration Incus INCUS_PROJECT="default" WEB_PATH="/var/www/geosector/web" FINAL_OWNER="nginx" FINAL_GROUP="nginx" # Configuration de sauvegarde BACKUP_DIR="/data/backup/geosector" # Couleurs pour les messages GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ===================================== # Fonctions utilitaires # ===================================== echo_step() { echo -e "${GREEN}==>${NC} $1" } echo_info() { echo -e "${BLUE}Info:${NC} $1" } echo_warning() { echo -e "${YELLOW}Warning:${NC} $1" } echo_error() { echo -e "${RED}Error:${NC} $1" exit 1 } # Fonction pour créer une sauvegarde locale create_local_backup() { local archive_file=$1 local backup_type=$2 echo_info "Creating backup in ${BACKUP_DIR}..." if [ ! -d "${BACKUP_DIR}" ]; then mkdir -p "${BACKUP_DIR}" || echo_warning "Could not create backup directory ${BACKUP_DIR}" fi if [ -d "${BACKUP_DIR}" ]; then BACKUP_FILE="${BACKUP_DIR}/web-${backup_type}-$(date +%Y%m%d-%H%M%S).tar.gz" cp "${archive_file}" "${BACKUP_FILE}" && { echo_info "Backup saved to: ${BACKUP_FILE}" echo_info "Backup size: $(du -h "${BACKUP_FILE}" | cut -f1)" # Nettoyer les anciens backups (garder les 10 derniers) echo_info "Cleaning old backups (keeping last 10)..." ls -t "${BACKUP_DIR}"/web-${backup_type}-*.tar.gz 2>/dev/null | tail -n +11 | xargs -r rm -f && { REMAINING_BACKUPS=$(ls "${BACKUP_DIR}"/web-${backup_type}-*.tar.gz 2>/dev/null | wc -l) echo_info "Kept ${REMAINING_BACKUPS} backup(s)" } } || echo_warning "Failed to create backup in ${BACKUP_DIR}" fi } # ===================================== # Détermination de la configuration selon l'environnement # ===================================== case $TARGET_ENV in "dev") echo_step "Configuring for LOCAL DEV deployment" SOURCE_TYPE="local_build" DEST_CONTAINER="geo" DEST_HOST="local" ENV_NAME="DEVELOPMENT" ;; "rca") echo_step "Configuring for RECETTE delivery" SOURCE_TYPE="local_container" SOURCE_CONTAINER="geo" DEST_CONTAINER="rca-geo" DEST_HOST="${RCA_HOST}" ENV_NAME="RECETTE" ;; "pra") echo_step "Configuring for PRODUCTION delivery" SOURCE_TYPE="remote_container" SOURCE_HOST="${RCA_HOST}" SOURCE_CONTAINER="rca-geo" DEST_CONTAINER="pra-geo" DEST_HOST="${PRA_HOST}" ENV_NAME="PRODUCTION" ;; *) echo_error "Unknown environment: $TARGET_ENV. Use 'dev', 'rca' or 'pra'" ;; esac echo_info "Deployment flow: ${ENV_NAME}" # ===================================== # Création de l'archive selon la source # ===================================== TIMESTAMP=$(date +%s) ARCHIVE_NAME="web-deploy-${TIMESTAMP}.tar.gz" TEMP_ARCHIVE="/tmp/${ARCHIVE_NAME}" if [ "$SOURCE_TYPE" = "local_build" ]; then # DEV: Build Svelte et créer une archive echo_step "Building Svelte app for DEV..." # Variables du projet BUILD_DIR="dist" SERVER_DIR="server" LOCAL_DEPLOY_DIR="deploy" # Installer les dépendances si nécessaire if [ ! -d "node_modules" ] || [ ! -f "package-lock.json" ]; then echo_info "Installing dependencies..." npm install || echo_error "npm install failed" fi # Build du frontend principal echo_info "Building frontend..." npm run build || echo_error "Build failed" # Vérifier que le build a réussi if [ ! -d "$BUILD_DIR" ]; then echo_error "Build directory not found" fi # Préparer le package de déploiement echo_info "Preparing deployment package..." rm -rf $LOCAL_DEPLOY_DIR mkdir -p $LOCAL_DEPLOY_DIR # Copier les fichiers frontend cp -r $BUILD_DIR/* $LOCAL_DEPLOY_DIR/ # Préparer le dossier serveur si nécessaire if [ -d "$SERVER_DIR" ]; then echo_info "Preparing server files..." mkdir -p $LOCAL_DEPLOY_DIR/server cp -r $SERVER_DIR/package.json $LOCAL_DEPLOY_DIR/server/ 2>/dev/null || echo_warning "package.json not found" cp -r $SERVER_DIR/server.js $LOCAL_DEPLOY_DIR/server/ 2>/dev/null || echo_warning "server.js not found" cp -r $SERVER_DIR/.env $LOCAL_DEPLOY_DIR/server/ 2>/dev/null || echo_warning ".env not found" mkdir -p $LOCAL_DEPLOY_DIR/server/logs fi # Créer l'archive echo_info "Creating archive..." COPYFILE_DISABLE=1 tar --exclude=".*" -czf "${TEMP_ARCHIVE}" -C $LOCAL_DEPLOY_DIR . || echo_error "Failed to create archive" create_local_backup "${TEMP_ARCHIVE}" "dev" # Nettoyer rm -rf $LOCAL_DEPLOY_DIR elif [ "$SOURCE_TYPE" = "local_container" ]; then # RCA: Créer une archive depuis le container local echo_step "Creating archive from local container ${SOURCE_CONTAINER}..." echo_info "Switching to Incus project ${INCUS_PROJECT}..." incus project switch ${INCUS_PROJECT} || echo_error "Failed to switch project" # Créer l'archive directement depuis le container local incus exec ${SOURCE_CONTAINER} -- tar -czf /tmp/${ARCHIVE_NAME} -C ${WEB_PATH} . || echo_error "Failed to create archive from container" # Récupérer l'archive depuis le container incus file pull ${SOURCE_CONTAINER}/tmp/${ARCHIVE_NAME} ${TEMP_ARCHIVE} || echo_error "Failed to pull archive from container" incus exec ${SOURCE_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME} create_local_backup "${TEMP_ARCHIVE}" "to-rca" elif [ "$SOURCE_TYPE" = "remote_container" ]; then # PRA: Créer une archive depuis un container distant echo_step "Creating archive from remote container ${SOURCE_CONTAINER} on ${SOURCE_HOST}..." # Créer l'archive sur le serveur source ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} " incus project switch ${INCUS_PROJECT} && incus exec ${SOURCE_CONTAINER} -- tar -czf /tmp/${ARCHIVE_NAME} -C ${WEB_PATH} . " || echo_error "Failed to create archive on remote" # Extraire l'archive du container vers l'hôte ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} " incus file pull ${SOURCE_CONTAINER}/tmp/${ARCHIVE_NAME} /tmp/${ARCHIVE_NAME} && incus exec ${SOURCE_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME} " || echo_error "Failed to extract archive from remote container" # Copier l'archive vers la machine locale pour backup scp -i ${HOST_KEY} -P ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${TEMP_ARCHIVE} || echo_error "Failed to copy archive locally" create_local_backup "${TEMP_ARCHIVE}" "to-pra" fi ARCHIVE_SIZE=$(du -h "${TEMP_ARCHIVE}" | cut -f1) echo_info "Archive size: ${ARCHIVE_SIZE}" # ===================================== # Déploiement selon la destination # ===================================== if [ "$DEST_HOST" = "local" ]; then # Déploiement sur container local (DEV) echo_step "Deploying to local container ${DEST_CONTAINER}..." echo_info "Switching to Incus project ${INCUS_PROJECT}..." incus project switch ${INCUS_PROJECT} || echo_error "Failed to switch to project ${INCUS_PROJECT}" echo_info "Pushing archive to container..." incus file push "${TEMP_ARCHIVE}" ${DEST_CONTAINER}/tmp/${ARCHIVE_NAME} || echo_error "Failed to push archive to container" echo_info "Preparing deployment directory..." incus exec ${DEST_CONTAINER} -- mkdir -p ${WEB_PATH} || echo_error "Failed to create deployment directory" incus exec ${DEST_CONTAINER} -- rm -rf ${WEB_PATH}/* || echo_warning "Could not clean deployment directory" echo_info "Extracting archive..." incus exec ${DEST_CONTAINER} -- tar -xzf /tmp/${ARCHIVE_NAME} -C ${WEB_PATH}/ || echo_error "Failed to extract archive" echo_info "Setting permissions..." incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER}:${FINAL_GROUP} ${WEB_PATH} incus exec ${DEST_CONTAINER} -- find ${WEB_PATH} -type d -exec chmod 755 {} \; incus exec ${DEST_CONTAINER} -- find ${WEB_PATH} -type f -exec chmod 644 {} \; # Permissions spéciales pour les dossiers server incus exec ${DEST_CONTAINER} -- sh -c " if [ -f ${WEB_PATH}/server/server.js ]; then chmod +x ${WEB_PATH}/server/server.js fi if [ -d ${WEB_PATH}/server/logs ]; then chmod 775 ${WEB_PATH}/server/logs fi " || true # Installer les dépendances du serveur si présent echo_info "Installing server dependencies if needed..." incus exec ${DEST_CONTAINER} -- sh -c " if [ -d ${WEB_PATH}/server ] && [ -f ${WEB_PATH}/server/package.json ]; then cd ${WEB_PATH}/server && npm install --production fi " || echo_warning "Server dependencies installation skipped" echo_info "Cleaning up..." incus exec ${DEST_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME} else # Déploiement sur container distant (RCA ou PRA) echo_step "Deploying to remote container ${DEST_CONTAINER} on ${DEST_HOST}..." # Créer une sauvegarde sur le serveur de destination BACKUP_TIMESTAMP=$(date +"%Y%m%d_%H%M%S") REMOTE_BACKUP_DIR="${WEB_PATH}_backup_${BACKUP_TIMESTAMP}" echo_info "Creating backup on destination..." ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} " incus project switch ${INCUS_PROJECT} && incus exec ${DEST_CONTAINER} -- test -d ${WEB_PATH} && incus exec ${DEST_CONTAINER} -- cp -r ${WEB_PATH} ${REMOTE_BACKUP_DIR} && echo 'Backup created: ${REMOTE_BACKUP_DIR}' " || echo_warning "No existing installation to backup" # Transférer l'archive vers le serveur de destination echo_info "Transferring archive to ${DEST_HOST}..." if [ "$SOURCE_TYPE" = "local_container" ]; then # Pour RCA: copier depuis local vers distant scp -i ${HOST_KEY} -P ${HOST_PORT} ${TEMP_ARCHIVE} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} || echo_error "Failed to copy archive to destination" else # Pour PRA: copier de serveur à serveur ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} " scp -i ${HOST_KEY} -P ${HOST_PORT} /tmp/${ARCHIVE_NAME} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} " || echo_error "Failed to transfer archive between servers" # Nettoyer sur le serveur source ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} "rm -f /tmp/${ARCHIVE_NAME}" fi # Déployer sur le container de destination echo_info "Extracting on destination container..." ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} " set -euo pipefail # Pousser l'archive dans le container incus project switch ${INCUS_PROJECT} && incus file push /tmp/${ARCHIVE_NAME} ${DEST_CONTAINER}/tmp/${ARCHIVE_NAME} && # Nettoyer et recréer le dossier incus exec ${DEST_CONTAINER} -- rm -rf ${WEB_PATH} && incus exec ${DEST_CONTAINER} -- mkdir -p ${WEB_PATH} && # Extraire l'archive incus exec ${DEST_CONTAINER} -- tar -xzf /tmp/${ARCHIVE_NAME} -C ${WEB_PATH}/ && # Permissions incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER}:${FINAL_GROUP} ${WEB_PATH} && incus exec ${DEST_CONTAINER} -- find ${WEB_PATH} -type d -exec chmod 755 {} \; && incus exec ${DEST_CONTAINER} -- find ${WEB_PATH} -type f -exec chmod 644 {} \; && # Permissions spéciales pour server incus exec ${DEST_CONTAINER} -- sh -c ' if [ -f ${WEB_PATH}/server/server.js ]; then chmod +x ${WEB_PATH}/server/server.js fi if [ -d ${WEB_PATH}/server/logs ]; then chmod 775 ${WEB_PATH}/server/logs fi ' || true && # Installer les dépendances du serveur si présent incus exec ${DEST_CONTAINER} -- sh -c ' if [ -d ${WEB_PATH}/server ] && [ -f ${WEB_PATH}/server/package.json ]; then cd ${WEB_PATH}/server && npm install --production fi ' || echo 'Server dependencies skipped' && # Nettoyage incus exec ${DEST_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME} && rm -f /tmp/${ARCHIVE_NAME} " || echo_error "Deployment failed on destination" echo_info "Remote backup saved: ${REMOTE_BACKUP_DIR} on ${DEST_CONTAINER}" fi # Nettoyage local rm -f "${TEMP_ARCHIVE}" # ===================================== # Résumé final # ===================================== echo_step "Deployment completed successfully!" echo_info "Environment: ${ENV_NAME}" if [ "$TARGET_ENV" = "dev" ]; then echo_info "Built and deployed Svelte web app to container ${DEST_CONTAINER}" elif [ "$TARGET_ENV" = "rca" ]; then echo_info "Delivered from ${SOURCE_CONTAINER} (local) to ${DEST_CONTAINER} on ${DEST_HOST}" elif [ "$TARGET_ENV" = "pra" ]; then echo_info "Delivered from ${SOURCE_CONTAINER} on ${SOURCE_HOST} to ${DEST_CONTAINER} on ${DEST_HOST}" fi echo_info "Deployment completed at: $(date)" # Journaliser le déploiement echo "$(date '+%Y-%m-%d %H:%M:%S') - Web app deployed to ${ENV_NAME} (${DEST_CONTAINER})" >> ~/.geo_deploy_history