Files
Momento/scripts/deploy-prod.sh
Antigravity e9e829e579
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 5m15s
CI / Deploy production (on server) (push) Successful in 37s
fix: TOUTES les clés i18n manquantes ajoutées — 0 erreur
- general.continue/send
- structuredViews.tagApplied/filterDone/filterTodo/propertyStatus
- wizard.taskA/taskB
- richTextEditor.preview*Tip (7 clés SlashPreview)
- wizard.* au niveau racine (48 clés FR + 48 EN)
- Total: 0 clé manquante pour FR et EN
- 0 erreur TypeScript
2026-06-20 17:01:04 +00:00

188 lines
7.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 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
git reset --hard origin/main
export GIT_COMMIT="$(git rev-parse HEAD)"
echo "=== Deploy $GIT_COMMIT ==="
if [ -n "$EXPECTED_COMMIT" ] && [ "$GIT_COMMIT" != "$EXPECTED_COMMIT" ]; then
echo "ERROR: git HEAD $GIT_COMMIT != expected $EXPECTED_COMMIT"
exit 1
fi
docker compose up -d postgres
for i in $(seq 1 30); do
docker compose exec -T postgres pg_isready -U "${POSTGRES_USER:-memento}" >/dev/null 2>&1 && break
[ "$i" -eq 30 ] && { echo "Postgres not ready"; exit 1; }
sleep 2
done
docker compose exec -T postgres psql -U "${POSTGRES_USER:-memento}" -d "${POSTGRES_DB:-memento}" -c "CREATE EXTENSION IF NOT EXISTS vector;" >/dev/null
if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -q '^memento-note/prisma/migrations/'; then
DUMP_FILE="/opt/memento/backups/pre-migrate-$(date +%Y%m%d-%H%M%S).sql.gz"
mkdir -p /opt/memento/backups
docker compose exec -T postgres pg_dump -U "${POSTGRES_USER:-memento}" -d "${POSTGRES_DB:-memento}" | gzip > "$DUMP_FILE"
DUMP_SIZE=$(stat -c%s "$DUMP_FILE")
if [ "$DUMP_SIZE" -lt 1048576 ]; then
echo "ERROR: Dump too small ($DUMP_SIZE bytes)"
exit 1
fi
echo "Backup: $DUMP_FILE ($(( DUMP_SIZE / 1024 ))KB)"
else
echo "No migration change — skip pre-migrate dump"
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/
export MEMENTO_DOCKERFILE=Dockerfile.prebuilt
export MEMENTO_SOCKET_DOCKERFILE=Dockerfile.socket.prebuilt
else
echo "ERROR: No CI artifact at $ARTIFACT_TGZ — full Docker build is not supported on this host."
telegram_notify "failure" "Deploy aborted: missing prebuilt artifact"
exit 1
fi
docker compose build memento-note
docker compose build memento-socket
if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -q '^mcp-server/'; then
docker compose build mcp-server
fi
docker compose up -d --remove-orphans --force-recreate memento-note
docker compose up -d memento-socket
docker compose up -d mcp-server 2>/dev/null || true
# Monitoring stack updates are handled at the end of successful deployment
echo "=== Migrations (Prisma CLI via node, pas npx) ==="
if docker compose exec -T memento-note test -f ./node_modules/prisma/build/index.js 2>/dev/null; then
docker compose exec -T memento-note node ./node_modules/prisma/build/index.js migrate deploy
else
echo "WARN: prisma CLI absent de l'image — les migrations tournent au démarrage (entrypoint) ou via psql manuel"
fi
nginx -t 2>/dev/null && systemctl reload nginx 2>/dev/null || true
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
echo "OK build-info commit=$ACTUAL"
echo "=== Updating monitoring stack ==="
# Fix potential Docker directory/file mount corruption for metrics-token
if [ -d monitoring/metrics-token ]; then
echo "WARN: monitoring/metrics-token is a directory on host, removing it"
rm -rf monitoring/metrics-token
git checkout monitoring/metrics-token || echo "default-token-value" > monitoring/metrics-token
fi
if [ -f /opt/memento/.env.docker ]; then
export $(cat /opt/memento/.env.docker | grep -v '^#' | xargs)
fi
if [ -n "${TELEGRAM_BOT_TOKEN:-}" ] && [ -n "${TELEGRAM_CHAT_ID:-}" ]; then
echo "=== Starting Monitoring Stack (with Telegram bot) ==="
docker compose -f monitoring/docker-compose.monitoring.yml --profile telegram up -d --remove-orphans 2>&1 || echo "WARN: Failed to bring up monitoring stack"
else
echo "=== Starting Monitoring Stack (without Telegram bot) ==="
docker compose -f monitoring/docker-compose.monitoring.yml up -d --remove-orphans 2>&1 || echo "WARN: Failed to bring up monitoring stack"
fi
# Force recreation of Grafana, Prometheus and Alertmanager to apply config changes and fix mounts
echo "=== Recreating Grafana, Prometheus and Alertmanager containers ==="
docker compose -f monitoring/docker-compose.monitoring.yml up -d --force-recreate grafana prometheus alertmanager 2>&1 || true
docker compose ps
telegram_notify "success" "Deployment successful — app is healthy"
exit 0
fi
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