check_app_imports.py
python
sha256:f65847c6a4ae29872f3ccbc2420f91a8948949b84a06320bdaf2ac281c89ff8a
docs(F7b): governance sync — BUILT awaiting Gabriel; carry …
Human
patch
30 days ago
| 1 | """Prove the FastAPI application imports cleanly with declared dependencies only. |
| 2 | |
| 3 | Why this exists |
| 4 | --------------- |
| 5 | ``feat/kd-6b`` added ``Form(...)`` parameters to |
| 6 | ``musehub/api/routes/musehub/ui_vault.py`` without declaring ``python-multipart`` |
| 7 | in ``requirements.txt`` or ``pyproject.toml``. FastAPI validates form |
| 8 | dependencies while the route decorator runs, so the failure is an ``ImportError`` |
| 9 | at module import — the whole app refuses to start, for every repo, not just |
| 10 | knowtation-domain ones (issue #169). |
| 11 | |
| 12 | Importing the app is the cheapest possible proof that no route module has an |
| 13 | undeclared dependency or an import-time contract error. It runs without Postgres |
| 14 | because database work happens in the lifespan handler, not at import. |
| 15 | |
| 16 | Exit codes |
| 17 | ---------- |
| 18 | ``0`` |
| 19 | ``musehub.main:app`` imported. Emits ``ARTIFACT_SHA256`` over the app title, |
| 20 | version, and route count for L1 evidence. |
| 21 | ``1`` |
| 22 | Import failed — the app would not start. |
| 23 | """ |
| 24 | |
| 25 | from __future__ import annotations |
| 26 | |
| 27 | import hashlib |
| 28 | import json |
| 29 | import sys |
| 30 | import traceback |
| 31 | |
| 32 | |
| 33 | def main() -> int: |
| 34 | try: |
| 35 | from musehub.main import app |
| 36 | except Exception: # noqa: BLE001 — the failure text is the finding |
| 37 | print("FAIL: musehub.main:app does not import", file=sys.stderr) |
| 38 | traceback.print_exc() |
| 39 | print( |
| 40 | "\nCheck for a route using Form(...)/File(...) without python-multipart " |
| 41 | "declared, or any other undeclared import-time dependency.", |
| 42 | file=sys.stderr, |
| 43 | ) |
| 44 | return 1 |
| 45 | |
| 46 | identity = { |
| 47 | "title": getattr(app, "title", None), |
| 48 | "version": getattr(app, "version", None), |
| 49 | "route_count": len(app.routes), |
| 50 | } |
| 51 | digest = hashlib.sha256( |
| 52 | json.dumps(identity, sort_keys=True).encode("utf-8") |
| 53 | ).hexdigest() |
| 54 | print(f"OK: app imported ({identity['route_count']} routes)") |
| 55 | print(f"ARTIFACT_SHA256={digest}") |
| 56 | return 0 |
| 57 | |
| 58 | |
| 59 | if __name__ == "__main__": |
| 60 | sys.exit(main()) |
File History
1 commit
sha256:f65847c6a4ae29872f3ccbc2420f91a8948949b84a06320bdaf2ac281c89ff8a
docs(F7b): governance sync — BUILT awaiting Gabriel; carry …
Human
patch
30 days ago