diff --git a/github/github.go b/github/github.go
index feb3382..2e777f5 100644
--- a/github/github.go
+++ b/github/github.go
@@ -14,8 +14,6 @@
// limitations under the License.
//
-//go:build go1.16
-
package github
import (
diff --git a/github/github_mocks.go b/github/github_mocks.go
index 98dc727..d6ebe27 100644
--- a/github/github_mocks.go
+++ b/github/github_mocks.go
@@ -14,49 +14,63 @@
// limitations under the License.
//
-//go:build go1.16
-
package github
import (
"context"
"net/http"
"os"
+ "reflect"
"testing"
"github.com/google/go-github/v64/github"
"github.com/stretchr/testify/assert"
)
+type assertParams struct {
+ /* number of index/times the production function has been called by production code, zero based. */
+ callIndex int
+ /* assertParameters is a slice of booleans that determine whether to assert the parameters passed to the function for
+ each call to the production function. If the value at the index of the callIndex is true, the actual parameters will be
+ asserted against the expected parameters. */
+ assertParameters []bool
+ /* expectedParameters is a slice of any types of slices that contains the expected parameters that should be passed
+ to the production function during the running of test. */
+ expectedParameters []any
+}
+
+func (a *assertParams) doAssert(t assert.TestingT, actualParameters []any) {
+ for i, expParams := range a.expectedParameters {
+ refExpParams := reflect.ValueOf(expParams)
+ assert.Equal(t, reflect.Slice, refExpParams.Kind(), "expected parameters must be a slice")
+ epForThisCall := refExpParams.Index(a.callIndex).Interface()
+ assert.Equal(t, epForThisCall, actualParameters[i])
+ }
+}
+
// RepositoriesMock mocks RepositoriesService
type RepositoriesMock struct {
- t *testing.T
- /* callCount is the number of times the CreateStatus function has been called by production code. */
- callCount int
- /* assertParameters is a slice of booleans that determine whether to assert the parameters passed to the function for
- each call to the CreateStatus function. If the value at the index of the callCount is true, the parameters will be
- asserted.
- */
- assertParameters []bool
- expectedCtx []context.Context
- expectedOwner, expectedRepo, expectedRef, expectedUser []string
- // expectedOpts *github.ListOptions
- expectedCreateStatusRepoStatus []*github.RepoStatus
- createStatusRepoStatus []*github.RepoStatus
- createStatusResponse []*github.Response
- createStatusError []error
- isCollaboratorResult bool
- isCollaboratorResp *github.Response
- isCollaboratorErr error
+ t *testing.T
+ assertParamsCreateStatus assertParams
+ createStatusRepoStatus []*github.RepoStatus
+ createStatusResponse []*github.Response
+ createStatusError []error
+ isCollaboratorResult bool
+ isCollaboratorResp *github.Response
+ isCollaboratorErr error
}
var _ RepositoriesService = (*RepositoriesMock)(nil)
-func setupMockRepositoriesService(t *testing.T, assertParameters []bool) (mock *RepositoriesMock) {
+func setupMockRepositoriesService(t *testing.T, assertParameters []bool, expectedParams []any) (mock *RepositoriesMock) {
mock = &RepositoriesMock{
- t: t,
- assertParameters: assertParameters,
+ t: t,
+ assertParamsCreateStatus: assertParams{
+ assertParameters: assertParameters,
+ expectedParameters: expectedParams,
+ },
}
+
return mock
}
@@ -67,35 +81,22 @@ func (r *RepositoriesMock) ListStatuses(ctx context.Context, owner, repo, ref st
}
func (r *RepositoriesMock) CreateStatus(ctx context.Context, owner, repo, ref string, status *github.RepoStatus) (retRepoStatus *github.RepoStatus, createStatusResponse *github.Response, createStatusError error) {
- defer func() { r.callCount++ }()
- if r.assertParameters != nil && r.assertParameters[r.callCount] {
- if r.expectedCtx != nil {
- assert.Equal(r.t, r.expectedCtx[r.callCount], ctx)
- }
- if r.expectedOwner != nil {
- assert.Equal(r.t, r.expectedOwner[r.callCount], owner)
- }
- if r.expectedRepo != nil {
- assert.Equal(r.t, r.expectedRepo[r.callCount], repo)
- }
- if r.expectedRef != nil {
- assert.Equal(r.t, r.expectedRef[r.callCount], ref)
- }
- if r.expectedCreateStatusRepoStatus != nil {
- assert.Equal(r.t, r.expectedCreateStatusRepoStatus[r.callCount], status)
- }
+ defer func() { r.assertParamsCreateStatus.callIndex++ }()
+ if r.assertParamsCreateStatus.assertParameters != nil && r.assertParamsCreateStatus.assertParameters[r.assertParamsCreateStatus.callIndex] {
+ actualParameters := []any{ctx, owner, repo, ref, status}
+ r.assertParamsCreateStatus.doAssert(r.t, actualParameters)
}
if r.createStatusRepoStatus != nil {
- retRepoStatus = r.createStatusRepoStatus[r.callCount]
+ retRepoStatus = r.createStatusRepoStatus[r.assertParamsCreateStatus.callIndex]
}
if r.createStatusRepoStatus != nil {
- createStatusResponse = r.createStatusResponse[r.callCount]
+ createStatusResponse = r.createStatusResponse[r.assertParamsCreateStatus.callIndex]
}
if r.createStatusError != nil {
- createStatusError = r.createStatusError[r.callCount]
+ createStatusError = r.createStatusError[r.assertParamsCreateStatus.callIndex]
}
return
}
@@ -113,13 +114,8 @@ func (r *RepositoriesMock) Get(context.Context, string, string) (*github.Reposit
}, nil, nil
}
+//goland:noinspection GoUnusedParameter
func (r *RepositoriesMock) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *github.Response, error) {
- if r.assertParameters != nil && r.assertParameters[r.callCount] {
- assert.Equal(r.t, r.expectedCtx[r.callCount], ctx)
- assert.Equal(r.t, r.expectedOwner[r.callCount], owner)
- assert.Equal(r.t, r.expectedRepo[r.callCount], repo)
- assert.Equal(r.t, r.expectedUser[r.callCount], user)
- }
return r.isCollaboratorResult, r.isCollaboratorResp, r.isCollaboratorErr
}
@@ -152,6 +148,8 @@ func (p *PullRequestsMock) ListCommits(ctx context.Context, owner string, repo s
}
type IssuesMock struct {
+ t *testing.T
+ assertParamsCreateComment assertParams
mockGetLabel *github.Label
MockGetLabelResponse *github.Response
mockGetLabelError error
@@ -203,6 +201,11 @@ func (i *IssuesMock) RemoveLabelForIssue(ctx context.Context, owner string, repo
//goland:noinspection GoUnusedParameter
func (i *IssuesMock) CreateComment(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) {
+ defer func() { i.assertParamsCreateComment.callIndex++ }()
+ if i.assertParamsCreateComment.assertParameters != nil && i.assertParamsCreateComment.assertParameters[i.assertParamsCreateComment.callIndex] {
+ actualParameters := []any{ctx, owner, repo, number, comment}
+ i.assertParamsCreateComment.doAssert(i.t, actualParameters)
+ }
return i.mockComment, i.mockCreateCommentResponse, i.mockCreateCommentError
}
@@ -290,6 +293,8 @@ func (g *GHInterfaceMock) NewClient(httpClient *http.Client) GHClient {
mockResponse: g.PullRequestsMock.mockResponse,
},
Issues: &IssuesMock{
+ t: g.IssuesMock.t,
+ assertParamsCreateComment: g.IssuesMock.assertParamsCreateComment,
mockGetLabel: g.IssuesMock.mockGetLabel,
MockGetLabelResponse: g.IssuesMock.MockGetLabelResponse,
mockGetLabelError: g.IssuesMock.mockGetLabelError,
diff --git a/github/github_test.go b/github/github_test.go
index 7e13287..bc98655 100644
--- a/github/github_test.go
+++ b/github/github_test.go
@@ -14,8 +14,6 @@
// limitations under the License.
//
-//go:build go1.16
-
package github
import (
@@ -351,7 +349,7 @@ func TestWithFullEnvironment(t *testing.T) {
t.Run("TestHandlePullRequestListCommitsError", func(t *testing.T) {
forcedError := fmt.Errorf("forced ListCommits error")
GHImpl = &GHInterfaceMock{
- RepositoriesMock: *setupMockRepositoriesService(t, []bool{false}),
+ RepositoriesMock: *setupMockRepositoriesService(t, []bool{false}, nil),
PullRequestsMock: PullRequestsMock{
mockListCommitsError: forcedError,
},
@@ -390,21 +388,26 @@ func TestWithFullEnvironment(t *testing.T) {
t.Run("TestHandlePullRequestListCommitsUnsignedCommit", func(t *testing.T) {
authors := []string{"john", "doe"}
- repositoriesMock := *setupMockRepositoriesService(t, []bool{true, true})
- repositoriesMock.expectedCtx = []context.Context{context.Background(), context.Background()}
-
- repositoriesMock.expectedCreateStatusRepoStatus = []*github.RepoStatus{
- {
- State: github.String("pending"),
- Description: github.String("Paul Botsco, the CLA verifier is running"),
- Context: &MockAppSlug,
- },
- {
- State: github.String("failure"),
- Description: github.String("One or more commits haven't met our Quality requirements."),
- Context: &MockAppSlug,
- },
- }
+ repositoriesMock := *setupMockRepositoriesService(t,
+ []bool{true, true},
+ []any{
+ []context.Context{context.Background(), context.Background()}, // ctx
+ []string{"", ""}, // owner
+ []string{"", ""}, // repo
+ []string{"", ""}, // sha
+ []*github.RepoStatus{
+ {
+ State: github.String("pending"),
+ Description: github.String("Paul Botsco, the CLA verifier is running"),
+ Context: &MockAppSlug,
+ },
+ {
+ State: github.String("failure"),
+ Description: github.String("One or more commits haven't met our Quality requirements."),
+ Context: &MockAppSlug,
+ },
+ },
+ })
GHImpl = getGHMock(getMockRepositoryCommits(authors, false), nil, &repositoriesMock)
mockDB, logger := setupMockDB(t, false)
@@ -542,6 +545,27 @@ func TestHandlePullRequestListCommitsNoAuthor(t *testing.T) {
mockRepositoryCommits: mockRepositoryCommits,
},
IssuesMock: IssuesMock{
+ t: t,
+ assertParamsCreateComment: assertParams{
+ assertParameters: []bool{true},
+ expectedParameters: []any{
+ []context.Context{context.Background()}, // ctx
+ []string{""}, // owner
+ []string{""}, // repo
+ []int{0}, // number
+ []*github.IssueComment{
+ {Body: github.String(
+ `Thanks for the contribution. Unfortunately some of your commits don't meet our standards. All commits must be signed and have author information set.
+
+The commits to review are:
+
+- johnSHA - missing author :cop:
+- johnSHA - unsigned commit :key:
+`,
+ )},
+ }, // comment
+ },
+ },
mockGetLabel: &github.Label{},
MockGetLabelResponse: &github.Response{
Response: &http.Response{},
diff --git a/go.mod b/go.mod
index cd1853d..3f35d58 100644
--- a/go.mod
+++ b/go.mod
@@ -1,20 +1,20 @@
module github.com/sonatype-nexus-community/the-cla
-go 1.21
+go 1.22.0
-toolchain go1.21.7
+toolchain go1.22.7
require (
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0
- github.com/golang-migrate/migrate/v4 v4.17.1
+ github.com/golang-migrate/migrate/v4 v4.18.1
github.com/google/go-github/v64 v64.0.0
github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v4 v4.12.0
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
- golang.org/x/oauth2 v0.21.0
+ golang.org/x/oauth2 v0.23.0
gopkg.in/go-playground/webhooks.v5 v5.17.0
)
@@ -35,10 +35,10 @@ require (
github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.24.0 // indirect
- golang.org/x/net v0.26.0 // indirect
- golang.org/x/sys v0.21.0 // indirect
- golang.org/x/text v0.16.0 // indirect
- golang.org/x/time v0.5.0 // indirect
+ golang.org/x/crypto v0.27.0 // indirect
+ golang.org/x/net v0.29.0 // indirect
+ golang.org/x/sys v0.25.0 // indirect
+ golang.org/x/text v0.18.0 // indirect
+ golang.org/x/time v0.6.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 37d0f8a..6f0fc70 100644
--- a/go.sum
+++ b/go.sum
@@ -4,18 +4,22 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0 h1:R9d0v+iobRHSaE4wKUnXFiZp53AL4ED5MzgEMwGTZag=
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0/go.mod h1:0LWKQwOHewXO/1acI6TtyE0Xc4ObDb2rFN7eHBAG71M=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg=
github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA=
+github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -26,6 +30,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
+github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y=
+github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks=
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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -44,6 +50,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
@@ -64,6 +72,7 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -74,6 +83,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -82,27 +93,66 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
+golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
+golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
+golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
+golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
+golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
+golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/webhooks.v5 v5.17.0 h1:truBced5ZmkiNKK47cM8bMe86wUSjNks7SFMuNKwzlc=