feat: Dreistufenmodell normative Verbindlichkeit + Duplikat-Filter + Auto-Deploy
- Source-Type-Klassifikation (58 Regulierungen: law/guideline/framework) - Backfill-Endpoint POST /controls/backfill-normative-strength - exclude_duplicates Filter fuer Control-Library (Backend + Proxy + UI-Toggle) - MkDocs-Kapitel: Normative Verbindlichkeit mit Mermaid-Diagrammen - scripts/deploy.sh: Auto-Push + Mac Mini rebuild + Coolify health monitoring - 26 Unit Tests fuer Klassifikations-Logik Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
164
scripts/deploy.sh
Executable file
164
scripts/deploy.sh
Executable file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
# =========================================================
|
||||
# BreakPilot Compliance — Deploy Script
|
||||
# =========================================================
|
||||
# Pushes to both remotes, rebuilds changed services on
|
||||
# Mac Mini, and monitors Coolify production health.
|
||||
#
|
||||
# Usage: ./scripts/deploy.sh
|
||||
# =========================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Configuration ---
|
||||
PROJECT="breakpilot-compliance"
|
||||
PROJECT_DIR="/Users/benjaminadmin/Projekte/${PROJECT}"
|
||||
COMPOSE_FILE="${PROJECT_DIR}/docker-compose.yml"
|
||||
DOCKER="/usr/local/bin/docker"
|
||||
MAC_MINI="macmini"
|
||||
|
||||
# Coolify health endpoints
|
||||
HEALTH_ENDPOINTS=(
|
||||
"https://api-dev.breakpilot.ai/health"
|
||||
"https://sdk-dev.breakpilot.ai/health"
|
||||
)
|
||||
HEALTH_INTERVAL=20
|
||||
HEALTH_TIMEOUT=300 # 5 minutes
|
||||
|
||||
# Map top-level directories to docker-compose service names
|
||||
declare -A DIR_TO_SERVICE=(
|
||||
[admin-compliance]=admin-compliance
|
||||
[backend-compliance]=backend-compliance
|
||||
[ai-compliance-sdk]=ai-compliance-sdk
|
||||
[developer-portal]=developer-portal
|
||||
[compliance-tts-service]=compliance-tts-service
|
||||
[document-crawler]=document-crawler
|
||||
[dsms-node]=dsms-node
|
||||
[dsms-gateway]=dsms-gateway
|
||||
[docs-src]=docs
|
||||
)
|
||||
|
||||
# --- Helpers ---
|
||||
info() { printf "\033[1;34m[INFO]\033[0m %s\n" "$*"; }
|
||||
ok() { printf "\033[1;32m[OK]\033[0m %s\n" "$*"; }
|
||||
warn() { printf "\033[1;33m[WARN]\033[0m %s\n" "$*"; }
|
||||
fail() { printf "\033[1;31m[FAIL]\033[0m %s\n" "$*"; }
|
||||
|
||||
# --- Step 1: Push to both remotes ---
|
||||
info "Pushing to origin (local Gitea)..."
|
||||
git push origin main
|
||||
ok "Pushed to origin."
|
||||
|
||||
info "Pushing to gitea (external)..."
|
||||
git push gitea main
|
||||
ok "Pushed to gitea."
|
||||
|
||||
# --- Step 2: Detect changed services ---
|
||||
info "Detecting changed services since last deploy..."
|
||||
|
||||
# Get the commit before the push (what Mac Mini currently has)
|
||||
REMOTE_HEAD=$(ssh "${MAC_MINI}" "git -C ${PROJECT_DIR} rev-parse HEAD" 2>/dev/null || echo "")
|
||||
LOCAL_HEAD=$(git rev-parse HEAD)
|
||||
|
||||
CHANGED_SERVICES=()
|
||||
|
||||
if [ -z "${REMOTE_HEAD}" ] || [ "${REMOTE_HEAD}" = "${LOCAL_HEAD}" ]; then
|
||||
# Cannot determine diff or already up to date — check last 1 commit
|
||||
info "Cannot determine remote HEAD or already equal. Checking last commit diff..."
|
||||
CHANGED_DIRS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | cut -d'/' -f1 | sort -u)
|
||||
else
|
||||
CHANGED_DIRS=$(git diff --name-only "${REMOTE_HEAD}" "${LOCAL_HEAD}" 2>/dev/null | cut -d'/' -f1 | sort -u)
|
||||
fi
|
||||
|
||||
for dir in ${CHANGED_DIRS}; do
|
||||
svc="${DIR_TO_SERVICE[${dir}]:-}"
|
||||
if [ -n "${svc}" ]; then
|
||||
CHANGED_SERVICES+=("${svc}")
|
||||
fi
|
||||
done
|
||||
|
||||
# Also check if docker-compose.yml itself changed
|
||||
if echo "${CHANGED_DIRS}" | grep -q "^docker-compose"; then
|
||||
info "docker-compose.yml changed — will rebuild all services."
|
||||
CHANGED_SERVICES=()
|
||||
for svc in "${DIR_TO_SERVICE[@]}"; do
|
||||
CHANGED_SERVICES+=("${svc}")
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${#CHANGED_SERVICES[@]} -eq 0 ]; then
|
||||
warn "No service directories changed. Nothing to rebuild on Mac Mini."
|
||||
info "Coolify will still deploy from the gitea push."
|
||||
else
|
||||
# Deduplicate
|
||||
CHANGED_SERVICES=($(printf '%s\n' "${CHANGED_SERVICES[@]}" | sort -u))
|
||||
info "Changed services: ${CHANGED_SERVICES[*]}"
|
||||
|
||||
# --- Step 3: Pull code on Mac Mini ---
|
||||
info "Pulling latest code on Mac Mini..."
|
||||
ssh "${MAC_MINI}" "git -C ${PROJECT_DIR} pull --no-rebase origin main"
|
||||
ok "Code pulled on Mac Mini."
|
||||
|
||||
# --- Step 4: Rebuild + restart changed services ---
|
||||
SERVICES_STR="${CHANGED_SERVICES[*]}"
|
||||
|
||||
info "Building changed services on Mac Mini: ${SERVICES_STR}"
|
||||
ssh "${MAC_MINI}" "${DOCKER} compose -f ${COMPOSE_FILE} build ${SERVICES_STR}"
|
||||
ok "Build complete."
|
||||
|
||||
info "Restarting changed services on Mac Mini: ${SERVICES_STR}"
|
||||
ssh "${MAC_MINI}" "${DOCKER} compose -f ${COMPOSE_FILE} up -d --no-deps ${SERVICES_STR}"
|
||||
ok "Services restarted on Mac Mini."
|
||||
fi
|
||||
|
||||
# --- Step 5: Monitor Coolify health in background ---
|
||||
info "Monitoring Coolify production health in background (every ${HEALTH_INTERVAL}s, max ${HEALTH_TIMEOUT}s)..."
|
||||
|
||||
(
|
||||
elapsed=0
|
||||
all_healthy=false
|
||||
|
||||
while [ ${elapsed} -lt ${HEALTH_TIMEOUT} ]; do
|
||||
sleep ${HEALTH_INTERVAL}
|
||||
elapsed=$((elapsed + HEALTH_INTERVAL))
|
||||
|
||||
healthy_count=0
|
||||
for endpoint in "${HEALTH_ENDPOINTS[@]}"; do
|
||||
if curl -sf --max-time 5 "${endpoint}" >/dev/null 2>&1; then
|
||||
healthy_count=$((healthy_count + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${healthy_count} -eq ${#HEALTH_ENDPOINTS[@]} ]; then
|
||||
all_healthy=true
|
||||
break
|
||||
fi
|
||||
|
||||
printf "\033[1;34m[HEALTH]\033[0m %d/%d endpoints healthy (%ds elapsed)\n" \
|
||||
${healthy_count} ${#HEALTH_ENDPOINTS[@]} ${elapsed}
|
||||
done
|
||||
|
||||
echo ""
|
||||
if ${all_healthy}; then
|
||||
printf "\033[1;32m========================================\033[0m\n"
|
||||
printf "\033[1;32m Coolify deploy complete! \033[0m\n"
|
||||
printf "\033[1;32m All health endpoints are healthy. \033[0m\n"
|
||||
printf "\033[1;32m Test at: https://admin-dev.breakpilot.ai\033[0m\n"
|
||||
printf "\033[1;32m========================================\033[0m\n"
|
||||
else
|
||||
printf "\033[1;31m========================================\033[0m\n"
|
||||
printf "\033[1;31m Coolify deploy may have failed! \033[0m\n"
|
||||
printf "\033[1;31m Not all endpoints healthy after %ds. \033[0m\n" ${HEALTH_TIMEOUT}
|
||||
printf "\033[1;31m Check Coolify logs. \033[0m\n"
|
||||
printf "\033[1;31m========================================\033[0m\n"
|
||||
fi
|
||||
) &
|
||||
|
||||
HEALTH_PID=$!
|
||||
|
||||
# --- Step 6: Report ---
|
||||
echo ""
|
||||
ok "Local deploy to Mac Mini: done."
|
||||
info "Coolify health monitor running in background (PID ${HEALTH_PID})."
|
||||
info "You will see a status banner when Coolify is ready (or after ${HEALTH_TIMEOUT}s timeout)."
|
||||
echo ""
|
||||
Reference in New Issue
Block a user