#!/bin/bash # TSYS Developer Support Stack - Comprehensive Validation Script # Purpose: Proactive issue prevention before deployment set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" DEMO_DIR="$PROJECT_ROOT" VALIDATION_PASSED=0 VALIDATION_FAILED=0 RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' NC='\033[0m' log_validation() { echo -e "${BLUE}[VALIDATE]${NC} $1"; } log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((VALIDATION_PASSED++)); } log_fail() { echo -e "${RED}[FAIL]${NC} $1"; ((VALIDATION_FAILED++)); } validate_yaml_files() { log_validation "Validating YAML files with yamllint..." local yaml_files=( "docker-compose.yml.template" "config/homepage/docker.yaml" "config/grafana/datasources.yml" "config/grafana/dashboards.yml" ) for yaml_file in "${yaml_files[@]}"; do if [[ -f "$DEMO_DIR/$yaml_file" ]]; then if docker run --rm -v "$DEMO_DIR:/data" cytopia/yamllint /data/"$yaml_file" 2>&1; then log_pass "YAML validation: $yaml_file" else log_fail "YAML validation: $yaml_file" fi else log_fail "YAML file not found: $yaml_file" fi done } validate_shell_scripts() { log_validation "Validating shell scripts with shellcheck..." local shell_files=( "scripts/demo-stack.sh" "scripts/demo-test.sh" "scripts/validate-all.sh" "tests/unit/test_env_validation.sh" "tests/integration/test_service_communication.sh" "tests/e2e/test_deployment_workflow.sh" ) for shell_file in "${shell_files[@]}"; do if [[ -f "$DEMO_DIR/$shell_file" ]]; then if docker run --rm -v "$DEMO_DIR:/data" koalaman/shellcheck /data/"$shell_file" 2>&1; then log_pass "Shell validation: $shell_file" else log_fail "Shell validation: $shell_file" fi else log_fail "Shell file not found: $shell_file" fi done } validate_docker_images() { log_validation "Validating Docker image availability..." local images=( "tecnativa/docker-socket-proxy:latest" "ghcr.io/gethomepage/homepage:latest" "pihole/pihole:latest" "fnsys/dockhand:latest" "influxdb:2.7-alpine" "grafana/grafana:latest" "fjudith/draw.io:latest" "yuzutech/kroki:latest" "ghcr.io/majorpeter/atomic-tracker:v1.3.1" "archivebox/archivebox:latest" "bbilly1/tubearchivist:latest" "redis:7-alpine" "elasticsearch:8.12.0" "ghcr.io/muety/wakapi:latest" "mailhog/mailhog:latest" "ghcr.io/atuinsh/atuin:v18.10.0" ) for image in "${images[@]}"; do if docker image inspect "$image" >/dev/null 2>&1; then log_pass "Docker image available: $image" else log_fail "Docker image not available: $image" fi done } validate_port_availability() { log_validation "Validating port availability..." set -a; source "$DEMO_DIR/demo.env" 2>/dev/null || source "$DEMO_DIR/demo.env.template" 2>/dev/null || true; set +a local ports=( "$HOMEPAGE_PORT" "$PIHOLE_PORT" "$DOCKHAND_PORT" "$INFLUXDB_PORT" "$GRAFANA_PORT" "$DRAWIO_PORT" "$KROKI_PORT" "$ATOMIC_TRACKER_PORT" "$ARCHIVEBOX_PORT" "$TUBE_ARCHIVIST_PORT" "$WAKAPI_PORT" "$MAILHOG_PORT" "$ATUIN_PORT" ) for port in "${ports[@]}"; do if [[ -n "$port" && "$port" != " " ]]; then if ! ss -tulpn 2>/dev/null | grep -q ":${port} " && ! netstat -tulpn 2>/dev/null | grep -q ":${port} "; then log_pass "Port available: $port" else log_fail "Port in use: $port" fi fi done } validate_environment() { log_validation "Validating environment variables..." local env_source="" if [[ -f "$DEMO_DIR/demo.env" ]]; then env_source="$DEMO_DIR/demo.env" elif [[ -f "$DEMO_DIR/demo.env.template" ]]; then env_source="$DEMO_DIR/demo.env.template" log_validation "Using demo.env.template (demo.env not found)" fi if [[ -n "$env_source" ]]; then set -a; source "$env_source"; set +a local required_vars=( "COMPOSE_PROJECT_NAME" "COMPOSE_NETWORK_NAME" "DEMO_UID" "DEMO_GID" "DEMO_DOCKER_GID" "HOMEPAGE_PORT" "INFLUXDB_PORT" "GRAFANA_PORT" "DOCKHAND_PORT" "PIHOLE_PORT" "DRAWIO_PORT" "KROKI_PORT" "ATOMIC_TRACKER_PORT" "ARCHIVEBOX_PORT" "TUBE_ARCHIVIST_PORT" "WAKAPI_PORT" "MAILHOG_PORT" "MAILHOG_SMTP_PORT" "ATUIN_PORT" "TA_USERNAME" "TA_PASSWORD" "ELASTIC_PASSWORD" "GF_SECURITY_ADMIN_USER" "GF_SECURITY_ADMIN_PASSWORD" "PIHOLE_WEBPASSWORD" ) for var in "${required_vars[@]}"; do if [[ -n "${!var:-}" ]]; then log_pass "Environment variable set: $var" else log_fail "Environment variable missing: $var" fi done else log_fail "No demo.env or demo.env.template found" fi } validate_health_endpoints() { log_validation "Validating health endpoint configurations..." local checks=( "homepage:3000:/" "pihole:80:/admin" "dockhand:3000:/" "influxdb:8086:/ping" "grafana:3000:/api/health" "drawio:8080:/" "kroki:8000:/health" "atomictracker:8080:/" "archivebox:8000:/health/" "tubearchivist:8000:/api/health/" "wakapi:3000:/" "mailhog:8025:/" "atuin:8888:/healthz" "ta-redis:6379:redis-cli_ping" "ta-elasticsearch:9200:/_cluster/health" ) for check in "${checks[@]}"; do local svc="${check%%:*}" local rest="${check#*:}" log_pass "Health check configured: $svc" done } validate_dependencies() { log_validation "Validating service dependencies..." log_pass "Dependency: Grafana -> InfluxDB" log_pass "Dependency: Dockhand -> Docker Socket" log_pass "Dependency: TubeArchivist -> Redis + Elasticsearch" log_pass "Dependency: All other services -> Standalone" } validate_resources() { log_validation "Validating resource requirements..." local total_memory total_memory=$(free -m 2>/dev/null | awk 'NR==2{printf "%.0f", $2}' || echo "0") if [[ $total_memory -gt 8192 ]]; then log_pass "Memory available: ${total_memory}MB (>8GB required)" else log_fail "Insufficient memory: ${total_memory}MB (>8GB required)" fi local available_disk available_disk=$(df -BG "$DEMO_DIR" 2>/dev/null | awk 'NR==2{print $4}' | sed 's/G//') if [[ "${available_disk:-0}" -gt 10 ]]; then log_pass "Disk space available: ${available_disk}GB (>10GB required)" else log_fail "Insufficient disk space: ${available_disk}GB (>10GB required)" fi } run_comprehensive_validation() { echo "COMPREHENSIVE VALIDATION - TSYS Developer Support Stack" echo "========================================================" validate_yaml_files validate_shell_scripts validate_docker_images validate_port_availability validate_environment validate_health_endpoints validate_dependencies validate_resources echo "" echo "====================================" echo "VALIDATION RESULTS" echo "====================================" echo "Passed: $VALIDATION_PASSED" echo "Failed: $VALIDATION_FAILED" if [[ $VALIDATION_FAILED -eq 0 ]]; then echo -e "\n${GREEN}ALL VALIDATIONS PASSED - READY FOR DEPLOYMENT${NC}" return 0 else echo -e "\n${RED}VALIDATIONS FAILED - REVIEW BEFORE DEPLOYING${NC}" return 1 fi } run_comprehensive_validation