diff --git a/update.sh b/update.sh index dba6ac7..4f93740 100644 --- a/update.sh +++ b/update.sh @@ -26,16 +26,13 @@ log_file_only() { echo "[$(date -Is)] $*" >>"$LOG_ARCHIVE" } -# ───────────────────────────── -# ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ spinner -# ───────────────────────────── +# ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ spinner spinner_start() { local msg="$1" local -a frames=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏") local i=0 printf "%s %s" "${frames[0]}" "$msg" - ( while true; do i=$(( (i + 1) % ${#frames[@]} )) @@ -48,6 +45,8 @@ spinner_start() { spinner_stop() { local rc="${1:-0}" + local msg="$2" + if [[ -n "${SPINNER_PID:-}" ]]; then kill "$SPINNER_PID" >/dev/null 2>&1 || true wait "$SPINNER_PID" 2>/dev/null || true @@ -55,15 +54,14 @@ spinner_stop() { fi if [[ "$rc" -eq 0 ]]; then - printf "\r✅ %s\n" "$2" + printf "\r✅ %s\n" "$msg" else - printf "\r❌ %s\n" "$2" + printf "\r❌ %s\n" "$msg" fi } run_cmd() { local title="$1"; shift - spinner_start "$title" log_file_only "----- ${title} -----" log_file_only "CMD: $*" @@ -82,7 +80,7 @@ run_cmd() { return 0 } -# 🔎 APT : nombre de paquets upgradables (simulation) +# 🔎 APT : nombre de paquets upgradables apt_upgradable_count() { LC_ALL=C apt-get -s upgrade 2>/dev/null | grep -c '^Inst ' || true } @@ -114,23 +112,32 @@ update_apk() { log "✅ Mise à jour APK terminée" } -docker_image_id() { - docker image inspect -f '{{.Id}}' "$1" 2>/dev/null || true +# Compose: détecter dirs via labels + vérifier compose file +compose_dirs_from_labels() { + docker ps -q | while read -r cid; do + docker inspect -f '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$cid" 2>/dev/null || true + done | sed '/^$/d;/^$/d' | sort -u } -update_docker_compose_dir() { +is_compose_dir_valid() { + local d="$1" + [[ -d "$d" ]] && { [[ -f "$d/docker-compose.yml" ]] || [[ -f "$d/compose.yml" ]]; } +} + +update_compose_dir() { local dir="$1" - log "📂 Projet : ${dir}" + log "📂 Projet : $dir" if docker compose version >/dev/null 2>&1; then run_cmd "Téléchargement des images (Compose)" bash -c "cd '$dir' && docker compose pull" - run_cmd "Redéploiement des services (Compose)" bash -c "cd '$dir' && docker compose up -d" + # 🔁 Recréation SAFE (volumes conservés) + run_cmd "Redéploiement des services (Compose)" bash -c "cd '$dir' && docker compose up -d --remove-orphans" return 0 fi if command -v docker-compose >/dev/null 2>&1; then run_cmd "Téléchargement des images (Compose v1)" bash -c "cd '$dir' && docker-compose pull" - run_cmd "Redéploiement des services (Compose v1)" bash -c "cd '$dir' && docker-compose up -d" + run_cmd "Redéploiement des services (Compose v1)" bash -c "cd '$dir' && docker-compose up -d --remove-orphans" return 0 fi @@ -138,89 +145,42 @@ update_docker_compose_dir() { return 2 } -update_docker() { - log "🐳 Mise à jour Docker" +update_docker_compose() { + log "🐳 Mise à jour Docker (Compose)" - # Vérif Docker avec spinner aussi run_cmd "Vérification Docker" docker ps log "🔍 Recherche de projets Docker Compose" + mapfile -t dirs < <(compose_dirs_from_labels) - mapfile -t dirs < <( - docker ps -q | while read -r cid; do - docker inspect -f '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$cid" 2>/dev/null || true - done | sed '/^$/d;/^$/d' | sort -u - ) - - valid_dirs=() + valid=() for d in "${dirs[@]}"; do - if [[ -d "$d" ]] && { [[ -f "$d/docker-compose.yml" ]] || [[ -f "$d/compose.yml" ]]; }; then - valid_dirs+=("$d") + if is_compose_dir_valid "$d"; then + valid+=("$d") else - log "⚠️ Compose ignoré (chemin invalide ou sans compose.yml) : $d" + log "⚠️ Projet ignoré (chemin invalide ou sans compose.yml) : $d" fi done - if (( ${#valid_dirs[@]} > 0 )); then - log "📁 Projet(s) Compose détecté(s) : ${#valid_dirs[@]}" - for d in "${valid_dirs[@]}"; do - update_docker_compose_dir "$d" - done - log "✅ Mise à jour Docker terminée" + if (( ${#valid[@]} == 0 )); then + log "⚠️ Aucun projet Compose détecté" return 0 fi - log "⚠️ Aucun projet Compose utilisable → mise à jour image par image" - - mapfile -t images < <(docker ps --format '{{.Image}}' | sort -u) - if (( ${#images[@]} == 0 )); then - log "✅ Aucun conteneur Docker en cours" - return 0 - fi - - local updated=0 - for img in "${images[@]}"; do - [[ -n "$img" ]] || continue - - local old_id new_id - old_id="$(docker_image_id "$img")" - - # Pull avec spinner - run_cmd "Mise à jour de l'image : ${img}" docker pull "$img" - - new_id="$(docker_image_id "$img")" - - if [[ -n "$old_id" && -n "$new_id" && "$old_id" != "$new_id" ]]; then - updated=$((updated+1)) - log "⬆️ Image mise à jour : ${img}" - log " 🔁 ${old_id:0:20} ➜ ${new_id:0:20}" - else - log "✅ Image déjà à jour : ${img}" - if [[ -n "$new_id" ]]; then - log " 🏷️ ID : ${new_id:0:20}" - fi - fi + log "📁 Projet(s) Compose détecté(s) : ${#valid[@]}" + for d in "${valid[@]}"; do + update_compose_dir "$d" done - if [[ "$updated" -eq 0 ]]; then - log "✅ Aucune mise à jour Docker à appliquer" - else - log "✅ Images Docker mises à jour : ${updated}" - log "⚠️ Note : sans Compose, les conteneurs ne sont pas recréés automatiquement." - fi + log "✅ Mise à jour Docker terminée" } -# ───────────────────────────── -# Mode : apt / apk + docker éventuel -# Exemples : apt, apk, apt+docker, apk+docker -# ───────────────────────────── +# --- Parsing MODE (apt/apk + docker) --- BASE_MODE="${MODE%%+docker}" HAS_DOCKER="0" -if [[ "$MODE" == *"+docker" ]]; then - HAS_DOCKER="1" -fi +[[ "$MODE" == *"+docker" ]] && HAS_DOCKER="1" -# ─────────────── Sections lisibles ─────────────── +# ─────────────── Sortie lisible ─────────────── log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log "📦 Mise à jour du système" @@ -229,9 +189,7 @@ log "━━━━━━━━━━━━━━━━━━━━━━━━━ case "$BASE_MODE" in apt) update_apt ;; apk) update_apk ;; - *) - log "⚠️ Impossible de détecter le gestionnaire de paquets (apt/apk)" - ;; + *) log "⚠️ Impossible de détecter le gestionnaire de paquets (apt/apk)" ;; esac if [[ "$HAS_DOCKER" == "1" ]]; then @@ -239,7 +197,7 @@ if [[ "$HAS_DOCKER" == "1" ]]; then log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log "🐳 Mise à jour du ou des conteneurs" log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - update_docker + update_docker_compose else log "" log "🐳 Aucun conteneur Docker détecté"