101 lines
3.1 KiB
Bash
101 lines
3.1 KiB
Bash
#!/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/osint-board}"
|
||
|
|
COMPOSE="docker compose -f ${REMOTE_DIR}/docker-compose.prod.yml --env-file /opt/gu_common/.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 gu_common configuration..."
|
||
|
|
ssh "$SERVER" "test -f /opt/gu_common/.env.prod || { echo 'ERROR: /opt/gu_common/.env.prod is missing'; 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://osint.glitch.university"
|