main.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from contextlib import asynccontextmanager
  2. from typing import Any
  3. from fastapi import FastAPI, HTTPException, Request
  4. from fastapi.middleware.cors import CORSMiddleware
  5. from .host_client import HostApiError, HostClient
  6. from .journey import build_journey
  7. from .models import JourneyView, RunSummary
  8. host = HostClient()
  9. @asynccontextmanager
  10. async def lifespan(_app: FastAPI):
  11. yield
  12. close = getattr(host, "aclose", None)
  13. if close is not None:
  14. await close()
  15. app = FastAPI(title="Script Build Journey", version="0.1.0", lifespan=lifespan)
  16. app.add_middleware(
  17. CORSMiddleware,
  18. allow_origins=["http://127.0.0.1:3008", "http://localhost:3008"],
  19. allow_credentials=True,
  20. allow_methods=["GET"],
  21. allow_headers=["*"],
  22. )
  23. @app.get("/api/health")
  24. def health() -> dict[str, str]:
  25. return {
  26. "status": "ok",
  27. "service": "script-build-journey",
  28. }
  29. @app.get("/api/runs", response_model=list[RunSummary])
  30. async def runs(request: Request) -> list[RunSummary]:
  31. payload = await _host_call(host.list_runs(request.headers))
  32. return [
  33. RunSummary(
  34. script_build_id=int(item["id"]),
  35. status=str(item.get("status") or "unknown"),
  36. summary=str(item.get("summary") or f"Script Build {item['id']}"),
  37. started_at=item.get("start_time"),
  38. completed_at=item.get("end_time"),
  39. )
  40. for item in payload.get("items") or []
  41. if isinstance(item, dict) and item.get("id") is not None
  42. ]
  43. @app.get("/api/runs/{script_build_id}/journey", response_model=JourneyView)
  44. async def journey(script_build_id: int, request: Request) -> JourneyView:
  45. source = await _host_call(host.journey_source(script_build_id, request.headers))
  46. return build_journey(script_build_id, source)
  47. @app.get("/api/runs/{script_build_id}/artifacts/{artifact_version_id}")
  48. async def artifact(
  49. script_build_id: int, artifact_version_id: int, request: Request
  50. ) -> dict[str, Any]:
  51. return await _host_call(host.artifact(script_build_id, artifact_version_id, request.headers))
  52. async def _host_call(awaitable: Any) -> dict[str, Any]:
  53. try:
  54. value = await awaitable
  55. except HostApiError as exc:
  56. raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc
  57. return value