#!/bin/bash # ================================================ # Math Platform - Pre-Deployment Validation # ================================================ set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ERRORS=0 WARNINGS=0 echo -e "${BLUE}============================================${NC}" echo -e "${BLUE}Math Platform - Pre-Deployment Validation${NC}" echo -e "${BLUE}============================================${NC}" # Function to print check result print_result() { local status=$1 local message=$2 if [ "$status" = "OK" ]; then echo -e "${GREEN}✓${NC} $message" elif [ "$status" = "WARN" ]; then echo -e "${YELLOW}⚠${NC} $message" WARNINGS=$((WARNINGS + 1)) else echo -e "${RED}✗${NC} $message" ERRORS=$((ERRORS + 1)) fi } # Check 1: Docker Installation echo -e "\n${BLUE}Checking Prerequisites${NC}" echo "----------------------------------------" if command -v docker &> /dev/null; then DOCKER_VERSION=$(docker --version | awk '{print $3}' | sed 's/,//') print_result "OK" "Docker installed: $DOCKER_VERSION" else print_result "FAIL" "Docker not installed" fi if command -v docker-compose &> /dev/null || docker compose version &> /dev/null; then print_result "OK" "Docker Compose available" else print_result "FAIL" "Docker Compose not installed" fi # Check 2: Environment File echo -e "\n${BLUE}Checking Environment Configuration${NC}" echo "----------------------------------------" if [ -f "$PROJECT_ROOT/.env" ]; then print_result "OK" ".env file exists" # Check critical variables source "$PROJECT_ROOT/.env" if [ -n "$DB_PASSWORD" ] && [ ${#DB_PASSWORD} -ge 16 ]; then print_result "OK" "DB_PASSWORD configured (length: ${#DB_PASSWORD})" else print_result "WARN" "DB_PASSWORD not set or too short (min 16 chars)" fi if [ -n "$REDIS_PASSWORD" ] && [ ${#REDIS_PASSWORD} -ge 16 ]; then print_result "OK" "REDIS_PASSWORD configured (length: ${#REDIS_PASSWORD})" else print_result "WARN" "REDIS_PASSWORD not set or too short (min 16 chars)" fi if [ -n "$JWT_SECRET" ] && [ ${#JWT_SECRET} -ge 32 ]; then print_result "OK" "JWT_SECRET configured (length: ${#JWT_SECRET})" else print_result "FAIL" "JWT_SECRET not set or too short (min 32 chars)" fi if [ -n "$AI_API_KEY" ]; then print_result "OK" "AI_API_KEY configured" else print_result "WARN" "AI_API_KEY not set (AI features won't work)" fi else print_result "FAIL" ".env file not found" fi # Check 3: Required Files echo -e "\n${BLUE}Checking Required Files${NC}" echo "----------------------------------------" files=( "docker-compose.yml:docker-compose.yml" "Dockerfile (Backend):docker/Dockerfile.backend" "Dockerfile (Frontend):docker/Dockerfile.frontend" "Dockerfile (Worker):docker/Dockerfile.worker" "Nginx config:docker/nginx.conf" "Backend package.json:backend/package.json" "Frontend package.json:frontend/package.json" "Prisma schema:backend/prisma/schema.prisma" "Next.js config:frontend/next.config.js" ) for file_info in "${files[@]}"; do file="${file_info##*:}" name="${file_info%:*}" if [ -f "$PROJECT_ROOT/$file" ]; then print_result "OK" "$name exists" else print_result "FAIL" "$name missing: $file" fi done # Check 4: Required Directories echo -e "\n${BLUE}Checking Directories${NC}" echo "----------------------------------------" dirs=( "Backend source:backend/src" "Frontend source:frontend/src" "Docker data:docker/data" "Docker logs:docker/logs" "Init scripts:docker/init-scripts" "Scripts:scripts" "PDF storage:pdfs" ) for dir_info in "${dirs[@]}"; do dir="${dir_info##*:}" name="${dir_info%:*}" if [ -d "$PROJECT_ROOT/$dir" ]; then print_result "OK" "$name exists" else print_result "WARN" "$name missing: $dir" fi done # Check 5: Script Permissions echo -e "\n${BLUE}Checking Script Permissions${NC}" echo "----------------------------------------" scripts=( "docker/start.sh" "docker/stop.sh" "docker/backup.sh" "scripts/test-e2e.sh" "scripts/health-check.sh" "scripts/monitor.sh" ) for script in "${scripts[@]}"; do if [ -f "$PROJECT_ROOT/$script" ]; then if [ -x "$PROJECT_ROOT/$script" ]; then print_result "OK" "$script is executable" else print_result "WARN" "$script is not executable" fi else print_result "WARN" "$script not found" fi done # Check 6: Docker Resources echo -e "\n${BLUE}Checking Docker Resources${NC}" echo "----------------------------------------" if docker info &> /dev/null; then # Check available disk space DISK_AVAILABLE=$(df -h "$PROJECT_ROOT" | awk 'NR==2 {print $4}') DISK_USAGE_PERCENT=$(df -h "$PROJECT_ROOT" | awk 'NR==2 {print $5}' | sed 's/%//') if [ "$DISK_USAGE_PERCENT" -lt 80 ]; then print_result "OK" "Disk space available: $DISK_AVAILABLE" else print_result "WARN" "Disk space low: $DISK_AVAILABLE available" fi # Check Docker memory DOCKER_MEMORY=$(docker info 2>/dev/null | grep "Total Memory" | awk '{print $3}' || echo "N/A") if [ "$DOCKER_MEMORY" != "N/A" ]; then print_result "OK" "Docker memory: $DOCKER_MEMORY" fi # Check for running containers RUNNING_CONTAINERS=$(docker ps -q | wc -l) print_result "OK" "Running containers: $RUNNING_CONTAINERS" else print_result "WARN" "Docker not running" fi # Check 7: Port Availability echo -e "\n${BLUE}Checking Port Availability${NC}" echo "----------------------------------------" ports=("80:HTTP" "3000:Frontend" "3001:Backend" "5432:PostgreSQL" "6379:Redis") for port_info in "${ports[@]}"; do port="${port_info%%:*}" name="${port_info##*:}" if netstat -tuln 2>/dev/null | grep -q ":$port " || ss -tuln 2>/dev/null | grep -q ":$port "; then print_result "WARN" "Port $port ($name) already in use" else print_result "OK" "Port $port ($name) available" fi done # Check 8: File Permissions echo -e "\n${BLUE}Checking File Permissions${NC}" echo "----------------------------------------" if [ -d "$PROJECT_ROOT/docker/data" ]; then if [ -w "$PROJECT_ROOT/docker/data" ]; then print_result "OK" "docker/data is writable" else print_result "FAIL" "docker/data is not writable" fi fi if [ -d "$PROJECT_ROOT/docker/logs" ]; then if [ -w "$PROJECT_ROOT/docker/logs" ]; then print_result "OK" "docker/logs is writable" else print_result "FAIL" "docker/logs is not writable" fi fi # Summary echo -e "\n${BLUE}============================================${NC}" echo -e "${BLUE}Validation Summary${NC}" echo -e "${BLUE}============================================${NC}" if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then echo -e "${GREEN}All checks passed! Ready for deployment.${NC}\n" exit 0 elif [ $ERRORS -eq 0 ]; then echo -e "${YELLOW}Validation passed with $WARNINGS warning(s).${NC}\n" exit 0 else echo -e "${RED}Validation failed with $ERRORS error(s) and $WARNINGS warning(s).${NC}\n" exit 1 fi