diff --git a/.github/workflows/on_pull-request_closed.yaml b/.github/workflows/on_pull-request_closed.yaml index 3fff54c1..64d1d4ca 100644 --- a/.github/workflows/on_pull-request_closed.yaml +++ b/.github/workflows/on_pull-request_closed.yaml @@ -12,6 +12,7 @@ env: jobs: remove-temp-image: runs-on: ubuntu-22.04 + continue-on-error: true # should match env.FS_TAG, in both pr-open.yaml and pr-close.yaml concurrency: pr-${{ github.event.pull_request.number }} diff --git a/.mockery.yaml b/.mockery.yaml index 4ca7eead..41be59a8 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -5,11 +5,7 @@ packages: # place your package-specific config here config: all: true - github.com/zapier/kubechecks/pkg/generator: - # place your package-specific config here - config: - all: true - github.com/zapier/kubechecks/pkg/affected_apps: + github.com/zapier/kubechecks/pkg/vcs/gitlab_client: # place your package-specific config here config: all: true diff --git a/cmd/root.go b/cmd/root.go index 06618df0..759f8710 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -115,6 +115,9 @@ func init() { stringFlag(flags, "worst-hooks-state", "The worst state that can be returned from the hooks renderer.", newStringOpts(). withDefault("panic")) + stringFlag(flags, "replan-comment-msg", "comment message which re-triggers kubechecks on PR.", + newStringOpts(). + withDefault("kubechecks again")) panicIfError(viper.BindPFlags(flags)) setupLogOutput() diff --git a/docs/usage.md b/docs/usage.md index b21725bd..ed61c6ca 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -64,6 +64,7 @@ The full list of supported environment variables is described below: |`KUBECHECKS_OTEL_ENABLED`|Enable OpenTelemetry.|`false`| |`KUBECHECKS_PERSIST_LOG_LEVEL`|Persists the set log level down to other module loggers.|`false`| |`KUBECHECKS_POLICIES_LOCATION`|Sets rego policy locations to be used for every check request. Can be common path inside the repos being checked or git urls in either git or http(s) format.|`[./policies]`| +|`KUBECHECKS_REPLAN_COMMENT_MSG`|comment message which re-triggers kubechecks on PR.|`kubechecks again`| |`KUBECHECKS_REPO_REFRESH_INTERVAL`|Interval between static repo refreshes (for schemas and policies).|`5m`| |`KUBECHECKS_SCHEMAS_LOCATION`|Sets schema locations to be used for every check request. Can be common paths inside the repos being checked or git urls in either git or http(s) format.|`[]`| |`KUBECHECKS_SHOW_DEBUG_INFO`|Set to true to print debug info to the footer of MR comments.|`false`| diff --git a/go.mod b/go.mod index 7349562d..eac8cc40 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - github.com/xanzy/go-gitlab v0.105.0 + github.com/xanzy/go-gitlab v0.107.0 github.com/yannh/kubeconform v0.6.4 github.com/ziflex/lecho/v3 v3.5.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 diff --git a/go.sum b/go.sum index 86d55bbe..3c6298d1 100644 --- a/go.sum +++ b/go.sum @@ -667,8 +667,11 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= -github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -1026,6 +1029,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/xanzy/go-gitlab v0.105.0 h1:3nyLq0ESez0crcaM19o5S//SvezOQguuIHZ3wgX64hM= github.com/xanzy/go-gitlab v0.105.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= +github.com/xanzy/go-gitlab v0.107.0 h1:P2CT9Uy9yN9lJo3FLxpMZ4xj6uWcpnigXsjvqJ6nd2Y= +github.com/xanzy/go-gitlab v0.107.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= diff --git a/mocks/gitlab_client/mocks/mock_CommitsServices.go b/mocks/gitlab_client/mocks/mock_CommitsServices.go new file mode 100644 index 00000000..61b67deb --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_CommitsServices.go @@ -0,0 +1,116 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockCommitsServices is an autogenerated mock type for the CommitsServices type +type MockCommitsServices struct { + mock.Mock +} + +type MockCommitsServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockCommitsServices) EXPECT() *MockCommitsServices_Expecter { + return &MockCommitsServices_Expecter{mock: &_m.Mock} +} + +// SetCommitStatus provides a mock function with given fields: pid, sha, opt, options +func (_m *MockCommitsServices) SetCommitStatus(pid interface{}, sha string, opt *gitlab.SetCommitStatusOptions, options ...gitlab.RequestOptionFunc) (*gitlab.CommitStatus, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, sha, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.CommitStatus + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, string, *gitlab.SetCommitStatusOptions, ...gitlab.RequestOptionFunc) (*gitlab.CommitStatus, *gitlab.Response, error)); ok { + return rf(pid, sha, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, string, *gitlab.SetCommitStatusOptions, ...gitlab.RequestOptionFunc) *gitlab.CommitStatus); ok { + r0 = rf(pid, sha, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.CommitStatus) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, string, *gitlab.SetCommitStatusOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, sha, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, string, *gitlab.SetCommitStatusOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, sha, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockCommitsServices_SetCommitStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetCommitStatus' +type MockCommitsServices_SetCommitStatus_Call struct { + *mock.Call +} + +// SetCommitStatus is a helper method to define mock.On call +// - pid interface{} +// - sha string +// - opt *gitlab.SetCommitStatusOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockCommitsServices_Expecter) SetCommitStatus(pid interface{}, sha interface{}, opt interface{}, options ...interface{}) *MockCommitsServices_SetCommitStatus_Call { + return &MockCommitsServices_SetCommitStatus_Call{Call: _e.mock.On("SetCommitStatus", + append([]interface{}{pid, sha, opt}, options...)...)} +} + +func (_c *MockCommitsServices_SetCommitStatus_Call) Run(run func(pid interface{}, sha string, opt *gitlab.SetCommitStatusOptions, options ...gitlab.RequestOptionFunc)) *MockCommitsServices_SetCommitStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(string), args[2].(*gitlab.SetCommitStatusOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockCommitsServices_SetCommitStatus_Call) Return(_a0 *gitlab.CommitStatus, _a1 *gitlab.Response, _a2 error) *MockCommitsServices_SetCommitStatus_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockCommitsServices_SetCommitStatus_Call) RunAndReturn(run func(interface{}, string, *gitlab.SetCommitStatusOptions, ...gitlab.RequestOptionFunc) (*gitlab.CommitStatus, *gitlab.Response, error)) *MockCommitsServices_SetCommitStatus_Call { + _c.Call.Return(run) + return _c +} + +// NewMockCommitsServices creates a new instance of MockCommitsServices. 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 NewMockCommitsServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockCommitsServices { + mock := &MockCommitsServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/gitlab_client/mocks/mock_MergeRequestsServices.go b/mocks/gitlab_client/mocks/mock_MergeRequestsServices.go new file mode 100644 index 00000000..a01086c6 --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_MergeRequestsServices.go @@ -0,0 +1,436 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockMergeRequestsServices is an autogenerated mock type for the MergeRequestsServices type +type MockMergeRequestsServices struct { + mock.Mock +} + +type MockMergeRequestsServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockMergeRequestsServices) EXPECT() *MockMergeRequestsServices_Expecter { + return &MockMergeRequestsServices_Expecter{mock: &_m.Mock} +} + +// GetMergeRequest provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockMergeRequestsServices) GetMergeRequest(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.MergeRequest + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestsOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestsOptions, ...gitlab.RequestOptionFunc) *gitlab.MergeRequest); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.MergeRequest) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.GetMergeRequestsOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.GetMergeRequestsOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockMergeRequestsServices_GetMergeRequest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMergeRequest' +type MockMergeRequestsServices_GetMergeRequest_Call struct { + *mock.Call +} + +// GetMergeRequest is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.GetMergeRequestsOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockMergeRequestsServices_Expecter) GetMergeRequest(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockMergeRequestsServices_GetMergeRequest_Call { + return &MockMergeRequestsServices_GetMergeRequest_Call{Call: _e.mock.On("GetMergeRequest", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockMergeRequestsServices_GetMergeRequest_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc)) *MockMergeRequestsServices_GetMergeRequest_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.GetMergeRequestsOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequest_Call) Return(_a0 *gitlab.MergeRequest, _a1 *gitlab.Response, _a2 error) *MockMergeRequestsServices_GetMergeRequest_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequest_Call) RunAndReturn(run func(interface{}, int, *gitlab.GetMergeRequestsOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)) *MockMergeRequestsServices_GetMergeRequest_Call { + _c.Call.Return(run) + return _c +} + +// GetMergeRequestChanges provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockMergeRequestsServices) GetMergeRequestChanges(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestChangesOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.MergeRequest + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestChangesOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestChangesOptions, ...gitlab.RequestOptionFunc) *gitlab.MergeRequest); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.MergeRequest) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.GetMergeRequestChangesOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.GetMergeRequestChangesOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockMergeRequestsServices_GetMergeRequestChanges_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMergeRequestChanges' +type MockMergeRequestsServices_GetMergeRequestChanges_Call struct { + *mock.Call +} + +// GetMergeRequestChanges is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.GetMergeRequestChangesOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockMergeRequestsServices_Expecter) GetMergeRequestChanges(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockMergeRequestsServices_GetMergeRequestChanges_Call { + return &MockMergeRequestsServices_GetMergeRequestChanges_Call{Call: _e.mock.On("GetMergeRequestChanges", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockMergeRequestsServices_GetMergeRequestChanges_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestChangesOptions, options ...gitlab.RequestOptionFunc)) *MockMergeRequestsServices_GetMergeRequestChanges_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.GetMergeRequestChangesOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequestChanges_Call) Return(_a0 *gitlab.MergeRequest, _a1 *gitlab.Response, _a2 error) *MockMergeRequestsServices_GetMergeRequestChanges_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequestChanges_Call) RunAndReturn(run func(interface{}, int, *gitlab.GetMergeRequestChangesOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)) *MockMergeRequestsServices_GetMergeRequestChanges_Call { + _c.Call.Return(run) + return _c +} + +// GetMergeRequestDiffVersions provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockMergeRequestsServices) GetMergeRequestDiffVersions(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*gitlab.MergeRequestDiffVersion + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestDiffVersionsOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.GetMergeRequestDiffVersionsOptions, ...gitlab.RequestOptionFunc) []*gitlab.MergeRequestDiffVersion); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.MergeRequestDiffVersion) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.GetMergeRequestDiffVersionsOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.GetMergeRequestDiffVersionsOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockMergeRequestsServices_GetMergeRequestDiffVersions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMergeRequestDiffVersions' +type MockMergeRequestsServices_GetMergeRequestDiffVersions_Call struct { + *mock.Call +} + +// GetMergeRequestDiffVersions is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.GetMergeRequestDiffVersionsOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockMergeRequestsServices_Expecter) GetMergeRequestDiffVersions(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call { + return &MockMergeRequestsServices_GetMergeRequestDiffVersions_Call{Call: _e.mock.On("GetMergeRequestDiffVersions", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc)) *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.GetMergeRequestDiffVersionsOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call) Return(_a0 []*gitlab.MergeRequestDiffVersion, _a1 *gitlab.Response, _a2 error) *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call) RunAndReturn(run func(interface{}, int, *gitlab.GetMergeRequestDiffVersionsOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error)) *MockMergeRequestsServices_GetMergeRequestDiffVersions_Call { + _c.Call.Return(run) + return _c +} + +// ListMergeRequestDiffs provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockMergeRequestsServices) ListMergeRequestDiffs(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiffsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiff, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*gitlab.MergeRequestDiff + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.ListMergeRequestDiffsOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiff, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.ListMergeRequestDiffsOptions, ...gitlab.RequestOptionFunc) []*gitlab.MergeRequestDiff); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.MergeRequestDiff) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.ListMergeRequestDiffsOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.ListMergeRequestDiffsOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockMergeRequestsServices_ListMergeRequestDiffs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListMergeRequestDiffs' +type MockMergeRequestsServices_ListMergeRequestDiffs_Call struct { + *mock.Call +} + +// ListMergeRequestDiffs is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.ListMergeRequestDiffsOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockMergeRequestsServices_Expecter) ListMergeRequestDiffs(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockMergeRequestsServices_ListMergeRequestDiffs_Call { + return &MockMergeRequestsServices_ListMergeRequestDiffs_Call{Call: _e.mock.On("ListMergeRequestDiffs", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockMergeRequestsServices_ListMergeRequestDiffs_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiffsOptions, options ...gitlab.RequestOptionFunc)) *MockMergeRequestsServices_ListMergeRequestDiffs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.ListMergeRequestDiffsOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockMergeRequestsServices_ListMergeRequestDiffs_Call) Return(_a0 []*gitlab.MergeRequestDiff, _a1 *gitlab.Response, _a2 error) *MockMergeRequestsServices_ListMergeRequestDiffs_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockMergeRequestsServices_ListMergeRequestDiffs_Call) RunAndReturn(run func(interface{}, int, *gitlab.ListMergeRequestDiffsOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiff, *gitlab.Response, error)) *MockMergeRequestsServices_ListMergeRequestDiffs_Call { + _c.Call.Return(run) + return _c +} + +// UpdateMergeRequest provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockMergeRequestsServices) UpdateMergeRequest(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.MergeRequest + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.UpdateMergeRequestOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.UpdateMergeRequestOptions, ...gitlab.RequestOptionFunc) *gitlab.MergeRequest); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.MergeRequest) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.UpdateMergeRequestOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.UpdateMergeRequestOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockMergeRequestsServices_UpdateMergeRequest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateMergeRequest' +type MockMergeRequestsServices_UpdateMergeRequest_Call struct { + *mock.Call +} + +// UpdateMergeRequest is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.UpdateMergeRequestOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockMergeRequestsServices_Expecter) UpdateMergeRequest(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockMergeRequestsServices_UpdateMergeRequest_Call { + return &MockMergeRequestsServices_UpdateMergeRequest_Call{Call: _e.mock.On("UpdateMergeRequest", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockMergeRequestsServices_UpdateMergeRequest_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc)) *MockMergeRequestsServices_UpdateMergeRequest_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.UpdateMergeRequestOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockMergeRequestsServices_UpdateMergeRequest_Call) Return(_a0 *gitlab.MergeRequest, _a1 *gitlab.Response, _a2 error) *MockMergeRequestsServices_UpdateMergeRequest_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockMergeRequestsServices_UpdateMergeRequest_Call) RunAndReturn(run func(interface{}, int, *gitlab.UpdateMergeRequestOptions, ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error)) *MockMergeRequestsServices_UpdateMergeRequest_Call { + _c.Call.Return(run) + return _c +} + +// NewMockMergeRequestsServices creates a new instance of MockMergeRequestsServices. 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 NewMockMergeRequestsServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockMergeRequestsServices { + mock := &MockMergeRequestsServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/gitlab_client/mocks/mock_NotesServices.go b/mocks/gitlab_client/mocks/mock_NotesServices.go new file mode 100644 index 00000000..629cc4c7 --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_NotesServices.go @@ -0,0 +1,348 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockNotesServices is an autogenerated mock type for the NotesServices type +type MockNotesServices struct { + mock.Mock +} + +type MockNotesServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockNotesServices) EXPECT() *MockNotesServices_Expecter { + return &MockNotesServices_Expecter{mock: &_m.Mock} +} + +// CreateMergeRequestNote provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockNotesServices) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.Note + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.CreateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.CreateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) *gitlab.Note); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Note) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.CreateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.CreateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockNotesServices_CreateMergeRequestNote_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateMergeRequestNote' +type MockNotesServices_CreateMergeRequestNote_Call struct { + *mock.Call +} + +// CreateMergeRequestNote is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.CreateMergeRequestNoteOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockNotesServices_Expecter) CreateMergeRequestNote(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockNotesServices_CreateMergeRequestNote_Call { + return &MockNotesServices_CreateMergeRequestNote_Call{Call: _e.mock.On("CreateMergeRequestNote", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockNotesServices_CreateMergeRequestNote_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc)) *MockNotesServices_CreateMergeRequestNote_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.CreateMergeRequestNoteOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockNotesServices_CreateMergeRequestNote_Call) Return(_a0 *gitlab.Note, _a1 *gitlab.Response, _a2 error) *MockNotesServices_CreateMergeRequestNote_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockNotesServices_CreateMergeRequestNote_Call) RunAndReturn(run func(interface{}, int, *gitlab.CreateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)) *MockNotesServices_CreateMergeRequestNote_Call { + _c.Call.Return(run) + return _c +} + +// DeleteMergeRequestNote provides a mock function with given fields: pid, mergeRequest, note, options +func (_m *MockNotesServices) DeleteMergeRequestNote(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, note) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.Response + var r1 error + if rf, ok := ret.Get(0).(func(interface{}, int, int, ...gitlab.RequestOptionFunc) (*gitlab.Response, error)); ok { + return rf(pid, mergeRequest, note, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, int, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r0 = rf(pid, mergeRequest, note, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, int, ...gitlab.RequestOptionFunc) error); ok { + r1 = rf(pid, mergeRequest, note, options...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotesServices_DeleteMergeRequestNote_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteMergeRequestNote' +type MockNotesServices_DeleteMergeRequestNote_Call struct { + *mock.Call +} + +// DeleteMergeRequestNote is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - note int +// - options ...gitlab.RequestOptionFunc +func (_e *MockNotesServices_Expecter) DeleteMergeRequestNote(pid interface{}, mergeRequest interface{}, note interface{}, options ...interface{}) *MockNotesServices_DeleteMergeRequestNote_Call { + return &MockNotesServices_DeleteMergeRequestNote_Call{Call: _e.mock.On("DeleteMergeRequestNote", + append([]interface{}{pid, mergeRequest, note}, options...)...)} +} + +func (_c *MockNotesServices_DeleteMergeRequestNote_Call) Run(run func(pid interface{}, mergeRequest int, note int, options ...gitlab.RequestOptionFunc)) *MockNotesServices_DeleteMergeRequestNote_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(int), variadicArgs...) + }) + return _c +} + +func (_c *MockNotesServices_DeleteMergeRequestNote_Call) Return(_a0 *gitlab.Response, _a1 error) *MockNotesServices_DeleteMergeRequestNote_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotesServices_DeleteMergeRequestNote_Call) RunAndReturn(run func(interface{}, int, int, ...gitlab.RequestOptionFunc) (*gitlab.Response, error)) *MockNotesServices_DeleteMergeRequestNote_Call { + _c.Call.Return(run) + return _c +} + +// ListMergeRequestNotes provides a mock function with given fields: pid, mergeRequest, opt, options +func (_m *MockNotesServices) ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Note, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*gitlab.Note + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.ListMergeRequestNotesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.Note, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.ListMergeRequestNotesOptions, ...gitlab.RequestOptionFunc) []*gitlab.Note); ok { + r0 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.Note) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.ListMergeRequestNotesOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.ListMergeRequestNotesOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockNotesServices_ListMergeRequestNotes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListMergeRequestNotes' +type MockNotesServices_ListMergeRequestNotes_Call struct { + *mock.Call +} + +// ListMergeRequestNotes is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - opt *gitlab.ListMergeRequestNotesOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockNotesServices_Expecter) ListMergeRequestNotes(pid interface{}, mergeRequest interface{}, opt interface{}, options ...interface{}) *MockNotesServices_ListMergeRequestNotes_Call { + return &MockNotesServices_ListMergeRequestNotes_Call{Call: _e.mock.On("ListMergeRequestNotes", + append([]interface{}{pid, mergeRequest, opt}, options...)...)} +} + +func (_c *MockNotesServices_ListMergeRequestNotes_Call) Run(run func(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestNotesOptions, options ...gitlab.RequestOptionFunc)) *MockNotesServices_ListMergeRequestNotes_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.ListMergeRequestNotesOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockNotesServices_ListMergeRequestNotes_Call) Return(_a0 []*gitlab.Note, _a1 *gitlab.Response, _a2 error) *MockNotesServices_ListMergeRequestNotes_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockNotesServices_ListMergeRequestNotes_Call) RunAndReturn(run func(interface{}, int, *gitlab.ListMergeRequestNotesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.Note, *gitlab.Response, error)) *MockNotesServices_ListMergeRequestNotes_Call { + _c.Call.Return(run) + return _c +} + +// UpdateMergeRequestNote provides a mock function with given fields: pid, mergeRequest, note, opt, options +func (_m *MockNotesServices) UpdateMergeRequestNote(pid interface{}, mergeRequest int, note int, opt *gitlab.UpdateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, mergeRequest, note, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.Note + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, int, *gitlab.UpdateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)); ok { + return rf(pid, mergeRequest, note, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, int, *gitlab.UpdateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) *gitlab.Note); ok { + r0 = rf(pid, mergeRequest, note, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Note) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, int, *gitlab.UpdateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, mergeRequest, note, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, int, *gitlab.UpdateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, mergeRequest, note, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockNotesServices_UpdateMergeRequestNote_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateMergeRequestNote' +type MockNotesServices_UpdateMergeRequestNote_Call struct { + *mock.Call +} + +// UpdateMergeRequestNote is a helper method to define mock.On call +// - pid interface{} +// - mergeRequest int +// - note int +// - opt *gitlab.UpdateMergeRequestNoteOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockNotesServices_Expecter) UpdateMergeRequestNote(pid interface{}, mergeRequest interface{}, note interface{}, opt interface{}, options ...interface{}) *MockNotesServices_UpdateMergeRequestNote_Call { + return &MockNotesServices_UpdateMergeRequestNote_Call{Call: _e.mock.On("UpdateMergeRequestNote", + append([]interface{}{pid, mergeRequest, note, opt}, options...)...)} +} + +func (_c *MockNotesServices_UpdateMergeRequestNote_Call) Run(run func(pid interface{}, mergeRequest int, note int, opt *gitlab.UpdateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc)) *MockNotesServices_UpdateMergeRequestNote_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-4) + for i, a := range args[4:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(int), args[3].(*gitlab.UpdateMergeRequestNoteOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockNotesServices_UpdateMergeRequestNote_Call) Return(_a0 *gitlab.Note, _a1 *gitlab.Response, _a2 error) *MockNotesServices_UpdateMergeRequestNote_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockNotesServices_UpdateMergeRequestNote_Call) RunAndReturn(run func(interface{}, int, int, *gitlab.UpdateMergeRequestNoteOptions, ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error)) *MockNotesServices_UpdateMergeRequestNote_Call { + _c.Call.Return(run) + return _c +} + +// NewMockNotesServices creates a new instance of MockNotesServices. 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 NewMockNotesServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockNotesServices { + mock := &MockNotesServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/gitlab_client/mocks/mock_PipelinesServices.go b/mocks/gitlab_client/mocks/mock_PipelinesServices.go new file mode 100644 index 00000000..d413db39 --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_PipelinesServices.go @@ -0,0 +1,115 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockPipelinesServices is an autogenerated mock type for the PipelinesServices type +type MockPipelinesServices struct { + mock.Mock +} + +type MockPipelinesServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockPipelinesServices) EXPECT() *MockPipelinesServices_Expecter { + return &MockPipelinesServices_Expecter{mock: &_m.Mock} +} + +// ListProjectPipelines provides a mock function with given fields: pid, opt, options +func (_m *MockPipelinesServices) ListProjectPipelines(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*gitlab.PipelineInfo + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.ListProjectPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error)); ok { + return rf(pid, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.ListProjectPipelinesOptions, ...gitlab.RequestOptionFunc) []*gitlab.PipelineInfo); ok { + r0 = rf(pid, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.PipelineInfo) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, *gitlab.ListProjectPipelinesOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, *gitlab.ListProjectPipelinesOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockPipelinesServices_ListProjectPipelines_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListProjectPipelines' +type MockPipelinesServices_ListProjectPipelines_Call struct { + *mock.Call +} + +// ListProjectPipelines is a helper method to define mock.On call +// - pid interface{} +// - opt *gitlab.ListProjectPipelinesOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockPipelinesServices_Expecter) ListProjectPipelines(pid interface{}, opt interface{}, options ...interface{}) *MockPipelinesServices_ListProjectPipelines_Call { + return &MockPipelinesServices_ListProjectPipelines_Call{Call: _e.mock.On("ListProjectPipelines", + append([]interface{}{pid, opt}, options...)...)} +} + +func (_c *MockPipelinesServices_ListProjectPipelines_Call) Run(run func(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc)) *MockPipelinesServices_ListProjectPipelines_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(*gitlab.ListProjectPipelinesOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockPipelinesServices_ListProjectPipelines_Call) Return(_a0 []*gitlab.PipelineInfo, _a1 *gitlab.Response, _a2 error) *MockPipelinesServices_ListProjectPipelines_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockPipelinesServices_ListProjectPipelines_Call) RunAndReturn(run func(interface{}, *gitlab.ListProjectPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error)) *MockPipelinesServices_ListProjectPipelines_Call { + _c.Call.Return(run) + return _c +} + +// NewMockPipelinesServices creates a new instance of MockPipelinesServices. 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 NewMockPipelinesServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockPipelinesServices { + mock := &MockPipelinesServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/gitlab_client/mocks/mock_ProjectsServices.go b/mocks/gitlab_client/mocks/mock_ProjectsServices.go new file mode 100644 index 00000000..7e3965e2 --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_ProjectsServices.go @@ -0,0 +1,353 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockProjectsServices is an autogenerated mock type for the ProjectsServices type +type MockProjectsServices struct { + mock.Mock +} + +type MockProjectsServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockProjectsServices) EXPECT() *MockProjectsServices_Expecter { + return &MockProjectsServices_Expecter{mock: &_m.Mock} +} + +// AddProjectHook provides a mock function with given fields: pid, opt, options +func (_m *MockProjectsServices) AddProjectHook(pid interface{}, opt *gitlab.AddProjectHookOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.ProjectHook + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.AddProjectHookOptions, ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error)); ok { + return rf(pid, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.AddProjectHookOptions, ...gitlab.RequestOptionFunc) *gitlab.ProjectHook); ok { + r0 = rf(pid, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.ProjectHook) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, *gitlab.AddProjectHookOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, *gitlab.AddProjectHookOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockProjectsServices_AddProjectHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddProjectHook' +type MockProjectsServices_AddProjectHook_Call struct { + *mock.Call +} + +// AddProjectHook is a helper method to define mock.On call +// - pid interface{} +// - opt *gitlab.AddProjectHookOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockProjectsServices_Expecter) AddProjectHook(pid interface{}, opt interface{}, options ...interface{}) *MockProjectsServices_AddProjectHook_Call { + return &MockProjectsServices_AddProjectHook_Call{Call: _e.mock.On("AddProjectHook", + append([]interface{}{pid, opt}, options...)...)} +} + +func (_c *MockProjectsServices_AddProjectHook_Call) Run(run func(pid interface{}, opt *gitlab.AddProjectHookOptions, options ...gitlab.RequestOptionFunc)) *MockProjectsServices_AddProjectHook_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(*gitlab.AddProjectHookOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockProjectsServices_AddProjectHook_Call) Return(_a0 *gitlab.ProjectHook, _a1 *gitlab.Response, _a2 error) *MockProjectsServices_AddProjectHook_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockProjectsServices_AddProjectHook_Call) RunAndReturn(run func(interface{}, *gitlab.AddProjectHookOptions, ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error)) *MockProjectsServices_AddProjectHook_Call { + _c.Call.Return(run) + return _c +} + +// EditProjectHook provides a mock function with given fields: pid, hook, opt, options +func (_m *MockProjectsServices) EditProjectHook(pid interface{}, hook int, opt *gitlab.EditProjectHookOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, hook, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.ProjectHook + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.EditProjectHookOptions, ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error)); ok { + return rf(pid, hook, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, int, *gitlab.EditProjectHookOptions, ...gitlab.RequestOptionFunc) *gitlab.ProjectHook); ok { + r0 = rf(pid, hook, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.ProjectHook) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, int, *gitlab.EditProjectHookOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, hook, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, int, *gitlab.EditProjectHookOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, hook, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockProjectsServices_EditProjectHook_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EditProjectHook' +type MockProjectsServices_EditProjectHook_Call struct { + *mock.Call +} + +// EditProjectHook is a helper method to define mock.On call +// - pid interface{} +// - hook int +// - opt *gitlab.EditProjectHookOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockProjectsServices_Expecter) EditProjectHook(pid interface{}, hook interface{}, opt interface{}, options ...interface{}) *MockProjectsServices_EditProjectHook_Call { + return &MockProjectsServices_EditProjectHook_Call{Call: _e.mock.On("EditProjectHook", + append([]interface{}{pid, hook, opt}, options...)...)} +} + +func (_c *MockProjectsServices_EditProjectHook_Call) Run(run func(pid interface{}, hook int, opt *gitlab.EditProjectHookOptions, options ...gitlab.RequestOptionFunc)) *MockProjectsServices_EditProjectHook_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(int), args[2].(*gitlab.EditProjectHookOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockProjectsServices_EditProjectHook_Call) Return(_a0 *gitlab.ProjectHook, _a1 *gitlab.Response, _a2 error) *MockProjectsServices_EditProjectHook_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockProjectsServices_EditProjectHook_Call) RunAndReturn(run func(interface{}, int, *gitlab.EditProjectHookOptions, ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error)) *MockProjectsServices_EditProjectHook_Call { + _c.Call.Return(run) + return _c +} + +// GetProject provides a mock function with given fields: pid, opt, options +func (_m *MockProjectsServices) GetProject(pid interface{}, opt *gitlab.GetProjectOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Project, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *gitlab.Project + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.GetProjectOptions, ...gitlab.RequestOptionFunc) (*gitlab.Project, *gitlab.Response, error)); ok { + return rf(pid, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.GetProjectOptions, ...gitlab.RequestOptionFunc) *gitlab.Project); ok { + r0 = rf(pid, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*gitlab.Project) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, *gitlab.GetProjectOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, *gitlab.GetProjectOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockProjectsServices_GetProject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetProject' +type MockProjectsServices_GetProject_Call struct { + *mock.Call +} + +// GetProject is a helper method to define mock.On call +// - pid interface{} +// - opt *gitlab.GetProjectOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockProjectsServices_Expecter) GetProject(pid interface{}, opt interface{}, options ...interface{}) *MockProjectsServices_GetProject_Call { + return &MockProjectsServices_GetProject_Call{Call: _e.mock.On("GetProject", + append([]interface{}{pid, opt}, options...)...)} +} + +func (_c *MockProjectsServices_GetProject_Call) Run(run func(pid interface{}, opt *gitlab.GetProjectOptions, options ...gitlab.RequestOptionFunc)) *MockProjectsServices_GetProject_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(*gitlab.GetProjectOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockProjectsServices_GetProject_Call) Return(_a0 *gitlab.Project, _a1 *gitlab.Response, _a2 error) *MockProjectsServices_GetProject_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockProjectsServices_GetProject_Call) RunAndReturn(run func(interface{}, *gitlab.GetProjectOptions, ...gitlab.RequestOptionFunc) (*gitlab.Project, *gitlab.Response, error)) *MockProjectsServices_GetProject_Call { + _c.Call.Return(run) + return _c +} + +// ListProjectHooks provides a mock function with given fields: pid, opt, options +func (_m *MockProjectsServices) ListProjectHooks(pid interface{}, opt *gitlab.ListProjectHooksOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectHook, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []*gitlab.ProjectHook + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.ListProjectHooksOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectHook, *gitlab.Response, error)); ok { + return rf(pid, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, *gitlab.ListProjectHooksOptions, ...gitlab.RequestOptionFunc) []*gitlab.ProjectHook); ok { + r0 = rf(pid, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*gitlab.ProjectHook) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, *gitlab.ListProjectHooksOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, *gitlab.ListProjectHooksOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockProjectsServices_ListProjectHooks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListProjectHooks' +type MockProjectsServices_ListProjectHooks_Call struct { + *mock.Call +} + +// ListProjectHooks is a helper method to define mock.On call +// - pid interface{} +// - opt *gitlab.ListProjectHooksOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockProjectsServices_Expecter) ListProjectHooks(pid interface{}, opt interface{}, options ...interface{}) *MockProjectsServices_ListProjectHooks_Call { + return &MockProjectsServices_ListProjectHooks_Call{Call: _e.mock.On("ListProjectHooks", + append([]interface{}{pid, opt}, options...)...)} +} + +func (_c *MockProjectsServices_ListProjectHooks_Call) Run(run func(pid interface{}, opt *gitlab.ListProjectHooksOptions, options ...gitlab.RequestOptionFunc)) *MockProjectsServices_ListProjectHooks_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(*gitlab.ListProjectHooksOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockProjectsServices_ListProjectHooks_Call) Return(_a0 []*gitlab.ProjectHook, _a1 *gitlab.Response, _a2 error) *MockProjectsServices_ListProjectHooks_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockProjectsServices_ListProjectHooks_Call) RunAndReturn(run func(interface{}, *gitlab.ListProjectHooksOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectHook, *gitlab.Response, error)) *MockProjectsServices_ListProjectHooks_Call { + _c.Call.Return(run) + return _c +} + +// NewMockProjectsServices creates a new instance of MockProjectsServices. 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 NewMockProjectsServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockProjectsServices { + mock := &MockProjectsServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/gitlab_client/mocks/mock_RepositoryFilesServices.go b/mocks/gitlab_client/mocks/mock_RepositoryFilesServices.go new file mode 100644 index 00000000..1f0ec98d --- /dev/null +++ b/mocks/gitlab_client/mocks/mock_RepositoryFilesServices.go @@ -0,0 +1,116 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package gitlab_client + +import ( + gitlab "github.com/xanzy/go-gitlab" + + mock "github.com/stretchr/testify/mock" +) + +// MockRepositoryFilesServices is an autogenerated mock type for the RepositoryFilesServices type +type MockRepositoryFilesServices struct { + mock.Mock +} + +type MockRepositoryFilesServices_Expecter struct { + mock *mock.Mock +} + +func (_m *MockRepositoryFilesServices) EXPECT() *MockRepositoryFilesServices_Expecter { + return &MockRepositoryFilesServices_Expecter{mock: &_m.Mock} +} + +// GetRawFile provides a mock function with given fields: pid, fileName, opt, options +func (_m *MockRepositoryFilesServices) GetRawFile(pid interface{}, fileName string, opt *gitlab.GetRawFileOptions, options ...gitlab.RequestOptionFunc) ([]byte, *gitlab.Response, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, pid, fileName, opt) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 []byte + var r1 *gitlab.Response + var r2 error + if rf, ok := ret.Get(0).(func(interface{}, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) ([]byte, *gitlab.Response, error)); ok { + return rf(pid, fileName, opt, options...) + } + if rf, ok := ret.Get(0).(func(interface{}, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) []byte); ok { + r0 = rf(pid, fileName, opt, options...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(interface{}, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) *gitlab.Response); ok { + r1 = rf(pid, fileName, opt, options...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*gitlab.Response) + } + } + + if rf, ok := ret.Get(2).(func(interface{}, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) error); ok { + r2 = rf(pid, fileName, opt, options...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockRepositoryFilesServices_GetRawFile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRawFile' +type MockRepositoryFilesServices_GetRawFile_Call struct { + *mock.Call +} + +// GetRawFile is a helper method to define mock.On call +// - pid interface{} +// - fileName string +// - opt *gitlab.GetRawFileOptions +// - options ...gitlab.RequestOptionFunc +func (_e *MockRepositoryFilesServices_Expecter) GetRawFile(pid interface{}, fileName interface{}, opt interface{}, options ...interface{}) *MockRepositoryFilesServices_GetRawFile_Call { + return &MockRepositoryFilesServices_GetRawFile_Call{Call: _e.mock.On("GetRawFile", + append([]interface{}{pid, fileName, opt}, options...)...)} +} + +func (_c *MockRepositoryFilesServices_GetRawFile_Call) Run(run func(pid interface{}, fileName string, opt *gitlab.GetRawFileOptions, options ...gitlab.RequestOptionFunc)) *MockRepositoryFilesServices_GetRawFile_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]gitlab.RequestOptionFunc, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(gitlab.RequestOptionFunc) + } + } + run(args[0].(interface{}), args[1].(string), args[2].(*gitlab.GetRawFileOptions), variadicArgs...) + }) + return _c +} + +func (_c *MockRepositoryFilesServices_GetRawFile_Call) Return(_a0 []byte, _a1 *gitlab.Response, _a2 error) *MockRepositoryFilesServices_GetRawFile_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MockRepositoryFilesServices_GetRawFile_Call) RunAndReturn(run func(interface{}, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) ([]byte, *gitlab.Response, error)) *MockRepositoryFilesServices_GetRawFile_Call { + _c.Call.Return(run) + return _c +} + +// NewMockRepositoryFilesServices creates a new instance of MockRepositoryFilesServices. 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 NewMockRepositoryFilesServices(t interface { + mock.TestingT + Cleanup(func()) +}) *MockRepositoryFilesServices { + mock := &MockRepositoryFilesServices{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 9e697099..cc09f634 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -78,6 +78,7 @@ type ServerConfig struct { TidyOutdatedCommentsMode string `mapstructure:"tidy-outdated-comments-mode"` MaxQueueSize int64 `mapstructure:"max-queue-size"` MaxConcurrenctChecks int `mapstructure:"max-concurrenct-checks"` + ReplanCommentMessage string `mapstructure:"replan-comment-msg"` } func New() (ServerConfig, error) { diff --git a/pkg/server/hook_handler.go b/pkg/server/hook_handler.go index 2f8929e0..1d67344f 100644 --- a/pkg/server/hook_handler.go +++ b/pkg/server/hook_handler.go @@ -47,11 +47,11 @@ func (h *VCSHookHandler) groupHandler(c echo.Context) error { return c.String(http.StatusUnauthorized, "Unauthorized") } - pr, err := h.ctr.VcsClient.ParseHook(c.Request(), payload) + pr, err := h.ctr.VcsClient.ParseHook(ctx, c.Request(), payload) if err != nil { switch err { case vcs.ErrInvalidType: - log.Debug().Msg("Ignoring event, not a merge request") + log.Debug().Msg("Ignoring event, not a supported request") return c.String(http.StatusOK, "Skipped") default: // TODO: do something ELSE with the error diff --git a/pkg/vcs/github_client/client.go b/pkg/vcs/github_client/client.go index a2255a1e..f7484f43 100644 --- a/pkg/vcs/github_client/client.go +++ b/pkg/vcs/github_client/client.go @@ -150,7 +150,7 @@ func (c *Client) VerifyHook(r *http.Request, secret string) ([]byte, error) { var nilPr vcs.PullRequest -func (c *Client) ParseHook(r *http.Request, request []byte) (vcs.PullRequest, error) { +func (c *Client) ParseHook(ctx context.Context, r *http.Request, request []byte) (vcs.PullRequest, error) { payload, err := github.ParseWebHook(github.WebHookType(r), request) if err != nil { return nilPr, err @@ -166,28 +166,44 @@ func (c *Client) ParseHook(r *http.Request, request []byte) (vcs.PullRequest, er log.Info().Str("action", p.GetAction()).Msg("ignoring Github pull request event due to non commit based action") return nilPr, vcs.ErrInvalidType } + case *github.IssueCommentEvent: + switch p.GetAction() { + case "created": + if strings.ToLower(p.Comment.GetBody()) == c.cfg.ReplanCommentMessage { + log.Info().Msgf("Got %s comment, Running again", c.cfg.ReplanCommentMessage) + return c.buildRepoFromComment(ctx, p) + } else { + log.Info().Str("action", p.GetAction()).Msg("ignoring Github issue comment event due to non matching string") + return nilPr, vcs.ErrInvalidType + } + default: + log.Info().Str("action", p.GetAction()).Msg("ignoring Github issue comment due to invalid action") + return nilPr, vcs.ErrInvalidType + } default: log.Error().Msg("invalid event provided to Github client") return nilPr, vcs.ErrInvalidType } } -func (c *Client) buildRepoFromEvent(event *github.PullRequestEvent) vcs.PullRequest { +func (c *Client) buildRepo(pullRequest *github.PullRequest) vcs.PullRequest { + repo := pullRequest.Head.Repo + var labels []string - for _, label := range event.PullRequest.Labels { + for _, label := range pullRequest.Labels { labels = append(labels, label.GetName()) } return vcs.PullRequest{ - BaseRef: *event.PullRequest.Base.Ref, - HeadRef: *event.PullRequest.Head.Ref, - DefaultBranch: *event.Repo.DefaultBranch, - CloneURL: *event.Repo.CloneURL, - FullName: event.Repo.GetFullName(), - Owner: *event.Repo.Owner.Login, - Name: event.Repo.GetName(), - CheckID: *event.PullRequest.Number, - SHA: *event.PullRequest.Head.SHA, + BaseRef: pullRequest.Base.GetRef(), + HeadRef: pullRequest.Head.GetRef(), + DefaultBranch: repo.GetDefaultBranch(), + CloneURL: repo.GetCloneURL(), + FullName: repo.GetFullName(), + Owner: repo.Owner.GetLogin(), + Name: repo.GetName(), + CheckID: pullRequest.GetNumber(), + SHA: pullRequest.Head.GetSHA(), Username: c.username, Email: c.email, Labels: labels, @@ -196,6 +212,25 @@ func (c *Client) buildRepoFromEvent(event *github.PullRequestEvent) vcs.PullRequ } } +func (c *Client) buildRepoFromEvent(event *github.PullRequestEvent) vcs.PullRequest { + return c.buildRepo(event.PullRequest) +} + +// buildRepoFromComment builds a vcs.PullRequest from a github.IssueCommentEvent +func (c *Client) buildRepoFromComment(context context.Context, comment *github.IssueCommentEvent) (vcs.PullRequest, error) { + owner := comment.GetRepo().GetOwner().GetLogin() + repoName := comment.GetRepo().GetName() + prNumber := comment.GetIssue().GetNumber() + + log.Info().Str("owner", owner).Str("repo", repoName).Int("number", prNumber).Msg("getting pr") + pr, _, err := c.googleClient.PullRequests.Get(context, owner, repoName, prNumber) + if err != nil { + return nilPr, errors.Wrap(err, "failed to get pull request") + } + + return c.buildRepo(pr), nil +} + func toGithubCommitStatus(state pkg.CommitState) *string { switch state { case pkg.StateError, pkg.StatePanic: @@ -283,7 +318,7 @@ func (c *Client) CreateHook(ctx context.Context, ownerAndRepoName, webhookUrl, w Secret: pkg.Pointer(webhookSecret), }, Events: []string{ - "pull_request", + "pull_request", "issue_comment", }, Name: pkg.Pointer("web"), }) diff --git a/pkg/vcs/github_client/client_test.go b/pkg/vcs/github_client/client_test.go index bd0704f3..9b5fe15f 100644 --- a/pkg/vcs/github_client/client_test.go +++ b/pkg/vcs/github_client/client_test.go @@ -10,6 +10,7 @@ import ( "github.com/shurcooL/githubv4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" githubMocks "github.com/zapier/kubechecks/mocks/github_client/mocks" "github.com/zapier/kubechecks/pkg/config" "github.com/zapier/kubechecks/pkg/vcs" @@ -25,6 +26,16 @@ func MockGitHubMethod(methodName string, returns []interface{}) *GClient { } } +// MockGitHubPullRequestMethod is a generic function to mock GitHub client methods +func MockGitHubPullRequestMethod(methodName string, returns []interface{}) *GClient { + mockClient := new(githubMocks.MockPullRequestsServices) + mockClient.On(methodName, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(returns...) + + return &GClient{ + PullRequests: mockClient, + } +} + func TestParseRepo(t *testing.T) { testcases := []struct { name, input string @@ -324,3 +335,130 @@ func TestClient_GetHookByUrl(t *testing.T) { }) } } + +func TestClient_buildRepoFromComment_HappyPath(t *testing.T) { + type fields struct { + shurcoolClient *githubv4.Client + googleClient *GClient + cfg config.ServerConfig + username string + email string + } + type args struct { + context context.Context + comment *github.IssueCommentEvent + } + tests := []struct { + name string + fields fields + args args + want vcs.PullRequest + }{ + { + name: "normal ok", + fields: fields{ + shurcoolClient: nil, + googleClient: MockGitHubPullRequestMethod("Get", + []interface{}{ + &github.PullRequest{ + ID: nil, + Number: github.Int(123), + Labels: []*github.Label{ + { + Name: github.String("test label1"), + }, + { + Name: github.String("test label2"), + }, + }, + Head: &github.PullRequestBranch{ + Ref: github.String("new-feature"), + SHA: github.String("dummySHAHead"), + Repo: &github.Repository{ + CloneURL: github.String("https://github.com/zapier/kubechecks/"), + DefaultBranch: github.String("main"), + FullName: github.String("zapier/kubechecks"), + Owner: &github.User{Login: github.String("fork")}, + Name: github.String("kubechecks"), + }, + }, + Base: &github.PullRequestBranch{ + Ref: github.String("main"), + SHA: github.String("dummySHABase"), + Repo: &github.Repository{ + CloneURL: github.String("https://github.com/zapier/kubechecks/"), + Owner: &github.User{Login: github.String("zapier")}, + }, + }, + }, + &github.Response{Response: &http.Response{StatusCode: http.StatusOK}}, + nil}, + ), + cfg: config.ServerConfig{}, + username: "unittestuser", + email: "unitestuser@localhost.local", + }, + args: args{ + context: context.TODO(), + comment: &github.IssueCommentEvent{ + Issue: &github.Issue{ + URL: github.String("https://github.com/zapier/kubechecks/pull/250"), + Number: github.Int(250), + Repository: &github.Repository{ + Name: github.String("kubechecks"), + Owner: &github.User{ + Name: github.String("zapier"), + }, + }, + }, + Repo: &github.Repository{ + DefaultBranch: github.String("main"), + Name: github.String("kubechecks"), + FullName: github.String("zapier/kubechecks"), + }, + }, + }, + want: vcs.PullRequest{ + BaseRef: "main", + HeadRef: "new-feature", + DefaultBranch: "main", + CloneURL: "https://github.com/zapier/kubechecks/", + Name: "kubechecks", + Owner: "fork", + CheckID: 123, + SHA: "dummySHAHead", + FullName: "zapier/kubechecks", + Username: "unittestuser", + Email: "unitestuser@localhost.local", + Labels: []string{"test label1", "test label2"}, + Config: config.ServerConfig{}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + shurcoolClient: tt.fields.shurcoolClient, + googleClient: tt.fields.googleClient, + cfg: tt.fields.cfg, + username: tt.fields.username, + email: tt.fields.email, + } + actual, err := c.buildRepoFromComment(tt.args.context, tt.args.comment) + require.NoError(t, err) + assert.Equal(t, tt.want.Name, actual.Name) + assert.Equal(t, tt.want.Labels, actual.Labels) + assert.Equal(t, tt.want.CheckID, actual.CheckID) + assert.Equal(t, tt.want.BaseRef, actual.BaseRef) + assert.Equal(t, tt.want.CloneURL, actual.CloneURL) + assert.Equal(t, tt.want.DefaultBranch, actual.DefaultBranch) + assert.Equal(t, tt.want.Email, actual.Email) + assert.Equal(t, tt.want.FullName, actual.FullName) + assert.Equal(t, tt.want.HeadRef, actual.HeadRef) + assert.Equal(t, tt.want.Owner, actual.Owner) + assert.Equal(t, tt.want.Remote, actual.Remote) + assert.Equal(t, tt.want.SHA, actual.SHA) + assert.Equal(t, tt.want.Username, actual.Username) + }) + } +} diff --git a/pkg/vcs/gitlab_client/client.go b/pkg/vcs/gitlab_client/client.go index 989f3d2d..3940d658 100644 --- a/pkg/vcs/gitlab_client/client.go +++ b/pkg/vcs/gitlab_client/client.go @@ -9,7 +9,7 @@ import ( "strconv" "strings" - "github.com/chainguard-dev/git-urls" + giturls "github.com/chainguard-dev/git-urls" "github.com/pkg/errors" "github.com/rs/zerolog/log" "github.com/xanzy/go-gitlab" @@ -22,12 +22,21 @@ import ( const GitlabTokenHeader = "X-Gitlab-Token" type Client struct { - c *gitlab.Client + c *GLClient cfg config.ServerConfig username, email string } +type GLClient struct { + MergeRequests MergeRequestsServices + RepositoryFiles RepositoryFilesServices + Notes NotesServices + Pipelines PipelinesServices + Projects ProjectsServices + Commits CommitsServices +} + func CreateGitlabClient(cfg config.ServerConfig) (*Client, error) { // Initialize the GitLab client with access token gitlabToken := cfg.VcsToken @@ -54,7 +63,14 @@ func CreateGitlabClient(cfg config.ServerConfig) (*Client, error) { } client := &Client{ - c: c, + c: &GLClient{ + MergeRequests: &MergeRequestsService{c.MergeRequests}, + RepositoryFiles: &RepositoryFilesService{c.RepositoryFiles}, + Notes: &NotesService{c.Notes}, + Projects: &ProjectsService{c.Projects}, + Commits: &CommitsService{c.Commits}, + Pipelines: &PipelinesService{c.Pipelines}, + }, cfg: cfg, username: user.Username, email: user.Email, @@ -89,7 +105,7 @@ func (c *Client) VerifyHook(r *http.Request, secret string) ([]byte, error) { var nilPr vcs.PullRequest // ParseHook parses and validates a webhook event; return an err if this isn't valid -func (c *Client) ParseHook(r *http.Request, request []byte) (vcs.PullRequest, error) { +func (c *Client) ParseHook(ctx context.Context, r *http.Request, request []byte) (vcs.PullRequest, error) { eventRequest, err := gitlab.ParseHook(gitlab.HookEventType(r), request) if err != nil { return nilPr, err @@ -109,6 +125,20 @@ func (c *Client) ParseHook(r *http.Request, request []byte) (vcs.PullRequest, er log.Trace().Msgf("Unhandled Action %s", event.ObjectAttributes.Action) return nilPr, vcs.ErrInvalidType } + case *gitlab.MergeCommentEvent: + switch event.ObjectAttributes.Action { + case gitlab.CommentEventActionCreate: + if strings.ToLower(event.ObjectAttributes.Note) == c.cfg.ReplanCommentMessage { + log.Info().Msgf("Got %s comment, Running again", c.cfg.ReplanCommentMessage) + return c.buildRepoFromComment(event), nil + } else { + log.Info().Msg("ignoring Gitlab merge comment event due to non matching string") + return nilPr, vcs.ErrInvalidType + } + default: + log.Info().Msg("ignoring Gitlab issue comment event due to non matching string") + return nilPr, vcs.ErrInvalidType + } default: log.Trace().Msgf("Unhandled Event: %T", event) return nilPr, vcs.ErrInvalidType @@ -145,6 +175,10 @@ func (c *Client) GetHookByUrl(ctx context.Context, repoName, webhookUrl string) if hook.MergeRequestsEvents { events = append(events, string(gitlab.MergeRequestEventTargetType)) } + if hook.NoteEvents { + events = append(events, string(gitlab.NoteEventTargetType)) + } + return &vcs.WebHookConfig{ Url: hook.URL, Events: events, @@ -161,13 +195,14 @@ func (c *Client) CreateHook(ctx context.Context, repoName, webhookUrl, webhookSe return errors.Wrap(err, "failed to parse repo name") } - _, _, err = c.c.Projects.AddProjectHook(pid, &gitlab.AddProjectHookOptions{ + _, glStatus, err := c.c.Projects.AddProjectHook(pid, &gitlab.AddProjectHookOptions{ URL: pkg.Pointer(webhookUrl), MergeRequestsEvents: pkg.Pointer(true), + NoteEvents: pkg.Pointer(true), Token: pkg.Pointer(webhookSecret), }) - if err != nil { + if err != nil && glStatus.StatusCode < http.StatusOK || glStatus.StatusCode >= http.StatusMultipleChoices { return errors.Wrap(err, "failed to create project webhook") } @@ -240,3 +275,26 @@ func (c *Client) buildRepoFromEvent(event *gitlab.MergeEvent) vcs.PullRequest { Config: c.cfg, } } + +func (c *Client) buildRepoFromComment(event *gitlab.MergeCommentEvent) vcs.PullRequest { + // Convert all labels from this MR to a string array of label names + var labels []string + for _, label := range event.MergeRequest.Labels { + labels = append(labels, label.Title) + } + return vcs.PullRequest{ + BaseRef: event.MergeRequest.TargetBranch, + HeadRef: event.MergeRequest.SourceBranch, + DefaultBranch: event.Project.DefaultBranch, + FullName: event.Project.PathWithNamespace, + CloneURL: event.Project.GitHTTPURL, + Name: event.Project.Name, + CheckID: event.MergeRequest.IID, + SHA: event.MergeRequest.LastCommit.ID, + Username: c.username, + Email: c.email, + Labels: labels, + + Config: c.cfg, + } +} diff --git a/pkg/vcs/gitlab_client/client_test.go b/pkg/vcs/gitlab_client/client_test.go index c86c60ce..531b6352 100644 --- a/pkg/vcs/gitlab_client/client_test.go +++ b/pkg/vcs/gitlab_client/client_test.go @@ -1,10 +1,18 @@ package gitlab_client import ( + "context" + "fmt" + "net/http" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/xanzy/go-gitlab" + gitlabMocks "github.com/zapier/kubechecks/mocks/gitlab_client/mocks" + "github.com/zapier/kubechecks/pkg/config" + "github.com/zapier/kubechecks/pkg/vcs" ) func TestCustomGitURLParsing(t *testing.T) { @@ -40,3 +48,184 @@ func TestCustomGitURLParsing(t *testing.T) { }) } } + +func TestClient_GetHookByUrl(t *testing.T) { + type fields struct { + c *GLClient + cfg config.ServerConfig + username string + email string + } + type args struct { + ctx context.Context + repoName string + webhookUrl string + } + tests := []struct { + name string + fields fields + args args + want *vcs.WebHookConfig + wantErr assert.ErrorAssertionFunc + }{ + { + name: "normal ok", + fields: fields{ + c: MockGitLabProjects("ListProjectHooks", + []interface{}{ + []*gitlab.ProjectHook{ + { + URL: "https://dummywebhooks.local", + MergeRequestsEvents: true, + NoteEvents: true, + }, + }, + &gitlab.Response{ + Response: &http.Response{StatusCode: http.StatusOK}, + }, + nil, + }), + cfg: config.ServerConfig{}, + username: "", + email: "", + }, + args: args{ + ctx: context.TODO(), + repoName: "test", + webhookUrl: "https://dummywebhooks.local", + }, + want: &vcs.WebHookConfig{ + Url: "https://dummywebhooks.local", + Events: []string{"merge_request", "note"}, + }, + wantErr: assert.NoError, + }, + { + name: "gl client err", + fields: fields{ + c: MockGitLabProjects("ListProjectHooks", + []interface{}{ + nil, + &gitlab.Response{ + Response: &http.Response{StatusCode: http.StatusInternalServerError}, + }, + fmt.Errorf("dummy error"), + }), + cfg: config.ServerConfig{}, + username: "", + email: "", + }, + args: args{ + ctx: context.TODO(), + repoName: "test", + webhookUrl: "https://dummywebhooks.local", + }, + want: nil, + wantErr: assert.Error, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + c: tt.fields.c, + cfg: tt.fields.cfg, + username: tt.fields.username, + email: tt.fields.email, + } + got, err := c.GetHookByUrl(tt.args.ctx, tt.args.repoName, tt.args.webhookUrl) + if !tt.wantErr(t, err, fmt.Sprintf("GetHookByUrl(%v, %v, %v)", tt.args.ctx, tt.args.repoName, tt.args.webhookUrl)) { + return + } + assert.Equalf(t, tt.want, got, "GetHookByUrl(%v, %v, %v)", tt.args.ctx, tt.args.repoName, tt.args.webhookUrl) + }) + } +} + +// MockGitLabProjects is a generic function to mock Gitlab MergeRequest client methods +func MockGitLabProjects(methodName string, returns []interface{}) *GLClient { + mockClient := new(gitlabMocks.MockProjectsServices) + mockClient.On(methodName, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(returns...) + + return &GLClient{ + Projects: mockClient, + } +} + +func TestClient_CreateHook(t *testing.T) { + type fields struct { + c *GLClient + cfg config.ServerConfig + username string + email string + } + type args struct { + ctx context.Context + repoName string + webhookUrl string + webhookSecret string + } + tests := []struct { + name string + fields fields + args args + wantErr assert.ErrorAssertionFunc + }{ + { + name: "normal ok", + fields: fields{ + c: MockGitLabProjects("AddProjectHook", + []interface{}{ + &gitlab.ProjectHook{ + URL: "https://dummywebhooks.local", + MergeRequestsEvents: true, + NoteEvents: true, + }, + &gitlab.Response{Response: &http.Response{StatusCode: http.StatusOK}}, + nil, + }), + cfg: config.ServerConfig{}, + username: "", + email: "", + }, + args: args{ + ctx: context.TODO(), + repoName: "main", + webhookUrl: "https://dummywebhooks.local", + webhookSecret: "", + }, + wantErr: assert.NoError, + }, + { + name: "gitlab error", + fields: fields{ + c: MockGitLabProjects("AddProjectHook", + []interface{}{ + nil, + &gitlab.Response{Response: &http.Response{StatusCode: http.StatusInternalServerError}}, + fmt.Errorf("dummy error"), + }), + cfg: config.ServerConfig{}, + username: "", + email: "", + }, + args: args{ + ctx: context.TODO(), + repoName: "main", + webhookUrl: "https://dummywebhooks.local", + webhookSecret: "", + }, + wantErr: assert.Error, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Client{ + c: tt.fields.c, + cfg: tt.fields.cfg, + username: tt.fields.username, + email: tt.fields.email, + } + tt.wantErr(t, c.CreateHook(tt.args.ctx, tt.args.repoName, tt.args.webhookUrl, tt.args.webhookSecret), fmt.Sprintf("CreateHook(%v, %v, %v, %v)", tt.args.ctx, tt.args.repoName, tt.args.webhookUrl, tt.args.webhookSecret)) + }) + } +} diff --git a/pkg/vcs/gitlab_client/merge.go b/pkg/vcs/gitlab_client/merge.go index 62f63427..7431e0f7 100644 --- a/pkg/vcs/gitlab_client/merge.go +++ b/pkg/vcs/gitlab_client/merge.go @@ -83,3 +83,15 @@ func (chg *Changes) validChange(path, fileType string) bool { return false } + +type MergeRequestsServices interface { + GetMergeRequestDiffVersions(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestDiffVersionsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiffVersion, *gitlab.Response, error) + GetMergeRequestChanges(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestChangesOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) + ListMergeRequestDiffs(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestDiffsOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.MergeRequestDiff, *gitlab.Response, error) + UpdateMergeRequest(pid interface{}, mergeRequest int, opt *gitlab.UpdateMergeRequestOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) + GetMergeRequest(pid interface{}, mergeRequest int, opt *gitlab.GetMergeRequestsOptions, options ...gitlab.RequestOptionFunc) (*gitlab.MergeRequest, *gitlab.Response, error) +} + +type MergeRequestsService struct { + MergeRequestsServices +} diff --git a/pkg/vcs/gitlab_client/message.go b/pkg/vcs/gitlab_client/message.go index 48e9e59f..50ed3fe7 100644 --- a/pkg/vcs/gitlab_client/message.go +++ b/pkg/vcs/gitlab_client/message.go @@ -162,3 +162,14 @@ func (c *Client) TidyOutdatedComments(ctx context.Context, pr vcs.PullRequest) e return c.hideOutdatedMessages(ctx, pr.FullName, pr.CheckID, allNotes) } + +type NotesServices interface { + CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *gitlab.CreateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) + UpdateMergeRequestNote(pid interface{}, mergeRequest, note int, opt *gitlab.UpdateMergeRequestNoteOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Note, *gitlab.Response, error) + DeleteMergeRequestNote(pid interface{}, mergeRequest, note int, options ...gitlab.RequestOptionFunc) (*gitlab.Response, error) + ListMergeRequestNotes(pid interface{}, mergeRequest int, opt *gitlab.ListMergeRequestNotesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.Note, *gitlab.Response, error) +} + +type NotesService struct { + NotesServices +} diff --git a/pkg/vcs/gitlab_client/pipeline.go b/pkg/vcs/gitlab_client/pipeline.go index 40bdd7e5..a1bbcf07 100644 --- a/pkg/vcs/gitlab_client/pipeline.go +++ b/pkg/vcs/gitlab_client/pipeline.go @@ -57,3 +57,11 @@ func (c *Client) GetLastPipelinesForCommit(projectName string, commitSHA string) return nil } + +type PipelinesServices interface { + ListProjectPipelines(pid interface{}, opt *gitlab.ListProjectPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineInfo, *gitlab.Response, error) +} + +type PipelinesService struct { + PipelinesServices +} diff --git a/pkg/vcs/gitlab_client/project.go b/pkg/vcs/gitlab_client/project.go index 374884e0..76527c5b 100644 --- a/pkg/vcs/gitlab_client/project.go +++ b/pkg/vcs/gitlab_client/project.go @@ -42,3 +42,22 @@ func (c *Client) GetRepoConfigFile(ctx context.Context, projectId int, mergeReqI return nil, errors.New(".kubecheck.yaml file not found") } + +type ProjectsServices interface { + AddProjectHook(pid interface{}, opt *gitlab.AddProjectHookOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error) + ListProjectHooks(pid interface{}, opt *gitlab.ListProjectHooksOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.ProjectHook, *gitlab.Response, error) + EditProjectHook(pid interface{}, hook int, opt *gitlab.EditProjectHookOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectHook, *gitlab.Response, error) + GetProject(pid interface{}, opt *gitlab.GetProjectOptions, options ...gitlab.RequestOptionFunc) (*gitlab.Project, *gitlab.Response, error) +} + +type ProjectsService struct { + ProjectsServices +} + +type RepositoryFilesServices interface { + GetRawFile(pid interface{}, fileName string, opt *gitlab.GetRawFileOptions, options ...gitlab.RequestOptionFunc) ([]byte, *gitlab.Response, error) +} + +type RepositoryFilesService struct { + RepositoryFilesServices +} diff --git a/pkg/vcs/gitlab_client/status.go b/pkg/vcs/gitlab_client/status.go index d3794332..b6b9cc4d 100644 --- a/pkg/vcs/gitlab_client/status.go +++ b/pkg/vcs/gitlab_client/status.go @@ -92,3 +92,11 @@ func configureBackOff() *backoff.ExponentialBackOff { return expBackOff } + +type CommitsServices interface { + SetCommitStatus(pid interface{}, sha string, opt *gitlab.SetCommitStatusOptions, options ...gitlab.RequestOptionFunc) (*gitlab.CommitStatus, *gitlab.Response, error) +} + +type CommitsService struct { + CommitsServices +} diff --git a/pkg/vcs/types.go b/pkg/vcs/types.go index 2512c74c..366dd99c 100644 --- a/pkg/vcs/types.go +++ b/pkg/vcs/types.go @@ -22,8 +22,8 @@ type Client interface { UpdateMessage(context.Context, *msg.Message, string) error // VerifyHook validates a webhook secret and return the body; must be called even if no secret VerifyHook(*http.Request, string) ([]byte, error) - // ParseHook parses webook payload for valid events - ParseHook(*http.Request, []byte) (PullRequest, error) + // ParseHook parses webook payload for valid events, with context for request-scoped values + ParseHook(context.Context, *http.Request, []byte) (PullRequest, error) // CommitStatus sets a status for a specific commit on the remote VCS CommitStatus(context.Context, PullRequest, pkg.CommitState) error // GetHookByUrl gets a webhook by url