#!/bin/bash # SerpentRace Backend Production Deployment Script # This script handles the complete deployment process set -e # Exit on any 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 log() { echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}" } error() { echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" } warn() { echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" } info() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO: $1${NC}" } # Check if required environment variables are set check_env() { log "Checking environment variables..." required_vars=( "DB_HOST" "DB_PORT" "DB_USERNAME" "DB_PASSWORD" "DB_NAME" "JWT_SECRET" "REDIS_HOST" "REDIS_PORT" ) missing_vars=() for var in "${required_vars[@]}"; do if [ -z "${!var}" ]; then missing_vars+=("$var") fi done if [ ${#missing_vars[@]} -ne 0 ]; then error "Missing required environment variables: ${missing_vars[*]}" error "Please set these variables before running the deployment" exit 1 fi log "All required environment variables are set" } # Install dependencies install_dependencies() { log "Installing production dependencies..." npm ci --only=production log "Dependencies installed successfully" } # Run the comprehensive build process run_build() { log "Running production build..." npm run build:production log "Build completed successfully" } # Test database connectivity test_database() { log "Testing database connectivity..." # Use a simple TypeScript script to test connection cat > /tmp/test-db.ts << 'EOF' import { AppDataSource } from './src/Infrastructure/ormconfig'; async function testConnection() { try { await AppDataSource.initialize(); console.log('✅ Database connection successful'); await AppDataSource.destroy(); process.exit(0); } catch (error) { console.error('❌ Database connection failed:', error); process.exit(1); } } testConnection(); EOF npx ts-node /tmp/test-db.ts || { error "Database connectivity test failed" exit 1 } rm -f /tmp/test-db.ts log "Database connectivity test passed" } # Test Redis connectivity test_redis() { log "Testing Redis connectivity..." # Use a simple script to test Redis connection cat > /tmp/test-redis.ts << 'EOF' import { createClient } from 'redis'; async function testRedis() { const client = createClient({ socket: { host: process.env.REDIS_HOST || 'localhost', port: parseInt(process.env.REDIS_PORT || '6379') } }); try { await client.connect(); await client.ping(); console.log('✅ Redis connection successful'); await client.disconnect(); process.exit(0); } catch (error) { console.error('❌ Redis connection failed:', error); process.exit(1); } } testRedis(); EOF npx ts-node /tmp/test-redis.ts || { warn "Redis connectivity test failed - continuing anyway" } rm -f /tmp/test-redis.ts log "Redis connectivity test completed" } # Create required directories setup_directories() { log "Setting up required directories..." mkdir -p logs mkdir -p uploads log "Directories created" } # Start the application (for testing) start_app() { log "Starting application for validation..." # Start the app in background and test if it responds npm start & APP_PID=$! # Wait for app to start sleep 10 # Test if the health endpoint responds if curl -f http://localhost:${PORT:-3000}/health > /dev/null 2>&1; then log "Application health check passed" kill $APP_PID wait $APP_PID 2>/dev/null else error "Application health check failed" kill $APP_PID 2>/dev/null || true wait $APP_PID 2>/dev/null || true exit 1 fi } # Main deployment function deploy() { log "🚀 Starting SerpentRace Backend production deployment..." # Check environment check_env # Install dependencies install_dependencies # Run build process run_build # Setup directories setup_directories # Test connections test_database test_redis # Test application startup if [ "${SKIP_APP_TEST}" != "true" ]; then start_app else warn "Skipping application startup test" fi log "🎉 Deployment completed successfully!" info "You can now start the application with: npm start" } # Handle script arguments case "${1:-deploy}" in "deploy") deploy ;; "build-only") log "Running build-only deployment..." check_env install_dependencies run_build setup_directories log "Build-only deployment completed" ;; "test-connections") log "Testing connections only..." check_env test_database test_redis log "Connection tests completed" ;; *) echo "Usage: $0 [deploy|build-only|test-connections]" echo " deploy - Full deployment (default)" echo " build-only - Only build, skip tests" echo " test-connections - Test database and Redis connections" exit 1 ;; esac