139 lines
7.0 KiB
Bash
Executable File
139 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# =============================================================================
|
|
# gitea-auto-update.sh — Vérifie et applique les mises à jour Gitea Docker
|
|
# =============================================================================
|
|
# À placer dans /usr/local/bin/ ou ~/scripts/
|
|
# Cron recommandé : 0 4 * * * /usr/local/bin/gitea-auto-update.sh
|
|
#
|
|
# Paramètres configurables (modifier ci-dessous ou passer en variables d'env)
|
|
# =============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# ─── Configuration (modifiable) ─────────────────────────────────────────────
|
|
COMPOSE_DIR="${COMPOSE_DIR:-$HOME/dev/git/outils/gitea}"
|
|
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.yml}"
|
|
CONTAINER_NAME="${CONTAINER_NAME:-gitea_server}"
|
|
IMAGE_NAME="${IMAGE_NAME:-gitea/gitea}"
|
|
IMAGE_TAG="${IMAGE_TAG:-latest}" # "latest" ou version spécifique
|
|
LOG_FILE="${LOG_FILE:-/var/log/gitea-update.log}"
|
|
ENABLE_NOTIFICATIONS="${ENABLE_NOTIFICATIONS:-false}" # true pour envoyer un résumé
|
|
NOTIFY_METHOD="${NOTIFY_METHOD:-log}" # log, telegram, ntfy
|
|
TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}"
|
|
NTPY_TOPIC="${NTPY_TOPIC:-}"
|
|
HEALTH_CHECK_URL="${HEALTH_CHECK_URL:-http://localhost:3000}"
|
|
HEALTH_CHECK_TIMEOUT="${HEALTH_CHECK_TIMEOUT:-30}"
|
|
|
|
# ─── Logging ─────────────────────────────────────────────────────────────────
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
notify() {
|
|
local msg="$1"
|
|
case "$NOTIFY_METHOD" in
|
|
telegram)
|
|
[[ -n "$TELEGRAM_CHAT_ID" ]] && curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
|
-d "chat_id=$TELEGRAM_CHAT_ID" -d "text=$msg" > /dev/null 2>&1 || true
|
|
;;
|
|
ntfy)
|
|
[[ -n "$NTPY_TOPIC" ]] && curl -s -H "Title: Gitea Update" -d "$msg" "https://ntfy.sh/$NTPY_TOPIC" > /dev/null 2>&1 || true
|
|
;;
|
|
esac
|
|
}
|
|
|
|
log "════════════════════════════════════════════════════════"
|
|
log "🔄 Début vérification mise à jour Gitea"
|
|
|
|
# ─── Pré-vérifications ──────────────────────────────────────────────────────
|
|
cd "$COMPOSE_DIR" || { log "❌ Répertoire $COMPOSE_DIR introuvable"; exit 1; }
|
|
|
|
if ! command -v docker &>/dev/null; then
|
|
log "❌ Docker n'est pas installé"
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Récupérer l'image digest actuelle ──────────────────────────────────────
|
|
OLD_DIGEST=$(docker image inspect "${IMAGE_NAME}:${IMAGE_TAG}" --format '{{.RepoDigests}}' 2>/dev/null | grep -oP 'sha256:[a-f0-9]+' || echo "")
|
|
|
|
log "📦 Image actuelle : ${IMAGE_NAME}:${IMAGE_TAG}"
|
|
log "🔍 Digest actuel : ${OLD_DIGEST:-non disponible}"
|
|
|
|
# ─── Pull de la nouvelle image ──────────────────────────────────────────────
|
|
log "📥 Pull de la nouvelle image..."
|
|
PULL_OUTPUT=$(docker compose -f "$COMPOSE_FILE" pull "$CONTAINER_NAME" 2>&1)
|
|
PULL_EXIT=$?
|
|
|
|
if [[ $PULL_EXIT -ne 0 ]]; then
|
|
log "❌ Échec du pull : $PULL_OUTPUT"
|
|
exit 1
|
|
fi
|
|
|
|
NEW_DIGEST=$(docker image inspect "${IMAGE_NAME}:${IMAGE_TAG}" --format '{{.RepoDigests}}' 2>/dev/null | grep -oP 'sha256:[a-f0-9]+' || echo "")
|
|
|
|
log "🔍 Nouveau digest : ${NEW_DIGEST:-non disponible}"
|
|
|
|
# ─── Comparer les digests ───────────────────────────────────────────────────
|
|
if [[ -n "$OLD_DIGEST" ]] && [[ -n "$NEW_DIGEST" ]] && [[ "$OLD_DIGEST" == "$NEW_DIGEST" ]]; then
|
|
log "✅ Aucune mise à jour disponible (digest identique)"
|
|
log "═══ Fin ───────────────────────────────────────────"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── MISE À JOUR NÉCESSAIRE ─────────────────────────────────────────────────
|
|
log "🔔 Nouvelle version détectée ! Mise à jour en cours..."
|
|
|
|
# Backup rapide avant mise à jour (optionnel, le script de backup complet gère le quotidien)
|
|
BACKUP_PRE_DIR="${BACKUP_PRE_DIR:-/tmp/gitea-pre-update-$(date +%Y%m%d-%H%M%S)}"
|
|
mkdir -p "$BACKUP_PRE_DIR"
|
|
|
|
log "💾 Backup pré-update vers $BACKUP_PRE_DIR"
|
|
docker exec gitea_db mysqldump -u root -pgitea gitea > "$BACKUP_PRE_DIR/gitea_db.sql" 2>/dev/null || {
|
|
log "⚠️ Backup pré-update DB échoué, on continue quand même"
|
|
}
|
|
|
|
# Recréer le conteneur avec la nouvelle image
|
|
log "🚀 Redémarrage du conteneur avec la nouvelle image..."
|
|
UP_OUTPUT=$(docker compose -f "$COMPOSE_FILE" up -d "$CONTAINER_NAME" 2>&1)
|
|
UP_EXIT=$?
|
|
|
|
if [[ $UP_EXIT -ne 0 ]]; then
|
|
log "❌ Échec du redémarrage : $UP_OUTPUT"
|
|
log "⚠️ Tentative de rollback..."
|
|
docker compose -f "$COMPOSE_FILE" up -d "$CONTAINER_NAME" 2>&1 || true
|
|
notify "❌ GITEA UPDATE FAILED sur $(hostname) — rollback effectué"
|
|
exit 1
|
|
fi
|
|
|
|
# ─── Vérification santé ─────────────────────────────────────────────────────
|
|
log "🏥 Vérification santé (timeout=${HEALTH_CHECK_TIMEOUT}s)..."
|
|
for i in $(seq 1 "$HEALTH_CHECK_TIMEOUT"); do
|
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_CHECK_URL" 2>/dev/null || echo "000")
|
|
if [[ "$STATUS" == "200" || "$STATUS" == "302" || "$STATUS" == "303" ]]; then
|
|
log "✅ Gitea répond (HTTP $STATUS) après ${i}s"
|
|
break
|
|
fi
|
|
if [[ $i -eq "$HEALTH_CHECK_TIMEOUT" ]]; then
|
|
log "❌ Gitea ne répond pas après ${HEALTH_CHECK_TIMEOUT}s"
|
|
notify "⚠️ GITEA UPDATE : service lent à démarrer sur $(hostname) — vérifier"
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
# ─── Rapport final ──────────────────────────────────────────────────────────
|
|
GITEA_VERSION=$(curl -s "$HEALTH_CHECK_URL/api/v1/version" 2>/dev/null | grep -oP '"version":"\K[^"]+' || echo "inconnue")
|
|
|
|
log "✅ Mise à jour réussie !"
|
|
log "📋 Nouvelle version : $GITEA_VERSION"
|
|
log "📋 Ancien digest : ${OLD_DIGEST:-N/A}"
|
|
log "📋 Nouveau digest : ${NEW_DIGEST:-N/A}"
|
|
log "═══ Fin ───────────────────────────────────────────"
|
|
|
|
notify "✅ Gitea mis à jour vers $GITEA_VERSION sur $(hostname)"
|
|
|
|
# Nettoyage vieilles images
|
|
docker image prune -f 2>/dev/null || true
|
|
|
|
exit 0
|