feat: reuse single comment
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import json
|
||||
|
||||
import httpx
|
||||
import respx
|
||||
|
||||
from agentci.adapters.gitea import GiteaClient
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_updates_issue_comment_by_id() -> None:
|
||||
route = respx.patch(
|
||||
"https://gitea.example/api/v1/repos/org/repo/issues/comments/17"
|
||||
).mock(return_value=httpx.Response(200, json={"id": 17}))
|
||||
client = GiteaClient("https://gitea.example", "secret")
|
||||
|
||||
try:
|
||||
await client.update_comment("org", "repo", 17, "updated status")
|
||||
finally:
|
||||
await client.close()
|
||||
|
||||
assert route.called
|
||||
assert json.loads(route.calls[0].request.content) == {"body": "updated status"}
|
||||
+87
-1
@@ -1,7 +1,8 @@
|
||||
from pathlib import Path
|
||||
|
||||
from agentci.domain.models import Job, JobKind, Workflow, WorkflowKind
|
||||
from agentci.domain.models import Job, JobKind, JobStatus, Workflow, WorkflowKind
|
||||
from agentci.worker import Worker
|
||||
from agentci.workflows.common import JobRejected
|
||||
|
||||
|
||||
class FakeStorage:
|
||||
@@ -20,6 +21,47 @@ class FakeOpenCode:
|
||||
self.aborted.add((session_id, workspace))
|
||||
|
||||
|
||||
class JobStorage(FakeStorage):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(None)
|
||||
self.updates: list[tuple[JobStatus | None, str | None, str | None]] = []
|
||||
self.comment_ids: list[int] = []
|
||||
|
||||
async def update_job(self, _job_id: str, **values) -> None:
|
||||
self.updates.append(
|
||||
(values.get("status"), values.get("stage"), values.get("error"))
|
||||
)
|
||||
|
||||
async def set_job_comment(self, _job_id: str, _column: str, comment_id: int) -> None:
|
||||
self.comment_ids.append(comment_id)
|
||||
|
||||
async def job_stage(self, _job_id: str) -> str:
|
||||
return "working"
|
||||
|
||||
async def fail_job_workflow(self, _job_id: str) -> None:
|
||||
return None
|
||||
|
||||
|
||||
class FakeGitea:
|
||||
def __init__(self) -> None:
|
||||
self.created: list[str] = []
|
||||
self.updated: list[tuple[int, str]] = []
|
||||
|
||||
async def create_comment(self, _owner: str, _repo: str, _number: int, body: str) -> int:
|
||||
self.created.append(body)
|
||||
return 42
|
||||
|
||||
async def update_comment(
|
||||
self, _owner: str, _repo: str, comment_id: int, body: str
|
||||
) -> None:
|
||||
self.updated.append((comment_id, body))
|
||||
|
||||
|
||||
class RejectingDispatcher:
|
||||
async def dispatch(self, _job: Job) -> None:
|
||||
raise JobRejected("not applicable")
|
||||
|
||||
|
||||
def job(*, workflow_id: str | None, runtime_session_id: str | None = None) -> Job:
|
||||
return Job(
|
||||
id="job",
|
||||
@@ -78,3 +120,47 @@ async def test_recovery_aborts_one_shot_fix_session(tmp_path: Path) -> None:
|
||||
)
|
||||
|
||||
assert opencode.aborted == {("fix-session", tmp_path / "fix-job" / "repo")}
|
||||
|
||||
|
||||
async def test_job_status_updates_existing_gitea_comment(tmp_path: Path) -> None:
|
||||
storage = JobStorage()
|
||||
gitea = FakeGitea()
|
||||
active_job = job(workflow_id=None)
|
||||
active_job.accepted_comment_id = 41
|
||||
value = Worker(
|
||||
storage=storage, # type: ignore[arg-type]
|
||||
gitea=gitea, # type: ignore[arg-type]
|
||||
opencode=FakeOpenCode(), # type: ignore[arg-type]
|
||||
dispatcher=RejectingDispatcher(), # type: ignore[arg-type]
|
||||
poll_seconds=1,
|
||||
workspaces_dir=tmp_path,
|
||||
)
|
||||
|
||||
await value._run_job(active_job)
|
||||
|
||||
assert gitea.created == []
|
||||
assert [comment_id for comment_id, _body in gitea.updated] == [41, 41]
|
||||
assert "started" in gitea.updated[0][1]
|
||||
assert "rejected" in gitea.updated[1][1]
|
||||
assert storage.updates[-1][:2] == (JobStatus.REJECTED, "rejected")
|
||||
|
||||
|
||||
async def test_worker_creates_only_one_comment_when_queue_comment_is_missing(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
storage = JobStorage()
|
||||
gitea = FakeGitea()
|
||||
value = Worker(
|
||||
storage=storage, # type: ignore[arg-type]
|
||||
gitea=gitea, # type: ignore[arg-type]
|
||||
opencode=FakeOpenCode(), # type: ignore[arg-type]
|
||||
dispatcher=RejectingDispatcher(), # type: ignore[arg-type]
|
||||
poll_seconds=1,
|
||||
workspaces_dir=tmp_path,
|
||||
)
|
||||
|
||||
await value._run_job(job(workflow_id=None))
|
||||
|
||||
assert len(gitea.created) == 1
|
||||
assert storage.comment_ids == [42]
|
||||
assert [comment_id for comment_id, _body in gitea.updated] == [42]
|
||||
|
||||
Reference in New Issue
Block a user