#!/usr/bin/env bash # deploy.sh — Deploy Performance West to production # # Usage: # ./scripts/deploy.sh # full deploy (rsync + build + restart) # ./scripts/deploy.sh --rsync # rsync only # ./scripts/deploy.sh --build # build only (run on server) # # Prerequisites: # - SSH key configured for deploy@207.174.124.71 port 22022 # - .env configured on server at /opt/performancewest/.env set -euo pipefail SERVER="deploy@207.174.124.71" SSH_PORT=22022 REMOTE_DIR="/opt/performancewest" LOCAL_DIR="$(cd "$(dirname "$0")/.." && pwd)" # Colors RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' log() { echo -e "${GREEN}[deploy]${NC} $*"; } warn() { echo -e "${YELLOW}[deploy]${NC} $*"; } die() { echo -e "${RED}[deploy] ERROR:${NC} $*" >&2; exit 1; } # ── Parse args ──────────────────────────────────────────────────────────────── DO_RSYNC=true DO_BUILD=true for arg in "$@"; do case "$arg" in --rsync) DO_RSYNC=true; DO_BUILD=false ;; --build) DO_RSYNC=false; DO_BUILD=true ;; esac done # ── 1. Rsync ────────────────────────────────────────────────────────────────── if $DO_RSYNC; then log "Syncing to ${SERVER}:${REMOTE_DIR} ..." rsync \ --archive \ --compress \ --delete \ --timeout=30 \ --exclude='.git' \ --exclude='node_modules' \ --exclude='site/.astro' \ --exclude='site/dist' \ --exclude='api/dist' \ --exclude='api/node_modules' \ --exclude='mcp/node_modules' \ --exclude='mcp/dist' \ --exclude='**/__pycache__' \ --exclude='*.pyc' \ --exclude='.env' \ --exclude='*.log' \ -e "ssh -p ${SSH_PORT}" \ "${LOCAL_DIR}/" \ "${SERVER}:${REMOTE_DIR}/" log "Rsync complete." fi # ── 2. Remote build + restart ───────────────────────────────────────────────── if $DO_BUILD; then log "Building + restarting on server ..." ssh -p "${SSH_PORT}" "${SERVER}" bash <<'REMOTE' set -euo pipefail cd /opt/performancewest echo "[remote] Building Docker images..." docker compose build --parallel echo "[remote] Running DB migrations..." docker compose run --rm api node -e " const { pool } = require('./dist/db.js'); pool.end().then(() => console.log('DB connection OK')); " 2>/dev/null || true echo "[remote] Restarting containers..." docker compose up -d --remove-orphans echo "[remote] Waiting for API health check..." for i in $(seq 1 20); do if curl -sf http://localhost:3001/health > /dev/null 2>&1; then echo "[remote] API is healthy." break fi sleep 3 done echo "[remote] Container status:" docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" REMOTE log "Deploy complete." fi log "Done. Site: https://performancewest.net | API: https://api.performancewest.net"