fix: I dunno, I'm making git server changes
This commit is contained in:
185
scripts/ci/health-check.sh
Executable file
185
scripts/ci/health-check.sh
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
# Health check script for blue-green deployment
|
||||
# Verifies container health and HTTP endpoints
|
||||
#
|
||||
# Usage: ./health-check.sh <stack> [timeout_seconds]
|
||||
# stack: blue or green
|
||||
# timeout_seconds: max wait time (default: 60)
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - All health checks passed
|
||||
# 1 - Health check failed
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
STACK="${1:-}"
|
||||
TIMEOUT="${2:-60}"
|
||||
|
||||
if [[ -z "$STACK" ]] || [[ ! "$STACK" =~ ^(blue|green)$ ]]; then
|
||||
echo "Usage: $0 <blue|green> [timeout_seconds]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FRONTEND_CONTAINER="mvp-frontend-$STACK"
|
||||
BACKEND_CONTAINER="mvp-backend-$STACK"
|
||||
|
||||
echo "========================================"
|
||||
echo "Health Check - $STACK Stack"
|
||||
echo "Timeout: ${TIMEOUT}s"
|
||||
echo "========================================"
|
||||
|
||||
# Function to check Docker container health
|
||||
check_container_health() {
|
||||
local container="$1"
|
||||
local status
|
||||
|
||||
status=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "not found")
|
||||
|
||||
case "$status" in
|
||||
"healthy")
|
||||
return 0
|
||||
;;
|
||||
"starting")
|
||||
return 2 # Still starting
|
||||
;;
|
||||
"unhealthy"|"not found"|"")
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check HTTP endpoint
|
||||
check_http_endpoint() {
|
||||
local container="$1"
|
||||
local port="$2"
|
||||
local path="$3"
|
||||
|
||||
if docker exec "$container" curl -sf "http://localhost:${port}${path}" > /dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check database connectivity via backend
|
||||
check_database_connectivity() {
|
||||
local container="$1"
|
||||
|
||||
# The /health endpoint should verify database connectivity
|
||||
if docker exec "$container" curl -sf "http://localhost:3001/health" 2>/dev/null | grep -q '"database"'; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Wait for containers to be healthy
|
||||
wait_for_health() {
|
||||
local container="$1"
|
||||
local elapsed=0
|
||||
|
||||
while [[ $elapsed -lt $TIMEOUT ]]; do
|
||||
check_container_health "$container"
|
||||
local status=$?
|
||||
|
||||
if [[ $status -eq 0 ]]; then
|
||||
return 0
|
||||
elif [[ $status -eq 1 ]]; then
|
||||
echo " ERROR: Container $container is unhealthy"
|
||||
docker logs "$container" --tail 20 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Still starting, wait
|
||||
sleep 2
|
||||
elapsed=$((elapsed + 2))
|
||||
echo " Waiting for $container... (${elapsed}s/${TIMEOUT}s)"
|
||||
done
|
||||
|
||||
echo " ERROR: Timeout waiting for $container"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Main health check sequence
|
||||
echo ""
|
||||
echo "Step 1/4: Checking container status..."
|
||||
echo "----------------------------------------"
|
||||
|
||||
for container in "$FRONTEND_CONTAINER" "$BACKEND_CONTAINER"; do
|
||||
running=$(docker inspect --format='{{.State.Running}}' "$container" 2>/dev/null || echo "false")
|
||||
if [[ "$running" != "true" ]]; then
|
||||
echo " ERROR: Container $container is not running"
|
||||
docker ps -a --filter "name=$container" --format "table {{.Names}}\t{{.Status}}"
|
||||
exit 1
|
||||
fi
|
||||
echo " OK: $container is running"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Step 2/4: Waiting for Docker health checks..."
|
||||
echo "----------------------------------------"
|
||||
|
||||
for container in "$FRONTEND_CONTAINER" "$BACKEND_CONTAINER"; do
|
||||
echo " Checking $container..."
|
||||
if ! wait_for_health "$container"; then
|
||||
echo " FAILED: $container health check"
|
||||
exit 1
|
||||
fi
|
||||
echo " OK: $container is healthy"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Step 3/4: Verifying HTTP endpoints..."
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Check frontend
|
||||
echo " Checking frontend HTTP..."
|
||||
if ! check_http_endpoint "$FRONTEND_CONTAINER" 3000 "/"; then
|
||||
echo " FAILED: Frontend HTTP check"
|
||||
exit 1
|
||||
fi
|
||||
echo " OK: Frontend responds on port 3000"
|
||||
|
||||
# Check backend health endpoint
|
||||
echo " Checking backend HTTP..."
|
||||
if ! check_http_endpoint "$BACKEND_CONTAINER" 3001 "/health"; then
|
||||
echo " FAILED: Backend HTTP check"
|
||||
exit 1
|
||||
fi
|
||||
echo " OK: Backend responds on port 3001"
|
||||
|
||||
echo ""
|
||||
echo "Step 4/4: Verifying database connectivity..."
|
||||
echo "----------------------------------------"
|
||||
|
||||
if ! check_database_connectivity "$BACKEND_CONTAINER"; then
|
||||
echo " WARNING: Could not verify database connectivity"
|
||||
echo " (Backend may not expose database status in /health)"
|
||||
else
|
||||
echo " OK: Database connectivity verified"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo "Health Check PASSED - $STACK Stack"
|
||||
echo "========================================"
|
||||
|
||||
# Update state file
|
||||
STATE_FILE="$PROJECT_ROOT/config/deployment/state.json"
|
||||
if [[ -f "$STATE_FILE" ]]; then
|
||||
# Update stack health status using jq if available
|
||||
if command -v jq &> /dev/null; then
|
||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
jq --arg stack "$STACK" --arg ts "$TIMESTAMP" \
|
||||
'.[$stack].healthy = true | .[$stack].last_health_check = $ts' \
|
||||
"$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user