Files
serverAppConfigs/tests/homepage_config.bats
T
Frank 87721ab0fe rename frank-small → frank-secondary (Dankclaw llama.cpp :7771)
Cross-cutting rename of the current llama.cpp endpoint on the RTX 3090
(port 7771) from frank-small to frank-secondary:

- Service trio: scripts/{frank-small.env,frank-small.service,
  serve-frank-small.sh,download-frank-small.sh} → frank-secondary.*
- Test: tests/frank_small_unit.bats → tests/frank_secondary_unit.bats
- Runbooks: serverAppConfigs-docs/LLM/frank-small-*.md →
  frank-secondary-*.md (9 files); the FreeToken runbook stays
  freetoken-frank-small.md (it documents the retired CUDA-era service)
- Identifiers: FRANK_SMALL→FRANK_SECONDARY, llm_small→llm_secondary,
  LLM_SMALL_*→LLM_SECONDARY_*, deploy_llm_small→deploy_llm_secondary
- Historical references to the OLD frank-small (FreeToken/CUDA on the
  3090, and the Dankserver service that became frank-medium) are
  preserved verbatim — they describe what the service was called
  at the time.
2026-10-06 15:37:13 -07:00

80 lines
3.3 KiB
Bash

#!/usr/bin/env bats
# Seam: shared/homepage/services.json — the service config the checker reads
# and the pages render. It must be a JSON list; every entry carries name,
# category, section, and a host:port probe. category is user or admin;
# section must be one the page's SECTION_ORDER renders. method, when
# present, is tcp or http. wip, when set, is "open" or "closed".
load helpers
@test "services.json: valid schema" {
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
path = sys.argv[1]
try:
data = json.load(open(path))
except FileNotFoundError:
sys.exit("services.json not found")
assert isinstance(data, list), "top level must be a list"
assert data, "the list must not be empty"
for svc in data:
for field in ("name", "category", "section", "probe"):
assert field in svc, f"{svc.get('name', '?')} is missing {field}"
assert svc["category"] in ("user", "admin"), svc["category"]
if "method" in svc:
assert svc["method"] in ("tcp", "http"), svc["method"]
wip = svc.get("wip")
assert wip is False or wip in ("open", "closed"), f"{svc['name']} wip must be false, 'open' or 'closed'"
host, _, port = svc["probe"].rpartition(":")
assert host and port.isdigit(), f"bad probe {svc['probe']}"
PY
}
@test "services.json: every section is one the page renders" {
# A service whose section is not in app.js's SECTION_ORDER for its
# category is silently dropped from the page. Pin the contract.
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
data = json.load(open(sys.argv[1]))
allowed = {
"user": {"AI", "Web Apps", "Media Library Apps"},
"admin": {"Media Library Apps", "Observability", "AI", "Infrastructure"},
}
for svc in data:
assert svc.get("section") in allowed[svc["category"]], (
f"{svc['name']} has unrenderable section {svc.get('section')!r} for {svc['category']}")
PY
}
@test "services.json: every user service has an Open link, status-only backends do not" {
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
data = json.load(open(sys.argv[1]))
for svc in data:
show = svc.get("showLink", True)
if show:
assert svc.get("url"), f"{svc['name']} shows a link but has no url"
else:
assert not svc.get("url"), f"{svc['name']} is status-only but has a url"
PY
}
@test "the LLM status cards track the fleet, not retired service names" {
# This drifted twice: the card probing Dankserver's :7770 was still named
# frank-small long after frank-medium took that endpoint, and the endpoint
# itself has since been frank-medium (radiance), frank-primary (lucebox)
# and frank-primary (llama.cpp). The probe target is what matters; the
# name has to follow it.
python3 - "$REPO_ROOT/shared/homepage/services.json" <<'PY'
import json, sys
services = json.load(open(sys.argv[1]))
by_probe = {s["probe"]: s["name"] for s in services}
primary = by_probe.get("192.168.0.235:7770")
assert primary == "frank-primary", f"Dankserver :7770 card is named {primary!r}"
# Dankclaw serves two endpoints on two ports: frank-large (unsloth llama.cpp
# on the iGPU, 7770) and frank-secondary (llama.cpp on the RTX 3090, 7771).
assert by_probe.get("127.0.0.1:7770") == "frank-large", by_probe.get("127.0.0.1:7770")
assert by_probe.get("127.0.0.1:7771") == "frank-secondary", by_probe.get("127.0.0.1:7771")
PY
}