Files
memory-infrastructure-palace/code/websites/pokedex.online/deploy.sh

439 lines
13 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
###############################################################################
# Pokedex.Online Deployment Automation Script
#
# This script automates the deployment process with pre-deployment checks,
# build verification, and rollback capability.
#
# Usage:
# ./deploy.sh [options]
#
# Options:
# --target <internal|external> Deployment target (default: internal)
# --port <number> Frontend HTTP port (default: 8080)
# --ssl-port <number> Frontend HTTPS port (optional)
# --backend-port <number> Backend port (default: 3000)
# --skip-tests Skip test execution
# --skip-build Skip build step (use existing dist/)
# --no-backup Skip backup creation
# --dry-run Show what would be deployed without deploying
#
# Examples:
# ./deploy.sh --target internal
# ./deploy.sh --target external --port 8080 --backend-port 3000
# ./deploy.sh --dry-run
###############################################################################
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
# Default configuration
TARGET="internal"
PORT=8080
SSL_PORT=""
BACKEND_PORT=3000
SKIP_TESTS=false
SKIP_BUILD=false
NO_BACKUP=false
DRY_RUN=false
# Script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$SCRIPT_DIR"
###############################################################################
# Helper Functions
###############################################################################
log_info() {
echo -e "${BLUE}${NC} $1"
}
log_success() {
echo -e "${GREEN}${NC} $1"
}
log_warning() {
echo -e "${YELLOW}${NC} $1"
}
log_error() {
echo -e "${RED}${NC} $1"
}
log_step() {
echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
}
###############################################################################
# Parse Arguments
###############################################################################
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--target)
TARGET="$2"
shift 2
;;
--port)
PORT="$2"
shift 2
;;
--ssl-port)
SSL_PORT="$2"
shift 2
;;
--backend-port)
BACKEND_PORT="$2"
shift 2
;;
--skip-tests)
SKIP_TESTS=true
shift
;;
--skip-build)
SKIP_BUILD=true
shift
;;
--no-backup)
NO_BACKUP=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
--help)
head -n 30 "$0" | tail -n 25
exit 0
;;
*)
log_error "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
}
###############################################################################
# Pre-Deployment Checks
###############################################################################
check_prerequisites() {
log_step "🔍 Checking Prerequisites"
# Check Node.js
if ! command -v node &> /dev/null; then
log_error "Node.js is not installed"
exit 1
fi
log_success "Node.js $(node --version)"
# Check npm
if ! command -v npm &> /dev/null; then
log_error "npm is not installed"
exit 1
fi
log_success "npm $(npm --version)"
# Check if dependencies are installed
if [ ! -d "$PROJECT_ROOT/node_modules" ]; then
log_error "Dependencies not installed. Run 'npm install' first"
exit 1
fi
log_success "Dependencies installed"
# Check if server dependencies are installed
if [ ! -d "$PROJECT_ROOT/server/node_modules" ]; then
log_error "Server dependencies not installed. Run 'npm install --workspace=server' first"
exit 1
fi
log_success "Server dependencies installed"
}
check_environment() {
log_step "🔧 Checking Environment Configuration"
# Check if .env exists
if [ ! -f "$PROJECT_ROOT/server/.env" ]; then
log_warning ".env file not found in server/"
log_info "Copy server/.env.example to server/.env and configure it"
if [ "$DRY_RUN" = false ]; then
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
else
log_success "Environment configuration found"
fi
}
run_tests() {
if [ "$SKIP_TESTS" = true ]; then
log_warning "Skipping tests (--skip-tests flag set)"
return
fi
log_step "🧪 Running Tests"
log_info "Running frontend tests..."
npm run test:run || {
log_error "Frontend tests failed"
exit 1
}
log_success "Frontend tests passed"
log_info "Running backend tests..."
npm run test:run --workspace=server || {
log_error "Backend tests failed"
exit 1
}
log_success "Backend tests passed"
}
###############################################################################
# Build
###############################################################################
build_application() {
if [ "$SKIP_BUILD" = true ]; then
log_warning "Skipping build (--skip-build flag set)"
# Check if dist exists
if [ ! -d "$PROJECT_ROOT/dist" ]; then
log_error "dist/ directory not found and --skip-build is set"
log_info "Remove --skip-build or run 'npm run build' first"
exit 1
fi
return
fi
log_step "🔨 Building Application"
log_info "Building frontend..."
npm run build:frontend || {
log_error "Frontend build failed"
exit 1
}
log_success "Frontend built successfully"
log_info "Verifying build..."
npm run build:verify || {
log_error "Build verification failed"
exit 1
}
log_success "Build verified"
}
###############################################################################
# Backup
###############################################################################
create_backup() {
if [ "$NO_BACKUP" = true ]; then
log_warning "Skipping backup (--no-backup flag set)"
return
fi
log_step "💾 Creating Backup"
BACKUP_DIR="$PROJECT_ROOT/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz"
mkdir -p "$BACKUP_DIR"
log_info "Creating backup of current deployment..."
tar -czf "$BACKUP_FILE" \
--exclude='node_modules' \
--exclude='dist' \
--exclude='.git' \
--exclude='backups' \
-C "$PROJECT_ROOT" . || {
log_error "Backup creation failed"
exit 1
}
log_success "Backup created: $BACKUP_FILE"
# Keep only last 5 backups
BACKUP_COUNT=$(ls -1 "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | wc -l)
if [ "$BACKUP_COUNT" -gt 5 ]; then
log_info "Cleaning old backups (keeping last 5)..."
ls -1t "$BACKUP_DIR"/backup_*.tar.gz | tail -n +6 | xargs rm -f
fi
}
###############################################################################
# Deployment
###############################################################################
deploy_to_server() {
log_step "🚀 Deploying to Server"
if [ "$DRY_RUN" = true ]; then
log_info "DRY RUN - Would deploy with following configuration:"
log_info " Target: $TARGET"
log_info " Frontend Port: $PORT"
[ -n "$SSL_PORT" ] && log_info " SSL Port: $SSL_PORT"
log_info " Backend Port: $BACKEND_PORT"
log_success "Dry run completed"
return
fi
# Build deployment command
DEPLOY_CMD="node ../../../utils/deploy-pokedex.js --target $TARGET --port $PORT --backend-port $BACKEND_PORT"
[ -n "$SSL_PORT" ] && DEPLOY_CMD="$DEPLOY_CMD --ssl-port $SSL_PORT"
log_info "Executing deployment..."
log_info "Command: $DEPLOY_CMD"
eval "$DEPLOY_CMD" || {
log_error "Deployment failed"
log_info "Check logs above for details"
exit 1
}
log_success "Deployment completed successfully"
}
###############################################################################
# Post-Deployment
###############################################################################
verify_deployment() {
log_step "🏥 Verifying Deployment"
if [ "$DRY_RUN" = true ]; then
log_info "DRY RUN - Skipping verification"
return
fi
# Determine host based on target
if [ "$TARGET" = "internal" ]; then
HOST="10.0.0.81"
else
HOST="home.gregrjacobs.com"
fi
log_info "Checking frontend health..."
sleep 3 # Give containers time to start
if curl -f -s "http://$HOST:$PORT/health" > /dev/null; then
log_success "Frontend is responding"
else
log_warning "Frontend health check failed"
fi
log_info "Checking backend health..."
if curl -f -s "http://$HOST:$BACKEND_PORT/health" > /dev/null; then
log_success "Backend is responding"
else
log_warning "Backend health check failed"
fi
}
print_summary() {
log_step "📊 Deployment Summary"
if [ "$DRY_RUN" = true ]; then
log_info "DRY RUN completed - no changes made"
return
fi
# Determine host based on target
if [ "$TARGET" = "internal" ]; then
HOST="10.0.0.81"
else
HOST="home.gregrjacobs.com"
fi
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN} 🎉 Deployment Successful!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e " ${BLUE}Frontend:${NC} http://$HOST:$PORT"
[ -n "$SSL_PORT" ] && echo -e " ${BLUE}HTTPS:${NC} https://$HOST:$SSL_PORT"
echo -e " ${BLUE}Backend:${NC} http://$HOST:$BACKEND_PORT"
echo -e " ${BLUE}Target:${NC} $TARGET"
echo ""
echo -e " ${YELLOW}Next Steps:${NC}"
echo -e " • Test the application manually"
echo -e " • Check logs: npm run docker:logs"
echo -e " • Monitor backend: curl http://$HOST:$BACKEND_PORT/health"
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
###############################################################################
# Rollback
###############################################################################
rollback() {
log_step "🔄 Rollback Instructions"
echo "To rollback to a previous version:"
echo ""
echo "1. List available backups:"
echo " ls -lh backups/"
echo ""
echo "2. Extract backup:"
echo " tar -xzf backups/backup_TIMESTAMP.tar.gz -C /tmp/restore"
echo ""
echo "3. Copy files back:"
echo " rsync -av /tmp/restore/ ./"
echo ""
echo "4. Redeploy:"
echo " ./deploy.sh --skip-tests --target $TARGET"
echo ""
echo "Or use the deployment script's built-in rollback:"
echo " node ../../../utils/deploy-pokedex.js --target $TARGET"
echo " (will auto-rollback on failure)"
}
###############################################################################
# Main Execution
###############################################################################
main() {
echo -e "${BLUE}"
echo "╔════════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ Pokedex.Online Deployment Automation ║"
echo "║ ║"
echo "╚════════════════════════════════════════════════════════════╝"
echo -e "${NC}\n"
# Parse command line arguments
parse_args "$@"
# Run deployment pipeline
check_prerequisites
check_environment
run_tests
build_application
create_backup
deploy_to_server
verify_deployment
print_summary
log_success "All done! 🚀"
}
# Run main function
main "$@"