feat(ci): add rollback mechanism and Telegram notifications
CI/CD Pipeline Improvement - Add automated rollback on deployment failure and Telegram notifications for CI/deploy status. Changes: - scripts/deploy-prod.sh: Add rollback_save_image(), rollback_restore_image(), and telegram_notify() functions - scripts/deploy-prod.sh: Save current Docker image before building new one - scripts/deploy-prod.sh: Rollback to previous image on health check failure - .gitea/workflows/ci.yaml: Add Telegram notifications for CI failures - memento-note/eslint.config.mjs: Disable experimental React Compiler rules Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,71 @@
|
||||
# Déploiement prod sur 192.168.1.190 — exécuter SUR LE SERVEUR (runner docker-host).
|
||||
set -euo pipefail
|
||||
|
||||
# Telegram notification function
|
||||
telegram_notify() {
|
||||
local status="$1"
|
||||
local message="$2"
|
||||
local bot_token="${TELEGRAM_BOT_TOKEN:-}"
|
||||
local chat_id="${TELEGRAM_CHAT_ID:-}"
|
||||
|
||||
if [ -z "$bot_token" ] || [ -z "$chat_id" ]; then
|
||||
echo "TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not set — skipping notification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local emoji="✅"
|
||||
if [ "$status" = "failure" ]; then
|
||||
emoji="❌"
|
||||
elif [ "$status" = "rollback" ]; then
|
||||
emoji="🔄"
|
||||
fi
|
||||
|
||||
local commit_msg=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "unknown")
|
||||
# Escape markdown special characters in commit message
|
||||
commit_msg=$(echo "$commit_msg" | sed 's/[_*`[\]()~>#+=|{}.!\\-]/\\&/g')
|
||||
local commit_short="${GIT_COMMIT:0:8}"
|
||||
|
||||
curl -s -X POST "https://api.telegram.org/bot${bot_token}/sendMessage" \
|
||||
-d "chat_id=${chat_id}" \
|
||||
-d "text=${emoji} Momento Deploy ${status}
|
||||
Commit: ${commit_short}
|
||||
Message: ${commit_msg}
|
||||
Details: ${message}" \
|
||||
-d "parse_mode=Markdown" > /dev/null 2>&1 || echo "Telegram notification failed"
|
||||
}
|
||||
|
||||
# Rollback functions
|
||||
rollback_save_image() {
|
||||
echo "=== Saving current image for rollback ==="
|
||||
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^memento-memento-note:latest"; then
|
||||
docker tag memento-memento-note:latest memento-memento-note:rollback || echo "WARN: Failed to tag rollback image"
|
||||
echo "Rollback image saved: memento-memento-note:rollback"
|
||||
else
|
||||
echo "WARN: No current memento-note image found to save"
|
||||
fi
|
||||
}
|
||||
|
||||
rollback_restore_image() {
|
||||
echo "=== Rolling back to previous image ==="
|
||||
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^memento-memento-note:rollback"; then
|
||||
docker tag memento-memento-note:rollback memento-memento-note:latest || echo "ERROR: Failed to restore rollback image"
|
||||
docker compose up -d --force-recreate memento-note || echo "ERROR: Failed to restart container"
|
||||
echo "Rollback completed"
|
||||
else
|
||||
echo "ERROR: No rollback image found"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
ROOT="${DEPLOY_ROOT:-/opt/memento}"
|
||||
ARTIFACT_TGZ="${ARTIFACT_TGZ:-}"
|
||||
EXPECTED_COMMIT="${EXPECTED_COMMIT:-}"
|
||||
|
||||
# Health check configuration: 24 iterations × 5 seconds = 2 minutes total timeout
|
||||
# This allows Next.js cold start time while keeping feedback fast
|
||||
HEALTH_CHECK_MAX_ITERATIONS=24
|
||||
HEALTH_CHECK_SLEEP_SECONDS=5
|
||||
|
||||
cd "$ROOT"
|
||||
git config --global --add safe.directory "$ROOT" 2>/dev/null || true
|
||||
git fetch origin main
|
||||
@@ -44,6 +105,9 @@ fi
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1
|
||||
export GIT_COMMIT
|
||||
|
||||
# Save current image for rollback before building new one
|
||||
rollback_save_image
|
||||
|
||||
if [ -n "$ARTIFACT_TGZ" ] && [ -f "$ARTIFACT_TGZ" ]; then
|
||||
echo "=== Fast image (CI artifact) ==="
|
||||
tar xzf "$ARTIFACT_TGZ" -C memento-note/
|
||||
@@ -83,7 +147,7 @@ fi
|
||||
|
||||
nginx -t 2>/dev/null && systemctl reload nginx 2>/dev/null || true
|
||||
|
||||
for i in $(seq 1 24); do
|
||||
for i in $(seq 1 "$HEALTH_CHECK_MAX_ITERATIONS"); do
|
||||
BODY=$(docker compose exec -T memento-note node -e "require('http').get('http://localhost:3000/api/build-info',r=>{let d='';r.on('data',c=>d+=c);r.on('end',()=>{console.log(d);process.exit(0)})}).on('error',()=>process.exit(1))" 2>/dev/null || true)
|
||||
ACTUAL=$(echo "$BODY" | jq -r '.commit // empty' 2>/dev/null || true)
|
||||
if [ "$ACTUAL" = "$GIT_COMMIT" ]; then
|
||||
@@ -108,11 +172,17 @@ for i in $(seq 1 24); do
|
||||
fi
|
||||
fi
|
||||
docker compose ps
|
||||
telegram_notify "success" "Deployment successful — app is healthy"
|
||||
exit 0
|
||||
fi
|
||||
sleep 5
|
||||
sleep "$HEALTH_CHECK_SLEEP_SECONDS"
|
||||
done
|
||||
|
||||
echo "ERROR: build-info=$ACTUAL expected=$GIT_COMMIT"
|
||||
docker logs memento-web --tail=40
|
||||
|
||||
# Rollback on health check failure
|
||||
rollback_restore_image
|
||||
telegram_notify "rollback" "Health check failed — rolled back to previous version"
|
||||
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user