diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 987377d..6493bab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,3 +26,23 @@ jobs: # since tests/overlay/conftest.py deliberately fails rather than skips # when the vectors are missing and CI is set. - run: pytest --tb=short -q --ignore=tests/overlay + + # The committed spec bootstraps the Kong gateway config, but nothing + # regenerated or verified it — it had rotted back to the pre-v1 API + # (84 paths, zero /v1) before #115. Generation is deterministic and + # independent of these paths; they only satisfy import-time reads. + - name: OpenAPI drift check + env: + PROJECT_ROOT_DIR: ${{ github.workspace }} + API_BACKEND_WWWAPP_PLAYBOOKS_DIR: ${{ github.workspace }} + API_BACKEND_PUBLIC_PLAYBOOKS_DIR: ${{ github.workspace }} + API_BACKEND_INVENTORY_DIR: ${{ github.workspace }}/inventory + PYTHONPATH: ${{ github.workspace }} + run: | + python -c " + import json + from app.main import create_app + print(json.dumps(create_app().openapi(), indent=2)) + " > /tmp/openapi.check.json + diff -u openapi.json /tmp/openapi.check.json \ + || { echo "::error::openapi.json is out of date — regenerate it (see README) and commit"; exit 1; } diff --git a/README.md b/README.md index f79edd8..11de1c3 100644 --- a/README.md +++ b/README.md @@ -139,9 +139,13 @@ VAULT_PASSWORD_FILE=/run/secrets/vault_pass docker compose up ### OpenAPI spec -The committed `openapi.json` at the repository root reflects the current API surface. It is used to bootstrap the Kong API gateway configuration. To regenerate it after adding or modifying routes: +The committed `openapi.json` at the repository root reflects the current API surface. It is used to bootstrap the Kong API gateway configuration, and **CI fails if it is out of date** — regenerate and commit it whenever you add or modify a route: ```bash +PROJECT_ROOT_DIR=$PWD \ +API_BACKEND_WWWAPP_PLAYBOOKS_DIR=$PWD \ +API_BACKEND_PUBLIC_PLAYBOOKS_DIR=$PWD \ +API_BACKEND_INVENTORY_DIR=$PWD/inventory \ PYTHONPATH=. python -c " import json from app.main import create_app @@ -149,6 +153,8 @@ print(json.dumps(create_app().openapi(), indent=2)) " > openapi.json ``` +The environment variables are only there to satisfy import-time reads — several route modules resolve paths at module scope, so the command dies without them. The generated document does not depend on their values. + --- ## Configuration