gabriel / musehub public
check_app_imports.py python
60 lines 1.9 KB
Raw
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