refactor tests
Publish container image / Build and push (push) Successful in 32s

This commit is contained in:
2026-07-26 23:49:40 +02:00
parent 5ef10d28fe
commit ce9f1e3d20
32 changed files with 1546 additions and 1923 deletions
+63 -97
View File
@@ -20,7 +20,6 @@ from agentci.engine.events import (
JobRejected as RejectedEvent,
)
from agentci.engine.model import (
IncomingCommand,
Job,
JobKind,
JobStatus,
@@ -31,12 +30,9 @@ from agentci.engine.model import (
WorkflowKind,
)
from agentci.engine.reducer import render_job_comment
from agentci.engine.repository import Repository
from agentci.integrations.gitea.models import CommentInfo
from agentci.workflows.render import JobRejected
MIGRATIONS = Path(__file__).parents[1] / "src" / "agentci" / "migrations"
class FakeRepository:
def __init__(
@@ -54,7 +50,6 @@ class FakeRepository:
self.events: list[tuple[str, object]] = []
self.operations: list[str] = []
self.running: list[Job] = []
self.failed_workflows: list[str] = []
self.complete_stop: asyncio.Event | None = None
async def claim_task(self, queue: QueueName) -> Task | None:
@@ -91,9 +86,6 @@ class FakeRepository:
async def get_workflow(self, _workflow_id: str) -> Workflow | None:
return self.workflow
async def fail_job_workflow(self, job_id: str) -> None:
self.failed_workflows.append(job_id)
class FakeGitea:
def __init__(self, *, permitted: bool = True) -> None:
@@ -181,7 +173,7 @@ def task(
def make_worker(
tmp_path: Path,
repository: FakeRepository | Repository,
repository: FakeRepository,
*,
gitea: FakeGitea | None = None,
opencode: FakeOpenCode | None = None,
@@ -329,74 +321,47 @@ async def test_run_recovers_before_starting_configured_consumers(
@pytest.mark.parametrize(
("permitted", "event_type", "suffix"),
("status", "permitted", "expected_events", "expected_permission_calls"),
[
(True, PermissionGranted, "permission-granted"),
(False, PermissionDenied, "permission-denied"),
pytest.param(
JobStatus.RECEIVED,
True,
[("task:7:permission-granted", PermissionGranted(job_id="job"))],
[("org", "repo", "alice")],
id="received-permitted",
),
pytest.param(
JobStatus.RECEIVED,
False,
[("task:7:permission-denied", PermissionDenied(job_id="job"))],
[("org", "repo", "alice")],
id="received-denied",
),
pytest.param(
JobStatus.QUEUED,
True,
[],
[],
id="queued",
),
],
)
async def test_authorize_records_permission_outcome(
async def test_handle_authorization_obeys_job_state_and_permission(
tmp_path: Path,
status: JobStatus,
permitted: bool,
event_type: type[PermissionGranted] | type[PermissionDenied],
suffix: str,
expected_events: list[tuple[str, object]],
expected_permission_calls: list[tuple[str, str, str]],
) -> None:
current = job()
repository = FakeRepository(current)
repository = FakeRepository(job(status=status))
gitea = FakeGitea(permitted=permitted)
authorize = task(TaskKind.AUTHORIZE, QueueName.CONTROL)
await make_worker(tmp_path, repository, gitea=gitea)._authorize(authorize, current)
assert gitea.permission_calls == [("org", "repo", "alice")]
assert repository.events[0][0] == f"task:{authorize.id}:{suffix}"
assert isinstance(repository.events[0][1], event_type)
async def test_authorize_ignores_job_after_received_status(tmp_path: Path) -> None:
current = job(status=JobStatus.QUEUED)
repository = FakeRepository(current)
gitea = FakeGitea()
await make_worker(tmp_path, repository, gitea=gitea)._authorize(
task(TaskKind.AUTHORIZE, QueueName.CONTROL), current
await make_worker(tmp_path, repository, gitea=gitea)._handle(
task(TaskKind.AUTHORIZE, QueueName.CONTROL)
)
assert gitea.permission_calls == []
assert repository.events == []
async def test_authorize_integrates_with_real_repository(
tmp_path: Path,
) -> None:
repository = Repository(tmp_path / "state.sqlite3", MIGRATIONS)
await repository.initialize()
accepted = await repository.accept(
IncomingCommand(
delivery_id="delivery-real",
comment_id=1,
repo_owner="org",
repo_name="repo",
issue_number=1,
pr_number=None,
requester="alice",
body="/agent plan write tests",
)
)
authorize = await repository.claim_task(QueueName.CONTROL)
assert authorize is not None
assert authorize.kind is TaskKind.AUTHORIZE
await make_worker(tmp_path, repository)._handle(authorize)
persisted = await repository.get_job(accepted.job.id)
assert persisted is not None
assert persisted.status is JobStatus.QUEUED
assert persisted.kind is JobKind.PLAN
assert persisted.message == "write tests"
execute = await repository.claim_task(QueueName.JOBS)
assert execute is not None
assert execute.kind is TaskKind.EXECUTE
assert repository.events == expected_events
assert gitea.permission_calls == expected_permission_calls
async def test_execute_completes_with_workflow_comment(
@@ -603,43 +568,44 @@ async def test_abort_collects_and_deduplicates_workflow_sessions(
assert set(opencode.aborted) == {(session, workspace) for session in expected}
async def test_abort_uses_one_shot_workspace_without_workflow(tmp_path: Path) -> None:
opencode = FakeOpenCode()
await make_worker(tmp_path, FakeRepository(), opencode=opencode)._abort_job_sessions(
job(workflow_id="missing", session_id="session")
)
assert opencode.aborted == [("session", tmp_path / "fix-job" / "repo")]
async def test_abort_does_not_mix_one_shot_session_into_existing_workflow(
@pytest.mark.parametrize(
("workflow_id", "session_id", "has_workflow", "uses_one_shot"),
[
pytest.param("missing", "session", False, True, id="one-shot-fallback"),
pytest.param("flow", "one-shot", True, False, id="workflow-precedence"),
pytest.param(None, None, False, False, id="no-sessions"),
],
)
async def test_abort_session_source_precedence(
tmp_path: Path,
workflow_id: str | None,
session_id: str | None,
has_workflow: bool,
uses_one_shot: bool,
) -> None:
workflow = Workflow(
id="flow",
kind=WorkflowKind.IMPLEMENT,
repo_owner="org",
repo_name="repo",
issue_number=1,
workspace_path=tmp_path / "workflow" / "repo",
base_sha="base",
persisted = (
Workflow(
id="flow",
kind=WorkflowKind.IMPLEMENT,
repo_owner="org",
repo_name="repo",
issue_number=1,
workspace_path=tmp_path / "workflow" / "repo",
base_sha="base",
)
if has_workflow
else None
)
opencode = FakeOpenCode()
await make_worker(
tmp_path, FakeRepository(workflow=workflow), opencode=opencode
)._abort_job_sessions(job(workflow_id="flow", session_id="one-shot"))
tmp_path,
FakeRepository(workflow=persisted),
opencode=opencode,
)._abort_job_sessions(job(workflow_id=workflow_id, session_id=session_id))
assert opencode.aborted == []
async def test_abort_without_persisted_sessions_is_noop(tmp_path: Path) -> None:
opencode = FakeOpenCode()
await make_worker(tmp_path, FakeRepository(), opencode=opencode)._abort_job_sessions(job())
assert opencode.aborted == []
expected = [("session", tmp_path / "fix-job" / "repo")] if uses_one_shot else []
assert opencode.aborted == expected
def test_safe_error_is_single_line_and_bounded() -> None: