- Complete Fastify gateway with 8-stage pipeline - Circuit breaker (opossum) per model tier - Rate limiting per caller - Ban list validation (EN/DE/auto-detected) - TIP validator (SFF-8024, part numbers, wavelengths) - Prometheus metrics - pg-boss async queue - PostgreSQL audit log + review queue - 9 prompt templates (TIP, LinkedIn, ShieldX) - Learning engine scaffolding - Auto-learning: ban-list, few-shot, routing, prompt optimizer
187 lines
5.4 KiB
Bash
Executable File
187 lines
5.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================
|
|
# LLM Gateway — One-command deploy (run locally on Mac)
|
|
#
|
|
# Usage:
|
|
# bash deploy/deploy.sh
|
|
# bash deploy/deploy.sh --skip-build # skip local build
|
|
# bash deploy/deploy.sh --health-only # just check remote health
|
|
# ============================================================
|
|
set -euo pipefail
|
|
|
|
ERIK_HOST="217.154.82.179"
|
|
ERIK_USER="root"
|
|
REMOTE_DIR="/opt/llm-gateway"
|
|
GITEA_BRANCH="main"
|
|
HEALTH_URL="http://${ERIK_HOST}:3100/health"
|
|
HEALTH_URL_CF="https://llm-gateway.context-x.org/health"
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
|
|
section() { echo -e "\n${BLUE}>> $*${NC}"; }
|
|
|
|
# Parse args
|
|
SKIP_BUILD=false
|
|
HEALTH_ONLY=false
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--skip-build) SKIP_BUILD=true ;;
|
|
--health-only) HEALTH_ONLY=true ;;
|
|
*) warn "Unknown argument: $arg" ;;
|
|
esac
|
|
done
|
|
|
|
# -------------------------------------------------------
|
|
# Health-only mode
|
|
# -------------------------------------------------------
|
|
if [[ "$HEALTH_ONLY" == "true" ]]; then
|
|
section "Remote health check"
|
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_URL" 2>/dev/null || echo "000")
|
|
BODY=$(curl -s "$HEALTH_URL" 2>/dev/null || echo "{}")
|
|
echo " HTTP status: $STATUS"
|
|
echo " Response: $BODY"
|
|
[[ "$STATUS" == "200" ]] && info "Gateway is healthy." || warn "Gateway may be unhealthy."
|
|
exit 0
|
|
fi
|
|
|
|
# -------------------------------------------------------
|
|
# 0. Pre-deploy checks
|
|
# -------------------------------------------------------
|
|
section "0. Pre-deploy checks"
|
|
|
|
command -v npm >/dev/null || error "npm not found."
|
|
command -v git >/dev/null || error "git not found."
|
|
command -v ssh >/dev/null || error "ssh not found."
|
|
command -v curl >/dev/null || error "curl not found."
|
|
|
|
# Check we're on main (warn only — don't block)
|
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
if [[ "$CURRENT_BRANCH" != "$GITEA_BRANCH" ]]; then
|
|
warn "Current branch is '$CURRENT_BRANCH', not '$GITEA_BRANCH'. Proceeding anyway."
|
|
fi
|
|
|
|
# Check for uncommitted changes
|
|
if ! git diff --quiet 2>/dev/null; then
|
|
warn "You have uncommitted changes. They will NOT be deployed."
|
|
fi
|
|
|
|
info "Pre-deploy checks passed."
|
|
|
|
# -------------------------------------------------------
|
|
# 1. Local build
|
|
# -------------------------------------------------------
|
|
section "1. Local build"
|
|
|
|
if [[ "$SKIP_BUILD" == "true" ]]; then
|
|
warn "Skipping local build (--skip-build)"
|
|
else
|
|
info "Running: npm run build"
|
|
npm run build
|
|
info "Build successful."
|
|
fi
|
|
|
|
# -------------------------------------------------------
|
|
# 2. Push to Gitea
|
|
# -------------------------------------------------------
|
|
section "2. Pushing to Gitea"
|
|
|
|
COMMIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
info "Pushing commit $COMMIT_SHA to Gitea ($GITEA_BRANCH)..."
|
|
|
|
git push origin "$GITEA_BRANCH"
|
|
info "Push complete."
|
|
|
|
# -------------------------------------------------------
|
|
# 3. Deploy on Erik
|
|
# -------------------------------------------------------
|
|
section "3. Deploying on Erik (${ERIK_HOST})"
|
|
|
|
info "Connecting via SSH..."
|
|
|
|
# shellcheck disable=SC2087
|
|
ssh -o ConnectTimeout=15 "${ERIK_USER}@${ERIK_HOST}" bash << 'REMOTE_SCRIPT'
|
|
set -euo pipefail
|
|
|
|
REMOTE_DIR="/opt/llm-gateway"
|
|
LOG_DIR="/var/log/llm-gateway"
|
|
|
|
echo "[remote] Pulling latest code..."
|
|
cd "$REMOTE_DIR"
|
|
git fetch origin
|
|
git reset --hard origin/main
|
|
|
|
echo "[remote] Installing dependencies..."
|
|
npm install --prefer-offline 2>/dev/null || npm install
|
|
|
|
echo "[remote] Building..."
|
|
npm run build
|
|
|
|
echo "[remote] Ensuring log directory..."
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
echo "[remote] Restarting PM2 processes..."
|
|
if pm2 list | grep -q "llm-gateway"; then
|
|
pm2 reload llm-gateway llm-learning --update-env
|
|
else
|
|
echo "[remote] PM2 processes not found — starting from ecosystem config..."
|
|
pm2 start deploy/ecosystem.config.cjs
|
|
fi
|
|
|
|
pm2 save
|
|
|
|
echo "[remote] Deploy complete."
|
|
REMOTE_SCRIPT
|
|
|
|
info "Remote deploy finished."
|
|
|
|
# -------------------------------------------------------
|
|
# 4. Post-deploy health check
|
|
# -------------------------------------------------------
|
|
section "4. Post-deploy health check"
|
|
|
|
MAX_RETRIES=8
|
|
RETRY_DELAY=5
|
|
|
|
info "Waiting ${RETRY_DELAY}s for restart to complete..."
|
|
sleep $RETRY_DELAY
|
|
|
|
for i in $(seq 1 $MAX_RETRIES); do
|
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$HEALTH_URL" 2>/dev/null || echo "000")
|
|
|
|
if [[ "$STATUS" == "200" ]]; then
|
|
BODY=$(curl -s --max-time 10 "$HEALTH_URL" 2>/dev/null || echo "{}")
|
|
info "Health check PASSED (HTTP 200)"
|
|
echo " $BODY"
|
|
break
|
|
fi
|
|
|
|
if [[ $i -eq $MAX_RETRIES ]]; then
|
|
warn "Health check did not return 200 after ${MAX_RETRIES} attempts."
|
|
warn "Check logs on Erik: ssh root@${ERIK_HOST} 'pm2 logs llm-gateway --lines 50'"
|
|
exit 1
|
|
fi
|
|
|
|
info " Attempt $i/$MAX_RETRIES — HTTP $STATUS. Retrying in ${RETRY_DELAY}s..."
|
|
sleep $RETRY_DELAY
|
|
done
|
|
|
|
# -------------------------------------------------------
|
|
# 5. Summary
|
|
# -------------------------------------------------------
|
|
echo ""
|
|
echo -e "${GREEN}Deploy successful!${NC}"
|
|
echo ""
|
|
echo " Commit: $COMMIT_SHA"
|
|
echo " Direct: $HEALTH_URL"
|
|
echo " Cloudflare: $HEALTH_URL_CF"
|
|
echo " PM2 status: ssh root@${ERIK_HOST} 'pm2 status'"
|
|
echo " Logs: ssh root@${ERIK_HOST} 'pm2 logs llm-gateway'"
|
|
echo ""
|