feat: replace Aider with secure mini-SWE-agent worker
This commit is contained in:
@@ -1,27 +1,130 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from test_config import settings
|
||||
|
||||
from lai_automation.gitea import GiteaClient
|
||||
from lai_automation.models import Issue, Label
|
||||
|
||||
|
||||
def test_create_pull_request_requires_url() -> None:
|
||||
client = GiteaClient(settings(gitea_token="token"))
|
||||
response = Mock()
|
||||
response.json.return_value = {"number": 12}
|
||||
client.session.post = Mock(return_value=response)
|
||||
|
||||
with pytest.raises(ValueError, match="pull request URL"):
|
||||
client.create_pull_request("ai/failure-1", "Fix", "Body")
|
||||
def response(payload, status: int = 200) -> Mock:
|
||||
result = Mock()
|
||||
result.json.return_value = payload
|
||||
result.status_code = status
|
||||
result.text = ""
|
||||
result.raise_for_status.return_value = None
|
||||
return result
|
||||
|
||||
|
||||
def test_create_pull_request_returns_html_url() -> None:
|
||||
client = GiteaClient(settings(gitea_token="token"))
|
||||
response = Mock()
|
||||
response.json.return_value = {"html_url": "https://example.test/owner/lai/pulls/12"}
|
||||
client.session.post = Mock(return_value=response)
|
||||
def test_list_queued_issues_filters_pull_requests(settings) -> None:
|
||||
client = GiteaClient(settings)
|
||||
client.session.request = Mock(
|
||||
return_value=response(
|
||||
[
|
||||
{
|
||||
"number": 7,
|
||||
"title": "Wrong answer",
|
||||
"body": "Details",
|
||||
"html_url": "https://gitea.example.test/owner/lai/issues/7",
|
||||
"labels": [{"id": 1, "name": "ai:queued"}],
|
||||
},
|
||||
{
|
||||
"number": 8,
|
||||
"title": "A pull request",
|
||||
"body": "",
|
||||
"html_url": "https://gitea.example.test/owner/lai/pulls/8",
|
||||
"labels": [{"id": 1, "name": "ai:queued"}],
|
||||
"pull_request": {"merged": False},
|
||||
},
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
result = client.create_pull_request("ai/failure-1", "Fix", "Body")
|
||||
issues = client.list_queued_issues()
|
||||
|
||||
assert result.endswith("/pulls/12")
|
||||
assert [issue.number for issue in issues] == [7]
|
||||
assert client.session.request.call_args.kwargs["params"]["labels"] == "ai:queued"
|
||||
|
||||
|
||||
def test_ensure_automation_labels_creates_only_missing_labels(settings) -> None:
|
||||
client = GiteaClient(settings)
|
||||
existing = [{"id": 1, "name": "ai:queued"}]
|
||||
created = iter(
|
||||
[
|
||||
{"id": 2, "name": "ai:running"},
|
||||
{"id": 3, "name": "ai:ready"},
|
||||
{"id": 4, "name": "ai:failed"},
|
||||
]
|
||||
)
|
||||
|
||||
def request(method, _url, **kwargs):
|
||||
if method == "GET":
|
||||
return response(existing)
|
||||
return response(next(created))
|
||||
|
||||
client.session.request = Mock(side_effect=request)
|
||||
|
||||
labels = client.ensure_automation_labels()
|
||||
|
||||
assert set(labels) == {"ai:queued", "ai:running", "ai:ready", "ai:failed"}
|
||||
assert client.session.request.call_count == 4
|
||||
|
||||
|
||||
def test_state_transition_preserves_manual_labels(settings) -> None:
|
||||
client = GiteaClient(settings)
|
||||
client.session.request = Mock(
|
||||
side_effect=[
|
||||
response(
|
||||
[
|
||||
{"id": 9, "name": "bug"},
|
||||
{"id": 2, "name": "ai:running"},
|
||||
]
|
||||
),
|
||||
response(
|
||||
{
|
||||
"number": 5,
|
||||
"title": "Issue",
|
||||
"body": "Body",
|
||||
"html_url": "https://gitea.example.test/owner/lai/issues/5",
|
||||
"labels": [
|
||||
{"id": 9, "name": "bug"},
|
||||
{"id": 2, "name": "ai:running"},
|
||||
],
|
||||
}
|
||||
),
|
||||
]
|
||||
)
|
||||
issue = Issue(
|
||||
number=5,
|
||||
title="Issue",
|
||||
body="Body",
|
||||
html_url="https://gitea.example.test/owner/lai/issues/5",
|
||||
labels=(Label(9, "bug"), Label(1, "ai:queued")),
|
||||
)
|
||||
known = {
|
||||
"ai:queued": Label(1, "ai:queued"),
|
||||
"ai:running": Label(2, "ai:running"),
|
||||
}
|
||||
|
||||
updated = client.set_automation_state(issue, "ai:running", known)
|
||||
|
||||
assert updated.has_label("ai:running")
|
||||
replace_call = client.session.request.call_args_list[0]
|
||||
assert replace_call.args[0] == "PUT"
|
||||
assert replace_call.args[1].endswith("/issues/5/labels")
|
||||
assert replace_call.kwargs["json"] == {"labels": [9, 2]}
|
||||
assert client.session.request.call_args_list[1].args[0] == "GET"
|
||||
|
||||
|
||||
def test_create_pull_request_returns_number_and_url(settings) -> None:
|
||||
client = GiteaClient(settings)
|
||||
client.session.request = Mock(
|
||||
return_value=response(
|
||||
{"number": 17, "html_url": "https://gitea.example.test/owner/lai/pulls/17"}
|
||||
)
|
||||
)
|
||||
|
||||
pull_request = client.create_pull_request("ai/issue-5", "Fix", "Fixes #5")
|
||||
|
||||
assert pull_request.number == 17
|
||||
assert pull_request.html_url.endswith("/pulls/17")
|
||||
assert client.session.request.call_args.kwargs["json"]["base"] == "main"
|
||||
Reference in New Issue
Block a user