feat: close issues after merged agent PRs
This commit is contained in:
@@ -8,7 +8,7 @@ import httpx
|
||||
from agent_gitea.config import AppConfig
|
||||
from agent_gitea.gitea import GiteaClient
|
||||
from agent_gitea.models import AgentResult, TaskState
|
||||
from agent_gitea.service import TaskRunner, scan_issues, sync_repositories
|
||||
from agent_gitea.service import TaskRunner, close_issues_for_merged_pull_requests, scan_issues, sync_repositories
|
||||
|
||||
|
||||
def make_config(tmp_path: Path, **overrides: object) -> AppConfig:
|
||||
@@ -265,12 +265,94 @@ def test_run_task_success_posts_review_comments(db, tmp_path):
|
||||
pull_requests = [payload for _, path, payload in requests if path == "/api/v1/repos/acme/service/pulls"]
|
||||
assert pull_requests[0]["title"] == "代理实现:Ready issue"
|
||||
assert "代理实现报告" in pull_requests[0]["body"]
|
||||
assert "Closes #1" in pull_requests[0]["body"]
|
||||
command = json.loads(db.list_agent_runs(task.id)[0]["command_json"])
|
||||
assert command[1] == "--cd"
|
||||
assert Path(command[2]).is_absolute()
|
||||
assert [path for _, path, _ in requests].count("/api/v1/repos/acme/service/issues/5/comments") == 2
|
||||
|
||||
|
||||
def test_close_issues_for_merged_pull_requests_closes_linked_issue(db):
|
||||
repo = db.upsert_repository(
|
||||
owner="acme",
|
||||
name="service",
|
||||
clone_url="https://gitea.test/acme/service.git",
|
||||
default_branch="main",
|
||||
enabled=True,
|
||||
)
|
||||
db.upsert_issue(
|
||||
repo_id=repo.id,
|
||||
issue_number=1,
|
||||
title="Ready issue",
|
||||
body="Body",
|
||||
labels=["agent:ready"],
|
||||
state="open",
|
||||
html_url="https://gitea.test/acme/service/issues/1",
|
||||
)
|
||||
task = db.create_task(repo.id, 1)
|
||||
db.transition(task.id, TaskState.CLAIMED)
|
||||
db.transition(task.id, TaskState.PLANNING)
|
||||
db.transition(task.id, TaskState.IMPLEMENTING)
|
||||
db.transition(task.id, TaskState.TESTING)
|
||||
db.transition(task.id, TaskState.PR_OPENED, pr_number=5)
|
||||
db.transition(task.id, TaskState.REVIEWING)
|
||||
db.transition(task.id, TaskState.HUMAN_REVIEW_READY, clear_lease=True)
|
||||
requests: list[tuple[str, str, dict]] = []
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
payload = json.loads(request.content.decode() or "{}")
|
||||
requests.append((request.method, request.url.path, payload))
|
||||
if request.url.path == "/api/v1/repos/acme/service/pulls/5":
|
||||
return httpx.Response(200, json={"number": 5, "state": "closed", "merged": True})
|
||||
if request.url.path == "/api/v1/repos/acme/service/issues/1/comments":
|
||||
return httpx.Response(201, json={"id": 1})
|
||||
if request.url.path == "/api/v1/repos/acme/service/issues/1":
|
||||
return httpx.Response(200, json={"number": 1, "state": "closed"})
|
||||
return httpx.Response(404)
|
||||
|
||||
closed = close_issues_for_merged_pull_requests(db, make_client(handler))
|
||||
|
||||
assert closed == 1
|
||||
assert db.get_issue(repo.id, 1).state == "closed" # type: ignore[union-attr]
|
||||
assert ("PATCH", "/api/v1/repos/acme/service/issues/1", {"state": "closed"}) in requests
|
||||
|
||||
|
||||
def test_close_issues_for_merged_pull_requests_skips_unmerged_pr(db):
|
||||
repo = db.upsert_repository(
|
||||
owner="acme",
|
||||
name="service",
|
||||
clone_url="https://gitea.test/acme/service.git",
|
||||
default_branch="main",
|
||||
enabled=True,
|
||||
)
|
||||
db.upsert_issue(
|
||||
repo_id=repo.id,
|
||||
issue_number=1,
|
||||
title="Ready issue",
|
||||
body="Body",
|
||||
labels=["agent:ready"],
|
||||
state="open",
|
||||
html_url="https://gitea.test/acme/service/issues/1",
|
||||
)
|
||||
task = db.create_task(repo.id, 1)
|
||||
db.transition(task.id, TaskState.CLAIMED)
|
||||
db.transition(task.id, TaskState.PLANNING)
|
||||
db.transition(task.id, TaskState.IMPLEMENTING)
|
||||
db.transition(task.id, TaskState.TESTING)
|
||||
db.transition(task.id, TaskState.PR_OPENED, pr_number=5)
|
||||
db.transition(task.id, TaskState.REVIEWING)
|
||||
db.transition(task.id, TaskState.HUMAN_REVIEW_READY, clear_lease=True)
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
assert request.url.path == "/api/v1/repos/acme/service/pulls/5"
|
||||
return httpx.Response(200, json={"number": 5, "state": "open", "merged": False})
|
||||
|
||||
closed = close_issues_for_merged_pull_requests(db, make_client(handler))
|
||||
|
||||
assert closed == 0
|
||||
assert db.get_issue(repo.id, 1).state == "open" # type: ignore[union-attr]
|
||||
|
||||
|
||||
def test_run_task_no_diff_becomes_blocked(db, tmp_path):
|
||||
config = make_config(tmp_path)
|
||||
seed_task(db)
|
||||
|
||||
Reference in New Issue
Block a user