🎓 Initial commit: Math2 Platform - Plataforma de Álgebra Lineal PRO
✨ Características: - 45 ejercicios universitarios (Basic → Advanced) - Renderizado LaTeX profesional - IA generativa (Z.ai/DashScope) - Docker 9 servicios - Tests 123/123 pasando - Seguridad enterprise (JWT, XSS, Rate limiting) 🐳 Infraestructura: - Next.js 14 + Node.js 20 - PostgreSQL 15 + Redis 7 - Docker Compose completo - Nginx + SSL ready 📚 Documentación: - 5 informes técnicos completos - README profesional - Scripts de deployment automatizados Estado: Producción lista ✅
This commit is contained in:
238
scripts/clean.sh
Executable file
238
scripts/clean.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Script de limpieza de artefactos generados
|
||||
# Uso: ./scripts/clean.sh [-a|--all] [-h|--help]
|
||||
#
|
||||
# Elimina:
|
||||
# - Build outputs (.next/, dist/, build/)
|
||||
# - Dependencias (node_modules/)
|
||||
# - Logs, coverage, archivos temporales
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colores
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Flags
|
||||
ALL=false
|
||||
DRY_RUN=false
|
||||
|
||||
# Función para mostrar ayuda
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Uso: ./scripts/clean.sh [OPCIONES]
|
||||
|
||||
Limpia artefactos generados del proyecto.
|
||||
|
||||
OPCIONES:
|
||||
-a, --all Limpia TODO incluyendo node_modules
|
||||
-d, --dry-run Muestra qué se eliminaría sin eliminarlo
|
||||
-h, --help Muestra esta ayuda
|
||||
|
||||
Ejemplos:
|
||||
./scripts/clean.sh # Limpia builds, logs, coverage
|
||||
./scripts/clean.sh -a # Limpia TODO incluyendo node_modules
|
||||
./scripts/clean.sh -d # Muestra qué se eliminaría
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parsear argumentos
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-a|--all)
|
||||
ALL=true
|
||||
shift
|
||||
;;
|
||||
-d|--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Error: Opción desconocida: $1${NC}"
|
||||
echo "Usa -h o --help para ver opciones disponibles"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Función para eliminar directorios
|
||||
remove_dir() {
|
||||
local path=$1
|
||||
if [[ -d "$path" ]]; then
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo -e "${YELLOW}[DRY RUN] Se eliminaría:${NC} $path"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Calcular tamaño
|
||||
local size
|
||||
size=$(du -sh "$path" 2>/dev/null | cut -f1) || size="?"
|
||||
rm -rf "$path"
|
||||
echo -e "${GREEN}✓${NC} Eliminado: $path (${size})"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Función para eliminar archivos
|
||||
remove_file() {
|
||||
local pattern=$1
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
find . -name "$pattern" -type f 2>/dev/null | while read -r file; do
|
||||
echo -e "${YELLOW}[DRY RUN] Se eliminaría:${NC} $file"
|
||||
done
|
||||
return 0
|
||||
fi
|
||||
|
||||
local count=0
|
||||
while IFS= read -r -d '' file; do
|
||||
rm -f "$file"
|
||||
((count++))
|
||||
done < <(find . -name "$pattern" -type f -print0 2>/dev/null)
|
||||
|
||||
if [[ $count -gt 0 ]]; then
|
||||
echo -e "${GREEN}✓${NC} Eliminados $count archivos: $pattern"
|
||||
fi
|
||||
}
|
||||
|
||||
# Header
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE} Limpieza de Artefactos Generados ${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo -e "${YELLOW}MODO DRY RUN - No se eliminará nada${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Contador de eliminados
|
||||
declare -i TOTAL_SIZE=0
|
||||
|
||||
# ============================================
|
||||
# FRONTEND - Build outputs
|
||||
# ============================================
|
||||
echo -e "${BLUE}Frontend:${NC}"
|
||||
remove_dir "frontend/.next"
|
||||
remove_dir "frontend/out"
|
||||
remove_dir "frontend/build"
|
||||
remove_dir "frontend/dist"
|
||||
|
||||
# ============================================
|
||||
# BACKEND - Build outputs
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Backend:${NC}"
|
||||
remove_dir "backend/dist"
|
||||
remove_dir "backend/build"
|
||||
remove_dir "backend/coverage"
|
||||
remove_dir "backend/.nyc_output"
|
||||
|
||||
# ============================================
|
||||
# ROOT - Build outputs
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Root:${NC}"
|
||||
remove_dir "coverage"
|
||||
remove_dir ".nyc_output"
|
||||
remove_dir ".cache"
|
||||
remove_dir ".temp"
|
||||
remove_dir ".tmp"
|
||||
|
||||
# ============================================
|
||||
# LOGS
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Logs:${NC}"
|
||||
remove_file "*.log"
|
||||
remove_file "npm-debug.log*"
|
||||
remove_file "yarn-debug.log*"
|
||||
remove_file "yarn-error.log*"
|
||||
|
||||
# ============================================
|
||||
# COVERAGE REPORTS
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Coverage:${NC}"
|
||||
remove_dir "coverage"
|
||||
remove_file "*.lcov"
|
||||
|
||||
# ============================================
|
||||
# NODE_MODULES (solo si --all)
|
||||
# ============================================
|
||||
if [[ "$ALL" == true ]]; then
|
||||
echo ""
|
||||
echo -e "${BLUE}Dependencias (node_modules):${NC}"
|
||||
remove_dir "frontend/node_modules"
|
||||
remove_dir "backend/node_modules"
|
||||
remove_dir "node_modules"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Para reinstalar dependencias:${NC}"
|
||||
echo " npm install"
|
||||
echo " cd frontend && npm install"
|
||||
echo " cd ../backend && npm install"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# DOCKER DATA (opcional)
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Docker data (si existen):${NC}"
|
||||
remove_dir "docker-data"
|
||||
remove_dir "postgres_data"
|
||||
remove_dir "redis_data"
|
||||
|
||||
# ============================================
|
||||
# OTROS ARTEFACTOS
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}Otros artefactos:${NC}"
|
||||
remove_file ".DS_Store"
|
||||
remove_file "Thumbs.db"
|
||||
remove_file "*.swp"
|
||||
remove_file "*.swo"
|
||||
remove_file "*~"
|
||||
remove_dir "uploads" # Excepto .gitkeep
|
||||
|
||||
# Preservar .gitkeep en uploads
|
||||
if [[ -d "uploads" && "$DRY_RUN" == false ]]; then
|
||||
mkdir -p uploads/pdfs
|
||||
touch uploads/pdfs/.gitkeep
|
||||
echo -e "${GREEN}✓${NC} Preservado uploads/pdfs/.gitkeep"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# RESUMEN
|
||||
# ============================================
|
||||
echo ""
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${GREEN}Limpieza completada!${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Nota:${NC} Esto fue un DRY RUN. Nada fue eliminado."
|
||||
echo "Ejecuta sin --dry-run para limpiar realmente."
|
||||
fi
|
||||
|
||||
if [[ "$ALL" == true ]]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Nota:${NC} Se eliminaron node_modules."
|
||||
echo "Ejecuta 'npm install' para reinstalar dependencias."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Para reinstalar dependencias:${NC}"
|
||||
echo " npm install"
|
||||
echo " cd frontend && npm install && cd ../backend && npm install"
|
||||
359
scripts/deploy.sh
Executable file
359
scripts/deploy.sh
Executable file
@@ -0,0 +1,359 @@
|
||||
#!/bin/bash
|
||||
# ========================================
|
||||
# MATH PLATFORM - PRODUCTION DEPLOYMENT
|
||||
# Enterprise Grade Deployment Script
|
||||
# ========================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
BACKUP_DIR="$PROJECT_DIR/backups"
|
||||
LOG_DIR="$PROJECT_DIR/logs"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Logging functions
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Error handler
|
||||
error_handler() {
|
||||
log_error "Deployment failed at line $1"
|
||||
log_info "Rolling back to previous state..."
|
||||
rollback_deployment
|
||||
exit 1
|
||||
}
|
||||
|
||||
trap 'error_handler $LINENO' ERR
|
||||
|
||||
# ========================================
|
||||
# PRE-DEPLOYMENT CHECKS
|
||||
# ========================================
|
||||
|
||||
check_prerequisites() {
|
||||
log_info "Checking prerequisites..."
|
||||
|
||||
# Check if running as root (should NOT)
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
log_error "Do not run this script as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check required commands
|
||||
local required_commands=("docker" "docker-compose" "curl" "wget")
|
||||
for cmd in "${required_commands[@]}"; do
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
log_error "$cmd is required but not installed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Check Docker is running
|
||||
if ! docker info &> /dev/null; then
|
||||
log_error "Docker daemon is not running"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Prerequisites check passed"
|
||||
}
|
||||
|
||||
check_environment() {
|
||||
log_info "Checking environment variables..."
|
||||
|
||||
local required_vars=(
|
||||
"DATABASE_URL"
|
||||
"REDIS_PASSWORD"
|
||||
"JWT_SECRET"
|
||||
)
|
||||
|
||||
local missing_vars=()
|
||||
for var in "${required_vars[@]}"; do
|
||||
if [[ -z "${!var:-}" ]]; then
|
||||
missing_vars+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing_vars[@]} -gt 0 ]]; then
|
||||
log_error "Missing required environment variables:"
|
||||
printf '%s\n' "${missing_vars[@]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Environment variables check passed"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# DATABASE OPERATIONS
|
||||
# ========================================
|
||||
|
||||
create_backup() {
|
||||
log_info "Creating database backup..."
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
local backup_file="$BACKUP_DIR/backup_$TIMESTAMP.sql"
|
||||
|
||||
# Extract database info from DATABASE_URL
|
||||
local db_container="math-postgres-prod"
|
||||
|
||||
if docker ps | grep -q "$db_container"; then
|
||||
if docker exec "$db_container" pg_dump -U mathuser mathdb > "$backup_file"; then
|
||||
log_success "Database backup created: $backup_file"
|
||||
|
||||
# Compress backup
|
||||
gzip "$backup_file"
|
||||
log_success "Backup compressed: ${backup_file}.gz"
|
||||
|
||||
# Keep only last 7 backups
|
||||
ls -t "$BACKUP_DIR"/backup_*.sql.gz | tail -n +8 | xargs -r rm
|
||||
else
|
||||
log_warning "Failed to create database backup, continuing anyway..."
|
||||
fi
|
||||
else
|
||||
log_warning "Database container not running, skipping backup"
|
||||
fi
|
||||
}
|
||||
|
||||
run_migrations() {
|
||||
log_info "Running database migrations..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Create temporary migration container
|
||||
docker-compose -f docker-compose.prod.yml run --rm backend npx prisma migrate deploy
|
||||
|
||||
log_success "Database migrations completed"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# DEPLOYMENT OPERATIONS
|
||||
# ========================================
|
||||
|
||||
build_images() {
|
||||
log_info "Building Docker images..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Export version for builds
|
||||
export VERSION=${VERSION:-1.0.0}
|
||||
|
||||
# Build all images
|
||||
docker-compose -f docker-compose.prod.yml build --no-cache
|
||||
|
||||
log_success "Docker images built successfully"
|
||||
}
|
||||
|
||||
zero_downtime_deploy() {
|
||||
log_info "Starting zero-downtime deployment..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Scale up new instances
|
||||
log_info "Scaling up backend instances..."
|
||||
docker-compose -f docker-compose.prod.yml up -d --no-deps --scale backend=3 backend
|
||||
|
||||
# Wait for health checks
|
||||
log_info "Waiting for health checks (30s)..."
|
||||
sleep 30
|
||||
|
||||
# Check health
|
||||
if ! check_service_health "backend"; then
|
||||
log_error "Backend health check failed after scaling"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Scale down to normal
|
||||
log_info "Scaling down to normal capacity..."
|
||||
docker-compose -f docker-compose.prod.yml up -d --no-deps --scale backend=2 backend
|
||||
|
||||
log_success "Zero-downtime deployment completed"
|
||||
}
|
||||
|
||||
deploy_services() {
|
||||
log_info "Deploying services..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Pull latest images if using registry
|
||||
if [[ "${PULL_IMAGES:-false}" == "true" ]]; then
|
||||
log_info "Pulling latest images from registry..."
|
||||
docker-compose -f docker-compose.prod.yml pull
|
||||
fi
|
||||
|
||||
# Deploy all services
|
||||
docker-compose -f docker-compose.prod.yml up -d --remove-orphans
|
||||
|
||||
log_success "Services deployed successfully"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# HEALTH CHECKS
|
||||
# ========================================
|
||||
|
||||
check_service_health() {
|
||||
local service=$1
|
||||
local max_attempts=${2:-10}
|
||||
local attempt=1
|
||||
|
||||
log_info "Checking health for service: $service"
|
||||
|
||||
while [[ $attempt -le $max_attempts ]]; do
|
||||
if docker-compose -f docker-compose.prod.yml ps "$service" | grep -q "healthy"; then
|
||||
log_success "$service is healthy"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Health check attempt $attempt/$max_attempts..."
|
||||
sleep 5
|
||||
((attempt++))
|
||||
done
|
||||
|
||||
log_error "$service failed health check after $max_attempts attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
run_health_checks() {
|
||||
log_info "Running comprehensive health checks..."
|
||||
|
||||
local services=("postgres" "redis" "backend" "frontend" "nginx")
|
||||
local failed_services=()
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
if ! check_service_health "$service"; then
|
||||
failed_services+=("$service")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#failed_services[@]} -gt 0 ]]; then
|
||||
log_error "Health checks failed for services:"
|
||||
printf '%s\n' "${failed_services[@]}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check main health endpoint
|
||||
local health_url="http://localhost/health"
|
||||
if curl -sf "$health_url" &> /dev/null; then
|
||||
log_success "Main health endpoint is responding"
|
||||
else
|
||||
log_warning "Main health endpoint not responding (might need SSL)"
|
||||
fi
|
||||
|
||||
log_success "All health checks passed"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# ROLLBACK
|
||||
# ========================================
|
||||
|
||||
rollback_deployment() {
|
||||
log_warning "Initiating rollback..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Get last successful version (if available)
|
||||
local last_version=${LAST_VERSION:-"latest"}
|
||||
|
||||
# Revert to previous images
|
||||
export VERSION="$last_version"
|
||||
docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
log_warning "Rollback completed"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# CLEANUP
|
||||
# ========================================
|
||||
|
||||
cleanup() {
|
||||
log_info "Running cleanup..."
|
||||
|
||||
# Remove old images
|
||||
docker image prune -af --filter "until=24h" || true
|
||||
|
||||
# Remove unused volumes
|
||||
docker volume prune -f || true
|
||||
|
||||
# Clean old logs
|
||||
find "$LOG_DIR" -name "*.log" -type f -mtime +7 -delete 2>/dev/null || true
|
||||
|
||||
log_success "Cleanup completed"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# MAIN
|
||||
# ========================================
|
||||
|
||||
main() {
|
||||
log_info "🚀 Starting Math Platform Production Deployment"
|
||||
log_info "Timestamp: $(date)"
|
||||
log_info "Version: ${VERSION:-1.0.0}"
|
||||
|
||||
# Pre-deployment
|
||||
check_prerequisites
|
||||
check_environment
|
||||
|
||||
# Backup
|
||||
create_backup
|
||||
|
||||
# Database
|
||||
run_migrations
|
||||
|
||||
# Build and deploy
|
||||
build_images
|
||||
deploy_services
|
||||
|
||||
# Zero-downtime for backend
|
||||
zero_downtime_deploy
|
||||
|
||||
# Verification
|
||||
run_health_checks
|
||||
|
||||
# Cleanup
|
||||
cleanup
|
||||
|
||||
log_success "✅ Deployment completed successfully!"
|
||||
log_info "Services are running at:"
|
||||
log_info " - Frontend: https://localhost"
|
||||
log_info " - API: https://localhost/api"
|
||||
log_info " - Grafana: http://localhost:3001 (if monitoring enabled)"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
case "${1:-deploy}" in
|
||||
"backup")
|
||||
create_backup
|
||||
;;
|
||||
"migrate")
|
||||
check_environment
|
||||
run_migrations
|
||||
;;
|
||||
"rollback")
|
||||
rollback_deployment
|
||||
;;
|
||||
"health")
|
||||
run_health_checks
|
||||
;;
|
||||
"deploy"|*)
|
||||
main
|
||||
;;
|
||||
esac
|
||||
172
scripts/health-check.sh
Executable file
172
scripts/health-check.sh
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# ================================================
|
||||
# Math Platform - Health Check Script
|
||||
# ================================================
|
||||
|
||||
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
|
||||
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
echo -e "${BLUE}Math Platform - Health Check${NC}"
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
|
||||
# Function to check service health
|
||||
check_service() {
|
||||
local service_name=$1
|
||||
local url=$2
|
||||
local expected_code=${3:-200}
|
||||
|
||||
echo -n "Checking $service_name... "
|
||||
|
||||
local response=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000")
|
||||
|
||||
if [ "$response" = "$expected_code" ]; then
|
||||
echo -e "${GREEN}OK${NC} (HTTP $response)"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}FAILED${NC} (HTTP $response, expected $expected_code)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check Docker container
|
||||
check_container() {
|
||||
local container_name=$1
|
||||
|
||||
echo -n "Checking container $container_name... "
|
||||
|
||||
if docker ps | grep -q "$container_name"; then
|
||||
local status=$(docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null || echo "no-health-check")
|
||||
|
||||
if [ "$status" = "healthy" ] || [ "$status" = "no-health-check" ]; then
|
||||
echo -e "${GREEN}RUNNING${NC} ($status)"
|
||||
return 0
|
||||
else
|
||||
echo -e "${YELLOW}UNHEALTHY${NC} ($status)"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}NOT RUNNING${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check disk space
|
||||
check_disk_space() {
|
||||
echo -n "Checking disk space... "
|
||||
|
||||
local usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
|
||||
if [ "$usage" -lt 80 ]; then
|
||||
echo -e "${GREEN}OK${NC} (${usage}% used)"
|
||||
return 0
|
||||
elif [ "$usage" -lt 90 ]; then
|
||||
echo -e "${YELLOW}WARNING${NC} (${usage}% used)"
|
||||
return 1
|
||||
else
|
||||
echo -e "${RED}CRITICAL${NC} (${usage}% used)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check memory usage
|
||||
check_memory() {
|
||||
echo -n "Checking memory usage... "
|
||||
|
||||
local mem_usage=$(free | awk 'NR==2{printf "%.0f", $3*100/$2 }')
|
||||
|
||||
if [ "$mem_usage" -lt 80 ]; then
|
||||
echo -e "${GREEN}OK${NC} (${mem_usage}% used)"
|
||||
return 0
|
||||
elif [ "$mem_usage" -lt 90 ]; then
|
||||
echo -e "${YELLOW}WARNING${NC} (${mem_usage}% used)"
|
||||
return 1
|
||||
else
|
||||
echo -e "${RED}CRITICAL${NC} (${mem_usage}% used)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check Docker resources
|
||||
check_docker_resources() {
|
||||
echo -n "Checking Docker resources... "
|
||||
|
||||
local available=$(docker info 2>/dev/null | grep "CPUs" | head -1 | awk '{print $2}')
|
||||
|
||||
if [ -n "$available" ]; then
|
||||
echo -e "${GREEN}OK${NC} ($available CPUs available)"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}FAILED${NC} (Docker not available)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main health check
|
||||
main() {
|
||||
local failed=0
|
||||
|
||||
echo -e "\n${BLUE}Container Status${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
check_container "math-postgres" || failed=$((failed + 1))
|
||||
check_container "math-redis" || failed=$((failed + 1))
|
||||
check_container "math-backend" || failed=$((failed + 1))
|
||||
check_container "math-frontend" || failed=$((failed + 1))
|
||||
check_container "math-nginx" || failed=$((failed + 1))
|
||||
|
||||
echo -e "\n${BLUE}Service Health${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
check_service "Backend API" "http://localhost:3001/health" "200" || failed=$((failed + 1))
|
||||
check_service "Frontend" "http://localhost:3000" "200" || failed=$((failed + 1))
|
||||
check_service "Nginx" "http://localhost/" "200" || failed=$((failed + 1))
|
||||
|
||||
echo -e "\n${BLUE}System Resources${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
check_disk_space || failed=$((failed + 1))
|
||||
check_memory || failed=$((failed + 1))
|
||||
check_docker_resources || failed=$((failed + 1))
|
||||
|
||||
echo -e "\n${BLUE}Database Connection${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
echo -n "Checking PostgreSQL connection... "
|
||||
if docker exec math-postgres pg_isready -U mathuser -d mathdb &>/dev/null; then
|
||||
echo -e "${GREEN}OK${NC}"
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
echo -n "Checking Redis connection... "
|
||||
if docker exec math-redis redis-cli -a "${REDIS_PASSWORD:-redis_secure_password_2024}" ping &>/dev/null; then
|
||||
echo -e "${GREEN}OK${NC}"
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo -e "\n${BLUE}============================================${NC}"
|
||||
echo -e "${BLUE}Summary${NC}"
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
|
||||
if [ $failed -eq 0 ]; then
|
||||
echo -e "${GREEN}All checks passed!${NC}\n"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}$failed check(s) failed!${NC}\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main
|
||||
113
scripts/monitor.sh
Executable file
113
scripts/monitor.sh
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
# ================================================
|
||||
# Math Platform - Monitoring Script
|
||||
# ================================================
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
clear
|
||||
|
||||
while true; do
|
||||
clear
|
||||
echo -e "${CYAN}╔═══════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Math Platform - Real-time Monitor ║${NC}"
|
||||
echo -e "${CYAN}║ $(date '+%Y-%m-%d %H:%M:%S') ║${NC}"
|
||||
echo -e "${CYAN}╚═══════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
# System Resources
|
||||
echo -e "\n${BLUE}System Resources${NC}"
|
||||
echo "----------------------------------------"
|
||||
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
|
||||
MEM_USAGE=$(free | awk 'NR==2{printf "%.1f%%", $3*100/$2}')
|
||||
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}')
|
||||
|
||||
echo -e "CPU: ${CPU_USAGE}%"
|
||||
echo -e "Memory: ${MEM_USAGE}"
|
||||
echo -e "Disk: ${DISK_USAGE}"
|
||||
|
||||
# Docker Containers
|
||||
echo -e "\n${BLUE}Container Status${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
containers=("math-postgres" "math-redis" "math-backend" "math-frontend" "math-nginx" "math-pdf-worker" "math-exercise-worker" "math-notification-worker")
|
||||
|
||||
for container in "${containers[@]}"; do
|
||||
if docker ps | grep -q "$container"; then
|
||||
status=$(docker inspect --format='{{.State.Status}}' "$container" 2>/dev/null)
|
||||
health=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "no-check")
|
||||
|
||||
if [ "$health" = "healthy" ] || [ "$health" = "no-check" ]; then
|
||||
echo -e "${GREEN}✓${NC} $container (${status})"
|
||||
else
|
||||
echo -e "${YELLOW}⚠${NC} $container (${health})"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗${NC} $container (not running)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Resource Usage per Container
|
||||
echo -e "\n${BLUE}Container Resource Usage${NC}"
|
||||
echo "----------------------------------------"
|
||||
echo -e "Container\tCPU\tMemory\tNet I/O"
|
||||
echo -e "---------\t---\t------\t-------"
|
||||
|
||||
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" 2>/dev/null | grep math- | head -7
|
||||
|
||||
# Service Health
|
||||
echo -e "\n${BLUE}Service Health${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Backend
|
||||
if curl -s http://localhost:3001/health > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC} Backend API (http://localhost:3001)"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Backend API (http://localhost:3001)"
|
||||
fi
|
||||
|
||||
# Frontend
|
||||
if curl -s http://localhost:3000 > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC} Frontend (http://localhost:3000)"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Frontend (http://localhost:3000)"
|
||||
fi
|
||||
|
||||
# Nginx
|
||||
if curl -s http://localhost:80 > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC} Nginx (http://localhost:80)"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Nginx (http://localhost:80)"
|
||||
fi
|
||||
|
||||
# Recent Logs (last 5 lines)
|
||||
echo -e "\n${BLUE}Recent Backend Logs${NC}"
|
||||
echo "----------------------------------------"
|
||||
docker logs --tail=5 math-backend 2>&1 | grep -v "^$" || echo "No logs available"
|
||||
|
||||
# Database Stats
|
||||
echo -e "\n${BLUE}Database Stats${NC}"
|
||||
echo "----------------------------------------"
|
||||
DB_SIZE=$(docker exec math-postgres psql -U mathuser -d mathdb -t -c "SELECT pg_size_pretty(pg_database_size('mathdb'));" 2>/dev/null | xargs || echo "N/A")
|
||||
DB_CONNS=$(docker exec math-postgres psql -U mathuser -d mathdb -t -c "SELECT count(*) FROM pg_stat_activity;" 2>/dev/null | xargs || echo "N/A")
|
||||
echo -e "Database Size: ${DB_SIZE}"
|
||||
echo -e "Active Connections: ${DB_CONNS}"
|
||||
|
||||
# Queue Stats
|
||||
echo -e "\n${BLUE}Queue Stats (Redis)${NC}"
|
||||
echo "----------------------------------------"
|
||||
QUEUE_INFO=$(docker exec math-redis redis-cli -a "${REDIS_PASSWORD:-redis_secure_password_2024}" INFO stats 2>/dev/null | grep -E "total_connections_received|total_commands_processed" | cut -d: -f2 | xargs || echo "N/A")
|
||||
echo -e "Connections: $(echo "$QUEUE_INFO" | head -1)"
|
||||
echo -e "Commands: $(echo "$QUEUE_INFO" | tail -1)"
|
||||
|
||||
# Instructions
|
||||
echo -e "\n${YELLOW}Press Ctrl+C to exit${NC}"
|
||||
echo -e "${YELLOW}Refreshing in 5 seconds...${NC}"
|
||||
|
||||
sleep 5
|
||||
done
|
||||
106
scripts/setup-secrets.sh
Executable file
106
scripts/setup-secrets.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# ==================================================
|
||||
# SECRETS SETUP SCRIPT
|
||||
# Script para configurar secrets localmente de forma segura
|
||||
# ==================================================
|
||||
|
||||
set -e
|
||||
|
||||
echo "=================================================="
|
||||
echo " Configuración de Secrets - Math Platform"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
|
||||
# Colores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Crear directorio de secrets
|
||||
SECRETS_DIR="./secrets"
|
||||
mkdir -p "$SECRETS_DIR"
|
||||
|
||||
echo -e "${YELLOW}Este script creará archivos de secrets en $SECRETS_DIR/${NC}"
|
||||
echo -e "${YELLOW}Estos archivos están en .gitignore y NO deben commitearse${NC}"
|
||||
echo ""
|
||||
|
||||
# Función para solicitar secret
|
||||
request_secret() {
|
||||
local name=$1
|
||||
local description=$2
|
||||
local file="$SECRETS_DIR/$name.txt"
|
||||
|
||||
echo "--------------------------------------------------"
|
||||
echo -e "${GREEN}$description${NC}"
|
||||
|
||||
if [ -f "$file" ]; then
|
||||
echo -e "${YELLOW}⚠️ Ya existe: $file${NC}"
|
||||
read -p "¿Desea sobrescribir? (s/N): " overwrite
|
||||
if [[ ! "$overwrite" =~ ^[Ss]$ ]]; then
|
||||
echo " → Saltando..."
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
read -s -p "Ingrese el valor (presione Enter para omitir): " value
|
||||
echo ""
|
||||
|
||||
if [ -n "$value" ]; then
|
||||
echo "$value" > "$file"
|
||||
chmod 600 "$file"
|
||||
echo -e "${GREEN} ✓ Creado: $file${NC}"
|
||||
else
|
||||
echo -e "${YELLOW} → Omitido${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Solicitar cada secret
|
||||
request_secret "db_password" "1. Contraseña de la Base de Datos PostgreSQL"
|
||||
request_secret "redis_password" "2. Contraseña de Redis"
|
||||
request_secret "jwt_secret" "3. JWT Secret (mínimo 32 caracteres recomendado)"
|
||||
request_secret "session_secret" "4. Session Secret"
|
||||
request_secret "ai_api_key" "5. AI API Key (DashScope/Aliyun)"
|
||||
request_secret "telegram_token" "6. Telegram Bot Token"
|
||||
request_secret "telegram_chat_id" "7. Telegram Admin Chat ID"
|
||||
request_secret "monitor_db_password" "8. Contraseña del usuario de monitoreo"
|
||||
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
echo -e "${GREEN}Configuración completada${NC}"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
|
||||
# Verificar permisos
|
||||
echo "Verificando permisos de seguridad..."
|
||||
chmod 600 "$SECRETS_DIR"/*.txt 2>/dev/null || true
|
||||
echo -e "${GREEN}✓ Permisos establecidos: 600 (solo lectura/escritura owner)${NC}"
|
||||
echo ""
|
||||
|
||||
# Listar secrets creados
|
||||
echo "Secrets configurados:"
|
||||
ls -la "$SECRETS_DIR/"
|
||||
echo ""
|
||||
|
||||
echo "=================================================="
|
||||
echo " INSTRUCCIONES DE USO"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
echo "1. Para desarrollo local con secrets:"
|
||||
echo " docker-compose -f docker-compose.secrets.yml up -d"
|
||||
echo ""
|
||||
echo "2. Para producción con Docker Swarm:"
|
||||
echo " docker secret create db_password secrets/db_password.txt"
|
||||
echo " docker stack deploy -c docker-compose.secrets.yml math-platform"
|
||||
echo ""
|
||||
echo "3. Para rotar credenciales:"
|
||||
echo " - Generar nuevos valores"
|
||||
echo " - Actualizar archivos en secrets/"
|
||||
echo " - Reiniciar servicios: docker-compose -f docker-compose.secrets.yml restart"
|
||||
echo ""
|
||||
echo -e "${RED}⚠️ IMPORTANTE:${NC}"
|
||||
echo -e "${RED} - NUNCA commitear archivos de secrets${NC}"
|
||||
echo -e "${RED} - Hacer backup de secrets en un lugar seguro${NC}"
|
||||
echo -e "${RED} - Rotar credenciales expuestas inmediatamente${NC}"
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
212
scripts/start-production.sh
Executable file
212
scripts/start-production.sh
Executable file
@@ -0,0 +1,212 @@
|
||||
#!/bin/bash
|
||||
# Script para iniciar el stack completo en modo producción
|
||||
# Math2 Platform - Production-Grade Deployment
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
COMPOSE_FILE="docker-compose.prod.yml"
|
||||
BACKEND_DIR="backend"
|
||||
HEALTH_TIMEOUT=60
|
||||
|
||||
echo -e "${BLUE}🚀 Iniciando Math2 Platform en modo producción...${NC}"
|
||||
echo "================================================"
|
||||
|
||||
# 1. Verificar que existe el archivo docker-compose.prod.yml
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
echo -e "${RED}❌ No se encuentra $COMPOSE_FILE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Verificar variables de entorno críticas
|
||||
echo -e "${BLUE}🔍 Verificando variables de entorno...${NC}"
|
||||
|
||||
REQUIRED_VARS=(
|
||||
"DATABASE_URL"
|
||||
"DB_PASSWORD"
|
||||
"REDIS_PASSWORD"
|
||||
"JWT_SECRET"
|
||||
)
|
||||
|
||||
MISSING_VARS=()
|
||||
for var in "${REQUIRED_VARS[@]}"; do
|
||||
if [ -z "${!var}" ]; then
|
||||
MISSING_VARS+=($var)
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#MISSING_VARS[@]} -ne 0 ]; then
|
||||
echo -e "${RED}❌ Variables de entorno faltantes:${NC}"
|
||||
for var in "${MISSING_VARS[@]}"; do
|
||||
echo " - $var"
|
||||
done
|
||||
echo ""
|
||||
echo -e "${YELLOW}ℹ️ Copia .env.example a .env y configura los valores${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Variables de entorno verificadas${NC}"
|
||||
|
||||
# 3. Verificar que TypeScript compila
|
||||
echo -e "${BLUE}🔍 Verificando compilación TypeScript...${NC}"
|
||||
cd $BACKEND_DIR
|
||||
|
||||
if ! npm run type-check > /tmp/type-check.log 2>&1; then
|
||||
echo -e "${RED}❌ TypeScript tiene errores:${NC}"
|
||||
cat /tmp/type-check.log
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ Corrige los errores antes de continuar${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ TypeScript compila correctamente${NC}"
|
||||
|
||||
# 4. Generar Prisma Client
|
||||
echo -e "${BLUE}📦 Generando Prisma Client...${NC}"
|
||||
npx prisma generate --generator client > /tmp/prisma-generate.log 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Error generando Prisma Client${NC}"
|
||||
cat /tmp/prisma-generate.log
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Prisma Client generado${NC}"
|
||||
|
||||
# 5. Construir imágenes Docker
|
||||
echo -e "${BLUE}🐳 Construyendo imágenes Docker...${NC}"
|
||||
cd ..
|
||||
|
||||
export VERSION=${VERSION:-1.0.0}
|
||||
docker-compose -f $COMPOSE_FILE build --parallel > /tmp/docker-build.log 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Error construyendo imágenes Docker${NC}"
|
||||
tail -50 /tmp/docker-build.log
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Imágenes Docker construidas (versión: $VERSION)${NC}"
|
||||
|
||||
# 6. Verificar volúmenes
|
||||
echo -e "${BLUE}💾 Verificando volúmenes...${NC}"
|
||||
docker volume ls | grep -q "postgres_data\|redis_data" || echo -e "${YELLOW}⚠️ Creando volúmenes por primera vez${NC}"
|
||||
|
||||
# 7. Iniciar servicios (con DB primero)
|
||||
echo -e "${BLUE}🚀 Iniciando servicios (PostgreSQL y Redis primero)...${NC}"
|
||||
docker-compose -f $COMPOSE_FILE up -d postgres redis
|
||||
|
||||
# Esperar a que DB esté lista
|
||||
echo -e "${BLUE}⏳ Esperando a que PostgreSQL esté listo...${NC}"
|
||||
for i in $(seq 1 30); do
|
||||
if docker-compose -f $COMPOSE_FILE exec -T postgres pg_isready -U ${DB_USER:-mathuser} -d ${DB_NAME:-mathdb} > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ PostgreSQL listo${NC}"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo -e "${RED}❌ Timeout esperando PostgreSQL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 8. Aplicar migraciones
|
||||
echo -e "${BLUE}🔄 Aplicando migraciones de base de datos...${NC}"
|
||||
cd $BACKEND_DIR
|
||||
export DATABASE_URL="postgresql://${DB_USER:-mathuser}:${DB_PASSWORD}@localhost:5432/${DB_NAME:-mathdb}"
|
||||
npx prisma migrate deploy > /tmp/migrate.log 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ Error aplicando migraciones${NC}"
|
||||
cat /tmp/migrate.log
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Migraciones aplicadas${NC}"
|
||||
|
||||
# 9. Seed si es necesario (solo si la tabla User está vacía)
|
||||
echo -e "${BLUE}🌱 Verificando si se necesita seed...${NC}"
|
||||
SEED_COUNT=$(npx prisma db execute --stdin <<EOF 2>/dev/null | head -1
|
||||
SELECT COUNT(*) FROM "User";
|
||||
EOF
|
||||
)
|
||||
if [ "$SEED_COUNT" = "0" ] || [ -z "$SEED_COUNT" ]; then
|
||||
echo -e "${BLUE}🌱 Ejecutando seed de base de datos...${NC}"
|
||||
npx prisma db seed > /tmp/seed.log 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${YELLOW}⚠️ Seed no completado (puede ser normal en primer despliegue)${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✅ Seed completado${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}✅ Datos existentes encontrados, omitiendo seed${NC}"
|
||||
fi
|
||||
|
||||
cd ..
|
||||
|
||||
# 10. Iniciar todos los servicios
|
||||
echo -e "${BLUE}🚀 Iniciando todos los servicios...${NC}"
|
||||
docker-compose -f $COMPOSE_FILE up -d
|
||||
|
||||
# 11. Health checks
|
||||
echo -e "${BLUE}⏳ Esperando servicios...${NC}"
|
||||
sleep 10
|
||||
|
||||
echo -e "${BLUE}🏥 Ejecutando health checks...${NC}"
|
||||
|
||||
# Backend health check
|
||||
echo -n " Backend: "
|
||||
for i in $(seq 1 $HEALTH_TIMEOUT); do
|
||||
if curl -sf http://localhost:3001/health > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq $HEALTH_TIMEOUT ]; then
|
||||
echo -e "${RED}❌ FAIL (timeout)${NC}"
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Frontend/Nginx health check
|
||||
echo -n " Frontend: "
|
||||
for i in $(seq 1 $HEALTH_TIMEOUT); do
|
||||
if curl -sf http://localhost > /dev/null 2>&1 || curl -sf http://localhost:80 > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ OK${NC}"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq $HEALTH_TIMEOUT ]; then
|
||||
echo -e "${RED}❌ FAIL (timeout)${NC}"
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Verificar workers (opcional, no crítico)
|
||||
echo -n " Workers: "
|
||||
WORKER_COUNT=$(docker-compose -f $COMPOSE_FILE ps -q pdf-worker exercise-worker notification-worker 2>/dev/null | wc -l)
|
||||
if [ "$WORKER_COUNT" -ge 3 ]; then
|
||||
echo -e "${GREEN}✅ OK ($WORKER_COUNT workers)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Parcial ($WORKER_COUNT/3 workers)${NC}"
|
||||
fi
|
||||
|
||||
# 12. Mostrar resumen
|
||||
echo ""
|
||||
echo -e "${GREEN}================================================${NC}"
|
||||
echo -e "${GREEN}✅ Math2 Platform iniciada en modo producción${NC}"
|
||||
echo -e "${GREEN}================================================${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}📊 Accesos:${NC}"
|
||||
echo " • Dashboard: http://localhost"
|
||||
echo " • API: http://localhost:3001"
|
||||
echo " • Health Check: http://localhost:3001/health"
|
||||
echo ""
|
||||
echo -e "${BLUE}🔧 Comandos útiles:${NC}"
|
||||
echo " • Ver logs: docker-compose -f $COMPOSE_FILE logs -f"
|
||||
echo " • Detener: docker-compose -f $COMPOSE_FILE down"
|
||||
echo " • Status: docker-compose -f $COMPOSE_FILE ps"
|
||||
echo " • Verificar: ./scripts/verify-production.sh"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ IMPORTANTE: Este es un entorno local de producción${NC}"
|
||||
echo -e "${YELLOW} Para deployment real, configura SSL y dominio${NC}"
|
||||
echo ""
|
||||
195
scripts/system-check.sh
Executable file
195
scripts/system-check.sh
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/bin/bash
|
||||
# ================================================
|
||||
# Math Platform - Complete System Verification
|
||||
# ================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Math Platform - Complete System Verification ║${NC}"
|
||||
echo -e "${CYAN}║ $(date '+%Y-%m-%d %H:%M:%S') ║${NC}"
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
total_checks=0
|
||||
passed_checks=0
|
||||
failed_checks=0
|
||||
warned_checks=0
|
||||
|
||||
# Function to perform check
|
||||
check() {
|
||||
local description=$1
|
||||
local command=$2
|
||||
local severity=${3:-ERROR} # ERROR or WARN
|
||||
|
||||
total_checks=$((total_checks + 1))
|
||||
echo -n "[$total_checks] $description... "
|
||||
|
||||
if eval "$command" > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
passed_checks=$((passed_checks + 1))
|
||||
return 0
|
||||
else
|
||||
if [ "$severity" = "WARN" ]; then
|
||||
echo -e "${YELLOW}WARN${NC}"
|
||||
warned_checks=$((warned_checks + 1))
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
failed_checks=$((failed_checks + 1))
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Section 1: Docker Environment
|
||||
echo -e "\n${BLUE}═══ Docker Environment ═══${NC}"
|
||||
check "Docker daemon running" "docker info"
|
||||
check "Docker Compose available" "command -v docker-compose || docker compose version"
|
||||
|
||||
# Section 2: Configuration Files
|
||||
echo -e "\n${BLUE}═══ Configuration Files ═══${NC}"
|
||||
check "docker-compose.yml exists" "test -f $PROJECT_ROOT/docker-compose.yml"
|
||||
check ".env file exists" "test -f $PROJECT_ROOT/.env"
|
||||
check "Backend Dockerfile exists" "test -f $PROJECT_ROOT/docker/Dockerfile.backend"
|
||||
check "Frontend Dockerfile exists" "test -f $PROJECT_ROOT/docker/Dockerfile.frontend"
|
||||
check "Worker Dockerfile exists" "test -f $PROJECT_ROOT/docker/Dockerfile.worker"
|
||||
check "Nginx config exists" "test -f $PROJECT_ROOT/docker/nginx.conf"
|
||||
|
||||
# Section 3: Application Structure
|
||||
echo -e "\n${BLUE}═══ Application Structure ═══${NC}"
|
||||
check "Backend package.json exists" "test -f $PROJECT_ROOT/backend/package.json"
|
||||
check "Frontend package.json exists" "test -f $PROJECT_ROOT/frontend/package.json"
|
||||
check "Prisma schema exists" "test -f $PROJECT_ROOT/backend/prisma/schema.prisma"
|
||||
check "Next.js config exists" "test -f $PROJECT_ROOT/frontend/next.config.js"
|
||||
check "Backend src directory exists" "test -d $PROJECT_ROOT/backend/src"
|
||||
check "Frontend src directory exists" "test -d $PROJECT_ROOT/frontend/src"
|
||||
|
||||
# Section 4: Scripts
|
||||
echo -e "\n${BLUE}═══ Management Scripts ═══${NC}"
|
||||
check "start.sh is executable" "test -x $PROJECT_ROOT/docker/start.sh"
|
||||
check "stop.sh is executable" "test -x $PROJECT_ROOT/docker/stop.sh"
|
||||
check "backup.sh is executable" "test -x $PROJECT_ROOT/docker/backup.sh"
|
||||
check "test-e2e.sh is executable" "test -x $PROJECT_ROOT/scripts/test-e2e.sh"
|
||||
check "health-check.sh is executable" "test -x $PROJECT_ROOT/scripts/health-check.sh"
|
||||
check "validate-deployment.sh is executable" "test -x $PROJECT_ROOT/scripts/validate-deployment.sh"
|
||||
|
||||
# Section 5: Directories
|
||||
echo -e "\n${BLUE}═══ Required Directories ═══${NC}"
|
||||
check "docker/data directory exists" "test -d $PROJECT_ROOT/docker/data"
|
||||
check "docker/logs directory exists" "test -d $PROJECT_ROOT/docker/logs"
|
||||
check "docker/init-scripts directory exists" "test -d $PROJECT_ROOT/docker/init-scripts"
|
||||
check "pdfs directory exists" "test -d $PROJECT_ROOT/pdfs"
|
||||
check "scripts directory exists" "test -d $PROJECT_ROOT/scripts"
|
||||
|
||||
# Section 6: Environment Variables (if services are running)
|
||||
echo -e "\n${BLUE}═══ Environment Variables ═══${NC}"
|
||||
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
source "$PROJECT_ROOT/.env"
|
||||
|
||||
check "DB_PASSWORD is set" "test -n '$DB_PASSWORD'" "WARN"
|
||||
check "REDIS_PASSWORD is set" "test -n '$REDIS_PASSWORD'" "WARN"
|
||||
check "JWT_SECRET is set" "test -n '$JWT_SECRET'" "WARN"
|
||||
check "AI_API_KEY is set" "test -n '$AI_API_KEY'" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}.env file not found, skipping variable checks${NC}"
|
||||
fi
|
||||
|
||||
# Section 7: Services (if running)
|
||||
echo -e "\n${BLUE}═══ Running Services ═══${NC}"
|
||||
|
||||
if docker info > /dev/null 2>&1; then
|
||||
check "PostgreSQL container running" "docker ps | grep -q math-postgres" "WARN"
|
||||
check "Redis container running" "docker ps | grep -q math-redis" "WARN"
|
||||
check "Backend container running" "docker ps | grep -q math-backend" "WARN"
|
||||
check "Frontend container running" "docker ps | grep -q math-frontend" "WARN"
|
||||
check "Nginx container running" "docker ps | grep -q math-nginx" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}Docker not running, skipping service checks${NC}"
|
||||
fi
|
||||
|
||||
# Section 8: Service Health (if running)
|
||||
echo -e "\n${BLUE}═══ Service Health Endpoints ═══${NC}"
|
||||
|
||||
if curl -s http://localhost:3001/health > /dev/null 2>&1; then
|
||||
check "Backend API health endpoint" "curl -s -f http://localhost:3001/health" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}Backend not accessible, skipping health checks${NC}"
|
||||
fi
|
||||
|
||||
if curl -s http://localhost:3000 > /dev/null 2>&1; then
|
||||
check "Frontend web server" "curl -s -f http://localhost:3000" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}Frontend not accessible, skipping health checks${NC}"
|
||||
fi
|
||||
|
||||
# Section 9: Port Availability (if services not running)
|
||||
echo -e "\n${BLUE}═══ Port Availability ═══${NC}"
|
||||
|
||||
if ! docker ps | grep -q math-postgres; then
|
||||
check "Port 5432 available" "! netstat -tuln 2>/dev/null | grep -q ':5432 ' || ! ss -tuln 2>/dev/null | grep -q ':5432 '" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}PostgreSQL running, skipping port check${NC}"
|
||||
fi
|
||||
|
||||
if ! docker ps | grep -q math-redis; then
|
||||
check "Port 6379 available" "! netstat -tuln 2>/dev/null | grep -q ':6379 ' || ! ss -tuln 2>/dev/null | grep -q ':6379 '" "WARN"
|
||||
else
|
||||
echo -e "${YELLOW}Redis running, skipping port check${NC}"
|
||||
fi
|
||||
|
||||
# Section 10: System Resources
|
||||
echo -e "\n${BLUE}═══ System Resources ═══${NC}"
|
||||
|
||||
DISK_USAGE=$(df -h "$PROJECT_ROOT" | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
if [ "$DISK_USAGE" -lt 80 ]; then
|
||||
check "Disk space OK (using ${DISK_USAGE}%)" "true"
|
||||
else
|
||||
check "Disk space low (using ${DISK_USAGE}%)" "false" "WARN"
|
||||
fi
|
||||
|
||||
MEM_USAGE=$(free | awk 'NR==2{printf "%.0f", $3*100/$2}')
|
||||
if [ "$MEM_USAGE" -lt 90 ]; then
|
||||
check "Memory OK (using ${MEM_USAGE}%)" "true"
|
||||
else
|
||||
check "Memory high (using ${MEM_USAGE}%)" "false" "WARN"
|
||||
fi
|
||||
|
||||
# Final Summary
|
||||
echo -e "\n${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║ Verification Summary ║${NC}"
|
||||
echo -e "${CYAN}╠════════════════════════════════════════════════════════════╣${NC}"
|
||||
printf "${CYAN}║ Total Checks: %-3d ║${NC}\n" $total_checks
|
||||
printf "${GREEN}║ Passed: %-3d ║${NC}\n" $passed_checks
|
||||
printf "${RED}║ Failed: %-3d ║${NC}\n" $failed_checks
|
||||
printf "${YELLOW}║ Warnings: %-3d ║${NC}\n" $warned_checks
|
||||
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
if [ $failed_checks -eq 0 ]; then
|
||||
echo -e "\n${GREEN}✓ All critical checks passed!${NC}\n"
|
||||
|
||||
if [ $warned_checks -gt 0 ]; then
|
||||
echo -e "${YELLOW}⚠ Some warnings detected. Review above for details.${NC}\n"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}Next steps:${NC}"
|
||||
echo -e " 1. Start services: ${CYAN}./docker/start.sh${NC}"
|
||||
echo -e " 2. Run health check: ${CYAN}./scripts/health-check.sh${NC}"
|
||||
echo -e " 3. Run E2E tests: ${CYAN}./scripts/test-e2e.sh${NC}"
|
||||
echo -e " 4. View documentation: ${CYAN}cat DEPLOY.md${NC}\n"
|
||||
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}✗ Some critical checks failed!${NC}"
|
||||
echo -e "${RED} Please resolve the issues above before proceeding.${NC}\n"
|
||||
exit 1
|
||||
fi
|
||||
436
scripts/test-e2e.sh
Executable file
436
scripts/test-e2e.sh
Executable file
@@ -0,0 +1,436 @@
|
||||
#!/bin/bash
|
||||
# ================================================
|
||||
# Math Platform - End-to-End Testing Script
|
||||
# ================================================
|
||||
|
||||
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
|
||||
|
||||
# Configuration
|
||||
API_BASE_URL="http://localhost:3001"
|
||||
FRONTEND_URL="http://localhost:3000"
|
||||
TEST_USER_EMAIL="test_$(date +%s)@example.com"
|
||||
TEST_USER_PASSWORD="Test123456!"
|
||||
TEST_USER_NAME="Test User"
|
||||
|
||||
# Test results
|
||||
TESTS_PASSED=0
|
||||
TESTS_FAILED=0
|
||||
TESTS_TOTAL=0
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "\n${BLUE}============================================${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}============================================${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${YELLOW}TEST: $1${NC}"
|
||||
TESTS_TOTAL=$((TESTS_TOTAL + 1))
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ PASSED: $1${NC}"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗ FAILED: $1${NC}"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
# Function to wait for service
|
||||
wait_for_service() {
|
||||
local url=$1
|
||||
local max_attempts=30
|
||||
local attempt=1
|
||||
|
||||
print_info "Waiting for $url..."
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if curl -s -f "$url" > /dev/null 2>&1; then
|
||||
print_success "Service is ready"
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
|
||||
print_error "Service not ready after $max_attempts attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to make API request
|
||||
api_request() {
|
||||
local method=$1
|
||||
local endpoint=$2
|
||||
local data=$3
|
||||
local token=$4
|
||||
|
||||
local url="${API_BASE_URL}${endpoint}"
|
||||
local headers="-H 'Content-Type: application/json'"
|
||||
|
||||
if [ -n "$token" ]; then
|
||||
headers="$headers -H 'Authorization: Bearer $token'"
|
||||
fi
|
||||
|
||||
if [ "$method" = "GET" ]; then
|
||||
curl -s -X GET "$url" $headers
|
||||
elif [ "$method" = "POST" ]; then
|
||||
curl -s -X POST "$url" $headers -d "$data"
|
||||
elif [ "$method" = "PUT" ]; then
|
||||
curl -s -X PUT "$url" $headers -d "$data"
|
||||
elif [ "$method" = "DELETE" ]; then
|
||||
curl -s -X DELETE "$url" $headers
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test user registration
|
||||
test_registration() {
|
||||
print_test "User Registration"
|
||||
|
||||
local response=$(api_request "POST" "/api/auth/register" "{\"email\":\"$TEST_USER_EMAIL\",\"password\":\"$TEST_USER_PASSWORD\",\"name\":\"$TEST_USER_NAME\"}")
|
||||
|
||||
if echo "$response" | grep -q "token"; then
|
||||
USER_TOKEN=$(echo "$response" | grep -o '"token":"[^"]*' | cut -d'"' -f4)
|
||||
USER_ID=$(echo "$response" | grep -o '"id":"[^"]*' | cut -d'"' -f4)
|
||||
print_success "User registered successfully"
|
||||
print_info "User ID: $USER_ID"
|
||||
print_info "Email: $TEST_USER_EMAIL"
|
||||
return 0
|
||||
else
|
||||
print_error "Registration failed"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test user login
|
||||
test_login() {
|
||||
print_test "User Login"
|
||||
|
||||
local response=$(api_request "POST" "/api/auth/login" "{\"email\":\"$TEST_USER_EMAIL\",\"password\":\"$TEST_USER_PASSWORD\"}")
|
||||
|
||||
if echo "$response" | grep -q "token"; then
|
||||
USER_TOKEN=$(echo "$response" | grep -o '"token":"[^"]*' | cut -d'"' -f4)
|
||||
print_success "User logged in successfully"
|
||||
return 0
|
||||
else
|
||||
print_error "Login failed"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test getting modules
|
||||
test_get_modules() {
|
||||
print_test "Get Learning Modules"
|
||||
|
||||
local response=$(api_request "GET" "/api/modules" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "modules"; then
|
||||
MODULE_COUNT=$(echo "$response" | grep -o '"id"' | wc -l)
|
||||
print_success "Retrieved $MODULE_COUNT modules"
|
||||
|
||||
# Get first module ID
|
||||
if [ $MODULE_COUNT -gt 0 ]; then
|
||||
MODULE_ID=$(echo "$response" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4)
|
||||
print_info "First Module ID: $MODULE_ID"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to retrieve modules"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test accessing a specific module
|
||||
test_access_module() {
|
||||
print_test "Access Module Content"
|
||||
|
||||
if [ -z "$MODULE_ID" ]; then
|
||||
print_error "No module ID available"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local response=$(api_request "GET" "/api/modules/$MODULE_ID" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "title"; then
|
||||
MODULE_TITLE=$(echo "$response" | grep -o '"title":"[^"]*' | cut -d'"' -f4)
|
||||
print_success "Accessed module: $MODULE_TITLE"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to access module"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test getting exercises
|
||||
test_get_exercises() {
|
||||
print_test "Get Exercises for Module"
|
||||
|
||||
if [ -z "$MODULE_ID" ]; then
|
||||
print_error "No module ID available"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local response=$(api_request "GET" "/api/exercises?moduleId=$MODULE_ID" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "exercises"; then
|
||||
EXERCISE_COUNT=$(echo "$response" | grep -o '"id"' | wc -l)
|
||||
print_success "Retrieved $EXERCISE_COUNT exercises"
|
||||
|
||||
# Get first exercise ID
|
||||
if [ $EXERCISE_COUNT -gt 0 ]; then
|
||||
EXERCISE_ID=$(echo "$response" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4)
|
||||
print_info "First Exercise ID: $EXERCISE_ID"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to retrieve exercises"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test submitting an exercise
|
||||
test_submit_exercise() {
|
||||
print_test "Submit Exercise Answer"
|
||||
|
||||
if [ -z "$EXERCISE_ID" ]; then
|
||||
print_error "No exercise ID available"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Submit a test answer
|
||||
local response=$(api_request "POST" "/api/exercises/$EXERCISE_ID/submit" "{\"answer\":\"42\",\"timeSpent\":60}" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "correct"; then
|
||||
print_success "Exercise submitted successfully"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to submit exercise"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test getting user progress
|
||||
test_get_progress() {
|
||||
print_test "Get User Progress"
|
||||
|
||||
local response=$(api_request "GET" "/api/users/progress" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "progress"; then
|
||||
print_success "Retrieved user progress"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to retrieve progress"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test getting ranking
|
||||
test_get_ranking() {
|
||||
print_test "Get User Ranking"
|
||||
|
||||
local response=$(api_request "GET" "/api/users/ranking?limit=10" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "ranking"; then
|
||||
print_success "Retrieved user ranking"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to retrieve ranking"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test getting achievements
|
||||
test_get_achievements() {
|
||||
print_test "Get User Achievements"
|
||||
|
||||
local response=$(api_request "GET" "/api/users/achievements" "" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "achievements"; then
|
||||
ACHIEVEMENT_COUNT=$(echo "$response" | grep -o '"id"' | wc -l)
|
||||
print_success "Retrieved $ACHIEVEMENT_COUNT achievements"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to retrieve achievements"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test updating user profile
|
||||
test_update_profile() {
|
||||
print_test "Update User Profile"
|
||||
|
||||
local new_name="Updated Test User"
|
||||
local response=$(api_request "PUT" "/api/users/profile" "{\"name\":\"$new_name\"}" "$USER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "name"; then
|
||||
print_success "Profile updated successfully"
|
||||
return 0
|
||||
else
|
||||
print_error "Failed to update profile"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test health endpoint
|
||||
test_health() {
|
||||
print_test "Health Check Endpoint"
|
||||
|
||||
local response=$(curl -s "$API_BASE_URL/health")
|
||||
|
||||
if echo "$response" | grep -q "status.*ok\|healthy"; then
|
||||
print_success "Health check passed"
|
||||
return 0
|
||||
else
|
||||
print_error "Health check failed"
|
||||
print_info "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test frontend accessibility
|
||||
test_frontend() {
|
||||
print_test "Frontend Accessibility"
|
||||
|
||||
local response=$(curl -s -o /dev/null -w "%{http_code}" "$FRONTEND_URL")
|
||||
|
||||
if [ "$response" = "200" ]; then
|
||||
print_success "Frontend is accessible"
|
||||
return 0
|
||||
else
|
||||
print_error "Frontend returned status code: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run all tests
|
||||
run_all_tests() {
|
||||
print_header "Math Platform E2E Test Suite"
|
||||
|
||||
# Check if services are running
|
||||
print_info "Checking service availability..."
|
||||
if ! wait_for_service "$API_BASE_URL/health"; then
|
||||
print_error "Backend service is not available. Please start the services first."
|
||||
print_info "Run: ./docker/start.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! wait_for_service "$FRONTEND_URL"; then
|
||||
print_error "Frontend service is not available. Please start the services first."
|
||||
print_info "Run: ./docker/start.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}All services are running! Starting tests...${NC}\n"
|
||||
|
||||
# Run tests
|
||||
test_health
|
||||
test_frontend
|
||||
test_registration
|
||||
test_login
|
||||
test_get_modules
|
||||
test_access_module
|
||||
test_get_exercises
|
||||
test_submit_exercise
|
||||
test_get_progress
|
||||
test_get_ranking
|
||||
test_get_achievements
|
||||
test_update_profile
|
||||
|
||||
# Print summary
|
||||
print_header "Test Summary"
|
||||
echo -e "Total Tests: $TESTS_TOTAL"
|
||||
echo -e "${GREEN}Passed: $TESTS_PASSED${NC}"
|
||||
echo -e "${RED}Failed: $TESTS_FAILED${NC}"
|
||||
|
||||
if [ $TESTS_FAILED -eq 0 ]; then
|
||||
echo -e "\n${GREEN}All tests passed!${NC}\n"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some tests failed!${NC}\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run specific test
|
||||
run_specific_test() {
|
||||
local test_name=$1
|
||||
|
||||
case $test_name in
|
||||
"health")
|
||||
test_health
|
||||
;;
|
||||
"frontend")
|
||||
test_frontend
|
||||
;;
|
||||
"register")
|
||||
test_registration
|
||||
;;
|
||||
"login")
|
||||
test_login
|
||||
;;
|
||||
"modules")
|
||||
test_get_modules
|
||||
;;
|
||||
"module")
|
||||
test_access_module
|
||||
;;
|
||||
"exercises")
|
||||
test_get_exercises
|
||||
;;
|
||||
"submit")
|
||||
test_submit_exercise
|
||||
;;
|
||||
"progress")
|
||||
test_get_progress
|
||||
;;
|
||||
"ranking")
|
||||
test_get_ranking
|
||||
;;
|
||||
"achievements")
|
||||
test_get_achievements
|
||||
;;
|
||||
"profile")
|
||||
test_update_profile
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown test: $test_name"
|
||||
echo "Available tests: health, frontend, register, login, modules, module, exercises, submit, progress, ranking, achievements, profile"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
if [ $# -eq 0 ]; then
|
||||
run_all_tests
|
||||
else
|
||||
run_specific_test "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
249
scripts/validate-deployment.sh
Executable file
249
scripts/validate-deployment.sh
Executable file
@@ -0,0 +1,249 @@
|
||||
#!/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
|
||||
187
scripts/verify-production.sh
Executable file
187
scripts/verify-production.sh
Executable file
@@ -0,0 +1,187 @@
|
||||
#!/bin/bash
|
||||
# Verificar que el stack de producción está funcionando correctamente
|
||||
# Math2 Platform - Production Verification
|
||||
|
||||
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
|
||||
|
||||
COMPOSE_FILE="docker-compose.prod.yml"
|
||||
VERIFICATION_LOG="/tmp/verify-production-$(date +%Y%m%d-%H%M%S).log"
|
||||
|
||||
echo -e "${BLUE}🔍 Verificando estado de producción...${NC}"
|
||||
echo "================================================" | tee -a $VERIFICATION_LOG
|
||||
date | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Función para verificar estado de contenedores
|
||||
check_containers() {
|
||||
echo -e "${BLUE}📦 Estado de contenedores:${NC}" | tee -a $VERIFICATION_LOG
|
||||
docker-compose -f $COMPOSE_FILE ps 2>&1 | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
}
|
||||
|
||||
# Función para verificar health de cada servicio
|
||||
check_service_health() {
|
||||
local service=$1
|
||||
local port=$2
|
||||
local endpoint=$3
|
||||
|
||||
echo -n " $service: " | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Verificar si el contenedor está corriendo
|
||||
if ! docker-compose -f $COMPOSE_FILE ps | grep -q "$service.*Up"; then
|
||||
echo -e "${RED}❌ CONTAINER DOWN${NC}" | tee -a $VERIFICATION_LOG
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verificar health endpoint si aplica
|
||||
if [ -n "$endpoint" ]; then
|
||||
if curl -sf http://localhost:$port$endpoint > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ HEALTHY${NC}" | tee -a $VERIFICATION_LOG
|
||||
return 0
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ RUNNING (No health endpoint)${NC}" | tee -a $VERIFICATION_LOG
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}✅ RUNNING${NC}" | tee -a $VERIFICATION_LOG
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Verificar estado de servicios
|
||||
echo -e "${BLUE}🏥 Health Checks de Servicios:${NC}" | tee -a $VERIFICATION_LOG
|
||||
SERVICES=(
|
||||
"postgres:5432:"
|
||||
"redis:6379:"
|
||||
"backend:3001:/health"
|
||||
"frontend:3000:"
|
||||
"nginx:80:"
|
||||
"pdf-worker:3002:/health"
|
||||
"exercise-worker:3003:/health"
|
||||
"notification-worker:3004:/health"
|
||||
)
|
||||
|
||||
FAILED_SERVICES=0
|
||||
for service_info in "${SERVICES[@]}"; do
|
||||
IFS=':' read -r service port endpoint <<< "$service_info"
|
||||
if ! check_service_health "$service" "$port" "$endpoint"; then
|
||||
((FAILED_SERVICES++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Verificar logs recientes (solo errores)
|
||||
echo -e "${BLUE}📋 Logs recientes (últimos errores):${NC}" | tee -a $VERIFICATION_LOG
|
||||
for service in backend frontend pdf-worker exercise-worker notification-worker; do
|
||||
echo -e "${YELLOW} [$service] Errores:${NC}" | tee -a $VERIFICATION_LOG
|
||||
docker-compose -f $COMPOSE_FILE logs --tail=20 $service 2>&1 | grep -E "(ERROR|FATAL|Exception|Traceback)" | head -5 | tee -a $VERIFICATION_LOG || echo " No hay errores recientes" | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
done
|
||||
|
||||
# Verificar recursos
|
||||
echo -e "${BLUE}💾 Uso de recursos:${NC}" | tee -a $VERIFICATION_LOG
|
||||
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" 2>/dev/null | grep -E "(math-|postgres|redis)" | tee -a $VERIFICATION_LOG || echo " No se pueden obtener estadísticas" | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Verificar base de datos
|
||||
echo -e "${BLUE}🗄️ Estado de Base de Datos:${NC}" | tee -a $VERIFICATION_LOG
|
||||
cd backend
|
||||
|
||||
# Verificar conexión a PostgreSQL
|
||||
if npx prisma db execute --stdin <<EOF 2>/dev/null | tee -a $VERIFICATION_LOG
|
||||
SELECT current_database(), current_user, version();
|
||||
EOF
|
||||
then
|
||||
echo -e "${GREEN}✅ Conexión a PostgreSQL OK${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${RED}❌ Error conectando a PostgreSQL${NC}" | tee -a $VERIFICATION_LOG
|
||||
((FAILED_SERVICES++))
|
||||
fi
|
||||
|
||||
# Verificar estado de migraciones
|
||||
echo -e "${BLUE}🔄 Estado de migraciones:${NC}" | tee -a $VERIFICATION_LOG
|
||||
if npx prisma migrate status 2>&1 | tee -a $VERIFICATION_LOG | grep -q "Database schema is up to date"; then
|
||||
echo -e "${GREEN}✅ Migraciones al día${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Verificar estado de migraciones${NC}" | tee -a $VERIFICATION_LOG
|
||||
fi
|
||||
cd ..
|
||||
|
||||
# Verificar Redis
|
||||
echo -e "${BLUE}📊 Estado de Redis:${NC}" | tee -a $VERIFICATION_LOG
|
||||
if docker-compose -f $COMPOSE_FILE exec -T redis redis-cli -a ${REDIS_PASSWORD} info stats 2>/dev/null | grep -E "(total_connections_received|total_commands_processed)" | tee -a $VERIFICATION_LOG; then
|
||||
echo -e "${GREEN}✅ Redis respondiendo${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Redis no responde a comandos${NC}" | tee -a $VERIFICATION_LOG
|
||||
fi
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Verificar volúmenes
|
||||
echo -e "${BLUE}💾 Estado de volúmenes:${NC}" | tee -a $VERIFICATION_LOG
|
||||
docker volume ls | grep -E "math|postgres_data|redis_data" | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Tests de endpoints HTTP
|
||||
echo -e "${BLUE}🌐 Tests de Endpoints:${NC}" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Backend health
|
||||
echo -n " Backend (/health): " | tee -a $VERIFICATION_LOG
|
||||
if curl -sf http://localhost:3001/health > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ OK${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${RED}❌ FAIL${NC}" | tee -a $VERIFICATION_LOG
|
||||
((FAILED_SERVICES++))
|
||||
fi
|
||||
|
||||
# Frontend
|
||||
echo -n " Frontend (/: " | tee -a $VERIFICATION_LOG
|
||||
if curl -sf http://localhost > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ OK${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${RED}❌ FAIL${NC}" | tee -a $VERIFICATION_LOG
|
||||
((FAILED_SERVICES++))
|
||||
fi
|
||||
|
||||
# API endpoints adicionales
|
||||
echo -n " API (/api/status): " | tee -a $VERIFICATION_LOG
|
||||
if curl -sf http://localhost:3001/api/status > /dev/null 2>&1 || curl -sf http://localhost/api/status > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ OK${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ No disponible${NC}" | tee -a $VERIFICATION_LOG
|
||||
fi
|
||||
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Resumen final
|
||||
echo -e "${BLUE}================================================${NC}" | tee -a $VERIFICATION_LOG
|
||||
echo -e "${BLUE}📊 RESUMEN DE VERIFICACIÓN${NC}" | tee -a $VERIFICATION_LOG
|
||||
echo -e "${BLUE}================================================${NC}" | tee -a $VERIFICATION_LOG
|
||||
|
||||
if [ $FAILED_SERVICES -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ TODOS LOS SERVICIOS FUNCIONAN CORRECTAMENTE${NC}" | tee -a $VERIFICATION_LOG
|
||||
else
|
||||
echo -e "${RED}❌ $FAILED_SERVICES SERVICIO(S) CON PROBLEMAS${NC}" | tee -a $VERIFICATION_LOG
|
||||
fi
|
||||
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
echo -e "${BLUE}📁 Log guardado en:${NC} $VERIFICATION_LOG" | tee -a $VERIFICATION_LOG
|
||||
echo "" | tee -a $VERIFICATION_LOG
|
||||
|
||||
# Recomendaciones
|
||||
if [ $FAILED_SERVICES -gt 0 ]; then
|
||||
echo -e "${YELLOW}⚠️ Recomendaciones:${NC}" | tee -a $VERIFICATION_LOG
|
||||
echo " 1. Revisa los logs: docker-compose -f $COMPOSE_FILE logs -f [servicio]" | tee -a $VERIFICATION_LOG
|
||||
echo " 2. Verifica variables de entorno en .env" | tee -a $VERIFICATION_LOG
|
||||
echo " 3. Reinicia servicios: docker-compose -f $COMPOSE_FILE restart" | tee -a $VERIFICATION_LOG
|
||||
echo " 4. Si persiste: docker-compose -f $COMPOSE_FILE down && ./scripts/start-production.sh" | tee -a $VERIFICATION_LOG
|
||||
fi
|
||||
|
||||
exit $FAILED_SERVICES
|
||||
Reference in New Issue
Block a user