179 lines
5.9 KiB
Bash
Executable File
179 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Verify the public installation and workspace documentation against the current topology.
|
|
set -euo pipefail
|
|
|
|
if [[ -n "${THT_DOCS_VERIFY_ROOT:-}" ]]; then
|
|
root="$(cd "$THT_DOCS_VERIFY_ROOT" && pwd -P)"
|
|
else
|
|
root="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
fi
|
|
|
|
fail() {
|
|
echo "verify-workspace-install-docs.sh: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
require_file() {
|
|
[[ -f "$root/$1" ]] || fail "missing required file: $1"
|
|
}
|
|
|
|
require_text() {
|
|
local path="$1" text="$2"
|
|
grep -Fq -- "$text" "$root/$path" || fail "$path must contain: $text"
|
|
}
|
|
|
|
forbid_text() {
|
|
local path="$1" text="$2"
|
|
if grep -Fq -- "$text" "$root/$path"; then
|
|
fail "$path retains obsolete reference: $text"
|
|
fi
|
|
}
|
|
|
|
verify_compose_topology() {
|
|
python3 - "$root/compose.yaml" <<'PY'
|
|
import pathlib
|
|
import sys
|
|
import yaml
|
|
|
|
compose = yaml.safe_load(pathlib.Path(sys.argv[1]).read_text())
|
|
expected = {
|
|
"catalog-db", "catalog-migrate", "core", "embedding", "embedding-model-init",
|
|
"frontend", "qdrant", "workspace-maintenance",
|
|
}
|
|
services = compose.get("services", {})
|
|
if set(services) != expected:
|
|
raise SystemExit(f"compose.yaml services mismatch: {sorted(services)}")
|
|
if services["catalog-migrate"].get("profiles") != ["catalog-maintenance"]:
|
|
raise SystemExit("catalog-migrate must remain an explicit catalog-maintenance operation")
|
|
if services["workspace-maintenance"].get("profiles") != ["workspace-maintenance"]:
|
|
raise SystemExit("workspace-maintenance must remain profile-gated")
|
|
if services["catalog-migrate"].get("depends_on", {}).get("catalog-db", {}).get("condition") != "service_healthy":
|
|
raise SystemExit("catalog-migrate must wait for healthy catalog-db")
|
|
PY
|
|
require_text scripts/run-stack.sh 'up -d catalog-db'
|
|
require_text scripts/run-stack.sh 'run --rm catalog-migrate'
|
|
echo "Compose topology contract passed"
|
|
}
|
|
|
|
verify_navigation() {
|
|
local path
|
|
for path in \
|
|
install/first-start.md \
|
|
install/standalone-manual-it.md \
|
|
install/standalone-manual-en.md \
|
|
operations/workspaces.md \
|
|
operations/database-management.md \
|
|
guida-utente.md \
|
|
product-overview.md \
|
|
install/shell-and-language.md; do
|
|
require_file "docs/$path"
|
|
require_text mkdocs.yml "$path"
|
|
done
|
|
echo "Current documentation navigation contract passed"
|
|
}
|
|
|
|
verify_standalone_installation_guides() {
|
|
for guide in docs/install/standalone-manual-it.md docs/install/standalone-manual-en.md; do
|
|
require_file "$guide"
|
|
for text in \
|
|
'git clone https://git.tylconsulting.it/mptyl/ThothII.git' \
|
|
'scripts/check-standalone-prerequisites.sh' \
|
|
'scripts/install-tht.sh' \
|
|
'tht setup --profile local --shell-mode full --shell-default-locale en' \
|
|
'scripts/verify-standalone-install.sh' \
|
|
'Docker Hub' \
|
|
'Gate A' \
|
|
'Gate B'; do
|
|
require_text "$guide" "$text"
|
|
done
|
|
done
|
|
require_file scripts/check-standalone-prerequisites.sh
|
|
require_file scripts/verify-standalone-install.sh
|
|
echo "Manual standalone installation guides contract passed"
|
|
}
|
|
|
|
verify_install_and_workspace_guides() {
|
|
local install='docs/install/first-start.md'
|
|
local workspace='docs/operations/workspaces.md'
|
|
require_file "$install"
|
|
require_file "$workspace"
|
|
|
|
for text in \
|
|
'tht setup --profile local' \
|
|
'--configure-only' \
|
|
'catalog-migrate' \
|
|
'tht --installation /absolute/path/thothii-installation.yaml doctor --json'; do
|
|
require_text "$install" "$text"
|
|
done
|
|
for text in \
|
|
'workspace inspect' \
|
|
'workspace preprocess run' \
|
|
'database in **Database Management**' \
|
|
'write-only runtime secrets' \
|
|
'Runtime sessions support direct PostgreSQL and REST bindings.'; do
|
|
require_text "$workspace" "$text"
|
|
done
|
|
|
|
for obsolete in \
|
|
'docs/install/local-workspace-registry.md' \
|
|
'docs/install/server-workspace-registry.md' \
|
|
'docs/install/local.md' \
|
|
'docs/install/server.md'; do
|
|
forbid_text README.md "$obsolete"
|
|
forbid_text "$install" "$obsolete"
|
|
forbid_text "$workspace" "$obsolete"
|
|
done
|
|
echo "Local installation and workspace operations contract passed"
|
|
}
|
|
|
|
verify_examples() {
|
|
require_file docs/install/examples/thothii-installation.local.yaml
|
|
require_file docs/install/examples/thothii-installation.server.yaml
|
|
require_file docs/install/examples/workspace-bindings.env.example
|
|
python3 - "$root/docs/install/examples/thothii-installation.local.yaml" \
|
|
"$root/docs/install/examples/thothii-installation.server.yaml" \
|
|
"$root/docs/install/examples/workspace-bindings.env.example" <<'PY'
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
import yaml
|
|
|
|
local = yaml.safe_load(pathlib.Path(sys.argv[1]).read_text())
|
|
server = yaml.safe_load(pathlib.Path(sys.argv[2]).read_text())
|
|
bindings = pathlib.Path(sys.argv[3]).read_text()
|
|
if local.get("profile") != "local" or server.get("profile") != "server":
|
|
raise SystemExit("installation examples must retain their local/server profiles")
|
|
for document in (local, server):
|
|
catalog = document.get("modelCatalog")
|
|
if not isinstance(catalog, dict) or "providers" not in catalog or "authentication" not in document:
|
|
raise SystemExit("installation example lacks model catalog or authentication configuration")
|
|
if re.search(r"(?:KEY|PASSWORD|TOKEN|SECRET)=[^\n#<][^\n]*", bindings):
|
|
raise SystemExit("workspace bindings example contains a secret value")
|
|
PY
|
|
echo "Installation examples contract passed"
|
|
}
|
|
|
|
verify_all() {
|
|
verify_compose_topology
|
|
verify_navigation
|
|
verify_standalone_installation_guides
|
|
verify_install_and_workspace_guides
|
|
verify_examples
|
|
}
|
|
|
|
case "${1:-}" in
|
|
--fixtures-only)
|
|
[[ $# -eq 1 ]] || fail 'usage: verify-workspace-install-docs.sh --fixtures-only | --profile {local|server}'
|
|
verify_all
|
|
;;
|
|
--profile)
|
|
[[ $# -eq 2 && "${2:-}" =~ ^(local|server)$ ]] \
|
|
|| fail 'usage: verify-workspace-install-docs.sh --fixtures-only | --profile {local|server}'
|
|
verify_all
|
|
echo "$2 installation documentation verification passed"
|
|
;;
|
|
*)
|
|
fail 'usage: verify-workspace-install-docs.sh --fixtures-only | --profile {local|server}'
|
|
;;
|
|
esac
|