feat(gitea): add issue mutation helpers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
5a561690be
commit
9a0a1f4435
3 changed files with 254 additions and 8 deletions
|
|
@ -133,6 +133,41 @@ func (c *Client) CreateIssue(owner, repo string, opts gitea.CreateIssueOption) (
|
||||||
return issue, nil
|
return issue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EditIssue edits an existing issue.
|
||||||
|
// Usage: EditIssue(...)
|
||||||
|
func (c *Client) EditIssue(owner, repo string, number int64, opts gitea.EditIssueOption) (*gitea.Issue, error) {
|
||||||
|
issue, _, err := c.api.EditIssue(owner, repo, number, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, log.E("gitea.EditIssue", "failed to edit issue", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return issue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignIssue assigns an issue to the specified users.
|
||||||
|
// Usage: AssignIssue(...)
|
||||||
|
func (c *Client) AssignIssue(owner, repo string, number int64, assignees []string) error {
|
||||||
|
_, _, err := c.api.EditIssue(owner, repo, number, gitea.EditIssueOption{
|
||||||
|
Assignees: assignees,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return log.E("gitea.AssignIssue", "failed to assign issue", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueComment posts a comment on an issue or pull request.
|
||||||
|
// Usage: CreateIssueComment(...)
|
||||||
|
func (c *Client) CreateIssueComment(owner, repo string, issue int64, body string) error {
|
||||||
|
_, _, err := c.api.CreateIssueComment(owner, repo, issue, gitea.CreateIssueCommentOption{
|
||||||
|
Body: body,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return log.E("gitea.CreateIssueComment", "failed to create comment", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListIssueComments returns all comments for an issue.
|
// ListIssueComments returns all comments for an issue.
|
||||||
// Usage: ListIssueComments(...)
|
// Usage: ListIssueComments(...)
|
||||||
func (c *Client) ListIssueComments(owner, repo string, number int64) ([]*gitea.Comment, error) {
|
func (c *Client) ListIssueComments(owner, repo string, number int64) ([]*gitea.Comment, error) {
|
||||||
|
|
@ -253,6 +288,52 @@ func (c *Client) ListIssueCommentsIter(owner, repo string, number int64) iter.Se
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetIssueLabels returns the labels currently attached to an issue.
|
||||||
|
// Usage: GetIssueLabels(...)
|
||||||
|
func (c *Client) GetIssueLabels(owner, repo string, number int64) ([]*gitea.Label, error) {
|
||||||
|
labels, _, err := c.api.GetIssueLabels(owner, repo, number, gitea.ListLabelsOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, log.E("gitea.GetIssueLabels", "failed to get issue labels", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIssueLabels adds labels to an issue.
|
||||||
|
// Usage: AddIssueLabels(...)
|
||||||
|
func (c *Client) AddIssueLabels(owner, repo string, number int64, labelIDs []int64) error {
|
||||||
|
_, _, err := c.api.AddIssueLabels(owner, repo, number, gitea.IssueLabelsOption{
|
||||||
|
Labels: labelIDs,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return log.E("gitea.AddIssueLabels", "failed to add labels to issue", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveIssueLabel removes a label from an issue.
|
||||||
|
// Usage: RemoveIssueLabel(...)
|
||||||
|
func (c *Client) RemoveIssueLabel(owner, repo string, number, labelID int64) error {
|
||||||
|
_, err := c.api.DeleteIssueLabel(owner, repo, number, labelID)
|
||||||
|
if err != nil {
|
||||||
|
return log.E("gitea.RemoveIssueLabel", "failed to remove label from issue", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseIssue closes an issue by setting its state to closed.
|
||||||
|
// Usage: CloseIssue(...)
|
||||||
|
func (c *Client) CloseIssue(owner, repo string, number int64) error {
|
||||||
|
closed := gitea.StateClosed
|
||||||
|
_, _, err := c.api.EditIssue(owner, repo, number, gitea.EditIssueOption{
|
||||||
|
State: &closed,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return log.E("gitea.CloseIssue", "failed to close issue", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetPullRequest returns a single pull request by number.
|
// GetPullRequest returns a single pull request by number.
|
||||||
// Usage: GetPullRequest(...)
|
// Usage: GetPullRequest(...)
|
||||||
func (c *Client) GetPullRequest(owner, repo string, number int64) (*gitea.PullRequest, error) {
|
func (c *Client) GetPullRequest(owner, repo string, number int64) (*gitea.PullRequest, error) {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,132 @@ func TestClient_CreateIssue_Bad_ServerError_Good(t *testing.T) {
|
||||||
assert.Contains(t, err.Error(), "failed to create issue")
|
assert.Contains(t, err.Error(), "failed to create issue")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClient_EditIssue_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
issue, err := client.EditIssue("test-org", "org-repo", 1, giteaSDK.EditIssueOption{
|
||||||
|
Title: "Updated Title",
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotNil(t, issue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_EditIssue_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
_, err := client.EditIssue("test-org", "org-repo", 1, giteaSDK.EditIssueOption{
|
||||||
|
Title: "Updated Title",
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to edit issue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AssignIssue_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.AssignIssue("test-org", "org-repo", 1, []string{"dev1", "dev2"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AssignIssue_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.AssignIssue("test-org", "org-repo", 1, []string{"dev1"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to assign issue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CreateIssueComment_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.CreateIssueComment("test-org", "org-repo", 1, "LGTM")
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CreateIssueComment_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.CreateIssueComment("test-org", "org-repo", 1, "LGTM")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to create comment")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_GetIssueLabels_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
labels, err := client.GetIssueLabels("test-org", "org-repo", 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, labels, 1)
|
||||||
|
assert.Equal(t, "bug", labels[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_GetIssueLabels_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
_, err := client.GetIssueLabels("test-org", "org-repo", 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to get issue labels")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AddIssueLabels_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.AddIssueLabels("test-org", "org-repo", 1, []int64{1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AddIssueLabels_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.AddIssueLabels("test-org", "org-repo", 1, []int64{1})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to add labels to issue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_RemoveIssueLabel_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.RemoveIssueLabel("test-org", "org-repo", 1, 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_RemoveIssueLabel_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.RemoveIssueLabel("test-org", "org-repo", 1, 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to remove label from issue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CloseIssue_Good(t *testing.T) {
|
||||||
|
client, srv := newTestClient(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.CloseIssue("test-org", "org-repo", 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CloseIssue_Bad_ServerError_Good(t *testing.T) {
|
||||||
|
client, srv := newErrorServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
err := client.CloseIssue("test-org", "org-repo", 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to close issue")
|
||||||
|
}
|
||||||
|
|
||||||
func TestClient_ListPullRequests_Good(t *testing.T) {
|
func TestClient_ListPullRequests_Good(t *testing.T) {
|
||||||
client, srv := newTestClient(t)
|
client, srv := newTestClient(t)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
|
||||||
|
|
@ -85,18 +85,57 @@ func newGiteaMux() *http.ServeMux {
|
||||||
|
|
||||||
// Single issue.
|
// Single issue.
|
||||||
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1", func(w http.ResponseWriter, r *http.Request) {
|
||||||
jsonResponse(w, map[string]any{
|
switch r.Method {
|
||||||
"id": 1, "number": 1, "title": "Issue 1", "state": "open",
|
case http.MethodPatch:
|
||||||
"body": "First issue body",
|
jsonResponse(w, map[string]any{
|
||||||
})
|
"id": 1, "number": 1, "title": "Issue 1", "state": "closed",
|
||||||
|
"body": "First issue body",
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
jsonResponse(w, map[string]any{
|
||||||
|
"id": 1, "number": 1, "title": "Issue 1", "state": "open",
|
||||||
|
"body": "First issue body",
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Issue comments.
|
// Issue comments.
|
||||||
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1/comments", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1/comments", func(w http.ResponseWriter, r *http.Request) {
|
||||||
jsonResponse(w, []map[string]any{
|
switch r.Method {
|
||||||
{"id": 100, "body": "comment 1", "user": map[string]any{"login": "user1"}, "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T00:00:00Z"},
|
case http.MethodPost:
|
||||||
{"id": 101, "body": "comment 2", "user": map[string]any{"login": "user2"}, "created_at": "2026-01-02T00:00:00Z", "updated_at": "2026-01-02T00:00:00Z"},
|
w.WriteHeader(http.StatusCreated)
|
||||||
})
|
jsonResponse(w, map[string]any{
|
||||||
|
"id": 100, "body": "test comment",
|
||||||
|
"user": map[string]any{"login": "test-user"},
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
jsonResponse(w, []map[string]any{
|
||||||
|
{"id": 100, "body": "comment 1", "user": map[string]any{"login": "user1"}, "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T00:00:00Z"},
|
||||||
|
{"id": 101, "body": "comment 2", "user": map[string]any{"login": "user2"}, "created_at": "2026-01-02T00:00:00Z", "updated_at": "2026-01-02T00:00:00Z"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Issue labels.
|
||||||
|
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1/labels", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPost:
|
||||||
|
jsonResponse(w, []map[string]any{
|
||||||
|
{"id": 1, "name": "bug", "color": "#ff0000"},
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
jsonResponse(w, []map[string]any{
|
||||||
|
{"id": 1, "name": "bug", "color": "#ff0000"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove issue label.
|
||||||
|
mux.HandleFunc("/api/v1/repos/test-org/org-repo/issues/1/labels/1", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == http.MethodDelete {
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Pull requests.
|
// Pull requests.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue