Files
storyforge/scripts/smoke_fnos_storyforge_lan.sh
kris 53b1854c21
Some checks failed
StoryForge CI / Baseline checks (push) Has been cancelled
StoryForge CI / Backend tests (push) Has been cancelled
StoryForge CI / Web tests (push) Has been cancelled
feat: tighten main agent execution traceability
2026-04-04 06:23:17 +08:00

129 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
FNOS_HOST="${FNOS_HOST:-192.168.31.188}"
WEB_PORT="${STORYFORGE_WEB_V4_DEV_PORT:-19192}"
COLLECTOR_PORT="${STORYFORGE_COLLECTOR_DEV_PORT:-19193}"
CUTVIDEO_FORWARD_PORT="${CUTVIDEO_FORWARD_PORT:-19186}"
STORYFORGE_COMPAT_FORWARD_PORT="${STORYFORGE_COMPAT_FORWARD_PORT:-19181}"
WEB_URL="${STORYFORGE_FNOS_WEB_URL:-http://$FNOS_HOST:$WEB_PORT}"
BACKEND_URL="${STORYFORGE_FNOS_COLLECTOR_URL:-http://$FNOS_HOST:$COLLECTOR_PORT}"
CUTVIDEO_URL="${CUTVIDEO_BASE_URL:-http://$FNOS_HOST:$CUTVIDEO_FORWARD_PORT}"
COMPAT_URL="${STORYFORGE_COMPAT_BASE_URL:-http://$FNOS_HOST:$STORYFORGE_COMPAT_FORWARD_PORT}"
CURL_MAX_TIME="${STORYFORGE_FNOS_CURL_MAX_TIME:-60}"
need_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "missing required command: $1" >&2
exit 1
fi
}
need_cmd curl
need_cmd python3
need_cmd rg
curl_fetch() {
curl -fsS --max-time "$CURL_MAX_TIME" "$@"
}
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
index_file="$tmp_dir/index.html"
runtime_file="$tmp_dir/runtime.js"
health_file="$tmp_dir/health.json"
session_file="$tmp_dir/session.json"
integrations_file="$tmp_dir/integrations.json"
bootstrap_file="$tmp_dir/bootstrap.json"
compat_file="$tmp_dir/compat.html"
token_file="$tmp_dir/token.txt"
echo "[1/6] check fnOS web"
curl_fetch "$WEB_URL/" >"$index_file"
rg -Fq "StoryForge" "$index_file"
echo "web ok"
echo "[2/6] check runtime config"
curl_fetch "$WEB_URL/assets/storyforge-runtime-config.js" >"$runtime_file"
rg -Fq "$BACKEND_URL" "$runtime_file"
echo "runtime config ok"
echo "[3/6] check collector healthz"
curl_fetch "$BACKEND_URL/healthz" >"$health_file"
python3 -c '
import json, pathlib, sys
payload = json.loads(pathlib.Path(sys.argv[1]).read_text())
expected_cutvideo = sys.argv[2]
if str(payload.get("status") or "").lower() != "ok":
raise SystemExit(f"unexpected health status: {payload.get('status')!r}")
lan_routing = payload.get("lanRouting") or {}
if not isinstance(lan_routing, dict):
raise SystemExit("lanRouting missing")
if lan_routing.get("cutvideoBaseUrl") != expected_cutvideo:
raise SystemExit(f"unexpected cutvideoBaseUrl: {lan_routing.get('cutvideoBaseUrl')!r}")
if lan_routing.get("cutvideoRouteMode") != "fnos_tunnel":
raise SystemExit(f"unexpected cutvideoRouteMode: {lan_routing.get('cutvideoRouteMode')!r}")
print("healthz ok")
' "$health_file" "$CUTVIDEO_URL"
echo "[4/6] check auto-session"
curl_fetch -X POST "$BACKEND_URL/v2/auth/auto-session" \
-H 'content-type: application/json' \
-d '{}' >"$session_file"
python3 -c '
import json, pathlib, sys
payload = json.loads(pathlib.Path(sys.argv[1]).read_text())
token = str(payload.get("token") or "")
mode = str(payload.get("mode") or "")
username = str((payload.get("account") or {}).get("username") or "")
if not token:
raise SystemExit("auto-session did not return token")
if mode != "auto":
raise SystemExit(f"unexpected mode: {mode!r}")
if not username:
raise SystemExit("auto-session returned empty username")
pathlib.Path(sys.argv[2]).write_text(token, encoding="utf-8")
print(f"auto-session ok: {username}")
' "$session_file" "$token_file"
token="$(cat "$token_file")"
echo "[5/6] check integrations health"
curl_fetch "$BACKEND_URL/v2/integrations/health" \
-H "Authorization: Bearer $token" >"$integrations_file"
python3 -c '
import json, pathlib, sys
payload = json.loads(pathlib.Path(sys.argv[1]).read_text())
expected_cutvideo = sys.argv[2]
cutvideo = payload.get("cutvideo") or {}
if cutvideo.get("base_url") != expected_cutvideo:
raise SystemExit(f"unexpected cutvideo base_url: {cutvideo.get('base_url')!r}")
if not cutvideo.get("reachable"):
raise SystemExit("cutvideo is not reachable")
if not cutvideo.get("supports_uploads"):
raise SystemExit("cutvideo uploads are not available")
print("integrations ok")
' "$integrations_file" "$CUTVIDEO_URL"
echo "[6/6] check fnOS tunnel endpoints"
curl_fetch "$CUTVIDEO_URL/api/bootstrap" >"$bootstrap_file"
curl_fetch "$COMPAT_URL/" >"$compat_file"
python3 -c '
import json, pathlib, sys
payload = json.loads(pathlib.Path(sys.argv[1]).read_text())
if not payload:
raise SystemExit("empty cutvideo bootstrap payload")
print("cutvideo bootstrap ok")
' "$bootstrap_file"
if ! rg -Fq "数字人网页业务台" "$compat_file" && ! rg -Fq "BUSINESS CONSOLE" "$compat_file"; then
echo "compat page does not look like the expected business console" >&2
exit 1
fi
echo "compat ok"
echo "fnOS lan smoke passed:"
echo " web: $WEB_URL/"
echo " collector: $BACKEND_URL"
echo " cutvideo: $CUTVIDEO_URL"
echo " compat: $COMPAT_URL"