mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[F015] flow_qa/flow_doc: add i_am_blocked route (manifest-registered escape hatch was 404)
This commit is contained in:
@@ -10,6 +10,7 @@ from roboco.api.routes.v1._role_dep import envelope_to_response, require_doc
|
|||||||
from roboco.api.schemas.v1.flow import (
|
from roboco.api.schemas.v1.flow import (
|
||||||
ClaimDocTaskRequest,
|
ClaimDocTaskRequest,
|
||||||
GiveMeWorkRequest,
|
GiveMeWorkRequest,
|
||||||
|
IAmBlockedRequest,
|
||||||
IAmIdleRequest,
|
IAmIdleRequest,
|
||||||
IDocumentedRequest,
|
IDocumentedRequest,
|
||||||
ResumeRequest,
|
ResumeRequest,
|
||||||
@@ -94,3 +95,23 @@ async def i_am_idle(
|
|||||||
) -> dict:
|
) -> dict:
|
||||||
env = await choreographer.i_am_idle(x_agent_id)
|
env = await choreographer.i_am_idle(x_agent_id)
|
||||||
return envelope_to_response(env, request)
|
return envelope_to_response(env, request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/i_am_blocked")
|
||||||
|
async def i_am_blocked(
|
||||||
|
request: Request,
|
||||||
|
body: IAmBlockedRequest,
|
||||||
|
x_agent_id: _AgentIdHeader,
|
||||||
|
choreographer: _ChoreographerDep,
|
||||||
|
) -> dict:
|
||||||
|
"""F015: the documenter manifest registers ``i_am_blocked`` — surface the
|
||||||
|
route so a blocked documenter's escape hatch returns an envelope instead of
|
||||||
|
a 404."""
|
||||||
|
env = await choreographer.i_am_blocked(
|
||||||
|
x_agent_id,
|
||||||
|
body.task_id,
|
||||||
|
body.reason,
|
||||||
|
blocker_type=body.blocker_type,
|
||||||
|
what_needed=body.what_needed,
|
||||||
|
)
|
||||||
|
return envelope_to_response(env, request)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from roboco.api.schemas.v1.flow import (
|
|||||||
ClaimReviewRequest,
|
ClaimReviewRequest,
|
||||||
FailReviewRequest,
|
FailReviewRequest,
|
||||||
GiveMeWorkRequest,
|
GiveMeWorkRequest,
|
||||||
|
IAmBlockedRequest,
|
||||||
IAmIdleRequest,
|
IAmIdleRequest,
|
||||||
PassReviewRequest,
|
PassReviewRequest,
|
||||||
ResumeRequest,
|
ResumeRequest,
|
||||||
@@ -106,3 +107,22 @@ async def i_am_idle(
|
|||||||
) -> dict:
|
) -> dict:
|
||||||
env = await choreographer.i_am_idle(x_agent_id)
|
env = await choreographer.i_am_idle(x_agent_id)
|
||||||
return envelope_to_response(env, request)
|
return envelope_to_response(env, request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/i_am_blocked")
|
||||||
|
async def i_am_blocked(
|
||||||
|
request: Request,
|
||||||
|
body: IAmBlockedRequest,
|
||||||
|
x_agent_id: _AgentIdHeader,
|
||||||
|
choreographer: _ChoreographerDep,
|
||||||
|
) -> dict:
|
||||||
|
"""F015: the QA manifest registers ``i_am_blocked`` — surface the route so a
|
||||||
|
blocked QA agent's escape hatch returns an envelope instead of a 404."""
|
||||||
|
env = await choreographer.i_am_blocked(
|
||||||
|
x_agent_id,
|
||||||
|
body.task_id,
|
||||||
|
body.reason,
|
||||||
|
blocker_type=body.blocker_type,
|
||||||
|
what_needed=body.what_needed,
|
||||||
|
)
|
||||||
|
return envelope_to_response(env, request)
|
||||||
|
|||||||
@@ -190,3 +190,25 @@ async def test_resume_dispatches() -> None:
|
|||||||
)
|
)
|
||||||
assert resp.status_code == _HTTP_200
|
assert resp.status_code == _HTTP_200
|
||||||
mock_chore.resume.assert_awaited_once()
|
mock_chore.resume.assert_awaited_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_i_am_blocked_dispatches_to_choreographer() -> None:
|
||||||
|
"""F015: POST /api/v1/flow/documenter/i_am_blocked must exist (the
|
||||||
|
documenter manifest registers i_am_blocked) and return an envelope, not 404
|
||||||
|
with a non-envelope body. Without this route a blocked documenter's escape
|
||||||
|
hatch 404s."""
|
||||||
|
mock_chore = MagicMock()
|
||||||
|
mock_chore.i_am_blocked = AsyncMock(
|
||||||
|
return_value=_make_envelope(status="blocked", task_id=_TASK_ID)
|
||||||
|
)
|
||||||
|
client = TestClient(_build_app(mock_chore))
|
||||||
|
resp = client.post(
|
||||||
|
"/api/v1/flow/documenter/i_am_blocked",
|
||||||
|
json={"task_id": _TASK_ID, "reason": "PR diff unavailable"},
|
||||||
|
headers=_HEADERS,
|
||||||
|
)
|
||||||
|
assert resp.status_code == _HTTP_200
|
||||||
|
body = resp.json()
|
||||||
|
assert body["status"] == "blocked"
|
||||||
|
mock_chore.i_am_blocked.assert_awaited_once()
|
||||||
|
|||||||
@@ -219,3 +219,24 @@ async def test_i_am_idle_dispatches_agent_id() -> None:
|
|||||||
)
|
)
|
||||||
assert resp.status_code == _HTTP_200
|
assert resp.status_code == _HTTP_200
|
||||||
mock_chore.i_am_idle.assert_awaited_once()
|
mock_chore.i_am_idle.assert_awaited_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_i_am_blocked_dispatches_to_choreographer() -> None:
|
||||||
|
"""F015: POST /api/v1/flow/qa/i_am_blocked must exist (the QA manifest
|
||||||
|
registers i_am_blocked) and return an envelope, not 404 with a non-envelope
|
||||||
|
body. Without this route a blocked QA agent's escape hatch 404s."""
|
||||||
|
mock_chore = MagicMock()
|
||||||
|
mock_chore.i_am_blocked = AsyncMock(
|
||||||
|
return_value=_make_envelope(status="blocked", task_id=_TASK_ID)
|
||||||
|
)
|
||||||
|
client = TestClient(_build_app(mock_chore))
|
||||||
|
resp = client.post(
|
||||||
|
"/api/v1/flow/qa/i_am_blocked",
|
||||||
|
json={"task_id": _TASK_ID, "reason": "PR diff won't load"},
|
||||||
|
headers=_HEADERS,
|
||||||
|
)
|
||||||
|
assert resp.status_code == _HTTP_200
|
||||||
|
body = resp.json()
|
||||||
|
assert body["status"] == "blocked"
|
||||||
|
mock_chore.i_am_blocked.assert_awaited_once()
|
||||||
|
|||||||
Reference in New Issue
Block a user