Files
unitforge/scripts/health_check.sh
William Valentin 25666a76cf feat: Add comprehensive Gitea CI/CD workflows for multi-arch container builds
- Add build-container.yml: Main build pipeline with multi-arch support
- Add pr-check.yml: Pull request validation with comprehensive testing
- Add release.yml: Automated release pipeline with security scanning
- Add nightly.yml: Daily builds with performance testing
- Add health_check.sh: Container health validation script
- Add setup-ci.sh: Local CI/CD environment setup script
- Add comprehensive CI/CD documentation

Features:
- Multi-architecture builds (linux/amd64, linux/arm64)
- Security scanning with Trivy
- Automated PyPI publishing for releases
- Container registry integration
- Performance testing and validation
- Artifact management and cleanup
- Build caching and optimization

Supports full development workflow from PR to production deployment.
2025-09-15 02:04:07 -07:00

307 lines
8.4 KiB
Bash
Executable File

#!/bin/bash
# Health check script for UnitForge CI/CD workflows
# Tests basic functionality of the running application
set -e
# Configuration
HOST=${HOST:-localhost}
PORT=${PORT:-8000}
TIMEOUT=${TIMEOUT:-30}
MAX_RETRIES=${MAX_RETRIES:-5}
RETRY_DELAY=${RETRY_DELAY:-2}
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Helper functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check if application is responding
check_health() {
local url="http://${HOST}:${PORT}/health"
local retry_count=0
log_info "Checking health endpoint: $url"
while [ $retry_count -lt "$MAX_RETRIES" ]; do
if curl -s -f --max-time "$TIMEOUT" "$url" > /dev/null 2>&1; then
log_info "Health check passed"
return 0
fi
retry_count=$((retry_count + 1))
log_warn "Health check failed (attempt $retry_count/$MAX_RETRIES)"
if [ $retry_count -lt "$MAX_RETRIES" ]; then
log_info "Retrying in ${RETRY_DELAY} seconds..."
sleep "$RETRY_DELAY"
fi
done
log_error "Health check failed after $MAX_RETRIES attempts"
return 1
}
# Check if main page loads
check_main_page() {
local url="http://${HOST}:${PORT}/"
log_info "Checking main page: $url"
local response
response=$(curl -s -w "%{http_code}" --max-time "$TIMEOUT" "$url")
local http_code="${response: -3}"
if [ "$http_code" = "200" ]; then
log_info "Main page check passed (HTTP $http_code)"
return 0
else
log_error "Main page check failed (HTTP $http_code)"
return 1
fi
}
# Check API endpoints
check_api() {
local base_url="http://${HOST}:${PORT}/api"
log_info "Checking API endpoints"
# Check API health
local api_health_url="${base_url}/health"
if curl -s -f --max-time "$TIMEOUT" "$api_health_url" > /dev/null 2>&1; then
log_info "API health endpoint passed"
else
log_warn "API health endpoint failed or not available"
fi
# Check API version
local api_version_url="${base_url}/version"
if curl -s -f --max-time "$TIMEOUT" "$api_version_url" > /dev/null 2>&1; then
log_info "API version endpoint passed"
else
log_warn "API version endpoint failed or not available"
fi
return 0
}
# Check static assets
check_static_assets() {
log_info "Checking static assets"
local assets=(
"/static/css/style.css"
"/static/js/app.js"
"/static/vendor/bootstrap/css/bootstrap.min.css"
"/static/vendor/fontawesome/css/all.min.css"
)
local failed_assets=0
for asset in "${assets[@]}"; do
local url="http://${HOST}:${PORT}${asset}"
if curl -s -f --max-time "$TIMEOUT" "$url" > /dev/null 2>&1; then
log_info "Asset check passed: $asset"
else
log_warn "Asset check failed: $asset"
failed_assets=$((failed_assets + 1))
fi
done
if [ $failed_assets -eq 0 ]; then
log_info "All static assets available"
return 0
else
log_warn "$failed_assets static assets failed to load"
return 0 # Don't fail health check for missing assets
fi
}
# Performance test
check_performance() {
log_info "Running basic performance test"
local url="http://${HOST}:${PORT}/"
local response_time
# Test response time
local response_time
response_time=$(curl -s -w "%{time_total}" --max-time "$TIMEOUT" -o /dev/null "$url")
if curl -s -w "%{time_total}" --max-time "$TIMEOUT" -o /dev/null "$url" > /dev/null 2>&1; then
log_info "Response time: ${response_time}s"
# Check if response time is reasonable (< 5 seconds)
if (( $(echo "$response_time < 5.0" | bc -l) )); then
log_info "Performance check passed"
return 0
else
log_warn "Performance check warning: slow response time (${response_time}s)"
return 0 # Don't fail health check for slow response
fi
else
log_error "Performance check failed: no response"
return 1
fi
}
# Memory usage check (if running in container)
check_memory() {
if command -v docker > /dev/null 2>&1 && [ -n "$CONTAINER_NAME" ]; then
log_info "Checking container memory usage"
local memory_usage
memory_usage=$(docker stats "$CONTAINER_NAME" --no-stream --format "{{.MemUsage}}" | cut -d'/' -f1)
if [ -n "$memory_usage" ]; then
log_info "Memory usage: $memory_usage"
else
log_warn "Could not determine memory usage"
fi
fi
}
# Wait for application to start
wait_for_startup() {
log_info "Waiting for application to start..."
local startup_timeout=60
local elapsed=0
while [ $elapsed -lt $startup_timeout ]; do
if curl -s --max-time 5 "http://${HOST}:${PORT}/" > /dev/null 2>&1; then
log_info "Application is responding"
return 0
fi
sleep 5
elapsed=$((elapsed + 5))
log_info "Waiting... (${elapsed}s/${startup_timeout}s)"
done
log_error "Application failed to start within ${startup_timeout} seconds"
return 1
}
# Main health check function
run_health_check() {
log_info "Starting UnitForge health check"
log_info "Target: http://${HOST}:${PORT}"
local failed_checks=0
# Wait for startup if needed
if ! curl -s --max-time 5 "http://${HOST}:${PORT}/" > /dev/null 2>&1; then
wait_for_startup || return 1
fi
# Run all checks
check_health || failed_checks=$((failed_checks + 1))
check_main_page || failed_checks=$((failed_checks + 1))
check_api || failed_checks=$((failed_checks + 1))
check_static_assets || true # Don't count static asset failures
check_performance || true # Don't count performance warnings
check_memory || true # Don't count memory check failures
# Summary
if [ $failed_checks -eq 0 ]; then
log_info "✅ All health checks passed"
return 0
else
log_error "$failed_checks health checks failed"
return 1
fi
}
# Usage information
usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -h, --host HOST Target host (default: localhost)"
echo " -p, --port PORT Target port (default: 8000)"
echo " -t, --timeout TIMEOUT Request timeout in seconds (default: 30)"
echo " -r, --retries RETRIES Maximum retry attempts (default: 5)"
echo " -d, --delay DELAY Retry delay in seconds (default: 2)"
echo " -c, --container NAME Container name for memory checks"
echo " --help Show this help message"
echo ""
echo "Environment variables:"
echo " HOST Same as --host"
echo " PORT Same as --port"
echo " TIMEOUT Same as --timeout"
echo " MAX_RETRIES Same as --retries"
echo " RETRY_DELAY Same as --delay"
echo " CONTAINER_NAME Same as --container"
echo ""
echo "Examples:"
echo " $0 # Check localhost:8000"
echo " $0 -h production.example.com -p 80 # Check production server"
echo " $0 -c unitforge-container # Include container memory check"
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--host)
HOST="$2"
shift 2
;;
-p|--port)
PORT="$2"
shift 2
;;
-t|--timeout)
TIMEOUT="$2"
shift 2
;;
-r|--retries)
MAX_RETRIES="$2"
shift 2
;;
-d|--delay)
RETRY_DELAY="$2"
shift 2
;;
-c|--container)
CONTAINER_NAME="$2"
shift 2
;;
--help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
done
# Check dependencies
if ! command -v curl > /dev/null 2>&1; then
log_error "curl is required but not installed"
exit 1
fi
if ! command -v bc > /dev/null 2>&1; then
log_warn "bc is not installed, performance timing may not work properly"
fi
# Run the health check
run_health_check
exit $?