Core tests / core (push) Successful in 9m57s
Full verification / application (push) Failing after 5m16s
Full verification / local-brain (push) Failing after 6m15s
Realm simulation / simulated-live-world (push) Failing after 5m32s
WoW integration lab / real-worldserver (push) Canceled after 17m23s
Source branch: feature/ai-brain-router Source commit: c2a09e0460465201a58aaab56c71424e9a96405e
159 lines
5.6 KiB
Bash
159 lines
5.6 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
LAB_ROOT="${AZEROTHAI_PLAYABLE_ROOT:-$HOME/azerothai-pc-lab}"
|
|
DEV_PORT="${AZEROTHAI_REMOTE_UI_DEV_PORT:-5173}"
|
|
PROXY_PORT="${AZEROTHAI_TAILNET_PROXY_PORT:-8788}"
|
|
APP_PORT="${AZEROTHAI_APP_PORT:-8787}"
|
|
PID_FILE="$LAB_ROOT/azerothai-ui-dev.pid"
|
|
LOG_FILE="$LAB_ROOT/azerothai-ui-dev.log"
|
|
NGINX_SITE="/etc/nginx/sites-available/azerothai-tailnet"
|
|
NGINX_LINK="/etc/nginx/sites-enabled/azerothai-tailnet"
|
|
|
|
need(){ command -v "$1" >/dev/null 2>&1 || { echo "Missing required command: $1" >&2; exit 1; }; }
|
|
need curl
|
|
need tailscale
|
|
need pnpm
|
|
|
|
TAILSCALE_IP="$(tailscale ip -4 2>/dev/null | head -n1 || true)"
|
|
if [[ -z "$TAILSCALE_IP" ]]; then
|
|
echo "No active Tailscale IPv4 address found." >&2
|
|
exit 2
|
|
fi
|
|
DNS_NAME="$(tailscale status --json 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print((d.get("Self",{}).get("DNSName") or "").rstrip("."))' 2>/dev/null || true)"
|
|
|
|
echo "==> Rebuilding live AzerothAI backend with current source"
|
|
cd "$REPO_ROOT"
|
|
pnpm build
|
|
if [[ -f "$LAB_ROOT/azerothai.pid" ]]; then
|
|
OLD_APP_PID="$(cat "$LAB_ROOT/azerothai.pid" 2>/dev/null || true)"
|
|
if [[ -n "$OLD_APP_PID" ]]; then kill "$OLD_APP_PID" 2>/dev/null || true; fi
|
|
fi
|
|
pkill -f "wrangler.*8787" 2>/dev/null || true
|
|
pkill -f "pnpm.*start:lan" 2>/dev/null || true
|
|
sleep 2
|
|
nohup pnpm start:lan >"$LAB_ROOT/azerothai.log" 2>&1 &
|
|
echo $! > "$LAB_ROOT/azerothai.pid"
|
|
|
|
echo "==> Waiting for live AzerothAI backend"
|
|
for _ in {1..90}; do
|
|
if curl -fsS "http://127.0.0.1:$APP_PORT/api/health" >/dev/null 2>&1; then break; fi
|
|
sleep 1
|
|
done
|
|
curl -fsS "http://127.0.0.1:$APP_PORT/api/health" >/dev/null
|
|
|
|
echo "==> Restarting autonomous high-level service if this lab is configured"
|
|
RUNTIME_ENV="$LAB_ROOT/runtime.env"
|
|
if [[ -f "$RUNTIME_ENV" ]] && grep -q '^AUTONOMY_TOKEN=' "$RUNTIME_ENV"; then
|
|
bash "$REPO_ROOT/deploy/playable/install-autonomy-service.sh"
|
|
fi
|
|
|
|
echo "==> Ensuring durable ALE database relay is active"
|
|
if [[ -f "$RUNTIME_ENV" ]] && grep -q '^ALE_BRIDGE_TOKEN=' "$RUNTIME_ENV" && grep -q '^DOCKER_DB_ROOT_PASSWORD=' "$RUNTIME_ENV"; then
|
|
bash "$REPO_ROOT/deploy/playable/install-ale-relay-service.sh"
|
|
fi
|
|
|
|
echo "==> Starting hydration-safe dashboard UI"
|
|
mkdir -p "$LAB_ROOT"
|
|
if [[ -f "$PID_FILE" ]]; then
|
|
OLD_PID="$(cat "$PID_FILE" 2>/dev/null || true)"
|
|
if [[ -n "$OLD_PID" ]]; then kill "$OLD_PID" 2>/dev/null || true; fi
|
|
fi
|
|
pkill -f "vinext.*$DEV_PORT" 2>/dev/null || true
|
|
cd "$REPO_ROOT"
|
|
nohup pnpm dev >"$LOG_FILE" 2>&1 &
|
|
echo $! > "$PID_FILE"
|
|
|
|
for _ in {1..90}; do
|
|
if curl -fsS "http://127.0.0.1:$DEV_PORT/" >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if ! curl -fsS "http://127.0.0.1:$DEV_PORT/" >/dev/null 2>&1; then
|
|
echo "Dashboard UI dev server did not start." >&2
|
|
tail -80 "$LOG_FILE" >&2 || true
|
|
exit 3
|
|
fi
|
|
|
|
echo "==> Installing nginx if needed"
|
|
if ! command -v nginx >/dev/null 2>&1; then
|
|
sudo apt-get update
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y nginx
|
|
fi
|
|
|
|
echo "==> Wiring UI to the live AzerothAI API"
|
|
sudo tee "$NGINX_SITE" >/dev/null <<EOF
|
|
server {
|
|
listen 127.0.0.1:$PROXY_PORT;
|
|
server_name _;
|
|
|
|
location ^~ /api/ {
|
|
proxy_http_version 1.1;
|
|
proxy_buffering off;
|
|
proxy_cache off;
|
|
proxy_set_header Host \$http_host;
|
|
proxy_set_header X-Forwarded-Host \$http_host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_pass http://127.0.0.1:$APP_PORT;
|
|
add_header Cache-Control "no-store" always;
|
|
}
|
|
|
|
location / {
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host 127.0.0.1:$DEV_PORT;
|
|
proxy_set_header X-Forwarded-Host \$http_host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_pass http://127.0.0.1:$DEV_PORT;
|
|
add_header Cache-Control "no-store" always;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
sudo ln -sfn "$NGINX_SITE" "$NGINX_LINK"
|
|
sudo nginx -t
|
|
sudo systemctl enable --now nginx
|
|
sudo systemctl reload nginx
|
|
|
|
echo "==> Verifying dashboard and live API through proxy"
|
|
VERIFY_HOST="${DNS_NAME:-$TAILSCALE_IP}"
|
|
curl -fsS -H "Host: $VERIFY_HOST" "http://127.0.0.1:$PROXY_PORT/" >/dev/null
|
|
curl -fsS -H "Host: $VERIFY_HOST" "http://127.0.0.1:$PROXY_PORT/api/state" >/dev/null
|
|
ORIGIN="https://$VERIFY_HOST"
|
|
ACTION_BODY="$(mktemp)"
|
|
ACTION_CODE="$(curl -sS -o "$ACTION_BODY" -w '%{http_code}' -X POST -H "Host: $VERIFY_HOST" -H "Origin: $ORIGIN" -H "Content-Type: application/json" --data '{}' "http://127.0.0.1:$PROXY_PORT/api/actions" || true)"
|
|
if [[ "$ACTION_CODE" == "403" ]] && grep -q "Cross-origin action rejected" "$ACTION_BODY"; then
|
|
echo "Remote action origin check is still rejecting the trusted tailnet host." >&2
|
|
cat "$ACTION_BODY" >&2
|
|
rm -f "$ACTION_BODY"
|
|
exit 47
|
|
fi
|
|
rm -f "$ACTION_BODY"
|
|
echo "Remote action origin check: accepted (HTTP $ACTION_CODE expected for empty test action)"
|
|
|
|
echo "==> Publishing privately with Tailscale Serve"
|
|
sudo tailscale serve --bg "$PROXY_PORT"
|
|
|
|
STAMP="$(date +%s)"
|
|
|
|
echo
|
|
echo "============================================================"
|
|
echo " AzerothAI remote dashboard is ready"
|
|
echo "============================================================"
|
|
if [[ -n "$DNS_NAME" ]]; then
|
|
echo "Open this fresh URL:"
|
|
echo " https://$DNS_NAME/?v=$STAMP"
|
|
else
|
|
echo "Run: tailscale serve status"
|
|
fi
|
|
echo
|
|
echo "UI log: $LOG_FILE"
|
|
echo "Live API remains on port $APP_PORT."
|