feat: add PR/release/branch/milestone/comment write tools
Adds six opt-in write tools (write-mode + policy + per-user permission still
enforced; no destructive or admin actions):
- create_pull_request (POST /pulls)
- create_release / edit_release (POST/PATCH /releases)
- create_branch (POST /branches; create only, no deletion)
- create_milestone (POST /milestones)
- edit_issue_comment (PATCH /issues/comments/{id})
Each: arg schema (extra=forbid, GitRef on branch/ref-like fields), Gitea client
method with url-encoded path segments, handler that surfaces auth errors, MCP
registration (write_operation=True), server wiring, docs, and success tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,10 +20,16 @@ from aegis_gitea_mcp.tools.read_tools import (
|
||||
from aegis_gitea_mcp.tools.write_tools import (
|
||||
add_labels_tool,
|
||||
assign_issue_tool,
|
||||
create_branch_tool,
|
||||
create_issue_comment_tool,
|
||||
create_issue_tool,
|
||||
create_label_tool,
|
||||
create_milestone_tool,
|
||||
create_pr_comment_tool,
|
||||
create_pull_request_tool,
|
||||
create_release_tool,
|
||||
edit_issue_comment_tool,
|
||||
edit_release_tool,
|
||||
remove_labels_tool,
|
||||
update_issue_tool,
|
||||
update_label_tool,
|
||||
@@ -114,6 +120,28 @@ class StubGitea:
|
||||
async def remove_labels(self, owner, repo, index, labels):
|
||||
return []
|
||||
|
||||
async def create_pull_request(self, owner, repo, *, title, head, base, body=""):
|
||||
return {"number": 7, "title": title, "state": "open"}
|
||||
|
||||
async def create_release(
|
||||
self, owner, repo, *, tag_name, name="", body="", draft=False, prerelease=False, target=None
|
||||
):
|
||||
return {"id": 3, "tag_name": tag_name, "name": name or tag_name}
|
||||
|
||||
async def edit_release(
|
||||
self, owner, repo, release_id, *, name=None, body=None, draft=None, prerelease=None
|
||||
):
|
||||
return {"id": release_id, "tag_name": "v1", "name": name or "rel"}
|
||||
|
||||
async def create_branch(self, owner, repo, *, new_branch_name, old_branch_name=None):
|
||||
return {"name": new_branch_name, "commit": {"id": "abc"}}
|
||||
|
||||
async def create_milestone(self, owner, repo, *, title, description="", due_on=None):
|
||||
return {"id": 4, "title": title, "state": "open"}
|
||||
|
||||
async def edit_issue_comment(self, owner, repo, comment_id, body):
|
||||
return {"id": comment_id, "body": body}
|
||||
|
||||
|
||||
class ErrorGitea(StubGitea):
|
||||
"""Stub that raises backend errors for failure-mode coverage."""
|
||||
@@ -201,6 +229,36 @@ async def test_extended_read_tools_failure_mode() -> None:
|
||||
{"owner": "acme", "repo": "app", "issue_number": 1, "labels": ["bug"]},
|
||||
"removed",
|
||||
),
|
||||
(
|
||||
create_pull_request_tool,
|
||||
{"owner": "acme", "repo": "app", "title": "PR", "head": "feature", "base": "main"},
|
||||
"number",
|
||||
),
|
||||
(
|
||||
create_release_tool,
|
||||
{"owner": "acme", "repo": "app", "tag_name": "v1.0.0"},
|
||||
"id",
|
||||
),
|
||||
(
|
||||
edit_release_tool,
|
||||
{"owner": "acme", "repo": "app", "release_id": 3, "name": "x"},
|
||||
"id",
|
||||
),
|
||||
(
|
||||
create_branch_tool,
|
||||
{"owner": "acme", "repo": "app", "new_branch_name": "feature/x"},
|
||||
"name",
|
||||
),
|
||||
(
|
||||
create_milestone_tool,
|
||||
{"owner": "acme", "repo": "app", "title": "M1"},
|
||||
"id",
|
||||
),
|
||||
(
|
||||
edit_issue_comment_tool,
|
||||
{"owner": "acme", "repo": "app", "comment_id": 5, "body": "edited"},
|
||||
"id",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_write_tools_success(tool, args, expected_key):
|
||||
|
||||
Reference in New Issue
Block a user