33800 Docs

← Retour
#!/bin/bash # ═══════════════════════════════════════════════════════════════════════════ # FILES.SH - Stratégie de déploiement fichiers # Releases + Symlinks (pour nginx, win11, pve, etc.) # # Structure créée: # /services/mon-app/ # ├── releases/ # │ ├── 2026-01-20_12-00-00-abc1234/ # │ └── 2026-01-20_13-00-00-def5678/ # ├── shared/ # │ ├── logs/ # │ ├── data/ # │ └── config/ # └── current -> releases/2026-01-20_13-00-00-def5678 # ═══════════════════════════════════════════════════════════════════════════ # ─────────────────────────────────────────────────────────────────────────── # Exclusions par défaut pour rsync # ─────────────────────────────────────────────────────────────────────────── DEFAULT_EXCLUDES=( '.git' 'node_modules' '.env*' 'conf.*.gouroubleu.yml' '.gitlab-ci.yml' '__pycache__' '*.pyc' '.pytest_cache' 'target/debug' '.cargo' '.Dockerfile.generated' 'docker-compose.generated.yml' ) # ─────────────────────────────────────────────────────────────────────────── # Fonction principale de déploiement fichiers # ─────────────────────────────────────────────────────────────────────────── deploy_files() { local service_name="${CFG_name}" local release_name="$(timestamp)-${COMMIT}" local remote_base="${TARGET_PATH}/${service_name}" local remote_release="${remote_base}/releases/${release_name}" local keep_releases="${CFG_keep_releases:-5}" log_info "Déploiement fichiers vers ${TARGET_HOST}:${remote_base}" log_info " Release: ${release_name}" # 1. Créer la structure de base log_step "Création de la structure..." create_directory_structure "$remote_base" "$remote_release" # 2. Copier les fichiers log_step "Copie des fichiers..." copy_files_to_release "$remote_release" # 3. Lier les dossiers shared log_step "Liaison des dossiers partagés..." link_shared_folders "$remote_base" "$remote_release" # 4. Exécuter pre_deploy si configuré if [[ -n "${CFG_pre_deploy:-}" ]]; then log_step "Exécution pre_deploy..." run_hook "$remote_release" "${CFG_pre_deploy}" fi # 5. Switcher le symlink current (atomique) log_step "Activation de la release..." activate_release "$remote_base" "$remote_release" "$release_name" # 6. Exécuter post_deploy si configuré if [[ -n "${CFG_post_deploy:-}" ]]; then log_step "Exécution post_deploy..." run_hook "${remote_base}/current" "${CFG_post_deploy}" fi # 7. Cleanup anciennes releases log_step "Nettoyage (garde: $keep_releases releases)..." cleanup_old_releases "$remote_base" "$keep_releases" log_success "Déploiement fichiers terminé: ${service_name}" } # ─────────────────────────────────────────────────────────────────────────── # Créer la structure de répertoires # ─────────────────────────────────────────────────────────────────────────── create_directory_structure() { local base="$1" local release="$2" if [[ "$TARGET_LOCAL" == "true" ]]; then mkdir -p "${release}" mkdir -p "${base}/shared/logs" mkdir -p "${base}/shared/data" mkdir -p "${base}/shared/config" else ssh_exec "$TARGET_HOST" "$TARGET_USER" \ "mkdir -p ${release} ${base}/shared/logs ${base}/shared/data ${base}/shared/config" fi } # ─────────────────────────────────────────────────────────────────────────── # Copier les fichiers vers la release # ─────────────────────────────────────────────────────────────────────────── copy_files_to_release() { local release="$1" # Construire les arguments --exclude local exclude_args="" for pattern in "${DEFAULT_EXCLUDES[@]}"; do exclude_args="$exclude_args --exclude='$pattern'" done # Ajouter les exclusions personnalisées si définies if [[ -n "${CFG_exclude:-}" ]]; then for pattern in ${CFG_exclude}; do exclude_args="$exclude_args --exclude='$pattern'" done fi if [[ "$TARGET_LOCAL" == "true" ]]; then eval "rsync -av $exclude_args '${PROJECT_DIR}/' '${release}/'" else eval "rsync -avz $exclude_args '${PROJECT_DIR}/' '${TARGET_USER}@${TARGET_HOST}:${release}/'" fi log_success "Fichiers copiés" } # ─────────────────────────────────────────────────────────────────────────── # Lier les dossiers partagés # ─────────────────────────────────────────────────────────────────────────── link_shared_folders() { local base="$1" local release="$2" # Dossiers partagés par défaut local shared_folders="logs" # Ajouter les dossiers configurés if [[ -n "${CFG_shared:-}" ]]; then shared_folders="${CFG_shared}" fi # Ajouter data si storage.data est activé if [[ "${CFG_storage_data:-false}" == "true" ]]; then shared_folders="$shared_folders data" fi for folder in $shared_folders; do log_info " Lien: $folder -> shared/$folder" if [[ "$TARGET_LOCAL" == "true" ]]; then # Supprimer le dossier s'il existe dans la release rm -rf "${release}/${folder}" 2>/dev/null || true # Créer le lien symbolique ln -sfn "${base}/shared/${folder}" "${release}/${folder}" else ssh_exec "$TARGET_HOST" "$TARGET_USER" \ "rm -rf '${release}/${folder}' 2>/dev/null; ln -sfn '${base}/shared/${folder}' '${release}/${folder}'" fi done } # ─────────────────────────────────────────────────────────────────────────── # Activer une release (switch atomique du symlink) # ─────────────────────────────────────────────────────────────────────────── activate_release() { local base="$1" local release="$2" local name="$3" if [[ "$TARGET_LOCAL" == "true" ]]; then ln -sfn "${release}" "${base}/current" else ssh_exec "$TARGET_HOST" "$TARGET_USER" "ln -sfn '${release}' '${base}/current'" fi log_success "Release activée: ${name}" } # ─────────────────────────────────────────────────────────────────────────── # Exécuter un hook (pre_deploy ou post_deploy) # ─────────────────────────────────────────────────────────────────────────── run_hook() { local dir="$1" local cmd="$2" if [[ "$TARGET_LOCAL" == "true" ]]; then (cd "${dir}" && eval "${cmd}") else ssh_exec "$TARGET_HOST" "$TARGET_USER" "cd '${dir}' && ${cmd}" fi log_success "Hook exécuté" } # ─────────────────────────────────────────────────────────────────────────── # Nettoyer les anciennes releases # ─────────────────────────────────────────────────────────────────────────── cleanup_old_releases() { local base="$1" local keep="$2" if [[ "$TARGET_LOCAL" == "true" ]]; then if [[ -d "${base}/releases" ]]; then (cd "${base}/releases" && ls -1t | tail -n +$((keep + 1)) | xargs -r rm -rf) fi else ssh_exec "$TARGET_HOST" "$TARGET_USER" \ "cd '${base}/releases' 2>/dev/null && ls -1t | tail -n +$((keep + 1)) | xargs -r rm -rf" fi log_info "Anciennes releases nettoyées" } # ─────────────────────────────────────────────────────────────────────────── # Rollback vers une release précédente # ─────────────────────────────────────────────────────────────────────────── rollback_files() { local service_name="${CFG_name}" local remote_base="${TARGET_PATH}/${service_name}" local steps="${1:-1}" log_info "Rollback de ${steps} release(s) pour ${service_name}..." local releases if [[ "$TARGET_LOCAL" == "true" ]]; then releases=$(ls -1t "${remote_base}/releases" 2>/dev/null) else releases=$(ssh_exec "$TARGET_HOST" "$TARGET_USER" "ls -1t '${remote_base}/releases'" 2>/dev/null) fi local target_release=$(echo "$releases" | sed -n "$((steps + 1))p") if [[ -z "$target_release" ]]; then log_error "Pas assez de releases pour rollback de ${steps} step(s)" return 1 fi log_info "Rollback vers: ${target_release}" activate_release "$remote_base" "${remote_base}/releases/${target_release}" "$target_release" log_success "Rollback terminé" }