mirror of
https://github.com/thegeeklab/wp-github-comment.git
synced 2024-11-21 13:50:40 +00:00
refactor: use dedicated github package (#115)
This commit is contained in:
parent
b0333e8700
commit
07d0b5405b
@ -95,3 +95,9 @@ run:
|
|||||||
linters-settings:
|
linters-settings:
|
||||||
gofumpt:
|
gofumpt:
|
||||||
extra-rules: true
|
extra-rules: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: "_test.go"
|
||||||
|
linters:
|
||||||
|
- err113
|
||||||
|
6
.mockery.yaml
Normal file
6
.mockery.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
all: True
|
||||||
|
dir: "{{.PackageName}}/mocks"
|
||||||
|
outpkg: "mocks"
|
||||||
|
packages:
|
||||||
|
github.com/thegeeklab/wp-github-comment/github:
|
8
Makefile
8
Makefile
@ -11,13 +11,14 @@ IMPORT := github.com/thegeeklab/$(EXECUTABLE)
|
|||||||
|
|
||||||
GO ?= go
|
GO ?= go
|
||||||
CWD ?= $(shell pwd)
|
CWD ?= $(shell pwd)
|
||||||
PACKAGES ?= $(shell go list ./...)
|
PACKAGES ?= $(shell go list ./... | grep -Ev '/mocks$$')
|
||||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||||
|
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@$(GOFUMPT_PACKAGE_VERSION)
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@$(GOFUMPT_PACKAGE_VERSION)
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_PACKAGE_VERSION)
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_PACKAGE_VERSION)
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
|
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
|
||||||
|
MOCKERY_PACKAGE ?= github.com/vektra/mockery/v2@latest
|
||||||
|
|
||||||
XGO_VERSION := go-1.22.x
|
XGO_VERSION := go-1.22.x
|
||||||
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
|
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
|
||||||
@ -65,10 +66,7 @@ lint: golangci-lint
|
|||||||
.PHONY: generate
|
.PHONY: generate
|
||||||
generate:
|
generate:
|
||||||
$(GO) generate $(PACKAGES)
|
$(GO) generate $(PACKAGES)
|
||||||
|
$(GO) run $(MOCKERY_PACKAGE)
|
||||||
.PHONY: generate-docs
|
|
||||||
generate-docs:
|
|
||||||
$(GO) generate ./cmd/$(EXECUTABLE)/flags.go
|
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
|
41
github/api.go
Normal file
41
github/api.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v61/github"
|
||||||
|
)
|
||||||
|
|
||||||
|
// APIClient is an interface that wraps the GitHub API client.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
type IssueService interface {
|
||||||
|
CreateComment(ctx context.Context, owner, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error)
|
||||||
|
EditComment(ctx context.Context, owner, repo string, commentID int64, comment *github.IssueComment) (*github.IssueComment, *github.Response, error)
|
||||||
|
ListComments(ctx context.Context, owner, repo string, number int, opts *github.IssueListCommentsOptions) ([]*github.IssueComment, *github.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type IssueServiceImpl struct {
|
||||||
|
client *github.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateComment wraps the CreateComment method of the github.IssuesService.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
func (s *IssueServiceImpl) CreateComment(ctx context.Context, owner, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) {
|
||||||
|
return s.client.Issues.CreateComment(ctx, owner, repo, number, comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditComment wraps the EditComment method of the github.IssuesService.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
func (s *IssueServiceImpl) EditComment(ctx context.Context, owner, repo string, commentID int64, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) {
|
||||||
|
return s.client.Issues.EditComment(ctx, owner, repo, commentID, comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComments wraps the ListComments method of the github.IssuesService.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
func (s *IssueServiceImpl) ListComments(ctx context.Context, owner, repo string, number int, opts *github.IssueListCommentsOptions) ([]*github.IssueComment, *github.Response, error) {
|
||||||
|
return s.client.Issues.ListComments(ctx, owner, repo, number, opts)
|
||||||
|
}
|
117
github/github.go
Normal file
117
github/github.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v61/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrCommentNotFound = errors.New("comment not found")
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
client *github.Client
|
||||||
|
Issue *Issue
|
||||||
|
}
|
||||||
|
|
||||||
|
type Issue struct {
|
||||||
|
client IssueService
|
||||||
|
Opt IssueOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
type IssueOptions struct {
|
||||||
|
Number int
|
||||||
|
Message string
|
||||||
|
Key string
|
||||||
|
Repo string
|
||||||
|
Owner string
|
||||||
|
Update bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGitHubClient creates a new GitHubClient instance that wraps the provided GitHub API client.
|
||||||
|
// The GitHubClient provides a higher-level interface for interacting with the GitHub API,
|
||||||
|
// including methods for managing GitHub issues.
|
||||||
|
func NewClient(ctx context.Context, url *url.URL, token string, client *http.Client) *Client {
|
||||||
|
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
|
||||||
|
tc := oauth2.NewClient(
|
||||||
|
context.WithValue(ctx, oauth2.HTTPClient, client),
|
||||||
|
ts,
|
||||||
|
)
|
||||||
|
|
||||||
|
c := github.NewClient(tc)
|
||||||
|
c.BaseURL = url
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
client: c,
|
||||||
|
Issue: &Issue{
|
||||||
|
client: &IssueServiceImpl{client: c},
|
||||||
|
Opt: IssueOptions{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddComment adds a new comment or updates an existing comment on a GitHub issue.
|
||||||
|
// If the Update field is true, it will append a unique identifier to the comment
|
||||||
|
// body and attempt to find and update the existing comment with that identifier.
|
||||||
|
// Otherwise, it will create a new comment on the issue.
|
||||||
|
func (i *Issue) AddComment(ctx context.Context) (*github.IssueComment, error) {
|
||||||
|
issueComment := &github.IssueComment{
|
||||||
|
Body: &i.Opt.Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Opt.Update {
|
||||||
|
// Append plugin comment ID to comment message so we can search for it later
|
||||||
|
*issueComment.Body = fmt.Sprintf("%s\n<!-- id: %s -->\n", i.Opt.Message, i.Opt.Key)
|
||||||
|
|
||||||
|
comment, err := i.FindComment(ctx)
|
||||||
|
if err != nil && !errors.Is(err, ErrCommentNotFound) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if comment != nil {
|
||||||
|
comment, _, err = i.client.EditComment(ctx, i.Opt.Owner, i.Opt.Repo, *comment.ID, issueComment)
|
||||||
|
|
||||||
|
return comment, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comment, _, err := i.client.CreateComment(ctx, i.Opt.Owner, i.Opt.Repo, i.Opt.Number, issueComment)
|
||||||
|
|
||||||
|
return comment, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindComment returns the GitHub issue comment that contains the specified key, or nil if no such comment exists.
|
||||||
|
// It retrieves all comments on the issue and searches for one that contains the specified key in the comment body.
|
||||||
|
func (i *Issue) FindComment(ctx context.Context) (*github.IssueComment, error) {
|
||||||
|
var allComments []*github.IssueComment
|
||||||
|
|
||||||
|
opts := &github.IssueListCommentsOptions{}
|
||||||
|
|
||||||
|
for {
|
||||||
|
comments, resp, err := i.client.ListComments(ctx, i.Opt.Owner, i.Opt.Repo, i.Opt.Number, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
allComments = append(allComments, comments...)
|
||||||
|
|
||||||
|
if resp == nil || resp.NextPage == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.Page = resp.NextPage
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, comment := range allComments {
|
||||||
|
if strings.Contains(*comment.Body, fmt.Sprintf("<!-- id: %s -->", i.Opt.Key)) {
|
||||||
|
return comment, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("%w: failed to find comment with key %s", ErrCommentNotFound, i.Opt.Key)
|
||||||
|
}
|
210
github/github_test.go
Normal file
210
github/github_test.go
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v61/github"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/thegeeklab/wp-github-comment/github/mocks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGithubIssue_FindComment(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
issueOpt IssueOptions
|
||||||
|
comments []*github.IssueComment
|
||||||
|
want *github.IssueComment
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no comments",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
},
|
||||||
|
wantErr: ErrCommentNotFound,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "comment found",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
},
|
||||||
|
comments: []*github.IssueComment{
|
||||||
|
{Body: github.String("<!-- id: test-key -->\ntest comment\n")},
|
||||||
|
},
|
||||||
|
want: &github.IssueComment{
|
||||||
|
Body: github.String("<!-- id: test-key -->\ntest comment\n"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "comment not found",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
},
|
||||||
|
comments: []*github.IssueComment{
|
||||||
|
{Body: github.String("other comment")},
|
||||||
|
},
|
||||||
|
wantErr: ErrCommentNotFound,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple comments",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
},
|
||||||
|
comments: []*github.IssueComment{
|
||||||
|
{Body: github.String("other comment")},
|
||||||
|
{Body: github.String("<!-- id: test-key -->\ntest comment\n")},
|
||||||
|
{Body: github.String("another comment")},
|
||||||
|
},
|
||||||
|
want: &github.IssueComment{Body: github.String("<!-- id: test-key -->\ntest comment\n")},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mockClient := mocks.NewMockIssueService(t)
|
||||||
|
issue := &Issue{
|
||||||
|
client: mockClient,
|
||||||
|
Opt: tt.issueOpt,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockClient.
|
||||||
|
On("ListComments", mock.Anything, tt.issueOpt.Owner, tt.issueOpt.Repo, mock.Anything, mock.Anything).
|
||||||
|
Return(tt.comments, nil, nil)
|
||||||
|
|
||||||
|
got, err := issue.FindComment(context.Background())
|
||||||
|
if tt.wantErr != nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGithubIssue_AddComment(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
issueOpt IssueOptions
|
||||||
|
comments []*github.IssueComment
|
||||||
|
want *github.IssueComment
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "create new comment",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Message: "test message",
|
||||||
|
Update: false,
|
||||||
|
},
|
||||||
|
want: &github.IssueComment{
|
||||||
|
Body: github.String("<!-- id: test-key -->\ntest message\n"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update existing comment",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Message: "test message",
|
||||||
|
Update: true,
|
||||||
|
},
|
||||||
|
comments: []*github.IssueComment{
|
||||||
|
{ID: github.Int64(123), Body: github.String("<!-- id: test-key -->\ntest message\n")},
|
||||||
|
},
|
||||||
|
want: &github.IssueComment{
|
||||||
|
Body: github.String("<!-- id: test-key -->\ntest message\n"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update non-existing comment",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Message: "test message",
|
||||||
|
Update: true,
|
||||||
|
},
|
||||||
|
want: &github.IssueComment{
|
||||||
|
Body: github.String("<!-- id: test-key -->\ntest message\n"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "create new comment with error",
|
||||||
|
issueOpt: IssueOptions{
|
||||||
|
Key: "test-key",
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Message: "test message",
|
||||||
|
Update: false,
|
||||||
|
},
|
||||||
|
wantErr: errors.New("internal server error"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mockClient := mocks.NewMockIssueService(t)
|
||||||
|
issue := &Issue{
|
||||||
|
client: mockClient,
|
||||||
|
Opt: tt.issueOpt,
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.issueOpt.Update {
|
||||||
|
mockClient.
|
||||||
|
On("ListComments", mock.Anything, tt.issueOpt.Owner, tt.issueOpt.Repo, mock.Anything, mock.Anything).
|
||||||
|
Return(tt.comments, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.issueOpt.Update && tt.comments != nil {
|
||||||
|
mockClient.
|
||||||
|
On("EditComment", mock.Anything, tt.issueOpt.Owner, tt.issueOpt.Repo, mock.Anything, mock.Anything).
|
||||||
|
Return(&github.IssueComment{
|
||||||
|
Body: github.String(fmt.Sprintf("<!-- id: %s -->\n%s\n", tt.issueOpt.Key, tt.issueOpt.Message)),
|
||||||
|
}, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.comments == nil {
|
||||||
|
var comment *github.IssueComment
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
comment = &github.IssueComment{
|
||||||
|
Body: github.String(fmt.Sprintf("<!-- id: %s -->\n%s\n", tt.issueOpt.Key, tt.issueOpt.Message)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockClient.
|
||||||
|
On("CreateComment", mock.Anything, tt.issueOpt.Owner, tt.issueOpt.Repo, mock.Anything, mock.Anything).
|
||||||
|
Return(comment, nil, tt.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := issue.AddComment(context.Background())
|
||||||
|
if tt.wantErr != nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
250
github/mocks/mock_IssueService.go
Normal file
250
github/mocks/mock_IssueService.go
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
// Code generated by mockery v2.43.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
github "github.com/google/go-github/v61/github"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockIssueService is an autogenerated mock type for the IssueService type
|
||||||
|
type MockIssueService struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockIssueService_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockIssueService) EXPECT() *MockIssueService_Expecter {
|
||||||
|
return &MockIssueService_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateComment provides a mock function with given fields: ctx, owner, repo, number, comment
|
||||||
|
func (_m *MockIssueService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, number, comment)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for CreateComment")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *github.IssueComment
|
||||||
|
var r1 *github.Response
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int, *github.IssueComment) (*github.IssueComment, *github.Response, error)); ok {
|
||||||
|
return rf(ctx, owner, repo, number, comment)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int, *github.IssueComment) *github.IssueComment); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, number, comment)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.IssueComment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, int, *github.IssueComment) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, number, comment)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, int, *github.IssueComment) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, number, comment)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockIssueService_CreateComment_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateComment'
|
||||||
|
type MockIssueService_CreateComment_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateComment is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - owner string
|
||||||
|
// - repo string
|
||||||
|
// - number int
|
||||||
|
// - comment *github.IssueComment
|
||||||
|
func (_e *MockIssueService_Expecter) CreateComment(ctx interface{}, owner interface{}, repo interface{}, number interface{}, comment interface{}) *MockIssueService_CreateComment_Call {
|
||||||
|
return &MockIssueService_CreateComment_Call{Call: _e.mock.On("CreateComment", ctx, owner, repo, number, comment)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_CreateComment_Call) Run(run func(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment)) *MockIssueService_CreateComment_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(int), args[4].(*github.IssueComment))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_CreateComment_Call) Return(_a0 *github.IssueComment, _a1 *github.Response, _a2 error) *MockIssueService_CreateComment_Call {
|
||||||
|
_c.Call.Return(_a0, _a1, _a2)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_CreateComment_Call) RunAndReturn(run func(context.Context, string, string, int, *github.IssueComment) (*github.IssueComment, *github.Response, error)) *MockIssueService_CreateComment_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditComment provides a mock function with given fields: ctx, owner, repo, commentID, comment
|
||||||
|
func (_m *MockIssueService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, commentID, comment)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for EditComment")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 *github.IssueComment
|
||||||
|
var r1 *github.Response
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int64, *github.IssueComment) (*github.IssueComment, *github.Response, error)); ok {
|
||||||
|
return rf(ctx, owner, repo, commentID, comment)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int64, *github.IssueComment) *github.IssueComment); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, commentID, comment)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.IssueComment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, int64, *github.IssueComment) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, commentID, comment)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, int64, *github.IssueComment) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, commentID, comment)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockIssueService_EditComment_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EditComment'
|
||||||
|
type MockIssueService_EditComment_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditComment is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - owner string
|
||||||
|
// - repo string
|
||||||
|
// - commentID int64
|
||||||
|
// - comment *github.IssueComment
|
||||||
|
func (_e *MockIssueService_Expecter) EditComment(ctx interface{}, owner interface{}, repo interface{}, commentID interface{}, comment interface{}) *MockIssueService_EditComment_Call {
|
||||||
|
return &MockIssueService_EditComment_Call{Call: _e.mock.On("EditComment", ctx, owner, repo, commentID, comment)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_EditComment_Call) Run(run func(ctx context.Context, owner string, repo string, commentID int64, comment *github.IssueComment)) *MockIssueService_EditComment_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(int64), args[4].(*github.IssueComment))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_EditComment_Call) Return(_a0 *github.IssueComment, _a1 *github.Response, _a2 error) *MockIssueService_EditComment_Call {
|
||||||
|
_c.Call.Return(_a0, _a1, _a2)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_EditComment_Call) RunAndReturn(run func(context.Context, string, string, int64, *github.IssueComment) (*github.IssueComment, *github.Response, error)) *MockIssueService_EditComment_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComments provides a mock function with given fields: ctx, owner, repo, number, opts
|
||||||
|
func (_m *MockIssueService) ListComments(ctx context.Context, owner string, repo string, number int, opts *github.IssueListCommentsOptions) ([]*github.IssueComment, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, number, opts)
|
||||||
|
|
||||||
|
if len(ret) == 0 {
|
||||||
|
panic("no return value specified for ListComments")
|
||||||
|
}
|
||||||
|
|
||||||
|
var r0 []*github.IssueComment
|
||||||
|
var r1 *github.Response
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int, *github.IssueListCommentsOptions) ([]*github.IssueComment, *github.Response, error)); ok {
|
||||||
|
return rf(ctx, owner, repo, number, opts)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int, *github.IssueListCommentsOptions) []*github.IssueComment); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, number, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*github.IssueComment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, int, *github.IssueListCommentsOptions) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, number, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, int, *github.IssueListCommentsOptions) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, number, opts)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockIssueService_ListComments_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListComments'
|
||||||
|
type MockIssueService_ListComments_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComments is a helper method to define mock.On call
|
||||||
|
// - ctx context.Context
|
||||||
|
// - owner string
|
||||||
|
// - repo string
|
||||||
|
// - number int
|
||||||
|
// - opts *github.IssueListCommentsOptions
|
||||||
|
func (_e *MockIssueService_Expecter) ListComments(ctx interface{}, owner interface{}, repo interface{}, number interface{}, opts interface{}) *MockIssueService_ListComments_Call {
|
||||||
|
return &MockIssueService_ListComments_Call{Call: _e.mock.On("ListComments", ctx, owner, repo, number, opts)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_ListComments_Call) Run(run func(ctx context.Context, owner string, repo string, number int, opts *github.IssueListCommentsOptions)) *MockIssueService_ListComments_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(int), args[4].(*github.IssueListCommentsOptions))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_ListComments_Call) Return(_a0 []*github.IssueComment, _a1 *github.Response, _a2 error) *MockIssueService_ListComments_Call {
|
||||||
|
_c.Call.Return(_a0, _a1, _a2)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockIssueService_ListComments_Call) RunAndReturn(run func(context.Context, string, string, int, *github.IssueListCommentsOptions) ([]*github.IssueComment, *github.Response, error)) *MockIssueService_ListComments_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockIssueService creates a new instance of MockIssueService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockIssueService(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockIssueService {
|
||||||
|
mock := &MockIssueService{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
5
go.mod
5
go.mod
@ -4,7 +4,6 @@ go 1.22
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/go-github/v61 v61.0.0
|
github.com/google/go-github/v61 v61.0.0
|
||||||
github.com/migueleliasweb/go-github-mock v0.0.23
|
|
||||||
github.com/rs/zerolog v1.32.0
|
github.com/rs/zerolog v1.32.0
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/thegeeklab/wp-plugin-go/v2 v2.3.1
|
github.com/thegeeklab/wp-plugin-go/v2 v2.3.1
|
||||||
@ -18,10 +17,8 @@ require (
|
|||||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/google/go-github/v59 v59.0.0 // indirect
|
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/uuid v1.1.1 // indirect
|
github.com/google/uuid v1.1.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
|
||||||
github.com/huandu/xstrings v1.3.3 // indirect
|
github.com/huandu/xstrings v1.3.3 // indirect
|
||||||
github.com/imdario/mergo v0.3.11 // indirect
|
github.com/imdario/mergo v0.3.11 // indirect
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
@ -33,10 +30,10 @@ require (
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/shopspring/decimal v1.2.0 // indirect
|
github.com/shopspring/decimal v1.2.0 // indirect
|
||||||
github.com/spf13/cast v1.3.1 // indirect
|
github.com/spf13/cast v1.3.1 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
||||||
golang.org/x/crypto v0.23.0 // indirect
|
golang.org/x/crypto v0.23.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
10
go.sum
10
go.sum
@ -15,16 +15,12 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-github/v59 v59.0.0 h1:7h6bgpF5as0YQLLkEiVqpgtJqjimMYhBkD4jT5aN3VA=
|
|
||||||
github.com/google/go-github/v59 v59.0.0/go.mod h1:rJU4R0rQHFVFDOkqGWxfLNo6vEk4dv40oDjhV/gH6wM=
|
|
||||||
github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go=
|
github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go=
|
||||||
github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY=
|
github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
|
||||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||||
@ -36,8 +32,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
|||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/migueleliasweb/go-github-mock v0.0.23 h1:GOi9oX/+Seu9JQ19V8bPDLqDI7M9iEOjo3g8v1k6L2c=
|
|
||||||
github.com/migueleliasweb/go-github-mock v0.0.23/go.mod h1:NsT8FGbkvIZQtDu38+295sZEX8snaUiiQgsGxi6GUxk=
|
|
||||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||||
@ -55,6 +49,8 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
|
|||||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
@ -100,8 +96,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
package plugin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/google/go-github/v61/github"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrCommentNotFound = errors.New("no comment found")
|
|
||||||
|
|
||||||
type GithubClient struct {
|
|
||||||
Client *github.Client
|
|
||||||
Issue *GithubIssue
|
|
||||||
}
|
|
||||||
|
|
||||||
type GithubIssue struct {
|
|
||||||
*github.Client
|
|
||||||
Number int
|
|
||||||
Message string
|
|
||||||
Key string
|
|
||||||
Repo string
|
|
||||||
Owner string
|
|
||||||
Update bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor function for Parent.
|
|
||||||
func NewGithubClient(client *github.Client) *GithubClient {
|
|
||||||
return &GithubClient{
|
|
||||||
Client: client,
|
|
||||||
Issue: &GithubIssue{Client: client},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddComment adds a new comment or updates an existing comment on a GitHub issue.
|
|
||||||
// If the Update field is true, it will append a unique identifier to the comment
|
|
||||||
// body and attempt to find and update the existing comment with that identifier.
|
|
||||||
// Otherwise, it will create a new comment on the issue.
|
|
||||||
func (i *GithubIssue) AddComment(ctx context.Context) (*github.IssueComment, error) {
|
|
||||||
issueComment := &github.IssueComment{
|
|
||||||
Body: &i.Message,
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.Update {
|
|
||||||
// Append plugin comment ID to comment message so we can search for it later
|
|
||||||
*issueComment.Body = fmt.Sprintf("%s\n<!-- id: %s -->\n", i.Message, i.Key)
|
|
||||||
|
|
||||||
comment, err := i.FindComment(ctx)
|
|
||||||
if err != nil && !errors.Is(err, ErrCommentNotFound) {
|
|
||||||
return comment, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if comment != nil {
|
|
||||||
comment, _, err = i.Client.Issues.EditComment(ctx, i.Owner, i.Repo, *comment.ID, issueComment)
|
|
||||||
|
|
||||||
return comment, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comment, _, err := i.Client.Issues.CreateComment(ctx, i.Owner, i.Repo, i.Number, issueComment)
|
|
||||||
|
|
||||||
return comment, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindComment returns the GitHub issue comment that contains the specified key, or nil if no such comment exists.
|
|
||||||
// It retrieves all comments on the issue and searches for one that contains the specified key in the comment body.
|
|
||||||
func (i *GithubIssue) FindComment(ctx context.Context) (*github.IssueComment, error) {
|
|
||||||
var allComments []*github.IssueComment
|
|
||||||
|
|
||||||
opts := &github.IssueListCommentsOptions{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
comments, resp, err := i.Client.Issues.ListComments(ctx, i.Owner, i.Repo, i.Number, opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
allComments = append(allComments, comments...)
|
|
||||||
|
|
||||||
if resp.NextPage == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Page = resp.NextPage
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, comment := range allComments {
|
|
||||||
if strings.Contains(*comment.Body, fmt.Sprintf("<!-- id: %s -->", i.Key)) {
|
|
||||||
return comment, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("%w key: %s", ErrCommentNotFound, i.Key)
|
|
||||||
}
|
|
@ -1,192 +0,0 @@
|
|||||||
package plugin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-github/v61/github"
|
|
||||||
"github.com/migueleliasweb/go-github-mock/src/mock"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGithubIssue_FindComment(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
key := "test-key"
|
|
||||||
keyPattern := "<!-- id: " + key + " -->"
|
|
||||||
owner := "test-owner"
|
|
||||||
repo := "test-repo"
|
|
||||||
number := 1
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
comments []*github.IssueComment
|
|
||||||
want *github.IssueComment
|
|
||||||
wantErr error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "no comments",
|
|
||||||
want: nil,
|
|
||||||
wantErr: ErrCommentNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "comment found",
|
|
||||||
comments: []*github.IssueComment{
|
|
||||||
{Body: github.String(keyPattern)},
|
|
||||||
},
|
|
||||||
want: &github.IssueComment{Body: github.String(keyPattern)},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "comment not found",
|
|
||||||
comments: []*github.IssueComment{
|
|
||||||
{Body: github.String("other comment")},
|
|
||||||
},
|
|
||||||
want: nil,
|
|
||||||
wantErr: ErrCommentNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multiple comments",
|
|
||||||
comments: []*github.IssueComment{
|
|
||||||
{Body: github.String("other comment")},
|
|
||||||
{Body: github.String(keyPattern)},
|
|
||||||
{Body: github.String("another comment")},
|
|
||||||
},
|
|
||||||
want: &github.IssueComment{Body: github.String(keyPattern)},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
mockedHTTPClient := mock.NewMockedHTTPClient(
|
|
||||||
mock.WithRequestMatch(
|
|
||||||
mock.GetReposIssuesCommentsByOwnerByRepoByIssueNumber,
|
|
||||||
tt.comments,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
client := github.NewClient(mockedHTTPClient)
|
|
||||||
issue := &GithubIssue{
|
|
||||||
Client: client,
|
|
||||||
Owner: owner,
|
|
||||||
Repo: repo,
|
|
||||||
Number: number,
|
|
||||||
Key: key,
|
|
||||||
}
|
|
||||||
|
|
||||||
got, err := issue.FindComment(ctx)
|
|
||||||
if tt.wantErr != nil {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Equal(t, tt.want, got)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, tt.want, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGithubIssue_AddComment(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
key := "test-key"
|
|
||||||
keyPattern := "<!-- id: " + key + " -->"
|
|
||||||
owner := "test-owner"
|
|
||||||
repo := "test-repo"
|
|
||||||
number := 1
|
|
||||||
message := "test message"
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
update bool
|
|
||||||
existingKey string
|
|
||||||
comments []*github.IssueComment
|
|
||||||
want *github.IssueComment
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "create new comment",
|
|
||||||
update: false,
|
|
||||||
want: &github.IssueComment{Body: github.String("test message\n<!-- id: test-key -->\n")},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "update existing comment",
|
|
||||||
update: true,
|
|
||||||
comments: []*github.IssueComment{
|
|
||||||
{ID: github.Int64(123), Body: github.String(keyPattern)},
|
|
||||||
},
|
|
||||||
want: &github.IssueComment{Body: github.String("test message\n<!-- id: test-key -->\n")},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "update non-existing comment",
|
|
||||||
update: true,
|
|
||||||
want: &github.IssueComment{Body: github.String("test message\n<!-- id: test-key -->\n")},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "create new comment with error",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
mockedHTTPClient := mock.NewMockedHTTPClient(
|
|
||||||
mock.WithRequestMatch(
|
|
||||||
mock.GetReposIssuesCommentsByOwnerByRepoByIssueNumber,
|
|
||||||
tt.comments,
|
|
||||||
),
|
|
||||||
mock.WithRequestMatchHandler(
|
|
||||||
mock.PostReposIssuesCommentsByOwnerByRepoByIssueNumber,
|
|
||||||
http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
if tt.wantErr {
|
|
||||||
mock.WriteError(w, http.StatusInternalServerError, "internal server error")
|
|
||||||
} else {
|
|
||||||
_, _ = w.Write(mock.MustMarshal(
|
|
||||||
&github.IssueComment{
|
|
||||||
Body: github.String(fmt.Sprintf("%s\n%s\n", message, keyPattern)),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
mock.WithRequestMatchHandler(
|
|
||||||
mock.PatchReposIssuesCommentsByOwnerByRepoByCommentId,
|
|
||||||
http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
if tt.wantErr {
|
|
||||||
mock.WriteError(w, http.StatusInternalServerError, "internal server error")
|
|
||||||
} else {
|
|
||||||
_, _ = w.Write(mock.MustMarshal(
|
|
||||||
&github.IssueComment{
|
|
||||||
Body: github.String(fmt.Sprintf("%s\n%s\n", message, keyPattern)),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
client := github.NewClient(mockedHTTPClient)
|
|
||||||
issue := &GithubIssue{
|
|
||||||
Client: client,
|
|
||||||
Owner: owner,
|
|
||||||
Repo: repo,
|
|
||||||
Number: number,
|
|
||||||
Key: key,
|
|
||||||
Message: message,
|
|
||||||
Update: tt.update,
|
|
||||||
}
|
|
||||||
|
|
||||||
got, err := issue.AddComment(ctx)
|
|
||||||
if tt.wantErr {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Equal(t, tt.want, got)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, tt.want, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,10 +8,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-github/v61/github"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
gh "github.com/thegeeklab/wp-github-comment/github"
|
||||||
"github.com/thegeeklab/wp-plugin-go/v2/file"
|
"github.com/thegeeklab/wp-plugin-go/v2/file"
|
||||||
"golang.org/x/oauth2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrPluginEventNotSupported = errors.New("event not supported")
|
var ErrPluginEventNotSupported = errors.New("event not supported")
|
||||||
@ -22,7 +21,6 @@ func (p *Plugin) run(ctx context.Context) error {
|
|||||||
return fmt.Errorf("validation failed: %w", err)
|
return fmt.Errorf("validation failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:contextcheck
|
|
||||||
if err := p.Execute(); err != nil {
|
if err := p.Execute(); err != nil {
|
||||||
return fmt.Errorf("execution failed: %w", err)
|
return fmt.Errorf("execution failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -68,22 +66,15 @@ func (p *Plugin) Validate() error {
|
|||||||
|
|
||||||
// Execute provides the implementation of the plugin.
|
// Execute provides the implementation of the plugin.
|
||||||
func (p *Plugin) Execute() error {
|
func (p *Plugin) Execute() error {
|
||||||
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: p.Settings.APIKey})
|
client := gh.NewClient(p.Network.Context, p.Settings.baseURL, p.Settings.APIKey, p.Network.Client)
|
||||||
tc := oauth2.NewClient(
|
client.Issue.Opt = gh.IssueOptions{
|
||||||
context.WithValue(p.Network.Context, oauth2.HTTPClient, p.Network.Client),
|
Repo: p.Metadata.Repository.Name,
|
||||||
ts,
|
Owner: p.Metadata.Repository.Owner,
|
||||||
)
|
Message: p.Settings.Message,
|
||||||
|
Update: p.Settings.Update,
|
||||||
gh := github.NewClient(tc)
|
Key: p.Settings.Key,
|
||||||
gh.BaseURL = p.Settings.baseURL
|
Number: p.Metadata.Curr.PullRequest,
|
||||||
|
}
|
||||||
client := NewGithubClient(gh)
|
|
||||||
client.Issue.Repo = p.Metadata.Repository.Name
|
|
||||||
client.Issue.Owner = p.Metadata.Repository.Owner
|
|
||||||
client.Issue.Message = p.Settings.Message
|
|
||||||
client.Issue.Update = p.Settings.Update
|
|
||||||
client.Issue.Key = p.Settings.Key
|
|
||||||
client.Issue.Number = p.Metadata.Curr.PullRequest
|
|
||||||
|
|
||||||
if p.Settings.SkipMissing && !p.Settings.IsFile {
|
if p.Settings.SkipMissing && !p.Settings.IsFile {
|
||||||
log.Info().
|
log.Info().
|
||||||
|
Loading…
Reference in New Issue
Block a user