71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
"""
|
|
B0.3.3 — export the API contract.
|
|
|
|
Writes openapi.json at the repository root. It is committed, and CI fails when
|
|
the exported document differs from the committed one, so a change to a request
|
|
or response shape has to be admitted in a diff rather than discovered by the
|
|
frontend at runtime.
|
|
|
|
APP_ENV=rework_test python scripts/export_openapi.py # write
|
|
APP_ENV=rework_test python scripts/export_openapi.py --check # verify
|
|
|
|
The contract is exported now, at 31% `response_model` coverage, rather than
|
|
after B0.3.1/B0.3.2 fill the remaining 166. An incomplete contract that cannot
|
|
silently change is worth considerably more than a complete one that arrives in
|
|
three weeks, and every endpoint that gains a `response_model` shows up as a diff
|
|
here — which makes progress visible instead of merely claimed.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
os.environ.setdefault("APP_ENV", "rework_test")
|
|
os.environ.setdefault("PYTHONIOENCODING", "utf-8")
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
OUTPUT = Path(__file__).parent.parent / "openapi.json"
|
|
|
|
|
|
def build() -> str:
|
|
from app.main import app
|
|
|
|
schema = app.openapi()
|
|
# sort_keys so the file is diffable: FastAPI does not guarantee key order,
|
|
# and an unordered dump would churn on every export.
|
|
return json.dumps(schema, indent=2, sort_keys=True, ensure_ascii=False) + "\n"
|
|
|
|
|
|
def main() -> int:
|
|
generated = build()
|
|
check = "--check" in sys.argv
|
|
|
|
if check:
|
|
if not OUTPUT.exists():
|
|
print("openapi.json is missing. Run scripts/export_openapi.py", file=sys.stderr)
|
|
return 1
|
|
committed = OUTPUT.read_text(encoding="utf-8")
|
|
if committed != generated:
|
|
print(
|
|
"openapi.json is stale — the API has changed since it was exported.\n"
|
|
"Regenerate and commit the diff:\n"
|
|
" APP_ENV=rework_test python scripts/export_openapi.py",
|
|
file=sys.stderr,
|
|
)
|
|
return 1
|
|
print("openapi.json is current")
|
|
return 0
|
|
|
|
OUTPUT.write_text(generated, encoding="utf-8")
|
|
schema = json.loads(generated)
|
|
print(f"wrote {OUTPUT.name}")
|
|
print(f" paths {len(schema.get('paths', {}))}")
|
|
print(f" schemas {len(schema.get('components', {}).get('schemas', {}))}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|