feat: implement CloseIssue and PostComment methods in gitea client

Add CloseIssue (PATCH state=closed) and PostComment (POST comment body)
methods to the Gitea client with cache invalidation. Add corresponding
handler routes POST /issues/{owner}/{repo}/{index}/close and
POST /issues/{owner}/{repo}/{index}/comment with HTMX support.
Include unit tests for both client methods.

Closes leeworks-agents/gitea-mobile#36

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
agent-company
2026-03-26 17:06:00 +00:00
parent 919a91d6aa
commit added0778e
3 changed files with 209 additions and 0 deletions
+45
View File
@@ -706,6 +706,51 @@ func (c *Client) SubmitReview(ctx context.Context, token, owner, repo string, in
return nil
}
// CloseIssue closes an issue by setting its state to "closed".
func (c *Client) CloseIssue(ctx context.Context, token, owner, repo string, index int64) error {
payload, err := json.Marshal(map[string]string{"state": "closed"})
if err != nil {
return fmt.Errorf("marshaling close request: %w", err)
}
path := fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index)
resp, err := c.doRequest(ctx, token, http.MethodPatch, path, strings.NewReader(string(payload)))
if err != nil {
return fmt.Errorf("closing issue: %w", err)
}
resp.Body.Close()
c.InvalidateAll()
return nil
}
// PostComment creates a comment on an issue and returns the created Comment.
func (c *Client) PostComment(ctx context.Context, token, owner, repo string, index int64, body string) (*Comment, error) {
payload, err := json.Marshal(map[string]string{"body": body})
if err != nil {
return nil, fmt.Errorf("marshaling comment: %w", err)
}
path := fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index)
resp, err := c.doRequest(ctx, token, http.MethodPost, path, strings.NewReader(string(payload)))
if err != nil {
return nil, fmt.Errorf("posting comment: %w", err)
}
defer resp.Body.Close()
var comment Comment
if err := json.NewDecoder(resp.Body).Decode(&comment); err != nil {
return nil, fmt.Errorf("decoding comment: %w", err)
}
// Populate convenience fields.
comment.User = comment.RawUser.Login
comment.CreatedAt = comment.RawCreatedAt.Format("Jan 2, 2006 15:04")
c.InvalidateAll()
return &comment, nil
}
// priorityScore returns a numeric score for sorting (lower = higher priority).
func priorityScore(labels []string) int {
for _, l := range labels {