#!/bin/bash ################################################################################ # CodePilot GCP Deployment Script # Deploys CodePilot to Google Cloud Platform VM with zero manual steps ################################################################################ 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 TARBALL_NAME="codepilot-deployment.tar.gz" REMOTE_DIR="~/codepilot" BACKUP_DIR="~/codepilot_backup" ################################################################################ # Helper Functions ################################################################################ log_info() { echo -e "${BLUE}ℹ️ $1${NC}" } log_success() { echo -e "${GREEN}✅ $1${NC}" } log_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } log_error() { echo -e "${RED}❌ $1${NC}" } ################################################################################ # Load and Validate Environment ################################################################################ log_info "Loading environment configuration..." # Load .env file if exists if [ -f .env ]; then source .env log_success "Loaded .env file" else log_warning ".env file not found - using environment variables only" fi # Validate required variables if [ -z "$GCP_VM_IP" ]; then log_error "GCP_VM_IP not set" echo "Please set GCP_VM_IP in .env file or environment" echo "Example: export GCP_VM_IP=34.123.45.67" exit 1 fi # Set defaults GCP_SSH_USER=${GCP_SSH_USER:-$(whoami)} GCP_SSH_KEY=${GCP_SSH_KEY:-~/.ssh/google_compute_engine} log_info "Deployment Configuration:" echo " • Target VM: $GCP_VM_IP" echo " • SSH User: $GCP_SSH_USER" echo " • SSH Key: $GCP_SSH_KEY" # Verify SSH key exists if [ ! -f "$GCP_SSH_KEY" ]; then log_error "SSH key not found: $GCP_SSH_KEY" echo "Generate one with: ssh-keygen -t rsa -f $GCP_SSH_KEY" exit 1 fi ################################################################################ # Pre-Deployment Checks ################################################################################ log_info "Running pre-deployment checks..." # Test SSH connectivity log_info "Testing SSH connection to $GCP_VM_IP..." if ssh -i "$GCP_SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes "$GCP_SSH_USER@$GCP_VM_IP" "echo 'SSH connection successful'" &>/dev/null; then log_success "SSH connection verified" else log_error "Cannot connect to $GCP_VM_IP" echo "Check that:" echo " 1. VM is running" echo " 2. Firewall allows SSH (port 22)" echo " 3. SSH key is added to VM" exit 1 fi ################################################################################ # Build Deployment Package ################################################################################ log_info "Building deployment package..." # Remove old tarball if exists rm -f "$TARBALL_NAME" # Create tarball excluding unnecessary files tar -czf "$TARBALL_NAME" \ --exclude=venv \ --exclude=.git \ --exclude=__pycache__ \ --exclude='*.pyc' \ --exclude='*.pyo' \ --exclude='.pytest_cache' \ --exclude='*.egg-info' \ --exclude='.DS_Store' \ --exclude='node_modules' \ --exclude="$TARBALL_NAME" \ . TARBALL_SIZE=$(du -h "$TARBALL_NAME" | cut -f1) log_success "Created tarball: $TARBALL_NAME ($TARBALL_SIZE)" ################################################################################ # Upload to GCP VM ################################################################################ log_info "Uploading to GCP VM..." scp -i "$GCP_SSH_KEY" \ -o StrictHostKeyChecking=no \ "$TARBALL_NAME" \ "$GCP_SSH_USER@$GCP_VM_IP:/tmp/" log_success "Upload complete" ################################################################################ # Deploy on Remote VM ################################################################################ log_info "Deploying on remote VM..." ssh -i "$GCP_SSH_KEY" \ -o StrictHostKeyChecking=no \ "$GCP_SSH_USER@$GCP_VM_IP" << 'REMOTE_SCRIPT' set -e # Exit on error # Colors for remote output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; } log_success() { echo -e "${GREEN}✅ $1${NC}"; } log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; } log_error() { echo -e "${RED}❌ $1${NC}"; } ################################################################################ # Backup existing deployment ################################################################################ if [ -d ~/codepilot ]; then log_info "Backing up existing deployment..." # Stop current containers cd ~/codepilot if [ -f docker-compose.yml ]; then docker-compose down || log_warning "Failed to stop containers (may not be running)" fi # Create backup BACKUP_NAME="codepilot_backup_$(date +%Y%m%d_%H%M%S)" mv ~/codepilot ~/"$BACKUP_NAME" log_success "Backup created: ~/$BACKUP_NAME" fi ################################################################################ # Extract new deployment ################################################################################ log_info "Extracting deployment package..." mkdir -p ~/codepilot cd /tmp tar -xzf codepilot-deployment.tar.gz -C ~/codepilot log_success "Extracted to ~/codepilot" ################################################################################ # Deploy with Docker Compose ################################################################################ cd ~/codepilot log_info "Starting Docker containers..." # Check if docker-compose.yml exists if [ ! -f docker-compose.yml ]; then log_error "docker-compose.yml not found in deployment package" exit 1 fi # Pull latest images and start docker-compose pull || log_warning "Failed to pull images (using cached)" docker-compose up -d log_success "Docker containers started" ################################################################################ # Health Check ################################################################################ log_info "Running health check..." sleep 5 # Wait for containers to initialize # Check if containers are running RUNNING_CONTAINERS=$(docker-compose ps --services --filter "status=running" | wc -l) TOTAL_CONTAINERS=$(docker-compose ps --services | wc -l) if [ "$RUNNING_CONTAINERS" -eq "$TOTAL_CONTAINERS" ]; then log_success "All containers healthy ($RUNNING_CONTAINERS/$TOTAL_CONTAINERS running)" else log_warning "Some containers not running ($RUNNING_CONTAINERS/$TOTAL_CONTAINERS)" docker-compose ps fi ################################################################################ # Cleanup ################################################################################ log_info "Cleaning up..." rm -f /tmp/codepilot-deployment.tar.gz log_success "Cleanup complete" echo "" log_success "🎉 Deployment successful!" echo "Access CodePilot at: http://$(hostname -I | awk '{print $1}'):8000" REMOTE_SCRIPT ################################################################################ # Local Cleanup ################################################################################ log_info "Cleaning up local files..." rm -f "$TARBALL_NAME" log_success "Local cleanup complete" ################################################################################ # Final Status ################################################################################ echo "" echo "╔════════════════════════════════════════════════════════════╗" echo "║ DEPLOYMENT SUCCESSFUL ║" echo "╚════════════════════════════════════════════════════════════╝" echo "" log_success "CodePilot deployed to $GCP_VM_IP" echo "" echo "Next steps:" echo " 1. Access UI: http://$GCP_VM_IP:8000" echo " 2. Check logs: ssh $GCP_SSH_USER@$GCP_VM_IP 'cd ~/codepilot && docker-compose logs -f'" echo " 3. Stop: ssh $GCP_SSH_USER@$GCP_VM_IP 'cd ~/codepilot && docker-compose down'" echo ""