hugin/scripts/demo.sh

121 lines
6.2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Startet Hugin lokal mit Beispieldaten zum Ausprobieren.
#
# scripts/demo.sh # Server auf http://127.0.0.1:8080, Daten in .demo/
# scripts/demo.sh --neu # Beispieldaten verwerfen und neu anlegen
# HOST=0.0.0.0 scripts/demo.sh # auch von anderen Rechnern erreichbar (z. B. Windows-Test)
# HUGIN_DATABASE_URL=postgresql+psycopg://hugin:hugin@127.0.0.1:55432/hugin scripts/demo.sh
# # mit der PostgreSQL aus docker-compose.yml
#
# Beim ersten Start legt das Skript Tenants, Projekte, Personen und Keys an,
# veröffentlicht die Beispielpakete und schreibt alle Keys nach .demo/keys.txt.
set -euo pipefail
RESET=""
case "${1:-}" in
"") ;;
--neu|--new) RESET=1 ;;
*) echo "Unbekannt: $1 (erlaubt: --neu)"; exit 2 ;;
esac
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DEMO="$ROOT/.demo"
PORT="${PORT:-8080}"
URL="http://127.0.0.1:$PORT"
mkdir -p "$DEMO"
if [[ -n "${HUGIN_DATABASE_URL:-}" ]]; then
# Eigene Datenbank (z. B. PostgreSQL): die Keys gehören zu dieser Datenbank
KEYS="$DEMO/keys-$(printf '%s' "$HUGIN_DATABASE_URL" | shasum | cut -c1-8).txt"
if [[ -n "$RESET" ]]; then
echo "--neu mit eigener Datenbank: Daten dort selbst löschen, z. B. docker compose down -v"; exit 2
fi
else
# Nur die SQLite-Demo verwerfen; Keys anderer Datenbanken (keys-*.txt) bleiben
[[ -n "$RESET" ]] && rm -f "$DEMO"/hugin.db* "$DEMO/keys.txt" "$DEMO/server.log"
export HUGIN_DATABASE_URL="sqlite:///$DEMO/hugin.db"
KEYS="$DEMO/keys.txt"
fi
export HUGIN_ADMIN_TOKEN="${HUGIN_ADMIN_TOKEN:-demo-admin}"
ADMIN=(-H "Authorization: Bearer $HUGIN_ADMIN_TOKEN")
if ! (cd "$ROOT/server" && uv run -q hugin-server migrate 2>"$DEMO/migrate.log"); then
tail -1 "$DEMO/migrate.log"
echo "Migration gescheitert; die Datenbank stammt vermutlich von einem älteren Stand (ganzer Fehler: $DEMO/migrate.log)."
echo "Neu anlegen: bei SQLite 'scripts/demo.sh --neu',"
echo "bei PostgreSQL aus docker-compose.yml 'docker compose down -v && docker compose up -d'."
exit 1
fi
if [[ -f "$KEYS" ]]; then
echo "Beispieldaten vorhanden (.demo/). Keys: $KEYS"
else
(cd "$ROOT/server" && exec uv run -q hugin-server run --host "${HOST:-127.0.0.1}" --port "$PORT") >"$DEMO/server.log" 2>&1 &
SERVER=$!
trap 'kill $SERVER 2>/dev/null; wait $SERVER 2>/dev/null || true' EXIT
for _ in $(seq 60); do curl -fsS "$URL/readyz" >/dev/null 2>&1 && break; sleep 0.25; done
if curl -fsS "${ADMIN[@]}" "$URL/api/v1/admin/tenants" 2>/dev/null | grep -q '"plattform"'; then
echo "Die Datenbank enthält schon Demo-Daten, aber die Keys dazu fehlen ($KEYS)."
echo "Neu anlegen: bei PostgreSQL aus docker-compose.yml 'docker compose down -v && docker compose up -d',"
echo "bei SQLite 'scripts/demo.sh --neu'."
exit 1
fi
api() { curl -fsS -H "Content-Type: application/json" "$@"; }
field() { python3 -c "import json,sys; print(json.load(sys.stdin)['$1'])"; }
for t in plattform:kern shop:api shop:web; do
api "${ADMIN[@]}" "$URL/api/v1/admin/tenants" -d "{\"slug\":\"${t%%:*}\",\"name\":\"${t%%:*}\"}" >/dev/null 2>&1 || true
api "${ADMIN[@]}" "$URL/api/v1/admin/tenants/${t%%:*}/projects" -d "{\"slug\":\"${t##*:}\",\"name\":\"${t##*:}\"}" >/dev/null
done
person() { api "${ADMIN[@]}" "$URL/api/v1/admin/tenants/$1/people" -d "$2" | field key; }
key() { api "${ADMIN[@]}" "$URL/api/v1/admin/tenants/$1/keys" -d "$2" | field key; }
AUTHOR=$(person plattform '{"name":"Autor","mail":"autor@firma.de","project":"kern","roles":["pub_author"]}')
REVIEWER=$(person plattform '{"name":"Prüfer","mail":"pruefer@firma.de","roles":["pub_reviewer"]}')
REVIEWER2=$(person plattform '{"name":"Prüfer 2","mail":"pruefer2@firma.de","roles":["pub_reviewer"]}')
ADMIN_PERSON=$(person plattform '{"name":"Admin","mail":"admin@firma.de","roles":["pub_reviewer","tenant_admin"]}')
SHOP_ADMIN=$(key shop '{"kind":"tenant","name":"Shop-Admin"}')
SHOP_CI=$(key shop '{"kind":"project","name":"Shop CI","project":"api"}')
SHOP_INT=$(key shop '{"kind":"integration","name":"Softwareverteilung"}')
publish() {
local zip="$DEMO/package.zip"
rm -f "$zip"; (cd "$ROOT/contract/examples/packages/$1" && zip -qr "$zip" .)
curl -fsS -H "Authorization: Bearer $AUTHOR" -H "Content-Type: application/zip" --data-binary "@$zip" "$URL/api/v1/drafts" >/dev/null
local base="$URL/api/v1/packages/${1%/*}/versions/${1#*/}"
api -H "Authorization: Bearer $AUTHOR" -X POST "$base/submit" >/dev/null
[[ "${2:-}" == "open" ]] || api -H "Authorization: Bearer $REVIEWER" "$base/approve" -d '{"comment":"Demo"}' >/dev/null
}
for p in pub-munin-nutzen/1.4.0 pub-hausregeln/1.0.0 pub-munin-anbindung/1.0.0 pub-release-notiz/1.0.0 pub-code-review/1.0.0; do
publish "$p"
done
# Pakete für den Alltag: Skills, Befehle und Subagenten zum Ausprobieren
for p in pub-schlank pub-doku-schreiben pub-grill-me pub-fehlersuche pub-erklaeren pub-plan pub-commit-text \
pub-recherche pub-doku-pruefer pub-sicherheits-review; do
publish "$p/1.0.0"
done
publish pub-munin-nutzen/1.5.0 open # liegt bei den Prüfungen
curl -fsS "${ADMIN[@]}" -X PUT -H "Content-Type: application/json" "$URL/api/v1/admin/mandatory/pub-munin-anbindung" -d '{"tenant":null}'
api -H "Authorization: Bearer $SHOP_CI" "$URL/api/v1/usage" \
-d '{"repo":"git.intern/shop/api","tools":{"claude":"2.1.302","opencode":"1.15.4"},"installed":{"pub-munin-nutzen":"1.4.0","pub-hausregeln":"1.0.0"}}' >/dev/null
cat > "$KEYS" <<EOF
Hugin-Demo — Keys zum Anmelden unter $URL
(nur für diese lokale Demo; .demo/ löschen oder scripts/demo.sh --neu)
Plattform-Admin (alles, System) $HUGIN_ADMIN_TOKEN
Autor (pub_author, Person) $AUTHOR
Prüfer (pub_reviewer, Person) $REVIEWER
Prüfer 2 (pub_reviewer, Person) $REVIEWER2
Admin (Prüfer + Tenant-Admin, Person) $ADMIN_PERSON
Shop-Admin (Tenant shop) $SHOP_ADMIN
Shop CI (Projekt shop/api, lesen) $SHOP_CI
Softwareverteilung (Integration shop) $SHOP_INT
EOF
kill $SERVER 2>/dev/null; wait $SERVER 2>/dev/null || true
trap - EXIT
fi
cat "$KEYS"
echo
echo "Weboberfläche: $URL API-Doku: $URL/api/docs MCP: $URL/mcp"
echo "Beenden mit Strg+C."
cd "$ROOT/server" && exec uv run -q hugin-server run --host "${HOST:-127.0.0.1}" --port "$PORT"