107 lines
4.9 KiB
Bash
Executable file
107 lines
4.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# Deploy quinn.admin-api to black (canonical mesh-only origin).
|
|
#
|
|
# Targets BLACK, not vps-0. The vps-0:quinn.admin deploy is the legacy path
|
|
# being retired by this migration. See ~/.claude/plans/quiet-pulsing-anchor.md.
|
|
#
|
|
# Assumes the API monolith + admin frontend have already been built (CI does
|
|
# this in earlier workflow steps). Pass --skip-build to skip the local build
|
|
# fallback when running outside CI.
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../../" && pwd)"
|
|
|
|
REMOTE="${REMOTE_HOST:-black}"
|
|
# shellcheck source=../../ci/local-remote.sh
|
|
source "$REPO_ROOT/deployments/ci/local-remote.sh"
|
|
init_deploy_local
|
|
|
|
REMOTE_API="/opt/quinn-admin-api"
|
|
REMOTE_BACKUPS_API="/opt/quinn-admin-api.deploy-backups"
|
|
API_BUNDLE="codebase/@features/api/dist/server.node.js"
|
|
TIMESTAMP="$(date '+%Y%m%d_%H%M%S')"
|
|
BACKUP_API="${REMOTE_BACKUPS_API}/${TIMESTAMP}"
|
|
SERVICE_NAME="quinn-admin-api.service"
|
|
|
|
# ─── --rollback ─────────────────────────────────────────────────────────────
|
|
if [[ "${1:-}" == "--rollback" ]]; then
|
|
echo "==> [ROLLBACK] Restoring previous quinn.admin-api on ${REMOTE}..."
|
|
run_remote <<'ENDSSH'
|
|
REMOTE_BACKUPS_API="/opt/quinn-admin-api.deploy-backups"
|
|
REMOTE_API="/opt/quinn-admin-api"
|
|
latest_api="$(ls -1t "$REMOTE_BACKUPS_API" 2>/dev/null | head -1)"
|
|
if [[ -z "$latest_api" ]]; then
|
|
echo "ERROR: no API backups found." >&2; exit 1
|
|
fi
|
|
echo " Restoring API from $REMOTE_BACKUPS_API/$latest_api ..."
|
|
rsync -a --delete "$REMOTE_BACKUPS_API/$latest_api/" "$REMOTE_API/"
|
|
ENDSSH
|
|
run_remote_cmd "sudo systemctl restart ${SERVICE_NAME}"
|
|
echo "Rollback completed at $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
exit 0
|
|
fi
|
|
|
|
# ─── flag parsing ───────────────────────────────────────────────────────────
|
|
SKIP_BUILD=false
|
|
for arg in "$@"; do
|
|
[[ "$arg" == "--skip-build" ]] && SKIP_BUILD=true
|
|
done
|
|
|
|
cd "$REPO_ROOT"
|
|
|
|
if [[ "$SKIP_BUILD" != "true" ]]; then
|
|
echo "==> Building API monolith..."
|
|
pushd codebase/@features/api >/dev/null
|
|
bun install --frozen-lockfile
|
|
bun run typecheck
|
|
bun build --target=node --external better-sqlite3 --external sharp \
|
|
src/app/server.ts --outfile=dist/server.node.js --sourcemap=none
|
|
popd >/dev/null
|
|
fi
|
|
|
|
if [[ ! -f "$API_BUNDLE" ]]; then
|
|
echo "ERROR: missing API bundle at $API_BUNDLE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# ─── snapshot current state on black for rollback ───────────────────────────
|
|
echo "==> Snapshotting current API state into $BACKUP_API..."
|
|
run_remote_cmd "mkdir -p $BACKUP_API && rsync -a --delete $REMOTE_API/ $BACKUP_API/ 2>/dev/null || true"
|
|
|
|
# ─── rsync the new bundle ───────────────────────────────────────────────────
|
|
echo "==> Pushing new bundle to ${REMOTE}:${REMOTE_API}..."
|
|
run_remote_cmd "mkdir -p $REMOTE_API"
|
|
if [[ "$DEPLOY_LOCAL" == true ]]; then
|
|
mkdir -p "$REMOTE_API/dist"
|
|
rsync -av --no-perms --no-owner --no-group \
|
|
"$API_BUNDLE" "$REMOTE_API/dist/server.node.js"
|
|
else
|
|
rsync -av --no-perms --no-owner --no-group \
|
|
"$API_BUNDLE" "${REMOTE}:${REMOTE_API}/dist/server.node.js"
|
|
fi
|
|
|
|
# ─── secrets guard ───────────────────────────────────────────────────────────
|
|
# ANALYTICS_COLLECTOR_URL is load-bearing: the www edge relays
|
|
# transquinnftw.com/analytics/track/* to this service (black:3023), and
|
|
# without the var the relay 202s and silently DROPS every event
|
|
# (prod ingest outage 2026-06-10). Schema-optional, so guard it here.
|
|
echo "==> Ensuring ANALYTICS_COLLECTOR_URL in /etc/quinn-admin-api/secrets.env..."
|
|
run_remote_cmd "sudo grep -q '^ANALYTICS_COLLECTOR_URL=' /etc/quinn-admin-api/secrets.env \
|
|
|| echo 'ANALYTICS_COLLECTOR_URL=https://data.transquinnftw.com' \
|
|
| sudo tee -a /etc/quinn-admin-api/secrets.env >/dev/null"
|
|
|
|
# ─── restart + smoke test ───────────────────────────────────────────────────
|
|
echo "==> Restarting ${SERVICE_NAME}..."
|
|
run_remote_cmd "sudo systemctl restart ${SERVICE_NAME}"
|
|
sleep 2
|
|
|
|
echo "==> Smoke-testing public read endpoint..."
|
|
run_remote_cmd "curl -sf http://10.0.0.11:3023/www/tour/status -o /dev/null \
|
|
-w 'admin-api /www/tour/status HTTP %{http_code}\n' \
|
|
|| (echo 'FAIL — rolling back'; exit 7)"
|
|
|
|
echo ""
|
|
echo "✓ quinn.admin-api deployed to ${REMOTE} at $(date '+%Y-%m-%d %H:%M:%S %Z')"
|