#!/bin/bash # deploy.sh - Deploy OSINT Board to the shared gu_common infrastructure set -e SKIP_PULL=false if [ "$1" = "--skip-pull" ]; then SKIP_PULL=true fi SERVER="${DEPLOY_SERVER:-root@76.13.144.52}" REMOTE_DIR="${DEPLOY_DIR:-/opt/gupi}" # GUPI runs from its own dir with its own env; the shared services come from gu_common. COMPOSE="docker compose -f ${REMOTE_DIR}/docker-compose.prod.yml --env-file ${REMOTE_DIR}/.env.prod" TARGET_HOST=$(echo "${SERVER}" | sed 's/.*@//') OWN_IP=$(curl -sf --max-time 3 ifconfig.me 2>/dev/null || echo "unknown") if [ "$OWN_IP" = "$TARGET_HOST" ]; then echo "Error: deploy.sh must be run from your local machine, not the server." exit 1 fi REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo "==> Deploying OSINT Board to ${SERVER}:${REMOTE_DIR}" if [ "$SKIP_PULL" = true ]; then echo "==> Skipping git pull (--skip-pull flag set)" else echo "==> Checking for upstream changes..." HEAD_BEFORE=$(git -C "$REPO_DIR" rev-parse HEAD) if ! git -C "$REPO_DIR" pull --ff-only; then echo "Error: git pull failed. Resolve local state before deploying." exit 1 fi HEAD_AFTER=$(git -C "$REPO_DIR" rev-parse HEAD) if [ "$HEAD_BEFORE" != "$HEAD_AFTER" ]; then echo "New upstream commits were pulled. Review and test them before deploying." git -C "$REPO_DIR" log --oneline "${HEAD_BEFORE}..${HEAD_AFTER}" exit 1 fi fi echo "==> Building locally..." npm run build echo "==> Syncing files..." ssh "$SERVER" "mkdir -p ${REMOTE_DIR}" rsync -avz --delete \ --exclude 'node_modules' \ --exclude '.git' \ --exclude 'dist' \ --exclude '.env' \ --exclude '.env.local' \ --exclude '.env.prod' \ --exclude '.DS_Store' \ ./ "${SERVER}:${REMOTE_DIR}/" echo "==> Verifying GUPI environment..." ssh "$SERVER" "test -f ${REMOTE_DIR}/.env.prod || { echo 'ERROR: ${REMOTE_DIR}/.env.prod is missing (copy .env.prod.example and fill it in)'; exit 1; }" echo "==> Ensuring shared network exists..." ssh "$SERVER" "docker network create gnommo 2>/dev/null || true" echo "==> Building application image..." ssh "$SERVER" "CACHEBUST=\$(date +%s) && $COMPOSE build --build-arg CACHEBUST=\$CACHEBUST app" echo "==> Waiting for gu_common PostgreSQL..." for i in $(seq 1 12); do if ssh "$SERVER" "docker exec gnommo-db pg_isready -q" 2>/dev/null; then echo " PostgreSQL is ready." break fi echo " Not ready yet, waiting... ($i/12)" sleep 5 if [ "$i" -eq 12 ]; then echo "ERROR: gu_common PostgreSQL did not become ready." exit 1 fi done echo "==> Running osint schema migrations..." ssh "$SERVER" "$COMPOSE run --rm --no-deps app npm run migrate:up" echo "==> Starting application..." ssh "$SERVER" "$COMPOSE up -d app" echo "==> Waiting for OSINT Board health check..." for i in $(seq 1 24); do if ssh "$SERVER" "docker exec gnommo-osint-board node -e \"fetch('http://127.0.0.1:8787/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\"" 2>/dev/null; then echo " OSINT Board is healthy." break fi echo " Not ready yet, waiting... ($i/24)" sleep 5 if [ "$i" -eq 24 ]; then echo "ERROR: OSINT Board did not become healthy within 2 minutes." exit 1 fi done echo "==> Done! https://gupi.glitch.university"