Merge main into watchpr auth failure branch
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

Keep both sides' additions to client_test.go and adopt main's
EditPROptions -> EditOptions rename.
This commit is contained in:
2026-09-19 16:40:44 +10:00
10 changed files with 760 additions and 66 deletions
+42 -9
View File
@@ -273,19 +273,20 @@ func (c *GiteaClient) CreatePR(repoPath string, opts CreatePROptions) (PullReque
return pr, err
}
// EditPROptions are the fields an edit may change. Pointers so an unset field
// is omitted from the payload entirely, leaving that field as it is. The two
// fields are not symmetric: Gitea only applies a title when it is non-empty,
// so Title can be set but never cleared and a "" title is a silent no-op,
// while a pointer to "" Body really does blank the body.
type EditPROptions struct {
// EditOptions are the fields an edit may change, for a pull request or an
// issue alike. Pointers so an unset field is omitted from the payload
// entirely, leaving that field as it is. The two fields are not symmetric:
// Gitea only applies a title when it is non-empty, so Title can be set but
// never cleared and a "" title is a silent no-op, while a pointer to "" Body
// really does blank the body.
type EditOptions struct {
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
}
// EditPR updates a pull request's title and/or body
// (PATCH /api/v1/repos/{owner}/{repo}/pulls/{index}).
func (c *GiteaClient) EditPR(repoPath string, number int, opts EditPROptions) (PullRequest, error) {
func (c *GiteaClient) EditPR(repoPath string, number int, opts EditOptions) (PullRequest, error) {
var pr PullRequest
err := c.do(http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/pulls/%d", repoPath, number), opts, &pr)
return pr, err
@@ -298,6 +299,36 @@ func (c *GiteaClient) GetPR(repoPath string, number int) (PullRequest, error) {
return pr, err
}
// Issue is the subset of Gitea's issue object we track. Gitea numbers issues
// and pull requests in one sequence, so Number is comparable to a PR number.
type Issue struct {
Number int `json:"number"`
State string `json:"state"`
Title string `json:"title"`
HTMLURL string `json:"html_url"`
}
// CreateIssueOptions are the fields for filing an issue.
type CreateIssueOptions struct {
Title string `json:"title"`
Body string `json:"body"`
}
// CreateIssue files an issue (POST /api/v1/repos/{owner}/{repo}/issues).
func (c *GiteaClient) CreateIssue(repoPath string, opts CreateIssueOptions) (Issue, error) {
var issue Issue
err := c.do(http.MethodPost, "/api/v1/repos/"+repoPath+"/issues", opts, &issue)
return issue, err
}
// EditIssue updates an issue's title and/or body
// (PATCH /api/v1/repos/{owner}/{repo}/issues/{index}).
func (c *GiteaClient) EditIssue(repoPath string, number int, opts EditOptions) (Issue, error) {
var issue Issue
err := c.do(http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/issues/%d", repoPath, number), opts, &issue)
return issue, err
}
// Comment is the subset of an issue comment we track.
type Comment struct {
ID int64 `json:"id"`
@@ -305,8 +336,10 @@ type Comment struct {
Body string `json:"body"`
}
// CreateComment posts a comment on the PR's issue thread
// (POST /api/v1/repos/{owner}/{repo}/issues/{n}/comments).
// CreateComment posts a comment on an issue thread
// (POST /api/v1/repos/{owner}/{repo}/issues/{n}/comments). Gitea backs a pull
// request with an issue of the same number, so this is the single path for
// both.
func (c *GiteaClient) CreateComment(repoPath string, number int, body string) (Comment, error) {
var cm Comment
payload := map[string]string{"body": body}