142 lines
4.9 KiB
Bash
Executable file
142 lines
4.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# =============================================================================
|
|
# OliVAS Production Deploy Script
|
|
# Idempotent — safe to run for initial deploy and subsequent updates
|
|
# =============================================================================
|
|
|
|
REPO_DIR=/opt/olivas
|
|
WEB_DIR=/var/www/html/olivas
|
|
COMPOSE="docker compose -f docker-compose.yml -f docker-compose.prod.yml"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Color helpers
|
|
# ---------------------------------------------------------------------------
|
|
info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; }
|
|
warn() { printf '\033[1;33m[WARN]\033[0m %s\n' "$*"; }
|
|
error() { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*"; }
|
|
success() { printf '\033[1;32m[OK]\033[0m %s\n' "$*"; }
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Preflight checks
|
|
# ---------------------------------------------------------------------------
|
|
if ! command -v docker &>/dev/null; then
|
|
error "docker is not installed."
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker compose version &>/dev/null; then
|
|
error "docker compose plugin is not available."
|
|
exit 1
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. Pull latest code
|
|
# ---------------------------------------------------------------------------
|
|
cd "$REPO_DIR"
|
|
info "Pulling latest code..."
|
|
git pull --ff-only origin main
|
|
COMMIT=$(git rev-parse --short HEAD)
|
|
success "At commit $COMMIT"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. Handle .env
|
|
# ---------------------------------------------------------------------------
|
|
if [[ ! -f .env ]]; then
|
|
cp .env.example .env
|
|
warn ".env was created from .env.example."
|
|
warn "Edit /opt/olivas/.env with production values, then re-run this script."
|
|
exit 0
|
|
fi
|
|
|
|
info "Loading .env..."
|
|
set -a
|
|
# shellcheck disable=SC1091
|
|
source .env
|
|
set +a
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. Build backend Docker image
|
|
# ---------------------------------------------------------------------------
|
|
info "Building backend image..."
|
|
$COMPOSE build backend
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5. Start postgres and wait for it to be healthy
|
|
# ---------------------------------------------------------------------------
|
|
info "Starting postgres..."
|
|
$COMPOSE up -d postgres
|
|
|
|
info "Waiting for postgres to be ready..."
|
|
for i in $(seq 1 30); do
|
|
if $COMPOSE exec postgres pg_isready -U olivas &>/dev/null; then
|
|
success "Postgres is ready."
|
|
break
|
|
fi
|
|
if [[ $i -eq 30 ]]; then
|
|
error "Postgres did not become ready within 30 seconds."
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 6. Run database migrations
|
|
# ---------------------------------------------------------------------------
|
|
info "Starting backend for migrations..."
|
|
$COMPOSE up -d backend
|
|
|
|
info "Running database migrations..."
|
|
$COMPOSE exec -e PYTHONPATH=/app backend alembic -c alembic.ini upgrade head
|
|
success "Migrations complete."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 7. Restart backend (pick up new code/env)
|
|
# ---------------------------------------------------------------------------
|
|
info "Restarting backend..."
|
|
$COMPOSE up -d --force-recreate backend
|
|
success "Backend restarted."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 8. Build frontend in a temporary Docker container
|
|
# ---------------------------------------------------------------------------
|
|
info "Building frontend..."
|
|
docker run --rm \
|
|
-v "$REPO_DIR/frontend:/app" \
|
|
-w /app \
|
|
-e VITE_AZURE_TENANT_ID \
|
|
-e VITE_AZURE_CLIENT_ID \
|
|
-e VITE_AZURE_REDIRECT_URI \
|
|
node:20-alpine \
|
|
sh -c "npm ci --prefer-offline && npm run build"
|
|
success "Frontend built."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 9. Deploy frontend to web directory
|
|
# ---------------------------------------------------------------------------
|
|
info "Deploying frontend to $WEB_DIR..."
|
|
mkdir -p "$WEB_DIR"
|
|
rm -rf "${WEB_DIR:?}"/*
|
|
cp -r "$REPO_DIR/frontend/dist/"* "$WEB_DIR/"
|
|
chmod -R a+rX "$WEB_DIR"
|
|
success "Frontend deployed."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 10. Health check
|
|
# ---------------------------------------------------------------------------
|
|
info "Waiting for backend health check..."
|
|
sleep 3
|
|
if curl -sf http://localhost:8000/api/health > /dev/null 2>&1; then
|
|
success "Backend health check passed."
|
|
else
|
|
warn "Backend health check failed — it may still be starting up."
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 11. Summary
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
success "Deploy complete"
|
|
info "Commit: $COMMIT"
|
|
info "Timestamp: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|