From 2f9a789252ec91291948dd5a077c00d2e18e3271 Mon Sep 17 00:00:00 2001 From: Mike McDougall Date: Wed, 22 Jul 2026 12:18:35 -1000 Subject: [PATCH] docs: replace raw HTTP examples with supported clients --- .github/workflows/ci.yml | 3 ++ examples/async_feature_service/README.md | 11 +++--- scripts/check_docs_command_policy.py | 46 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 scripts/check_docs_command_policy.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 254767b..7c7405a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,9 @@ jobs: - name: Run Ruff run: ruff check . + - name: Enforce maintained documentation command policy + run: python scripts/check_docs_command_policy.py + - name: Verify generated sync clients are not stale # The synchronous clients (honua_sdk/client.py, honua_admin/_client.py) # are generated from their async source-of-truth by scripts/gen_sync.py diff --git a/examples/async_feature_service/README.md b/examples/async_feature_service/README.md index e27ae5f..48fd16f 100644 --- a/examples/async_feature_service/README.md +++ b/examples/async_feature_service/README.md @@ -48,14 +48,11 @@ The service reads the shared demo environment contract: ## Try the routes -```bash -# List catalog services -curl 'http://localhost:8000/services' +Open these URLs in a browser or an API client after starting the service: -# Query features (optionally filtered by attribute and/or bbox) -curl 'http://localhost:8000/features?where=1%3D1&limit=10' -curl 'http://localhost:8000/features?bbox=-158,21,-157,22' -``` +- list catalog services: +- query features by attribute: +- query features by bounding box: `bbox` is `minx,miny,maxx,maxy` in EPSG:4326. An invalid bbox returns HTTP 422. diff --git a/scripts/check_docs_command_policy.py b/scripts/check_docs_command_policy.py new file mode 100644 index 0000000..436df0a --- /dev/null +++ b/scripts/check_docs_command_policy.py @@ -0,0 +1,46 @@ +"""Reject unsupported raw HTTP command examples in maintained documentation.""" + +from __future__ import annotations + +import re +from pathlib import Path + + +ROOT = Path(__file__).resolve().parent.parent +DOC_ROOTS = (ROOT / "docs", ROOT / "examples", ROOT / "packages") +TOP_LEVEL_DOCS = (ROOT / "README.md", ROOT / "INSTALL.md", *ROOT.glob("llms*.txt")) +DOC_SUFFIXES = {".md", ".mdx", ".rst", ".txt"} +RAW_HTTP_COMMAND = re.compile(r"\bcurl(?:\.exe)?\b", re.IGNORECASE) + + +def maintained_docs() -> list[Path]: + files = [path for path in TOP_LEVEL_DOCS if path.is_file()] + for root in DOC_ROOTS: + if not root.exists(): + continue + files.extend( + path + for path in root.rglob("*") + if path.is_file() + and path.suffix.lower() in DOC_SUFFIXES + and path.name not in {"AGENTS.md", "CHANGELOG.md"} + ) + return sorted(set(files)) + + +def main() -> int: + violations: list[str] = [] + for path in maintained_docs(): + for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): + if RAW_HTTP_COMMAND.search(line): + violations.append(f"{path.relative_to(ROOT)}:{line_number}:{line.strip()}") + if violations: + print("Maintained documentation must use supported SDK, CLI, or API-reference workflows:") + print("\n".join(violations)) + return 1 + print("Maintained documentation command policy passed.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())