- Update all scripts to use 'docker compose' instead of 'docker-compose' - Fix compose file paths after consolidation (test.yml, prod.yml) - Update cleanup.sh to handle --profile debug and --profile smoke - Update test fixtures to reference consolidated compose files
241 lines
8.4 KiB
Bash
Executable file
241 lines
8.4 KiB
Bash
Executable file
#!/bin/bash
|
|
# Quick deployment script for fetch_ml
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
|
|
export FETCHML_REPO_ROOT="${FETCHML_REPO_ROOT:-${REPO_ROOT}}"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Function to print colored output
|
|
print_status() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Function to show usage
|
|
show_usage() {
|
|
echo "Usage: $0 [ENVIRONMENT] [ACTION]"
|
|
echo ""
|
|
echo "Environments:"
|
|
echo " dev Development environment"
|
|
echo " staging Staging environment (pre-production)"
|
|
echo " secure Secure homelab environment"
|
|
echo " prod Production environment"
|
|
echo ""
|
|
echo "Actions:"
|
|
echo " up Start services"
|
|
echo " down Stop services"
|
|
echo " restart Restart services"
|
|
echo " logs Show logs"
|
|
echo " status Show status"
|
|
echo " rollback Rollback to previous deployment (image only)"
|
|
echo " health-check Check service health and compliance mode"
|
|
echo " check-audit-sink Verify audit sink reachability"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 dev up # Start development environment"
|
|
echo " $0 staging up # Start staging environment"
|
|
echo " $0 prod down # Stop production environment"
|
|
echo " $0 staging rollback # Rollback staging deployment"
|
|
echo " $0 prod health-check # Check production health"
|
|
echo " $0 prod check-audit-sink # Verify audit sink before deploy"
|
|
}
|
|
|
|
# Function to check if docker-compose file exists
|
|
check_compose_file() {
|
|
local env=$1
|
|
local compose_file=""
|
|
|
|
case $env in
|
|
"dev")
|
|
compose_file="${FETCHML_REPO_ROOT}/deployments/docker-compose.dev.yml"
|
|
;;
|
|
"staging")
|
|
compose_file="${FETCHML_REPO_ROOT}/deployments/docker-compose.staging.yml"
|
|
;;
|
|
"secure")
|
|
compose_file="${FETCHML_REPO_ROOT}/deployments/docker-compose.homelab-secure.yml"
|
|
;;
|
|
"prod")
|
|
compose_file="${FETCHML_REPO_ROOT}/deployments/docker-compose.prod.yml"
|
|
;;
|
|
*)
|
|
print_error "Unknown environment: $env"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
if [ ! -f "$compose_file" ]; then
|
|
print_error "Docker Compose file not found: $compose_file"
|
|
exit 1
|
|
fi
|
|
|
|
echo "$compose_file"
|
|
}
|
|
|
|
# Function to check if .env file exists
|
|
check_env_file() {
|
|
local env=$1
|
|
|
|
if [ ! -f "${FETCHML_REPO_ROOT}/.env" ]; then
|
|
print_warning ".env file not found. Creating from example..."
|
|
if [ "$env" = "dev" ]; then
|
|
cp "${FETCHML_REPO_ROOT}/deployments/env.dev.example" "${FETCHML_REPO_ROOT}/.env"
|
|
elif [ "$env" = "prod" ]; then
|
|
cp "${FETCHML_REPO_ROOT}/deployments/env.prod.example" "${FETCHML_REPO_ROOT}/.env"
|
|
else
|
|
cp "${FETCHML_REPO_ROOT}/deployments/env.dev.example" "${FETCHML_REPO_ROOT}/.env"
|
|
fi
|
|
print_warning "Please edit .env file with your configuration"
|
|
fi
|
|
}
|
|
|
|
# Main script
|
|
main() {
|
|
if [ $# -ne 2 ]; then
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
local environment=$1
|
|
local action=$2
|
|
|
|
print_status "Environment: $environment"
|
|
print_status "Action: $action"
|
|
|
|
# Check compose file
|
|
compose_file=$(check_compose_file "$environment")
|
|
print_status "Using: $compose_file"
|
|
|
|
# Check .env file
|
|
check_env_file "$environment"
|
|
|
|
# Execute action
|
|
case $action in
|
|
"up")
|
|
print_status "Starting $environment environment..."
|
|
docker compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" up -d
|
|
print_success "$environment environment started successfully!"
|
|
|
|
# Show service URLs
|
|
echo ""
|
|
print_status "Service URLs:"
|
|
echo " API Server: http://localhost:9101"
|
|
if [ "$environment" = "dev" ]; then
|
|
echo " Grafana: http://localhost:3000 (admin/admin123)"
|
|
echo " Prometheus: http://localhost:9090"
|
|
fi
|
|
;;
|
|
"down")
|
|
print_status "Stopping $environment environment..."
|
|
docker-compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" down
|
|
print_success "$environment environment stopped successfully!"
|
|
;;
|
|
"restart")
|
|
print_status "Restarting $environment environment..."
|
|
docker-compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" restart
|
|
print_success "$environment environment restarted successfully!"
|
|
;;
|
|
"logs")
|
|
print_status "Showing logs for $environment environment..."
|
|
docker-compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" logs -f
|
|
;;
|
|
"status")
|
|
print_status "Status of $environment environment:"
|
|
docker-compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" ps
|
|
;;
|
|
"rollback")
|
|
print_warning "Rolling back $environment environment..."
|
|
print_warning "⚠ This rolls back the image only - queue state and audit log are NOT rolled back"
|
|
|
|
if [ "$environment" = "prod" ]; then
|
|
print_warning "⚠ CRITICAL: Production rollback"
|
|
print_warning "⚠ Queue state is NOT rolled back"
|
|
print_warning "⚠ Audit log chain is NOT rolled back (must never break chain)"
|
|
read -p "CONFIRM PRODUCTION ROLLBACK? [yes/N] " confirm
|
|
if [ "$confirm" != "yes" ]; then
|
|
print_error "Rollback cancelled"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Get previous deployment info
|
|
LOG_FILE="${FETCHML_REPO_ROOT}/deployments/.${environment}-audit.log"
|
|
if [ -f "$LOG_FILE" ]; then
|
|
PREVIOUS_SHA=$(tail -2 "$LOG_FILE" | head -1 | grep -o 'sha-[a-f0-9]*' || echo "")
|
|
if [ -n "$PREVIOUS_SHA" ]; then
|
|
print_status "Rolling back to: $PREVIOUS_SHA"
|
|
fi
|
|
fi
|
|
|
|
docker compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" down
|
|
docker compose --project-directory "${FETCHML_REPO_ROOT}" -f "$compose_file" up -d
|
|
|
|
# Write rollback entry to audit log
|
|
echo "$(date -Iseconds) | rollback | $environment | actor=$(whoami)" >> "$LOG_FILE" 2>/dev/null || true
|
|
|
|
print_success "$environment rollback complete!"
|
|
print_status "Verify health with: $0 $environment health-check"
|
|
;;
|
|
"health-check"|"health")
|
|
print_status "Health check for $environment environment..."
|
|
|
|
# Determine port based on environment
|
|
case $environment in
|
|
dev) PORT=9101 ;;
|
|
staging) PORT=9102 ;;
|
|
prod) PORT=9101 ;;
|
|
*) PORT=9101 ;;
|
|
esac
|
|
|
|
# Check API health
|
|
if curl -fsS "http://localhost:${PORT}/health" > /dev/null 2>&1; then
|
|
print_success "API is healthy (port $PORT)"
|
|
|
|
# Check compliance_mode
|
|
COMPLIANCE_MODE=$(curl -fsS "http://localhost:${PORT}/health" 2>/dev/null | grep -o '"compliance_mode":"[^"]*"' | cut -d'"' -f4 || echo "unknown")
|
|
print_status "Compliance mode: $COMPLIANCE_MODE"
|
|
else
|
|
print_error "API health check failed (port $PORT)"
|
|
exit 1
|
|
fi
|
|
;;
|
|
"check-audit-sink")
|
|
print_status "Checking audit sink for $environment..."
|
|
|
|
if [ -f "${FETCHML_REPO_ROOT}/scripts/check-audit-sink.sh" ]; then
|
|
"${FETCHML_REPO_ROOT}/scripts/check-audit-sink.sh" --env "$environment"
|
|
else
|
|
print_warning "Audit sink check script not found"
|
|
fi
|
|
;;
|
|
*)
|
|
print_error "Unknown action: $action"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|