feat: assign issues to milestones on create/update (#22) #25

Merged
Latte merged 6 commits from feat/issue-milestone-assignment into main 2026-06-22 16:00:30 +00:00
Showing only changes of commit 538d6d964a - Show all commits
+60 -1
View File
@@ -3,7 +3,7 @@
import pytest
from aegis_gitea_mcp.config import reset_settings
from aegis_gitea_mcp.gitea_client import GiteaError
from aegis_gitea_mcp.gitea_client import GiteaAuthenticationError, GiteaError
from aegis_gitea_mcp.tools.read_tools import (
compare_refs_tool,
get_branch_tool,
@@ -402,3 +402,62 @@ def test_create_label_args_reject_invalid_color() -> None:
with pytest.raises(pydantic.ValidationError):
CreateLabelArgs(owner="o", repo="r", name="bug", color="red")
# (tool, valid_args) for every write tool, used to exercise error branches.
WRITE_TOOL_ERROR_CASES = [
(create_issue_tool, {"owner": "acme", "repo": "app", "title": "Issue"}),
(update_issue_tool, {"owner": "acme", "repo": "app", "issue_number": 1, "title": "x"}),
(create_issue_comment_tool, {"owner": "acme", "repo": "app", "issue_number": 1, "body": "c"}),
(create_pr_comment_tool, {"owner": "acme", "repo": "app", "pull_number": 1, "body": "c"}),
(add_labels_tool, {"owner": "acme", "repo": "app", "issue_number": 1, "labels": ["bug"]}),
(assign_issue_tool, {"owner": "acme", "repo": "app", "issue_number": 1, "assignees": ["al"]}),
(create_label_tool, {"owner": "acme", "repo": "app", "name": "bug", "color": "#ff0000"}),
(update_label_tool, {"owner": "acme", "repo": "app", "name": "bug", "new_name": "defect"}),
(remove_labels_tool, {"owner": "acme", "repo": "app", "issue_number": 1, "labels": ["bug"]}),
(
create_pull_request_tool,
{"owner": "acme", "repo": "app", "title": "PR", "head": "feature", "base": "main"},
),
(create_release_tool, {"owner": "acme", "repo": "app", "tag_name": "v1.0.0"}),
(edit_release_tool, {"owner": "acme", "repo": "app", "release_id": 3, "name": "x"}),
(create_branch_tool, {"owner": "acme", "repo": "app", "new_branch_name": "feature/x"}),
(create_milestone_tool, {"owner": "acme", "repo": "app", "title": "M1"}),
(edit_issue_comment_tool, {"owner": "acme", "repo": "app", "comment_id": 5, "body": "e"}),
]
class _WriteBackendErrorGitea:
"""Stub whose every method raises a generic Gitea backend error."""
def __getattr__(self, name: str):
async def _raise(*args: object, **kwargs: object) -> object:
raise GiteaError("backend failure")
return _raise
class _WriteAuthErrorGitea:
"""Stub whose every method raises an authentication error."""
def __getattr__(self, name: str):
async def _raise(*args: object, **kwargs: object) -> object:
raise GiteaAuthenticationError("token expired")
return _raise
@pytest.mark.asyncio
@pytest.mark.parametrize("tool,args", WRITE_TOOL_ERROR_CASES)
async def test_write_tools_wrap_backend_errors(tool, args) -> None:
"""Every write tool wraps a backend GiteaError as a RuntimeError."""
with pytest.raises(RuntimeError):
await tool(_WriteBackendErrorGitea(), args)
@pytest.mark.asyncio
@pytest.mark.parametrize("tool,args", WRITE_TOOL_ERROR_CASES)
async def test_write_tools_propagate_auth_errors(tool, args) -> None:
"""Every write tool lets auth failures surface for re-authorization."""
with pytest.raises(GiteaAuthenticationError):
await tool(_WriteAuthErrorGitea(), args)