|
18 | 18 | import uuid as _uuid_module |
19 | 19 | from uuid import UUID |
20 | 20 |
|
21 | | -from fastapi import APIRouter, Depends, HTTPException, Request, Response, status |
| 21 | +from fastapi import APIRouter, Depends, HTTPException, Query, Request, Response, status |
22 | 22 | from sqlalchemy.ext.asyncio import AsyncSession |
23 | 23 | from streaming_form_data import StreamingFormDataParser |
24 | 24 | from streaming_form_data.targets import FileTarget, ValueTarget |
|
30 | 30 | from app.config import settings |
31 | 31 | from app.crud.audit_log import write_audit |
32 | 32 | from app.crud.external_case_artifacts import create_artifact |
33 | | -from app.crud.external_case_results import create_case_result, get_case_result, update_case_result |
34 | | -from app.crud.external_results import create_session, finish_session_db, get_session |
| 33 | +from app.crud.external_case_results import ( |
| 34 | + create_case_result, |
| 35 | + get_case_result, |
| 36 | + list_case_results_for_session, |
| 37 | + update_case_result, |
| 38 | +) |
| 39 | +from app.crud.external_results import create_session, finish_session_db, get_session, list_sessions |
35 | 40 | from app.db.session import get_db |
36 | 41 | from app.models.external_case_artifact import ArtifactKind |
37 | 42 | from app.models.runner_token import RunnerToken |
38 | 43 | from app.schemas.external_results import ( |
39 | 44 | ArtifactResponse, |
40 | 45 | CaseResultCreate, |
| 46 | + CaseResultListResponse, |
41 | 47 | CaseResultResponse, |
42 | 48 | CaseResultUpdate, |
| 49 | + RunStatus, |
43 | 50 | SessionCreate, |
44 | 51 | SessionFinish, |
| 52 | + SessionListResponse, |
45 | 53 | SessionResponse, |
46 | 54 | ) |
47 | 55 | from app.storage import get_storage |
@@ -103,8 +111,9 @@ def _session_to_response(session) -> SessionResponse: |
103 | 111 | project_id=session.project_id, |
104 | 112 | git_sha=session.git_sha, |
105 | 113 | git_branch=session.git_branch, |
106 | | - ci_url=session.ci_url, |
| 114 | + ci_url=str(session.ci_url) if session.ci_url else None, |
107 | 115 | metadata=session.run_metadata or {}, |
| 116 | + summary=session.summary or {}, |
108 | 117 | ) |
109 | 118 |
|
110 | 119 |
|
@@ -248,6 +257,28 @@ async def get_external_session( |
248 | 257 | return _session_to_response(session) |
249 | 258 |
|
250 | 259 |
|
| 260 | +@router.get( |
| 261 | + "/external-results/sessions", |
| 262 | + response_model=SessionListResponse, |
| 263 | +) |
| 264 | +async def list_external_sessions( |
| 265 | + project_id: UUID | None = Query(None), |
| 266 | + status: RunStatus | None = Query(None), |
| 267 | + skip: int = Query(0, ge=0), |
| 268 | + limit: int = Query(25, ge=1, le=100), |
| 269 | + db: AsyncSession = Depends(get_db), |
| 270 | + _auth=Depends(get_runner_or_user_auth), |
| 271 | +) -> SessionListResponse: |
| 272 | + """Return a paginated list of sessions, newest first.""" |
| 273 | + sessions, total = await list_sessions(db, project_id=project_id, status=status, skip=skip, limit=limit) |
| 274 | + return SessionListResponse( |
| 275 | + sessions=[_session_to_response(s) for s in sessions], |
| 276 | + total=total, |
| 277 | + skip=skip, |
| 278 | + limit=limit, |
| 279 | + ) |
| 280 | + |
| 281 | + |
251 | 282 | # --------------------------------------------------------------------------- |
252 | 283 | # POST /external-results/case — create a case result |
253 | 284 | # --------------------------------------------------------------------------- |
@@ -416,6 +447,33 @@ async def get_external_case_result( |
416 | 447 | return _case_result_to_response(case_result) |
417 | 448 |
|
418 | 449 |
|
| 450 | +@router.get( |
| 451 | + "/external-results/session/{session_id}/cases", |
| 452 | + response_model=CaseResultListResponse, |
| 453 | +) |
| 454 | +async def list_external_session_cases( |
| 455 | + session_id: UUID, |
| 456 | + skip: int = Query(0, ge=0), |
| 457 | + limit: int = Query(200, ge=1, le=500), |
| 458 | + db: AsyncSession = Depends(get_db), |
| 459 | + _auth=Depends(get_runner_or_user_auth), |
| 460 | +) -> CaseResultListResponse: |
| 461 | + """Return all case results for a given session.""" |
| 462 | + session = await get_session(db, session_id) |
| 463 | + if session is None: |
| 464 | + raise HTTPException( |
| 465 | + status_code=status.HTTP_404_NOT_FOUND, |
| 466 | + detail={"code": "session.not_found", "message": f"Session {session_id} does not exist.", "details": None}, |
| 467 | + ) |
| 468 | + cases, total = await list_case_results_for_session(db, session_id=session_id, skip=skip, limit=limit) |
| 469 | + return CaseResultListResponse( |
| 470 | + cases=[_case_result_to_response(c) for c in cases], |
| 471 | + total=total, |
| 472 | + skip=skip, |
| 473 | + limit=limit, |
| 474 | + ) |
| 475 | + |
| 476 | + |
419 | 477 | # --------------------------------------------------------------------------- |
420 | 478 | # POST /external-results/artifact — upload an artifact |
421 | 479 | # --------------------------------------------------------------------------- |
|
0 commit comments