diff --git a/go.mod b/go.mod index 432faa9d0..ea07dd490 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/sirupsen/logrus v1.9.4 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 - gitlab.com/gitlab-org/api/client-go v0.145.0 + gitlab.com/gitlab-org/api/client-go v1.46.0 golang.org/x/sync v0.19.0 k8s.io/apimachinery v0.34.4 k8s.io/client-go v0.34.4 @@ -68,10 +68,10 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/gojek/valkyrie v0.0.0-20180215180059-6aee720afcdf // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/cel-go v0.26.1 // indirect + github.com/google/cel-go v0.27.0 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect + github.com/google/go-querystring v1.2.0 // indirect github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -125,20 +125,20 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/arch v0.20.0 // indirect golang.org/x/crypto v0.47.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect golang.org/x/mod v0.32.0 // indirect golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.39.0 // indirect golang.org/x/text v0.33.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.41.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/grpc v1.79.3 // indirect - google.golang.org/protobuf v1.36.10 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 5ca61f0fa..cb80ea223 100644 --- a/go.sum +++ b/go.sum @@ -124,10 +124,13 @@ github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0= +github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -302,6 +305,8 @@ github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= gitlab.com/gitlab-org/api/client-go v0.145.0 h1:gvi4bwoF6fyQq6kJix4WicApy/jBRpGlqzI0PDRD9kU= gitlab.com/gitlab-org/api/client-go v0.145.0/go.mod h1:eABRp++g3IbUP10ZeBIys+9g59dgJnlQLEk8XgKNB54= +gitlab.com/gitlab-org/api/client-go v1.46.0 h1:YxBWFZIFYKcGESCb9fpkwzouo+apyB9pr/XTWzNoL24= +gitlab.com/gitlab-org/api/client-go v1.46.0/go.mod h1:FtgyU6g2HS5+fMhw6nLK96GBEEBx5MzntOiJWfIaiN8= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= @@ -343,6 +348,8 @@ golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE= +golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -382,6 +389,8 @@ golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -406,6 +415,8 @@ google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pkg/clients/gitlab/team_membership.go b/pkg/clients/gitlab/team_membership.go index 388bcd543..25f1f4ef2 100644 --- a/pkg/clients/gitlab/team_membership.go +++ b/pkg/clients/gitlab/team_membership.go @@ -64,7 +64,7 @@ func (g *GitlabClient) AddUserToTeam(ctx context.Context, teamID string, userIDs accessLevel := gitlab.DeveloperPermissions for _, userID := range userIDs { - userIDInt, convErr := strconv.Atoi(userID) + userIDInt, convErr := strconv.ParseInt(userID, 10, 64) if convErr != nil { return convErr } @@ -96,7 +96,7 @@ func (g *GitlabClient) RemoveUserFromTeam(ctx context.Context, teamID string, us } for _, userID := range userIDs { - userIDInt, convErr := strconv.Atoi(userID) + userIDInt, convErr := strconv.ParseInt(userID, 10, 64) if convErr != nil { return convErr } @@ -127,7 +127,7 @@ func (g *GitlabClient) ReconcileGroupParams(ctx context.Context, teamID string, return fmt.Errorf("team %s not found to reconcile group params", teamID) } - teamIDInt, convErr := strconv.Atoi(teamID) + teamIDInt, convErr := strconv.ParseInt(teamID, 10, 64) if convErr != nil { return convErr } diff --git a/pkg/clients/gitlab/teams.go b/pkg/clients/gitlab/teams.go index 2f3680591..de2d2ef7d 100644 --- a/pkg/clients/gitlab/teams.go +++ b/pkg/clients/gitlab/teams.go @@ -160,7 +160,7 @@ func (g *GitlabClient) DeleteTeamByID(ctx context.Context, teamID string) error return nil } -func (g *GitlabClient) addToLdapGroup(groupID int) (string, int, error) { +func (g *GitlabClient) addToLdapGroup(groupID int64) (string, int, error) { accessLevel := gitlab.DeveloperPermissions ldapLink, response, err := g.gitlabClient.Groups.AddGroupLDAPLink(groupID, &gitlab.AddGroupLDAPLinkOptions{ GroupAccess: &accessLevel, @@ -216,7 +216,7 @@ func (g *GitlabClient) pollForPendingDeletion(ctx context.Context, return "", fmt.Errorf("timeout: Group %v was not marked for deletion after %d attempts", teamID, maxAttempts) } -func (g *GitlabClient) addGroupAsProjectDeveloper(groupID int, projectPathString string) (int, error) { +func (g *GitlabClient) addGroupAsProjectDeveloper(groupID int64, projectPathString string) (int, error) { developerAccess := gitlab.DeveloperPermissions opt := &gitlab.ShareWithGroupOptions{ GroupID: &groupID, diff --git a/pkg/clients/gitlab/types.go b/pkg/clients/gitlab/types.go index 2a4e83d80..049c99aca 100644 --- a/pkg/clients/gitlab/types.go +++ b/pkg/clients/gitlab/types.go @@ -37,5 +37,5 @@ type GitlabClient struct { type GitlabConfig struct { URL string `json:"url"` Token string `json:"token"` - ParentGroupId int `json:"parent_group_id"` + ParentGroupId int64 `json:"parent_group_id"` } diff --git a/pkg/clients/gitlab/users.go b/pkg/clients/gitlab/users.go index d68cfdbf4..de1845b7e 100644 --- a/pkg/clients/gitlab/users.go +++ b/pkg/clients/gitlab/users.go @@ -65,7 +65,7 @@ func (g *GitlabClient) FetchAllUsers(ctx context.Context) (map[string]*structs.U } // Check if we got fewer users than requested (last page) - if len(users) < opt.PerPage { + if int64(len(users)) < opt.PerPage { break } @@ -88,7 +88,7 @@ func (g *GitlabClient) FetchUserDetails(ctx context.Context, userID string) (*st log.Info("fetching user details") var user *gitlab.User - userIDInt, err := strconv.Atoi(userID) + userIDInt, err := strconv.ParseInt(userID, 10, 64) if err != nil { var numErr *strconv.NumError // If the error is a syntax error, it's not a number, so we assume it's a username. @@ -186,7 +186,7 @@ func (g *GitlabClient) DeleteUser(ctx context.Context, userID string) error { return nil } - userIDInt, err := strconv.Atoi(userID) + userIDInt, err := strconv.ParseInt(userID, 10, 64) if err != nil { log.WithError(err).Error("Failed to convert userID to int") return err diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go index 91198f819..c93695403 100644 --- a/vendor/github.com/google/go-querystring/query/encode.go +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -6,22 +6,21 @@ // // As a simple example: // -// type Options struct { -// Query string `url:"q"` -// ShowAll bool `url:"all"` -// Page int `url:"page"` -// } +// type Options struct { +// Query string `url:"q"` +// ShowAll bool `url:"all"` +// Page int `url:"page"` +// } // -// opt := Options{ "foo", true, 2 } -// v, _ := query.Values(opt) -// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" +// opt := Options{ "foo", true, 2 } +// v, _ := query.Values(opt) +// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" // // The exact mapping between Go values and url.Values is described in the // documentation for the Values() function. package query import ( - "bytes" "fmt" "net/url" "reflect" @@ -47,8 +46,8 @@ type Encoder interface { // // Each exported struct field is encoded as a URL parameter unless // -// - the field's tag is "-", or -// - the field is empty and its tag specifies the "omitempty" option +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option // // The empty values are false, 0, any nil pointer or interface value, any array // slice, map, or string of length zero, and any type (such as time.Time) that @@ -59,19 +58,19 @@ type Encoder interface { // field's tag value is the key name, followed by an optional comma and // options. For example: // -// // Field is ignored by this package. -// Field int `url:"-"` +// // Field is ignored by this package. +// Field int `url:"-"` // -// // Field appears as URL parameter "myName". -// Field int `url:"myName"` +// // Field appears as URL parameter "myName". +// Field int `url:"myName"` // -// // Field appears as URL parameter "myName" and the field is omitted if -// // its value is empty -// Field int `url:"myName,omitempty"` +// // Field appears as URL parameter "myName" and the field is omitted if +// // its value is empty +// Field int `url:"myName,omitempty"` // -// // Field appears as URL parameter "Field" (the default), but the field -// // is skipped if empty. Note the leading comma. -// Field int `url:",omitempty"` +// // Field appears as URL parameter "Field" (the default), but the field +// // is skipped if empty. Note the leading comma. +// Field int `url:",omitempty"` // // For encoding individual field values, the following type-dependent rules // apply: @@ -88,8 +87,8 @@ type Encoder interface { // "url" tag) will use the value of the "layout" tag as a layout passed to // time.Format. For example: // -// // Encode a time.Time as YYYY-MM-DD -// Field time.Time `layout:"2006-01-02"` +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` // // Slice and Array values default to encoding as multiple URL values of the // same name. Including the "comma" option signals that the field should be @@ -103,9 +102,9 @@ type Encoder interface { // from the "url" tag) will use the value of the "del" tag as the delimiter. // For example: // -// // Encode a slice of bools as ints ("1" for true, "0" for false), -// // separated by exclamation points "!". -// Field []bool `url:",int" del:"!"` +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the standard Go @@ -114,10 +113,10 @@ type Encoder interface { // // Non-nil pointer values are encoded as the value pointed to. // -// Nested structs are encoded including parent fields in value names for -// scoping. e.g: +// Nested structs have their fields processed recursively and are encoded +// including parent fields in value names for scoping. For example, // -// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" // // All other values are encoded using their default string representation. // @@ -125,6 +124,11 @@ type Encoder interface { // as multiple URL values of the same name. func Values(v interface{}) (url.Values, error) { values := make(url.Values) + + if v == nil { + return values, nil + } + val := reflect.ValueOf(v) for val.Kind() == reflect.Ptr { if val.IsNil() { @@ -133,10 +137,6 @@ func Values(v interface{}) (url.Values, error) { val = val.Elem() } - if v == nil { - return values, nil - } - if val.Kind() != reflect.Struct { return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) } @@ -209,6 +209,11 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { + if sv.Len() == 0 { + // skip if slice or array is empty + continue + } + var del string if opts.Contains("comma") { del = "," @@ -223,7 +228,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if del != "" { - s := new(bytes.Buffer) + s := new(strings.Builder) first := true for i := 0; i < sv.Len(); i++ { if first { diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/.gitignore b/vendor/gitlab.com/gitlab-org/api/client-go/.gitignore index 79e862f1f..6dc065c6b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/.gitignore +++ b/vendor/gitlab.com/gitlab-org/api/client-go/.gitignore @@ -39,3 +39,5 @@ scripts/commitlint/node_modules gl-code-quality-report.json .mise/ +Gitlab-license.txt +.vscode/ diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/.gitlab-ci.yml b/vendor/gitlab.com/gitlab-org/api/client-go/.gitlab-ci.yml index c51a13685..76df79623 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/.gitlab-ci.yml +++ b/vendor/gitlab.com/gitlab-org/api/client-go/.gitlab-ci.yml @@ -7,9 +7,11 @@ workflow: include: - template: Jobs/SAST.gitlab-ci.yml - - component: ${CI_SERVER_FQDN}/gitlab-org/components/danger-review/danger-review@2.0.0 + - component: ${CI_SERVER_FQDN}/components/dependency-scanning/main@0.8.0 + - component: ${CI_SERVER_FQDN}/components/dependency-scanning/main@0.8.0 + - component: ${CI_SERVER_FQDN}/gitlab-com/gl-infra/common-ci-tasks/danger@v3.5.3 inputs: - job_stage: lint + stage: lint job_allow_failure: true # NOTE: the two includes below are a hack to conditionally set the tags node @@ -18,17 +20,38 @@ include: # groups. However, there is no easy way to conditionally set tags or even variables without # jeopardizing existing (complex) workflow:rules or job:rules. Thus, we resort to # this nasty conditionally include hack. - - local: '.gitlab/ci/gitlab-go-runner-tags.gitlab-ci.yml' + - local: ".gitlab/ci/gitlab-go-runner-tags.gitlab-ci.yml" rules: - if: $CI_PROJECT_ROOT_NAMESPACE == 'gitlab-org' || $CI_PROJECT_ROOT_NAMESPACE == 'gitlab-community' - - local: '.gitlab/ci/community-go-runner-tags.gitlab-ci.yml' + - local: ".gitlab/ci/community-go-runner-tags.gitlab-ci.yml" rules: - if: $CI_PROJECT_ROOT_NAMESPACE != 'gitlab-org' && $CI_PROJECT_ROOT_NAMESPACE != 'gitlab-community' + + # Add Work Type Classification labels to merge requests, + # see https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/autolabels.md + - project: "gitlab-com/gl-infra/common-ci-tasks" + ref: v2.93.0 + file: "autolabels.yml" + inputs: + stage: lint + + + # Add Work Type Classification labels to merge requests, + # see https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/autolabels.md + - project: "gitlab-com/gl-infra/common-ci-tasks" + ref: v2.93.0 + file: "autolabels.yml" + inputs: + stage: lint + # Analyze commits to determine whether to cut a release # see https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/semantic-release.md - - project: 'gitlab-com/gl-infra/common-ci-tasks' - ref: v2.85.0 # renovate:managed - file: 'semantic-release.yml' + - project: "gitlab-com/gl-infra/common-ci-tasks" + ref: v2.93.0 + file: "semantic-release.yml" + - project: "gitlab-com/gl-infra/common-ci-tasks" + ref: v2.93.0 + file: "semantic-release.yml" inputs: stage: deploy validate_stage: lint @@ -43,8 +66,8 @@ stages: parallel: matrix: - GOLANG_IMAGE_VERSION: - - '1.23' - '1.24' + - '1.25' .go:base: extends: @@ -71,17 +94,17 @@ stages: - $GOLANGCI_LINT_CACHE/ - key: prefix: mise- - files: ['.tool-versions'] + files: [".tool-versions"] paths: - $MISE_DATA_DIR # We only need to run Go-related jobs when actual Go files changed # or when running either on the default branch or for a tag. rules: - - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH" - if: $CI_COMMIT_TAG - changes: - - '**/*.go' + - "**/*.go" - testdata/** - go.mod - go.sum @@ -97,8 +120,8 @@ golangci-lint: stage: lint needs: [] variables: - REPORT_FILENAME: 'gl-code-quality-report.json' - image: golangci/golangci-lint:v2.4.0 + REPORT_FILENAME: "gl-code-quality-report.json" + image: golangci/golangci-lint:v2.10.1 script: - golangci-lint run artifacts: @@ -134,31 +157,37 @@ verify-generated-code: exit 1; } -commitlint: - stage: lint +Download GraphQL schema: + stage: test needs: [] - rules: - # lint.js script makes an API call without authentication, so the project or fork must be public - - if: '$CI_MERGE_REQUEST_IID && $CI_PROJECT_VISIBILITY == "public"' - when: always - image: ${GITLAB_DEPENDENCY_PROXY}node:22-slim + image: node:25-alpine script: - - apt-get update && apt-get install -y git - - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_COMMIT_SHA - - cd scripts/commitlint && npm ci - - ./lint.sh + - | + if [ ! -f schema/gitlab.graphql ]; then + mkdir schema + npm install -g get-graphql-schema + get-graphql-schema "${CI_API_GRAPHQL_URL}" --sdl >schema/gitlab.graphql + fi + cache: + key: $CI_COMMIT_REF_SLUG + paths: + - schema/gitlab.graphql + policy: pull-push + artifacts: + paths: + - schema/gitlab.graphql tests:unit: extends: - - .go:base - .go:versions stage: test - needs: [] + needs: + - Download GraphQL schema image: golang:$GOLANG_IMAGE_VERSION variables: # configure tooling versions - GOTESTSUM_VERSION: 'v1.12.0' - GOCOVER_COBERTURA_VERSION: 'v1.2.1-0.20240107185409-0818f3538137' + GOTESTSUM_VERSION: 'v1.13.0' + GOCOVER_COBERTURA_VERSION: 'v1.4.0' # configure artifact files JUNIT_FILENAME: tests.xml @@ -182,6 +211,61 @@ tests:unit: coverage_format: cobertura when: always +tests:integration: + stage: test + rules: + - if: $ENABLE_EE_ACCEPTANCE_TESTS == "true" + needs: [] + image: golang:1.25-bookworm + timeout: 2 hours + services: + - docker:29.2.1-dind + variables: + # Docker-in-docker configuration + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_VERIFY: 1 + DOCKER_TLS_CERTDIR: "/certs" + DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" + + # GitLab test configuration + GITLAB_BASE_URL: http://docker:8095/api/v4 + + # Since we're not using the makefile, this doesn't default to the testing token + # properly. + GITLAB_TOKEN: "glpat-ACCTEST1234567890123" + + # configure tooling versions + GOTESTSUM_VERSION: 'v1.12.0' + GOCOVER_COBERTURA_VERSION: 'v1.2.1-0.20240107185409-0818f3538137' + MISE_VERSION: v2025.6.1 + + # configure artifact files + JUNIT_FILENAME: integration-tests.xml + COVERPROFILE_FILENAME: integration-coverage.out + COVERPROFILE_XML_FILENAME: integration-coverage.xml + before_script: + # Install docker + compose + - curl -fsSL https://get.docker.com | sh + # Install mise + - curl --retry 3 https://mise.run | MISE_VERSION=${MISE_VERSION} MISE_INSTALL_PATH=/usr/local/bin/mise sh + - eval "$(mise activate bash --shims)" + + # Install Go and other tools with mise + - mise install + + # Copy the license to the correct location + - test -f "${GITLAB_LICENSE}" && cp "${GITLAB_LICENSE}" "${CI_PROJECT_DIR}/Gitlab-license.txt" + + # Start GitLab instance + - make testacc-up SERVICE=gitlab-ee + script: + - go run gotest.tools/gotestsum@${GOTESTSUM_VERSION} --format=standard-quiet --junitfile=$JUNIT_FILENAME -- -race -coverprofile=$COVERPROFILE_FILENAME -covermode=atomic -tags=integration ./gitlab_test/... + - grep -v '_generated.go' "$COVERPROFILE_FILENAME" | grep -v '_mock.go' > "${COVERPROFILE_FILENAME}.tmp" + - mv "${COVERPROFILE_FILENAME}.tmp" "$COVERPROFILE_FILENAME" + - go run github.com/boumenot/gocover-cobertura@${GOCOVER_COBERTURA_VERSION} < $COVERPROFILE_FILENAME > $COVERPROFILE_XML_FILENAME + - go tool cover -func $COVERPROFILE_FILENAME + + # Update rules on SAST to ensure the jobs show up in the pipeline # this prevents forks that don't have `ultimate` from skipping SAST scans # since gitlab-advaced-sast replaces semgrep. @@ -190,12 +274,11 @@ semgrep-sast: rules: - when: always -# Patch common-ci semantic release jobs -semantic_release_check: - before_script: - - npm install -g semantic-release @semantic-release/gitlab @semantic-release/git @semantic-release/changelog - -semantic_release: - script: - - npm install -g semantic-release @semantic-release/gitlab @semantic-release/git @semantic-release/changelog - - semantic-release +# Update rules on dependency scanning so that it only runs when on the +# canonical project or the community fork. This ensures that when people +# use personal forks, it doesn't fail stating the forks are unlicensed. +dependency-scanning: + rules: + - if: $CI_PROJECT_ID == "65271576" # Canonical repository + - if: $CI_PROJECT_ID == "65275361" # Community Fork + - when: never diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/.golangci.yml b/vendor/gitlab.com/gitlab-org/api/client-go/.golangci.yml index 48438462d..7df81bdf5 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/.golangci.yml +++ b/vendor/gitlab.com/gitlab-org/api/client-go/.golangci.yml @@ -18,19 +18,26 @@ output: linters: enable: - asciicheck + - canonicalheader - dogsled - dupword - errorlint - goconst + - godoclint - misspell + - modernize - nakedret - nolintlint - revive + - sloglint - staticcheck - testifylint - unconvert - usestdlibvars + - usetesting - whitespace + - tparallel + - paralleltest disable: - errcheck settings: @@ -38,14 +45,31 @@ linters: locale: US ignore-rules: - noteable + modernize: + disable: + - omitzero revive: enable-all-rules: false rules: + - name: comment-spacings - name: deep-exit + - name: error-strings - name: get-return + - name: identical-switch-branches + - name: increment-decrement + - name: indent-error-flow - name: redundant-import-alias + - name: struct-tag - name: time-date + - name: unnecessary-stmt + - name: unused-parameter + - name: use-errors-new - name: var-naming + arguments: + - [] + - [] + - - skip-package-name-collision-with-go-std: true + staticcheck: checks: - ST1020 @@ -65,6 +89,7 @@ linters: - error-nil - expected-actual - formatter + - go-require - len - negative-positive - nil-compare @@ -74,6 +99,10 @@ linters: http-method: false http-status-code: false time-date-month: true + usetesting: + context-background: true + context-todo: true + os-temp-dir: true # List of regexps of issue texts to exclude. exclusions: @@ -91,28 +120,11 @@ linters: - source: "// GitLab API docs:" linters: - staticcheck - - text: "var-naming: struct field PipelineId should be PipelineID" - path: commits\.go - linters: - - revive - - text: "var-naming: struct field SelectiveSyncNamespaceIds should be SelectiveSyncNamespaceIDs" - path: geo_nodes\.go - linters: - - revive - - text: "var-naming: struct field RefsUrl should be RefsURL" - path: import\.go - linters: - - revive - - text: "var-naming: struct field BitbucketServerUrl should be BitbucketServerURL" - path: import\.go - linters: - - revive - - text: "var-naming: struct field CrlUrl should be CrlURL" - path: tags\.go + - path: _test\.go$ + text: unused-parameter linters: - revive - - text: "var-naming: type ServicePingNonSqlMetrics should be ServicePingNonSQLMetrics" - path: usage_data\.go + - path: ^testing/ linters: - revive paths: diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/.releaserc.json b/vendor/gitlab.com/gitlab-org/api/client-go/.releaserc.json index 0e6170194..ab9aa899c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/.releaserc.json +++ b/vendor/gitlab.com/gitlab-org/api/client-go/.releaserc.json @@ -1,24 +1,7 @@ { "branches": ["main"], "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "angular", - "releaseRules": [ - {"type": "breaking", "release": "major"}, - {"type": "feat", "release": "minor"}, - {"type": "fix", "release": "patch"}, - {"type": "refactor", "release": "patch"}, - {"type": "chore", "release": "patch"}, - {"type": "docs", "release": "patch"}, - {"type": "style", "release": false}, - {"type": "test", "release": false}, - {"scope": "no-release", "release": false}, - {"scope": "deps", "release": false} - ] - } - ], + "@gitlab/semantic-release-merge-request-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/changelog", "@semantic-release/gitlab", @@ -31,4 +14,3 @@ ] ] } - diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/.tool-versions b/vendor/gitlab.com/gitlab-org/api/client-go/.tool-versions index 379a7c137..afedc36bf 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/.tool-versions +++ b/vendor/gitlab.com/gitlab-org/api/client-go/.tool-versions @@ -1,5 +1,5 @@ -golang 1.23 -golangci-lint 2.3.1 +golang 1.24 +golangci-lint 2.10.1 gofumpt 0.8.0 buf 1.55.1 -node 24.8.0 \ No newline at end of file +node 24.8.0 diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/AGENTS.md b/vendor/gitlab.com/gitlab-org/api/client-go/AGENTS.md new file mode 100644 index 000000000..26c890968 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/AGENTS.md @@ -0,0 +1,401 @@ +# AI Agent Guidelines for GitLab client-go + +This document provides comprehensive guidelines for AI agents working with the GitLab client-go repository. It covers development practices, testing requirements, code formatting, API alignment, and code generation procedures. + +## Repository Overview + +The GitLab client-go is a Go client library for the GitLab API, enabling Go programs to interact with GitLab in a simple and uniform way. The repository follows strict Go best practices and maintains close alignment with GitLab's official API documentation. + +## Development Workflow + +### Prerequisites + +When asked to modify code, read CONTRIBUTING.md and README.md for examples and formatting instructions. Where the +instructions in CONTRIBUTING.md and README.md conflict with information in AGENTS.md, prefer the instructions in +CONTRIBUTING.md and README.md over the instructions in AGENTS.md + +When asked to perform analysis on the codebase instead of changing code, skipping the read of CONTRIBUTING.md and README.md +is allowed and preferred, since understanding contributing guidelines is not required to perform analysis. + +### Required Tools + +- **Go** - Use the version specified in go.mod +- **gofumpt** - Code formatter +- **golangci-lint** - Linting tool +- **buf** - Protocol buffer tools for code generation +- **gomock** - Mock generation + +### Running Tests + +```bash +# Run all tests with race detection +mise exec -- make test + +# Run the complete reviewable process (includes tests) +mise exec -- make reviewable +``` + +### Test Patterns + +- Tests are parallelized using `t.Parallel()` +- Mock HTTP handlers are used for API testing +- Test data is stored in `testdata/` directory +- Each service method should have corresponding test coverage + - **CRITICAL** - When fixing bugs or creating new features, ensure new test scenarios are added to cover the new logic. +- When writing a test, write Gherkin comments in-line with the test to make the tests easier to read. This means adding GIVEN/WHEN/THEN comments in tests. +- All tests use the `testing` package with `testify/assert` + +Do not use `reflect.DeepEqual` in tests, use testify instead. + +```go +// This is an example of the incorrect test setup +want := &MyStruct{ + MyField: "Meow Kitty" +} +if !reflect.DeepEqual(want, otherStruct) { + t.Errorf("MyStruct returned %+v, want %+v", otherStruct, want) +} + +// Instead, use this +want := &MyStruct{ + MyField: "Meow Kitty" +} +assert.Equal(t, want, otherStruct) +``` + +### Test Structure Example + +```go +func TestGetUser(t *testing.T) { + t.Parallel() + mux, client := setup(t) + + path := "/api/v4/users/1" + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + mustWriteHTTPResponse(t, w, "testdata/get_user.json") + }) + + user, _, err := client.Users.GetUser(1, GetUsersOptions{}) + assert.NoError(t, err) + // ... assertions +} +``` + +## Code Formatting and Linting + +### Formatting + +The project uses `gofumpt` for code formatting: + +```bash +# Format all Go files +mise exec -- make fmt +``` + +**Formatting Rules:** +- Line width for comments: < 80 characters +- Line width for code: < 100 characters (where sensible) +- Use `gofumpt` for consistent formatting +- Follow Go best practices + +### Linting + +```bash +# Run all linters +mise exec -- make lint +``` + +**Linting Configuration:** +- Uses `golangci-lint` with custom configuration in `.golangci.yml` +- Enabled linters: asciicheck, dogsled, dupword, errorlint, goconst, misspell, + nakedret, nolintlint, revive, staticcheck, testifylint, unconvert, + usestdlibvars, whitespace +- Excludes generated files and examples directory + +## Mock generation + +This repository uses gomock to generate testing structs, which are in the `testing/` folder. These need to be kept up-to-date with function signatures to that the Service implementations match the interfaces that have generated mocks. + +### Available Generation Commands + +```bash +# Generate all code (protobuf, mocks, testing client) +mise exec -- make generate + +# Clean generated files +mise exec -- make clean +``` + +### Generation Scripts + +1. **`scripts/generate_testing_client.sh`** - Generates testing client with mocks +2. **`scripts/generate_mock_api.sh`** - Generates mock interfaces for all services +3. **`scripts/generate_service_interface_map.sh`** - Generates service interface mapping + +### When to Regenerate + +- After adding new service interfaces +- After modifying existing interfaces +- Before committing changes +- When mock generation fails + +## Function Comment Formatting + +### Required Comment Structure + +Every public function, type, and method must have properly formatted comments: + +```go +// FunctionName performs a specific action with the given parameters. +// +// GitLab API docs: https://docs.gitlab.com/api/endpoint/ +func (s *ServiceName) FunctionName(param Type, opt *Options, options ...RequestOptionFunc) (*ReturnType, *Response, error) { + // Implementation +} +``` + +### Comment Guidelines + +1. **Function Comments:** + - Start with function name (no "The" or "This function") + - Use present tense ("performs", "returns", "creates") + - Keep under 80 characters per line + - Include GitLab API documentation link + +2. **Type Comments:** + - Start with type name + - Describe the purpose and usage + - Include GitLab API documentation link + +3. **Struct Field Comments:** + - Use `json:"field_name"` tags + - Include `url:"field_name,omitempty"` for query parameters + - Document complex fields + +### GitLab API Documentation Alignment + +**CRITICAL: All code must align with GitLab's official API documentation.** + +#### API Documentation References + +Every function must reference the corresponding GitLab API documentation: + +```go +// GitLab API docs: https://docs.gitlab.com/api/users/ +// GitLab API docs: https://docs.gitlab.com/api/projects/#list-all-projects +// GitLab API docs: https://docs.gitlab.com/api/commits/#get-the-diff-of-a-commit +``` + +#### Field Ordering + +Struct fields and methods should be ordered to match the GitLab API documentation: + +```go +type CreateProjectOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` + // ... other fields in API documentation order +} +``` + +#### Parameter Validation + +- Use `any` type for project/group IDs to support both int64 and string. +- Implement proper parameter parsing with `parseID()` function +- Validate required parameters before making API calls + +## Code Structure and Patterns + +### Service Structure + +Each GitLab API service follows this pattern: + +```go +type ( + ServiceNameInterface interface { + MethodName(opt *MethodOptions, options ...RequestOptionFunc) (*ReturnType, *Response, error) + // ... other methods + } + + // ServiceName handles communication with the service related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/service/ + ServiceName struct { + client *Client + } +) + +var _ ServiceNameInterface = (*ServiceName)(nil) +``` + +### Request Options Pattern + +All API methods should accept `options ...RequestOptionFunc`: + +```go +func (s *ServiceName) MethodName(opt *MethodOptions, options ...RequestOptionFunc) (*ReturnType, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + + u := fmt.Sprintf("projects/%s/endpoint", PathEscape(project)) + + req, err := s.client.NewRequest(http.MethodGet, u, opt, options) + if err != nil { + return nil, nil, err + } + + var result *ReturnType + resp, err := s.client.Do(req, &result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} +``` + +### Error Handling + +- Always return `(*Type, *Response, error)` tuple +- Use `PathEscape()` for URL path parameters +- Use `url.PathEscape()` for query parameters +- Handle `parseID()` errors for project/group IDs + +### Type Usage + +- Do not use `interface{}`, use the `any` alias instead! +- Do not use `int`, use `int64` instead! This applies to both slices and maps. + +## Pre-commit Checklist + +**CRITICAL: Tests MUST be run for every build or code modification.** +**CRITICAL: Linting MUST pass for every build or code modification.** +**CRITICAL: Mock generation should be run any time function signatures change** + +You can accomplish all three of these by running `mise exec -- make reviewable`, which will do: + +1. `mise exec -- make setup` - Install dependencies +2. `mise exec -- make generate` - Generate required code +3. `mise exec -- make fmt` - Format code +4. `mise exec -- make lint` - Run linters +5. `mise exec -- make test` - Run tests + +## Code Generation Guidelines + +### When Adding New Services + +1. Create the service file (e.g., `new_service.go`) +2. Define the interface and struct following the established pattern +3. Implement all methods with proper error handling +4. Add comprehensive tests in `new_service_test.go` +5. Run `mise exec -- make generate` to update mocks and testing client +6. Ensure all tests pass with `mise exec -- make test` + +### Mock Generation + +The repository uses `gomock` for generating mocks: + +```bash +# Generate mocks for all interfaces +mise exec -- make generate +``` + +Mocks are automatically generated in the `testing/` package and should not be manually edited. + +## File Organization + +### Service Files + +- One service per file (e.g., `users.go`, `projects.go`) +- Corresponding test file (e.g., `users_test.go`) +- Interface definition at the top of the file +- Service struct and implementation below + +### Generated Files + +- `testing/*_mock.go` - Generated mock files +- `testing/*_generated.go` - Generated testing client files +- `*_generated_test.go` - Generated test files + +**Never edit generated files manually.** + +## Common Patterns and Best Practices + +### Pointer Usage + +Use pointers for optional fields in structs: + +```go +type CreateUserOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + Email *string `url:"email,omitempty" json:"email,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` +} +``` + +### Time Handling + +Use `*time.Time` for time fields and `ISOTime` for custom time types that only support year-month-day formatting: + +```go +type User struct { + CreatedAt *time.Time `json:"created_at"` + LastActivityOn *ISOTime `json:"last_activity_on"` +} +``` + +### Response Handling + +Always return the full response for pagination and metadata: + +```go +users, resp, err := client.Users.ListUsers(&gitlab.ListUsersOptions{}) +if err != nil { + return err +} + +// Access pagination info +fmt.Printf("Total pages: %d\n", resp.TotalPages) +``` + +## Troubleshooting + +### Common Issues + +1. **Tests failing after changes:** + - Run `mise exec -- make generate` to update mocks + - Check for linting errors with `mise exec -- make lint` + - Ensure all imports are correct + +2. **Linting errors:** + - Run `mise exec -- make fmt` to fix formatting issues + - Check `.golangci.yml` for specific rule configurations + - Address any static analysis warnings + +3. **Generation failures:** + - Ensure all interfaces are properly defined + - Check that service files follow the correct pattern + - Verify that all required tools are installed + +### Getting Help + +- Check existing issues in the [issue tracker](https://gitlab.com/gitlab-org/api/client-go/-/issues) +- Review the [contributing guide](CONTRIBUTING.md) +- Examine similar implementations in the codebase +- Refer to [GitLab API documentation](https://docs.gitlab.com/ee/api/) + +## Summary + +When working with this repository: + +1. **Always run tests** - `mise exec -- make test` is mandatory +2. **Follow formatting rules** - Use `gofumpt` and respect line limits +3. **Align with GitLab API docs** - Every function must reference official documentation +4. **Generate code when needed** - Run `mise exec -- make generate` after interface changes +5. **Use proper commenting** - Include GitLab API links and follow format guidelines +6. **Maintain consistency** - Follow established patterns and conventions diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/CHANGELOG.md b/vendor/gitlab.com/gitlab-org/api/client-go/CHANGELOG.md index eb19da327..123f38d42 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/CHANGELOG.md +++ b/vendor/gitlab.com/gitlab-org/api/client-go/CHANGELOG.md @@ -1,3 +1,1411 @@ +## 1.46.0 + +### ๐Ÿš€ Features + +- Update urls and add missing ([!2785](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2785)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + + + +# [1.46.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.45.0...v1.46.0) (2026-03-01) + +## 1.45.0 + +### ๐Ÿš€ Features + +- Add LockMembershipsToSAML support to Application Settings ([!2791](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2791)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + +### ๐Ÿ”„ Other Changes + +- test(integration): Use epic IID instead of ID in `DeleteEpic` cleanup. ([!2794](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2794)) by [Florian Forster](https://gitlab.com/fforster) + + + +# [1.45.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.44.0...v1.45.0) (2026-02-27) + + +### Bug Fixes + +* **test:** Use epic IID instead of ID in `DeleteEpic` cleanup. ([49dea05](https://gitlab.com/gitlab-org/api/client-go/commit/49dea0587894cd75d5962e69080974fccedde406)) + +## 1.44.0 + +### ๐Ÿš€ Features + +- Implement runner controller instance-level runner scope support ([!2765](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2765)) by [Timo Furrer](https://gitlab.com/timofurrer) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module github.com/graph-gophers/graphql-go to v1.9.0 ([!2789](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2789)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.44.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.43.0...v1.44.0) (2026-02-26) + +## 1.43.0 + +### ๐Ÿš€ Features + +- feat(pagination): Add `ScanAndCollectN` to collect at most _n_ results. ([!2788](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2788)) by [Florian Forster](https://gitlab.com/fforster) + + + +# [1.43.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.42.0...v1.43.0) (2026-02-25) + + +### Features + +* **pagination:** Add `ScanAndCollectN` to collect at most _n_ results. ([f821c08](https://gitlab.com/gitlab-org/api/client-go/commit/f821c08c2a460755a0ae4db08fa468b54cbb4be1)) + +## 1.42.0 + +### ๐Ÿš€ Features + +- feat: Add public_email to CreateUserOptions ([!2787](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2787)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) + + + +# [1.42.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.41.1...v1.42.0) (2026-02-24) + + +### Features + +* Add public_email to CreateUserOptions ([ab1ec31](https://gitlab.com/gitlab-org/api/client-go/commit/ab1ec3131687de457c8518c60150c254cc56fd83)) + +## 1.41.1 + +### ๐Ÿ› Bug Fixes + +- fix: Fixed a set of endpoints where inputs were escaped and should not be escaped ([!2772](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2772)) by [kilianpaquier](https://gitlab.com/u.kilianpaquier) + +### ๐Ÿ”„ Other Changes + +- Add `primary_domain` and `pages_primary_domain` to Pages structs ([!2786](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2786)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + + + +## [1.41.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.41.0...v1.41.1) (2026-02-24) + + +### Bug Fixes + +* Fixed a set of endpoints where inputs were escaped and should not be escaped ([d6d7b17](https://gitlab.com/gitlab-org/api/client-go/commit/d6d7b17f0c4d63c2613ae2aed2ea2901e87c7b8b)) + +## 1.41.0 + +### ๐Ÿš€ Features + +- feat: Add missing event toggles to Group Slack integration ([!2784](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2784)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/go/protovalidate to v1.1.3 ([!2783](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2783)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.41.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.40.1...v1.41.0) (2026-02-22) + + +### Features + +* Add missing event toggles to Group Slack integration ([a4e84a2](https://gitlab.com/gitlab-org/api/client-go/commit/a4e84a27f22083a40f351591c5a851ba19b6a7dc)) + +## 1.40.1 + +### ๐Ÿ› Bug Fixes + +- Add missing group API parameters to Go SDK structs ([!2764](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2764)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + + + +## [1.40.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.40.0...v1.40.1) (2026-02-21) + +## 1.40.0 + +### ๐Ÿš€ Features + +- feat: Add visibility option to listgroupoptions ([!2775](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2775)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) +- Add missing parameters to MergeRequestDiff struct ([!2767](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2767)) by [Alekhin Sergey](https://gitlab.com/a.sergey) + +### ๐Ÿ”„ Other Changes + +- chore(oauth): use go:embed to extract the html ([!2740](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2740)) by [Tomas Vik](https://gitlab.com/viktomas) + + + +# [1.40.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.39.0...v1.40.0) (2026-02-21) + + +### Features + +* Add visibility option to listgroupoptions ([ca08a62](https://gitlab.com/gitlab-org/api/client-go/commit/ca08a62935f8d946dc52e35fcef5528c5950c104)) + +## 1.39.0 + +### ๐Ÿš€ Features + +- feat: Add hide backlog and closed list properties to IssueBoards ([!2780](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2780)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) +- feat(groups): Add provider to AddGroupSAMLLinkOptions ([!2776](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2776)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) + + + +# [1.39.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.38.0...v1.39.0) (2026-02-19) + + +### Features + +* Add hide backlog and closed list properties to IssueBoards ([a66984e](https://gitlab.com/gitlab-org/api/client-go/commit/a66984ee5934bc55b9618f83d16272b6a4ebf94f)) +* **groups:** Add provider to AddGroupSAMLLinkOptions ([bb97c7f](https://gitlab.com/gitlab-org/api/client-go/commit/bb97c7f334ab6cab3eb7153457f14a71b9ff0c55)) + +## 1.38.0 + +### ๐Ÿš€ Features + +- feat(events): Add missing parameters for label operations and update documentation links ([!2781](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2781)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) +- feat(labels): add missing params and edit links ([!2778](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2778)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + +### ๐Ÿ”„ Other Changes + +- docs: Fix broken GitLab docs anchors for alert_management API ([!2777](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2777)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) +- docs: Fix broken documentation links in attestations.go ([!2779](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2779)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) + + + +# [1.38.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.37.0...v1.38.0) (2026-02-19) + + +### Features + +* **events:** Add missing parameters for label operations and update documentation links ([11b9f08](https://gitlab.com/gitlab-org/api/client-go/commit/11b9f08b37a4c2ada9413259282f163f28b94051)) +* **labels:** add missing params and edit links ([ec1b92b](https://gitlab.com/gitlab-org/api/client-go/commit/ec1b92bff403c10446ab1ff6566a3a638871bb7e)) + +## 1.37.0 + +### ๐Ÿš€ Features + +- Support system & system_action fields for merge event attributes ([!2737](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2737)) by [Artem Mikheev](https://gitlab.com/renbou) + +### ๐Ÿ”„ Other Changes + +- Update links of geo_sites.go ([!2782](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2782)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) +- chore(deps): update dependency golangci-lint to v2.10.1 ([!2770](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2770)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update golangci/golangci-lint docker tag to v2.10.1 ([!2771](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2771)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update golangci/golangci-lint docker tag to v2.10.0 ([!2769](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2769)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update dependency golangci-lint to v2.10.0 ([!2768](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2768)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.37.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.36.0...v1.37.0) (2026-02-19) + +## 1.36.0 + +### ๐Ÿš€ Features + +- feat: add support for google chat APIs ([!2766](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2766)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/go/protovalidate to v1.1.2 ([!2757](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2757)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.36.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.35.0...v1.36.0) (2026-02-17) + + +### Features + +* add support for google chat APIs ([81e58cb](https://gitlab.com/gitlab-org/api/client-go/commit/81e58cbc5296f1ed7651498de367ee42f1a46b1f)) + +## 1.35.0 + +### ๐Ÿš€ Features + +- feat(groups): add code_owner_approval_required in a group's default_branch_protection_defaults ([!2725](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2725)) by [Preethi Atchudan](https://gitlab.com/preethiatchudan) + +### ๐Ÿ› Bug Fixes + +- fix(integration): Add missing json tags to ms teams struct ([!2703](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2703)) by [aishahsofea](https://gitlab.com/aishahsofea) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to v1.36.11-20260209202127-80ab13bee0bf.1 ([!2749](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2749)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update node docker tag to v25 ([!2762](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2762)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.35.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.34.0...v1.35.0) (2026-02-16) + + +### Bug Fixes + +* **integration:** Add missing json tags to ms teams struct ([dafd6fd](https://gitlab.com/gitlab-org/api/client-go/commit/dafd6fd9937246278d151e0858aa6cd2a0e8343a)) + +## 1.34.0 + +### ๐Ÿš€ Features + +- feat(workitems): Add an initial "Work Items" service with "Get" and "List" methods. ([!2719](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2719)) by [Florian Forster](https://gitlab.com/fforster) + +### ๐Ÿ”„ Other Changes + +- refactor: migrate to math/rand/v2 ([!2759](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2759)) by [Ville Skyttรค](https://gitlab.com/scop) + + + +# [1.34.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.33.0...v1.34.0) (2026-02-13) + + +### Bug Fixes + +* **workitems:** Use `int64` for global work item IDs. ([f04e3d0](https://gitlab.com/gitlab-org/api/client-go/commit/f04e3d08a0e73f535f8049bab43b25753f62cbc0)) + + +### Features + +* **request_options:** Add boolean return value to `WithNext`. ([1cd1e1e](https://gitlab.com/gitlab-org/api/client-go/commit/1cd1e1e5ca3ad9c330ada3cbac4f48f22eab9e92)) +* **workitems:** Add comprehensive filtering to `ListWorkItemsOptions` ([052a897](https://gitlab.com/gitlab-org/api/client-go/commit/052a897891791acba55afb2fdc5e686ca14ad1df)) +* **workitems:** Add pagination support to `ListWorkItems`. ([cfdf5ee](https://gitlab.com/gitlab-org/api/client-go/commit/cfdf5ee61077951a6504b08dfe27033e9bccec5a)) +* **workitems:** Add WorkItems service with Get methods ([00925c2](https://gitlab.com/gitlab-org/api/client-go/commit/00925c26114c6a1fb2ad9758ce2ac8658e087f01)), closes [gitlab-org/api/client-go#2213](https://gitlab.com/gitlab-org/api/client-go/issues/2213) +* **workitems:** Implement the `ListWorkItems` method. ([4f8a709](https://gitlab.com/gitlab-org/api/client-go/commit/4f8a7092a23298e3de951564cd0c46a8481c28d7)) + +## 1.33.0 + +### ๐Ÿš€ Features + +- Support unauthenticated clients via Unauthenticated auth source ([!2761](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2761)) by [Timo Furrer](https://gitlab.com/timofurrer) + + + +# [1.33.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.32.0...v1.33.0) (2026-02-13) + +## 1.32.0 + +### ๐Ÿš€ Features + +- Implement endpoints for runner controller scopes ([!2758](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2758)) by [Timo Furrer](https://gitlab.com/timofurrer) + +### ๐Ÿ”„ Other Changes + +- test(namespaces): Address test feedback to simplify the test ([!2744](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2744)) by [Patrick Rice](https://gitlab.com/PatrickRice) +- chore(deps): update golangci/golangci-lint docker tag to v2.9.0 ([!2755](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2755)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update dependency golangci-lint to v2.9.0 ([!2754](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2754)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.32.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.31.0...v1.32.0) (2026-02-13) + +## 1.31.0 + +### ๐Ÿš€ Features + +- Add missing fields to emoji and milestone event types ([!2704](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2704)) by [Huijie Shi](https://gitlab.com/lcdlyxrqy) + + + +# [1.31.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.30.0...v1.31.0) (2026-02-11) + +## 1.30.0 + +### ๐Ÿš€ Features + +- Add missing query params to ListGroupsOptions ([!2726](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2726)) by [Mohamed Mongy](https://gitlab.com/mohamedmongy96) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/go/protovalidate to v1.1.1 ([!2750](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2750)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- docs(no-release): update url for community fork ([!2748](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2748)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [1.30.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.29.0...v1.30.0) (2026-02-10) + +## 1.29.0 + +### ๐Ÿš€ Features + +- Update runner controllers to match latest state ([!2747](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2747)) by [Timo Furrer](https://gitlab.com/timofurrer) + +### ๐Ÿ”„ Other Changes + +- chore(deps): migrate from gopkg.in/yaml.v3 to go.yaml.in/yaml/v3 ([!2639](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2639)) by [Ville Skyttรค](https://gitlab.com/scop) + + + +# [1.29.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.28.1...v1.29.0) (2026-02-09) + +## 1.28.1 + +### ๐Ÿ› Bug Fixes + +- Fix error where GetNamespace double escaped URL-encoded projects ([!2743](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2743)) by [Patrick Rice](https://gitlab.com/PatrickRice) + +### ๐Ÿ”„ Other Changes + +- refactor: moved comments to interface ([!2716](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2716)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +## [1.28.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.28.0...v1.28.1) (2026-02-06) + +## 1.28.0 + +### ๐Ÿš€ Features + +- Add `destroy` attribute for pipeline schedule inputs ([!2702](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2702)) by [long nguyen huy](https://gitlab.com/n.h.long.9697) + +### ๐Ÿ”„ Other Changes + +- Migrate bytes endpoints to new `do` pattern ([!2738](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2738)) by [Timo Furrer](https://gitlab.com/timofurrer) +- docs(users): document the `Locked` and `State` fields ([!2741](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2741)) by [Florian Forster](https://gitlab.com/fforster) +- ci: migrate to Danger from `common-ci-tasks` ([!2742](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2742)) by [Florian Forster](https://gitlab.com/fforster) +- chore(oauth): improve the look of the OAuth confirmation page ([!2739](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2739)) by [Tomas Vik](https://gitlab.com/viktomas) + + + +# [1.28.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.27.0...v1.28.0) (2026-02-05) + +## 1.27.0 + +### ๐Ÿš€ Features + +- Trim leading `@` in user ids in `do()` requests paths ([!2736](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2736)) by [Timo Furrer](https://gitlab.com/timofurrer) + +### ๐Ÿ”„ Other Changes + +- Migrate endpoints with special status code handling to new `do` pattern ([!2733](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2733)) by [Timo Furrer](https://gitlab.com/timofurrer) +- Support file uploads in `do()` request handler ([!2732](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2732)) by [Timo Furrer](https://gitlab.com/timofurrer) +- Migrate more endpoints to the `do()` pattern ([!2731](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2731)) by [Timo Furrer](https://gitlab.com/timofurrer) +- Revert "refactor(http): preserve response body without copying in multiple services" ([!2730](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2730)) by [Timo Furrer](https://gitlab.com/timofurrer) +- chore(deps): update docker docker tag to v29.2.1 ([!2729](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2729)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.27.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.26.0...v1.27.0) (2026-02-04) + +## 1.26.0 + +### ๐Ÿš€ Features + +- Add slack integration support ([!2692](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2692)) by [Hamza Hassanain](https://gitlab.com/HamzaHassanain) + +### ๐Ÿ”„ Other Changes + +- refactor(no-release): fix minor revive issues ([!2711](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2711)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [1.26.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.25.0...v1.26.0) (2026-02-03) + +## 1.25.0 + +### ๐Ÿš€ Features + +- feat(hooks): Add webexintegration ([!2707](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2707)) by [Preethi Atchudan](https://gitlab.com/preethiatchudan) + +### ๐Ÿ”„ Other Changes + +- fix: Fix broken GitLab docs anchors for Wikis API ([!2723](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2723)) by [Mohamed Othman](https://gitlab.com/mohamed.othman27) +- refactor: moved comments to interface 7 ([!2715](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2715)) by [Zubeen](https://gitlab.com/syedzubeen) +- chore(deps): update module github.com/google/cel-go to v0.27.0 ([!2721](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2721)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- refactor: moved comments to interface 1 ([!2706](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2706)) by [Zubeen](https://gitlab.com/syedzubeen) +- Refactor low complexity endpoints to use new `do` request function ([!2718](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2718)) by [Timo Furrer](https://gitlab.com/timofurrer) +- Add some additional test coverage for functions before migrating to `do` ([!2720](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2720)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +# [1.25.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.24.0...v1.25.0) (2026-02-01) + + +### Bug Fixes + +* Fix broken GitLab docs anchors for Wikis API ([bdbb5c0](https://gitlab.com/gitlab-org/api/client-go/commit/bdbb5c0e93847846f6f786c93d649bec18db38e4)) + + +### Features + +* **hooks:** Add webexintegration ([857ac6a](https://gitlab.com/gitlab-org/api/client-go/commit/857ac6a82ff63a65ae4df221cf8347fed8946f53)) + +## 1.24.0 + +### ๐Ÿš€ Features + +- Add assignee_id to issues api ([!2673](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2673)) by [David Schneider](https://gitlab.com/dvob) + + + +# [1.24.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.23.0...v1.24.0) (2026-01-29) + +## 1.23.0 + +### ๐Ÿš€ Features + +- feat: add group protected branches service ([!2685](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2685)) by [Prakash Divy](https://gitlab.com/prakashdivyy) + +### ๐Ÿ”„ Other Changes + +- chore(no-release): refactor to slog.DiscardHandler ([!2710](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2710)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [1.23.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.22.1...v1.23.0) (2026-01-28) + + +### Features + +* add group protected branches service ([c7ffe6f](https://gitlab.com/gitlab-org/api/client-go/commit/c7ffe6ff7bc12996ce27df767a706a253a3ce00b)) + +## 1.22.1 + +### ๐Ÿ› Bug Fixes + +- fix: Type Mismatch in UpdateSettingsOptions for SentryEnabled ([!2690](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2690)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ”„ Other Changes + +- fix: URL tags for throttle protected path settings in UpdateSettingsOptions ([!2705](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2705)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: Refactor tests to use testify assertions 7 ([!2700](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2700)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: Refactor tests to use testify assertions 4 ([!2696](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2696)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: Refactor tests to use testify assertions 3 ([!2695](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2695)) by [Zubeen](https://gitlab.com/syedzubeen) +- test(no-release): Refactor tests to use testify assertions 2 ([!2694](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2694)) by [Zubeen](https://gitlab.com/syedzubeen) +- test(no-release): Refactor tests to use testify assertions ([!2693](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2693)) by [Zubeen](https://gitlab.com/syedzubeen) +- test(no-release): Refactor tests to use testify assertions 6 ([!2699](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2699)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +## [1.22.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.22.0...v1.22.1) (2026-01-28) + + +### Bug Fixes + +* Type Mismatch in UpdateSettingsOptions for SentryEnabled ([c2d3ca9](https://gitlab.com/gitlab-org/api/client-go/commit/c2d3ca98450719f615a951930153ad9fc2585b19)) +* URL tags for throttle protected path settings in UpdateSettingsOptions ([a4a525d](https://gitlab.com/gitlab-org/api/client-go/commit/a4a525dce32ba6aa80f45b48fbc0261e59cdabd3)) + +## 1.22.0 + +### ๐Ÿš€ Features + +- feat(project_mirror): add ForceSyncProjectMirror ([!2683](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2683)) by [Prakash Divy](https://gitlab.com/prakashdivyy) + +### ๐Ÿ”„ Other Changes + +- test: Refactor tests to use testify assertions 5 ([!2697](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2697)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +# [1.22.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.21.0...v1.22.0) (2026-01-28) + + +### Features + +* **project_mirror:** add ForceSyncProjectMirror ([b13fcb7](https://gitlab.com/gitlab-org/api/client-go/commit/b13fcb79e6ffb454dc9fd7e332bde90c79a62376)) + +## 1.21.0 + +### ๐Ÿš€ Features + +- feat(settings): Add AnonymousSearchesAllowed field support ([!2678](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2678)) by [Seif Hatem](https://gitlab.com/seif-hatem) + +### ๐Ÿ”„ Other Changes + +- feat: improve URL validation and error handling in client initialization ([!2656](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2656)) by [Amer Khaled](https://gitlab.com/amrkhald777) + + + +# [1.21.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.20.0...v1.21.0) (2026-01-27) + + +### Features + +* improve URL validation and error handling in client initialization ([9417155](https://gitlab.com/gitlab-org/api/client-go/commit/9417155f9c8a5d7c044d052e61d8da5c91bbe57d)) +* **settings:** Add AnonymousSearchesAllowed field support ([7185888](https://gitlab.com/gitlab-org/api/client-go/commit/7185888208173e18216ecb353fdfebe91423f0c4)) + +## 1.20.0 + +### ๐Ÿš€ Features + +- feat: update events ([!2689](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2689)) by [Huijie Shi](https://gitlab.com/lcdlyxrqy) + +### ๐Ÿ”„ Other Changes + +- chore(no-release): remove redundant build tag ([!2701](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2701)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- chore(deps): update docker docker tag to v29.2.0 ([!2698](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2698)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.20.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.19.0...v1.20.0) (2026-01-27) + + +### Features + +* update events ([46ba91c](https://gitlab.com/gitlab-org/api/client-go/commit/46ba91cabfe7c13cf4f80738d48ca60b810f520a)) + +## 1.19.0 + +### ๐Ÿš€ Features + +- feat(integrations): Add Chat & Notify integrations ([!2691](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2691)) by [Hamza Hassanain](https://gitlab.com/HamzaHassanain) + +### ๐Ÿ”„ Other Changes + +- refactor: use do function for requests ([!2674](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2674)) by [Timo Furrer](https://gitlab.com/timofurrer) +- chore(docs): Update adding API support guide for new coding patterns ([!2688](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2688)) by [Heidi Berry](https://gitlab.com/heidi.berry) + + + +# [1.19.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.18.0...v1.19.0) (2026-01-26) + + +### Features + +* **integrations:** Add Chat & Notify integrations ([cc692ed](https://gitlab.com/gitlab-org/api/client-go/commit/cc692edd6d8dfed55fd411559af7e53b55d4e2dd)) +* **mocks:** add streaming methods for various services ([889b407](https://gitlab.com/gitlab-org/api/client-go/commit/889b407e48432b32b4c1589102ceed6fadb857db)) + +## 1.18.0 + +### ๐Ÿš€ Features + +- feat(settings): Added support for inactive_resource_access_tokens_delete_after_days to the... ([!2686](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2686)) by [Preethi Atchudan](https://gitlab.com/preethiatchudan) + +### ๐Ÿ”„ Other Changes + +- Add missing tests for refactored functions ([!2676](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2676)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +# [1.18.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.17.0...v1.18.0) (2026-01-25) + + +### Features + +* **settings:** Added support for inactive_resource_access_tokens_delete_after_days to the... ([52b60c3](https://gitlab.com/gitlab-org/api/client-go/commit/52b60c3345ef56cc18ae7e8e1e2dd7c9f7f71344)) + +## 1.17.0 + +### ๐Ÿš€ Features + +- Add support for Group Mattermost integrations ([!2675](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2675)) by [Hamza Hassanain](https://gitlab.com/HamzaHassanain) + + + +# [1.17.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.16.0...v1.17.0) (2026-01-23) + +## 1.16.0 + +### ๐Ÿš€ Features + +- Add environment, deployed_after, and deployed_before params to merge requests options struct ([!2672](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2672)) by [Filip Aleksic](https://gitlab.com/faleksic) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module golang.org/x/oauth2 to v0.34.0 ([!2640](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2640)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.16.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.15.0...v1.16.0) (2026-01-20) + +## 1.15.0 + +### ๐Ÿš€ Features + +- Add ExpiresAt field to ProjectSharedWithGroup struct ([!2671](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2671)) by [cindy](https://gitlab.com/wscix) + +### ๐Ÿ”„ Other Changes + +- feat: convert examples to testable examples for pkg.go.dev ([!2655](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2655)) by [Amer Khaled](https://gitlab.com/amrkhald777) +- refactor(no-release): enable usetesting linter ([!2664](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2664)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- chore(deps): update docker docker tag to v29.1.5 ([!2665](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2665)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- Draft: Users: Fix GetUsersOptions naming inconsistency ([!2667](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2667)) by [Seif Hatem](https://gitlab.com/seif-hatem) + + + +# [1.15.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.14.0...v1.15.0) (2026-01-20) + + +### Bug Fixes + +* Deprecate incorrect fields returned in response for Emails on Push integration ([71d747d](https://gitlab.com/gitlab-org/api/client-go/commit/71d747da9a297451911b0c4eb4850632a588e3e8)) + + +### Features + +* convert examples to testable examples for pkg.go.dev ([fee39f1](https://gitlab.com/gitlab-org/api/client-go/commit/fee39f1f21b264765bbbed80ba23265bd3f633a9)) +* **issue_links:** Add ID field to IssueLink struct ([8f813a8](https://gitlab.com/gitlab-org/api/client-go/commit/8f813a8a2e73c41bc81403aceb82d7d94e9ff684)) + +## 1.14.0 + +### ๐Ÿš€ Features + +- feat(hooks): Add project hook support for vulnerability events and branch filter strategy ([!2658](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2658)) by [Heidi Berry](https://gitlab.com/heidi.berry) +- Add max_artifacts_size parameter to groups and projects ([!2652](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2652)) by [Betty Godier](https://gitlab.com/betty-godier) + + + +# [1.14.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.13.0...v1.14.0) (2026-01-13) + + +### Features + +* **hooks:** Add project hook support for vulnerability events and branch filter strategy ([4f6d252](https://gitlab.com/gitlab-org/api/client-go/commit/4f6d252a47411602ac6757400e6b5479d807cdb8)) + +## 1.13.0 + +### ๐Ÿš€ Features + +- feat(groups): add Active parameter to ListGroupProjects ([!2657](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2657)) by [Kai Armstrong](https://gitlab.com/phikai) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update docker docker tag to v29.1.4 ([!2651](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2651)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.13.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.12.0...v1.13.0) (2026-01-12) + + +### Features + +* **groups:** add Active parameter to ListGroupProjects ([dec511a](https://gitlab.com/gitlab-org/api/client-go/commit/dec511a199b0adb7ba87f5a02a50651049b68b71)) + +## 1.12.0 + +### ๐Ÿš€ Features + +- feat: add EmojiEvents field support to Project Webhooks ([!2653](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2653)) by [Yugan](https://gitlab.com/yugannkt) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update dependency golangci-lint to v2.8.0 ([!2650](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2650)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- refactor(no-release): use errors.New instead of fmt.Errorf ([!2644](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2644)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [1.12.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.11.0...v1.12.0) (2026-01-11) + + +### Features + +* add EmojiEvents field support to Project Webhooks ([2bcfa1f](https://gitlab.com/gitlab-org/api/client-go/commit/2bcfa1fd77756a3ccdb2bcf685736ee839b745be)) + +## 1.11.0 + +### ๐Ÿš€ Features + +- feat(groups): add support for merge related settings ([!2625](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2625)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ› Bug Fixes + +- fix(api): typo in ms teams slug ([!2643](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2643)) by [aishahsofea](https://gitlab.com/aishahsofea) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module golang.org/x/text to v0.32.0 ([!2642](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2642)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module golang.org/x/sys to v0.39.0 ([!2641](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2641)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module github.com/godbus/dbus/v5 to v5.2.2 ([!2637](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2637)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module github.com/google/go-querystring to v1.2.0 ([!2638](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2638)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.11.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.10.0...v1.11.0) (2026-01-05) + + +### Bug Fixes + +* **api:** typo in ms teams slug ([1ed6c95](https://gitlab.com/gitlab-org/api/client-go/commit/1ed6c9509b23db53c3988a2dde2f11d22c8be5f9)) + + +### Features + +* **groups:** add support for merge related settings ([cb8412f](https://gitlab.com/gitlab-org/api/client-go/commit/cb8412fc495d19ee6e44819a2f69fd213d19a199)) + +## 1.10.0 + +### ๐Ÿš€ Features + +- feat: implement Runner Controller API ([!2634](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2634)) by [Duo Developer](https://gitlab.com/duo-developer) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module github.com/godbus/dbus/v5 to v5.2.1 ([!2635](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2635)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.10.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.9.1...v1.10.0) (2025-12-19) + + +### Features + +* implement Runner Controller API ([66f19f4](https://gitlab.com/gitlab-org/api/client-go/commit/66f19f4073ce87566c7751e0987f857eeb008849)) + +## 1.9.1 + +### ๐Ÿ› Bug Fixes + +- fix: use parameters in config.NewClient and Jobs.DownloadArtifactsFile ([!2633](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2633)) by [Oleksandr Redko](https://gitlab.com/alexandear) + +### ๐Ÿ”„ Other Changes + +- test: fix TestCreateMergeRequestContextCommits failing locally ([!2631](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2631)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- Code Refactor Using Request Handlers - 8 ([!2523](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2523)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 6 ([!2521](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2521)) by [Yashesvinee V](https://gitlab.com/yashes7516) + + + +## [1.9.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.9.0...v1.9.1) (2025-12-17) + + +### Bug Fixes + +* use parameters in config.NewClient and Jobs.DownloadArtifactsFile ([28b7cd7](https://gitlab.com/gitlab-org/api/client-go/commit/28b7cd72f06777a2d3ec7772870c26565140341a)) + +## 1.9.0 + +### ๐Ÿš€ Features + +- feat(api): add support for matrix project integration ([!2630](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2630)) by [aishahsofea](https://gitlab.com/aishahsofea) + + + +# [1.9.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.8.2...v1.9.0) (2025-12-16) + + +### Features + +* **api:** add support for matrix project integration ([0a5b11b](https://gitlab.com/gitlab-org/api/client-go/commit/0a5b11b9e2e405fb0a22009d60ce38091cc96625)) + +## 1.8.2 + +### ๐Ÿ› Bug Fixes + +- fix: correct omitempty tag in VariableFilter.EnvironmentScope field ([!2629](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2629)) by [Oleksandr Redko](https://gitlab.com/alexandear) + +### ๐Ÿ”„ Other Changes + +- feat(protectedTags): add support for `deploy_key_id` to `protected_tags` ([!2624](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2624)) by [Zubeen](https://gitlab.com/syedzubeen) +- chore(deps): update docker docker tag to v29.1.3 ([!2623](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2623)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to v1.36.11-20251209175733-2a1774d88802.1 ([!2622](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2622)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module google.golang.org/protobuf to v1.36.11 ([!2621](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2621)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +## [1.8.2](https://gitlab.com/gitlab-org/api/client-go/compare/v1.8.1...v1.8.2) (2025-12-15) + + +### Bug Fixes + +* correct omitempty tag in VariableFilter.EnvironmentScope field ([c117da1](https://gitlab.com/gitlab-org/api/client-go/commit/c117da1b123251ba86271d1ce3bf9750617e344f)) + + +### Features + +* **protectedTags:** add support for `deploy_key_id` to `protected_tags` ([c0fc3db](https://gitlab.com/gitlab-org/api/client-go/commit/c0fc3db793b51bfabb0ac8bb42442e6916b9df3f)) + +## 1.8.1 + +### ๐Ÿ› Bug Fixes + +- fix(epics): handle datetime format in ISOTime UnmarshalJSON ([!2612](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2612)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/go/protovalidate to v1.1.0 ([!2619](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2619)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore: add deprecation notice for PersonalAccessTokens.RevokePersonalAccessToken ([!2615](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2615)) by [aishahsofea](https://gitlab.com/aishahsofea) +- chore(deps): update golangci/golangci-lint docker tag to v2.7.2 ([!2613](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2613)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): do not use the experimental package ([!2614](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2614)) by [Mikhail Mazurskiy](https://gitlab.com/ash2k) +- test: Replace SkipIfRunningCE with SkipIfNotLicensed ([!2616](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2616)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +## [1.8.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.8.0...v1.8.1) (2025-12-10) + + +### Bug Fixes + +* **epics:** handle datetime format in ISOTime UnmarshalJSON ([257e0ac](https://gitlab.com/gitlab-org/api/client-go/commit/257e0acd29daf887456d924c0063b52ebc2e808f)) + +## 1.8.0 + +### ๐Ÿš€ Features + +- feat(hooks): add support for all hook event types ([!2606](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2606)) by [Heidi Berry](https://gitlab.com/heidi.berry) + + + +# [1.8.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.7.0...v1.8.0) (2025-12-08) + + +### Features + +* **hooks:** add support for all hook event types ([c3c9ca2](https://gitlab.com/gitlab-org/api/client-go/commit/c3c9ca275969adffca37908d63e5c70f634d7bbe)) + +## 1.7.0 + +### ๐Ÿš€ Features + +- feat(users): Add support for a user to see only one file diff per page ([!2597](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2597)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +# [1.7.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.6.0...v1.7.0) (2025-12-06) + + +### Features + +* **users:** Add support for a user to see only one file diff per page ([e2a9e09](https://gitlab.com/gitlab-org/api/client-go/commit/e2a9e09e79e7949e0b19dcfc97e3b7b533541856)) + +## 1.6.0 + +### ๐Ÿš€ Features + +- feat: add admin compliance policy settings API ([!2610](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2610)) by [Hannes Lange](https://gitlab.com/hlange4) + +### ๐Ÿ”„ Other Changes + +- doc: fix typo ([!2603](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2603)) by [Guilhem Bonnefille](https://gitlab.com/gbonnefille) +- chore(deps): update golangci/golangci-lint docker tag to v2.7.1 ([!2611](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2611)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update docker docker tag to v29.1.2 ([!2609](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2609)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update golangci/golangci-lint docker tag to v2.7.0 ([!2608](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2608)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.6.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.5.0...v1.6.0) (2025-12-05) + + +### Features + +* add admin compliance policy settings API ([5c17773](https://gitlab.com/gitlab-org/api/client-go/commit/5c17773ca94ddece28978c7396bddcc6c65fb6a7)) + +## 1.5.0 + +### ๐Ÿš€ Features + +- feat(Project Mirrors): Add missing Mirror attributes when reading or updating Project Mirrors ([!2600](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2600)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +# [1.5.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.4.1...v1.5.0) (2025-12-03) + + +### Features + +* **Project Mirrors:** Add missing Mirror attributes when reading or updating Project Mirrors ([a49b32d](https://gitlab.com/gitlab-org/api/client-go/commit/a49b32df59aeae97247d21a83be3fab97da1bbfe)) + +## 1.4.1 + +### ๐Ÿ› Bug Fixes + +- Encode package managers as CSV in query for dependencies list ([!2604](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2604)) by [Timo Furrer](https://gitlab.com/timofurrer) + + + +## [1.4.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.4.0...v1.4.1) (2025-12-02) + +## 1.4.0 + +### ๐Ÿš€ Features + +- feat(integrations): Add attestations integrations ([!2582](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2582)) by [Sam Roque-Worcel](https://gitlab.com/sroque-worcel) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update docker docker tag to v29.1.1 ([!2602](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2602)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.4.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.3.1...v1.4.0) (2025-12-02) + + +### Features + +* **integrations:** Add attestations integrations ([4f50db4](https://gitlab.com/gitlab-org/api/client-go/commit/4f50db4acfb19212bfdfc12eb808dbc7ed8d7ad2)) + +## 1.3.1 + +### ๐Ÿ› Bug Fixes + +- fix(merge_requests): Reinstate missing request option ([!2601](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2601)) by [Heidi Berry](https://gitlab.com/heidi.berry) + + + +## [1.3.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.3.0...v1.3.1) (2025-12-01) + + +### Bug Fixes + +* **merge_requests:** Reinstate missing request option ([f5f912d](https://gitlab.com/gitlab-org/api/client-go/commit/f5f912ddc2dfb1af88de8710bde783f3f7ccd7c2)) + +## 1.3.0 + +### ๐Ÿš€ Features + +- feat(credentials): Add support for revoking group PATs, listing/deleting group SSH keys ([!2594](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2594)) by [Heidi Berry](https://gitlab.com/heidi.berry) + +### ๐Ÿ”„ Other Changes + +- refactor: moved comments to interface ([!2595](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2595)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(users): moved comments to interface ([!2596](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2596)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor: moved comments to interface ([!2599](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2599)) by [Zubeen](https://gitlab.com/syedzubeen) +- Simplify more request functions, introducing NoEscape ([!2592](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2592)) by [Timo Furrer](https://gitlab.com/timofurrer) + + + +# [1.3.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.2.0...v1.3.0) (2025-11-30) + + +### Features + +* **credentials:** Add support for revoking group PATs, listing/deleting group SSH keys ([3439f4f](https://gitlab.com/gitlab-org/api/client-go/commit/3439f4f0345b97dea0abf926ecaac9d3a7eb6769)) + +## 1.2.0 + +### ๐Ÿš€ Features + +- feat(credentials): Add support for listing all SaaS enterprise user personal access tokens ([!2593](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2593)) by [Heidi Berry](https://gitlab.com/heidi.berry) + +### ๐Ÿ”„ Other Changes + +- Code Refactor Using Request Handlers - 10 ([!2525](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2525)) by [Yashesvinee V](https://gitlab.com/yashes7516) + + + +# [1.2.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.1.0...v1.2.0) (2025-11-27) + + +### Features + +* **credentials:** Add support for listing all SaaS enterprise user personal access tokens ([3697779](https://gitlab.com/gitlab-org/api/client-go/commit/369777938e435b043e37460ff1feffedd84b7dd1)) + +## 1.1.0 + +### ๐Ÿš€ Features + +- feat(service_account): allow providing email when update a Service Account ([!2589](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2589)) by [kilianpaquier](https://gitlab.com/u.kilianpaquier) + +### ๐Ÿ”„ Other Changes + +- Bump dependencies ([!2591](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2591)) by [Timo Furrer](https://gitlab.com/timofurrer) +- chore(deps): update docker docker tag to v29 ([!2586](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2586)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [1.1.0](https://gitlab.com/gitlab-org/api/client-go/compare/v1.0.1...v1.1.0) (2025-11-26) + + +### Features + +* **service_account:** allow providing email when update a Service Account ([324d080](https://gitlab.com/gitlab-org/api/client-go/commit/324d0806a5cd8cb6ae7f68381d09cf5e2a31a0cc)) + +## 1.0.1 + +### ๐Ÿ› Bug Fixes + +- fix: fix ReviewerID() and let it accept int64 ([!2587](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2587)) by [Ilya Savitsky](https://gitlab.com/ipsavitsky234) + + + +## [1.0.1](https://gitlab.com/gitlab-org/api/client-go/compare/v1.0.0...v1.0.1) (2025-11-25) + + +### Bug Fixes + +* fix ReviewerID() and let it accept int64 ([6a6d439](https://gitlab.com/gitlab-org/api/client-go/commit/6a6d43952b70191358e7b726eff4f7f24a0f7ff6)) + +## 1.0.0 + +### ๐Ÿ’ฅ Breaking Changes + +- Release client-go 1.0 ([!2575](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2575)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +# [1.0.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.161.1...v1.0.0) (2025-11-24) + + +* Merge branch 'release-client-1.0' into 'main' ([f06b8c2](https://gitlab.com/gitlab-org/api/client-go/commit/f06b8c2cb4446e2e76a13bbc707c64e22a64d477)) + + +### Bug Fixes + +* **issues:** use AssigneeIDValue for ListProjectIssuesOptions.AssigneeID ([1dcb219](https://gitlab.com/gitlab-org/api/client-go/commit/1dcb219c343bc5b5622ff49933199c003a231bd4)) + + +### Features + +* **ListOptions:** Update ListOptions to use composition instead of aliasing ([60beef3](https://gitlab.com/gitlab-org/api/client-go/commit/60beef36d0f93a7dc66749f55d98defbc1b3fe28)) + + +### BREAKING CHANGES + +* Release 1.0 +* **ListOptions:** ListOptions implementation changed from aliasing to composition +Changelog: Improvements + +## 0.161.1 + +### ๐Ÿ› Bug Fixes + +- fix(users): Fix a bug where error parsing causes user blocking to not function properly ([!2584](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2584)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +## [0.161.1](https://gitlab.com/gitlab-org/api/client-go/compare/v0.161.0...v0.161.1) (2025-11-24) + + +### Bug Fixes + +* **users:** Fix a bug where error parsing causes user blocking to not function properly ([2ad5506](https://gitlab.com/gitlab-org/api/client-go/commit/2ad55065d624d27d1f539a3c41489989b9a0d036)) + +## 0.161.0 + +### ๐Ÿš€ Features + +- fix: return detailed API errors for BlockUser instead of generic LDAP message ([!2581](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2581)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +# [0.161.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.160.2...v0.161.0) (2025-11-24) + + +### Bug Fixes + +* return detailed API errors for BlockUser instead of generic LDAP message ([2ba9fa6](https://gitlab.com/gitlab-org/api/client-go/commit/2ba9fa6995de6cadf0dae1bf600979b73ee471ce)) + +## 0.160.2 + +### ๐Ÿ› Bug Fixes + +- Fix double escaping in paths ([!2583](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2583)) by [Timo Furrer](https://gitlab.com/timofurrer) + + + +## [0.160.2](https://gitlab.com/gitlab-org/api/client-go/compare/v0.160.1...v0.160.2) (2025-11-24) + +## 0.160.1 + +### ๐Ÿ› Bug Fixes + +- fix: update input field from "key" to "name" in pipeline schedules to prevent an API error ([!2580](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2580)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ”„ Other Changes + +- Code Refactor Using Request Handlers - 9 ([!2524](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2524)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 7 ([!2522](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2522)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 5 ([!2518](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2518)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 2 ([!2515](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2515)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 4 ([!2517](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2517)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Code Refactor Using Request Handlers - 3 ([!2516](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2516)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- chore(deps): update module github.com/godbus/dbus/v5 to v5.2.0 ([!2576](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2576)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update golangci/golangci-lint docker tag to v2.6.2 ([!2577](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2577)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- Code Refactor Using Request Handlers - 1 ([!2514](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2514)) by [Yashesvinee V](https://gitlab.com/yashes7516) + + + +## [0.160.1](https://gitlab.com/gitlab-org/api/client-go/compare/v0.160.0...v0.160.1) (2025-11-19) + + +### Bug Fixes + +* update input field from "key" to "name" in pipeline schedules to prevent an API error ([062133f](https://gitlab.com/gitlab-org/api/client-go/commit/062133f0c24b32ca6ae64a9f7b80fd3fa7e58256)) + +## 0.160.0 + +### ๐Ÿš€ Features + +- feat (project_members): Add show_seat_info option to ProjectMembers ([!2572](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2572)) by [Zubeen](https://gitlab.com/syedzubeen) + +### ๐Ÿ”„ Other Changes + +- refactor: fix modernize lint issues ([!2574](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2574)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- chore(deps): update module cel.dev/expr to v0.25.1 ([!2573](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2573)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- docs(no-release): format examples, update pkg doc url ([!2543](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2543)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [0.160.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.159.0...v0.160.0) (2025-11-12) + +## 0.159.0 + +### ๐Ÿš€ Features + +- feat(integrations): add group integration API endpoints for Jira ([!2563](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2563)) by [Harsh Rai](https://gitlab.com/harshrai654) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update golangci/golangci-lint docker tag to v2.6.1 ([!2564](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2564)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [0.159.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.158.0...v0.159.0) (2025-11-04) + + +### Features + +* **integrations:** add group integration API endpoints for Jira ([09e18ee](https://gitlab.com/gitlab-org/api/client-go/commit/09e18ee598bb7805ac8221f6a05426b1785f9011)) + +## 0.158.0 + +### ๐Ÿš€ Features + +- Add support to send variables for GraphQL queries ([!2562](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2562)) by [rafasf](https://gitlab.com/rafasf) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module cel.dev/expr to v0.25.0 ([!2560](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2560)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(no-release): standardize GitLab name capitalization ([!2551](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2551)) by [Zubeen](https://gitlab.com/syedzubeen) +- chore(deps): update golangci/golangci-lint docker tag to v2.6.0 ([!2558](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2558)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- refactor: moved comments to interface 2 ([!2557](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2557)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor: moved comments to interface ([!2556](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2556)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(test): avoid panic in tests with goroutines ([!2553](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2553)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [0.158.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.157.1...v0.158.0) (2025-11-03) + +## 0.157.1 + +### ๐Ÿ› Bug Fixes + +- fix(protected_packages): fix invalid types ([!2554](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2554)) by [Ruwen Schwedewsky](https://gitlab.com/RuwenSchwedewskySinch) + +### ๐Ÿ”„ Other Changes + +- chore: Update review instructions for mentioning GitLab ([!2552](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2552)) by [Zubeen](https://gitlab.com/syedzubeen) +- Implement do function to reduce boilerplate ([!2550](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2550)) by [Timo Furrer](https://gitlab.com/timofurrer) +- refactor(test): migrate to testify assertions 4 ([!2548](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2548)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(test): migrate to testify assertions 2 ([!2546](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2546)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(test): migrate to testify assertions ([!2545](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2545)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(test): migrate to testify assertions 5 ([!2549](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2549)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: add unit tests for cluster agents and deployments ([!2499](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2499)) by [Zubeen](https://gitlab.com/syedzubeen) +- refactor(test): migrate to testify assertions 3 ([!2547](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2547)) by [Zubeen](https://gitlab.com/syedzubeen) +- Fix: Helper Functions for Code Refactoring ([!2544](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2544)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- test: adds UT for formatPackageURL ([!2527](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2527)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: adds UT for getEpicLinks ([!2526](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2526)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: add test for ApproveOrRejectProjectDeployment ([!2498](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2498)) by [Zubeen](https://gitlab.com/syedzubeen) +- test: adds UTs for packages ([!2529](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2529)) by [Zubeen](https://gitlab.com/syedzubeen) + + + +## [0.157.1](https://gitlab.com/gitlab-org/api/client-go/compare/v0.157.0...v0.157.1) (2025-10-28) + + +### Bug Fixes + +* **no-release:** Helper Functions for Code Refactoring ([6feffea](https://gitlab.com/gitlab-org/api/client-go/commit/6feffea6696a8e333fd0811eee8501e58ba743e3)) +* **protected_packages:** fix invalid types ([c09943b](https://gitlab.com/gitlab-org/api/client-go/commit/c09943b0dde510dca32a2544a9c0f75f85943d96)) + +## 0.157.0 + +### ๐Ÿš€ Features + +- Add merge requests commit api ([!2539](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2539)) by [Ilya Savitsky](https://gitlab.com/ipsavitsky234) + +### ๐Ÿ”„ Other Changes + +- test: adds missing UTs for notifications ([!2528](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2528)) by [Zubeen](https://gitlab.com/syedzubeen) +- chore: Update review instructions ([!2537](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2537)) by [Patrick Rice](https://gitlab.com/PatrickRice) +- chore(no-release): Fix godoc comments; enable godoclint ([!2535](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2535)) by [Oleksandr Redko](https://gitlab.com/alexandear) + + + +# [0.157.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.156.0...v0.157.0) (2025-10-13) + +## 0.156.0 + +### ๐Ÿš€ Features + +- feat(api): add support for test report summary api ([!2487](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2487)) by [Daniela Filipe Bento](https://gitlab.com/danifbento) + + + +# [0.156.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.155.0...v0.156.0) (2025-10-10) + + +### Features + +* **api:** add support for test report summary api ([8a0c6dd](https://gitlab.com/gitlab-org/api/client-go/commit/8a0c6dde10a4c9c034274a439eaa060dc6e40995)) + +## 0.155.0 + +### ๐Ÿš€ Features + +- feat(group_relations_export): Added Group Relations API integration ([!2508](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2508)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) + +### ๐Ÿ”„ Other Changes + +- chore: use local protoc plugin with buf ([!2536](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2536)) by [Timo Furrer](https://gitlab.com/timofurrer) +- chore(no-release): Change generated file comment ([!2532](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2532)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- docs(no-release): Fix the comment for EnvVarGitLabContext ([!2533](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2533)) by [Oleksandr Redko](https://gitlab.com/alexandear) +- feat(client_options): Added unit tests ([!2510](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2510)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) + + + +# [0.155.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.154.0...v0.155.0) (2025-10-09) + + +### Features + +* **client_options:** Added unit tests ([c148031](https://gitlab.com/gitlab-org/api/client-go/commit/c14803189aa47a0cc9e64e9b455b93e6d4c4e4b9)) +* **group_relations_export:** Added Group Relations API integration ([956e039](https://gitlab.com/gitlab-org/api/client-go/commit/956e03950d6bc03c56fa1ea4c5d6e06bfd0b264f)) + +## 0.154.0 + +### ๐Ÿš€ Features + +- feat(protected_packages): Add api integration ([!2520](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2520)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) + + + +# [0.154.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.153.0...v0.154.0) (2025-10-08) + + +### Features + +* **protected_packages:** Add api integration ([2de15c7](https://gitlab.com/gitlab-org/api/client-go/commit/2de15c7875e232b0b0b1e5e5bb8e184cd11d0774)) + +## 0.153.0 + +### ๐Ÿš€ Features + +- feat(project_Statistics): Added api integration ([!2512](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2512)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) + +### ๐Ÿ”„ Other Changes + +- refactor: moved comments to interface ([!2509](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2509)) by [ajey muthiah](https://gitlab.com/ajeymuthiah) +- chore(no-release): Helper Functions for Code Refactoring ([!2503](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2503)) by [Yashesvinee V](https://gitlab.com/yashes7516) +- Add t.Parallel() to all tests and enable linters ([!2513](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2513)) by [Timo Furrer](https://gitlab.com/timofurrer) +- ci: Remove the `commitlint` job. ([!2511](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2511)) by [Florian Forster](https://gitlab.com/fforster) +- refactor: moved comments to interface ([!2507](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2507)) by [ajey muthiah](https://gitlab.com/ajeymuthiah) + + + +# [0.153.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.152.0...v0.153.0) (2025-10-08) + + +### Features + +* **project_Statistics:** Added api integration ([75b5a03](https://gitlab.com/gitlab-org/api/client-go/commit/75b5a03010a39d5353c975a558fda0b6f00cb697)) + +## 0.152.0 + +### ๐Ÿš€ Features + +- feat(api): add api support for listing users who starred a project ([!2486](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2486)) by [ajey muthiah](https://gitlab.com/ajeymuthiah) + +### ๐Ÿ”„ Other Changes + +- chore(no-release): Update Duo Review Instructions ([!2502](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2502)) by [Patrick Rice](https://gitlab.com/PatrickRice) +- feat(model_registry_api): Added api integration ([!2501](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2501)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) +- feat(no-release): Add AGENTS.md file ([!2479](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2479)) by [Patrick Rice](https://gitlab.com/PatrickRice) +- chore(no-release): Disable dependency scanning on personal forks ([!2500](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2500)) by [Patrick Rice](https://gitlab.com/PatrickRice) + + + +# [0.152.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.151.0...v0.152.0) (2025-10-06) + + +### Features + +* **api:** add api support for listing users who starred a project ([0cdb4ce](https://gitlab.com/gitlab-org/api/client-go/commit/0cdb4ce5399b43e47bf120a90b16d00c022e194c)) +* **model_registry_api:** Added api integration ([065dd63](https://gitlab.com/gitlab-org/api/client-go/commit/065dd639bc8bd0f44cab4d92dbe3ea7f134b913f)) +* **no-release:** Add AGENTS.md file ([b9febab](https://gitlab.com/gitlab-org/api/client-go/commit/b9febab3181c3f87edd1fd99b5e596f76bc8b7cc)) + +## 0.151.0 + +### ๐Ÿš€ Features + +- feat(api): add api support for delete enterprise user ([!2492](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2492)) by [ajey muthiah](https://gitlab.com/ajeymuthiah) + +### ๐Ÿ”„ Other Changes + +- docs(no-release): Make it easier to find the docs on issues ([!2497](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2497)) by [Heidi Berry](https://gitlab.com/heidi.berry) + + + +# [0.151.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.150.0...v0.151.0) (2025-10-04) + + +### Features + +* **api:** add api support for delete enterprise user ([36ca8ab](https://gitlab.com/gitlab-org/api/client-go/commit/36ca8ab7672c352a073d59dacae3d763d4089abb)) + +## 0.150.0 + +### ๐Ÿš€ Features + +- feat: add Project Aliases API support ([!2493](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2493)) by [Yashesvinee V](https://gitlab.com/yashes7516) + +### ๐Ÿ”„ Other Changes + +- chore(deps): update module buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to v1.36.10-20250912141014-52f32327d4b0.1 ([!2495](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2495)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- chore(deps): update module github.com/danieljoos/wincred to v1.2.3 ([!2494](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2494)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) + + + +# [0.150.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.149.0...v0.150.0) (2025-10-03) + + +### Features + +* add Project Aliases API support ([4ece88e](https://gitlab.com/gitlab-org/api/client-go/commit/4ece88e6a8cfa0f53e68184b2905d4c2fb6e857a)) + +## 0.149.0 + +### ๐Ÿš€ Features + +- feat(no-release): Add dependency scanning ([!2480](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2480)) by [Patrick Rice](https://gitlab.com/PatrickRice) + +### ๐Ÿ”„ Other Changes + +- ci(semantic-release): migrate to `@gitlab/semantic-release-merge-request-analyzer` ([!2490](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2490)) by [Florian Forster](https://gitlab.com/fforster) +- ci: add the `autolabels` job ([!2489](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2489)) by [Florian Forster](https://gitlab.com/fforster) +- chore(deps): update module google.golang.org/protobuf to v1.36.10 ([!2488](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2488)) by [GitLab Dependency Bot](https://gitlab.com/gitlab-dependency-update-bot) +- refactor(no-release): added tests for delete project hook method ([!2482](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2482)) by [Jose Gabriel Companioni Benitez](https://gitlab.com/elC0mpa) +- docs(no-release): Add guide for adding new APIs and issue templates ([!2478](https://gitlab.com/gitlab-org/api/client-go/-/merge_requests/2478)) by [Heidi Berry](https://gitlab.com/heidi.berry) + + + +# [0.149.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.148.1...v0.149.0) (2025-10-02) + + +### Features + +* **no-release:** Add dependency scanning ([8b0ee10](https://gitlab.com/gitlab-org/api/client-go/commit/8b0ee10acb8adceb5d34be2165b7d587b1e42e49)) + +## [0.148.1](https://gitlab.com/gitlab-org/api/client-go/compare/v0.148.0...v0.148.1) (2025-09-26) + + +### Bug Fixes + +* label unmarshaling for `BasicMergeRequest` list operations ([e80c453](https://gitlab.com/gitlab-org/api/client-go/commit/e80c453aa6a5a265ec8748ae3f3f761a70f4470e)) + +# [0.148.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.147.1...v0.148.0) (2025-09-23) + + +### Features + +* **ResourceGroup:** add `newest_ready_first` to resource group `process_mode` ([fc8f743](https://gitlab.com/gitlab-org/api/client-go/commit/fc8f7431da4ca8594723105473687e8f1378df2b)) + +## [0.147.1](https://gitlab.com/gitlab-org/api/client-go/compare/v0.147.0...v0.147.1) (2025-09-22) + + +### Bug Fixes + +* **client:** use default retry policy from retryablehttp ([2a72511](https://gitlab.com/gitlab-org/api/client-go/commit/2a725113118608712f668b159ca2dab11f4e588e)) + +# [0.147.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.146.0...v0.147.0) (2025-09-22) + + +### Features + +* **Project:** add resource_group_default_process_mode ([7804faf](https://gitlab.com/gitlab-org/api/client-go/commit/7804fafa18cc15fec8a0886a081bf3311d72eb1f)) + +# [0.146.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.145.0...v0.146.0) (2025-09-18) + + +### Features + +* **pipelines:** Add compile-time type-safe pipeline inputs support ([4b30e60](https://gitlab.com/gitlab-org/api/client-go/commit/4b30e60260e4f06e7684352693aac49abd748579)), closes [gitlab-org/api/client-go#2154](https://gitlab.com/gitlab-org/api/client-go/issues/2154) +* **PipelinesService:** Add support for pipeline inputs with type validation ([ab3056f](https://gitlab.com/gitlab-org/api/client-go/commit/ab3056f403ec0268e14b312de3f5b51b115ad97a)), closes [gitlab-org/api/client-go#2154](https://gitlab.com/gitlab-org/api/client-go/issues/2154) +* **PipelineTriggersService:** Add support for pipeline inputs to trigger API ([9ad770e](https://gitlab.com/gitlab-org/api/client-go/commit/9ad770e49e59b2a41c665dfc4781f3b56650e813)), closes [gitlab-org/api/client-go#2154](https://gitlab.com/gitlab-org/api/client-go/issues/2154) + # [0.145.0](https://gitlab.com/gitlab-org/api/client-go/compare/v0.144.1...v0.145.0) (2025-09-15) diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/CONTRIBUTING.md b/vendor/gitlab.com/gitlab-org/api/client-go/CONTRIBUTING.md index fb7d5c273..550771cc1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/CONTRIBUTING.md +++ b/vendor/gitlab.com/gitlab-org/api/client-go/CONTRIBUTING.md @@ -23,7 +23,7 @@ this project only supports what is in the public API docs. ### Use community fork to contribute To contribute to this project we recommend that you use the -[community fork](https://gitlab.com/gitlab-community/api/client-go). +[community fork](https://gitlab.com/gitlab-community/gitlab-org/api/client-go). Have a look at the [community fork README](https://gitlab.com/gitlab-community#gitlab-community-forks) to learn more about what it is and why you should prefer it over @@ -43,16 +43,24 @@ New `struct` fields or methods should be placed (as much as possible) in the sam order as the ordering used in the public API docs. The idea is that this makes it easier to find things. -### Setting up your local development environment to contribute +## Setting up your local development environment to contribute 1. Install dependencies: + ```sh make setup ``` + 1. Make your changes on your feature branch in the community fork or your personal fork 1. Run the reviewable command, which tests, lints and formats the code: + ```sh make reviewable ``` + 1. Push your feature branch upstream 1. Open up your merge request + +## Development Guides + +For more detailed advice on adding new features, please see our dedicated [guide for adding new APIs or Endpoints](./docs/guides/AddingAPISupport.md). diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/Makefile b/vendor/gitlab.com/gitlab-org/api/client-go/Makefile index 1ae79c886..956828568 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/Makefile +++ b/vendor/gitlab.com/gitlab-org/api/client-go/Makefile @@ -10,7 +10,7 @@ reviewable: setup generate fmt lint test ## Run before committing. fmt: ## Format code @buf format -w - @gofumpt -l -w *.go testing/*.go examples/*.go + @gofumpt -l -w *.go testing/*.go lint: ## Run linter @golangci-lint run @@ -37,3 +37,18 @@ clean: ## Remove generated files test: ## Run tests go test ./... -race + +test-integration: ## Run integration tests + go test ./... -race -tags=integration + +testacc-up: ## Launch a GitLab instance. + GITLAB_TOKEN=$(GITLAB_TOKEN) $(CONTAINER_COMPOSE_ENGINE) up -d $(SERVICE) + GITLAB_BASE_URL=$(GITLAB_BASE_URL) GITLAB_TOKEN=$(GITLAB_TOKEN) ./scripts/await_healthy.sh + +testacc-down: ## Teardown a GitLab instance. + $(CONTAINER_COMPOSE_ENGINE) down --volumes + +SERVICE ?= gitlab-ee-no-license +GITLAB_TOKEN ?= glpat-ACCTEST1234567890123 +GITLAB_BASE_URL ?= http://127.0.0.1:8095/api/v4 +CONTAINER_COMPOSE_ENGINE ?= $(shell docker compose version >/dev/null 2>&1 && echo 'docker compose' || echo 'docker-compose') diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/README.md b/vendor/gitlab.com/gitlab-org/api/client-go/README.md index d8dc8d1a0..13ba22e47 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/README.md +++ b/vendor/gitlab.com/gitlab-org/api/client-go/README.md @@ -7,6 +7,12 @@ A GitLab API client enabling Go programs to interact with GitLab in a simple and [[_TOC_]] +## `client-go` 1.0 Has Been Released! + +We're pleased to announce that version 1.0 has been released for the `client-go` library, which comes with +a backwards-compatibility guarantee. For more details of our major release plans moving forward, and for +migration guides, please see the [Migration Guides](#migration-guides) section below! + ## Usage ```go @@ -20,7 +26,7 @@ users: ```go git, err := gitlab.NewClient("yourtokengoeshere") if err != nil { - log.Fatalf("Failed to create client: %v", err) + log.Fatalf("Failed to create client: %v", err) } users, _, err := git.Users.ListUsers(&gitlab.ListUsersOptions{}) ``` @@ -80,10 +86,10 @@ func main() { // Add a new snippet s := &gitlab.CreateProjectSnippetOptions{ - Title: gitlab.Ptr("Dummy Snippet"), - FileName: gitlab.Ptr("snippet.go"), - Content: gitlab.Ptr("package main...."), - Visibility: gitlab.Ptr(gitlab.PublicVisibility), + Title: gitlab.Ptr("Dummy Snippet"), + FileName: gitlab.Ptr("snippet.go"), + Content: gitlab.Ptr("package main...."), + Visibility: gitlab.Ptr(gitlab.PublicVisibility), } _, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s) if err != nil { @@ -225,7 +231,7 @@ func main() { } ``` -For complete usage of go-gitlab, see the full [package docs](https://godoc.org/gitlab.com/gitlab-org/api/client-go). +For complete usage of go-gitlab, see the full [package docs](https://pkg.go.dev/gitlab.com/gitlab-org/api/client-go). ## Installation @@ -244,22 +250,22 @@ You can use them like this: ```go func TestMockExample(t *testing.T) { - client := gitlabtesting.NewTestClient(t) - opts := &gitlab.ListAgentsOptions{} - expectedResp := &gitlab.Response{} - pid := 1 - // Setup expectations - client.MockClusterAgents.EXPECT(). - ListAgents(pid, opts). - Return([]*gitlab.Agent{{ID: 1}}, expectedResp, nil) - - // Use the client in your test - // You'd probably call your own code here that gets the client injected. - // You can also retrieve a `gitlab.Client` object from `client.Client`. - agents, resp, err := client.ClusterAgents.ListAgents(pid, opts) - assert.NoError(t, err) - assert.Equal(t, expectedResp, resp) - assert.Len(t, agents, 1) + client := gitlabtesting.NewTestClient(t) + opts := &gitlab.ListAgentsOptions{} + expectedResp := &gitlab.Response{} + pid := 1 + // Setup expectations + client.MockClusterAgents.EXPECT(). + ListAgents(pid, opts). + Return([]*gitlab.Agent{{ID: 1}}, expectedResp, nil) + + // Use the client in your test + // You'd probably call your own code here that gets the client injected. + // You can also retrieve a `gitlab.Client` object from `client.Client`. + agents, resp, err := client.ClusterAgents.ListAgents(pid, opts) + assert.NoError(t, err) + assert.Equal(t, expectedResp, resp) + assert.Len(t, agents, 1) } ``` @@ -293,6 +299,13 @@ and the unit test matrix in [`.gitlab-ci.yml`](/.gitlab-ci.yml). You may also use https://endoflife.date/go to quickly discover the supported Go versions. +### Migration Guides + +`client-go` will release a major update roughly once every 6 months to align to the Go release cycle. Each +major release will publish a migration guide to help users migrate from the previous major release. + +- [Migration Guide for 0.X -> 1.X](docs/release-1.0-migration.md) + ## Contributing Contributions are always welcome. For more information, check out the diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/access_requests.go b/vendor/gitlab.com/gitlab-org/api/client-go/access_requests.go index 1c2ef31c7..b37cd94dd 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/access_requests.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/access_requests.go @@ -17,21 +17,80 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( AccessRequestsServiceInterface interface { + // ListProjectAccessRequests gets a list of access requests + // viewable by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project + // ListProjectAccessRequests gets a list of access requests + // viewable by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project ListProjectAccessRequests(pid any, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) + + // ListGroupAccessRequests gets a list of access requests + // viewable by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project + + // ListGroupAccessRequests gets a list of access requests + // viewable by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project ListGroupAccessRequests(gid any, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) + + // RequestProjectAccess requests access for the authenticated user + // to a group or project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#request-access-to-a-group-or-project + + // RequestProjectAccess requests access for the authenticated user + // to a group or project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#request-access-to-a-group-or-project RequestProjectAccess(pid any, options ...RequestOptionFunc) (*AccessRequest, *Response, error) + + // RequestGroupAccess requests access for the authenticated user + // to a group or project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#request-access-to-a-group-or-project RequestGroupAccess(gid any, options ...RequestOptionFunc) (*AccessRequest, *Response, error) - ApproveProjectAccessRequest(pid any, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) - ApproveGroupAccessRequest(gid any, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) - DenyProjectAccessRequest(pid any, user int, options ...RequestOptionFunc) (*Response, error) - DenyGroupAccessRequest(gid any, user int, options ...RequestOptionFunc) (*Response, error) + + // ApproveProjectAccessRequest approves an access request for the given user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#approve-an-access-request + ApproveProjectAccessRequest(pid any, user int64, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) + + // ApproveGroupAccessRequest approves an access request for the given user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#approve-an-access-request + ApproveGroupAccessRequest(gid any, user int64, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) + + // DenyProjectAccessRequest denies an access request for the given user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#deny-an-access-request + DenyProjectAccessRequest(pid any, user int64, options ...RequestOptionFunc) (*Response, error) + + // DenyGroupAccessRequest denies an access request for the given user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/access_requests/#deny-an-access-request + DenyGroupAccessRequest(gid any, user int64, options ...RequestOptionFunc) (*Response, error) } // AccessRequestsService handles communication with the project/group @@ -50,7 +109,7 @@ var _ AccessRequestsServiceInterface = (*AccessRequestsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/access_requests/ type AccessRequest struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Name string `json:"name"` State string `json:"state"` @@ -64,110 +123,42 @@ type AccessRequest struct { // // GitLab API docs: // https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project -type ListAccessRequestsOptions ListOptions +type ListAccessRequestsOptions struct { + ListOptions +} -// ListProjectAccessRequests gets a list of access requests -// viewable by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project func (s *AccessRequestsService) ListProjectAccessRequests(pid any, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_requests", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ars []*AccessRequest - resp, err := s.client.Do(req, &ars) - if err != nil { - return nil, resp, err - } - - return ars, resp, nil + return do[[]*AccessRequest](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/access_requests", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListGroupAccessRequests gets a list of access requests -// viewable by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#list-access-requests-for-a-group-or-project func (s *AccessRequestsService) ListGroupAccessRequests(gid any, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_requests", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ars []*AccessRequest - resp, err := s.client.Do(req, &ars) - if err != nil { - return nil, resp, err - } - - return ars, resp, nil + return do[[]*AccessRequest](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/access_requests", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// RequestProjectAccess requests access for the authenticated user -// to a group or project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#request-access-to-a-group-or-project func (s *AccessRequestsService) RequestProjectAccess(pid any, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_requests", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - ar := new(AccessRequest) - resp, err := s.client.Do(req, ar) - if err != nil { - return nil, resp, err - } - - return ar, resp, nil + return do[*AccessRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/access_requests", ProjectID{pid}), + withRequestOpts(options...), + ) } -// RequestGroupAccess requests access for the authenticated user -// to a group or project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#request-access-to-a-group-or-project func (s *AccessRequestsService) RequestGroupAccess(gid any, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_requests", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - ar := new(AccessRequest) - resp, err := s.client.Do(req, ar) - if err != nil { - return nil, resp, err - } - - return ar, resp, nil + return do[*AccessRequest](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/access_requests", GroupID{gid}), + withRequestOpts(options...), + ) } // ApproveAccessRequestOptions represents the available @@ -179,90 +170,38 @@ type ApproveAccessRequestOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` } -// ApproveProjectAccessRequest approves an access request for the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#approve-an-access-request -func (s *AccessRequestsService) ApproveProjectAccessRequest(pid any, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_requests/%d/approve", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ar := new(AccessRequest) - resp, err := s.client.Do(req, ar) - if err != nil { - return nil, resp, err - } - - return ar, resp, nil +func (s *AccessRequestsService) ApproveProjectAccessRequest(pid any, user int64, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { + return do[*AccessRequest](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/access_requests/%d/approve", ProjectID{pid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ApproveGroupAccessRequest approves an access request for the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#approve-an-access-request -func (s *AccessRequestsService) ApproveGroupAccessRequest(gid any, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_requests/%d/approve", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ar := new(AccessRequest) - resp, err := s.client.Do(req, ar) - if err != nil { - return nil, resp, err - } - - return ar, resp, nil +func (s *AccessRequestsService) ApproveGroupAccessRequest(gid any, user int64, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) { + return do[*AccessRequest](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/access_requests/%d/approve", GroupID{gid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DenyProjectAccessRequest denies an access request for the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#deny-an-access-request -func (s *AccessRequestsService) DenyProjectAccessRequest(pid any, user int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/access_requests/%d", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *AccessRequestsService) DenyProjectAccessRequest(pid any, user int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/access_requests/%d", ProjectID{pid}, user), + withRequestOpts(options...), + ) + return resp, err } -// DenyGroupAccessRequest denies an access request for the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/access_requests/#deny-an-access-request -func (s *AccessRequestsService) DenyGroupAccessRequest(gid any, user int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/access_requests/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *AccessRequestsService) DenyGroupAccessRequest(gid any, user int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/access_requests/%d", GroupID{gid}, user), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/admin_compliance_policy_settings.go b/vendor/gitlab.com/gitlab-org/api/client-go/admin_compliance_policy_settings.go new file mode 100644 index 000000000..2da145eb8 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/admin_compliance_policy_settings.go @@ -0,0 +1,85 @@ +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package gitlab + +import ( + "net/http" +) + +type ( + AdminCompliancePolicySettingsServiceInterface interface { + // GetCompliancePolicySettings gets the current security policy settings for the GitLab instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/compliance_policy_settings/#get-security-policy-settings + GetCompliancePolicySettings(options ...RequestOptionFunc) (*AdminCompliancePolicySettings, *Response, error) + + // UpdateCompliancePolicySettings updates the security policy settings for the GitLab instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/compliance_policy_settings/#update-security-policy-settings + UpdateCompliancePolicySettings(opt *UpdateAdminCompliancePolicySettingsOptions, options ...RequestOptionFunc) (*AdminCompliancePolicySettings, *Response, error) + } + + // AdminCompliancePolicySettingsService handles communication with the + // admin compliance policy settings related methods of the GitLab API. + // + // GitLab API docs: + // https://docs.gitlab.com/api/compliance_policy_settings/ + AdminCompliancePolicySettingsService struct { + client *Client + } +) + +var _ AdminCompliancePolicySettingsServiceInterface = (*AdminCompliancePolicySettingsService)(nil) + +// AdminCompliancePolicySettings represents the GitLab admin compliance policy settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/compliance_policy_settings/ +type AdminCompliancePolicySettings struct { + CSPNamespaceID *int64 `json:"csp_namespace_id"` +} + +func (s AdminCompliancePolicySettings) String() string { + return Stringify(s) +} + +func (s *AdminCompliancePolicySettingsService) GetCompliancePolicySettings(options ...RequestOptionFunc) (*AdminCompliancePolicySettings, *Response, error) { + return do[*AdminCompliancePolicySettings](s.client, + withMethod(http.MethodGet), + withPath("admin/security/compliance_policy_settings"), + withRequestOpts(options...), + ) +} + +// UpdateAdminCompliancePolicySettingsOptions represents the available +// UpdateCompliancePolicySettings() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/compliance_policy_settings/#update-security-policy-settings +type UpdateAdminCompliancePolicySettingsOptions struct { + CSPNamespaceID *int64 `url:"csp_namespace_id,omitempty" json:"csp_namespace_id,omitempty"` +} + +func (s *AdminCompliancePolicySettingsService) UpdateCompliancePolicySettings(opt *UpdateAdminCompliancePolicySettingsOptions, options ...RequestOptionFunc) (*AdminCompliancePolicySettings, *Response, error) { + return do[*AdminCompliancePolicySettings](s.client, + withMethod(http.MethodPut), + withPath("admin/security/compliance_policy_settings"), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/alert_management.go b/vendor/gitlab.com/gitlab-org/api/client-go/alert_management.go index c7e8b955c..c52ba3555 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/alert_management.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/alert_management.go @@ -15,7 +15,6 @@ package gitlab import ( - "fmt" "io" "net/http" "time" @@ -23,10 +22,29 @@ import ( type ( AlertManagementServiceInterface interface { - UploadMetricImage(pid any, alertIID int, content io.Reader, filename string, opt *UploadMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) - ListMetricImages(pid any, alertIID int, opt *ListMetricImagesOptions, options ...RequestOptionFunc) ([]*MetricImage, *Response, error) - UpdateMetricImage(pid any, alertIID int, id int, opt *UpdateMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) - DeleteMetricImage(pid any, alertIID int, id int, options ...RequestOptionFunc) (*Response, error) + // UploadMetricImage uploads a metric image to a project alert. + // + // GitLab API docs: + // https://docs.gitlab.com/api/alert_management_alerts/#upload-metric-image + UploadMetricImage(pid any, alertIID int64, content io.Reader, filename string, opt *UploadMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) + + // ListMetricImages lists all the metric images for a project alert. + // + // GitLab API docs: + // https://docs.gitlab.com/api/alert_management_alerts/#list-all-metric-images + ListMetricImages(pid any, alertIID int64, opt *ListMetricImagesOptions, options ...RequestOptionFunc) ([]*MetricImage, *Response, error) + + // UpdateMetricImage updates a metric image for a project alert. + // + // GitLab API docs: + // https://docs.gitlab.com/api/alert_management_alerts/#update-a-metric-image + UpdateMetricImage(pid any, alertIID int64, id int64, opt *UpdateMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) + + // DeleteMetricImage deletes a metric image for a project alert. + // + // GitLab API docs: + // https://docs.gitlab.com/api/alert_management_alerts/#delete-a-metric-image + DeleteMetricImage(pid any, alertIID int64, id int64, options ...RequestOptionFunc) (*Response, error) } // AlertManagementService handles communication with the alert management @@ -46,7 +64,7 @@ var _ AlertManagementServiceInterface = (*AlertManagementService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/alert_management_alerts/ type MetricImage struct { - ID int `json:"id"` + ID int64 `json:"id"` CreatedAt *time.Time `json:"created_at"` Filename string `json:"filename"` FilePath string `json:"file_path"` @@ -63,29 +81,14 @@ type UploadMetricImageOptions struct { URLText *string `url:"url_text,omitempty" json:"url_text,omitempty"` } -// UploadMetricImage uploads a metric image to a project alert. -// -// GitLab API docs: -// https://docs.gitlab.com/api/alert_management_alerts/#upload-metric-image -func (s *AlertManagementService) UploadMetricImage(pid any, alertIID int, content io.Reader, filename string, opt *UploadMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/alert_management_alerts/%d/metric_images", PathEscape(project), alertIID) - - req, err := s.client.UploadRequest(http.MethodPost, u, content, filename, UploadFile, opt, options) - if err != nil { - return nil, nil, err - } - - mi := new(MetricImage) - resp, err := s.client.Do(req, mi) - if err != nil { - return nil, resp, err - } - - return mi, resp, nil +func (s *AlertManagementService) UploadMetricImage(pid any, alertIID int64, content io.Reader, filename string, opt *UploadMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) { + return do[*MetricImage](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/alert_management_alerts/%d/metric_images", ProjectID{pid}, alertIID), + withUpload(content, filename, UploadFile), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListMetricImagesOptions represents the available ListMetricImages() options. @@ -96,29 +99,13 @@ type ListMetricImagesOptions struct { ListOptions } -// ListMetricImages lists all the metric images for a project alert. -// -// GitLab API docs: -// https://docs.gitlab.com/api/alert_management_alerts/#list-metric-images -func (s *AlertManagementService) ListMetricImages(pid any, alertIID int, opt *ListMetricImagesOptions, options ...RequestOptionFunc) ([]*MetricImage, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/alert_management_alerts/%d/metric_images", PathEscape(project), alertIID) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mis []*MetricImage - resp, err := s.client.Do(req, &mis) - if err != nil { - return nil, resp, err - } - - return mis, resp, nil +func (s *AlertManagementService) ListMetricImages(pid any, alertIID int64, opt *ListMetricImagesOptions, options ...RequestOptionFunc) ([]*MetricImage, *Response, error) { + return do[[]*MetricImage](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/alert_management_alerts/%d/metric_images", ProjectID{pid}, alertIID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateMetricImageOptions represents the available UpdateMetricImage() options. @@ -130,46 +117,20 @@ type UpdateMetricImageOptions struct { URLText *string `url:"url_text,omitempty" json:"url_text,omitempty"` } -// UpdateMetricImage updates a metric image for a project alert. -// -// GitLab API docs: -// https://docs.gitlab.com/api/alert_management_alerts/#update-metric-image -func (s *AlertManagementService) UpdateMetricImage(pid any, alertIID int, id int, opt *UpdateMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/alert_management_alerts/%d/metric_images/%d", PathEscape(project), alertIID, id) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - mi := new(MetricImage) - resp, err := s.client.Do(req, mi) - if err != nil { - return nil, resp, err - } - - return mi, resp, nil +func (s *AlertManagementService) UpdateMetricImage(pid any, alertIID int64, id int64, opt *UpdateMetricImageOptions, options ...RequestOptionFunc) (*MetricImage, *Response, error) { + return do[*MetricImage](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/alert_management_alerts/%d/metric_images/%d", ProjectID{pid}, alertIID, id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteMetricImage deletes a metric image for a project alert. -// -// GitLab API docs: -// https://docs.gitlab.com/api/alert_management_alerts/#delete-metric-image -func (s *AlertManagementService) DeleteMetricImage(pid any, alertIID int, id int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/alert_management_alerts/%d/metric_images/%d", PathEscape(project), alertIID, id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *AlertManagementService) DeleteMetricImage(pid any, alertIID int64, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/alert_management_alerts/%d/metric_images/%d", ProjectID{pid}, alertIID, id), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/appearance.go b/vendor/gitlab.com/gitlab-org/api/client-go/appearance.go index 6b4724e50..c7167ef95 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/appearance.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/appearance.go @@ -20,13 +20,22 @@ import "net/http" type ( AppearanceServiceInterface interface { + // GetAppearance gets the current appearance configuration of the GitLab instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/appearance/#get-details-on-current-application-appearance GetAppearance(options ...RequestOptionFunc) (*Appearance, *Response, error) + + // ChangeAppearance changes the appearance configuration. + // + // GitLab API docs: + // https://docs.gitlab.com/api/appearance/#update-application-appearance ChangeAppearance(opt *ChangeAppearanceOptions, options ...RequestOptionFunc) (*Appearance, *Response, error) } - // AppearanceService handles communication with appearance of the Gitlab API. + // AppearanceService handles communication with appearance of the GitLab API. // - // Gitlab API docs: https://docs.gitlab.com/api/appearance/ + // GitLab API docs: https://docs.gitlab.com/api/appearance/ AppearanceService struct { client *Client } @@ -36,7 +45,7 @@ var _ AppearanceServiceInterface = (*AppearanceService)(nil) // Appearance represents a GitLab appearance. // -// Gitlab API docs: https://docs.gitlab.com/api/appearance/ +// GitLab API docs: https://docs.gitlab.com/api/appearance/ type Appearance struct { Title string `json:"title"` Description string `json:"description"` @@ -57,23 +66,12 @@ type Appearance struct { EmailHeaderAndFooterEnabled bool `json:"email_header_and_footer_enabled"` } -// GetAppearance gets the current appearance configuration of the GitLab instance. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/appearance/#get-details-on-current-application-appearance func (s *AppearanceService) GetAppearance(options ...RequestOptionFunc) (*Appearance, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "application/appearance", nil, options) - if err != nil { - return nil, nil, err - } - - as := new(Appearance) - resp, err := s.client.Do(req, as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[*Appearance](s.client, + withMethod(http.MethodGet), + withPath("application/appearance"), + withRequestOpts(options...), + ) } // ChangeAppearanceOptions represents the available ChangeAppearance() options. @@ -101,21 +99,11 @@ type ChangeAppearanceOptions struct { URL *string `url:"url,omitempty" json:"url,omitempty"` } -// ChangeAppearance changes the appearance configuration. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/appearance/#update-application-appearance func (s *AppearanceService) ChangeAppearance(opt *ChangeAppearanceOptions, options ...RequestOptionFunc) (*Appearance, *Response, error) { - req, err := s.client.NewRequest(http.MethodPut, "application/appearance", opt, options) - if err != nil { - return nil, nil, err - } - - as := new(Appearance) - resp, err := s.client.Do(req, as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[*Appearance](s.client, + withMethod(http.MethodPut), + withPath("application/appearance"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/application_statistics.go b/vendor/gitlab.com/gitlab-org/api/client-go/application_statistics.go index 5442852c5..f1be66133 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/application_statistics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/application_statistics.go @@ -18,6 +18,10 @@ import "net/http" type ( ApplicationStatisticsServiceInterface interface { + // GetApplicationStatistics gets details on the current application statistics. + // + // GitLab API docs: + // https://docs.gitlab.com/api/statistics/#get-details-on-current-application-statistics GetApplicationStatistics(options ...RequestOptionFunc) (*ApplicationStatistics, *Response, error) } @@ -36,33 +40,23 @@ var _ ApplicationStatisticsServiceInterface = (*ApplicationStatisticsService)(ni // // GitLab API docs: https://docs.gitlab.com/api/statistics/ type ApplicationStatistics struct { - Forks int `url:"forks" json:"forks"` - Issues int `url:"issues" json:"issues"` - MergeRequests int `url:"merge_requests" json:"merge_requests"` - Notes int `url:"notes" json:"notes"` - Snippets int `url:"snippets" json:"snippets"` - SSHKeys int `url:"ssh_keys" json:"ssh_keys"` - Milestones int `url:"milestones" json:"milestones"` - Users int `url:"users" json:"users"` - Groups int `url:"groups" json:"groups"` - Projects int `url:"projects" json:"projects"` - ActiveUsers int `url:"active_users" json:"active_users"` + Forks int64 `url:"forks" json:"forks"` + Issues int64 `url:"issues" json:"issues"` + MergeRequests int64 `url:"merge_requests" json:"merge_requests"` + Notes int64 `url:"notes" json:"notes"` + Snippets int64 `url:"snippets" json:"snippets"` + SSHKeys int64 `url:"ssh_keys" json:"ssh_keys"` + Milestones int64 `url:"milestones" json:"milestones"` + Users int64 `url:"users" json:"users"` + Groups int64 `url:"groups" json:"groups"` + Projects int64 `url:"projects" json:"projects"` + ActiveUsers int64 `url:"active_users" json:"active_users"` } -// GetApplicationStatistics gets details on the current application statistics. -// -// GitLab API docs: -// https://docs.gitlab.com/api/statistics/#get-details-on-current-application-statistics func (s *ApplicationStatisticsService) GetApplicationStatistics(options ...RequestOptionFunc) (*ApplicationStatistics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "application/statistics", nil, options) - if err != nil { - return nil, nil, err - } - - statistics := new(ApplicationStatistics) - resp, err := s.client.Do(req, statistics) - if err != nil { - return nil, resp, err - } - return statistics, resp, nil + return do[*ApplicationStatistics](s.client, + withMethod(http.MethodGet), + withPath("application/statistics"), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/applications.go b/vendor/gitlab.com/gitlab-org/api/client-go/applications.go index 06dae54cb..c550ea5e1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/applications.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/applications.go @@ -17,21 +17,34 @@ package gitlab import ( - "fmt" "net/http" ) type ( ApplicationsServiceInterface interface { + // CreateApplication creates a new application owned by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/applications/#create-an-application CreateApplication(opt *CreateApplicationOptions, options ...RequestOptionFunc) (*Application, *Response, error) + + // ListApplications get a list of administrables applications by the authenticated user + // + // GitLab API docs: + // https://docs.gitlab.com/api/applications/#list-all-applications ListApplications(opt *ListApplicationsOptions, options ...RequestOptionFunc) ([]*Application, *Response, error) - DeleteApplication(application int, options ...RequestOptionFunc) (*Response, error) + + // DeleteApplication removes a specific application. + // + // GitLab API docs: + // https://docs.gitlab.com/api/applications/#delete-an-application + DeleteApplication(application int64, options ...RequestOptionFunc) (*Response, error) } // ApplicationsService handles communication with administrables applications - // of the Gitlab API. + // of the GitLab API. // - // Gitlab API docs: https://docs.gitlab.com/api/applications/ + // GitLab API docs: https://docs.gitlab.com/api/applications/ ApplicationsService struct { client *Client } @@ -41,7 +54,7 @@ var _ ApplicationsServiceInterface = (*ApplicationsService)(nil) // Application represents a GitLab application type Application struct { - ID int `json:"id"` + ID int64 `json:"id"` ApplicationID string `json:"application_id"` ApplicationName string `json:"application_name"` Secret string `json:"secret"` @@ -60,57 +73,35 @@ type CreateApplicationOptions struct { Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` } -// CreateApplication creates a new application owned by the authenticated user. -// -// Gitlab API docs: https://docs.gitlab.com/api/applications/#create-an-application func (s *ApplicationsService) CreateApplication(opt *CreateApplicationOptions, options ...RequestOptionFunc) (*Application, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "applications", opt, options) - if err != nil { - return nil, nil, err - } - - a := new(Application) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil + return do[*Application](s.client, + withMethod(http.MethodPost), + withPath("applications"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListApplicationsOptions represents the available // ListApplications() options. -type ListApplicationsOptions ListOptions +type ListApplicationsOptions struct { + ListOptions +} -// ListApplications get a list of administrables applications by the authenticated user -// -// Gitlab API docs : https://docs.gitlab.com/api/applications/#list-all-applications func (s *ApplicationsService) ListApplications(opt *ListApplicationsOptions, options ...RequestOptionFunc) ([]*Application, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "applications", opt, options) - if err != nil { - return nil, nil, err - } - - var as []*Application - resp, err := s.client.Do(req, &as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[[]*Application](s.client, + withMethod(http.MethodGet), + withPath("applications"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteApplication removes a specific application. -// -// GitLab API docs: -// https://docs.gitlab.com/api/applications/#delete-an-application -func (s *ApplicationsService) DeleteApplication(application int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("applications/%d", application) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ApplicationsService) DeleteApplication(application int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("applications/%d", application), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/attestations.go b/vendor/gitlab.com/gitlab-org/api/client-go/attestations.go new file mode 100644 index 000000000..0cfa14119 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/attestations.go @@ -0,0 +1,64 @@ +package gitlab + +import ( + "bytes" + "net/http" + "time" +) + +type ( + AttestationsServiceInterface interface { + // ListAttestations gets a list of all attestations + // + // GitLab API docs: https://docs.gitlab.com/api/attestations/#list-all-attestations + ListAttestations(pid any, subjectDigest string, options ...RequestOptionFunc) ([]*Attestation, *Response, error) + + // DownloadAttestation + // + // GitLab API docs: https://docs.gitlab.com/api/attestations/#download-an-attestation + DownloadAttestation(pid any, attestationIID int64, options ...RequestOptionFunc) ([]byte, *Response, error) + } + + // AttestationsService handles communication with the keys related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/attestations + AttestationsService struct { + client *Client + } +) + +var _ AttestationsServiceInterface = (*AttestationsService)(nil) + +type Attestation struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` + BuildID int64 `json:"build_id"` + Status string `json:"status"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + ExpireAt *time.Time `json:"expire_at"` + PredicateKind string `json:"predicate_kind"` + PredicateType string `json:"predicate_type"` + SubjectDigest string `json:"subject_digest"` + DownloadURL string `json:"download_url"` +} + +func (s *AttestationsService) ListAttestations(pid any, subjectDigest string, options ...RequestOptionFunc) ([]*Attestation, *Response, error) { + return do[[]*Attestation](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/attestations/%s", ProjectID{pid}, subjectDigest), + withRequestOpts(options...), + ) +} + +func (s *AttestationsService) DownloadAttestation(pid any, attestationIID int64, options ...RequestOptionFunc) ([]byte, *Response, error) { + b, resp, err := do[bytes.Buffer](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/attestations/%d/download", ProjectID{pid}, attestationIID), + withRequestOpts(options...), + ) + + return b.Bytes(), resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/audit_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/audit_events.go index 3a61d8a4f..6e98b8e88 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/audit_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/audit_events.go @@ -1,19 +1,53 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( AuditEventsServiceInterface interface { + // ListInstanceAuditEvents gets a list of audit events for instance. + // Authentication as Administrator is required. + // + // GitLab API docs: + // https://docs.gitlab.com/api/audit_events/#retrieve-all-instance-audit-events + // ListInstanceAuditEvents gets a list of audit events for instance. + // Authentication as Administrator is required. + // + // GitLab API docs: + // https://docs.gitlab.com/api/audit_events/#retrieve-all-instance-audit-events ListInstanceAuditEvents(opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) - GetInstanceAuditEvent(event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) + + // GetInstanceAuditEvent gets a specific instance audit event. + // Authentication as Administrator is required. + // + // GitLab API docs: + // https://docs.gitlab.com/api/audit_events/#retrieve-single-instance-audit-event + GetInstanceAuditEvent(event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) + + // ListGroupAuditEvents gets a list of audit events for the specified group + // viewable by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/audit_events/#retrieve-all-group-audit-events ListGroupAuditEvents(gid any, opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) - GetGroupAuditEvent(gid any, event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) + + // GetGroupAuditEvent gets a specific group audit event. + // + // GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-a-specific-group-audit-event + GetGroupAuditEvent(gid any, event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) + + // ListProjectAuditEvents gets a list of audit events for the specified project + // viewable by the authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-all-project-audit-events ListProjectAuditEvents(pid any, opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) - GetProjectAuditEvent(pid any, event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) + + // GetProjectAuditEvent gets a specific project audit event. + // + // GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-a-specific-project-audit-event + GetProjectAuditEvent(pid any, event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) } // AuditEventsService handles communication with the project/group/instance @@ -31,9 +65,9 @@ var _ AuditEventsServiceInterface = (*AuditEventsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/audit_events/ type AuditEvent struct { - ID int `json:"id"` - AuthorID int `json:"author_id"` - EntityID int `json:"entity_id"` + ID int64 `json:"id"` + AuthorID int64 `json:"author_id"` + EntityID int64 `json:"entity_id"` EntityType string `json:"entity_type"` EventName string `json:"event_name"` Details AuditEventDetails `json:"details"` @@ -77,141 +111,53 @@ type ListAuditEventsOptions struct { CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` } -// ListInstanceAuditEvents gets a list of audit events for instance. -// Authentication as Administrator is required. -// -// GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-all-instance-audit-events func (s *AuditEventsService) ListInstanceAuditEvents(opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "audit_events", opt, options) - if err != nil { - return nil, nil, err - } - - var aes []*AuditEvent - resp, err := s.client.Do(req, &aes) - if err != nil { - return nil, resp, err - } - - return aes, resp, nil + return do[[]*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("audit_events"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetInstanceAuditEvent gets a specific instance audit event. -// Authentication as Administrator is required. -// -// GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-single-instance-audit-event -func (s *AuditEventsService) GetInstanceAuditEvent(event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { - u := fmt.Sprintf("audit_events/%d", event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ae := new(AuditEvent) - resp, err := s.client.Do(req, ae) - if err != nil { - return nil, resp, err - } - - return ae, resp, nil +func (s *AuditEventsService) GetInstanceAuditEvent(event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { + return do[*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("audit_events/%d", event), + withRequestOpts(options...), + ) } -// ListGroupAuditEvents gets a list of audit events for the specified group -// viewable by the authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-all-group-audit-events func (s *AuditEventsService) ListGroupAuditEvents(gid any, opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/audit_events", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var aes []*AuditEvent - resp, err := s.client.Do(req, &aes) - if err != nil { - return nil, resp, err - } - - return aes, resp, nil + return do[[]*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/audit_events", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetGroupAuditEvent gets a specific group audit event. -// -// GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-a-specific-group-audit-event -func (s *AuditEventsService) GetGroupAuditEvent(gid any, event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/audit_events/%d", PathEscape(group), event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ae := new(AuditEvent) - resp, err := s.client.Do(req, ae) - if err != nil { - return nil, resp, err - } - - return ae, resp, nil +func (s *AuditEventsService) GetGroupAuditEvent(gid any, event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { + return do[*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/audit_events/%d", GroupID{gid}, event), + withRequestOpts(options...), + ) } -// ListProjectAuditEvents gets a list of audit events for the specified project -// viewable by the authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/audit_events/#retrieve-all-project-audit-events func (s *AuditEventsService) ListProjectAuditEvents(pid any, opt *ListAuditEventsOptions, options ...RequestOptionFunc) ([]*AuditEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/audit_events", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var aes []*AuditEvent - resp, err := s.client.Do(req, &aes) - if err != nil { - return nil, resp, err - } - - return aes, resp, nil + return do[[]*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/audit_events", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectAuditEvent gets a specific project audit event. -// -// GitLab API docs: -// https://docs.gitlab.com/api/audit_events/#retrieve-a-specific-project-audit-event -func (s *AuditEventsService) GetProjectAuditEvent(pid any, event int, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/audit_events/%d", PathEscape(project), event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ae := new(AuditEvent) - resp, err := s.client.Do(req, ae) - if err != nil { - return nil, resp, err - } - - return ae, resp, nil +func (s *AuditEventsService) GetProjectAuditEvent(pid any, event int64, options ...RequestOptionFunc) (*AuditEvent, *Response, error) { + return do[*AuditEvent](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/audit_events/%d", ProjectID{pid}, event), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/avatar.go b/vendor/gitlab.com/gitlab-org/api/client-go/avatar.go index e0bf2d6f7..9b2ed7d0a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/avatar.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/avatar.go @@ -22,6 +22,10 @@ import ( type ( AvatarRequestsServiceInterface interface { + // GetAvatar gets the avatar URL for a user with the given email address. + // + // GitLab API docs: + // https://docs.gitlab.com/api/avatar/#get-details-on-an-account-avatar GetAvatar(opt *GetAvatarOptions, options ...RequestOptionFunc) (*Avatar, *Response, error) } @@ -49,24 +53,14 @@ type Avatar struct { // https://docs.gitlab.com/api/avatar/#get-details-on-an-account-avatar type GetAvatarOptions struct { Email *string `url:"email,omitempty" json:"email,omitempty"` - Size *int `url:"size,omitempty" json:"size,omitempty"` + Size *int64 `url:"size,omitempty" json:"size,omitempty"` } -// GetAvatar gets the avatar URL for a user with the given email address. -// -// GitLab API docs: -// https://docs.gitlab.com/api/avatar/#get-details-on-an-account-avatar func (s *AvatarRequestsService) GetAvatar(opt *GetAvatarOptions, options ...RequestOptionFunc) (*Avatar, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "avatar", opt, options) - if err != nil { - return nil, nil, err - } - - avatar := new(Avatar) - response, err := s.client.Do(req, avatar) - if err != nil { - return nil, response, err - } - - return avatar, response, nil + return do[*Avatar](s.client, + withMethod(http.MethodGet), + withPath("avatar"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/award_emojis.go b/vendor/gitlab.com/gitlab-org/api/client-go/award_emojis.go index 360a16f3e..26a2e28c2 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/award_emojis.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/award_emojis.go @@ -17,37 +17,161 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( AwardEmojiServiceInterface interface { - ListMergeRequestAwardEmoji(pid any, mergeRequestIID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - ListIssueAwardEmoji(pid any, issueIID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - ListSnippetAwardEmoji(pid any, snippetID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - GetMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - GetIssueAwardEmoji(pid any, issueIID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - GetSnippetAwardEmoji(pid any, snippetID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateMergeRequestAwardEmoji(pid any, mergeRequestIID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateIssueAwardEmoji(pid any, issueIID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateSnippetAwardEmoji(pid any, snippetID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - DeleteIssueAwardEmoji(pid any, issueIID, awardID int, options ...RequestOptionFunc) (*Response, error) - DeleteMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int, options ...RequestOptionFunc) (*Response, error) - DeleteSnippetAwardEmoji(pid any, snippetID, awardID int, options ...RequestOptionFunc) (*Response, error) - ListIssuesAwardEmojiOnNote(pid any, issueID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - ListMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - ListSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) - GetIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - GetMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - GetSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateIssuesAwardEmojiOnNote(pid any, issueID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - CreateSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) - DeleteIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) - DeleteMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) - DeleteSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) + // ListMergeRequestAwardEmoji gets a list of all award emoji on the merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions + ListMergeRequestAwardEmoji(pid any, mergeRequestIID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // ListIssueAwardEmoji gets a list of all award emoji on the issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions + ListIssueAwardEmoji(pid any, issueIID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // ListSnippetAwardEmoji gets a list of all award emoji on the snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions + ListSnippetAwardEmoji(pid any, snippetID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // GetMergeRequestAwardEmoji get an award emoji from merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction + GetMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // GetIssueAwardEmoji get an award emoji from issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction + GetIssueAwardEmoji(pid any, issueIID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // GetSnippetAwardEmoji get an award emoji from snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction + GetSnippetAwardEmoji(pid any, snippetID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateMergeRequestAwardEmoji get an award emoji from merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction + CreateMergeRequestAwardEmoji(pid any, mergeRequestIID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateIssueAwardEmoji get an award emoji from issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction + CreateIssueAwardEmoji(pid any, issueIID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateSnippetAwardEmoji get an award emoji from snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction + CreateSnippetAwardEmoji(pid any, snippetID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // DeleteIssueAwardEmoji delete award emoji on an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction + DeleteIssueAwardEmoji(pid any, issueIID, awardID int64, options ...RequestOptionFunc) (*Response, error) + + // DeleteMergeRequestAwardEmoji delete award emoji on a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction + DeleteMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int64, options ...RequestOptionFunc) (*Response, error) + + // DeleteSnippetAwardEmoji delete award emoji on a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction + DeleteSnippetAwardEmoji(pid any, snippetID, awardID int64, options ...RequestOptionFunc) (*Response, error) + + // ListIssuesAwardEmojiOnNote gets a list of all award emoji on a note from the + // issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions + ListIssuesAwardEmojiOnNote(pid any, issueID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // ListMergeRequestAwardEmojiOnNote gets a list of all award emoji on a note + // from the merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions + ListMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // ListSnippetAwardEmojiOnNote gets a list of all award emoji on a note from the + // snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions + ListSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) + + // GetIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment + GetIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // GetMergeRequestAwardEmojiOnNote gets an award emoji on a note from a + // merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment + GetMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // GetSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment + GetSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment + CreateIssuesAwardEmojiOnNote(pid any, issueID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateMergeRequestAwardEmojiOnNote gets an award emoji on a note from a + // merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment + CreateMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // CreateSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment + CreateSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) + + // DeleteIssuesAwardEmojiOnNote deletes an award emoji on a note from an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment + DeleteIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) + + // DeleteMergeRequestAwardEmojiOnNote deletes an award emoji on a note from a + // merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment + DeleteMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) + + // DeleteSnippetAwardEmojiOnNote deletes an award emoji on a note from a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment + DeleteSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) } // AwardEmojiService handles communication with the emoji awards related methods @@ -65,19 +189,12 @@ var _ AwardEmojiServiceInterface = (*AwardEmojiService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/emoji_reactions/ type AwardEmoji struct { - ID int `json:"id"` - Name string `json:"name"` - User struct { - Name string `json:"name"` - Username string `json:"username"` - ID int `json:"id"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"user"` + ID int64 `json:"id"` + Name string `json:"name"` + User BasicUser `json:"user"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` - AwardableID int `json:"awardable_id"` + AwardableID int64 `json:"awardable_id"` AwardableType string `json:"awardable_type"` } @@ -92,105 +209,49 @@ const ( // // GitLab API docs: // https://docs.gitlab.com/api/emoji_reactions/ -type ListAwardEmojiOptions ListOptions +type ListAwardEmojiOptions struct { + ListOptions +} -// ListMergeRequestAwardEmoji gets a list of all award emoji on the merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions -func (s *AwardEmojiService) ListMergeRequestAwardEmoji(pid any, mergeRequestIID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListMergeRequestAwardEmoji(pid any, mergeRequestIID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmoji(pid, awardMergeRequest, mergeRequestIID, opt, options...) } -// ListIssueAwardEmoji gets a list of all award emoji on the issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions -func (s *AwardEmojiService) ListIssueAwardEmoji(pid any, issueIID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListIssueAwardEmoji(pid any, issueIID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmoji(pid, awardIssue, issueIID, opt, options...) } -// ListSnippetAwardEmoji gets a list of all award emoji on the snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-an-awardables-emoji-reactions -func (s *AwardEmojiService) ListSnippetAwardEmoji(pid any, snippetID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListSnippetAwardEmoji(pid any, snippetID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmoji(pid, awardSnippets, snippetID, opt, options...) } -func (s *AwardEmojiService) listAwardEmoji(pid any, resource string, resourceID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/award_emoji", - PathEscape(project), - resource, - resourceID, +func (s *AwardEmojiService) listAwardEmoji(pid any, resource string, resourceID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { + return do[[]*AwardEmoji](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/%s/%d/award_emoji", ProjectID{pid}, resource, resourceID), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var as []*AwardEmoji - resp, err := s.client.Do(req, &as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil } -// GetMergeRequestAwardEmoji get an award emoji from merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction -func (s *AwardEmojiService) GetMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getAwardEmoji(pid, awardMergeRequest, mergeRequestIID, awardID, options...) } -// GetIssueAwardEmoji get an award emoji from issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction -func (s *AwardEmojiService) GetIssueAwardEmoji(pid any, issueIID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetIssueAwardEmoji(pid any, issueIID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getAwardEmoji(pid, awardIssue, issueIID, awardID, options...) } -// GetSnippetAwardEmoji get an award emoji from snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-single-emoji-reaction -func (s *AwardEmojiService) GetSnippetAwardEmoji(pid any, snippetID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetSnippetAwardEmoji(pid any, snippetID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getAwardEmoji(pid, awardSnippets, snippetID, awardID, options...) } -func (s *AwardEmojiService) getAwardEmoji(pid any, resource string, resourceID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/award_emoji/%d", - PathEscape(project), - resource, - resourceID, - awardID, +func (s *AwardEmojiService) getAwardEmoji(pid any, resource string, resourceID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { + return do[*AwardEmoji](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/%s/%d/award_emoji/%d", ProjectID{pid}, resource, resourceID, awardID), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(AwardEmoji) - resp, err := s.client.Do(req, &a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil } // CreateAwardEmojiOptions represents the available options for awarding emoji @@ -202,76 +263,36 @@ type CreateAwardEmojiOptions struct { Name string `json:"name"` } -// CreateMergeRequestAwardEmoji get an award emoji from merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction -func (s *AwardEmojiService) CreateMergeRequestAwardEmoji(pid any, mergeRequestIID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateMergeRequestAwardEmoji(pid any, mergeRequestIID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmoji(pid, awardMergeRequest, mergeRequestIID, opt, options...) } -// CreateIssueAwardEmoji get an award emoji from issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction -func (s *AwardEmojiService) CreateIssueAwardEmoji(pid any, issueIID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateIssueAwardEmoji(pid any, issueIID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmoji(pid, awardIssue, issueIID, opt, options...) } -// CreateSnippetAwardEmoji get an award emoji from snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction -func (s *AwardEmojiService) CreateSnippetAwardEmoji(pid any, snippetID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateSnippetAwardEmoji(pid any, snippetID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmoji(pid, awardSnippets, snippetID, opt, options...) } -func (s *AwardEmojiService) createAwardEmoji(pid any, resource string, resourceID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/award_emoji", - PathEscape(project), - resource, - resourceID, +func (s *AwardEmojiService) createAwardEmoji(pid any, resource string, resourceID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { + return do[*AwardEmoji](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/award_emoji", ProjectID{pid}, resource, resourceID), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - a := new(AwardEmoji) - resp, err := s.client.Do(req, &a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil } -// DeleteIssueAwardEmoji delete award emoji on an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction -func (s *AwardEmojiService) DeleteIssueAwardEmoji(pid any, issueIID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteIssueAwardEmoji(pid any, issueIID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmoji(pid, awardIssue, issueIID, awardID, options...) } -// DeleteMergeRequestAwardEmoji delete award emoji on a merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction -func (s *AwardEmojiService) DeleteMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteMergeRequestAwardEmoji(pid any, mergeRequestIID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmoji(pid, awardMergeRequest, mergeRequestIID, awardID, options...) } -// DeleteSnippetAwardEmoji delete award emoji on a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction -func (s *AwardEmojiService) DeleteSnippetAwardEmoji(pid any, snippetID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteSnippetAwardEmoji(pid any, snippetID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmoji(pid, awardSnippets, snippetID, awardID, options...) } @@ -279,145 +300,66 @@ func (s *AwardEmojiService) DeleteSnippetAwardEmoji(pid any, snippetID, awardID // // GitLab API docs: // https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction -func (s *AwardEmojiService) deleteAwardEmoji(pid any, resource string, resourceID, awardID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/award_emoji/%d", PathEscape(project), resource, - resourceID, awardID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - return s.client.Do(req, nil) +func (s *AwardEmojiService) deleteAwardEmoji(pid any, resource string, resourceID, awardID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/%s/%d/award_emoji/%d", ProjectID{pid}, resource, resourceID, awardID), + withRequestOpts(options...), + ) + return resp, err } -// ListIssuesAwardEmojiOnNote gets a list of all award emoji on a note from the -// issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions -func (s *AwardEmojiService) ListIssuesAwardEmojiOnNote(pid any, issueID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListIssuesAwardEmojiOnNote(pid any, issueID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmojiOnNote(pid, awardIssue, issueID, noteID, opt, options...) } -// ListMergeRequestAwardEmojiOnNote gets a list of all award emoji on a note -// from the merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions -func (s *AwardEmojiService) ListMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, opt, options...) } -// ListSnippetAwardEmojiOnNote gets a list of all award emoji on a note from the -// snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#list-a-comments-emoji-reactions -func (s *AwardEmojiService) ListSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) ListSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { return s.listAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, opt, options...) } -func (s *AwardEmojiService) listAwardEmojiOnNote(pid any, resources string, resourceID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji", PathEscape(project), resources, - resourceID, noteID) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var as []*AwardEmoji - resp, err := s.client.Do(req, &as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil +func (s *AwardEmojiService) listAwardEmojiOnNote(pid any, resources string, resourceID, noteID int64, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) { + return do[[]*AwardEmoji](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/%s/%d/notes/%d/award_emoji", ProjectID{pid}, resources, resourceID, noteID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment -func (s *AwardEmojiService) GetIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getSingleNoteAwardEmoji(pid, awardIssue, issueID, noteID, awardID, options...) } -// GetMergeRequestAwardEmojiOnNote gets an award emoji on a note from a -// merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment -func (s *AwardEmojiService) GetMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getSingleNoteAwardEmoji(pid, awardMergeRequest, mergeRequestIID, noteID, awardID, options...) } -// GetSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#get-an-emoji-reaction-for-a-comment -func (s *AwardEmojiService) GetSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) GetSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.getSingleNoteAwardEmoji(pid, awardSnippets, snippetIID, noteID, awardID, options...) } -func (s *AwardEmojiService) getSingleNoteAwardEmoji(pid any, resource string, resourceID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji/%d", - PathEscape(project), - resource, - resourceID, - noteID, - awardID, +func (s *AwardEmojiService) getSingleNoteAwardEmoji(pid any, resource string, resourceID, noteID, awardID int64, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { + return do[*AwardEmoji](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/%s/%d/notes/%d/award_emoji/%d", ProjectID{pid}, resource, resourceID, noteID, awardID), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(AwardEmoji) - resp, err := s.client.Do(req, &a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil } -// CreateIssuesAwardEmojiOnNote gets an award emoji on a note from an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment -func (s *AwardEmojiService) CreateIssuesAwardEmojiOnNote(pid any, issueID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateIssuesAwardEmojiOnNote(pid any, issueID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmojiOnNote(pid, awardIssue, issueID, noteID, opt, options...) } -// CreateMergeRequestAwardEmojiOnNote gets an award emoji on a note from a -// merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment -func (s *AwardEmojiService) CreateMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, opt, options...) } -// CreateSnippetAwardEmojiOnNote gets an award emoji on a note from a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment -func (s *AwardEmojiService) CreateSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { +func (s *AwardEmojiService) CreateSnippetAwardEmojiOnNote(pid any, snippetIID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { return s.createAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, opt, options...) } @@ -425,75 +367,33 @@ func (s *AwardEmojiService) CreateSnippetAwardEmojiOnNote(pid any, snippetIID, n // // GitLab API docs: // https://docs.gitlab.com/api/emoji_reactions/#add-a-new-emoji-reaction-to-a-comment -func (s *AwardEmojiService) createAwardEmojiOnNote(pid any, resource string, resourceID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji", - PathEscape(project), - resource, - resourceID, - noteID, +func (s *AwardEmojiService) createAwardEmojiOnNote(pid any, resource string, resourceID, noteID int64, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) { + return do[*AwardEmoji](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/notes/%d/award_emoji", ProjectID{pid}, resource, resourceID, noteID), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - a := new(AwardEmoji) - resp, err := s.client.Do(req, &a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil } -// DeleteIssuesAwardEmojiOnNote deletes an award emoji on a note from an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment -func (s *AwardEmojiService) DeleteIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteIssuesAwardEmojiOnNote(pid any, issueID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmojiOnNote(pid, awardIssue, issueID, noteID, awardID, options...) } -// DeleteMergeRequestAwardEmojiOnNote deletes an award emoji on a note from a -// merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment -func (s *AwardEmojiService) DeleteMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteMergeRequestAwardEmojiOnNote(pid any, mergeRequestIID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmojiOnNote(pid, awardMergeRequest, mergeRequestIID, noteID, awardID, options...) } -// DeleteSnippetAwardEmojiOnNote deletes an award emoji on a note from a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/emoji_reactions/#delete-an-emoji-reaction-from-a-comment -func (s *AwardEmojiService) DeleteSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) { +func (s *AwardEmojiService) DeleteSnippetAwardEmojiOnNote(pid any, snippetIID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) { return s.deleteAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, awardID, options...) } -func (s *AwardEmojiService) deleteAwardEmojiOnNote(pid any, resource string, resourceID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/notes/%d/award_emoji/%d", - PathEscape(project), - resource, - resourceID, - noteID, - awardID, +func (s *AwardEmojiService) deleteAwardEmojiOnNote(pid any, resource string, resourceID, noteID, awardID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/%s/%d/notes/%d/award_emoji/%d", ProjectID{pid}, resource, resourceID, noteID, awardID), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/boards.go b/vendor/gitlab.com/gitlab-org/api/client-go/boards.go index 1d1558d02..0cbf49b7c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/boards.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/boards.go @@ -17,22 +17,76 @@ package gitlab import ( - "fmt" "net/http" ) type ( IssueBoardsServiceInterface interface { + // CreateIssueBoard creates a new issue board. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#create-an-issue-board + // CreateIssueBoard creates a new issue board. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#create-an-issue-board CreateIssueBoard(pid any, opt *CreateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) - UpdateIssueBoard(pid any, board int, opt *UpdateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) - DeleteIssueBoard(pid any, board int, options ...RequestOptionFunc) (*Response, error) + + // UpdateIssueBoard update an issue board. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#update-an-issue-board + UpdateIssueBoard(pid any, board int64, opt *UpdateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) + + // DeleteIssueBoard deletes an issue board. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#delete-an-issue-board + DeleteIssueBoard(pid any, board int64, options ...RequestOptionFunc) (*Response, error) + + // ListIssueBoards gets a list of all issue boards in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#list-project-issue-boards ListIssueBoards(pid any, opt *ListIssueBoardsOptions, options ...RequestOptionFunc) ([]*IssueBoard, *Response, error) - GetIssueBoard(pid any, board int, options ...RequestOptionFunc) (*IssueBoard, *Response, error) - GetIssueBoardLists(pid any, board int, opt *GetIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) - GetIssueBoardList(pid any, board, list int, options ...RequestOptionFunc) (*BoardList, *Response, error) - CreateIssueBoardList(pid any, board int, opt *CreateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) - UpdateIssueBoardList(pid any, board, list int, opt *UpdateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) - DeleteIssueBoardList(pid any, board, list int, options ...RequestOptionFunc) (*Response, error) + + // GetIssueBoard gets a single issue board of a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#show-a-single-issue-board + GetIssueBoard(pid any, board int64, options ...RequestOptionFunc) (*IssueBoard, *Response, error) + + // GetIssueBoardLists gets a list of the issue board's lists. Does not include + // backlog and closed lists. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#list-board-lists-in-a-project-issue-board + GetIssueBoardLists(pid any, board int64, opt *GetIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) + + // GetIssueBoardList gets a single issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#show-a-single-board-list + GetIssueBoardList(pid any, board, list int64, options ...RequestOptionFunc) (*BoardList, *Response, error) + + // CreateIssueBoardList creates a new issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#create-a-board-list + CreateIssueBoardList(pid any, board int64, opt *CreateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) + + // UpdateIssueBoardList updates the position of an existing issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#reorder-a-list-in-a-board + UpdateIssueBoardList(pid any, board, list int64, opt *UpdateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) + + // DeleteIssueBoardList soft deletes an issue board list. Only for admins and + // project owners. + // + // GitLab API docs: + // https://docs.gitlab.com/api/boards/#delete-a-board-list-from-a-board + DeleteIssueBoardList(pid any, board, list int64, options ...RequestOptionFunc) (*Response, error) } // IssueBoardsService handles communication with the issue board related @@ -50,21 +104,16 @@ var _ IssueBoardsServiceInterface = (*IssueBoardsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/boards/ type IssueBoard struct { - ID int `json:"id"` - Name string `json:"name"` - Project *Project `json:"project"` - Milestone *Milestone `json:"milestone"` - Assignee *struct { - ID int `json:"id"` - Username string `json:"username"` - Name string `json:"name"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"assignee"` - Lists []*BoardList `json:"lists"` - Weight int `json:"weight"` - Labels []*LabelDetails `json:"labels"` + ID int64 `json:"id"` + Name string `json:"name"` + Project *Project `json:"project"` + Milestone *Milestone `json:"milestone"` + Assignee *BasicUser `json:"assignee"` + Lists []*BoardList `json:"lists"` + Weight int64 `json:"weight"` + Labels []*LabelDetails `json:"labels"` + HideBacklogList bool `json:"hide_backlog_list"` + HideClosedList bool `json:"hide_closed_list"` } func (b IssueBoard) String() string { @@ -75,24 +124,33 @@ func (b IssueBoard) String() string { // // GitLab API docs: https://docs.gitlab.com/api/boards/ type BoardList struct { - ID int `json:"id"` - Assignee *struct { - ID int `json:"id"` - Name string `json:"name"` - Username string `json:"username"` - } `json:"assignee"` - Iteration *ProjectIteration `json:"iteration"` - Label *Label `json:"label"` - MaxIssueCount int `json:"max_issue_count"` - MaxIssueWeight int `json:"max_issue_weight"` - Milestone *Milestone `json:"milestone"` - Position int `json:"position"` + ID int64 `json:"id"` + Assignee *BoardListAssignee `json:"assignee"` + Iteration *ProjectIteration `json:"iteration"` + Label *Label `json:"label"` + MaxIssueCount int64 `json:"max_issue_count"` + MaxIssueWeight int64 `json:"max_issue_weight"` + Milestone *Milestone `json:"milestone"` + Position int64 `json:"position"` } func (b BoardList) String() string { return Stringify(b) } +// BoardListAssignee represents a GitLab board list assignee. +// +// GitLab API docs: https://docs.gitlab.com/api/boards/ +type BoardListAssignee struct { + ID int64 `json:"id"` + Name string `json:"name"` + Username string `json:"username"` +} + +func (a BoardListAssignee) String() string { + return Stringify(a) +} + // CreateIssueBoardOptions represents the available CreateIssueBoard() options. // // GitLab API docs: https://docs.gitlab.com/api/boards/#create-an-issue-board @@ -100,192 +158,92 @@ type CreateIssueBoardOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` } -// CreateIssueBoard creates a new issue board. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#create-an-issue-board func (s *IssueBoardsService) CreateIssueBoard(pid any, opt *CreateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - board := new(IssueBoard) - resp, err := s.client.Do(req, board) - if err != nil { - return nil, resp, err - } - - return board, resp, nil + return do[*IssueBoard](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/boards", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateIssueBoardOptions represents the available UpdateIssueBoard() options. // // GitLab API docs: https://docs.gitlab.com/api/boards/#update-an-issue-board type UpdateIssueBoardOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` - Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` - Weight *int `url:"weight,omitempty" json:"weight,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` + Weight *int64 `url:"weight,omitempty" json:"weight,omitempty"` + HideBacklogList *bool `url:"hide_backlog_list,omitempty" json:"hide_backlog_list,omitempty"` + HideClosedList *bool `url:"hide_closed_list,omitempty" json:"hide_closed_list,omitempty"` } -// UpdateIssueBoard update an issue board. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#update-an-issue-board -func (s *IssueBoardsService) UpdateIssueBoard(pid any, board int, opt *UpdateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d", PathEscape(project), board) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - is := new(IssueBoard) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil +func (s *IssueBoardsService) UpdateIssueBoard(pid any, board int64, opt *UpdateIssueBoardOptions, options ...RequestOptionFunc) (*IssueBoard, *Response, error) { + return do[*IssueBoard](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/boards/%d", ProjectID{pid}, board), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteIssueBoard deletes an issue board. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#delete-an-issue-board -func (s *IssueBoardsService) DeleteIssueBoard(pid any, board int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d", PathEscape(project), board) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *IssueBoardsService) DeleteIssueBoard(pid any, board int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/boards/%d", ProjectID{pid}, board), + withRequestOpts(options...), + ) + return resp, err } // ListIssueBoardsOptions represents the available ListIssueBoards() options. // // GitLab API docs: https://docs.gitlab.com/api/boards/#list-project-issue-boards -type ListIssueBoardsOptions ListOptions +type ListIssueBoardsOptions struct { + ListOptions +} -// ListIssueBoards gets a list of all issue boards in a project. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#list-project-issue-boards func (s *IssueBoardsService) ListIssueBoards(pid any, opt *ListIssueBoardsOptions, options ...RequestOptionFunc) ([]*IssueBoard, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var is []*IssueBoard - resp, err := s.client.Do(req, &is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil + return do[[]*IssueBoard](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/boards", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetIssueBoard gets a single issue board of a project. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#show-a-single-issue-board -func (s *IssueBoardsService) GetIssueBoard(pid any, board int, options ...RequestOptionFunc) (*IssueBoard, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d", PathEscape(project), board) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ib := new(IssueBoard) - resp, err := s.client.Do(req, ib) - if err != nil { - return nil, resp, err - } - - return ib, resp, nil +func (s *IssueBoardsService) GetIssueBoard(pid any, board int64, options ...RequestOptionFunc) (*IssueBoard, *Response, error) { + return do[*IssueBoard](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/boards/%d", ProjectID{pid}, board), + withRequestOpts(options...), + ) } // GetIssueBoardListsOptions represents the available GetIssueBoardLists() options. // // GitLab API docs: https://docs.gitlab.com/api/boards/#list-board-lists-in-a-project-issue-board -type GetIssueBoardListsOptions ListOptions - -// GetIssueBoardLists gets a list of the issue board's lists. Does not include -// backlog and closed lists. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#list-board-lists-in-a-project-issue-board -func (s *IssueBoardsService) GetIssueBoardLists(pid any, board int, opt *GetIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d/lists", PathEscape(project), board) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var bl []*BoardList - resp, err := s.client.Do(req, &bl) - if err != nil { - return nil, resp, err - } - - return bl, resp, nil +type GetIssueBoardListsOptions struct { + ListOptions } -// GetIssueBoardList gets a single issue board list. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#show-a-single-board-list -func (s *IssueBoardsService) GetIssueBoardList(pid any, board, list int, options ...RequestOptionFunc) (*BoardList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", - PathEscape(project), - board, - list, +func (s *IssueBoardsService) GetIssueBoardLists(pid any, board int64, opt *GetIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { + return do[[]*BoardList](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/boards/%d/lists", ProjectID{pid}, board), + withAPIOpts(opt), + withRequestOpts(options...), ) +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - bl := new(BoardList) - resp, err := s.client.Do(req, bl) - if err != nil { - return nil, resp, err - } - - return bl, resp, nil +func (s *IssueBoardsService) GetIssueBoardList(pid any, board, list int64, options ...RequestOptionFunc) (*BoardList, *Response, error) { + return do[*BoardList](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/boards/%d/lists/%d", ProjectID{pid}, board, list), + withRequestOpts(options...), + ) } // CreateIssueBoardListOptions represents the available CreateIssueBoardList() @@ -293,34 +251,19 @@ func (s *IssueBoardsService) GetIssueBoardList(pid any, board, list int, options // // GitLab API docs: https://docs.gitlab.com/api/boards/#create-a-board-list type CreateIssueBoardListOptions struct { - LabelID *int `url:"label_id,omitempty" json:"label_id,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` - IterationID *int `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` + LabelID *int64 `url:"label_id,omitempty" json:"label_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + IterationID *int64 `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` } -// CreateIssueBoardList creates a new issue board list. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#create-a-board-list -func (s *IssueBoardsService) CreateIssueBoardList(pid any, board int, opt *CreateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d/lists", PathEscape(project), board) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - bl := new(BoardList) - resp, err := s.client.Do(req, bl) - if err != nil { - return nil, resp, err - } - - return bl, resp, nil +func (s *IssueBoardsService) CreateIssueBoardList(pid any, board int64, opt *CreateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { + return do[*BoardList](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/boards/%d/lists", ProjectID{pid}, board), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateIssueBoardListOptions represents the available UpdateIssueBoardList() @@ -328,57 +271,23 @@ func (s *IssueBoardsService) CreateIssueBoardList(pid any, board int, opt *Creat // // GitLab API docs: https://docs.gitlab.com/api/boards/#reorder-a-list-in-a-board type UpdateIssueBoardListOptions struct { - Position *int `url:"position" json:"position"` + Position *int64 `url:"position" json:"position"` } -// UpdateIssueBoardList updates the position of an existing issue board list. -// -// GitLab API docs: https://docs.gitlab.com/api/boards/#reorder-a-list-in-a-board -func (s *IssueBoardsService) UpdateIssueBoardList(pid any, board, list int, opt *UpdateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", - PathEscape(project), - board, - list, +func (s *IssueBoardsService) UpdateIssueBoardList(pid any, board, list int64, opt *UpdateIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { + return do[*BoardList](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/boards/%d/lists/%d", ProjectID{pid}, board, list), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - bl := new(BoardList) - resp, err := s.client.Do(req, bl) - if err != nil { - return nil, resp, err - } - - return bl, resp, nil } -// DeleteIssueBoardList soft deletes an issue board list. Only for admins and -// project owners. -// -// GitLab API docs: -// https://docs.gitlab.com/api/boards/#delete-a-board-list-from-a-board -func (s *IssueBoardsService) DeleteIssueBoardList(pid any, board, list int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/boards/%d/lists/%d", - PathEscape(project), - board, - list, +func (s *IssueBoardsService) DeleteIssueBoardList(pid any, board, list int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/boards/%d/lists/%d", ProjectID{pid}, board, list), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/branches.go b/vendor/gitlab.com/gitlab-org/api/client-go/branches.go index 1c753b17f..528532c05 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/branches.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/branches.go @@ -17,17 +17,39 @@ package gitlab import ( - "fmt" "net/http" - "net/url" ) type ( BranchesServiceInterface interface { + // ListBranches gets a list of repository branches from a project, sorted by name alphabetically. + // + // GitLab API docs: + // https://docs.gitlab.com/api/branches/#list-repository-branches ListBranches(pid any, opts *ListBranchesOptions, options ...RequestOptionFunc) ([]*Branch, *Response, error) + + // GetBranch gets a single project repository branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/branches/#get-single-repository-branch GetBranch(pid any, branch string, options ...RequestOptionFunc) (*Branch, *Response, error) + + // CreateBranch creates branch from commit SHA or existing branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/branches/#create-repository-branch CreateBranch(pid any, opt *CreateBranchOptions, options ...RequestOptionFunc) (*Branch, *Response, error) + + // DeleteBranch deletes an existing branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/branches/#delete-repository-branch DeleteBranch(pid any, branch string, options ...RequestOptionFunc) (*Response, error) + + // DeleteMergedBranches deletes all branches that are merged into the project's default branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/branches/#delete-merged-branches DeleteMergedBranches(pid any, options ...RequestOptionFunc) (*Response, error) } @@ -71,55 +93,21 @@ type ListBranchesOptions struct { Regex *string `url:"regex,omitempty" json:"regex,omitempty"` } -// ListBranches gets a list of repository branches from a project, sorted by -// name alphabetically. -// -// GitLab API docs: -// https://docs.gitlab.com/api/branches/#list-repository-branches func (s *BranchesService) ListBranches(pid any, opts *ListBranchesOptions, options ...RequestOptionFunc) ([]*Branch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/branches", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var b []*Branch - resp, err := s.client.Do(req, &b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil + return do[[]*Branch](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/branches", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// GetBranch gets a single project repository branch. -// -// GitLab API docs: -// https://docs.gitlab.com/api/branches/#get-single-repository-branch func (s *BranchesService) GetBranch(pid any, branch string, options ...RequestOptionFunc) (*Branch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/branches/%s", PathEscape(project), url.PathEscape(branch)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - b := new(Branch) - resp, err := s.client.Do(req, b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil + return do[*Branch](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/branches/%s", ProjectID{pid}, branch), + withRequestOpts(options...), + ) } // CreateBranchOptions represents the available CreateBranch() options. @@ -131,65 +119,29 @@ type CreateBranchOptions struct { Ref *string `url:"ref,omitempty" json:"ref,omitempty"` } -// CreateBranch creates branch from commit SHA or existing branch. -// -// GitLab API docs: -// https://docs.gitlab.com/api/branches/#create-repository-branch func (s *BranchesService) CreateBranch(pid any, opt *CreateBranchOptions, options ...RequestOptionFunc) (*Branch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/branches", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - b := new(Branch) - resp, err := s.client.Do(req, b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil + return do[*Branch](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/branches", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteBranch deletes an existing branch. -// -// GitLab API docs: -// https://docs.gitlab.com/api/branches/#delete-repository-branch func (s *BranchesService) DeleteBranch(pid any, branch string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/repository/branches/%s", PathEscape(project), url.PathEscape(branch)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/repository/branches/%s", ProjectID{pid}, branch), + withRequestOpts(options...), + ) + return resp, err } -// DeleteMergedBranches deletes all branches that are merged into the project's default branch. -// -// GitLab API docs: -// https://docs.gitlab.com/api/branches/#delete-merged-branches func (s *BranchesService) DeleteMergedBranches(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/repository/merged_branches", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/repository/merged_branches", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/broadcast_messages.go b/vendor/gitlab.com/gitlab-org/api/client-go/broadcast_messages.go index 2e4220086..e40db9d3c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/broadcast_messages.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/broadcast_messages.go @@ -17,18 +17,41 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( BroadcastMessagesServiceInterface interface { + // ListBroadcastMessages gets a list of all broadcasted messages. + // + // GitLab API docs: + // https://docs.gitlab.com/api/broadcast_messages/#get-all-broadcast-messages ListBroadcastMessages(opt *ListBroadcastMessagesOptions, options ...RequestOptionFunc) ([]*BroadcastMessage, *Response, error) - GetBroadcastMessage(broadcast int, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) + + // GetBroadcastMessage gets a single broadcast message. + // + // GitLab API docs: + // https://docs.gitlab.com/api/broadcast_messages/#get-a-specific-broadcast-message + GetBroadcastMessage(broadcast int64, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) + + // CreateBroadcastMessage creates a message to broadcast. + // + // GitLab API docs: + // https://docs.gitlab.com/api/broadcast_messages/#create-a-broadcast-message CreateBroadcastMessage(opt *CreateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) - UpdateBroadcastMessage(broadcast int, opt *UpdateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) - DeleteBroadcastMessage(broadcast int, options ...RequestOptionFunc) (*Response, error) + + // UpdateBroadcastMessage updates a broadcasted message. + // + // GitLab API docs: + // https://docs.gitlab.com/api/broadcast_messages/#update-a-broadcast-message + UpdateBroadcastMessage(broadcast int64, opt *UpdateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) + + // DeleteBroadcastMessage deletes a broadcasted message. + // + // GitLab API docs: + // https://docs.gitlab.com/api/broadcast_messages/#delete-a-broadcast-message + DeleteBroadcastMessage(broadcast int64, options ...RequestOptionFunc) (*Response, error) } // BroadcastMessagesService handles communication with the broadcast @@ -51,7 +74,7 @@ type BroadcastMessage struct { StartsAt *time.Time `json:"starts_at"` EndsAt *time.Time `json:"ends_at"` Font string `json:"font"` - ID int `json:"id"` + ID int64 `json:"id"` Active bool `json:"active"` TargetAccessLevels []AccessLevelValue `json:"target_access_levels"` TargetPath string `json:"target_path"` @@ -65,46 +88,25 @@ type BroadcastMessage struct { // // GitLab API docs: // https://docs.gitlab.com/api/broadcast_messages/#get-all-broadcast-messages -type ListBroadcastMessagesOptions ListOptions +type ListBroadcastMessagesOptions struct { + ListOptions +} -// ListBroadcastMessages gets a list of all broadcasted messages. -// -// GitLab API docs: -// https://docs.gitlab.com/api/broadcast_messages/#get-all-broadcast-messages func (s *BroadcastMessagesService) ListBroadcastMessages(opt *ListBroadcastMessagesOptions, options ...RequestOptionFunc) ([]*BroadcastMessage, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "broadcast_messages", opt, options) - if err != nil { - return nil, nil, err - } - - var bs []*BroadcastMessage - resp, err := s.client.Do(req, &bs) - if err != nil { - return nil, resp, err - } - - return bs, resp, nil + return do[[]*BroadcastMessage](s.client, + withMethod(http.MethodGet), + withPath("broadcast_messages"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetBroadcastMessage gets a single broadcast message. -// -// GitLab API docs: -// https://docs.gitlab.com/api/broadcast_messages/#get-a-specific-broadcast-message -func (s *BroadcastMessagesService) GetBroadcastMessage(broadcast int, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) { - u := fmt.Sprintf("broadcast_messages/%d", broadcast) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - b := new(BroadcastMessage) - resp, err := s.client.Do(req, &b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil +func (s *BroadcastMessagesService) GetBroadcastMessage(broadcast int64, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) { + return do[*BroadcastMessage](s.client, + withMethod(http.MethodGet), + withPath("broadcast_messages/%d", broadcast), + withRequestOpts(options...), + ) } // CreateBroadcastMessageOptions represents the available CreateBroadcastMessage() @@ -124,23 +126,13 @@ type CreateBroadcastMessageOptions struct { Theme *string `url:"theme,omitempty" json:"theme,omitempty"` } -// CreateBroadcastMessage creates a message to broadcast. -// -// GitLab API docs: -// https://docs.gitlab.com/api/broadcast_messages/#create-a-broadcast-message func (s *BroadcastMessagesService) CreateBroadcastMessage(opt *CreateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "broadcast_messages", opt, options) - if err != nil { - return nil, nil, err - } - - b := new(BroadcastMessage) - resp, err := s.client.Do(req, &b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil + return do[*BroadcastMessage](s.client, + withMethod(http.MethodPost), + withPath("broadcast_messages"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateBroadcastMessageOptions represents the available CreateBroadcastMessage() @@ -160,38 +152,20 @@ type UpdateBroadcastMessageOptions struct { Theme *string `url:"theme,omitempty" json:"theme,omitempty"` } -// UpdateBroadcastMessage update a broadcasted message. -// -// GitLab API docs: -// https://docs.gitlab.com/api/broadcast_messages/#update-a-broadcast-message -func (s *BroadcastMessagesService) UpdateBroadcastMessage(broadcast int, opt *UpdateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) { - u := fmt.Sprintf("broadcast_messages/%d", broadcast) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - b := new(BroadcastMessage) - resp, err := s.client.Do(req, &b) - if err != nil { - return nil, resp, err - } - - return b, resp, nil +func (s *BroadcastMessagesService) UpdateBroadcastMessage(broadcast int64, opt *UpdateBroadcastMessageOptions, options ...RequestOptionFunc) (*BroadcastMessage, *Response, error) { + return do[*BroadcastMessage](s.client, + withMethod(http.MethodPut), + withPath("broadcast_messages/%d", broadcast), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteBroadcastMessage deletes a broadcasted message. -// -// GitLab API docs: -// https://docs.gitlab.com/api/broadcast_messages/#delete-a-broadcast-message -func (s *BroadcastMessagesService) DeleteBroadcastMessage(broadcast int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("broadcast_messages/%d", broadcast) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *BroadcastMessagesService) DeleteBroadcastMessage(broadcast int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("broadcast_messages/%d", broadcast), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/buf.gen.yaml b/vendor/gitlab.com/gitlab-org/api/client-go/buf.gen.yaml index 897db7737..dd0e5916d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/buf.gen.yaml +++ b/vendor/gitlab.com/gitlab-org/api/client-go/buf.gen.yaml @@ -1,6 +1,6 @@ version: v2 plugins: - - remote: buf.build/protocolbuffers/go:v1.36.6 + - local: ["go", "run", "google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.10"] out: . opt: - paths=source_relative diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/bulk_imports.go b/vendor/gitlab.com/gitlab-org/api/client-go/bulk_imports.go index 70464498e..fe5f319dc 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/bulk_imports.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/bulk_imports.go @@ -52,7 +52,7 @@ type BulkImportStartMigrationOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/bulk_imports/#start-a-new-group-or-project-migration type BulkImportStartMigrationResponse struct { - ID int `json:"id"` + ID int64 `json:"id"` Status string `json:"status"` SourceType string `json:"source_type"` SourceURL string `json:"source_url"` @@ -61,20 +61,11 @@ type BulkImportStartMigrationResponse struct { HasFailures bool `json:"has_failures"` } -// StartMigration starts a migration. -// -// GitLab API docs: https://docs.gitlab.com/api/bulk_imports/#start-a-new-group-or-project-migration func (b *BulkImportsService) StartMigration(startMigrationOptions *BulkImportStartMigrationOptions, options ...RequestOptionFunc) (*BulkImportStartMigrationResponse, *Response, error) { - request, err := b.client.NewRequest(http.MethodPost, "bulk_imports", startMigrationOptions, options) - if err != nil { - return nil, nil, err - } - - startMigrationResponse := new(BulkImportStartMigrationResponse) - response, err := b.client.Do(request, startMigrationResponse) - if err != nil { - return nil, response, err - } - - return startMigrationResponse, response, nil + return do[*BulkImportStartMigrationResponse](b.client, + withMethod(http.MethodPost), + withPath("bulk_imports"), + withAPIOpts(startMigrationOptions), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/ci_yml_templates.go b/vendor/gitlab.com/gitlab-org/api/client-go/ci_yml_templates.go index 168ca1fc4..f57621ee6 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/ci_yml_templates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/ci_yml_templates.go @@ -17,13 +17,21 @@ package gitlab import ( - "fmt" "net/http" ) type ( CIYMLTemplatesServiceInterface interface { + // ListAllTemplates get all GitLab CI YML templates. + // + // GitLab API docs: + // https://docs.gitlab.com/api/templates/gitlab_ci_ymls/#list-gitlab-ci-yaml-templates ListAllTemplates(opt *ListCIYMLTemplatesOptions, options ...RequestOptionFunc) ([]*CIYMLTemplateListItem, *Response, error) + + // GetTemplate get a single GitLab CI YML template. + // + // GitLab API docs: + // https://docs.gitlab.com/api/templates/gitlab_ci_ymls/#single-gitlab-ci-yaml-template GetTemplate(key string, options ...RequestOptionFunc) (*CIYMLTemplate, *Response, error) } @@ -61,44 +69,23 @@ type CIYMLTemplateListItem struct { // // GitLab API docs: // https://docs.gitlab.com/api/templates/gitlab_ci_ymls/#list-gitlab-ci-yaml-templates -type ListCIYMLTemplatesOptions ListOptions +type ListCIYMLTemplatesOptions struct { + ListOptions +} -// ListAllTemplates get all GitLab CI YML templates. -// -// GitLab API docs: -// https://docs.gitlab.com/api/templates/gitlab_ci_ymls/#list-gitlab-ci-yaml-templates func (s *CIYMLTemplatesService) ListAllTemplates(opt *ListCIYMLTemplatesOptions, options ...RequestOptionFunc) ([]*CIYMLTemplateListItem, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "templates/gitlab_ci_ymls", opt, options) - if err != nil { - return nil, nil, err - } - - var cts []*CIYMLTemplateListItem - resp, err := s.client.Do(req, &cts) - if err != nil { - return nil, resp, err - } - - return cts, resp, nil + return do[[]*CIYMLTemplateListItem](s.client, + withMethod(http.MethodGet), + withPath("templates/gitlab_ci_ymls"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetTemplate get a single GitLab CI YML template. -// -// GitLab API docs: -// https://docs.gitlab.com/api/templates/gitlab_ci_ymls/#single-gitlab-ci-yaml-template func (s *CIYMLTemplatesService) GetTemplate(key string, options ...RequestOptionFunc) (*CIYMLTemplate, *Response, error) { - u := fmt.Sprintf("templates/gitlab_ci_ymls/%s", PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ct := new(CIYMLTemplate) - resp, err := s.client.Do(req, ct) - if err != nil { - return nil, resp, err - } - - return ct, resp, nil + return do[*CIYMLTemplate](s.client, + withMethod(http.MethodGet), + withPath("templates/gitlab_ci_ymls/%s", key), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/client_options.go b/vendor/gitlab.com/gitlab-org/api/client-go/client_options.go index 57a7f2024..b416acac1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/client_options.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/client_options.go @@ -17,7 +17,8 @@ package gitlab import ( - "fmt" + "errors" + "log/slog" "net/http" "time" @@ -150,6 +151,19 @@ func WithUserAgent(userAgent string) ClientOptionFunc { } } +// WithURLWarningLogger sets a custom logger for URL validation warnings. +// By default, warnings are logged using slog.Default(). +// Pass slog.New(slog.DiscardHandler) to disable warnings. +func WithURLWarningLogger(logger *slog.Logger) ClientOptionFunc { + return func(c *Client) error { + if logger == nil { + return errors.New("logger cannot be nil, use slog.New(slog.DiscardHandler) to discard warnings") + } + c.urlWarningLogger = logger + return nil + } +} + // WithCookieJar can be used to configure a cookie jar. func WithCookieJar(jar http.CookieJar) ClientOptionFunc { return func(c *Client) error { @@ -163,7 +177,7 @@ func WithCookieJar(jar http.CookieJar) ClientOptionFunc { func WithInterceptor(i Interceptor) ClientOptionFunc { return func(c *Client) error { if i == nil { - return fmt.Errorf("interceptor cannot be nil") + return errors.New("interceptor cannot be nil") } c.interceptors = append(c.interceptors, i) return nil diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/cluster_agents.go b/vendor/gitlab.com/gitlab-org/api/client-go/cluster_agents.go index 88855174d..bd124bc44 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/cluster_agents.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/cluster_agents.go @@ -17,21 +17,63 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ClusterAgentsServiceInterface interface { + // ListAgents returns a list of agents registered for the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#list-the-agents-for-a-project + // ListAgents returns a list of agents registered for the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#list-the-agents-for-a-project ListAgents(pid any, opt *ListAgentsOptions, options ...RequestOptionFunc) ([]*Agent, *Response, error) - GetAgent(pid any, id int, options ...RequestOptionFunc) (*Agent, *Response, error) + + // GetAgent gets a single agent details. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#get-details-about-an-agent + GetAgent(pid any, id int64, options ...RequestOptionFunc) (*Agent, *Response, error) + + // RegisterAgent registers an agent to the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#register-an-agent-with-a-project RegisterAgent(pid any, opt *RegisterAgentOptions, options ...RequestOptionFunc) (*Agent, *Response, error) - DeleteAgent(pid any, id int, options ...RequestOptionFunc) (*Response, error) - ListAgentTokens(pid any, aid int, opt *ListAgentTokensOptions, options ...RequestOptionFunc) ([]*AgentToken, *Response, error) - GetAgentToken(pid any, aid int, id int, options ...RequestOptionFunc) (*AgentToken, *Response, error) - CreateAgentToken(pid any, aid int, opt *CreateAgentTokenOptions, options ...RequestOptionFunc) (*AgentToken, *Response, error) - RevokeAgentToken(pid any, aid int, id int, options ...RequestOptionFunc) (*Response, error) + + // DeleteAgent deletes an existing agent registration. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#delete-a-registered-agent + DeleteAgent(pid any, id int64, options ...RequestOptionFunc) (*Response, error) + + // ListAgentTokens returns a list of tokens for an agent. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#list-tokens-for-an-agent + ListAgentTokens(pid any, aid int64, opt *ListAgentTokensOptions, options ...RequestOptionFunc) ([]*AgentToken, *Response, error) + + // GetAgentToken gets a single agent token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#get-a-single-agent-token + GetAgentToken(pid any, aid int64, id int64, options ...RequestOptionFunc) (*AgentToken, *Response, error) + + // CreateAgentToken creates a new token for an agent. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#create-an-agent-token + CreateAgentToken(pid any, aid int64, opt *CreateAgentTokenOptions, options ...RequestOptionFunc) (*AgentToken, *Response, error) + + // RevokeAgentToken revokes an agent token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/cluster_agents/#revoke-an-agent-token + RevokeAgentToken(pid any, aid int64, id int64, options ...RequestOptionFunc) (*Response, error) } // ClusterAgentsService handles communication with the cluster agents related @@ -49,15 +91,15 @@ var _ ClusterAgentsServiceInterface = (*ClusterAgentsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/cluster_agents/ type Agent struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` CreatedAt *time.Time `json:"created_at"` - CreatedByUserID int `json:"created_by_user_id"` + CreatedByUserID int64 `json:"created_by_user_id"` ConfigProject ConfigProject `json:"config_project"` } type ConfigProject struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -75,13 +117,13 @@ func (a Agent) String() string { // GitLab API docs: // https://docs.gitlab.com/api/cluster_agents/#list-tokens-for-an-agent type AgentToken struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Description string `json:"description"` - AgentID int `json:"agent_id"` + AgentID int64 `json:"agent_id"` Status string `json:"status"` CreatedAt *time.Time `json:"created_at"` - CreatedByUserID int `json:"created_by_user_id"` + CreatedByUserID int64 `json:"created_by_user_id"` LastUsedAt *time.Time `json:"last_used_at"` Token string `json:"token"` } @@ -94,56 +136,23 @@ func (a AgentToken) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/cluster_agents/#list-the-agents-for-a-project -type ListAgentsOptions ListOptions +type ListAgentsOptions struct { + ListOptions +} -// ListAgents returns a list of agents registered for the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#list-the-agents-for-a-project func (s *ClusterAgentsService) ListAgents(pid any, opt *ListAgentsOptions, options ...RequestOptionFunc) ([]*Agent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, uri, opt, options) - if err != nil { - return nil, nil, err - } - - var as []*Agent - resp, err := s.client.Do(req, &as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[[]*Agent](s.client, + withPath("projects/%s/cluster_agents", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetAgent gets a single agent details. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#get-details-about-an-agent -func (s *ClusterAgentsService) GetAgent(pid any, id int, options ...RequestOptionFunc) (*Agent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodGet, uri, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(Agent) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil +func (s *ClusterAgentsService) GetAgent(pid any, id int64, options ...RequestOptionFunc) (*Agent, *Response, error) { + return do[*Agent](s.client, + withPath("projects/%s/cluster_agents/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) } // RegisterAgentOptions represents the available RegisterAgent() @@ -155,104 +164,47 @@ type RegisterAgentOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` } -// RegisterAgent registers an agent to the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#register-an-agent-with-a-project func (s *ClusterAgentsService) RegisterAgent(pid any, opt *RegisterAgentOptions, options ...RequestOptionFunc) (*Agent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, uri, opt, options) - if err != nil { - return nil, nil, err - } - - a := new(Agent) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil + return do[*Agent](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/cluster_agents", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteAgent deletes an existing agent registration. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#delete-a-registered-agent -func (s *ClusterAgentsService) DeleteAgent(pid any, id int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodDelete, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ClusterAgentsService) DeleteAgent(pid any, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/cluster_agents/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) + return resp, err } // ListAgentTokensOptions represents the available ListAgentTokens() options. // // GitLab API docs: // https://docs.gitlab.com/api/cluster_agents/#list-tokens-for-an-agent -type ListAgentTokensOptions ListOptions - -// ListAgentTokens returns a list of tokens for an agent. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#list-tokens-for-an-agent -func (s *ClusterAgentsService) ListAgentTokens(pid any, aid int, opt *ListAgentTokensOptions, options ...RequestOptionFunc) ([]*AgentToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d/tokens", PathEscape(project), aid) - - req, err := s.client.NewRequest(http.MethodGet, uri, opt, options) - if err != nil { - return nil, nil, err - } - - var ats []*AgentToken - resp, err := s.client.Do(req, &ats) - if err != nil { - return nil, resp, err - } - - return ats, resp, nil +type ListAgentTokensOptions struct { + ListOptions } -// GetAgentToken gets a single agent token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#get-a-single-agent-token -func (s *ClusterAgentsService) GetAgentToken(pid any, aid int, id int, options ...RequestOptionFunc) (*AgentToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d/tokens/%d", PathEscape(project), aid, id) - - req, err := s.client.NewRequest(http.MethodGet, uri, nil, options) - if err != nil { - return nil, nil, err - } - - at := new(AgentToken) - resp, err := s.client.Do(req, at) - if err != nil { - return nil, resp, err - } +func (s *ClusterAgentsService) ListAgentTokens(pid any, aid int64, opt *ListAgentTokensOptions, options ...RequestOptionFunc) ([]*AgentToken, *Response, error) { + return do[[]*AgentToken](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/cluster_agents/%d/tokens", ProjectID{pid}, aid), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - return at, resp, nil +func (s *ClusterAgentsService) GetAgentToken(pid any, aid int64, id int64, options ...RequestOptionFunc) (*AgentToken, *Response, error) { + return do[*AgentToken](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/cluster_agents/%d/tokens/%d", ProjectID{pid}, aid, id), + withRequestOpts(options...), + ) } // CreateAgentTokenOptions represents the available CreateAgentToken() options. @@ -264,46 +216,20 @@ type CreateAgentTokenOptions struct { Description *string `url:"description,omitempty" json:"description,omitempty"` } -// CreateAgentToken creates a new token for an agent. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#create-an-agent-token -func (s *ClusterAgentsService) CreateAgentToken(pid any, aid int, opt *CreateAgentTokenOptions, options ...RequestOptionFunc) (*AgentToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d/tokens", PathEscape(project), aid) - - req, err := s.client.NewRequest(http.MethodPost, uri, opt, options) - if err != nil { - return nil, nil, err - } - - at := new(AgentToken) - resp, err := s.client.Do(req, at) - if err != nil { - return nil, resp, err - } - - return at, resp, nil +func (s *ClusterAgentsService) CreateAgentToken(pid any, aid int64, opt *CreateAgentTokenOptions, options ...RequestOptionFunc) (*AgentToken, *Response, error) { + return do[*AgentToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/cluster_agents/%d/tokens", ProjectID{pid}, aid), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// RevokeAgentToken revokes an agent token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/cluster_agents/#revoke-an-agent-token -func (s *ClusterAgentsService) RevokeAgentToken(pid any, aid int, id int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/cluster_agents/%d/tokens/%d", PathEscape(project), aid, id) - - req, err := s.client.NewRequest(http.MethodDelete, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ClusterAgentsService) RevokeAgentToken(pid any, aid int64, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/cluster_agents/%d/tokens/%d", ProjectID{pid}, aid, id), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/commits.go b/vendor/gitlab.com/gitlab-org/api/client-go/commits.go index c139bdf86..36e678461 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/commits.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/commits.go @@ -17,9 +17,8 @@ package gitlab import ( - "fmt" + "errors" "net/http" - "net/url" "time" ) @@ -29,18 +28,85 @@ import ( // GitLab API docs: https://docs.gitlab.com/api/commits/ type ( CommitsServiceInterface interface { + // ListCommits gets a list of repository commits in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#list-repository-commits ListCommits(pid any, opt *ListCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) + + // GetCommitRefs gets all references (from branches or tags) a commit is pushed to. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#get-references-a-commit-is-pushed-to GetCommitRefs(pid any, sha string, opt *GetCommitRefsOptions, options ...RequestOptionFunc) ([]*CommitRef, *Response, error) + + // GetCommit gets a specific commit identified by the commit hash or name of a + // branch or tag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#get-a-single-commit GetCommit(pid any, sha string, opt *GetCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) + + // CreateCommit creates a commit with multiple files and actions. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#create-a-commit-with-multiple-files-and-actions CreateCommit(pid any, opt *CreateCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) + + // GetCommitDiff gets the diff of a commit in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#get-the-diff-of-a-commit GetCommitDiff(pid any, sha string, opt *GetCommitDiffOptions, options ...RequestOptionFunc) ([]*Diff, *Response, error) + + // GetCommitComments gets the comments of a commit in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#get-the-comments-of-a-commit GetCommitComments(pid any, sha string, opt *GetCommitCommentsOptions, options ...RequestOptionFunc) ([]*CommitComment, *Response, error) + + // PostCommitComment adds a comment to a commit. Optionally you can post + // comments on a specific line of a commit. Therefore both path, line_new and + // line_old are required. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#post-comment-to-commit PostCommitComment(pid any, sha string, opt *PostCommitCommentOptions, options ...RequestOptionFunc) (*CommitComment, *Response, error) + + // GetCommitStatuses gets the statuses of a commit in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#list-the-statuses-of-a-commit GetCommitStatuses(pid any, sha string, opt *GetCommitStatusesOptions, options ...RequestOptionFunc) ([]*CommitStatus, *Response, error) + + // SetCommitStatus sets the status of a commit in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#set-the-pipeline-status-of-a-commit SetCommitStatus(pid any, sha string, opt *SetCommitStatusOptions, options ...RequestOptionFunc) (*CommitStatus, *Response, error) + + // ListMergeRequestsByCommit gets merge request associated with a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#list-merge-requests-associated-with-a-commit ListMergeRequestsByCommit(pid any, sha string, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) + + // CherryPickCommit cherry picks a commit to a given branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#cherry-pick-a-commit CherryPickCommit(pid any, sha string, opt *CherryPickCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) + + // RevertCommit reverts a commit in a given branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#revert-a-commit RevertCommit(pid any, sha string, opt *RevertCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) + + // GetGPGSignature gets a GPG signature of a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/commits/#get-signature-of-a-commit GetGPGSignature(pid any, sha string, options ...RequestOptionFunc) (*GPGSignature, *Response, error) } @@ -74,7 +140,7 @@ type Commit struct { Stats *CommitStats `json:"stats"` Status *BuildStateValue `json:"status"` LastPipeline *PipelineInfo `json:"last_pipeline"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Trailers map[string]string `json:"trailers"` ExtendedTrailers map[string]string `json:"extended_trailers"` WebURL string `json:"web_url"` @@ -84,9 +150,9 @@ type Commit struct { // // GitLab API docs: https://docs.gitlab.com/api/commits/ type CommitStats struct { - Additions int `json:"additions"` - Deletions int `json:"deletions"` - Total int `json:"total"` + Additions int64 `json:"additions"` + Deletions int64 `json:"deletions"` + Total int64 `json:"total"` } func (c Commit) String() string { @@ -109,28 +175,13 @@ type ListCommitsOptions struct { Trailers *bool `url:"trailers,omitempty" json:"trailers,omitempty"` } -// ListCommits gets a list of repository commits in a project. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#list-repository-commits func (s *CommitsService) ListCommits(pid any, opt *ListCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var c []*Commit - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[[]*Commit](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CommitRef represents the reference of branches/tags in a commit. @@ -151,29 +202,13 @@ type GetCommitRefsOptions struct { Type *string `url:"type,omitempty" json:"type,omitempty"` } -// GetCommitRefs gets all references (from branches or tags) a commit is pushed to -// -// GitLab API docs: -// https://docs.gitlab.com/api/commits/#get-references-a-commit-is-pushed-to func (s *CommitsService) GetCommitRefs(pid any, sha string, opt *GetCommitRefsOptions, options ...RequestOptionFunc) ([]*CommitRef, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/refs", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var cs []*CommitRef - resp, err := s.client.Do(req, &cs) - if err != nil { - return nil, resp, err - } - - return cs, resp, nil + return do[[]*CommitRef](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/refs", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetCommitOptions represents the available GetCommit() options. @@ -184,32 +219,17 @@ type GetCommitOptions struct { Stats *bool `url:"stats,omitempty" json:"stats,omitempty"` } -// GetCommit gets a specific commit identified by the commit hash or name of a -// branch or tag. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#get-a-single-commit func (s *CommitsService) GetCommit(pid any, sha string, opt *GetCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } if sha == "" { - return nil, nil, fmt.Errorf("SHA must be a non-empty string") + return nil, nil, errors.New("SHA must be a non-empty string") } - u := fmt.Sprintf("projects/%s/repository/commits/%s", PathEscape(project), url.PathEscape(sha)) - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Commit) - resp, err := s.client.Do(req, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*Commit](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateCommitOptions represents the available options for a new commit. @@ -242,28 +262,13 @@ type CommitActionOptions struct { ExecuteFilemode *bool `url:"execute_filemode,omitempty" json:"execute_filemode,omitempty"` } -// CreateCommit creates a commit with multiple files and actions. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#create-a-commit-with-multiple-files-and-actions func (s *CommitsService) CreateCommit(pid any, opt *CreateCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Commit) - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*Commit](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // Diff represents a GitLab diff. @@ -293,29 +298,13 @@ type GetCommitDiffOptions struct { Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"` } -// GetCommitDiff gets the diff of a commit in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/commits/#get-the-diff-of-a-commit func (s *CommitsService) GetCommitDiff(pid any, sha string, opt *GetCommitDiffOptions, options ...RequestOptionFunc) ([]*Diff, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/diff", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var d []*Diff - resp, err := s.client.Do(req, &d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil + return do[[]*Diff](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/diff", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CommitComment represents a GitLab commit comment. @@ -324,14 +313,14 @@ func (s *CommitsService) GetCommitDiff(pid any, sha string, opt *GetCommitDiffOp type CommitComment struct { Note string `json:"note"` Path string `json:"path"` - Line int `json:"line"` + Line int64 `json:"line"` LineType string `json:"line_type"` Author Author `json:"author"` } // Author represents a GitLab commit author type Author struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Email string `json:"email"` Name string `json:"name"` @@ -348,31 +337,17 @@ func (c CommitComment) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/commits/#get-the-comments-of-a-commit -type GetCommitCommentsOptions ListOptions +type GetCommitCommentsOptions struct { + ListOptions +} -// GetCommitComments gets the comments of a commit in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/commits/#get-the-comments-of-a-commit func (s *CommitsService) GetCommitComments(pid any, sha string, opt *GetCommitCommentsOptions, options ...RequestOptionFunc) ([]*CommitComment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var c []*CommitComment - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[[]*CommitComment](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/comments", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // PostCommitCommentOptions represents the available PostCommitComment() @@ -383,35 +358,17 @@ func (s *CommitsService) GetCommitComments(pid any, sha string, opt *GetCommitCo type PostCommitCommentOptions struct { Note *string `url:"note,omitempty" json:"note,omitempty"` Path *string `url:"path" json:"path"` - Line *int `url:"line" json:"line"` + Line *int64 `url:"line" json:"line"` LineType *string `url:"line_type" json:"line_type"` } -// PostCommitComment adds a comment to a commit. Optionally you can post -// comments on a specific line of a commit. Therefor both path, line_new and -// line_old are required. -// -// GitLab API docs: -// https://docs.gitlab.com/api/commits/#post-comment-to-commit func (s *CommitsService) PostCommitComment(pid any, sha string, opt *PostCommitCommentOptions, options ...RequestOptionFunc) (*CommitComment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(CommitComment) - resp, err := s.client.Do(req, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*CommitComment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits/%s/comments", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetCommitStatusesOptions represents the available GetCommitStatuses() options. @@ -422,7 +379,7 @@ type GetCommitStatusesOptions struct { Ref *string `url:"ref,omitempty" json:"ref,omitempty"` Stage *string `url:"stage,omitempty" json:"stage,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` - PipelineID *int `url:"pipeline_id,omitempty" json:"pipeline_id,omitempty"` + PipelineID *int64 `url:"pipeline_id,omitempty" json:"pipeline_id,omitempty"` All *bool `url:"all,omitempty" json:"all,omitempty"` } @@ -430,7 +387,7 @@ type GetCommitStatusesOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/commits/#commit-status type CommitStatus struct { - ID int `json:"id"` + ID int64 `json:"id"` SHA string `json:"sha"` Ref string `json:"ref"` Status string `json:"status"` @@ -440,34 +397,19 @@ type CommitStatus struct { Name string `json:"name"` AllowFailure bool `json:"allow_failure"` Coverage float64 `json:"coverage"` - PipelineId int `json:"pipeline_id"` + PipelineID int64 `json:"pipeline_id"` Author Author `json:"author"` Description string `json:"description"` TargetURL string `json:"target_url"` } -// GetCommitStatuses gets the statuses of a commit in a project. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#list-the-statuses-of-a-commit func (s *CommitsService) GetCommitStatuses(pid any, sha string, opt *GetCommitStatusesOptions, options ...RequestOptionFunc) ([]*CommitStatus, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/statuses", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var cs []*CommitStatus - resp, err := s.client.Do(req, &cs) - if err != nil { - return nil, resp, err - } - - return cs, resp, nil + return do[[]*CommitStatus](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/statuses", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SetCommitStatusOptions represents the available SetCommitStatus() options. @@ -481,56 +423,24 @@ type SetCommitStatusOptions struct { TargetURL *string `url:"target_url,omitempty" json:"target_url,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` Coverage *float64 `url:"coverage,omitempty" json:"coverage,omitempty"` - PipelineID *int `url:"pipeline_id,omitempty" json:"pipeline_id,omitempty"` + PipelineID *int64 `url:"pipeline_id,omitempty" json:"pipeline_id,omitempty"` } -// SetCommitStatus sets the status of a commit in a project. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#set-the-pipeline-status-of-a-commit func (s *CommitsService) SetCommitStatus(pid any, sha string, opt *SetCommitStatusOptions, options ...RequestOptionFunc) (*CommitStatus, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/statuses/%s", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - cs := new(CommitStatus) - resp, err := s.client.Do(req, &cs) - if err != nil { - return nil, resp, err - } - - return cs, resp, nil + return do[*CommitStatus](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/statuses/%s", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListMergeRequestsByCommit gets merge request associated with a commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/commits/#list-merge-requests-associated-with-a-commit func (s *CommitsService) ListMergeRequestsByCommit(pid any, sha string, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/merge_requests", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var mrs []*BasicMergeRequest - resp, err := s.client.Do(req, &mrs) - if err != nil { - return nil, resp, err - } - - return mrs, resp, nil + return do[[]*BasicMergeRequest](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/merge_requests", ProjectID{pid}, sha), + withRequestOpts(options...), + ) } // CherryPickCommitOptions represents the available CherryPickCommit() options. @@ -542,94 +452,47 @@ type CherryPickCommitOptions struct { Message *string `url:"message,omitempty" json:"message,omitempty"` } -// CherryPickCommit cherry picks a commit to a given branch. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#cherry-pick-a-commit -func (s *CommitsService) CherryPickCommit(pid any, sha string, opt *CherryPickCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/cherry_pick", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Commit) - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil -} - // RevertCommitOptions represents the available RevertCommit() options. -// // GitLab API docs: https://docs.gitlab.com/api/commits/#revert-a-commit type RevertCommitOptions struct { Branch *string `url:"branch,omitempty" json:"branch,omitempty"` } -// RevertCommit reverts a commit in a given branch. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#revert-a-commit -func (s *CommitsService) RevertCommit(pid any, sha string, opt *RevertCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/revert", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Commit) - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } +func (s *CommitsService) CherryPickCommit(pid any, sha string, opt *CherryPickCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { + return do[*Commit](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits/%s/cherry_pick", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - return c, resp, nil +func (s *CommitsService) RevertCommit(pid any, sha string, opt *RevertCommitOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { + return do[*Commit](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits/%s/revert", ProjectID{pid}, sha), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GPGSignature represents a Gitlab commit's GPG Signature. +// GPGSignature represents a GitLab commit's GPG Signature. // // GitLab API docs: // https://docs.gitlab.com/api/commits/#get-signature-of-a-commit type GPGSignature struct { - KeyID int `json:"gpg_key_id"` + KeyID int64 `json:"gpg_key_id"` KeyPrimaryKeyID string `json:"gpg_key_primary_keyid"` KeyUserName string `json:"gpg_key_user_name"` KeyUserEmail string `json:"gpg_key_user_email"` VerificationStatus string `json:"verification_status"` - KeySubkeyID int `json:"gpg_key_subkey_id"` + KeySubkeyID int64 `json:"gpg_key_subkey_id"` } -// GetGPGSignature gets a GPG signature of a commit. -// -// GitLab API docs: https://docs.gitlab.com/api/commits/#get-signature-of-a-commit func (s *CommitsService) GetGPGSignature(pid any, sha string, options ...RequestOptionFunc) (*GPGSignature, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/signature", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - sig := new(GPGSignature) - resp, err := s.client.Do(req, &sig) - if err != nil { - return nil, resp, err - } - - return sig, resp, nil + return do[*GPGSignature](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/repository/commits/%s/signature", ProjectID{pid}, sha), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/container_registry.go b/vendor/gitlab.com/gitlab-org/api/client-go/container_registry.go index 4e473ee0e..5ebe2664d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/container_registry.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/container_registry.go @@ -17,21 +17,59 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ContainerRegistryServiceInterface interface { - ListProjectRegistryRepositories(pid any, opt *ListRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) - ListGroupRegistryRepositories(gid any, opt *ListRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) + // ListProjectRegistryRepositories gets a list of registry repositories in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#within-a-project + ListProjectRegistryRepositories(pid any, opt *ListProjectRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) + + // ListGroupRegistryRepositories gets a list of registry repositories in a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#within-a-group + ListGroupRegistryRepositories(gid any, opt *ListGroupRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) + + // GetSingleRegistryRepository gets the details of single registry repository. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#get-details-of-a-single-repository GetSingleRegistryRepository(pid any, opt *GetSingleRegistryRepositoryOptions, options ...RequestOptionFunc) (*RegistryRepository, *Response, error) - DeleteRegistryRepository(pid any, repository int, options ...RequestOptionFunc) (*Response, error) - ListRegistryRepositoryTags(pid any, repository int, opt *ListRegistryRepositoryTagsOptions, options ...RequestOptionFunc) ([]*RegistryRepositoryTag, *Response, error) - GetRegistryRepositoryTagDetail(pid any, repository int, tagName string, options ...RequestOptionFunc) (*RegistryRepositoryTag, *Response, error) - DeleteRegistryRepositoryTag(pid any, repository int, tagName string, options ...RequestOptionFunc) (*Response, error) - DeleteRegistryRepositoryTags(pid any, repository int, opt *DeleteRegistryRepositoryTagsOptions, options ...RequestOptionFunc) (*Response, error) + + // DeleteRegistryRepository deletes a repository in a registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#delete-registry-repository + DeleteRegistryRepository(pid any, repository int64, options ...RequestOptionFunc) (*Response, error) + + // ListRegistryRepositoryTags gets a list of tags for given registry repository. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#list-registry-repository-tags + ListRegistryRepositoryTags(pid any, repository int64, opt *ListRegistryRepositoryTagsOptions, options ...RequestOptionFunc) ([]*RegistryRepositoryTag, *Response, error) + + // GetRegistryRepositoryTagDetail get details of a registry repository tag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#get-details-of-a-registry-repository-tag + GetRegistryRepositoryTagDetail(pid any, repository int64, tagName string, options ...RequestOptionFunc) (*RegistryRepositoryTag, *Response, error) + + // DeleteRegistryRepositoryTag deletes a registry repository tag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#delete-a-registry-repository-tag + DeleteRegistryRepositoryTag(pid any, repository int64, tagName string, options ...RequestOptionFunc) (*Response, error) + + // DeleteRegistryRepositoryTags deletes repository tags in bulk based on given criteria. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_registry/#delete-registry-repository-tags-in-bulk + DeleteRegistryRepositoryTags(pid any, repository int64, opt *DeleteRegistryRepositoryTagsOptions, options ...RequestOptionFunc) (*Response, error) } // ContainerRegistryService handles communication with the container registry @@ -49,15 +87,15 @@ var _ ContainerRegistryServiceInterface = (*ContainerRegistryService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/container_registry/ type RegistryRepository struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Path string `json:"path"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Location string `json:"location"` CreatedAt *time.Time `json:"created_at"` CleanupPolicyStartedAt *time.Time `json:"cleanup_policy_started_at"` Status *ContainerRegistryStatus `json:"status"` - TagsCount int `json:"tags_count"` + TagsCount int64 `json:"tags_count"` Tags []*RegistryRepositoryTag `json:"tags"` } @@ -76,74 +114,50 @@ type RegistryRepositoryTag struct { ShortRevision string `json:"short_revision"` Digest string `json:"digest"` CreatedAt *time.Time `json:"created_at"` - TotalSize int `json:"total_size"` + TotalSize int64 `json:"total_size"` } func (s RegistryRepositoryTag) String() string { return Stringify(s) } -// ListRegistryRepositoriesOptions represents the available -// ListRegistryRepositories() options. +// ListProjectRegistryRepositoriesOptions represents the available +// ListProjectRegistryRepositories() options. // // GitLab API docs: // https://docs.gitlab.com/api/container_registry/#list-registry-repositories -type ListRegistryRepositoriesOptions struct { +type ListProjectRegistryRepositoriesOptions struct { ListOptions - // Deprecated: These options are deprecated for ListGroupRegistryRepositories calls. (Removed in GitLab 15.0) Tags *bool `url:"tags,omitempty" json:"tags,omitempty"` TagsCount *bool `url:"tags_count,omitempty" json:"tags_count,omitempty"` } -// ListProjectRegistryRepositories gets a list of registry repositories in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#within-a-project -func (s *ContainerRegistryService) ListProjectRegistryRepositories(pid any, opt *ListRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var repos []*RegistryRepository - resp, err := s.client.Do(req, &repos) - if err != nil { - return nil, resp, err - } - - return repos, resp, nil -} - -// ListGroupRegistryRepositories gets a list of registry repositories in a group. +// ListGroupRegistryRepositoriesOptions represents the available +// ListGroupRegistryRepositories() options. // // GitLab API docs: // https://docs.gitlab.com/api/container_registry/#within-a-group -func (s *ContainerRegistryService) ListGroupRegistryRepositories(gid any, opt *ListRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/registry/repositories", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } +type ListGroupRegistryRepositoriesOptions struct { + ListOptions +} - var repos []*RegistryRepository - resp, err := s.client.Do(req, &repos) - if err != nil { - return nil, resp, err - } +func (s *ContainerRegistryService) ListProjectRegistryRepositories(pid any, opt *ListProjectRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) { + return do[[]*RegistryRepository](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/registry/repositories", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - return repos, resp, nil +func (s *ContainerRegistryService) ListGroupRegistryRepositories(gid any, opt *ListGroupRegistryRepositoriesOptions, options ...RequestOptionFunc) ([]*RegistryRepository, *Response, error) { + return do[[]*RegistryRepository](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/registry/repositories", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetSingleRegistryRepositoryOptions represents the available @@ -156,48 +170,22 @@ type GetSingleRegistryRepositoryOptions struct { TagsCount *bool `url:"tags_count,omitempty" json:"tags_count,omitempty"` } -// GetSingleRegistryRepository gets the details of single registry repository. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#get-details-of-a-single-repository func (s *ContainerRegistryService) GetSingleRegistryRepository(pid any, opt *GetSingleRegistryRepositoryOptions, options ...RequestOptionFunc) (*RegistryRepository, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("registry/repositories/%s", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - repo := new(RegistryRepository) - resp, err := s.client.Do(req, repo) - if err != nil { - return nil, resp, err - } - - return repo, resp, nil + return do[*RegistryRepository](s.client, + withMethod(http.MethodGet), + withPath("registry/repositories/%s", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteRegistryRepository deletes a repository in a registry. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#delete-registry-repository -func (s *ContainerRegistryService) DeleteRegistryRepository(pid any, repository int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories/%d", PathEscape(project), repository) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ContainerRegistryService) DeleteRegistryRepository(pid any, repository int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/registry/repositories/%d", ProjectID{pid}, repository), + withRequestOpts(options...), + ) + return resp, err } // ListRegistryRepositoryTagsOptions represents the available @@ -205,86 +193,34 @@ func (s *ContainerRegistryService) DeleteRegistryRepository(pid any, repository // // GitLab API docs: // https://docs.gitlab.com/api/container_registry/#list-registry-repository-tags -type ListRegistryRepositoryTagsOptions ListOptions +type ListRegistryRepositoryTagsOptions struct { + ListOptions +} -// ListRegistryRepositoryTags gets a list of tags for given registry repository. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#list-registry-repository-tags -func (s *ContainerRegistryService) ListRegistryRepositoryTags(pid any, repository int, opt *ListRegistryRepositoryTagsOptions, options ...RequestOptionFunc) ([]*RegistryRepositoryTag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags", - PathEscape(project), - repository, +func (s *ContainerRegistryService) ListRegistryRepositoryTags(pid any, repository int64, opt *ListRegistryRepositoryTagsOptions, options ...RequestOptionFunc) ([]*RegistryRepositoryTag, *Response, error) { + return do[[]*RegistryRepositoryTag](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/registry/repositories/%d/tags", ProjectID{pid}, repository), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var tags []*RegistryRepositoryTag - resp, err := s.client.Do(req, &tags) - if err != nil { - return nil, resp, err - } - - return tags, resp, nil } -// GetRegistryRepositoryTagDetail get details of a registry repository tag -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#get-details-of-a-registry-repository-tag -func (s *ContainerRegistryService) GetRegistryRepositoryTagDetail(pid any, repository int, tagName string, options ...RequestOptionFunc) (*RegistryRepositoryTag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags/%s", - PathEscape(project), - repository, - tagName, +func (s *ContainerRegistryService) GetRegistryRepositoryTagDetail(pid any, repository int64, tagName string, options ...RequestOptionFunc) (*RegistryRepositoryTag, *Response, error) { + return do[*RegistryRepositoryTag](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/registry/repositories/%d/tags/%s", ProjectID{pid}, repository, tagName), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - tag := new(RegistryRepositoryTag) - resp, err := s.client.Do(req, &tag) - if err != nil { - return nil, resp, err - } - - return tag, resp, nil } -// DeleteRegistryRepositoryTag deletes a registry repository tag. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#delete-a-registry-repository-tag -func (s *ContainerRegistryService) DeleteRegistryRepositoryTag(pid any, repository int, tagName string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags/%s", - PathEscape(project), - repository, - tagName, +func (s *ContainerRegistryService) DeleteRegistryRepositoryTag(pid any, repository int64, tagName string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/registry/repositories/%d/tags/%s", ProjectID{pid}, repository, tagName), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // DeleteRegistryRepositoryTagsOptions represents the available @@ -295,32 +231,19 @@ func (s *ContainerRegistryService) DeleteRegistryRepositoryTag(pid any, reposito type DeleteRegistryRepositoryTagsOptions struct { NameRegexpDelete *string `url:"name_regex_delete,omitempty" json:"name_regex_delete,omitempty"` NameRegexpKeep *string `url:"name_regex_keep,omitempty" json:"name_regex_keep,omitempty"` - KeepN *int `url:"keep_n,omitempty" json:"keep_n,omitempty"` + KeepN *int64 `url:"keep_n,omitempty" json:"keep_n,omitempty"` OlderThan *string `url:"older_than,omitempty" json:"older_than,omitempty"` // Deprecated: NameRegexp is deprecated in favor of NameRegexpDelete. NameRegexp *string `url:"name_regex,omitempty" json:"name_regex,omitempty"` } -// DeleteRegistryRepositoryTags deletes repository tags in bulk based on -// given criteria. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_registry/#delete-registry-repository-tags-in-bulk -func (s *ContainerRegistryService) DeleteRegistryRepositoryTags(pid any, repository int, opt *DeleteRegistryRepositoryTagsOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/registry/repositories/%d/tags", - PathEscape(project), - repository, +func (s *ContainerRegistryService) DeleteRegistryRepositoryTags(pid any, repository int64, opt *DeleteRegistryRepositoryTagsOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/registry/repositories/%d/tags", ProjectID{pid}, repository), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/container_registry_protection_rules.go b/vendor/gitlab.com/gitlab-org/api/client-go/container_registry_protection_rules.go index 5871f3983..3f505e547 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/container_registry_protection_rules.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/container_registry_protection_rules.go @@ -15,16 +15,49 @@ package gitlab import ( - "fmt" "net/http" ) type ( ContainerRegistryProtectionRulesServiceInterface interface { + // ListContainerRegistryProtectionRules gets a list of container repository + // protection rules from a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#list-container-repository-protection-rules + // ListContainerRegistryProtectionRules gets a list of container repository + // protection rules from a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#list-container-repository-protection-rules ListContainerRegistryProtectionRules(pid any, options ...RequestOptionFunc) ([]*ContainerRegistryProtectionRule, *Response, error) + + // CreateContainerRegistryProtectionRule creates a container repository + // protection rule for a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#create-a-container-repository-protection-rule + + // CreateContainerRegistryProtectionRule creates a container repository + // protection rule for a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#create-a-container-repository-protection-rule CreateContainerRegistryProtectionRule(pid any, opt *CreateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) - UpdateContainerRegistryProtectionRule(pid any, ruleID int, opt *UpdateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) - DeleteContainerRegistryProtectionRule(pid any, ruleID int, options ...RequestOptionFunc) (*Response, error) + + // UpdateContainerRegistryProtectionRule updates a container repository protection + // rule for a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#update-a-container-repository-protection-rule + UpdateContainerRegistryProtectionRule(pid any, ruleID int64, opt *UpdateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) + + // DeleteContainerRegistryProtectionRule deletes a container repository protection + // rule from a projectโ€™s container registry. + // + // GitLab API docs: + // https://docs.gitlab.com/api/container_repository_protection_rules/#delete-a-container-repository-protection-rule + DeleteContainerRegistryProtectionRule(pid any, ruleID int64, options ...RequestOptionFunc) (*Response, error) } // ContainerRegistryProtectionRulesService handles communication with @@ -46,8 +79,8 @@ var _ ContainerRegistryProtectionRulesServiceInterface = (*ContainerRegistryProt // GitLab API docs: // https://docs.gitlab.com/api/container_repository_protection_rules/ type ContainerRegistryProtectionRule struct { - ID int `json:"id"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` RepositoryPathPattern string `json:"repository_path_pattern"` MinimumAccessLevelForPush ProtectionRuleAccessLevel `json:"minimum_access_level_for_push"` MinimumAccessLevelForDelete ProtectionRuleAccessLevel `json:"minimum_access_level_for_delete"` @@ -57,30 +90,12 @@ func (s ContainerRegistryProtectionRule) String() string { return Stringify(s) } -// ListContainerRegistryProtectionRules gets a list of container repository -// protection rules from a projectโ€™s container registry. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_repository_protection_rules/#list-container-repository-protection-rules func (s *ContainerRegistryProtectionRulesService) ListContainerRegistryProtectionRules(pid any, options ...RequestOptionFunc) ([]*ContainerRegistryProtectionRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/protection/repository/rules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var rules []*ContainerRegistryProtectionRule - resp, err := s.client.Do(req, &rules) - if err != nil { - return nil, resp, err - } - - return rules, resp, nil + return do[[]*ContainerRegistryProtectionRule](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/registry/protection/repository/rules", ProjectID{pid}), + withRequestOpts(options...), + ) } // CreateContainerRegistryProtectionRuleOptions represents the available @@ -94,30 +109,13 @@ type CreateContainerRegistryProtectionRuleOptions struct { MinimumAccessLevelForDelete *ProtectionRuleAccessLevel `url:"minimum_access_level_for_delete,omitempty" json:"minimum_access_level_for_delete,omitempty"` } -// CreateContainerRegistryProtectionRule creates a container repository -// protection rule for a projectโ€™s container registry. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_repository_protection_rules/#create-a-container-repository-protection-rule func (s *ContainerRegistryProtectionRulesService) CreateContainerRegistryProtectionRule(pid any, opt *CreateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/protection/repository/rules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - rule := new(ContainerRegistryProtectionRule) - resp, err := s.client.Do(req, rule) - if err != nil { - return nil, resp, err - } - - return rule, resp, nil + return do[*ContainerRegistryProtectionRule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/registry/protection/repository/rules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateContainerRegistryProtectionRuleOptions represents the available @@ -131,48 +129,20 @@ type UpdateContainerRegistryProtectionRuleOptions struct { MinimumAccessLevelForDelete *ProtectionRuleAccessLevel `url:"minimum_access_level_for_delete,omitempty" json:"minimum_access_level_for_delete,omitempty"` } -// UpdateContainerRegistryProtectionRule updates a container repository protection -// rule for a projectโ€™s container registry. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_repository_protection_rules/#update-a-container-repository-protection-rule -func (s *ContainerRegistryProtectionRulesService) UpdateContainerRegistryProtectionRule(pid any, ruleID int, opt *UpdateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/registry/protection/repository/rules/%d", PathEscape(project), ruleID) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, nil, err - } - - rule := new(ContainerRegistryProtectionRule) - resp, err := s.client.Do(req, rule) - if err != nil { - return nil, resp, err - } - - return rule, resp, nil +func (s *ContainerRegistryProtectionRulesService) UpdateContainerRegistryProtectionRule(pid any, ruleID int64, opt *UpdateContainerRegistryProtectionRuleOptions, options ...RequestOptionFunc) (*ContainerRegistryProtectionRule, *Response, error) { + return do[*ContainerRegistryProtectionRule](s.client, + withMethod(http.MethodPatch), + withPath("projects/%s/registry/protection/repository/rules/%d", ProjectID{pid}, ruleID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteContainerRegistryProtectionRule deletes a container repository protection -// rule from a projectโ€™s container registry. -// -// GitLab API docs: -// https://docs.gitlab.com/api/container_repository_protection_rules/#delete-a-container-repository-protection-rule -func (s *ContainerRegistryProtectionRulesService) DeleteContainerRegistryProtectionRule(pid any, ruleID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/registry/protection/repository/rules/%d", PathEscape(project), ruleID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ContainerRegistryProtectionRulesService) DeleteContainerRegistryProtectionRule(pid any, ruleID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/registry/protection/repository/rules/%d", ProjectID{pid}, ruleID), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/custom_attributes.go b/vendor/gitlab.com/gitlab-org/api/client-go/custom_attributes.go index 92e3babce..3e3958674 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/custom_attributes.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/custom_attributes.go @@ -17,24 +17,82 @@ package gitlab import ( - "fmt" "net/http" ) type ( CustomAttributesServiceInterface interface { - ListCustomUserAttributes(user int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) - ListCustomGroupAttributes(group int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) - ListCustomProjectAttributes(project int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) - GetCustomUserAttribute(user int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - GetCustomGroupAttribute(group int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - GetCustomProjectAttribute(project int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - SetCustomUserAttribute(user int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - SetCustomGroupAttribute(group int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - SetCustomProjectAttribute(project int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) - DeleteCustomUserAttribute(user int, key string, options ...RequestOptionFunc) (*Response, error) - DeleteCustomGroupAttribute(group int, key string, options ...RequestOptionFunc) (*Response, error) - DeleteCustomProjectAttribute(project int, key string, options ...RequestOptionFunc) (*Response, error) + // ListCustomUserAttributes lists the custom attributes of the specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes + ListCustomUserAttributes(user int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) + + // ListCustomGroupAttributes lists the custom attributes of the specified group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes + ListCustomGroupAttributes(group int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) + + // ListCustomProjectAttributes lists the custom attributes of the specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes + ListCustomProjectAttributes(project int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) + + // GetCustomUserAttribute returns the user attribute with a specific key. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute + GetCustomUserAttribute(user int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // GetCustomGroupAttribute returns the group attribute with a specific key. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute + GetCustomGroupAttribute(group int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // GetCustomProjectAttribute returns the project attribute with a specific key. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute + GetCustomProjectAttribute(project int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // SetCustomUserAttribute sets the custom attributes of the specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute + SetCustomUserAttribute(user int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // SetCustomGroupAttribute sets the custom attributes of the specified group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute + SetCustomGroupAttribute(group int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // SetCustomProjectAttribute sets the custom attributes of the specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute + SetCustomProjectAttribute(project int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) + + // DeleteCustomUserAttribute removes the custom attribute of the specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute + DeleteCustomUserAttribute(user int64, key string, options ...RequestOptionFunc) (*Response, error) + + // DeleteCustomGroupAttribute removes the custom attribute of the specified group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute + DeleteCustomGroupAttribute(group int64, key string, options ...RequestOptionFunc) (*Response, error) + + // DeleteCustomProjectAttribute removes the custom attribute of the specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute + DeleteCustomProjectAttribute(project int64, key string, options ...RequestOptionFunc) (*Response, error) } // CustomAttributesService handles communication with the group, project and @@ -56,152 +114,99 @@ type CustomAttribute struct { Value string `json:"value"` } -// ListCustomUserAttributes lists the custom attributes of the specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes -func (s *CustomAttributesService) ListCustomUserAttributes(user int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) ListCustomUserAttributes(user int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { return s.listCustomAttributes("users", user, options...) } -// ListCustomGroupAttributes lists the custom attributes of the specified group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes -func (s *CustomAttributesService) ListCustomGroupAttributes(group int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) ListCustomGroupAttributes(group int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { return s.listCustomAttributes("groups", group, options...) } -// ListCustomProjectAttributes lists the custom attributes of the specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#list-custom-attributes -func (s *CustomAttributesService) ListCustomProjectAttributes(project int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) ListCustomProjectAttributes(project int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { return s.listCustomAttributes("projects", project, options...) } -func (s *CustomAttributesService) listCustomAttributes(resource string, id int, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { - u := fmt.Sprintf("%s/%d/custom_attributes", resource, id) - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var cas []*CustomAttribute - resp, err := s.client.Do(req, &cas) +func (s *CustomAttributesService) listCustomAttributes(resource string, id int64, options ...RequestOptionFunc) ([]*CustomAttribute, *Response, error) { + res, resp, err := do[[]*CustomAttribute](s.client, + withMethod(http.MethodGet), + withPath("%s/%d/custom_attributes", resource, id), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return cas, resp, nil + return res, resp, nil } -// GetCustomUserAttribute returns the user attribute with a specific key. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute -func (s *CustomAttributesService) GetCustomUserAttribute(user int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) GetCustomUserAttribute(user int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.getCustomAttribute("users", user, key, options...) } -// GetCustomGroupAttribute returns the group attribute with a specific key. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute -func (s *CustomAttributesService) GetCustomGroupAttribute(group int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) GetCustomGroupAttribute(group int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.getCustomAttribute("groups", group, key, options...) } -// GetCustomProjectAttribute returns the project attribute with a specific key. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#single-custom-attribute -func (s *CustomAttributesService) GetCustomProjectAttribute(project int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) GetCustomProjectAttribute(project int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.getCustomAttribute("projects", project, key, options...) } -func (s *CustomAttributesService) getCustomAttribute(resource string, id int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { - u := fmt.Sprintf("%s/%d/custom_attributes/%s", resource, id, key) - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var ca *CustomAttribute - resp, err := s.client.Do(req, &ca) +func (s *CustomAttributesService) getCustomAttribute(resource string, id int64, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { + res, resp, err := do[*CustomAttribute](s.client, + withMethod(http.MethodGet), + withPath("%s/%d/custom_attributes/%s", resource, id, key), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return ca, resp, nil + return res, resp, nil } -// SetCustomUserAttribute sets the custom attributes of the specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute -func (s *CustomAttributesService) SetCustomUserAttribute(user int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) SetCustomUserAttribute(user int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.setCustomAttribute("users", user, c, options...) } -// SetCustomGroupAttribute sets the custom attributes of the specified group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute -func (s *CustomAttributesService) SetCustomGroupAttribute(group int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) SetCustomGroupAttribute(group int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.setCustomAttribute("groups", group, c, options...) } -// SetCustomProjectAttribute sets the custom attributes of the specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#set-custom-attribute -func (s *CustomAttributesService) SetCustomProjectAttribute(project int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { +func (s *CustomAttributesService) SetCustomProjectAttribute(project int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { return s.setCustomAttribute("projects", project, c, options...) } -func (s *CustomAttributesService) setCustomAttribute(resource string, id int, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { - u := fmt.Sprintf("%s/%d/custom_attributes/%s", resource, id, c.Key) - req, err := s.client.NewRequest(http.MethodPut, u, c, options) - if err != nil { - return nil, nil, err - } - - ca := new(CustomAttribute) - resp, err := s.client.Do(req, ca) +func (s *CustomAttributesService) setCustomAttribute(resource string, id int64, c CustomAttribute, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) { + res, resp, err := do[*CustomAttribute](s.client, + withMethod(http.MethodPut), + withPath("%s/%d/custom_attributes/%s", resource, id, c.Key), + withAPIOpts(c), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return ca, resp, nil + return res, resp, nil } -// DeleteCustomUserAttribute removes the custom attribute of the specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute -func (s *CustomAttributesService) DeleteCustomUserAttribute(user int, key string, options ...RequestOptionFunc) (*Response, error) { +func (s *CustomAttributesService) DeleteCustomUserAttribute(user int64, key string, options ...RequestOptionFunc) (*Response, error) { return s.deleteCustomAttribute("users", user, key, options...) } -// DeleteCustomGroupAttribute removes the custom attribute of the specified group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute -func (s *CustomAttributesService) DeleteCustomGroupAttribute(group int, key string, options ...RequestOptionFunc) (*Response, error) { +func (s *CustomAttributesService) DeleteCustomGroupAttribute(group int64, key string, options ...RequestOptionFunc) (*Response, error) { return s.deleteCustomAttribute("groups", group, key, options...) } -// DeleteCustomProjectAttribute removes the custom attribute of the specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/custom_attributes/#delete-custom-attribute -func (s *CustomAttributesService) DeleteCustomProjectAttribute(project int, key string, options ...RequestOptionFunc) (*Response, error) { +func (s *CustomAttributesService) DeleteCustomProjectAttribute(project int64, key string, options ...RequestOptionFunc) (*Response, error) { return s.deleteCustomAttribute("projects", project, key, options...) } -func (s *CustomAttributesService) deleteCustomAttribute(resource string, id int, key string, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("%s/%d/custom_attributes/%s", resource, id, key) - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - return s.client.Do(req, nil) +func (s *CustomAttributesService) deleteCustomAttribute(resource string, id int64, key string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("%s/%d/custom_attributes/%s", resource, id, key), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/database_migrations.go b/vendor/gitlab.com/gitlab-org/api/client-go/database_migrations.go index 058e32cc7..a7ca83f6a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/database_migrations.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/database_migrations.go @@ -15,13 +15,18 @@ package gitlab import ( - "fmt" "net/http" ) type ( DatabaseMigrationsServiceInterface interface { - MarkMigrationAsSuccessful(version int, opt *MarkMigrationAsSuccessfulOptions, options ...RequestOptionFunc) (*Response, error) + // MarkMigrationAsSuccessful marks pending migrations as successfully executed + // to prevent them from being executed by the db:migrate tasks. Use this API to + // skip failing migrations after they are determined to be safe to skip. + // + // GitLab API docs: + // https://docs.gitlab.com/api/database_migrations/#mark-a-migration-as-successful + MarkMigrationAsSuccessful(version int64, opt *MarkMigrationAsSuccessfulOptions, options ...RequestOptionFunc) (*Response, error) } // DatabaseMigrationsService handles communication with the database @@ -44,19 +49,12 @@ type MarkMigrationAsSuccessfulOptions struct { Database string `url:"database,omitempty" json:"database,omitempty"` } -// MarkMigrationAsSuccessful marks pending migrations as successfully executed -// to prevent them from being executed by the db:migrate tasks. Use this API to -// skip failing migrations after they are determined to be safe to skip. -// -// GitLab API docs: -// https://docs.gitlab.com/api/database_migrations/#mark-a-migration-as-successful -func (s *DatabaseMigrationsService) MarkMigrationAsSuccessful(version int, opt *MarkMigrationAsSuccessfulOptions, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("admin/migrations/%d/mark", version) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DatabaseMigrationsService) MarkMigrationAsSuccessful(version int64, opt *MarkMigrationAsSuccessfulOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("admin/migrations/%d/mark", version), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/dependencies.go b/vendor/gitlab.com/gitlab-org/api/client-go/dependencies.go index e4b85381e..076d0b6bd 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/dependencies.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/dependencies.go @@ -14,13 +14,14 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( DependenciesServiceInterface interface { + // ListProjectDependencies Get a list of project dependencies. This API partially + // mirroring Dependency List feature. This list can be generated only for languages + // and package managers supported by Gemnasium. + // + // GitLab API docs: + // https://docs.gitlab.com/api/dependencies/#list-project-dependencies ListProjectDependencies(pid any, opt *ListProjectDependenciesOptions, options ...RequestOptionFunc) ([]*Dependency, *Response, error) } @@ -53,7 +54,7 @@ type Dependency struct { type DependencyVulnerability struct { Name string `url:"name" json:"name"` Severity string `url:"severity" json:"severity"` - ID int `url:"id" json:"id"` + ID int64 `url:"id" json:"id"` URL string `url:"url" json:"url"` } @@ -72,32 +73,13 @@ type DependencyLicense struct { // https://docs.gitlab.com/api/dependencies/#list-project-dependencies type ListProjectDependenciesOptions struct { ListOptions - PackageManager []*DependencyPackageManagerValue `url:"package_manager,omitempty" json:"package_manager,omitempty"` + PackageManager []*DependencyPackageManagerValue `url:"package_manager,comma,omitempty" json:"package_manager,omitempty"` } -// ListProjectDependencies Get a list of project dependencies. This API partially -// mirroring Dependency List feature. This list can be generated only for languages -// and package managers supported by Gemnasium. -// -// GitLab API docs: -// https://docs.gitlab.com/api/dependencies/#list-project-dependencies func (s *DependenciesService) ListProjectDependencies(pid any, opt *ListProjectDependenciesOptions, options ...RequestOptionFunc) ([]*Dependency, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/dependencies", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var dependencies []*Dependency - resp, err := s.client.Do(req, &dependencies) - if err != nil { - return nil, resp, err - } - - return dependencies, resp, nil + return do[[]*Dependency](s.client, + withPath("projects/%s/dependencies", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/dependency_list_export.go b/vendor/gitlab.com/gitlab-org/api/client-go/dependency_list_export.go index ed475fd46..6f82f5963 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/dependency_list_export.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/dependency_list_export.go @@ -2,16 +2,44 @@ package gitlab import ( "bytes" - "fmt" "io" "net/http" ) type ( DependencyListExportServiceInterface interface { - CreateDependencyListExport(pipelineID int, opt *CreateDependencyListExportOptions, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) - GetDependencyListExport(id int, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) - DownloadDependencyListExport(id int, options ...RequestOptionFunc) (io.Reader, *Response, error) + // CreateDependencyListExport creates a new CycloneDX JSON export for all the project dependencies + // detected in a pipeline. + // + // If an authenticated user does not have permission to read_dependency, this request returns a 403 + // Forbidden status code. + // + // SBOM exports can be only accessed by the exportโ€™s author. + // + // GitLab docs: + // https://docs.gitlab.com/api/dependency_list_export/#create-a-dependency-list-export + CreateDependencyListExport(pipelineID int64, opt *CreateDependencyListExportOptions, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) + + // GetDependencyListExport gets metadata about a single dependency list export. + // + // GitLab docs: + // https://docs.gitlab.com/api/dependency_list_export/#get-single-dependency-list-export + GetDependencyListExport(id int64, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) + + // DownloadDependencyListExport downloads a single dependency list export. + // + // The github.com/CycloneDX/cyclonedx-go package can be used to parse the data from the returned io.Reader. + // + // sbom := new(cdx.BOM) + // decoder := cdx.NewBOMDecoder(reader, cdx.BOMFileFormatJSON) + // + // if err = decoder.Decode(sbom); err != nil { + // panic(err) + // } + // + // GitLab docs: + // https://docs.gitlab.com/api/dependency_list_export/#download-dependency-list-export + DownloadDependencyListExport(id int64, options ...RequestOptionFunc) (io.Reader, *Response, error) } // DependencyListExportService handles communication with the dependency list export @@ -39,7 +67,7 @@ type CreateDependencyListExportOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/dependency_list_export/#create-a-dependency-list-export type DependencyListExport struct { - ID int `json:"id"` + ID int64 `json:"id"` HasFinished bool `json:"has_finished"` Self string `json:"self"` Download string `json:"download"` @@ -47,20 +75,7 @@ type DependencyListExport struct { const defaultExportType = "sbom" -// CreateDependencyListExport creates a new CycloneDX JSON export for all the project dependencies -// detected in a pipeline. -// -// If an authenticated user does not have permission to read_dependency, this request returns a 403 -// Forbidden status code. -// -// SBOM exports can be only accessed by the exportโ€™s author. -// -// GitLab docs: -// https://docs.gitlab.com/api/dependency_list_export/#create-a-dependency-list-export -func (s *DependencyListExportService) CreateDependencyListExport(pipelineID int, opt *CreateDependencyListExportOptions, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) { - // POST /pipelines/:id/dependency_list_exports - createExportPath := fmt.Sprintf("pipelines/%d/dependency_list_exports", pipelineID) - +func (s *DependencyListExportService) CreateDependencyListExport(pipelineID int64, opt *CreateDependencyListExportOptions, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) { if opt == nil { opt = &CreateDependencyListExportOptions{} } @@ -68,69 +83,28 @@ func (s *DependencyListExportService) CreateDependencyListExport(pipelineID int, opt.ExportType = Ptr(defaultExportType) } - req, err := s.client.NewRequest(http.MethodPost, createExportPath, opt, options) - if err != nil { - return nil, nil, err - } - - export := new(DependencyListExport) - resp, err := s.client.Do(req, &export) - if err != nil { - return nil, resp, err - } - - return export, resp, nil + return do[*DependencyListExport](s.client, + withMethod(http.MethodPost), + withPath("pipelines/%d/dependency_list_exports", pipelineID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetDependencyListExport gets metadata about a single dependency list export. -// -// GitLab docs: -// https://docs.gitlab.com/api/dependency_list_export/#get-single-dependency-list-export -func (s *DependencyListExportService) GetDependencyListExport(id int, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) { - // GET /dependency_list_exports/:id - getExportPath := fmt.Sprintf("dependency_list_exports/%d", id) - - req, err := s.client.NewRequest(http.MethodGet, getExportPath, nil, options) - if err != nil { - return nil, nil, err - } - - export := new(DependencyListExport) - resp, err := s.client.Do(req, &export) - if err != nil { - return nil, resp, err - } - - return export, resp, nil +func (s *DependencyListExportService) GetDependencyListExport(id int64, options ...RequestOptionFunc) (*DependencyListExport, *Response, error) { + return do[*DependencyListExport](s.client, + withPath("dependency_list_exports/%d", id), + withRequestOpts(options...), + ) } -// DownloadDependencyListExport downloads a single dependency list export. -// -// The github.com/CycloneDX/cyclonedx-go package can be used to parse the data from the returned io.Reader. -// -// sbom := new(cdx.BOM) -// decoder := cdx.NewBOMDecoder(reader, cdx.BOMFileFormatJSON) -// -// if err = decoder.Decode(sbom); err != nil { -// panic(err) -// } -// -// GitLab docs: -// https://docs.gitlab.com/api/dependency_list_export/#download-dependency-list-export -func (s *DependencyListExportService) DownloadDependencyListExport(id int, options ...RequestOptionFunc) (io.Reader, *Response, error) { - // GET /dependency_list_exports/:id/download - downloadExportPath := fmt.Sprintf("dependency_list_exports/%d/download", id) - - req, err := s.client.NewRequest(http.MethodGet, downloadExportPath, nil, options) - if err != nil { - return nil, nil, err - } - - var sbomBuffer bytes.Buffer - resp, err := s.client.Do(req, &sbomBuffer) +func (s *DependencyListExportService) DownloadDependencyListExport(id int64, options ...RequestOptionFunc) (io.Reader, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("dependency_list_exports/%d/download", id), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return &sbomBuffer, resp, nil + return &buf, resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/dependency_proxy.go b/vendor/gitlab.com/gitlab-org/api/client-go/dependency_proxy.go index a475cb5fd..a9516e640 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/dependency_proxy.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/dependency_proxy.go @@ -14,13 +14,15 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( DependencyProxyServiceInterface interface { + // PurgeGroupDependencyProxy schedules for deletion the cached manifests and blobs + // for a group. This endpoint requires the Owner role for the group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/dependency_proxy/#purge-the-dependency-proxy-for-a-group PurgeGroupDependencyProxy(gid any, options ...RequestOptionFunc) (*Response, error) } @@ -35,22 +37,11 @@ type ( var _ DependencyProxyServiceInterface = (*DependencyProxyService)(nil) -// PurgeGroupDependencyProxy schedules for deletion the cached manifests and blobs -// for a group. This endpoint requires the Owner role for the group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/dependency_proxy/#purge-the-dependency-proxy-for-a-group func (s *DependencyProxyService) PurgeGroupDependencyProxy(gid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/dependency_proxy/cache", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/dependency_proxy/cache", GroupID{gid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/deploy_keys.go b/vendor/gitlab.com/gitlab-org/api/client-go/deploy_keys.go index 8f54a1344..78c988995 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/deploy_keys.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/deploy_keys.go @@ -17,22 +17,86 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( DeployKeysServiceInterface interface { + // ListAllDeployKeys gets a list of all deploy keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#list-all-deploy-keys + // ListAllDeployKeys gets a list of all deploy keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#list-all-deploy-keys ListAllDeployKeys(opt *ListInstanceDeployKeysOptions, options ...RequestOptionFunc) ([]*InstanceDeployKey, *Response, error) + + // AddInstanceDeployKey creates a deploy key for the GitLab instance. + // Requires administrator access. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#add-deploy-key + + // AddInstanceDeployKey creates a deploy key for the GitLab instance. + // Requires administrator access. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#add-deploy-key AddInstanceDeployKey(opt *AddInstanceDeployKeyOptions, options ...RequestOptionFunc) (*InstanceDeployKey, *Response, error) + + // ListProjectDeployKeys gets a list of a project's deploy keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#list-deploy-keys-for-project + + // ListProjectDeployKeys gets a list of a project's deploy keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#list-deploy-keys-for-project ListProjectDeployKeys(pid any, opt *ListProjectDeployKeysOptions, options ...RequestOptionFunc) ([]*ProjectDeployKey, *Response, error) + + // ListUserProjectDeployKeys gets a list of a user's deploy keys. + // + // uid can be either a user ID (int) or a username (string). If a username + // is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#list-project-deploy-keys-for-user ListUserProjectDeployKeys(uid any, opt *ListUserProjectDeployKeysOptions, options ...RequestOptionFunc) ([]*ProjectDeployKey, *Response, error) - GetDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) + + // GetDeployKey gets a single deploy key. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#get-a-single-deploy-key + GetDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) + + // AddDeployKey creates a new deploy key for a project. If the deploy key already + // exists in another project, it will be joined to the project but only if + // the original one is accessible by the same user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#add-deploy-key-for-a-project AddDeployKey(pid any, opt *AddDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) - DeleteDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*Response, error) - EnableDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) - UpdateDeployKey(pid any, deployKey int, opt *UpdateDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) + + // DeleteDeployKey deletes a deploy key from a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#delete-deploy-key + DeleteDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*Response, error) + + // EnableDeployKey enables a deploy key. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#enable-a-deploy-key + EnableDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) + + // UpdateDeployKey updates a deploy key for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_keys/#update-deploy-key + UpdateDeployKey(pid any, deployKey int64, opt *UpdateDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) } // DeployKeysService handles communication with the keys related methods @@ -49,7 +113,7 @@ var _ DeployKeysServiceInterface = (*DeployKeysService)(nil) // InstanceDeployKey represents a GitLab deploy key with the associated // projects it has write access to. type InstanceDeployKey struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` CreatedAt *time.Time `json:"created_at"` ExpiresAt *time.Time `json:"expires_at"` @@ -66,7 +130,7 @@ func (k InstanceDeployKey) String() string { // DeployKeyProject refers to a project an InstanceDeployKey has write access to. type DeployKeyProject struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -81,7 +145,7 @@ func (k DeployKeyProject) String() string { // ProjectDeployKey represents a GitLab project deploy key. type ProjectDeployKey struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Key string `json:"key"` Fingerprint string `json:"fingerprint"` @@ -105,23 +169,12 @@ type ListInstanceDeployKeysOptions struct { Public *bool `url:"public,omitempty" json:"public,omitempty"` } -// ListAllDeployKeys gets a list of all deploy keys -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#list-all-deploy-keys func (s *DeployKeysService) ListAllDeployKeys(opt *ListInstanceDeployKeysOptions, options ...RequestOptionFunc) ([]*InstanceDeployKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "deploy_keys", opt, options) - if err != nil { - return nil, nil, err - } - - var ks []*InstanceDeployKey - resp, err := s.client.Do(req, &ks) - if err != nil { - return nil, resp, err - } - - return ks, resp, nil + return do[[]*InstanceDeployKey](s.client, + withPath("deploy_keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddInstanceDeployKeyOptions represents the available AddInstanceDeployKey() @@ -135,24 +188,13 @@ type AddInstanceDeployKeyOptions struct { ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"` } -// AddInstanceDeployKey creates a deploy key for the GitLab instance. -// Requires administrator access. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#add-deploy-key func (s *DeployKeysService) AddInstanceDeployKey(opt *AddInstanceDeployKeyOptions, options ...RequestOptionFunc) (*InstanceDeployKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "deploy_keys", opt, options) - if err != nil { - return nil, nil, err - } - - key := new(InstanceDeployKey) - resp, err := s.client.Do(req, &key) - if err != nil { - return nil, resp, err - } - - return key, resp, nil + return do[*InstanceDeployKey](s.client, + withMethod(http.MethodPost), + withPath("deploy_keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListProjectDeployKeysOptions represents the available ListProjectDeployKeys() @@ -160,31 +202,16 @@ func (s *DeployKeysService) AddInstanceDeployKey(opt *AddInstanceDeployKeyOption // // GitLab API docs: // https://docs.gitlab.com/api/deploy_keys/#list-deploy-keys-for-project -type ListProjectDeployKeysOptions ListOptions +type ListProjectDeployKeysOptions struct { + ListOptions +} -// ListProjectDeployKeys gets a list of a project's deploy keys -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#list-deploy-keys-for-project func (s *DeployKeysService) ListProjectDeployKeys(pid any, opt *ListProjectDeployKeysOptions, options ...RequestOptionFunc) ([]*ProjectDeployKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ks []*ProjectDeployKey - resp, err := s.client.Do(req, &ks) - if err != nil { - return nil, resp, err - } - - return ks, resp, nil + return do[[]*ProjectDeployKey](s.client, + withPath("projects/%s/deploy_keys", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListUserProjectDeployKeysOptions represents the available ListUserProjectDeployKeys() @@ -192,56 +219,30 @@ func (s *DeployKeysService) ListProjectDeployKeys(pid any, opt *ListProjectDeplo // // GitLab API docs: // https://docs.gitlab.com/api/deploy_keys/#list-project-deploy-keys-for-user -type ListUserProjectDeployKeysOptions ListOptions +type ListUserProjectDeployKeysOptions struct { + ListOptions +} -// ListUserProjectDeployKeys gets a list of a user's deploy keys +// ListUserProjectDeployKeys gets a list of a user's deploy keys. +// +// uid can be either a user ID (int) or a username (string). If a username +// is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. // // GitLab API docs: // https://docs.gitlab.com/api/deploy_keys/#list-project-deploy-keys-for-user func (s *DeployKeysService) ListUserProjectDeployKeys(uid any, opt *ListUserProjectDeployKeysOptions, options ...RequestOptionFunc) ([]*ProjectDeployKey, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("users/%s/project_deploy_keys", PathEscape(user)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ks []*ProjectDeployKey - resp, err := s.client.Do(req, &ks) - if err != nil { - return nil, resp, err - } - - return ks, resp, nil + return do[[]*ProjectDeployKey](s.client, + withPath("users/%s/project_deploy_keys", UserID{uid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetDeployKey gets a single deploy key. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#get-a-single-deploy-key -func (s *DeployKeysService) GetDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys/%d", PathEscape(project), deployKey) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(ProjectDeployKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *DeployKeysService) GetDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { + return do[*ProjectDeployKey](s.client, + withPath("projects/%s/deploy_keys/%d", ProjectID{pid}, deployKey), + withRequestOpts(options...), + ) } // AddDeployKeyOptions represents the available ADDDeployKey() options. @@ -255,75 +256,30 @@ type AddDeployKeyOptions struct { ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"` } -// AddDeployKey creates a new deploy key for a project. If deploy key already -// exists in another project - it will be joined to project but only if -// original one is accessible by the same user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#add-deploy-key-for-a-project func (s *DeployKeysService) AddDeployKey(pid any, opt *AddDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - k := new(ProjectDeployKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[*ProjectDeployKey](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/deploy_keys", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteDeployKey deletes a deploy key from a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#delete-deploy-key -func (s *DeployKeysService) DeleteDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys/%d", PathEscape(project), deployKey) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DeployKeysService) DeleteDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/deploy_keys/%d", ProjectID{pid}, deployKey), + withRequestOpts(options...), + ) + return resp, err } -// EnableDeployKey enables a deploy key. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#enable-a-deploy-key -func (s *DeployKeysService) EnableDeployKey(pid any, deployKey int, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys/%d/enable", PathEscape(project), deployKey) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(ProjectDeployKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *DeployKeysService) EnableDeployKey(pid any, deployKey int64, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { + return do[*ProjectDeployKey](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/deploy_keys/%d/enable", ProjectID{pid}, deployKey), + withRequestOpts(options...), + ) } // UpdateDeployKeyOptions represents the available UpdateDeployKey() options. @@ -335,27 +291,11 @@ type UpdateDeployKeyOptions struct { CanPush *bool `url:"can_push,omitempty" json:"can_push,omitempty"` } -// UpdateDeployKey updates a deploy key for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_keys/#update-deploy-key -func (s *DeployKeysService) UpdateDeployKey(pid any, deployKey int, opt *UpdateDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_keys/%d", PathEscape(project), deployKey) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - k := new(ProjectDeployKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *DeployKeysService) UpdateDeployKey(pid any, deployKey int64, opt *UpdateDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) { + return do[*ProjectDeployKey](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/deploy_keys/%d", ProjectID{pid}, deployKey), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/deploy_tokens.go b/vendor/gitlab.com/gitlab-org/api/client-go/deploy_tokens.go index f7128a69f..8083c845e 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/deploy_tokens.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/deploy_tokens.go @@ -17,22 +17,74 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( DeployTokensServiceInterface interface { + // ListAllDeployTokens gets a list of all deploy tokens. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#list-all-deploy-tokens + // ListAllDeployTokens gets a list of all deploy tokens. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#list-all-deploy-tokens ListAllDeployTokens(options ...RequestOptionFunc) ([]*DeployToken, *Response, error) + + // ListProjectDeployTokens gets a list of a project's deploy tokens. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#list-project-deploy-tokens + + // ListProjectDeployTokens gets a list of a project's deploy tokens. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#list-project-deploy-tokens ListProjectDeployTokens(pid any, opt *ListProjectDeployTokensOptions, options ...RequestOptionFunc) ([]*DeployToken, *Response, error) - GetProjectDeployToken(pid any, deployToken int, options ...RequestOptionFunc) (*DeployToken, *Response, error) + + // GetProjectDeployToken gets a single deploy token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#get-a-project-deploy-token + GetProjectDeployToken(pid any, deployToken int64, options ...RequestOptionFunc) (*DeployToken, *Response, error) + + // CreateProjectDeployToken creates a new deploy token for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#create-a-project-deploy-token CreateProjectDeployToken(pid any, opt *CreateProjectDeployTokenOptions, options ...RequestOptionFunc) (*DeployToken, *Response, error) - DeleteProjectDeployToken(pid any, deployToken int, options ...RequestOptionFunc) (*Response, error) + + // DeleteProjectDeployToken removes a deploy token from the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#delete-a-project-deploy-token + DeleteProjectDeployToken(pid any, deployToken int64, options ...RequestOptionFunc) (*Response, error) + + // ListGroupDeployTokens gets a list of a groupโ€™s deploy tokens. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#list-group-deploy-tokens ListGroupDeployTokens(gid any, opt *ListGroupDeployTokensOptions, options ...RequestOptionFunc) ([]*DeployToken, *Response, error) - GetGroupDeployToken(gid any, deployToken int, options ...RequestOptionFunc) (*DeployToken, *Response, error) + + // GetGroupDeployToken gets a single deploy token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#get-a-group-deploy-token + GetGroupDeployToken(gid any, deployToken int64, options ...RequestOptionFunc) (*DeployToken, *Response, error) + + // CreateGroupDeployToken creates a new deploy token for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#create-a-group-deploy-token CreateGroupDeployToken(gid any, opt *CreateGroupDeployTokenOptions, options ...RequestOptionFunc) (*DeployToken, *Response, error) - DeleteGroupDeployToken(gid any, deployToken int, options ...RequestOptionFunc) (*Response, error) + + // DeleteGroupDeployToken removes a deploy token from the group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deploy_tokens/#delete-a-group-deploy-token + DeleteGroupDeployToken(gid any, deployToken int64, options ...RequestOptionFunc) (*Response, error) } // DeployTokensService handles communication with the deploy tokens related methods @@ -46,7 +98,7 @@ type ( // DeployToken represents a GitLab deploy token. type DeployToken struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Username string `json:"username"` ExpiresAt *time.Time `json:"expires_at"` @@ -60,23 +112,11 @@ func (k DeployToken) String() string { return Stringify(k) } -// ListAllDeployTokens gets a list of all deploy tokens. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#list-all-deploy-tokens func (s *DeployTokensService) ListAllDeployTokens(options ...RequestOptionFunc) ([]*DeployToken, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "deploy_tokens", nil, options) - if err != nil { - return nil, nil, err - } - - var ts []*DeployToken - resp, err := s.client.Do(req, &ts) - if err != nil { - return nil, resp, err - } - - return ts, resp, nil + return do[[]*DeployToken](s.client, + withPath("deploy_tokens"), + withRequestOpts(options...), + ) } // ListProjectDeployTokensOptions represents the available ListProjectDeployTokens() @@ -84,56 +124,23 @@ func (s *DeployTokensService) ListAllDeployTokens(options ...RequestOptionFunc) // // GitLab API docs: // https://docs.gitlab.com/api/deploy_tokens/#list-project-deploy-tokens -type ListProjectDeployTokensOptions ListOptions +type ListProjectDeployTokensOptions struct { + ListOptions +} -// ListProjectDeployTokens gets a list of a project's deploy tokens. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#list-project-deploy-tokens func (s *DeployTokensService) ListProjectDeployTokens(pid any, opt *ListProjectDeployTokensOptions, options ...RequestOptionFunc) ([]*DeployToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_tokens", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ts []*DeployToken - resp, err := s.client.Do(req, &ts) - if err != nil { - return nil, resp, err - } - - return ts, resp, nil + return do[[]*DeployToken](s.client, + withPath("projects/%s/deploy_tokens", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectDeployToken gets a single deploy token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#get-a-project-deploy-token -func (s *DeployTokensService) GetProjectDeployToken(pid any, deployToken int, options ...RequestOptionFunc) (*DeployToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_tokens/%d", PathEscape(project), deployToken) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(DeployToken) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *DeployTokensService) GetProjectDeployToken(pid any, deployToken int64, options ...RequestOptionFunc) (*DeployToken, *Response, error) { + return do[*DeployToken](s.client, + withPath("projects/%s/deploy_tokens/%d", ProjectID{pid}, deployToken), + withRequestOpts(options...), + ) } // CreateProjectDeployTokenOptions represents the available CreateProjectDeployToken() options. @@ -147,48 +154,22 @@ type CreateProjectDeployTokenOptions struct { Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"` } -// CreateProjectDeployToken creates a new deploy token for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#create-a-project-deploy-token func (s *DeployTokensService) CreateProjectDeployToken(pid any, opt *CreateProjectDeployTokenOptions, options ...RequestOptionFunc) (*DeployToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deploy_tokens", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(DeployToken) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*DeployToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/deploy_tokens", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteProjectDeployToken removes a deploy token from the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#delete-a-project-deploy-token -func (s *DeployTokensService) DeleteProjectDeployToken(pid any, deployToken int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/deploy_tokens/%d", PathEscape(project), deployToken) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DeployTokensService) DeleteProjectDeployToken(pid any, deployToken int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/deploy_tokens/%d", ProjectID{pid}, deployToken), + withRequestOpts(options...), + ) + return resp, err } // ListGroupDeployTokensOptions represents the available ListGroupDeployTokens() @@ -196,56 +177,23 @@ func (s *DeployTokensService) DeleteProjectDeployToken(pid any, deployToken int, // // GitLab API docs: // https://docs.gitlab.com/api/deploy_tokens/#list-group-deploy-tokens -type ListGroupDeployTokensOptions ListOptions +type ListGroupDeployTokensOptions struct { + ListOptions +} -// ListGroupDeployTokens gets a list of a groupโ€™s deploy tokens. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#list-group-deploy-tokens func (s *DeployTokensService) ListGroupDeployTokens(gid any, opt *ListGroupDeployTokensOptions, options ...RequestOptionFunc) ([]*DeployToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/deploy_tokens", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ts []*DeployToken - resp, err := s.client.Do(req, &ts) - if err != nil { - return nil, resp, err - } - - return ts, resp, nil + return do[[]*DeployToken](s.client, + withPath("groups/%s/deploy_tokens", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetGroupDeployToken gets a single deploy token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#get-a-group-deploy-token -func (s *DeployTokensService) GetGroupDeployToken(gid any, deployToken int, options ...RequestOptionFunc) (*DeployToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/deploy_tokens/%d", PathEscape(group), deployToken) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(DeployToken) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *DeployTokensService) GetGroupDeployToken(gid any, deployToken int64, options ...RequestOptionFunc) (*DeployToken, *Response, error) { + return do[*DeployToken](s.client, + withPath("groups/%s/deploy_tokens/%d", GroupID{gid}, deployToken), + withRequestOpts(options...), + ) } // CreateGroupDeployTokenOptions represents the available CreateGroupDeployToken() options. @@ -259,46 +207,20 @@ type CreateGroupDeployTokenOptions struct { Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"` } -// CreateGroupDeployToken creates a new deploy token for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#create-a-group-deploy-token func (s *DeployTokensService) CreateGroupDeployToken(gid any, opt *CreateGroupDeployTokenOptions, options ...RequestOptionFunc) (*DeployToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/deploy_tokens", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(DeployToken) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*DeployToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/deploy_tokens", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteGroupDeployToken removes a deploy token from the group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deploy_tokens/#delete-a-group-deploy-token -func (s *DeployTokensService) DeleteGroupDeployToken(gid any, deployToken int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/deploy_tokens/%d", PathEscape(group), deployToken) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DeployTokensService) DeleteGroupDeployToken(gid any, deployToken int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/deploy_tokens/%d", GroupID{gid}, deployToken), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/deployments.go b/vendor/gitlab.com/gitlab-org/api/client-go/deployments.go index 7368477c9..77405df2f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/deployments.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/deployments.go @@ -16,7 +16,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -24,12 +23,45 @@ import ( type ( // DeploymentsServiceInterface defines all the API methods for the DeploymentsService DeploymentsServiceInterface interface { + // ListProjectDeployments gets a list of deployments in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#list-project-deployments + // ListProjectDeployments gets a list of deployments in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#list-project-deployments ListProjectDeployments(pid any, opts *ListProjectDeploymentsOptions, options ...RequestOptionFunc) ([]*Deployment, *Response, error) - GetProjectDeployment(pid any, deployment int, options ...RequestOptionFunc) (*Deployment, *Response, error) + + // GetProjectDeployment gets a specific deployment for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#get-a-specific-deployment + GetProjectDeployment(pid any, deployment int64, options ...RequestOptionFunc) (*Deployment, *Response, error) + + // CreateProjectDeployment creates a project deployment. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#create-a-deployment CreateProjectDeployment(pid any, opt *CreateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) - UpdateProjectDeployment(pid any, deployment int, opt *UpdateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) - ApproveOrRejectProjectDeployment(pid any, deployment int, opt *ApproveOrRejectProjectDeploymentOptions, options ...RequestOptionFunc) (*Response, error) - DeleteProjectDeployment(pid any, deployment int, options ...RequestOptionFunc) (*Response, error) + + // UpdateProjectDeployment updates a project deployment. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#update-a-deployment + UpdateProjectDeployment(pid any, deployment int64, opt *UpdateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) + + // ApproveOrRejectProjectDeployment approves or rejects a blocked deployment. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#approve-or-reject-a-blocked-deployment + ApproveOrRejectProjectDeployment(pid any, deployment int64, opt *ApproveOrRejectProjectDeploymentOptions, options ...RequestOptionFunc) (*Response, error) + + // DeleteProjectDeployment deletes a specific deployment. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#delete-a-specific-deployment + DeleteProjectDeployment(pid any, deployment int64, options ...RequestOptionFunc) (*Response, error) } // DeploymentsService handles communication with the deployment related methods @@ -43,41 +75,47 @@ type ( var _ DeploymentsServiceInterface = (*DeploymentsService)(nil) -// Deployment represents the Gitlab deployment +// Deployment represents the GitLab deployment type Deployment struct { - ID int `json:"id"` - IID int `json:"iid"` - Ref string `json:"ref"` - SHA string `json:"sha"` - Status string `json:"status"` - CreatedAt *time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at"` - User *ProjectUser `json:"user"` - Environment *Environment `json:"environment"` - Deployable struct { - ID int `json:"id"` - Status string `json:"status"` - Stage string `json:"stage"` - Name string `json:"name"` - Ref string `json:"ref"` - Tag bool `json:"tag"` - Coverage float64 `json:"coverage"` - CreatedAt *time.Time `json:"created_at"` - StartedAt *time.Time `json:"started_at"` - FinishedAt *time.Time `json:"finished_at"` - Duration float64 `json:"duration"` - User *User `json:"user"` - Commit *Commit `json:"commit"` - Pipeline struct { - ID int `json:"id"` - SHA string `json:"sha"` - Ref string `json:"ref"` - Status string `json:"status"` - CreatedAt *time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at"` - } `json:"pipeline"` - Runner *Runner `json:"runner"` - } `json:"deployable"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + Ref string `json:"ref"` + SHA string `json:"sha"` + Status string `json:"status"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + User *ProjectUser `json:"user"` + Environment *Environment `json:"environment"` + Deployable DeploymentDeployable `json:"deployable"` +} + +// DeploymentDeployable represents the Gitlab deployment deployable +type DeploymentDeployable struct { + ID int64 `json:"id"` + Status string `json:"status"` + Stage string `json:"stage"` + Name string `json:"name"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + Coverage float64 `json:"coverage"` + CreatedAt *time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at"` + FinishedAt *time.Time `json:"finished_at"` + Duration float64 `json:"duration"` + User *User `json:"user"` + Commit *Commit `json:"commit"` + Pipeline DeploymentDeployablePipeline `json:"pipeline"` + Runner *Runner `json:"runner"` +} + +// DeploymentDeployablePipeline represents the Gitlab deployment deployable pipeline +type DeploymentDeployablePipeline struct { + ID int64 `json:"id"` + SHA string `json:"sha"` + Ref string `json:"ref"` + Status string `json:"status"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` } // ListProjectDeploymentsOptions represents the available ListProjectDeployments() options. @@ -91,63 +129,28 @@ type ListProjectDeploymentsOptions struct { Environment *string `url:"environment,omitempty" json:"environment,omitempty"` Status *string `url:"status,omitempty" json:"status,omitempty"` - // Only for Gitlab versions less than 14 + // Only for GitLab versions less than 14 UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` - // Only for Gitlab 14 or higher + // Only for GitLab 14 or higher FinishedAfter *time.Time `url:"finished_after,omitempty" json:"finished_after,omitempty"` FinishedBefore *time.Time `url:"finished_before,omitempty" json:"finished_before,omitempty"` } -// ListProjectDeployments gets a list of deployments in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#list-project-deployments func (s *DeploymentsService) ListProjectDeployments(pid any, opts *ListProjectDeploymentsOptions, options ...RequestOptionFunc) ([]*Deployment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deployments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var ds []*Deployment - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil + return do[[]*Deployment](s.client, + withPath("projects/%s/deployments", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// GetProjectDeployment get a deployment for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#get-a-specific-deployment -func (s *DeploymentsService) GetProjectDeployment(pid any, deployment int, options ...RequestOptionFunc) (*Deployment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deployments/%d", PathEscape(project), deployment) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Deployment) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DeploymentsService) GetProjectDeployment(pid any, deployment int64, options ...RequestOptionFunc) (*Deployment, *Response, error) { + return do[*Deployment](s.client, + withPath("projects/%s/deployments/%d", ProjectID{pid}, deployment), + withRequestOpts(options...), + ) } // CreateProjectDeploymentOptions represents the available @@ -163,29 +166,13 @@ type CreateProjectDeploymentOptions struct { Status *DeploymentStatusValue `url:"status,omitempty" json:"status,omitempty"` } -// CreateProjectDeployment creates a project deployment. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#create-a-deployment func (s *DeploymentsService) CreateProjectDeployment(pid any, opt *CreateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deployments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Deployment) - resp, err := s.client.Do(req, &d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil + return do[*Deployment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/deployments", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateProjectDeploymentOptions represents the available @@ -197,29 +184,13 @@ type UpdateProjectDeploymentOptions struct { Status *DeploymentStatusValue `url:"status,omitempty" json:"status,omitempty"` } -// UpdateProjectDeployment updates a project deployment. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#update-a-deployment -func (s *DeploymentsService) UpdateProjectDeployment(pid any, deployment int, opt *UpdateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deployments/%d", PathEscape(project), deployment) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Deployment) - resp, err := s.client.Do(req, &d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DeploymentsService) UpdateProjectDeployment(pid any, deployment int64, opt *UpdateProjectDeploymentOptions, options ...RequestOptionFunc) (*Deployment, *Response, error) { + return do[*Deployment](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/deployments/%d", ProjectID{pid}, deployment), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ApproveOrRejectProjectDeploymentOptions represents the available @@ -233,42 +204,21 @@ type ApproveOrRejectProjectDeploymentOptions struct { RepresentedAs *string `url:"represented_as,omitempty" json:"represented_as,omitempty"` } -// ApproveOrRejectProjectDeployment approve or reject a blocked deployment. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#approve-or-reject-a-blocked-deployment -func (s *DeploymentsService) ApproveOrRejectProjectDeployment(pid any, deployment int, - opt *ApproveOrRejectProjectDeploymentOptions, options ...RequestOptionFunc, -) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/deployments/%d/approval", PathEscape(project), deployment) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DeploymentsService) ApproveOrRejectProjectDeployment(pid any, deployment int64, opt *ApproveOrRejectProjectDeploymentOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/deployments/%d/approval", ProjectID{pid}, deployment), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// DeleteProjectDeployment delete a project deployment. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#delete-a-specific-deployment -func (s *DeploymentsService) DeleteProjectDeployment(pid any, deployment int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/deployments/%d", PathEscape(project), deployment) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DeploymentsService) DeleteProjectDeployment(pid any, deployment int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/deployments/%d", ProjectID{pid}, deployment), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/deployments_merge_requests.go b/vendor/gitlab.com/gitlab-org/api/client-go/deployments_merge_requests.go index a2b0e717c..4d418e51d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/deployments_merge_requests.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/deployments_merge_requests.go @@ -11,17 +11,17 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -package gitlab -import ( - "fmt" - "net/http" -) +package gitlab type ( // DeploymentMergeRequestsServiceInterface defines all the API methods for the DeploymentMergeRequestsService DeploymentMergeRequestsServiceInterface interface { - ListDeploymentMergeRequests(pid any, deployment int, opts *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) + // ListDeploymentMergeRequests get the merge requests associated with deployment. + // + // GitLab API docs: + // https://docs.gitlab.com/api/deployments/#list-of-merge-requests-associated-with-a-deployment + ListDeploymentMergeRequests(pid any, deployment int64, opts *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) } // DeploymentMergeRequestsService handles communication with the deployment's @@ -36,27 +36,10 @@ type ( var _ DeploymentMergeRequestsServiceInterface = (*DeploymentMergeRequestsService)(nil) -// ListDeploymentMergeRequests get the merge requests associated with deployment. -// -// GitLab API docs: -// https://docs.gitlab.com/api/deployments/#list-of-merge-requests-associated-with-a-deployment -func (s *DeploymentMergeRequestsService) ListDeploymentMergeRequests(pid any, deployment int, opts *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/deployments/%d/merge_requests", PathEscape(project), deployment) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var mrs []*MergeRequest - resp, err := s.client.Do(req, &mrs) - if err != nil { - return nil, resp, err - } - - return mrs, resp, nil +func (s *DeploymentMergeRequestsService) ListDeploymentMergeRequests(pid any, deployment int64, opts *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) { + return do[[]*MergeRequest](s.client, + withPath("projects/%s/deployments/%d/merge_requests", ProjectID{pid}, deployment), + withAPIOpts(opts), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/discussions.go b/vendor/gitlab.com/gitlab-org/api/client-go/discussions.go index f73a865ad..e305dcaff 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/discussions.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/discussions.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,37 +24,205 @@ import ( type ( // DiscussionsServiceInterface defines all the API methods for the DiscussionsService DiscussionsServiceInterface interface { - ListIssueDiscussions(pid any, issue int, opt *ListIssueDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) - GetIssueDiscussion(pid any, issue int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) - CreateIssueDiscussion(pid any, issue int, opt *CreateIssueDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) - AddIssueDiscussionNote(pid any, issue int, discussion string, opt *AddIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateIssueDiscussionNote(pid any, issue int, discussion string, note int, opt *UpdateIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteIssueDiscussionNote(pid any, issue int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) - ListSnippetDiscussions(pid any, snippet int, opt *ListSnippetDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) - GetSnippetDiscussion(pid any, snippet int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) - CreateSnippetDiscussion(pid any, snippet int, opt *CreateSnippetDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) - AddSnippetDiscussionNote(pid any, snippet int, discussion string, opt *AddSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateSnippetDiscussionNote(pid any, snippet int, discussion string, note int, opt *UpdateSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteSnippetDiscussionNote(pid any, snippet int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) - ListGroupEpicDiscussions(gid any, epic int, opt *ListGroupEpicDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) - GetEpicDiscussion(gid any, epic int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) - CreateEpicDiscussion(gid any, epic int, opt *CreateEpicDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) - AddEpicDiscussionNote(gid any, epic int, discussion string, opt *AddEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateEpicDiscussionNote(gid any, epic int, discussion string, note int, opt *UpdateEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteEpicDiscussionNote(gid any, epic int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) - ListMergeRequestDiscussions(pid any, mergeRequest int, opt *ListMergeRequestDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) - GetMergeRequestDiscussion(pid any, mergeRequest int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) - CreateMergeRequestDiscussion(pid any, mergeRequest int, opt *CreateMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) - ResolveMergeRequestDiscussion(pid any, mergeRequest int, discussion string, opt *ResolveMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) - AddMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, opt *AddMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, note int, opt *UpdateMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) + // ListIssueDiscussions gets a list of all discussions for a single issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#list-project-issue-discussion-items + ListIssueDiscussions(pid any, issue int64, opt *ListIssueDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) + + // GetIssueDiscussion returns a single discussion for a specific project issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-issue-discussion-item + GetIssueDiscussion(pid any, issue int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // CreateIssueDiscussion creates a new discussion to a single project issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-issue-thread + CreateIssueDiscussion(pid any, issue int64, opt *CreateIssueDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // AddIssueDiscussionNote creates a new note in an existing discussion of an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-issue-thread + AddIssueDiscussionNote(pid any, issue int64, discussion string, opt *AddIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // UpdateIssueDiscussionNote modifies an existing note in a discussion of an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#modify-existing-issue-thread-note + UpdateIssueDiscussionNote(pid any, issue int64, discussion string, note int64, opt *UpdateIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // DeleteIssueDiscussionNote deletes a note from a discussion of an issue. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#delete-an-issue-thread-note + DeleteIssueDiscussionNote(pid any, issue int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) + + // ListSnippetDiscussions gets all discussions for a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#list-project-snippet-discussion-items + ListSnippetDiscussions(pid any, snippet int64, opt *ListSnippetDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) + + // GetSnippetDiscussion returns a single discussion for a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-snippet-discussion-item + GetSnippetDiscussion(pid any, snippet int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // CreateSnippetDiscussion creates a new discussion for a snippet. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-snippet-thread + CreateSnippetDiscussion(pid any, snippet int64, opt *CreateSnippetDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // AddSnippetDiscussionNote adds a new note to a snippet discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-snippet-thread + AddSnippetDiscussionNote(pid any, snippet int64, discussion string, opt *AddSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // UpdateSnippetDiscussionNote modifies an existing note in a snippet discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#modify-existing-snippet-thread-note + UpdateSnippetDiscussionNote(pid any, snippet int64, discussion string, note int64, opt *UpdateSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // DeleteSnippetDiscussionNote deletes a note from a snippet discussion. + // + // GitLab API docs: https://docs.gitlab.com/api/discussions/#delete-a-snippet-thread-note + DeleteSnippetDiscussionNote(pid any, snippet int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) + + // ListGroupEpicDiscussions gets all discussions for a group epic. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#list-group-epic-discussion-items + ListGroupEpicDiscussions(gid any, epic int64, opt *ListGroupEpicDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) + + // GetEpicDiscussion returns a single discussion for a group epic. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-epic-discussion-item + GetEpicDiscussion(gid any, epic int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // CreateEpicDiscussion creates a new discussion for a group epic. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-epic-thread + CreateEpicDiscussion(gid any, epic int64, opt *CreateEpicDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // AddEpicDiscussionNote adds a new note to an epic discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-epic-thread + AddEpicDiscussionNote(gid any, epic int64, discussion string, opt *AddEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // UpdateEpicDiscussionNote modifies an existing note in an epic discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#modify-existing-epic-thread-note + UpdateEpicDiscussionNote(gid any, epic int64, discussion string, note int64, opt *UpdateEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // DeleteEpicDiscussionNote deletes a note from an epic discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#delete-an-epic-thread-note + DeleteEpicDiscussionNote(gid any, epic int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) + + // ListMergeRequestDiscussions gets all discussions for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#list-project-merge-request-discussion-items + ListMergeRequestDiscussions(pid any, mergeRequest int64, opt *ListMergeRequestDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) + + // GetMergeRequestDiscussion returns a single discussion for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-merge-request-discussion-item + GetMergeRequestDiscussion(pid any, mergeRequest int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // CreateMergeRequestDiscussion creates a new discussion for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-merge-request-thread + CreateMergeRequestDiscussion(pid any, mergeRequest int64, opt *CreateMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // ResolveMergeRequestDiscussion resolves or unresolves a merge request discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#resolve-a-merge-request-thread + ResolveMergeRequestDiscussion(pid any, mergeRequest int64, discussion string, opt *ResolveMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // AddMergeRequestDiscussionNote adds a new note to a merge request discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-merge-request-thread + AddMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, opt *AddMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // UpdateMergeRequestDiscussionNote modifies an existing note in a merge request discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#modify-an-existing-merge-request-thread-note + UpdateMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, note int64, opt *UpdateMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // DeleteMergeRequestDiscussionNote deletes a note from a merge request discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#delete-a-merge-request-thread-note + DeleteMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) + + // ListCommitDiscussions gets all discussions for a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#list-project-commit-discussion-items ListCommitDiscussions(pid any, commit string, opt *ListCommitDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) + + // GetCommitDiscussion returns a single discussion for a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-commit-discussion-item + + // GetCommitDiscussion returns a single discussion for a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#get-single-commit-discussion-item GetCommitDiscussion(pid any, commit string, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // CreateCommitDiscussion creates a new discussion for a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-commit-thread + + // CreateCommitDiscussion creates a new discussion for a commit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#create-new-commit-thread CreateCommitDiscussion(pid any, commit string, opt *CreateCommitDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) + + // AddCommitDiscussionNote adds a new note to a commit discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-commit-thread + + // AddCommitDiscussionNote adds a new note to a commit discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#add-note-to-existing-commit-thread AddCommitDiscussionNote(pid any, commit string, discussion string, opt *AddCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateCommitDiscussionNote(pid any, commit string, discussion string, note int, opt *UpdateCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteCommitDiscussionNote(pid any, commit string, discussion string, note int, options ...RequestOptionFunc) (*Response, error) + + // UpdateCommitDiscussionNote modifies an existing note in a commit discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#modify-an-existing-commit-thread-note + UpdateCommitDiscussionNote(pid any, commit string, discussion string, note int64, opt *UpdateCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + + // DeleteCommitDiscussionNote deletes a note from a commit discussion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/discussions/#delete-a-commit-thread-note + DeleteCommitDiscussionNote(pid any, commit string, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) } // DiscussionsService handles communication with the discussions related @@ -87,61 +254,23 @@ func (d Discussion) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/discussions/#list-project-issue-discussion-items -type ListIssueDiscussionsOptions ListOptions - -// ListIssueDiscussions gets a list of all discussions for a single -// issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#list-project-issue-discussion-items -func (s *DiscussionsService) ListIssueDiscussions(pid any, issue int, opt *ListIssueDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ds []*Discussion - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil +type ListIssueDiscussionsOptions struct { + ListOptions } -// GetIssueDiscussion returns a single discussion for a specific project issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#get-single-issue-discussion-item -func (s *DiscussionsService) GetIssueDiscussion(pid any, issue int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s", - PathEscape(project), - issue, - discussion, +func (s *DiscussionsService) ListIssueDiscussions(pid any, issue int64, opt *ListIssueDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { + return do[[]*Discussion](s.client, + withPath("projects/%s/issues/%d/discussions", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), ) +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DiscussionsService) GetIssueDiscussion(pid any, issue int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withPath("projects/%s/issues/%d/discussions/%s", ProjectID{pid}, issue, discussion), + withRequestOpts(options...), + ) } // CreateIssueDiscussionOptions represents the available CreateIssueDiscussion() @@ -154,29 +283,13 @@ type CreateIssueDiscussionOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// CreateIssueDiscussion creates a new discussion to a single project issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#create-new-issue-thread -func (s *DiscussionsService) CreateIssueDiscussion(pid any, issue int, opt *CreateIssueDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DiscussionsService) CreateIssueDiscussion(pid any, issue int64, opt *CreateIssueDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/discussions", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddIssueDiscussionNoteOptions represents the available AddIssueDiscussionNote() @@ -189,33 +302,13 @@ type AddIssueDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// AddIssueDiscussionNote creates a new discussion to a single project issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#add-note-to-existing-issue-thread -func (s *DiscussionsService) AddIssueDiscussionNote(pid any, issue int, discussion string, opt *AddIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes", - PathEscape(project), - issue, - discussion, +func (s *DiscussionsService) AddIssueDiscussionNote(pid any, issue int64, discussion string, opt *AddIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/discussions/%s/notes", ProjectID{pid}, issue, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } // UpdateIssueDiscussionNoteOptions represents the available @@ -228,58 +321,22 @@ type UpdateIssueDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// UpdateIssueDiscussionNote modifies existing discussion of an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#modify-existing-issue-thread-note -func (s *DiscussionsService) UpdateIssueDiscussionNote(pid any, issue int, discussion string, note int, opt *UpdateIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes/%d", - PathEscape(project), - issue, - discussion, - note, +func (s *DiscussionsService) UpdateIssueDiscussionNote(pid any, issue int64, discussion string, note int64, opt *UpdateIssueDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/issues/%d/discussions/%s/notes/%d", ProjectID{pid}, issue, discussion, note), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } -// DeleteIssueDiscussionNote deletes an existing discussion of an issue. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#delete-an-issue-thread-note -func (s *DiscussionsService) DeleteIssueDiscussionNote(pid any, issue int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/discussions/%s/notes/%d", - PathEscape(project), - issue, - discussion, - note, +func (s *DiscussionsService) DeleteIssueDiscussionNote(pid any, issue int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/issues/%d/discussions/%s/notes/%d", ProjectID{pid}, issue, discussion, note), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // ListSnippetDiscussionsOptions represents the available ListSnippetDiscussions() @@ -287,61 +344,23 @@ func (s *DiscussionsService) DeleteIssueDiscussionNote(pid any, issue int, discu // // GitLab API docs: // https://docs.gitlab.com/api/discussions/#list-project-snippet-discussion-items -type ListSnippetDiscussionsOptions ListOptions - -// ListSnippetDiscussions gets a list of all discussions for a single -// snippet. Snippet discussions are comments users can post to a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#list-project-snippet-discussion-items -func (s *DiscussionsService) ListSnippetDiscussions(pid any, snippet int, opt *ListSnippetDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ds []*Discussion - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil +type ListSnippetDiscussionsOptions struct { + ListOptions } -// GetSnippetDiscussion returns a single discussion for a given snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#get-single-snippet-discussion-item -func (s *DiscussionsService) GetSnippetDiscussion(pid any, snippet int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s", - PathEscape(project), - snippet, - discussion, +func (s *DiscussionsService) ListSnippetDiscussions(pid any, snippet int64, opt *ListSnippetDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { + return do[[]*Discussion](s.client, + withPath("projects/%s/snippets/%d/discussions", ProjectID{pid}, snippet), + withAPIOpts(opt), + withRequestOpts(options...), ) +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DiscussionsService) GetSnippetDiscussion(pid any, snippet int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withPath("projects/%s/snippets/%d/discussions/%s", ProjectID{pid}, snippet, discussion), + withRequestOpts(options...), + ) } // CreateSnippetDiscussionOptions represents the available @@ -354,30 +373,13 @@ type CreateSnippetDiscussionOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// CreateSnippetDiscussion creates a new discussion for a single snippet. -// Snippet discussions are comments users can post to a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#create-new-snippet-thread -func (s *DiscussionsService) CreateSnippetDiscussion(pid any, snippet int, opt *CreateSnippetDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil +func (s *DiscussionsService) CreateSnippetDiscussion(pid any, snippet int64, opt *CreateSnippetDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/snippets/%d/discussions", ProjectID{pid}, snippet), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddSnippetDiscussionNoteOptions represents the available @@ -390,34 +392,13 @@ type AddSnippetDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// AddSnippetDiscussionNote creates a new discussion to a single project -// snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#add-note-to-existing-snippet-thread -func (s *DiscussionsService) AddSnippetDiscussionNote(pid any, snippet int, discussion string, opt *AddSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes", - PathEscape(project), - snippet, - discussion, +func (s *DiscussionsService) AddSnippetDiscussionNote(pid any, snippet int64, discussion string, opt *AddSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/snippets/%d/discussions/%s/notes", ProjectID{pid}, snippet, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } // UpdateSnippetDiscussionNoteOptions represents the available @@ -430,58 +411,22 @@ type UpdateSnippetDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// UpdateSnippetDiscussionNote modifies existing discussion of a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#modify-existing-snippet-thread-note -func (s *DiscussionsService) UpdateSnippetDiscussionNote(pid any, snippet int, discussion string, note int, opt *UpdateSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes/%d", - PathEscape(project), - snippet, - discussion, - note, +func (s *DiscussionsService) UpdateSnippetDiscussionNote(pid any, snippet int64, discussion string, note int64, opt *UpdateSnippetDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/snippets/%d/discussions/%s/notes/%d", ProjectID{pid}, snippet, discussion, note), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } -// DeleteSnippetDiscussionNote deletes an existing discussion of a snippet. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#delete-a-snippet-thread-note -func (s *DiscussionsService) DeleteSnippetDiscussionNote(pid any, snippet int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/discussions/%s/notes/%d", - PathEscape(project), - snippet, - discussion, - note, +func (s *DiscussionsService) DeleteSnippetDiscussionNote(pid any, snippet int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/snippets/%d/discussions/%s/notes/%d", ProjectID{pid}, snippet, discussion, note), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // ListGroupEpicDiscussionsOptions represents the available @@ -489,64 +434,23 @@ func (s *DiscussionsService) DeleteSnippetDiscussionNote(pid any, snippet int, d // // GitLab API docs: // https://docs.gitlab.com/api/discussions/#list-group-epic-discussion-items -type ListGroupEpicDiscussionsOptions ListOptions +type ListGroupEpicDiscussionsOptions struct { + ListOptions +} -// ListGroupEpicDiscussions gets a list of all discussions for a single -// epic. Epic discussions are comments users can post to a epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#list-group-epic-discussion-items -func (s *DiscussionsService) ListGroupEpicDiscussions(gid any, epic int, opt *ListGroupEpicDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions", - PathEscape(group), - epic, +func (s *DiscussionsService) ListGroupEpicDiscussions(gid any, epic int64, opt *ListGroupEpicDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { + return do[[]*Discussion](s.client, + withPath("groups/%s/epics/%d/discussions", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ds []*Discussion - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil } -// GetEpicDiscussion returns a single discussion for a given epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#get-single-epic-discussion-item -func (s *DiscussionsService) GetEpicDiscussion(gid any, epic int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s", - PathEscape(group), - epic, - discussion, +func (s *DiscussionsService) GetEpicDiscussion(gid any, epic int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withPath("groups/%s/epics/%d/discussions/%s", GroupID{gid}, epic, discussion), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // CreateEpicDiscussionOptions represents the available CreateEpicDiscussion() @@ -559,33 +463,13 @@ type CreateEpicDiscussionOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// CreateEpicDiscussion creates a new discussion for a single epic. Epic -// discussions are comments users can post to a epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#create-new-epic-thread -func (s *DiscussionsService) CreateEpicDiscussion(gid any, epic int, opt *CreateEpicDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions", - PathEscape(group), - epic, +func (s *DiscussionsService) CreateEpicDiscussion(gid any, epic int64, opt *CreateEpicDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/epics/%d/discussions", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // AddEpicDiscussionNoteOptions represents the available @@ -598,33 +482,13 @@ type AddEpicDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// AddEpicDiscussionNote creates a new discussion to a single project epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#add-note-to-existing-epic-thread -func (s *DiscussionsService) AddEpicDiscussionNote(gid any, epic int, discussion string, opt *AddEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes", - PathEscape(group), - epic, - discussion, +func (s *DiscussionsService) AddEpicDiscussionNote(gid any, epic int64, discussion string, opt *AddEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/epics/%d/discussions/%s/notes", GroupID{gid}, epic, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } // UpdateEpicDiscussionNoteOptions represents the available UpdateEpicDiscussion() @@ -637,58 +501,22 @@ type UpdateEpicDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// UpdateEpicDiscussionNote modifies existing discussion of an epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#modify-existing-epic-thread-note -func (s *DiscussionsService) UpdateEpicDiscussionNote(gid any, epic int, discussion string, note int, opt *UpdateEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes/%d", - PathEscape(group), - epic, - discussion, - note, +func (s *DiscussionsService) UpdateEpicDiscussionNote(gid any, epic int64, discussion string, note int64, opt *UpdateEpicDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/epics/%d/discussions/%s/notes/%d", GroupID{gid}, epic, discussion, note), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } -// DeleteEpicDiscussionNote deletes an existing discussion of a epic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#delete-an-epic-thread-note -func (s *DiscussionsService) DeleteEpicDiscussionNote(gid any, epic int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/discussions/%s/notes/%d", - PathEscape(group), - epic, - discussion, - note, +func (s *DiscussionsService) DeleteEpicDiscussionNote(gid any, epic int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/epics/%d/discussions/%s/notes/%d", GroupID{gid}, epic, discussion, note), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // ListMergeRequestDiscussionsOptions represents the available @@ -696,65 +524,23 @@ func (s *DiscussionsService) DeleteEpicDiscussionNote(gid any, epic int, discuss // // GitLab API docs: // https://docs.gitlab.com/api/discussions/#list-project-merge-request-discussion-items -type ListMergeRequestDiscussionsOptions ListOptions +type ListMergeRequestDiscussionsOptions struct { + ListOptions +} -// ListMergeRequestDiscussions gets a list of all discussions for a single -// merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#list-project-merge-request-discussion-items -func (s *DiscussionsService) ListMergeRequestDiscussions(pid any, mergeRequest int, opt *ListMergeRequestDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions", - PathEscape(project), - mergeRequest, +func (s *DiscussionsService) ListMergeRequestDiscussions(pid any, mergeRequest int64, opt *ListMergeRequestDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { + return do[[]*Discussion](s.client, + withPath("projects/%s/merge_requests/%d/discussions", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ds []*Discussion - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil } -// GetMergeRequestDiscussion returns a single discussion for a given merge -// request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#get-single-merge-request-discussion-item -func (s *DiscussionsService) GetMergeRequestDiscussion(pid any, mergeRequest int, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s", - PathEscape(project), - mergeRequest, - discussion, +func (s *DiscussionsService) GetMergeRequestDiscussion(pid any, mergeRequest int64, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withPath("projects/%s/merge_requests/%d/discussions/%s", ProjectID{pid}, mergeRequest, discussion), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // CreateMergeRequestDiscussionOptions represents the available @@ -777,11 +563,11 @@ type PositionOptions struct { NewPath *string `url:"new_path,omitempty" json:"new_path,omitempty"` OldPath *string `url:"old_path,omitempty" json:"old_path,omitempty"` PositionType *string `url:"position_type,omitempty" json:"position_type"` - NewLine *int `url:"new_line,omitempty" json:"new_line,omitempty"` - OldLine *int `url:"old_line,omitempty" json:"old_line,omitempty"` + NewLine *int64 `url:"new_line,omitempty" json:"new_line,omitempty"` + OldLine *int64 `url:"old_line,omitempty" json:"old_line,omitempty"` LineRange *LineRangeOptions `url:"line_range,omitempty" json:"line_range,omitempty"` - Width *int `url:"width,omitempty" json:"width,omitempty"` - Height *int `url:"height,omitempty" json:"height,omitempty"` + Width *int64 `url:"width,omitempty" json:"width,omitempty"` + Height *int64 `url:"height,omitempty" json:"height,omitempty"` X *float64 `url:"x,omitempty" json:"x,omitempty"` Y *float64 `url:"y,omitempty" json:"y,omitempty"` } @@ -796,37 +582,17 @@ type LineRangeOptions struct { type LinePositionOptions struct { LineCode *string `url:"line_code,omitempty" json:"line_code,omitempty"` Type *string `url:"type,omitempty" json:"type,omitempty"` - OldLine *int `url:"old_line,omitempty" json:"old_line,omitempty"` - NewLine *int `url:"new_line,omitempty" json:"new_line,omitempty"` + OldLine *int64 `url:"old_line,omitempty" json:"old_line,omitempty"` + NewLine *int64 `url:"new_line,omitempty" json:"new_line,omitempty"` } -// CreateMergeRequestDiscussion creates a new discussion for a single merge -// request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#create-new-merge-request-thread -func (s *DiscussionsService) CreateMergeRequestDiscussion(pid any, mergeRequest int, opt *CreateMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions", - PathEscape(project), - mergeRequest, +func (s *DiscussionsService) CreateMergeRequestDiscussion(pid any, mergeRequest int64, opt *CreateMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/discussions", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // ResolveMergeRequestDiscussionOptions represents the available @@ -838,34 +604,13 @@ type ResolveMergeRequestDiscussionOptions struct { Resolved *bool `url:"resolved,omitempty" json:"resolved,omitempty"` } -// ResolveMergeRequestDiscussion resolves/unresolves whole discussion of a merge -// request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#resolve-a-merge-request-thread -func (s *DiscussionsService) ResolveMergeRequestDiscussion(pid any, mergeRequest int, discussion string, opt *ResolveMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s", - PathEscape(project), - mergeRequest, - discussion, +func (s *DiscussionsService) ResolveMergeRequestDiscussion(pid any, mergeRequest int64, discussion string, opt *ResolveMergeRequestDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { + return do[*Discussion](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/discussions/%s", ProjectID{pid}, mergeRequest, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // AddMergeRequestDiscussionNoteOptions represents the available @@ -878,34 +623,13 @@ type AddMergeRequestDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// AddMergeRequestDiscussionNote creates a new discussion to a single project -// merge request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#add-note-to-existing-merge-request-thread -func (s *DiscussionsService) AddMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, opt *AddMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s/notes", - PathEscape(project), - mergeRequest, - discussion, +func (s *DiscussionsService) AddMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, opt *AddMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/discussions/%s/notes", ProjectID{pid}, mergeRequest, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } // UpdateMergeRequestDiscussionNoteOptions represents the available @@ -919,60 +643,22 @@ type UpdateMergeRequestDiscussionNoteOptions struct { Resolved *bool `url:"resolved,omitempty" json:"resolved,omitempty"` } -// UpdateMergeRequestDiscussionNote modifies existing discussion of a merge -// request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#modify-an-existing-merge-request-thread-note -func (s *DiscussionsService) UpdateMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, note int, opt *UpdateMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s/notes/%d", - PathEscape(project), - mergeRequest, - discussion, - note, +func (s *DiscussionsService) UpdateMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, note int64, opt *UpdateMergeRequestDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/discussions/%s/notes/%d", ProjectID{pid}, mergeRequest, discussion, note), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } -// DeleteMergeRequestDiscussionNote deletes an existing discussion of a merge -// request. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#delete-a-merge-request-thread-note -func (s *DiscussionsService) DeleteMergeRequestDiscussionNote(pid any, mergeRequest int, discussion string, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/discussions/%s/notes/%d", - PathEscape(project), - mergeRequest, - discussion, - note, +func (s *DiscussionsService) DeleteMergeRequestDiscussionNote(pid any, mergeRequest int64, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/discussions/%s/notes/%d", ProjectID{pid}, mergeRequest, discussion, note), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // ListCommitDiscussionsOptions represents the available @@ -980,65 +666,23 @@ func (s *DiscussionsService) DeleteMergeRequestDiscussionNote(pid any, mergeRequ // // GitLab API docs: // https://docs.gitlab.com/api/discussions/#list-project-commit-discussion-items -type ListCommitDiscussionsOptions ListOptions +type ListCommitDiscussionsOptions struct { + ListOptions +} -// ListCommitDiscussions gets a list of all discussions for a single -// commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#list-project-commit-discussion-items func (s *DiscussionsService) ListCommitDiscussions(pid any, commit string, opt *ListCommitDiscussionsOptions, options ...RequestOptionFunc) ([]*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions", - PathEscape(project), - commit, + return do[[]*Discussion](s.client, + withPath("projects/%s/repository/commits/%s/discussions", ProjectID{pid}, commit), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ds []*Discussion - resp, err := s.client.Do(req, &ds) - if err != nil { - return nil, resp, err - } - - return ds, resp, nil } -// GetCommitDiscussion returns a single discussion for a specific project -// commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#get-single-commit-discussion-item func (s *DiscussionsService) GetCommitDiscussion(pid any, commit string, discussion string, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s", - PathEscape(project), - commit, - discussion, + return do[*Discussion](s.client, + withPath("projects/%s/repository/commits/%s/discussions/%s", ProjectID{pid}, commit, discussion), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // CreateCommitDiscussionOptions represents the available @@ -1052,32 +696,13 @@ type CreateCommitDiscussionOptions struct { Position *NotePosition `url:"position,omitempty" json:"position,omitempty"` } -// CreateCommitDiscussion creates a new discussion to a single project commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#create-new-commit-thread func (s *DiscussionsService) CreateCommitDiscussion(pid any, commit string, opt *CreateCommitDiscussionOptions, options ...RequestOptionFunc) (*Discussion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions", - PathEscape(project), - commit, + return do[*Discussion](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits/%s/discussions", ProjectID{pid}, commit), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - d := new(Discussion) - resp, err := s.client.Do(req, d) - if err != nil { - return nil, resp, err - } - - return d, resp, nil } // AddCommitDiscussionNoteOptions represents the available @@ -1090,33 +715,13 @@ type AddCommitDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// AddCommitDiscussionNote creates a new discussion to a single project commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#add-note-to-existing-commit-thread func (s *DiscussionsService) AddCommitDiscussionNote(pid any, commit string, discussion string, opt *AddCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes", - PathEscape(project), - commit, - discussion, + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/commits/%s/discussions/%s/notes", ProjectID{pid}, commit, discussion), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } // UpdateCommitDiscussionNoteOptions represents the available @@ -1129,56 +734,20 @@ type UpdateCommitDiscussionNoteOptions struct { CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` } -// UpdateCommitDiscussionNote modifies existing discussion of a commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#modify-an-existing-commit-thread-note -func (s *DiscussionsService) UpdateCommitDiscussionNote(pid any, commit string, discussion string, note int, opt *UpdateCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes/%d", - PathEscape(project), - commit, - discussion, - note, +func (s *DiscussionsService) UpdateCommitDiscussionNote(pid any, commit string, discussion string, note int64, opt *UpdateCommitDiscussionNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/repository/commits/%s/discussions/%s/notes/%d", ProjectID{pid}, commit, discussion, note), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil } -// DeleteCommitDiscussionNote deletes an existing discussion of an commit. -// -// GitLab API docs: -// https://docs.gitlab.com/api/discussions/#delete-a-commit-thread-note -func (s *DiscussionsService) DeleteCommitDiscussionNote(pid any, commit string, discussion string, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/repository/commits/%s/discussions/%s/notes/%d", - PathEscape(project), - commit, - discussion, - note, +func (s *DiscussionsService) DeleteCommitDiscussionNote(pid any, commit string, discussion string, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/repository/commits/%s/discussions/%s/notes/%d", ProjectID{pid}, commit, discussion, note), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/docker-compose.yml b/vendor/gitlab.com/gitlab-org/api/client-go/docker-compose.yml new file mode 100644 index 000000000..d5fdf197e --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/docker-compose.yml @@ -0,0 +1,61 @@ +# Acceptance tests depend on a running GitLab instance. +# Only one of these services should be run at a time. +services: + gitlab-ee-no-license: + image: docker.io/gitlab/gitlab-ee:${GITLAB_CE_VERSION:-latest} + platform: linux/amd64 + shm_size: 256m + ports: + - 8095:80 + environment: + GITLAB_ROOT_PASSWORD: "FoQ7PaTZqWaftrZ7zvAK" + # The token uses the value of GITLAB_TOKEN, which is set in the makefile (unless overridden) + GITLAB_TOKEN: $GITLAB_TOKEN + labels: + client-go/owned: "" + volumes: + - config-ce:/etc/gitlab + - logs-ce:/var/log/gitlab + - data-ce:/var/opt/gitlab + - ${PWD}/scripts/healthcheck_and_setup.sh:/healthcheck-and-setup.sh:Z + - ${PWD}/scripts/gitlab.rb:/etc/gitlab/gitlab.rb:ro + - ${PWD}/certs:/etc/gitlab/ssl:ro + healthcheck: + test: /healthcheck-and-setup.sh + interval: 60s + timeout: 10m + + gitlab-ee: + image: docker.io/gitlab/gitlab-ee:${GITLAB_EE_VERSION:-latest} + platform: linux/amd64 + shm_size: 256m + ports: + - 8095:80 + environment: + GITLAB_ROOT_PASSWORD: "FoQ7PaTZqWaftrZ7zvAK" + # The token uses the value of GITLAB_TOKEN, which is set in the makefile (unless overridden) + GITLAB_TOKEN: $GITLAB_TOKEN + GITLAB_LICENSE_FILE: /Gitlab-license.txt + labels: + client-go/owned: "" + volumes: + - config-ee:/etc/gitlab + - logs-ee:/var/log/gitlab + - data-ee:/var/opt/gitlab + - ${PWD}/scripts/healthcheck_and_setup.sh:/healthcheck-and-setup.sh:Z + - ${PWD}/Gitlab-license.txt:/Gitlab-license.txt:Z + - ${PWD}/scripts/gitlab.rb:/etc/gitlab/gitlab.rb:ro + - ${PWD}/certs:/etc/gitlab/ssl:ro + healthcheck: + test: /healthcheck-and-setup.sh + interval: 60s + timeout: 10m + +volumes: + config-ce: + logs-ce: + data-ce: + config-ee: + logs-ee: + data-ee: + diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/dockerfile_templates.go b/vendor/gitlab.com/gitlab-org/api/client-go/dockerfile_templates.go index 0885b3b88..438cba905 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/dockerfile_templates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/dockerfile_templates.go @@ -16,16 +16,19 @@ package gitlab -import ( - "fmt" - "net/http" - "net/url" -) - type ( // DockerfileTemplatesServiceInterface defines all the API methods for the DockerfileTemplatesService DockerfileTemplatesServiceInterface interface { + // ListTemplates get a list of available Dockerfile templates. + // + // GitLab API docs: + // https://docs.gitlab.com/api/templates/dockerfiles/#list-dockerfile-templates ListTemplates(opt *ListDockerfileTemplatesOptions, options ...RequestOptionFunc) ([]*DockerfileTemplateListItem, *Response, error) + + // GetTemplate get a single Dockerfile template. + // + // GitLab API docs: + // https://docs.gitlab.com/api/templates/dockerfiles/#single-dockerfile-template GetTemplate(key string, options ...RequestOptionFunc) (*DockerfileTemplate, *Response, error) } @@ -60,44 +63,21 @@ type DockerfileTemplateListItem struct { // // GitLab API docs: // https://docs.gitlab.com/api/templates/dockerfiles/#list-dockerfile-templates -type ListDockerfileTemplatesOptions ListOptions +type ListDockerfileTemplatesOptions struct { + ListOptions +} -// ListTemplates get a list of available Dockerfile templates. -// -// GitLab API docs: -// https://docs.gitlab.com/api/templates/dockerfiles/#list-dockerfile-templates func (s *DockerfileTemplatesService) ListTemplates(opt *ListDockerfileTemplatesOptions, options ...RequestOptionFunc) ([]*DockerfileTemplateListItem, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "templates/dockerfiles", opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*DockerfileTemplateListItem - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*DockerfileTemplateListItem](s.client, + withPath("templates/dockerfiles"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetTemplate get a single Dockerfile template. -// -// GitLab API docs: -// https://docs.gitlab.com/api/templates/dockerfiles/#single-dockerfile-template func (s *DockerfileTemplatesService) GetTemplate(key string, options ...RequestOptionFunc) (*DockerfileTemplate, *Response, error) { - u := fmt.Sprintf("templates/dockerfiles/%s", url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(DockerfileTemplate) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*DockerfileTemplate](s.client, + withPath("templates/dockerfiles/%s", key), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/dora_metrics.go b/vendor/gitlab.com/gitlab-org/api/client-go/dora_metrics.go index fd04b352d..5db875ad5 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/dora_metrics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/dora_metrics.go @@ -16,22 +16,26 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( // DORAMetricsServiceInterface defines all the API methods for the DORAMetricsService DORAMetricsServiceInterface interface { + // GetProjectDORAMetrics gets the DORA metrics for a project. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/dora/metrics/#get-project-level-dora-metrics GetProjectDORAMetrics(pid any, opt GetDORAMetricsOptions, options ...RequestOptionFunc) ([]DORAMetric, *Response, error) + + // GetGroupDORAMetrics gets the DORA metrics for a group. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/dora/metrics/#get-group-level-dora-metrics GetGroupDORAMetrics(gid any, opt GetDORAMetricsOptions, options ...RequestOptionFunc) ([]DORAMetric, *Response, error) } // DORAMetricsService handles communication with the DORA metrics related methods // of the GitLab API. // - // Gitlab API docs: https://docs.gitlab.com/api/dora/metrics/ + // GitLab API docs: https://docs.gitlab.com/api/dora/metrics/ DORAMetricsService struct { client *Client } @@ -41,7 +45,7 @@ var _ DORAMetricsServiceInterface = (*DORAMetricsService)(nil) // DORAMetric represents a single DORA metric data point. // -// Gitlab API docs: https://docs.gitlab.com/api/dora/metrics/ +// GitLab API docs: https://docs.gitlab.com/api/dora/metrics/ type DORAMetric struct { Date string `json:"date"` Value float64 `json:"value"` @@ -66,52 +70,18 @@ type GetDORAMetricsOptions struct { StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"` } -// GetProjectDORAMetrics gets the DORA metrics for a project. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/dora/metrics/#get-project-level-dora-metrics func (s *DORAMetricsService) GetProjectDORAMetrics(pid any, opt GetDORAMetricsOptions, options ...RequestOptionFunc) ([]DORAMetric, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/dora/metrics", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var metrics []DORAMetric - resp, err := s.client.Do(req, &metrics) - if err != nil { - return nil, resp, err - } - - return metrics, resp, err + return do[[]DORAMetric](s.client, + withPath("projects/%s/dora/metrics", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetGroupDORAMetrics gets the DORA metrics for a group. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/dora/metrics/#get-group-level-dora-metrics func (s *DORAMetricsService) GetGroupDORAMetrics(gid any, opt GetDORAMetricsOptions, options ...RequestOptionFunc) ([]DORAMetric, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/dora/metrics", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var metrics []DORAMetric - resp, err := s.client.Do(req, &metrics) - if err != nil { - return nil, resp, err - } - - return metrics, resp, err + return do[[]DORAMetric](s.client, + withPath("groups/%s/dora/metrics", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/draft_notes.go b/vendor/gitlab.com/gitlab-org/api/client-go/draft_notes.go index 452096562..e82570cf2 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/draft_notes.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/draft_notes.go @@ -17,20 +17,53 @@ package gitlab import ( - "fmt" "net/http" ) type ( // DraftNotesServiceInterface defines all the API methods for the DraftNotesService DraftNotesServiceInterface interface { - ListDraftNotes(pid any, mergeRequest int, opt *ListDraftNotesOptions, options ...RequestOptionFunc) ([]*DraftNote, *Response, error) - GetDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*DraftNote, *Response, error) - CreateDraftNote(pid any, mergeRequest int, opt *CreateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) - UpdateDraftNote(pid any, mergeRequest int, note int, opt *UpdateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) - DeleteDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) - PublishDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) - PublishAllDraftNotes(pid any, mergeRequest int, options ...RequestOptionFunc) (*Response, error) + // ListDraftNotes gets a list of all draft notes for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#list-all-merge-request-draft-notes + ListDraftNotes(pid any, mergeRequest int64, opt *ListDraftNotesOptions, options ...RequestOptionFunc) ([]*DraftNote, *Response, error) + + // GetDraftNote gets a single draft note for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#get-a-single-draft-note + GetDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*DraftNote, *Response, error) + + // CreateDraftNote creates a draft note for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#create-a-draft-note + CreateDraftNote(pid any, mergeRequest int64, opt *CreateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) + + // UpdateDraftNote updates a draft note for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#update-a-draft-note + UpdateDraftNote(pid any, mergeRequest int64, note int64, opt *UpdateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) + + // DeleteDraftNote deletes a single draft note for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#delete-a-draft-note + DeleteDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*Response, error) + + // PublishDraftNote publishes a single draft note for a merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#publish-a-draft-note + PublishDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*Response, error) + + // PublishAllDraftNotes publishes all draft notes for a merge request that belong to the user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/draft_notes/#publish-a-draft-note + PublishAllDraftNotes(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Response, error) } // DraftNotesService handles communication with the draft notes related methods @@ -46,9 +79,9 @@ type ( var _ DraftNotesServiceInterface = (*DraftNotesService)(nil) type DraftNote struct { - ID int `json:"id"` - AuthorID int `json:"author_id"` - MergeRequestID int `json:"merge_request_id"` + ID int64 `json:"id"` + AuthorID int64 `json:"author_id"` + MergeRequestID int64 `json:"merge_request_id"` ResolveDiscussion bool `json:"resolve_discussion"` DiscussionID string `json:"discussion_id"` Note string `json:"note"` @@ -68,60 +101,26 @@ type ListDraftNotesOptions struct { Sort *string `url:"sort,omitempty" json:"sort,omitempty"` } -// ListDraftNotes gets a list of all draft notes for a merge request. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#list-all-merge-request-draft-notes -func (s *DraftNotesService) ListDraftNotes(pid any, mergeRequest int, opt *ListDraftNotesOptions, options ...RequestOptionFunc) ([]*DraftNote, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var n []*DraftNote - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *DraftNotesService) ListDraftNotes(pid any, mergeRequest int64, opt *ListDraftNotesOptions, options ...RequestOptionFunc) ([]*DraftNote, *Response, error) { + return do[[]*DraftNote](s.client, + withPath("projects/%s/merge_requests/%d/draft_notes", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetDraftNote gets a single draft note for a merge request. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#get-a-single-draft-note -func (s *DraftNotesService) GetDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*DraftNote, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(DraftNote) - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *DraftNotesService) GetDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*DraftNote, *Response, error) { + return do[*DraftNote](s.client, + withPath("projects/%s/merge_requests/%d/draft_notes/%d", ProjectID{pid}, mergeRequest, note), + withRequestOpts(options...), + ) } // CreateDraftNoteOptions represents the available CreateDraftNote() // options. // -// Gitlab API docs: +// GitLab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/draft_notes/#create-a-draft-note type CreateDraftNoteOptions struct { Note *string `url:"note" json:"note"` @@ -131,118 +130,58 @@ type CreateDraftNoteOptions struct { Position *PositionOptions `url:"position,omitempty" json:"position,omitempty"` } -// CreateDraftNote creates a draft note for a merge request. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#create-a-draft-note -func (s *DraftNotesService) CreateDraftNote(pid any, mergeRequest int, opt *CreateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(DraftNote) - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *DraftNotesService) CreateDraftNote(pid any, mergeRequest int64, opt *CreateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) { + return do[*DraftNote](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/draft_notes", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateDraftNoteOptions represents the available UpdateDraftNote() // options. // -// Gitlab API docs: +// GitLab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/draft_notes/#create-a-draft-note type UpdateDraftNoteOptions struct { Note *string `url:"note,omitempty" json:"note,omitempty"` Position *PositionOptions `url:"position,omitempty" json:"position,omitempty"` } -// UpdateDraftNote updates a draft note for a merge request. -// -// Gitlab API docs: https://docs.gitlab.com/api/draft_notes/#create-a-draft-note -func (s *DraftNotesService) UpdateDraftNote(pid any, mergeRequest int, note int, opt *UpdateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(DraftNote) - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *DraftNotesService) UpdateDraftNote(pid any, mergeRequest int64, note int64, opt *UpdateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) { + return do[*DraftNote](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/draft_notes/%d", ProjectID{pid}, mergeRequest, note), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteDraftNote deletes a single draft note for a merge request. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#delete-a-draft-note -func (s *DraftNotesService) DeleteDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DraftNotesService) DeleteDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/draft_notes/%d", ProjectID{pid}, mergeRequest, note), + withRequestOpts(options...), + ) + return resp, err } -// PublishDraftNote publishes a single draft note for a merge request. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#publish-a-draft-note -func (s *DraftNotesService) PublishDraftNote(pid any, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d/publish", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodPut, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DraftNotesService) PublishDraftNote(pid any, mergeRequest int64, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/draft_notes/%d/publish", ProjectID{pid}, mergeRequest, note), + withRequestOpts(options...), + ) + return resp, err } -// PublishAllDraftNotes publishes all draft notes for a merge request that belong to the user. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/draft_notes/#publish-a-draft-note -func (s *DraftNotesService) PublishAllDraftNotes(pid any, mergeRequest int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/bulk_publish", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *DraftNotesService) PublishAllDraftNotes(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/draft_notes/bulk_publish", ProjectID{pid}, mergeRequest), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/enterprise_users.go b/vendor/gitlab.com/gitlab-org/api/client-go/enterprise_users.go index e50b5c511..74f6c93fc 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/enterprise_users.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/enterprise_users.go @@ -15,16 +15,20 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( EnterpriseUsersServiceInterface interface { + // ListEnterpriseUsers lists all enterprise users for a given top-level group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_enterprise_users/#list-all-enterprise-users ListEnterpriseUsers(gid any, opt *ListEnterpriseUsersOptions, options ...RequestOptionFunc) ([]*User, *Response, error) - GetEnterpriseUser(gid any, uid int, options ...RequestOptionFunc) (*User, *Response, error) - Disable2FAForEnterpriseUser(gid any, uid int, options ...RequestOptionFunc) (*Response, error) + GetEnterpriseUser(gid any, uid int64, options ...RequestOptionFunc) (*User, *Response, error) + Disable2FAForEnterpriseUser(gid any, uid int64, options ...RequestOptionFunc) (*Response, error) + DeleteEnterpriseUser(gid any, uid int64, deleteOptions *DeleteEnterpriseUserOptions, options ...RequestOptionFunc) (*Response, error) } // EnterpriseUsersService handles communication with the enterprise users @@ -54,54 +58,23 @@ type ListEnterpriseUsersOptions struct { TwoFactor string `url:"two_factor,omitempty" json:"two_factor,omitempty"` } -// ListEnterpriseUsers lists all enterprise users for a given top-level group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_enterprise_users/#list-all-enterprise-users func (s *EnterpriseUsersService) ListEnterpriseUsers(gid any, opt *ListEnterpriseUsersOptions, options ...RequestOptionFunc) ([]*User, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/enterprise_users", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var users []*User - resp, err := s.client.Do(req, &users) - if err != nil { - return nil, resp, err - } - - return users, resp, nil + return do[[]*User](s.client, + withPath("groups/%s/enterprise_users", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetEnterpriseUser gets details on a specified enterprise user. // // GitLab API docs: // https://docs.gitlab.com/api/group_enterprise_users/#get-details-on-an-enterprise-user -func (s *EnterpriseUsersService) GetEnterpriseUser(gid any, uid int, options ...RequestOptionFunc) (*User, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/enterprise_users/%d", PathEscape(group), uid) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - user := new(User) - resp, err := s.client.Do(req, &user) - if err != nil { - return nil, resp, err - } - - return user, resp, nil +func (s *EnterpriseUsersService) GetEnterpriseUser(gid any, uid int64, options ...RequestOptionFunc) (*User, *Response, error) { + return do[*User](s.client, + withPath("groups/%s/enterprise_users/%d", GroupID{gid}, uid), + withRequestOpts(options...), + ) } // Disable2FAForEnterpriseUser disables two-factor authentication (2FA) for a @@ -109,17 +82,33 @@ func (s *EnterpriseUsersService) GetEnterpriseUser(gid any, uid int, options ... // // GitLab API docs: // https://docs.gitlab.com/api/group_enterprise_users/#disable-two-factor-authentication-for-an-enterprise-user -func (s *EnterpriseUsersService) Disable2FAForEnterpriseUser(gid any, uid int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/enterprise_users/%d/disable_two_factor", PathEscape(group), uid) +func (s *EnterpriseUsersService) Disable2FAForEnterpriseUser(gid any, uid int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPatch), + withPath("groups/%s/enterprise_users/%d/disable_two_factor", GroupID{gid}, uid), + withRequestOpts(options...), + ) + return resp, err +} - req, err := s.client.NewRequest(http.MethodPatch, u, nil, options) - if err != nil { - return nil, err - } +// DeleteEnterpriseUserOptions represents the available DeleteEnterpriseUser options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_enterprise_users/#delete-an-enterprise-user +type DeleteEnterpriseUserOptions struct { + HardDelete *bool `url:"hard_delete,omitempty" json:"hard_delete,omitempty"` +} - return s.client.Do(req, nil) +// DeleteEnterpriseUser deletes an specified enterprise user. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_enterprise_users/#delete-an-enterprise-user +func (s *EnterpriseUsersService) DeleteEnterpriseUser(gid any, uid int64, opt *DeleteEnterpriseUserOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/enterprise_users/%d", GroupID{gid}, uid), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/environments.go b/vendor/gitlab.com/gitlab-org/api/client-go/environments.go index 9d8f9fedc..6cf8512b0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/environments.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/environments.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,12 +24,17 @@ import ( type ( // EnvironmentsServiceInterface defines all the API methods for the EnvironmentsService EnvironmentsServiceInterface interface { + // ListEnvironments gets a list of environments from a project, sorted by name + // alphabetically. + // + // GitLab API docs: + // https://docs.gitlab.com/api/environments/#list-environments ListEnvironments(pid any, opts *ListEnvironmentsOptions, options ...RequestOptionFunc) ([]*Environment, *Response, error) - GetEnvironment(pid any, environment int, options ...RequestOptionFunc) (*Environment, *Response, error) + GetEnvironment(pid any, environment int64, options ...RequestOptionFunc) (*Environment, *Response, error) CreateEnvironment(pid any, opt *CreateEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) - EditEnvironment(pid any, environment int, opt *EditEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) - DeleteEnvironment(pid any, environment int, options ...RequestOptionFunc) (*Response, error) - StopEnvironment(pid any, environmentID int, opt *StopEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) + EditEnvironment(pid any, environment int64, opt *EditEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) + DeleteEnvironment(pid any, environment int64, options ...RequestOptionFunc) (*Response, error) + StopEnvironment(pid any, environmentID int64, opt *StopEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) } // EnvironmentsService handles communication with the environment related methods @@ -48,7 +52,7 @@ var _ EnvironmentsServiceInterface = (*EnvironmentsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/environments/ type Environment struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Slug string `json:"slug"` Description string `json:"description"` @@ -81,55 +85,19 @@ type ListEnvironmentsOptions struct { States *string `url:"states,omitempty" json:"states,omitempty"` } -// ListEnvironments gets a list of environments from a project, sorted by name -// alphabetically. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#list-environments func (s *EnvironmentsService) ListEnvironments(pid any, opts *ListEnvironmentsOptions, options ...RequestOptionFunc) ([]*Environment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/environments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var envs []*Environment - resp, err := s.client.Do(req, &envs) - if err != nil { - return nil, resp, err - } - - return envs, resp, nil + return do[[]*Environment](s.client, + withPath("projects/%s/environments", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// GetEnvironment gets a specific environment from a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#get-a-specific-environment -func (s *EnvironmentsService) GetEnvironment(pid any, environment int, options ...RequestOptionFunc) (*Environment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/environments/%d", PathEscape(project), environment) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - env := new(Environment) - resp, err := s.client.Do(req, env) - if err != nil { - return nil, resp, err - } - - return env, resp, nil +func (s *EnvironmentsService) GetEnvironment(pid any, environment int64, options ...RequestOptionFunc) (*Environment, *Response, error) { + return do[*Environment](s.client, + withPath("projects/%s/environments/%d", ProjectID{pid}, environment), + withRequestOpts(options...), + ) } // CreateEnvironmentOptions represents the available CreateEnvironment() options. @@ -141,37 +109,19 @@ type CreateEnvironmentOptions struct { Description *string `url:"description,omitempty" json:"description,omitempty"` ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` Tier *string `url:"tier,omitempty" json:"tier,omitempty"` - ClusterAgentID *int `url:"cluster_agent_id,omitempty" json:"cluster_agent_id,omitempty"` + ClusterAgentID *int64 `url:"cluster_agent_id,omitempty" json:"cluster_agent_id,omitempty"` KubernetesNamespace *string `url:"kubernetes_namespace,omitempty" json:"kubernetes_namespace,omitempty"` FluxResourcePath *string `url:"flux_resource_path,omitempty" json:"flux_resource_path,omitempty"` AutoStopSetting *string `url:"auto_stop_setting,omitempty" json:"auto_stop_setting,omitempty"` } -// CreateEnvironment adds an environment to a project. This method is idempotent -// and can be called multiple times with the same parameters. Creating an environment -// that already exists does not affect the existing association. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#create-a-new-environment func (s *EnvironmentsService) CreateEnvironment(pid any, opt *CreateEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/environments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - env := new(Environment) - resp, err := s.client.Do(req, env) - if err != nil { - return nil, resp, err - } - - return env, resp, nil + return do[*Environment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/environments", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditEnvironmentOptions represents the available EditEnvironment() options. @@ -183,54 +133,28 @@ type EditEnvironmentOptions struct { Description *string `url:"description,omitempty" json:"description,omitempty"` ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` Tier *string `url:"tier,omitempty" json:"tier,omitempty"` - ClusterAgentID *int `url:"cluster_agent_id,omitempty" json:"cluster_agent_id,omitempty"` + ClusterAgentID *int64 `url:"cluster_agent_id,omitempty" json:"cluster_agent_id,omitempty"` KubernetesNamespace *string `url:"kubernetes_namespace,omitempty" json:"kubernetes_namespace,omitempty"` FluxResourcePath *string `url:"flux_resource_path,omitempty" json:"flux_resource_path,omitempty"` AutoStopSetting *string `url:"auto_stop_setting,omitempty" json:"auto_stop_setting,omitempty"` } -// EditEnvironment updates a project team environment to a specified access level.. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#update-an-existing-environment -func (s *EnvironmentsService) EditEnvironment(pid any, environment int, opt *EditEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/environments/%d", PathEscape(project), environment) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - env := new(Environment) - resp, err := s.client.Do(req, env) - if err != nil { - return nil, resp, err - } - - return env, resp, nil +func (s *EnvironmentsService) EditEnvironment(pid any, environment int64, opt *EditEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) { + return do[*Environment](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/environments/%d", ProjectID{pid}, environment), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteEnvironment removes an environment from a project team. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#delete-an-environment -func (s *EnvironmentsService) DeleteEnvironment(pid any, environment int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/environments/%d", PathEscape(project), environment) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *EnvironmentsService) DeleteEnvironment(pid any, environment int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/environments/%d", ProjectID{pid}, environment), + withRequestOpts(options...), + ) + return resp, err } // StopEnvironmentOptions represents the available StopEnvironment() options. @@ -241,27 +165,11 @@ type StopEnvironmentOptions struct { Force *bool `url:"force,omitempty" json:"force,omitempty"` } -// StopEnvironment stops an environment within a specific project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/environments/#stop-an-environment -func (s *EnvironmentsService) StopEnvironment(pid any, environmentID int, opt *StopEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/environments/%d/stop", PathEscape(project), environmentID) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - env := new(Environment) - resp, err := s.client.Do(req, env) - if err != nil { - return nil, resp, err - } - - return env, resp, nil +func (s *EnvironmentsService) StopEnvironment(pid any, environmentID int64, opt *StopEnvironmentOptions, options ...RequestOptionFunc) (*Environment, *Response, error) { + return do[*Environment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/environments/%d/stop", ProjectID{pid}, environmentID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/epic_issues.go b/vendor/gitlab.com/gitlab-org/api/client-go/epic_issues.go index 625d86c11..738db84ee 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/epic_issues.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/epic_issues.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -26,13 +25,13 @@ type ( // Will be removed in v5 of the API, use Work Items API instead EpicIssuesServiceInterface interface { // Will be removed in v5 of the API, use Work Items API instead - ListEpicIssues(gid any, epic int, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + ListEpicIssues(gid any, epic int64, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) // Will be removed in v5 of the API, use Work Items API instead - AssignEpicIssue(gid any, epic, issue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) + AssignEpicIssue(gid any, epic, issue int64, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) // Will be removed in v5 of the API, use Work Items API instead - RemoveEpicIssue(gid any, epic, epicIssue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) + RemoveEpicIssue(gid any, epic, epicIssue int64, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) // Will be removed in v5 of the API, use Work Items API instead - UpdateEpicIssueAssignment(gid any, epic, epicIssue int, opt *UpdateEpicIssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + UpdateEpicIssueAssignment(gid any, epic, epicIssue int64, opt *UpdateEpicIssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) } // EpicIssuesService handles communication with the epic issue related methods @@ -49,12 +48,12 @@ type ( var _ EpicIssuesServiceInterface = (*EpicIssuesService)(nil) // EpicIssueAssignment contains both the epic and issue objects returned from -// Gitlab with the assignment ID. +// GitLab with the assignment ID. // Will be removed in v5 of the API, use Work Items API instead // // GitLab API docs: https://docs.gitlab.com/api/epic_issues/ type EpicIssueAssignment struct { - ID int `json:"id"` + ID int64 `json:"id"` Epic *Epic `json:"epic"` Issue *Issue `json:"issue"` } @@ -64,25 +63,12 @@ type EpicIssueAssignment struct { // // Gitlab API docs: // https://docs.gitlab.com/api/epic_issues/#list-issues-for-an-epic -func (s *EpicIssuesService) ListEpicIssues(gid any, epic int, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/issues", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var is []*Issue - resp, err := s.client.Do(req, &is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil +func (s *EpicIssuesService) ListEpicIssues(gid any, epic int64, opt *ListOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withPath("groups/%s/epics/%d/issues", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AssignEpicIssue assigns an existing issue to an epic. @@ -90,25 +76,12 @@ func (s *EpicIssuesService) ListEpicIssues(gid any, epic int, opt *ListOptions, // // Gitlab API Docs: // https://docs.gitlab.com/api/epic_issues/#assign-an-issue-to-the-epic -func (s *EpicIssuesService) AssignEpicIssue(gid any, epic, issue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", PathEscape(group), epic, issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(EpicIssueAssignment) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil +func (s *EpicIssuesService) AssignEpicIssue(gid any, epic, issue int64, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) { + return do[*EpicIssueAssignment](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/epics/%d/issues/%d", GroupID{gid}, epic, issue), + withRequestOpts(options...), + ) } // RemoveEpicIssue removes an issue from an epic. @@ -116,66 +89,31 @@ func (s *EpicIssuesService) AssignEpicIssue(gid any, epic, issue int, options .. // // Gitlab API Docs: // https://docs.gitlab.com/api/epic_issues/#remove-an-issue-from-the-epic -func (s *EpicIssuesService) RemoveEpicIssue(gid any, epic, epicIssue int, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", PathEscape(group), epic, epicIssue) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(EpicIssueAssignment) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil +func (s *EpicIssuesService) RemoveEpicIssue(gid any, epic, epicIssue int64, options ...RequestOptionFunc) (*EpicIssueAssignment, *Response, error) { + return do[*EpicIssueAssignment](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/epics/%d/issues/%d", GroupID{gid}, epic, epicIssue), + withRequestOpts(options...), + ) } -// UpdateEpicIssueAssignmentOptions describes the UpdateEpicIssueAssignment() -// options. -// Will be removed in v5 of the API, use Work Items API instead -// -// Gitlab API Docs: -// https://docs.gitlab.com/api/epic_issues/#update-epic---issue-association type UpdateEpicIssueAssignmentOptions struct { *ListOptions - MoveBeforeID *int `url:"move_before_id,omitempty" json:"move_before_id,omitempty"` - MoveAfterID *int `url:"move_after_id,omitempty" json:"move_after_id,omitempty"` + MoveBeforeID *int64 `url:"move_before_id,omitempty" json:"move_before_id,omitempty"` + MoveAfterID *int64 `url:"move_after_id,omitempty" json:"move_after_id,omitempty"` } -// UpdateEpicIsssueAssignmentOptions is kept for backwards compatibility. -// Deprecated: use UpdateEpicIssueAssignmentOptions instead. -type UpdateEpicIsssueAssignmentOptions = UpdateEpicIssueAssignmentOptions - // UpdateEpicIssueAssignment moves an issue before or after another issue in an // epic issue list. // Will be removed in v5 of the API, use Work Items API instead // // Gitlab API Docs: // https://docs.gitlab.com/api/epic_issues/#update-epic---issue-association -func (s *EpicIssuesService) UpdateEpicIssueAssignment(gid any, epic, epicIssue int, opt *UpdateEpicIssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/issues/%d", PathEscape(group), epic, epicIssue) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - var is []*Issue - resp, err := s.client.Do(req, &is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil +func (s *EpicIssuesService) UpdateEpicIssueAssignment(gid any, epic, epicIssue int64, opt *UpdateEpicIssueAssignmentOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/epics/%d/issues/%d", GroupID{gid}, epic, epicIssue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/epics.go b/vendor/gitlab.com/gitlab-org/api/client-go/epics.go index fa3f6b614..9f4818a7d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/epics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/epics.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -26,18 +25,29 @@ type ( // EpicsServiceInterface defines all the API methods for the EpicsService // Will be removed in v5 of the API, use Work Items API instead EpicsServiceInterface interface { + // ListGroupEpics gets a list of group epics. This function accepts pagination + // parameters page and per_page to return the list of group epics. // Will be removed in v5 of the API, use Work Items API instead + // + // GitLab API docs: https://docs.gitlab.com/api/epics/#list-epics-for-a-group ListGroupEpics(gid any, opt *ListGroupEpicsOptions, options ...RequestOptionFunc) ([]*Epic, *Response, error) + + // GetEpic gets a single group epic. // Will be removed in v5 of the API, use Work Items API instead - GetEpic(gid any, epic int, options ...RequestOptionFunc) (*Epic, *Response, error) + GetEpic(gid any, epic int64, options ...RequestOptionFunc) (*Epic, *Response, error) // Will be removed in v5 of the API, use Work Items API instead - GetEpicLinks(gid any, epic int, options ...RequestOptionFunc) ([]*Epic, *Response, error) + GetEpicLinks(gid any, epic int64, options ...RequestOptionFunc) ([]*Epic, *Response, error) // Will be removed in v5 of the API, use Work Items API instead + // + // GitLab API docs: https://docs.gitlab.com/api/epics/#new-epic CreateEpic(gid any, opt *CreateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) + + // UpdateEpic updates an existing group epic. This function is also used + // to mark an epic as closed. // Will be removed in v5 of the API, use Work Items API instead - UpdateEpic(gid any, epic int, opt *UpdateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) + UpdateEpic(gid any, epic int64, opt *UpdateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) // Will be removed in v5 of the API, use Work Items API instead - DeleteEpic(gid any, epic int, options ...RequestOptionFunc) (*Response, error) + DeleteEpic(gid any, epic int64, options ...RequestOptionFunc) (*Response, error) } // EpicsService handles communication with the epic related methods @@ -56,7 +66,7 @@ var _ EpicsServiceInterface = (*EpicsService)(nil) // EpicAuthor represents a author of the epic. // Will be removed in v5 of the API, use Work Items API instead type EpicAuthor struct { - ID int `json:"id"` + ID int64 `json:"id"` State string `json:"state"` WebURL string `json:"web_url"` Name string `json:"name"` @@ -69,10 +79,10 @@ type EpicAuthor struct { // // GitLab API docs: https://docs.gitlab.com/api/epics/ type Epic struct { - ID int `json:"id"` - IID int `json:"iid"` - GroupID int `json:"group_id"` - ParentID int `json:"parent_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + GroupID int64 `json:"group_id"` + ParentID int64 `json:"parent_id"` Title string `json:"title"` Description string `json:"description"` State string `json:"state"` @@ -91,9 +101,9 @@ type Epic struct { UpdatedAt *time.Time `json:"updated_at"` ClosedAt *time.Time `json:"closed_at"` Labels []string `json:"labels"` - Upvotes int `json:"upvotes"` - Downvotes int `json:"downvotes"` - UserNotesCount int `json:"user_notes_count"` + Upvotes int64 `json:"upvotes"` + Downvotes int64 `json:"downvotes"` + UserNotesCount int64 `json:"user_notes_count"` URL string `json:"url"` } @@ -110,7 +120,7 @@ func (e Epic) String() string { // GitLab API docs: https://docs.gitlab.com/api/epics/#list-epics-for-a-group type ListGroupEpicsOptions struct { ListOptions - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` WithLabelDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` @@ -126,80 +136,34 @@ type ListGroupEpicsOptions struct { MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` } -// ListGroupEpics gets a list of group epics. This function accepts pagination -// parameters page and per_page to return the list of group epics. -// Will be removed in v5 of the API, use Work Items API instead -// -// GitLab API docs: https://docs.gitlab.com/api/epics/#list-epics-for-a-group func (s *EpicsService) ListGroupEpics(gid any, opt *ListGroupEpicsOptions, options ...RequestOptionFunc) ([]*Epic, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var es []*Epic - resp, err := s.client.Do(req, &es) - if err != nil { - return nil, resp, err - } - - return es, resp, nil + return do[[]*Epic](s.client, + withPath("groups/%s/epics", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetEpic gets a single group epic. // Will be removed in v5 of the API, use Work Items API instead // // GitLab API docs: https://docs.gitlab.com/api/epics/#single-epic -func (s *EpicsService) GetEpic(gid any, epic int, options ...RequestOptionFunc) (*Epic, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - e := new(Epic) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil +func (s *EpicsService) GetEpic(gid any, epic int64, options ...RequestOptionFunc) (*Epic, *Response, error) { + return do[*Epic](s.client, + withPath("groups/%s/epics/%d", GroupID{gid}, epic), + withRequestOpts(options...), + ) } // GetEpicLinks gets all child epics of an epic. // Will be removed in v5 of the API, use Work Items API instead // // GitLab API docs: https://docs.gitlab.com/api/epic_links/ -func (s *EpicsService) GetEpicLinks(gid any, epic int, options ...RequestOptionFunc) ([]*Epic, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/epics", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var e []*Epic - resp, err := s.client.Do(req, &e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil +func (s *EpicsService) GetEpicLinks(gid any, epic int64, options ...RequestOptionFunc) ([]*Epic, *Response, error) { + return do[[]*Epic](s.client, + withPath("groups/%s/epics/%d/epics", GroupID{gid}, epic), + withRequestOpts(options...), + ) } // CreateEpicOptions represents the available CreateEpic() options. @@ -217,32 +181,16 @@ type CreateEpicOptions struct { StartDateFixed *ISOTime `url:"start_date_fixed,omitempty" json:"start_date_fixed,omitempty"` DueDateIsFixed *bool `url:"due_date_is_fixed,omitempty" json:"due_date_is_fixed,omitempty"` DueDateFixed *ISOTime `url:"due_date_fixed,omitempty" json:"due_date_fixed,omitempty"` - ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` + ParentID *int64 `url:"parent_id,omitempty" json:"parent_id,omitempty"` } -// CreateEpic creates a new group epic. -// Will be removed in v5 of the API, use Work Items API instead -// -// GitLab API docs: https://docs.gitlab.com/api/epics/#new-epic func (s *EpicsService) CreateEpic(gid any, opt *CreateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - e := new(Epic) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil + return do[*Epic](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/epics", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateEpicOptions represents the available UpdateEpic() options. @@ -256,7 +204,7 @@ type UpdateEpicOptions struct { DueDateFixed *ISOTime `url:"due_date_fixed,omitempty" json:"due_date_fixed,omitempty"` DueDateIsFixed *bool `url:"due_date_is_fixed,omitempty" json:"due_date_is_fixed,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` - ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` + ParentID *int64 `url:"parent_id,omitempty" json:"parent_id,omitempty"` RemoveLabels *LabelOptions `url:"remove_labels,omitempty" json:"remove_labels,omitempty"` StartDateFixed *ISOTime `url:"start_date_fixed,omitempty" json:"start_date_fixed,omitempty"` StartDateIsFixed *bool `url:"start_date_is_fixed,omitempty" json:"start_date_is_fixed,omitempty"` @@ -271,42 +219,24 @@ type UpdateEpicOptions struct { // Will be removed in v5 of the API, use Work Items API instead // // GitLab API docs: https://docs.gitlab.com/api/epics/#update-epic -func (s *EpicsService) UpdateEpic(gid any, epic int, opt *UpdateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - e := new(Epic) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil +func (s *EpicsService) UpdateEpic(gid any, epic int64, opt *UpdateEpicOptions, options ...RequestOptionFunc) (*Epic, *Response, error) { + return do[*Epic](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/epics/%d", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteEpic deletes a single group epic. // Will be removed in v5 of the API, use Work Items API instead // // GitLab API docs: https://docs.gitlab.com/api/epics/#delete-epic -func (s *EpicsService) DeleteEpic(gid any, epic int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *EpicsService) DeleteEpic(gid any, epic int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/epics/%d", GroupID{gid}, epic), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/error_tracking.go b/vendor/gitlab.com/gitlab-org/api/client-go/error_tracking.go index 14de8ea88..d39a10610 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/error_tracking.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/error_tracking.go @@ -16,19 +16,41 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( // ErrorTrackingServiceInterface defines all the API methods for the ErrorTrackingService ErrorTrackingServiceInterface interface { + // GetErrorTrackingSettings gets error tracking settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/error_tracking/#get-error-tracking-settings GetErrorTrackingSettings(pid any, options ...RequestOptionFunc) (*ErrorTrackingSettings, *Response, error) + + // EnableDisableErrorTracking allows you to enable or disable the error tracking + // settings for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/error_tracking/#enable-or-disable-the-error-tracking-project-settings EnableDisableErrorTracking(pid any, opt *EnableDisableErrorTrackingOptions, options ...RequestOptionFunc) (*ErrorTrackingSettings, *Response, error) + + // ListClientKeys lists error tracking project client keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/error_tracking/#list-project-client-keys ListClientKeys(pid any, opt *ListClientKeysOptions, options ...RequestOptionFunc) ([]*ErrorTrackingClientKey, *Response, error) + + // CreateClientKey creates a new client key for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/error_tracking/#create-a-client-key CreateClientKey(pid any, options ...RequestOptionFunc) (*ErrorTrackingClientKey, *Response, error) - DeleteClientKey(pid any, keyID int, options ...RequestOptionFunc) (*Response, error) + + // DeleteClientKey removes a client key from the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/error_tracking/#delete-a-client-key + DeleteClientKey(pid any, keyID int64, options ...RequestOptionFunc) (*Response, error) } // ErrorTrackingService handles communication with the error tracking @@ -47,7 +69,7 @@ var _ ErrorTrackingServiceInterface = (*ErrorTrackingService)(nil) // GitLab docs: // https://docs.gitlab.com/api/error_tracking/#error-tracking-client-keys type ErrorTrackingClientKey struct { - ID int `json:"id"` + ID int64 `json:"id"` Active bool `json:"active"` PublicKey string `json:"public_key"` SentryDsn string `json:"sentry_dsn"` @@ -72,29 +94,11 @@ func (p ErrorTrackingSettings) String() string { return Stringify(p) } -// GetErrorTrackingSettings gets error tracking settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/error_tracking/#get-error-tracking-settings func (s *ErrorTrackingService) GetErrorTrackingSettings(pid any, options ...RequestOptionFunc) (*ErrorTrackingSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/error_tracking/settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ets := new(ErrorTrackingSettings) - resp, err := s.client.Do(req, ets) - if err != nil { - return nil, resp, err - } - - return ets, resp, nil + return do[*ErrorTrackingSettings](s.client, + withPath("projects/%s/error_tracking/settings", ProjectID{pid}), + withRequestOpts(options...), + ) } // EnableDisableErrorTrackingOptions represents the available @@ -107,103 +111,48 @@ type EnableDisableErrorTrackingOptions struct { Integrated *bool `url:"integrated,omitempty" json:"integrated,omitempty"` } -// EnableDisableErrorTracking allows you to enable or disable the error tracking -// settings for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/error_tracking/#enable-or-disable-the-error-tracking-project-settings func (s *ErrorTrackingService) EnableDisableErrorTracking(pid any, opt *EnableDisableErrorTrackingOptions, options ...RequestOptionFunc) (*ErrorTrackingSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/error_tracking/settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, nil, err - } - - ets := new(ErrorTrackingSettings) - resp, err := s.client.Do(req, &ets) - if err != nil { - return nil, resp, err - } - - return ets, resp, nil + return do[*ErrorTrackingSettings](s.client, + withMethod(http.MethodPatch), + withPath("projects/%s/error_tracking/settings", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListClientKeysOptions represents the available ListClientKeys() options. // // GitLab API docs: // https://docs.gitlab.com/api/error_tracking/#list-project-client-keys -type ListClientKeysOptions ListOptions +type ListClientKeysOptions struct { + ListOptions +} -// ListClientKeys lists error tracking project client keys. -// -// GitLab API docs: -// https://docs.gitlab.com/api/error_tracking/#list-project-client-keys func (s *ErrorTrackingService) ListClientKeys(pid any, opt *ListClientKeysOptions, options ...RequestOptionFunc) ([]*ErrorTrackingClientKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/error_tracking/client_keys", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var cks []*ErrorTrackingClientKey - resp, err := s.client.Do(req, &cks) - if err != nil { - return nil, resp, err - } - - return cks, resp, nil + return do[[]*ErrorTrackingClientKey](s.client, + withPath("projects/%s/error_tracking/client_keys", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// CreateClientKey creates a new client key for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/error_tracking/#create-a-client-key func (s *ErrorTrackingService) CreateClientKey(pid any, options ...RequestOptionFunc) (*ErrorTrackingClientKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/error_tracking/client_keys", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - ck := new(ErrorTrackingClientKey) - resp, err := s.client.Do(req, ck) - if err != nil { - return nil, resp, err - } - - return ck, resp, nil + return do[*ErrorTrackingClientKey](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/error_tracking/client_keys", ProjectID{pid}), + withRequestOpts(options...), + ) } // DeleteClientKey removes a client key from the project. // // GitLab API docs: // https://docs.gitlab.com/api/error_tracking/#delete-a-client-key -func (s *ErrorTrackingService) DeleteClientKey(pid any, keyID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/error_tracking/client_keys/%d", PathEscape(project), keyID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ErrorTrackingService) DeleteClientKey(pid any, keyID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/error_tracking/client_keys/%d", ProjectID{pid}, keyID), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/event_parsing.go b/vendor/gitlab.com/gitlab-org/api/client-go/event_parsing.go index cae15b4bc..c446da3f3 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/event_parsing.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/event_parsing.go @@ -18,11 +18,12 @@ package gitlab import ( "encoding/json" + "errors" "fmt" "net/http" ) -// EventType represents a Gitlab event type. +// EventType represents a GitLab event type. type EventType string // List of available event types. @@ -31,13 +32,16 @@ const ( EventConfidentialNote EventType = "Confidential Note Hook" EventTypeBuild EventType = "Build Hook" EventTypeDeployment EventType = "Deployment Hook" + EventTypeEmoji EventType = "Emoji Hook" EventTypeFeatureFlag EventType = "Feature Flag Hook" EventTypeIssue EventType = "Issue Hook" EventTypeJob EventType = "Job Hook" EventTypeMember EventType = "Member Hook" EventTypeMergeRequest EventType = "Merge Request Hook" + EventTypeMilestone EventType = "Milestone Hook" EventTypeNote EventType = "Note Hook" EventTypePipeline EventType = "Pipeline Hook" + EventTypeProject EventType = "Project Hook" EventTypePush EventType = "Push Hook" EventTypeRelease EventType = "Release Hook" EventTypeResourceAccessToken EventType = "Resource Access Token Hook" @@ -45,6 +49,7 @@ const ( EventTypeSubGroup EventType = "Subgroup Hook" EventTypeSystemHook EventType = "System Hook" EventTypeTagPush EventType = "Tag Push Hook" + EventTypeVulnerability EventType = "Vulnerability Hook" EventTypeWikiPage EventType = "Wiki Page Hook" ) @@ -62,10 +67,12 @@ const ( ) type noteEvent struct { - ObjectKind string `json:"object_kind"` - ObjectAttributes struct { - NoteableType string `json:"noteable_type"` - } `json:"object_attributes"` + ObjectKind string `json:"object_kind"` + ObjectAttributes noteEventObjectAttributes `json:"object_attributes"` +} + +type noteEventObjectAttributes struct { + NoteableType string `json:"noteable_type"` } type serviceEvent struct { @@ -221,6 +228,8 @@ func ParseWebhook(eventType EventType, payload []byte) (event any, err error) { event = &BuildEvent{} case EventTypeDeployment: event = &DeploymentEvent{} + case EventTypeEmoji: + event = &EmojiEvent{} case EventTypeFeatureFlag: event = &FeatureFlagEvent{} case EventTypeIssue, EventConfidentialIssue: @@ -231,6 +240,8 @@ func ParseWebhook(eventType EventType, payload []byte) (event any, err error) { event = &MemberEvent{} case EventTypeMergeRequest: event = &MergeEvent{} + case EventTypeMilestone: + event = &MilestoneWebhookEvent{} case EventTypeNote, EventConfidentialNote: note := ¬eEvent{} err := json.Unmarshal(payload, note) @@ -256,6 +267,8 @@ func ParseWebhook(eventType EventType, payload []byte) (event any, err error) { } case EventTypePipeline: event = &PipelineEvent{} + case EventTypeProject: + event = &ProjectWebhookEvent{} case EventTypePush: event = &PushEvent{} case EventTypeRelease: @@ -276,7 +289,7 @@ func ParseWebhook(eventType EventType, payload []byte) (event any, err error) { case projectEvent: event = &ProjectResourceAccessTokenEvent{} default: - return nil, fmt.Errorf("unexpected resource access token payload") + return nil, errors.New("unexpected resource access token payload") } case EventTypeServiceHook: service := &serviceEvent{} @@ -298,6 +311,8 @@ func ParseWebhook(eventType EventType, payload []byte) (event any, err error) { event = &SubGroupEvent{} case EventTypeTagPush: event = &TagEvent{} + case EventTypeVulnerability: + event = &VulnerabilityEvent{} case EventTypeWikiPage: event = &WikiPageEvent{} default: diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/event_systemhook_types.go b/vendor/gitlab.com/gitlab-org/api/client-go/event_systemhook_types.go index 50940e832..fdbc13514 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/event_systemhook_types.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/event_systemhook_types.go @@ -44,7 +44,7 @@ type ProjectSystemEvent struct { Name string `json:"name"` Path string `json:"path"` PathWithNamespace string `json:"path_with_namespace"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` OwnerName string `json:"owner_name"` OwnerEmail string `json:"owner_email"` ProjectVisibility string `json:"project_visibility"` @@ -60,7 +60,7 @@ type GroupSystemEvent struct { Name string `json:"name"` Path string `json:"path"` PathWithNamespace string `json:"full_path"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` OwnerName string `json:"owner_name"` OwnerEmail string `json:"owner_email"` ProjectVisibility string `json:"project_visibility"` @@ -74,7 +74,7 @@ type GroupSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/ type KeySystemEvent struct { BaseSystemEvent - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Key string `json:"key"` } @@ -85,7 +85,7 @@ type KeySystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/ type UserSystemEvent struct { BaseSystemEvent - ID int `json:"user_id"` + ID int64 `json:"user_id"` Name string `json:"name"` Username string `json:"username"` OldUsername string `json:"old_username,omitempty"` @@ -99,11 +99,11 @@ type UserSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/ type UserGroupSystemEvent struct { BaseSystemEvent - ID int `json:"user_id"` + ID int64 `json:"user_id"` Name string `json:"user_name"` Username string `json:"user_username"` Email string `json:"user_email"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` GroupName string `json:"group_name"` GroupPath string `json:"group_path"` GroupAccess string `json:"group_access"` @@ -115,11 +115,11 @@ type UserGroupSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/ type UserTeamSystemEvent struct { BaseSystemEvent - ID int `json:"user_id"` + ID int64 `json:"user_id"` Name string `json:"user_name"` Username string `json:"user_username"` Email string `json:"user_email"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` ProjectName string `json:"project_name"` ProjectPath string `json:"project_path"` ProjectPathWithNamespace string `json:"project_path_with_namespace"` @@ -133,41 +133,59 @@ type UserTeamSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/#push-events type PushSystemEvent struct { BaseSystemEvent - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - CheckoutSHA string `json:"checkout_sha"` - UserID int `json:"user_id"` - UserName string `json:"user_name"` - UserUsername string `json:"user_username"` - UserEmail string `json:"user_email"` - UserAvatar string `json:"user_avatar"` - ProjectID int `json:"project_id"` - Project struct { - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL string `json:"avatar_url"` - GitHTTPURL string `json:"git_http_url"` - GitSSHURL string `json:"git_ssh_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - } `json:"project"` - Commits []struct { - ID string `json:"id"` - Message string `json:"message"` - Timestamp time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"commits"` - TotalCommitsCount int `json:"total_commits_count"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + CheckoutSHA string `json:"checkout_sha"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + UserUsername string `json:"user_username"` + UserEmail string `json:"user_email"` + UserAvatar string `json:"user_avatar"` + ProjectID int64 `json:"project_id"` + Project PushSystemEventProject `json:"project"` + Commits []PushSystemEventCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` +} + +// PushSystemEventProject represents a push system event's project. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#push-events +type PushSystemEventProject struct { + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitHTTPURL string `json:"git_http_url"` + GitSSHURL string `json:"git_ssh_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` +} + +// PushSystemEventCommit represents a push system event's commit. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#push-events +type PushSystemEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + URL string `json:"url"` + Author PushSystemEventCommitAuthor `json:"author"` +} + +// PushSystemEventCommitAuthor represents a push system event's commit author. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#push-events +type PushSystemEventCommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` } // TagPushSystemEvent represents a tag push system event. @@ -176,41 +194,59 @@ type PushSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/#tag-events type TagPushSystemEvent struct { BaseSystemEvent - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - CheckoutSHA string `json:"checkout_sha"` - UserID int `json:"user_id"` - UserName string `json:"user_name"` - UserUsername string `json:"user_username"` - UserEmail string `json:"user_email"` - UserAvatar string `json:"user_avatar"` - ProjectID int `json:"project_id"` - Project struct { - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL string `json:"avatar_url"` - GitHTTPURL string `json:"git_http_url"` - GitSSHURL string `json:"git_ssh_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - } `json:"project"` - Commits []struct { - ID string `json:"id"` - Message string `json:"message"` - Timestamp time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"commits"` - TotalCommitsCount int `json:"total_commits_count"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + CheckoutSHA string `json:"checkout_sha"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + UserUsername string `json:"user_username"` + UserEmail string `json:"user_email"` + UserAvatar string `json:"user_avatar"` + ProjectID int64 `json:"project_id"` + Project TagPushSystemEventProject `json:"project"` + Commits []TagPushSystemEventCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` +} + +// TagPushSystemEventProject represents a tag push system event's project. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#tag-events +type TagPushSystemEventProject struct { + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitHTTPURL string `json:"git_http_url"` + GitSSHURL string `json:"git_ssh_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` +} + +// TagPushSystemEventCommit represents a tag push system event's commit. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#tag-events +type TagPushSystemEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + URL string `json:"url"` + Author TagPushSystemEventCommitAuthor `json:"author"` +} + +// TagPushSystemEventCommitAuthor represents a tag push system event's commit author. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#tag-events +type TagPushSystemEventCommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` } // RepositoryUpdateSystemEvent represents a repository updated system event. @@ -219,31 +255,43 @@ type TagPushSystemEvent struct { // https://docs.gitlab.com/administration/system_hooks/#repository-update-events type RepositoryUpdateSystemEvent struct { BaseSystemEvent - UserID int `json:"user_id"` - UserName string `json:"user_name"` - UserEmail string `json:"user_email"` - UserAvatar string `json:"user_avatar"` - ProjectID int `json:"project_id"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL string `json:"avatar_url"` - GitHTTPURL string `json:"git_http_url"` - GitSSHURL string `json:"git_ssh_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CiConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - } `json:"project"` - Changes []struct { - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - } `json:"changes"` - Refs []string `json:"refs"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + UserEmail string `json:"user_email"` + UserAvatar string `json:"user_avatar"` + ProjectID int64 `json:"project_id"` + Project RepositoryUpdateSystemEventProject `json:"project"` + Changes []RepositoryUpdateSystemEventChange `json:"changes"` + Refs []string `json:"refs"` +} + +// RepositoryUpdateSystemEventProject represents a repository updated system event's project. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#repository-update-events +type RepositoryUpdateSystemEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitHTTPURL string `json:"git_http_url"` + GitSSHURL string `json:"git_ssh_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CiConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` +} + +// RepositoryUpdateSystemEventChange represents a repository updated system event's change. +// +// GitLab API docs: +// https://docs.gitlab.com/administration/system_hooks/#repository-update-events +type RepositoryUpdateSystemEventChange struct { + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/event_webhook_types.go b/vendor/gitlab.com/gitlab-org/api/client-go/event_webhook_types.go index 780747329..212375321 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/event_webhook_types.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/event_webhook_types.go @@ -28,7 +28,7 @@ import ( // There are no GitLab API docs on the subject, but the mappings can be found in // GitLab's codebase: // https://gitlab.com/gitlab-org/gitlab-foss/-/blob/ba5be4989e/app/models/concerns/issuable.rb#L39-42 -type StateID int +type StateID int64 const ( StateIDNone StateID = 0 @@ -43,35 +43,37 @@ const ( // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#job-events type BuildEvent struct { - ObjectKind string `json:"object_kind"` - Ref string `json:"ref"` - Tag bool `json:"tag"` - BeforeSHA string `json:"before_sha"` - SHA string `json:"sha"` - BuildID int `json:"build_id"` - BuildName string `json:"build_name"` - BuildStage string `json:"build_stage"` - BuildStatus string `json:"build_status"` - BuildCreatedAt string `json:"build_created_at"` - BuildStartedAt string `json:"build_started_at"` - BuildFinishedAt string `json:"build_finished_at"` - BuildDuration float64 `json:"build_duration"` - BuildAllowFailure bool `json:"build_allow_failure"` - ProjectID int `json:"project_id"` - ProjectName string `json:"project_name"` - User *EventUser `json:"user"` - Commit struct { - ID int `json:"id"` - SHA string `json:"sha"` - Message string `json:"message"` - AuthorName string `json:"author_name"` - AuthorEmail string `json:"author_email"` - Status string `json:"status"` - Duration int `json:"duration"` - StartedAt string `json:"started_at"` - FinishedAt string `json:"finished_at"` - } `json:"commit"` - Repository *Repository `json:"repository"` + ObjectKind string `json:"object_kind"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + BeforeSHA string `json:"before_sha"` + SHA string `json:"sha"` + BuildID int64 `json:"build_id"` + BuildName string `json:"build_name"` + BuildStage string `json:"build_stage"` + BuildStatus string `json:"build_status"` + BuildCreatedAt string `json:"build_created_at"` + BuildStartedAt string `json:"build_started_at"` + BuildFinishedAt string `json:"build_finished_at"` + BuildDuration float64 `json:"build_duration"` + BuildAllowFailure bool `json:"build_allow_failure"` + ProjectID int64 `json:"project_id"` + ProjectName string `json:"project_name"` + User *EventUser `json:"user"` + Commit BuildEventCommit `json:"commit"` + Repository *Repository `json:"repository"` +} + +type BuildEventCommit struct { + ID int64 `json:"id"` + SHA string `json:"sha"` + Message string `json:"message"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + Status string `json:"status"` + Duration int64 `json:"duration"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` } // CommitCommentEvent represents a comment on a commit event. @@ -79,57 +81,65 @@ type BuildEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#comment-on-a-commit type CommitCommentEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *User `json:"user"` - ProjectID int `json:"project_id"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - ObjectAttributes struct { - ID int `json:"id"` - Note string `json:"note"` - NoteableType string `json:"noteable_type"` - AuthorID int `json:"author_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ProjectID int `json:"project_id"` - Attachment string `json:"attachment"` - LineCode string `json:"line_code"` - CommitID string `json:"commit_id"` - NoteableID int `json:"noteable_id"` - System bool `json:"system"` - StDiff *Diff `json:"st_diff"` - Description string `json:"description"` - Action CommentEventAction `json:"action"` - URL string `json:"url"` - } `json:"object_attributes"` - Commit *struct { - ID string `json:"id"` - Title string `json:"title"` - Message string `json:"message"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"commit"` + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *User `json:"user"` + ProjectID int64 `json:"project_id"` + Project CommitCommentEventProject `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes CommitCommentEventObjectAttributes `json:"object_attributes"` + Commit *CommitCommentEventCommit `json:"commit"` +} + +type CommitCommentEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type CommitCommentEventObjectAttributes struct { + ID int64 `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int64 `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int64 `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int64 `json:"noteable_id"` + System bool `json:"system"` + StDiff *Diff `json:"st_diff"` + Description string `json:"description"` + Action CommentEventAction `json:"action"` + URL string `json:"url"` +} + +type CommitCommentEventCommit struct { + ID string `json:"id"` + Title string `json:"title"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` +} + +type EventCommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` } // DeploymentEvent represents a deployment event. @@ -137,39 +147,41 @@ type CommitCommentEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#deployment-events type DeploymentEvent struct { - ObjectKind string `json:"object_kind"` - Status string `json:"status"` - StatusChangedAt string `json:"status_changed_at"` - DeploymentID int `json:"deployment_id"` - DeployableID int `json:"deployable_id"` - DeployableURL string `json:"deployable_url"` - Environment string `json:"environment"` - EnvironmentSlug string `json:"environment_slug"` - EnvironmentExternalURL string `json:"environment_external_url"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL *string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CIConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - } `json:"project"` - Ref string `json:"ref"` - ShortSHA string `json:"short_sha"` - User *EventUser `json:"user"` - UserURL string `json:"user_url"` - CommitURL string `json:"commit_url"` - CommitTitle string `json:"commit_title"` + ObjectKind string `json:"object_kind"` + Status string `json:"status"` + StatusChangedAt string `json:"status_changed_at"` + DeploymentID int64 `json:"deployment_id"` + DeployableID int64 `json:"deployable_id"` + DeployableURL string `json:"deployable_url"` + Environment string `json:"environment"` + EnvironmentSlug string `json:"environment_slug"` + EnvironmentExternalURL string `json:"environment_external_url"` + Project DeploymentEventProject `json:"project"` + Ref string `json:"ref"` + ShortSHA string `json:"short_sha"` + User *EventUser `json:"user"` + UserURL string `json:"user_url"` + CommitURL string `json:"commit_url"` + CommitTitle string `json:"commit_title"` +} + +type DeploymentEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL *string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + VisibilityLevel int64 `json:"visibility_level"` + CIConfigPath string `json:"ci_config_path"` } // FeatureFlagEvent represents a feature flag event. @@ -177,33 +189,37 @@ type DeploymentEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#feature-flag-events type FeatureFlagEvent struct { - ObjectKind string `json:"object_kind"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL *string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CIConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - } `json:"project"` - User *EventUser `json:"user"` - UserURL string `json:"user_url"` - ObjectAttributes struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Active bool `json:"active"` - } `json:"object_attributes"` + ObjectKind string `json:"object_kind"` + Project FeatureFlagEventProject `json:"project"` + User *EventUser `json:"user"` + UserURL string `json:"user_url"` + ObjectAttributes FeatureFlagEventObjectAttributes `json:"object_attributes"` +} + +type FeatureFlagEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL *string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + VisibilityLevel int64 `json:"visibility_level"` + CIConfigPath string `json:"ci_config_path"` +} + +type FeatureFlagEventObjectAttributes struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Active bool `json:"active"` } // GroupResourceAccessTokenEvent represents a resource access token event for a @@ -212,20 +228,27 @@ type FeatureFlagEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#project-and-group-access-token-events type GroupResourceAccessTokenEvent struct { - EventName string `json:"event_name"` - ObjectKind string `json:"object_kind"` - Group struct { - GroupID int `json:"group_id"` - GroupName string `json:"group_name"` - GroupPath string `json:"group_path"` - } `json:"group"` - ObjectAttributes struct { - ID int `json:"id"` - UserID int `json:"user_id"` - Name string `json:"name"` - CreatedAt string `json:"created_at"` - ExpiresAt *ISOTime `json:"expires_at"` - } `json:"object_attributes"` + EventName string `json:"event_name"` + ObjectKind string `json:"object_kind"` + Group GroupResourceAccessTokenEventGroup `json:"group"` + ObjectAttributes GroupResourceAccessTokenEventObjectAttributes `json:"object_attributes"` +} + +// GroupResourceAccessTokenEventGroup represents a group in a resource access +// token event. +type GroupResourceAccessTokenEventGroup struct { + GroupID int64 `json:"group_id"` + GroupName string `json:"group_name"` + GroupPath string `json:"group_path"` + FullPath string `json:"full_path"` +} + +type GroupResourceAccessTokenEventObjectAttributes struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + Name string `json:"name"` + CreatedAt string `json:"created_at"` + ExpiresAt *ISOTime `json:"expires_at"` } // IssueCommentEvent represents a comment on an issue event. @@ -233,74 +256,80 @@ type GroupResourceAccessTokenEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#comment-on-an-issue type IssueCommentEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *User `json:"user"` - ProjectID int `json:"project_id"` - Project struct { - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - ObjectAttributes struct { - ID int `json:"id"` - Note string `json:"note"` - NoteableType string `json:"noteable_type"` - AuthorID int `json:"author_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ProjectID int `json:"project_id"` - Attachment string `json:"attachment"` - LineCode string `json:"line_code"` - CommitID string `json:"commit_id"` - DiscussionID string `json:"discussion_id"` - NoteableID int `json:"noteable_id"` - System bool `json:"system"` - StDiff []*Diff `json:"st_diff"` - Description string `json:"description"` - Action CommentEventAction `json:"action"` - URL string `json:"url"` - } `json:"object_attributes"` - Issue struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` - MilestoneID int `json:"milestone_id"` - AuthorID int `json:"author_id"` - Position int `json:"position"` - BranchName string `json:"branch_name"` - Description string `json:"description"` - State string `json:"state"` - Title string `json:"title"` - Labels []*EventLabel `json:"labels"` - LastEditedAt string `json:"last_edit_at"` - LastEditedByID int `json:"last_edited_by_id"` - UpdatedAt string `json:"updated_at"` - UpdatedByID int `json:"updated_by_id"` - CreatedAt string `json:"created_at"` - ClosedAt string `json:"closed_at"` - DueDate *ISOTime `json:"due_date"` - URL string `json:"url"` - TimeEstimate int `json:"time_estimate"` - Confidential bool `json:"confidential"` - TotalTimeSpent int `json:"total_time_spent"` - HumanTotalTimeSpent string `json:"human_total_time_spent"` - HumanTimeEstimate string `json:"human_time_estimate"` - AssigneeIDs []int `json:"assignee_ids"` - AssigneeID int `json:"assignee_id"` - } `json:"issue"` + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *User `json:"user"` + ProjectID int64 `json:"project_id"` + Project IssueCommentEventProject `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes IssueCommentEventObjectAttributes `json:"object_attributes"` + Issue IssueCommentEventIssue `json:"issue"` +} + +type IssueCommentEventProject struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type IssueCommentEventObjectAttributes struct { + ID int64 `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int64 `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int64 `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + DiscussionID string `json:"discussion_id"` + NoteableID int64 `json:"noteable_id"` + System bool `json:"system"` + StDiff []*Diff `json:"st_diff"` + Description string `json:"description"` + Action CommentEventAction `json:"action"` + URL string `json:"url"` +} + +type IssueCommentEventIssue struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` + MilestoneID int64 `json:"milestone_id"` + AuthorID int64 `json:"author_id"` + Position int64 `json:"position"` + BranchName string `json:"branch_name"` + Description string `json:"description"` + State string `json:"state"` + Title string `json:"title"` + Labels []*EventLabel `json:"labels"` + LastEditedAt string `json:"last_edit_at"` + LastEditedByID int64 `json:"last_edited_by_id"` + UpdatedAt string `json:"updated_at"` + UpdatedByID int64 `json:"updated_by_id"` + CreatedAt string `json:"created_at"` + ClosedAt string `json:"closed_at"` + DueDate *ISOTime `json:"due_date"` + URL string `json:"url"` + TimeEstimate int64 `json:"time_estimate"` + Confidential bool `json:"confidential"` + TotalTimeSpent int64 `json:"total_time_spent"` + HumanTotalTimeSpent string `json:"human_total_time_spent"` + HumanTimeEstimate string `json:"human_time_estimate"` + AssigneeIDs []int64 `json:"assignee_ids"` + AssigneeID int64 `json:"assignee_id"` } // IssueEvent represents a issue event. @@ -308,109 +337,135 @@ type IssueCommentEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#work-item-events type IssueEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *EventUser `json:"user"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - ObjectAttributes struct { - ID int `json:"id"` - Title string `json:"title"` - AssigneeIDs []int `json:"assignee_ids"` - AssigneeID int `json:"assignee_id"` - AuthorID int `json:"author_id"` - ProjectID int `json:"project_id"` - CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) - UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) - UpdatedByID int `json:"updated_by_id"` - LastEditedAt string `json:"last_edited_at"` - LastEditedByID int `json:"last_edited_by_id"` - RelativePosition int `json:"relative_position"` - BranchName string `json:"branch_name"` - Description string `json:"description"` - MilestoneID int `json:"milestone_id"` - StateID StateID `json:"state_id"` - Confidential bool `json:"confidential"` - DiscussionLocked bool `json:"discussion_locked"` - DueDate *ISOTime `json:"due_date"` - MovedToID int `json:"moved_to_id"` - DuplicatedToID int `json:"duplicated_to_id"` - TimeEstimate int `json:"time_estimate"` - TotalTimeSpent int `json:"total_time_spent"` - TimeChange int `json:"time_change"` - HumanTotalTimeSpent string `json:"human_total_time_spent"` - HumanTimeEstimate string `json:"human_time_estimate"` - HumanTimeChange string `json:"human_time_change"` - Weight int `json:"weight"` - IID int `json:"iid"` - URL string `json:"url"` - State string `json:"state"` - Action string `json:"action"` - Severity string `json:"severity"` - EscalationStatus string `json:"escalation_status"` - EscalationPolicy struct { - ID int `json:"id"` - Name string `json:"name"` - } `json:"escalation_policy"` - Labels []*EventLabel `json:"labels"` - } `json:"object_attributes"` - Assignee *EventUser `json:"assignee"` - Assignees *[]EventUser `json:"assignees"` - Labels []*EventLabel `json:"labels"` - Changes struct { - Assignees struct { - Previous []*EventUser `json:"previous"` - Current []*EventUser `json:"current"` - } `json:"assignees"` - Description struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"description"` - Labels struct { - Previous []*EventLabel `json:"previous"` - Current []*EventLabel `json:"current"` - } `json:"labels"` - Title struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"title"` - ClosedAt struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"closed_at"` - StateID struct { - Previous StateID `json:"previous"` - Current StateID `json:"current"` - } `json:"state_id"` - UpdatedAt struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"updated_at"` - UpdatedByID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"updated_by_id"` - TotalTimeSpent struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"total_time_spent"` - } `json:"changes"` + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *EventUser `json:"user"` + Project IssueEventProject `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes IssueEventObjectAttributes `json:"object_attributes"` + Assignee *EventUser `json:"assignee"` + Assignees *[]EventUser `json:"assignees"` + Labels []*EventLabel `json:"labels"` + Changes IssueEventChanges `json:"changes"` +} + +type IssueEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type IssueEventObjectAttributes struct { + ID int64 `json:"id"` + Title string `json:"title"` + AssigneeIDs []int64 `json:"assignee_ids"` + AssigneeID int64 `json:"assignee_id"` + AuthorID int64 `json:"author_id"` + ProjectID int64 `json:"project_id"` + CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) + UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) + UpdatedByID int64 `json:"updated_by_id"` + LastEditedAt string `json:"last_edited_at"` + LastEditedByID int64 `json:"last_edited_by_id"` + RelativePosition int64 `json:"relative_position"` + BranchName string `json:"branch_name"` + Description string `json:"description"` + MilestoneID int64 `json:"milestone_id"` + StateID StateID `json:"state_id"` + Confidential bool `json:"confidential"` + DiscussionLocked bool `json:"discussion_locked"` + DueDate *ISOTime `json:"due_date"` + MovedToID int64 `json:"moved_to_id"` + DuplicatedToID int64 `json:"duplicated_to_id"` + TimeEstimate int64 `json:"time_estimate"` + TotalTimeSpent int64 `json:"total_time_spent"` + TimeChange int64 `json:"time_change"` + HumanTotalTimeSpent string `json:"human_total_time_spent"` + HumanTimeEstimate string `json:"human_time_estimate"` + HumanTimeChange string `json:"human_time_change"` + Weight int64 `json:"weight"` + IID int64 `json:"iid"` + URL string `json:"url"` + State string `json:"state"` + Action string `json:"action"` + Severity string `json:"severity"` + EscalationStatus string `json:"escalation_status"` + EscalationPolicy IssueEventObjectAttributesEscalationPolicy `json:"escalation_policy"` + Labels []*EventLabel `json:"labels"` +} + +type IssueEventObjectAttributesEscalationPolicy struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + +type IssueEventChanges struct { + Assignees EventChangesAssignees `json:"assignees"` + Description EventChangesDescription `json:"description"` + Labels EventChangesLabels `json:"labels"` + Title EventChangesTitle `json:"title"` + ClosedAt IssueEventChangesClosedAt `json:"closed_at"` + StateID EventChangesStateID `json:"state_id"` + UpdatedAt EventChangesUpdatedAt `json:"updated_at"` + UpdatedByID EventChangesUpdatedByID `json:"updated_by_id"` + TotalTimeSpent IssueEventChangesTotalTimeSpent `json:"total_time_spent"` +} + +type EventChangesAssignees struct { + Previous []*EventUser `json:"previous"` + Current []*EventUser `json:"current"` +} + +type EventChangesDescription struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type EventChangesLabels struct { + Previous []*EventLabel `json:"previous"` + Current []*EventLabel `json:"current"` +} + +type EventChangesTitle struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type IssueEventChangesClosedAt struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type EventChangesStateID struct { + Previous StateID `json:"previous"` + Current StateID `json:"current"` +} + +type EventChangesUpdatedAt struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type EventChangesUpdatedByID struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` +} + +type IssueEventChangesTotalTimeSpent struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` } // JobEvent represents a job event. @@ -418,63 +473,73 @@ type IssueEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#job-events type JobEvent struct { - ObjectKind string `json:"object_kind"` - Ref string `json:"ref"` - Tag bool `json:"tag"` - BeforeSHA string `json:"before_sha"` - SHA string `json:"sha"` - BuildID int `json:"build_id"` - BuildName string `json:"build_name"` - BuildStage string `json:"build_stage"` - BuildStatus string `json:"build_status"` - BuildCreatedAt string `json:"build_created_at"` - BuildStartedAt string `json:"build_started_at"` - BuildFinishedAt string `json:"build_finished_at"` - BuildDuration float64 `json:"build_duration"` - BuildQueuedDuration float64 `json:"build_queued_duration"` - BuildAllowFailure bool `json:"build_allow_failure"` - BuildFailureReason string `json:"build_failure_reason"` - RetriesCount int `json:"retries_count"` - PipelineID int `json:"pipeline_id"` - ProjectID int `json:"project_id"` - ProjectName string `json:"project_name"` - User *EventUser `json:"user"` - Commit struct { - ID int `json:"id"` - Name string `json:"name"` - SHA string `json:"sha"` - Message string `json:"message"` - AuthorName string `json:"author_name"` - AuthorEmail string `json:"author_email"` - AuthorURL string `json:"author_url"` - Status string `json:"status"` - Duration int `json:"duration"` - StartedAt string `json:"started_at"` - FinishedAt string `json:"finished_at"` - } `json:"commit"` - Repository *Repository `json:"repository"` - Runner struct { - ID int `json:"id"` - Active bool `json:"active"` - RunnerType string `json:"runner_type"` - IsShared bool `json:"is_shared"` - Description string `json:"description"` - Tags []string `json:"tags"` - } `json:"runner"` - Environment struct { - Name string `json:"name"` - Action string `json:"action"` - DeploymentTier string `json:"deployment_tier"` - } `json:"environment"` - SourcePipeline struct { - Project struct { - ID int `json:"id"` - WebURL string `json:"web_url"` - PathWithNamespace string `json:"path_with_namespace"` - } `json:"project"` - PipelineID int `json:"pipeline_id"` - JobID int `json:"job_id"` - } `json:"source_pipeline"` + ObjectKind string `json:"object_kind"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + BeforeSHA string `json:"before_sha"` + SHA string `json:"sha"` + BuildID int64 `json:"build_id"` + BuildName string `json:"build_name"` + BuildStage string `json:"build_stage"` + BuildStatus string `json:"build_status"` + BuildCreatedAt string `json:"build_created_at"` + BuildStartedAt string `json:"build_started_at"` + BuildFinishedAt string `json:"build_finished_at"` + BuildDuration float64 `json:"build_duration"` + BuildQueuedDuration float64 `json:"build_queued_duration"` + BuildAllowFailure bool `json:"build_allow_failure"` + BuildFailureReason string `json:"build_failure_reason"` + RetriesCount int64 `json:"retries_count"` + PipelineID int64 `json:"pipeline_id"` + ProjectID int64 `json:"project_id"` + ProjectName string `json:"project_name"` + User *EventUser `json:"user"` + Commit JobEventCommit `json:"commit"` + Repository *Repository `json:"repository"` + Runner JobEventRunner `json:"runner"` + Environment EventEnvironment `json:"environment"` + SourcePipeline EventSourcePipeline `json:"source_pipeline"` +} + +type JobEventCommit struct { + ID int64 `json:"id"` + Name string `json:"name"` + SHA string `json:"sha"` + Message string `json:"message"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + AuthorURL string `json:"author_url"` + Status string `json:"status"` + Duration int64 `json:"duration"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` +} + +type JobEventRunner struct { + ID int64 `json:"id"` + Active bool `json:"active"` + RunnerType string `json:"runner_type"` + IsShared bool `json:"is_shared"` + Description string `json:"description"` + Tags []string `json:"tags"` +} + +type EventEnvironment struct { + Name string `json:"name"` + Action string `json:"action"` + DeploymentTier string `json:"deployment_tier"` +} + +type EventSourcePipeline struct { + Project EventSourcePipelineProject `json:"project"` + PipelineID int64 `json:"pipeline_id"` + JobID int64 `json:"job_id"` +} + +type EventSourcePipelineProject struct { + ID int64 `json:"id"` + WebURL string `json:"web_url"` + PathWithNamespace string `json:"path_with_namespace"` } // MemberEvent represents a member event. @@ -486,11 +551,11 @@ type MemberEvent struct { UpdatedAt *time.Time `json:"updated_at"` GroupName string `json:"group_name"` GroupPath string `json:"group_path"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` UserUsername string `json:"user_username"` UserName string `json:"user_name"` UserEmail string `json:"user_email"` - UserID int `json:"user_id"` + UserID int64 `json:"user_id"` GroupAccess string `json:"group_access"` GroupPlan string `json:"group_plan"` ExpiresAt *time.Time `json:"expires_at"` @@ -502,111 +567,116 @@ type MemberEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#comment-on-a-merge-request type MergeCommentEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *EventUser `json:"user"` - ProjectID int `json:"project_id"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - ObjectAttributes struct { - Attachment string `json:"attachment"` - AuthorID int `json:"author_id"` - ChangePosition *NotePosition `json:"change_position"` - CommitID string `json:"commit_id"` - CreatedAt string `json:"created_at"` - DiscussionID string `json:"discussion_id"` - ID int `json:"id"` - LineCode string `json:"line_code"` - Note string `json:"note"` - NoteableID int `json:"noteable_id"` - NoteableType string `json:"noteable_type"` - OriginalPosition *NotePosition `json:"original_position"` - Position *NotePosition `json:"position"` - ProjectID int `json:"project_id"` - ResolvedAt string `json:"resolved_at"` - ResolvedByID int `json:"resolved_by_id"` - ResolvedByPush bool `json:"resolved_by_push"` - StDiff *Diff `json:"st_diff"` - System bool `json:"system"` - Type string `json:"type"` - UpdatedAt string `json:"updated_at"` - UpdatedByID int `json:"updated_by_id"` - Description string `json:"description"` - Action CommentEventAction `json:"action"` - URL string `json:"url"` - } `json:"object_attributes"` - Repository *Repository `json:"repository"` - MergeRequest struct { - ID int `json:"id"` - TargetBranch string `json:"target_branch"` - SourceBranch string `json:"source_branch"` - SourceProjectID int `json:"source_project_id"` - AuthorID int `json:"author_id"` - AssigneeID int `json:"assignee_id"` - AssigneeIDs []int `json:"assignee_ids"` - ReviewerIDs []int `json:"reviewer_ids"` - Title string `json:"title"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - MilestoneID int `json:"milestone_id"` - State string `json:"state"` - MergeStatus string `json:"merge_status"` - TargetProjectID int `json:"target_project_id"` - IID int `json:"iid"` - Description string `json:"description"` - Position int `json:"position"` - Labels []*EventLabel `json:"labels"` - LockedAt string `json:"locked_at"` - UpdatedByID int `json:"updated_by_id"` - MergeError string `json:"merge_error"` - MergeParams *MergeParams `json:"merge_params"` - MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` - MergeUserID int `json:"merge_user_id"` - MergeCommitSHA string `json:"merge_commit_sha"` - DeletedAt string `json:"deleted_at"` - InProgressMergeCommitSHA string `json:"in_progress_merge_commit_sha"` - LockVersion int `json:"lock_version"` - ApprovalsBeforeMerge string `json:"approvals_before_merge"` - RebaseCommitSHA string `json:"rebase_commit_sha"` - TimeEstimate int `json:"time_estimate"` - Squash bool `json:"squash"` - LastEditedAt string `json:"last_edited_at"` - LastEditedByID int `json:"last_edited_by_id"` - Source *Repository `json:"source"` - Target *Repository `json:"target"` - LastCommit struct { - ID string `json:"id"` - Title string `json:"title"` - Message string `json:"message"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"last_commit"` - WorkInProgress bool `json:"work_in_progress"` - TotalTimeSpent int `json:"total_time_spent"` - HeadPipelineID int `json:"head_pipeline_id"` - Assignee *EventUser `json:"assignee"` - DetailedMergeStatus string `json:"detailed_merge_status"` - URL string `json:"url"` - } `json:"merge_request"` + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *EventUser `json:"user"` + ProjectID int64 `json:"project_id"` + Project MergeCommentEventProject `json:"project"` + ObjectAttributes MergeCommentEventObjectAttributes `json:"object_attributes"` + Repository *Repository `json:"repository"` + MergeRequest MergeCommentEventMergeRequest `json:"merge_request"` +} + +type MergeCommentEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type MergeCommentEventObjectAttributes struct { + Attachment string `json:"attachment"` + AuthorID int64 `json:"author_id"` + ChangePosition *NotePosition `json:"change_position"` + CommitID string `json:"commit_id"` + CreatedAt string `json:"created_at"` + DiscussionID string `json:"discussion_id"` + ID int64 `json:"id"` + LineCode string `json:"line_code"` + Note string `json:"note"` + NoteableID int64 `json:"noteable_id"` + NoteableType string `json:"noteable_type"` + OriginalPosition *NotePosition `json:"original_position"` + Position *NotePosition `json:"position"` + ProjectID int64 `json:"project_id"` + ResolvedAt string `json:"resolved_at"` + ResolvedByID int64 `json:"resolved_by_id"` + ResolvedByPush bool `json:"resolved_by_push"` + StDiff *Diff `json:"st_diff"` + System bool `json:"system"` + Type string `json:"type"` + UpdatedAt string `json:"updated_at"` + UpdatedByID int64 `json:"updated_by_id"` + Description string `json:"description"` + Action CommentEventAction `json:"action"` + URL string `json:"url"` +} + +type MergeCommentEventMergeRequest struct { + ID int64 `json:"id"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int64 `json:"source_project_id"` + AuthorID int64 `json:"author_id"` + AssigneeID int64 `json:"assignee_id"` + AssigneeIDs []int64 `json:"assignee_ids"` + ReviewerIDs []int64 `json:"reviewer_ids"` + Title string `json:"title"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + MilestoneID int64 `json:"milestone_id"` + State string `json:"state"` + MergeStatus string `json:"merge_status"` + TargetProjectID int64 `json:"target_project_id"` + IID int64 `json:"iid"` + Description string `json:"description"` + Position int64 `json:"position"` + Labels []*EventLabel `json:"labels"` + LockedAt string `json:"locked_at"` + UpdatedByID int64 `json:"updated_by_id"` + MergeError string `json:"merge_error"` + MergeParams *MergeParams `json:"merge_params"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MergeUserID int64 `json:"merge_user_id"` + MergeCommitSHA string `json:"merge_commit_sha"` + DeletedAt string `json:"deleted_at"` + InProgressMergeCommitSHA string `json:"in_progress_merge_commit_sha"` + LockVersion int64 `json:"lock_version"` + ApprovalsBeforeMerge string `json:"approvals_before_merge"` + RebaseCommitSHA string `json:"rebase_commit_sha"` + TimeEstimate int64 `json:"time_estimate"` + Squash bool `json:"squash"` + LastEditedAt string `json:"last_edited_at"` + LastEditedByID int64 `json:"last_edited_by_id"` + Source *Repository `json:"source"` + Target *Repository `json:"target"` + LastCommit EventMergeRequestLastCommit `json:"last_commit"` + WorkInProgress bool `json:"work_in_progress"` + TotalTimeSpent int64 `json:"total_time_spent"` + HeadPipelineID int64 `json:"head_pipeline_id"` + Assignee *EventUser `json:"assignee"` + DetailedMergeStatus string `json:"detailed_merge_status"` + URL string `json:"url"` +} + +type EventMergeRequestLastCommit struct { + ID string `json:"id"` + Title string `json:"title"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` } // MergeEvent represents a merge event. @@ -614,173 +684,170 @@ type MergeCommentEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#merge-request-events type MergeEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *EventUser `json:"user"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CIConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - ObjectAttributes struct { - ID int `json:"id"` - TargetBranch string `json:"target_branch"` - SourceBranch string `json:"source_branch"` - SourceProjectID int `json:"source_project_id"` - AuthorID int `json:"author_id"` - AssigneeID int `json:"assignee_id"` - AssigneeIDs []int `json:"assignee_ids"` - ReviewerIDs []int `json:"reviewer_ids"` - Title string `json:"title"` - CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) - UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) - StCommits []*Commit `json:"st_commits"` - StDiffs []*Diff `json:"st_diffs"` - LastEditedAt string `json:"last_edited_at"` - LastEditedByID int `json:"last_edited_by_id"` - MilestoneID int `json:"milestone_id"` - StateID StateID `json:"state_id"` - State string `json:"state"` - MergeStatus string `json:"merge_status"` - TargetProjectID int `json:"target_project_id"` - IID int `json:"iid"` - Description string `json:"description"` - Position int `json:"position"` - LockedAt string `json:"locked_at"` - UpdatedByID int `json:"updated_by_id"` - MergeError string `json:"merge_error"` - MergeParams *MergeParams `json:"merge_params"` - MergeWhenBuildSucceeds bool `json:"merge_when_build_succeeds"` - MergeUserID int `json:"merge_user_id"` - MergeCommitSHA string `json:"merge_commit_sha"` - DeletedAt string `json:"deleted_at"` - ApprovalsBeforeMerge string `json:"approvals_before_merge"` - RebaseCommitSHA string `json:"rebase_commit_sha"` - InProgressMergeCommitSHA string `json:"in_progress_merge_commit_sha"` - LockVersion int `json:"lock_version"` - TimeEstimate int `json:"time_estimate"` - Source *Repository `json:"source"` - Target *Repository `json:"target"` - HeadPipelineID *int `json:"head_pipeline_id"` - LastCommit struct { - ID string `json:"id"` - Message string `json:"message"` - Title string `json:"title"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"last_commit"` - BlockingDiscussionsResolved bool `json:"blocking_discussions_resolved"` - WorkInProgress bool `json:"work_in_progress"` - Draft bool `json:"draft"` - TotalTimeSpent int `json:"total_time_spent"` - TimeChange int `json:"time_change"` - HumanTotalTimeSpent string `json:"human_total_time_spent"` - HumanTimeChange string `json:"human_time_change"` - HumanTimeEstimate string `json:"human_time_estimate"` - FirstContribution bool `json:"first_contribution"` - URL string `json:"url"` - Labels []*EventLabel `json:"labels"` - Action string `json:"action"` - DetailedMergeStatus string `json:"detailed_merge_status"` - OldRev string `json:"oldrev"` - } `json:"object_attributes"` - Repository *Repository `json:"repository"` - Labels []*EventLabel `json:"labels"` - Changes struct { - Assignees struct { - Previous []*EventUser `json:"previous"` - Current []*EventUser `json:"current"` - } `json:"assignees"` - Reviewers struct { - Previous []*EventUser `json:"previous"` - Current []*EventUser `json:"current"` - } `json:"reviewers"` - Description struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"description"` - Draft struct { - Previous bool `json:"previous"` - Current bool `json:"current"` - } `json:"draft"` - Labels struct { - Previous []*EventLabel `json:"previous"` - Current []*EventLabel `json:"current"` - } `json:"labels"` - LastEditedAt struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"last_edited_at"` - LastEditedByID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"last_edited_by_id"` - MergeStatus struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"merge_status"` - MilestoneID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"milestone_id"` - SourceBranch struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"source_branch"` - SourceProjectID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"source_project_id"` - StateID struct { - Previous StateID `json:"previous"` - Current StateID `json:"current"` - } `json:"state_id"` - TargetBranch struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"target_branch"` - TargetProjectID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"target_project_id"` - Title struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"title"` - UpdatedAt struct { - Previous string `json:"previous"` - Current string `json:"current"` - } `json:"updated_at"` - UpdatedByID struct { - Previous int `json:"previous"` - Current int `json:"current"` - } `json:"updated_by_id"` - } `json:"changes"` - Assignees []*EventUser `json:"assignees"` - Reviewers []*EventUser `json:"reviewers"` -} - -// EventUser represents a user record in an event and is used as an even + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *EventUser `json:"user"` + Project MergeEventProject `json:"project"` + ObjectAttributes MergeEventObjectAttributes `json:"object_attributes"` + Repository *Repository `json:"repository"` + Labels []*EventLabel `json:"labels"` + Changes MergeEventChanges `json:"changes"` + Assignees []*EventUser `json:"assignees"` + Reviewers []*EventUser `json:"reviewers"` +} + +type MergeEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CIConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type MergeEventObjectAttributes struct { + ID int64 `json:"id"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int64 `json:"source_project_id"` + AuthorID int64 `json:"author_id"` + AssigneeID int64 `json:"assignee_id"` + AssigneeIDs []int64 `json:"assignee_ids"` + ReviewerIDs []int64 `json:"reviewer_ids"` + Title string `json:"title"` + CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) + UpdatedAt string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468) + StCommits []*Commit `json:"st_commits"` + StDiffs []*Diff `json:"st_diffs"` + LastEditedAt string `json:"last_edited_at"` + LastEditedByID int64 `json:"last_edited_by_id"` + MilestoneID int64 `json:"milestone_id"` + StateID StateID `json:"state_id"` + State string `json:"state"` + MergeStatus string `json:"merge_status"` + TargetProjectID int64 `json:"target_project_id"` + IID int64 `json:"iid"` + Description string `json:"description"` + Position int64 `json:"position"` + LockedAt string `json:"locked_at"` + UpdatedByID int64 `json:"updated_by_id"` + MergeError string `json:"merge_error"` + MergeParams *MergeParams `json:"merge_params"` + MergeWhenBuildSucceeds bool `json:"merge_when_build_succeeds"` + MergeUserID int64 `json:"merge_user_id"` + MergeCommitSHA string `json:"merge_commit_sha"` + DeletedAt string `json:"deleted_at"` + ApprovalsBeforeMerge string `json:"approvals_before_merge"` + RebaseCommitSHA string `json:"rebase_commit_sha"` + InProgressMergeCommitSHA string `json:"in_progress_merge_commit_sha"` + LockVersion int64 `json:"lock_version"` + TimeEstimate int64 `json:"time_estimate"` + Source *Repository `json:"source"` + Target *Repository `json:"target"` + HeadPipelineID *int64 `json:"head_pipeline_id"` + LastCommit EventMergeRequestLastCommit `json:"last_commit"` + BlockingDiscussionsResolved bool `json:"blocking_discussions_resolved"` + WorkInProgress bool `json:"work_in_progress"` + Draft bool `json:"draft"` + TotalTimeSpent int64 `json:"total_time_spent"` + TimeChange int64 `json:"time_change"` + HumanTotalTimeSpent string `json:"human_total_time_spent"` + HumanTimeChange string `json:"human_time_change"` + HumanTimeEstimate string `json:"human_time_estimate"` + FirstContribution bool `json:"first_contribution"` + URL string `json:"url"` + Labels []*EventLabel `json:"labels"` + Action string `json:"action"` + DetailedMergeStatus string `json:"detailed_merge_status"` + OldRev string `json:"oldrev"` + System bool `json:"system"` + SystemAction string `json:"system_action"` +} + +type MergeEventChanges struct { + Assignees EventChangesAssignees `json:"assignees"` + Reviewers MergeEventChangesReviewers `json:"reviewers"` + Description EventChangesDescription `json:"description"` + Draft MergeEventChangesDraft `json:"draft"` + Labels EventChangesLabels `json:"labels"` + LastEditedAt MergeEventChangesLastEditedAt `json:"last_edited_at"` + LastEditedByID MergeEventChangesLastEditedByID `json:"last_edited_by_id"` + MergeStatus MergeEventChangesMergeStatus `json:"merge_status"` + MilestoneID MergeEventChangesMilestoneID `json:"milestone_id"` + SourceBranch MergeEventChangesSourceBranch `json:"source_branch"` + SourceProjectID MergeEventChangesSourceProjectID `json:"source_project_id"` + StateID EventChangesStateID `json:"state_id"` + TargetBranch MergeEventChangesTargetBranch `json:"target_branch"` + TargetProjectID MergeEventChangesTargetProjectID `json:"target_project_id"` + Title EventChangesTitle `json:"title"` + UpdatedAt EventChangesUpdatedAt `json:"updated_at"` + UpdatedByID EventChangesUpdatedByID `json:"updated_by_id"` +} + +type MergeEventChangesReviewers struct { + Previous []*EventUser `json:"previous"` + Current []*EventUser `json:"current"` +} + +type MergeEventChangesDraft struct { + Previous bool `json:"previous"` + Current bool `json:"current"` +} + +type MergeEventChangesLastEditedAt struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type MergeEventChangesLastEditedByID struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` +} + +type MergeEventChangesMergeStatus struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type MergeEventChangesMilestoneID struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` +} + +type MergeEventChangesSourceBranch struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type MergeEventChangesSourceProjectID struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` +} + +type MergeEventChangesTargetBranch struct { + Previous string `json:"previous"` + Current string `json:"current"` +} + +type MergeEventChangesTargetProjectID struct { + Previous int64 `json:"previous"` + Current int64 `json:"current"` +} + +// EventUser represents a user record in an event and is used as an event // initiator or a merge assignee. type EventUser struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Username string `json:"username"` AvatarURL string `json:"avatar_url"` @@ -832,113 +899,114 @@ func (p *MergeParams) UnmarshalJSON(b []byte) error { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#pipeline-events type PipelineEvent struct { - ObjectKind string `json:"object_kind"` - ObjectAttributes struct { - ID int `json:"id"` - IID int `json:"iid"` - Name string `json:"name"` - Ref string `json:"ref"` - Tag bool `json:"tag"` - SHA string `json:"sha"` - BeforeSHA string `json:"before_sha"` - Source string `json:"source"` - Status string `json:"status"` - DetailedStatus string `json:"detailed_status"` - Stages []string `json:"stages"` - CreatedAt string `json:"created_at"` - FinishedAt string `json:"finished_at"` - Duration int `json:"duration"` - QueuedDuration int `json:"queued_duration"` - URL string `json:"url"` - Variables []struct { - Key string `json:"key"` - Value string `json:"value"` - } `json:"variables"` - } `json:"object_attributes"` - MergeRequest struct { - ID int `json:"id"` - IID int `json:"iid"` - Title string `json:"title"` - SourceBranch string `json:"source_branch"` - SourceProjectID int `json:"source_project_id"` - TargetBranch string `json:"target_branch"` - TargetProjectID int `json:"target_project_id"` - State string `json:"state"` - MergeRequestStatus string `json:"merge_status"` - DetailedMergeStatus string `json:"detailed_merge_status"` - URL string `json:"url"` - } `json:"merge_request"` - User *EventUser `json:"user"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Commit struct { - ID string `json:"id"` - Message string `json:"message"` - Title string `json:"title"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"commit"` - SourcePipeline struct { - Project struct { - ID int `json:"id"` - WebURL string `json:"web_url"` - PathWithNamespace string `json:"path_with_namespace"` - } `json:"project"` - PipelineID int `json:"pipeline_id"` - JobID int `json:"job_id"` - } `json:"source_pipeline"` - Builds []struct { - ID int `json:"id"` - Stage string `json:"stage"` - Name string `json:"name"` - Status string `json:"status"` - CreatedAt string `json:"created_at"` - StartedAt string `json:"started_at"` - FinishedAt string `json:"finished_at"` - Duration float64 `json:"duration"` - QueuedDuration float64 `json:"queued_duration"` - FailureReason string `json:"failure_reason"` - When string `json:"when"` - Manual bool `json:"manual"` - AllowFailure bool `json:"allow_failure"` - User *EventUser `json:"user"` - Runner struct { - ID int `json:"id"` - Description string `json:"description"` - Active bool `json:"active"` - IsShared bool `json:"is_shared"` - RunnerType string `json:"runner_type"` - Tags []string `json:"tags"` - } `json:"runner"` - ArtifactsFile struct { - Filename string `json:"filename"` - Size int `json:"size"` - } `json:"artifacts_file"` - Environment struct { - Name string `json:"name"` - Action string `json:"action"` - DeploymentTier string `json:"deployment_tier"` - } `json:"environment"` - } `json:"builds"` + ObjectKind string `json:"object_kind"` + ObjectAttributes PipelineEventObjectAttributes `json:"object_attributes"` + MergeRequest PipelineEventMergeRequest `json:"merge_request"` + User *EventUser `json:"user"` + Project PipelineEventProject `json:"project"` + Commit PipelineEventCommit `json:"commit"` + SourcePipeline EventSourcePipeline `json:"source_pipeline"` + Builds []PipelineEventBuild `json:"builds"` +} + +type PipelineEventObjectAttributes struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + Name string `json:"name"` + Ref string `json:"ref"` + Tag bool `json:"tag"` + SHA string `json:"sha"` + BeforeSHA string `json:"before_sha"` + Source string `json:"source"` + Status string `json:"status"` + DetailedStatus string `json:"detailed_status"` + Stages []string `json:"stages"` + CreatedAt string `json:"created_at"` + FinishedAt string `json:"finished_at"` + Duration int64 `json:"duration"` + QueuedDuration int64 `json:"queued_duration"` + URL string `json:"url"` + Variables []PipelineEventObjectAttributesVariable `json:"variables"` +} + +type PipelineEventObjectAttributesVariable struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type PipelineEventMergeRequest struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + Title string `json:"title"` + SourceBranch string `json:"source_branch"` + SourceProjectID int64 `json:"source_project_id"` + TargetBranch string `json:"target_branch"` + TargetProjectID int64 `json:"target_project_id"` + State string `json:"state"` + MergeRequestStatus string `json:"merge_status"` + DetailedMergeStatus string `json:"detailed_merge_status"` + URL string `json:"url"` +} + +type PipelineEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type PipelineEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Title string `json:"title"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` +} + +type PipelineEventBuild struct { + ID int64 `json:"id"` + Stage string `json:"stage"` + Name string `json:"name"` + Status string `json:"status"` + CreatedAt string `json:"created_at"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` + Duration float64 `json:"duration"` + QueuedDuration float64 `json:"queued_duration"` + FailureReason string `json:"failure_reason"` + When string `json:"when"` + Manual bool `json:"manual"` + AllowFailure bool `json:"allow_failure"` + User *EventUser `json:"user"` + Runner PipelineEventBuildRunner `json:"runner"` + ArtifactsFile PipelineEventBuildArtifactsFile `json:"artifacts_file"` + Environment EventEnvironment `json:"environment"` +} + +type PipelineEventBuildRunner struct { + ID int64 `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + RunnerType string `json:"runner_type"` + Tags []string `json:"tags"` +} + +type PipelineEventBuildArtifactsFile struct { + Filename string `json:"filename"` + Size int64 `json:"size"` } // ProjectResourceAccessTokenEvent represents a resource access token event for @@ -947,33 +1015,37 @@ type PipelineEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#project-and-group-access-token-events type ProjectResourceAccessTokenEvent struct { - EventName string `json:"event_name"` - ObjectKind string `json:"object_kind"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CIConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - } `json:"project"` - ObjectAttributes struct { - ID int `json:"id"` - UserID int `json:"user_id"` - Name string `json:"name"` - CreatedAt string `json:"created_at"` - ExpiresAt *ISOTime `json:"expires_at"` - } `json:"object_attributes"` + EventName string `json:"event_name"` + ObjectKind string `json:"object_kind"` + Project ProjectResourceAccessTokenEventProject `json:"project"` + ObjectAttributes ProjectResourceAccessTokenEventObjectAttributes `json:"object_attributes"` +} + +type ProjectResourceAccessTokenEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CIConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` +} + +type ProjectResourceAccessTokenEventObjectAttributes struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + Name string `json:"name"` + CreatedAt string `json:"created_at"` + ExpiresAt *ISOTime `json:"expires_at"` } // PushEvent represents a push event. @@ -981,52 +1053,53 @@ type ProjectResourceAccessTokenEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#push-events type PushEvent struct { - ObjectKind string `json:"object_kind"` - EventName string `json:"event_name"` - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - RefProtected bool `json:"ref_protected"` - CheckoutSHA string `json:"checkout_sha"` - UserID int `json:"user_id"` - UserName string `json:"user_name"` - UserUsername string `json:"user_username"` - UserEmail string `json:"user_email"` - UserAvatar string `json:"user_avatar"` - ProjectID int `json:"project_id"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - Commits []*struct { - ID string `json:"id"` - Message string `json:"message"` - Title string `json:"title"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - Added []string `json:"added"` - Modified []string `json:"modified"` - Removed []string `json:"removed"` - } `json:"commits"` - TotalCommitsCount int `json:"total_commits_count"` + ObjectKind string `json:"object_kind"` + EventName string `json:"event_name"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + RefProtected bool `json:"ref_protected"` + CheckoutSHA string `json:"checkout_sha"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + UserUsername string `json:"user_username"` + UserEmail string `json:"user_email"` + UserAvatar string `json:"user_avatar"` + ProjectID int64 `json:"project_id"` + Project PushEventProject `json:"project"` + Repository *Repository `json:"repository"` + Commits []*PushEventCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` +} + +type PushEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type PushEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Title string `json:"title"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` + Added []string `json:"added"` + Modified []string `json:"modified"` + Removed []string `json:"removed"` } // ReleaseEvent represents a release event @@ -1034,58 +1107,65 @@ type PushEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#release-events type ReleaseEvent struct { - ID int `json:"id"` - CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) - Description string `json:"description"` - Name string `json:"name"` - Tag string `json:"tag"` - ReleasedAt string `json:"released_at"` // Should be *time.Time (see Gitlab issue #21468) - ObjectKind string `json:"object_kind"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - WebURL string `json:"web_url"` - AvatarURL *string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - VisibilityLevel int `json:"visibility_level"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - CIConfigPath string `json:"ci_config_path"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - } `json:"project"` + ID int64 `json:"id"` + CreatedAt string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468) + Description string `json:"description"` + Name string `json:"name"` + Tag string `json:"tag"` + ReleasedAt string `json:"released_at"` // Should be *time.Time (see Gitlab issue #21468) + ObjectKind string `json:"object_kind"` + Project ReleaseEventProject `json:"project"` + URL string `json:"url"` + Action string `json:"action"` + Assets ReleaseEventAssets `json:"assets"` + Commit ReleaseEventCommit `json:"commit"` +} + +type ReleaseEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL *string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CIConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` +} + +type ReleaseEventAssets struct { + Count int64 `json:"count"` + Links []ReleaseEventAssetsLink `json:"links"` + Sources []ReleaseEventAssetsSource `json:"sources"` +} + +type ReleaseEventAssetsLink struct { + ID int64 `json:"id"` + External bool `json:"external"` + LinkType string `json:"link_type"` + Name string `json:"name"` + URL string `json:"url"` +} + +type ReleaseEventAssetsSource struct { + Format string `json:"format"` URL string `json:"url"` - Action string `json:"action"` - Assets struct { - Count int `json:"count"` - Links []struct { - ID int `json:"id"` - External bool `json:"external"` - LinkType string `json:"link_type"` - Name string `json:"name"` - URL string `json:"url"` - } `json:"links"` - Sources []struct { - Format string `json:"format"` - URL string `json:"url"` - } `json:"sources"` - } `json:"assets"` - Commit struct { - ID string `json:"id"` - Message string `json:"message"` - Title string `json:"title"` - Timestamp string `json:"timestamp"` // Should be *time.Time (see Gitlab issue #21468) - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - } `json:"commit"` +} + +type ReleaseEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Title string `json:"title"` + Timestamp string `json:"timestamp"` // Should be *time.Time (see Gitlab issue #21468) + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` } // SnippetCommentEvent represents a comment on a snippet event. @@ -1093,61 +1173,67 @@ type ReleaseEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#comment-on-a-code-snippet type SnippetCommentEvent struct { - ObjectKind string `json:"object_kind"` - EventType string `json:"event_type"` - User *EventUser `json:"user"` - ProjectID int `json:"project_id"` - Project struct { - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - ObjectAttributes struct { - ID int `json:"id"` - Note string `json:"note"` - NoteableType string `json:"noteable_type"` - AuthorID int `json:"author_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ProjectID int `json:"project_id"` - Attachment string `json:"attachment"` - LineCode string `json:"line_code"` - CommitID string `json:"commit_id"` - NoteableID int `json:"noteable_id"` - System bool `json:"system"` - StDiff *Diff `json:"st_diff"` - Description string `json:"description"` - Action CommentEventAction `json:"action"` - URL string `json:"url"` - } `json:"object_attributes"` - Snippet *struct { - ID int `json:"id"` - Title string `json:"title"` - Content string `json:"content"` - AuthorID int `json:"author_id"` - ProjectID int `json:"project_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - Filename string `json:"file_name"` - ExpiresAt string `json:"expires_at"` - Type string `json:"type"` - VisibilityLevel int `json:"visibility_level"` - Description string `json:"description"` - Secret bool `json:"secret"` - RepositoryReadOnly bool `json:"repository_read_only"` - } `json:"snippet"` + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User *EventUser `json:"user"` + ProjectID int64 `json:"project_id"` + Project SnippetCommentEventProject `json:"project"` + Repository *Repository `json:"repository"` + ObjectAttributes SnippetCommentEventObjectAttributes `json:"object_attributes"` + Snippet *SnippetCommentEventSnippet `json:"snippet"` +} + +type SnippetCommentEventProject struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type SnippetCommentEventObjectAttributes struct { + ID int64 `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int64 `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int64 `json:"project_id"` + Attachment string `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int64 `json:"noteable_id"` + System bool `json:"system"` + StDiff *Diff `json:"st_diff"` + Description string `json:"description"` + Action CommentEventAction `json:"action"` + URL string `json:"url"` +} + +type SnippetCommentEventSnippet struct { + ID int64 `json:"id"` + Title string `json:"title"` + Content string `json:"content"` + AuthorID int64 `json:"author_id"` + ProjectID int64 `json:"project_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Filename string `json:"file_name"` + ExpiresAt string `json:"expires_at"` + Type string `json:"type"` + VisibilityLevel int64 `json:"visibility_level"` + Description string `json:"description"` + Secret bool `json:"secret"` + RepositoryReadOnly bool `json:"repository_read_only"` } // SubGroupEvent represents a subgroup event. @@ -1161,8 +1247,8 @@ type SubGroupEvent struct { Name string `json:"name"` Path string `json:"path"` FullPath string `json:"full_path"` - GroupID int `json:"group_id"` - ParentGroupID int `json:"parent_group_id"` + GroupID int64 `json:"group_id"` + ParentGroupID int64 `json:"parent_group_id"` ParentName string `json:"parent_name"` ParentPath string `json:"parent_path"` ParentFullPath string `json:"parent_full_path"` @@ -1173,52 +1259,53 @@ type SubGroupEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#tag-events type TagEvent struct { - ObjectKind string `json:"object_kind"` - EventName string `json:"event_name"` - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - CheckoutSHA string `json:"checkout_sha"` - UserID int `json:"user_id"` - UserName string `json:"user_name"` - UserUsername string `json:"user_username"` - UserAvatar string `json:"user_avatar"` - UserEmail string `json:"user_email"` - ProjectID int `json:"project_id"` - Message string `json:"message"` - Project struct { - ID int `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Repository *Repository `json:"repository"` - Commits []*struct { - ID string `json:"id"` - Message string `json:"message"` - Title string `json:"title"` - Timestamp *time.Time `json:"timestamp"` - URL string `json:"url"` - Author struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"author"` - Added []string `json:"added"` - Modified []string `json:"modified"` - Removed []string `json:"removed"` - } `json:"commits"` - TotalCommitsCount int `json:"total_commits_count"` + ObjectKind string `json:"object_kind"` + EventName string `json:"event_name"` + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + CheckoutSHA string `json:"checkout_sha"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + UserUsername string `json:"user_username"` + UserAvatar string `json:"user_avatar"` + UserEmail string `json:"user_email"` + ProjectID int64 `json:"project_id"` + Message string `json:"message"` + Project TagEventProject `json:"project"` + Repository *Repository `json:"repository"` + Commits []*TagEventCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` +} + +type TagEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type TagEventCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Title string `json:"title"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` + Added []string `json:"added"` + Modified []string `json:"modified"` + Removed []string `json:"removed"` } // WikiPageEvent represents a wiki page event. @@ -1226,41 +1313,384 @@ type TagEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#wiki-page-events type WikiPageEvent struct { - ObjectKind string `json:"object_kind"` - User *EventUser `json:"user"` - Project struct { - Name string `json:"name"` - Description string `json:"description"` - AvatarURL string `json:"avatar_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - Namespace string `json:"namespace"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - Homepage string `json:"homepage"` - URL string `json:"url"` - SSHURL string `json:"ssh_url"` - HTTPURL string `json:"http_url"` - WebURL string `json:"web_url"` - Visibility VisibilityValue `json:"visibility"` - } `json:"project"` - Wiki struct { - WebURL string `json:"web_url"` - GitSSHURL string `json:"git_ssh_url"` - GitHTTPURL string `json:"git_http_url"` - PathWithNamespace string `json:"path_with_namespace"` - DefaultBranch string `json:"default_branch"` - } `json:"wiki"` - ObjectAttributes struct { - Title string `json:"title"` - Content string `json:"content"` - Format string `json:"format"` - Message string `json:"message"` - Slug string `json:"slug"` - URL string `json:"url"` - Action string `json:"action"` - DiffURL string `json:"diff_url"` - } `json:"object_attributes"` + ObjectKind string `json:"object_kind"` + User *EventUser `json:"user"` + Project WikiPageEventProject `json:"project"` + Wiki WikiPageEventWiki `json:"wiki"` + ObjectAttributes WikiPageEventObjectAttributes `json:"object_attributes"` +} + +type WikiPageEventProject struct { + Name string `json:"name"` + Description string `json:"description"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` + WebURL string `json:"web_url"` + Visibility VisibilityValue `json:"visibility"` +} + +type WikiPageEventWiki struct { + WebURL string `json:"web_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` +} + +type WikiPageEventObjectAttributes struct { + Title string `json:"title"` + Content string `json:"content"` + Format string `json:"format"` + Message string `json:"message"` + Slug string `json:"slug"` + URL string `json:"url"` + Action string `json:"action"` + DiffURL string `json:"diff_url"` +} + +// EmojiEvent represents an emoji event. +// +// GitLab API docs: +// https://docs.gitlab.com/user/project/integrations/webhook_events/#emoji-events +type EmojiEvent struct { + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + User EventUser `json:"user"` + ProjectID int64 `json:"project_id"` + Project EmojiEventProject `json:"project"` + ObjectAttributes EmojiEventObjectAttributes `json:"object_attributes"` + Note *EmojiEventNote `json:"note,omitempty"` + Issue *EmojiEventIssue `json:"issue,omitempty"` + MergeRequest *EmojiEventMergeRequest `json:"merge_request,omitempty"` + ProjectSnippet *EmojiEventSnippet `json:"project_snippet,omitempty"` + Commit *EmojiEventCommit `json:"commit,omitempty"` +} + +// EmojiEventProject represents a project in an emoji event. +type EmojiEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CIConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` +} + +type EmojiEventObjectAttributes struct { + UserID int64 `json:"user_id"` + CreatedAt string `json:"created_at"` + ID int64 `json:"id"` + Name string `json:"name"` + AwardableType string `json:"awardable_type"` + AwardableID int64 `json:"awardable_id"` + UpdatedAt string `json:"updated_at"` + Action string `json:"action"` + AwardedOnURL string `json:"awarded_on_url"` +} + +type EmojiEventNote struct { + Attachment *string `json:"attachment"` + AuthorID int64 `json:"author_id"` + ChangePosition *NotePosition `json:"change_position"` + CommitID *string `json:"commit_id"` + CreatedAt string `json:"created_at"` + DiscussionID string `json:"discussion_id"` + ID int64 `json:"id"` + LineCode *string `json:"line_code"` + Note string `json:"note"` + NoteableID int64 `json:"noteable_id"` + NoteableType string `json:"noteable_type"` + OriginalPosition *NotePosition `json:"original_position"` + Position *NotePosition `json:"position"` + ProjectID int64 `json:"project_id"` + ResolvedAt *string `json:"resolved_at"` + ResolvedByID *int64 `json:"resolved_by_id"` + ResolvedByPush *bool `json:"resolved_by_push"` + StDiff *Diff `json:"st_diff"` + System bool `json:"system"` + Type *string `json:"type"` + UpdatedAt string `json:"updated_at"` + UpdatedByID *int64 `json:"updated_by_id"` + Description string `json:"description"` + URL string `json:"url"` +} + +type EmojiEventIssue struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` + AuthorID int64 `json:"author_id"` + ClosedAt *string `json:"closed_at"` + Confidential bool `json:"confidential"` + CreatedAt string `json:"created_at"` + Description string `json:"description"` + DiscussionLocked *bool `json:"discussion_locked"` + DueDate *ISOTime `json:"due_date"` + LastEditedAt *string `json:"last_edited_at"` + LastEditedByID *int64 `json:"last_edited_by_id"` + MilestoneID *int64 `json:"milestone_id"` + MovedToID *int64 `json:"moved_to_id"` + DuplicatedToID *int64 `json:"duplicated_to_id"` + RelativePosition int64 `json:"relative_position"` + StateID StateID `json:"state_id"` + TimeEstimate int64 `json:"time_estimate"` + Title string `json:"title"` + UpdatedAt string `json:"updated_at"` + UpdatedByID *int64 `json:"updated_by_id"` + Weight *int64 `json:"weight"` + HealthStatus *string `json:"health_status"` + URL string `json:"url"` + TotalTimeSpent int64 `json:"total_time_spent"` + TimeChange int64 `json:"time_change"` + HumanTotalTimeSpent *string `json:"human_total_time_spent"` + HumanTimeChange *string `json:"human_time_change"` + HumanTimeEstimate *string `json:"human_time_estimate"` + AssigneeIDs []int64 `json:"assignee_ids"` + AssigneeID *int64 `json:"assignee_id"` + Labels []*EventLabel `json:"labels"` + State string `json:"state"` + Severity string `json:"severity"` +} + +// EmojiEventMergeRequest represents a merge request in an emoji event. +type EmojiEventMergeRequest struct { + ID int64 `json:"id"` + TargetBranch string `json:"target_branch"` + SourceBranch string `json:"source_branch"` + SourceProjectID int64 `json:"source_project_id"` + AuthorID int64 `json:"author_id"` + AssigneeID int64 `json:"assignee_id"` + AssigneeIDs []int64 `json:"assignee_ids"` + ReviewerIDs []int64 `json:"reviewer_ids"` + Title string `json:"title"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + MilestoneID int64 `json:"milestone_id"` + State string `json:"state"` + MergeStatus string `json:"merge_status"` + TargetProjectID int64 `json:"target_project_id"` + IID int64 `json:"iid"` + Description string `json:"description"` + Position int64 `json:"position"` + Labels []*EventLabel `json:"labels"` + LockedAt string `json:"locked_at"` + UpdatedByID int64 `json:"updated_by_id"` + MergeError string `json:"merge_error"` + MergeParams *MergeParams `json:"merge_params"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MergeUserID int64 `json:"merge_user_id"` + MergeCommitSHA string `json:"merge_commit_sha"` + DeletedAt string `json:"deleted_at"` + InProgressMergeCommitSHA string `json:"in_progress_merge_commit_sha"` + LockVersion int64 `json:"lock_version"` + ApprovalsBeforeMerge string `json:"approvals_before_merge"` + RebaseCommitSHA string `json:"rebase_commit_sha"` + TimeEstimate int64 `json:"time_estimate"` + Squash bool `json:"squash"` + LastEditedAt string `json:"last_edited_at"` + LastEditedByID int64 `json:"last_edited_by_id"` + Source *Repository `json:"source"` + Target *Repository `json:"target"` + LastCommit EventMergeRequestLastCommit `json:"last_commit"` + WorkInProgress bool `json:"work_in_progress"` + TotalTimeSpent int64 `json:"total_time_spent"` + HeadPipelineID int64 `json:"head_pipeline_id"` + Assignee *EventUser `json:"assignee"` + DetailedMergeStatus string `json:"detailed_merge_status"` + URL string `json:"url"` +} + +// EmojiEventSnippet represents a snippet in an emoji event. +type EmojiEventSnippet struct { + ID int64 `json:"id"` + Title string `json:"title"` + Content string `json:"content"` + AuthorID int64 `json:"author_id"` + ProjectID int64 `json:"project_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Filename string `json:"file_name"` + ExpiresAt string `json:"expires_at"` + Type string `json:"type"` + VisibilityLevel int64 `json:"visibility_level"` + Description string `json:"description"` + Secret bool `json:"secret"` + RepositoryReadOnly bool `json:"repository_read_only"` +} + +// EmojiEventCommit represents a commit in an emoji event. +type EmojiEventCommit struct { + ID string `json:"id"` + Title string `json:"title"` + Message string `json:"message"` + Timestamp *time.Time `json:"timestamp"` + URL string `json:"url"` + Author EventCommitAuthor `json:"author"` +} + +// MilestoneWebhookEvent represents a milestone webhook event. +// +// GitLab API docs: +// https://docs.gitlab.com/user/project/integrations/webhook_events/#milestone-events +type MilestoneWebhookEvent struct { + ObjectKind string `json:"object_kind"` + EventType string `json:"event_type"` + Project MilestoneEventProject `json:"project"` + Group *MilestoneEventGroup `json:"group,omitempty"` + ObjectAttributes MilestoneEventObjectAttributes `json:"object_attributes"` + Action string `json:"action"` +} + +type MilestoneEventObjectAttributes struct { + ID int64 `json:"id"` + IID int64 `json:"iid"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + DueDate *ISOTime `json:"due_date"` + StartDate *ISOTime `json:"start_date"` + GroupID *int64 `json:"group_id"` + ProjectID int64 `json:"project_id"` +} + +// MilestoneEventGroup represents a group in a milestone event. +type MilestoneEventGroup struct { + GroupID int64 `json:"group_id"` + GroupName string `json:"group_name"` + GroupPath string `json:"group_path"` + FullPath string `json:"full_path"` +} + +// MilestoneEventProject represents a project in a milestone event. +type MilestoneEventProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + WebURL string `json:"web_url"` + AvatarURL string `json:"avatar_url"` + GitSSHURL string `json:"git_ssh_url"` + GitHTTPURL string `json:"git_http_url"` + Namespace string `json:"namespace"` + VisibilityLevel int64 `json:"visibility_level"` + PathWithNamespace string `json:"path_with_namespace"` + DefaultBranch string `json:"default_branch"` + CIConfigPath string `json:"ci_config_path"` + Homepage string `json:"homepage"` + URL string `json:"url"` + SSHURL string `json:"ssh_url"` + HTTPURL string `json:"http_url"` +} + +// ProjectWebhookEvent represents a project webhook event for group webhooks. +// +// GitLab API docs: +// https://docs.gitlab.com/user/project/integrations/webhook_events/#project-events +type ProjectWebhookEvent struct { + EventName string `json:"event_name"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Name string `json:"name"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + ProjectID int64 `json:"project_id"` + ProjectNamespaceID int64 `json:"project_namespace_id"` + Owners []ProjectEventOwner `json:"owners"` + ProjectVisibility string `json:"project_visibility"` + OldPathWithNamespace string `json:"old_path_with_namespace,omitempty"` +} + +type ProjectEventOwner struct { + Name string `json:"name"` + Email string `json:"email"` +} + +// VulnerabilityEvent represents a vulnerability event. +// +// GitLab API docs: +// https://docs.gitlab.com/user/project/integrations/webhook_events/#vulnerability-events +type VulnerabilityEvent struct { + ObjectKind string `json:"object_kind"` + ObjectAttributes VulnerabilityEventObjectAttributes `json:"object_attributes"` +} + +type VulnerabilityEventObjectAttributes struct { + ID int64 `json:"id"` + URL string `json:"url"` + Title string `json:"title"` + State string `json:"state"` + ProjectID int64 `json:"project_id"` + Location VulnerabilityEventLocation `json:"location"` + CVSS []VulnerabilityEventCVSS `json:"cvss"` + Severity string `json:"severity"` + SeverityOverridden bool `json:"severity_overridden"` + Identifiers []VulnerabilityEventIdentifier `json:"identifiers"` + Issues []VulnerabilityEventIssue `json:"issues"` + ReportType string `json:"report_type"` + Confidence string `json:"confidence"` + ConfidenceOverridden bool `json:"confidence_overridden"` + ConfirmedAt string `json:"confirmed_at"` + ConfirmedByID int64 `json:"confirmed_by_id"` + DismissedAt string `json:"dismissed_at"` + DismissedByID int64 `json:"dismissed_by_id"` + ResolvedAt string `json:"resolved_at"` + ResolvedByID int64 `json:"resolved_by_id"` + AutoResolved bool `json:"auto_resolved"` + ResolvedOnDefaultBranch bool `json:"resolved_on_default_branch"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} + +type VulnerabilityEventLocation struct { + File string `json:"file"` + Dependency VulnerabilityEventLocationDependency `json:"dependency"` +} + +type VulnerabilityEventLocationDependency struct { + Package VulnerabilityEventLocationDependencyPackage `json:"package"` + Version string `json:"version"` +} + +type VulnerabilityEventLocationDependencyPackage struct { + Name string `json:"name"` +} + +type VulnerabilityEventCVSS struct { + Vector string `json:"vector"` + Vendor string `json:"vendor"` +} + +type VulnerabilityEventIdentifier struct { + Name string `json:"name"` + ExternalID string `json:"external_id"` + ExternalType string `json:"external_type"` + URL string `json:"url"` +} + +type VulnerabilityEventIssue struct { + Title string `json:"title"` + URL string `json:"url"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } // EventLabel represents a label inside a webhook event. @@ -1268,14 +1698,14 @@ type WikiPageEvent struct { // GitLab API docs: // https://docs.gitlab.com/user/project/integrations/webhook_events/#work-item-events type EventLabel struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Color string `json:"color"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` Template bool `json:"template"` Description string `json:"description"` Type string `json:"type"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/events.go b/vendor/gitlab.com/gitlab-org/api/client-go/events.go index 5107a5aa6..75df36658 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/events.go @@ -17,15 +17,23 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( // EventsServiceInterface defines all the API methods for the EventsService EventsServiceInterface interface { + // ListCurrentUserContributionEvents retrieves all events + // for the currently authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/events/#list-all-events ListCurrentUserContributionEvents(opt *ListContributionEventsOptions, options ...RequestOptionFunc) ([]*ContributionEvent, *Response, error) + + // ListProjectVisibleEvents gets the events for the specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/events/#list-a-projects-visible-events ListProjectVisibleEvents(pid any, opt *ListProjectVisibleEventsOptions, options ...RequestOptionFunc) ([]*ProjectEvent, *Response, error) } @@ -45,35 +53,34 @@ var _ EventsServiceInterface = (*EventsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/events/#get-user-contribution-events type ContributionEvent struct { - ID int `json:"id"` - Title string `json:"title"` - ProjectID int `json:"project_id"` - ActionName string `json:"action_name"` - TargetID int `json:"target_id"` - TargetIID int `json:"target_iid"` - TargetType string `json:"target_type"` - AuthorID int `json:"author_id"` - TargetTitle string `json:"target_title"` - CreatedAt *time.Time `json:"created_at"` - PushData struct { - CommitCount int `json:"commit_count"` - Action string `json:"action"` - RefType string `json:"ref_type"` - CommitFrom string `json:"commit_from"` - CommitTo string `json:"commit_to"` - Ref string `json:"ref"` - CommitTitle string `json:"commit_title"` - } `json:"push_data"` - Note *Note `json:"note"` - Author struct { - Name string `json:"name"` - Username string `json:"username"` - ID int `json:"id"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"author"` - AuthorUsername string `json:"author_username"` + ID int64 `json:"id"` + Title string `json:"title"` + ProjectID int64 `json:"project_id"` + ActionName string `json:"action_name"` + TargetID int64 `json:"target_id"` + TargetIID int64 `json:"target_iid"` + TargetType string `json:"target_type"` + AuthorID int64 `json:"author_id"` + TargetTitle string `json:"target_title"` + CreatedAt *time.Time `json:"created_at"` + PushData ContributionEventPushData `json:"push_data"` + Note *Note `json:"note"` + Author BasicUser `json:"author"` + AuthorUsername string `json:"author_username"` +} + +// ContributionEventPushData represents a user's contribution push data. +// +// GitLab API docs: +// https://docs.gitlab.com/api/events/#get-contribution-events-for-a-user +type ContributionEventPushData struct { + CommitCount int64 `json:"commit_count"` + Action string `json:"action"` + RefType string `json:"ref_type"` + CommitFrom string `json:"commit_from"` + CommitTo string `json:"commit_to"` + Ref string `json:"ref"` + CommitTitle string `json:"commit_title"` } // ListContributionEventsOptions represents the options for GetUserContributionEvents @@ -87,125 +94,136 @@ type ListContributionEventsOptions struct { Before *ISOTime `url:"before,omitempty" json:"before,omitempty"` After *ISOTime `url:"after,omitempty" json:"after,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` } -// ListUserContributionEvents retrieves user contribution events -// for the specified user, sorted from newest to oldest. -// -// GitLab API docs: -// https://docs.gitlab.com/api/events/#get-user-contribution-events func (s *UsersService) ListUserContributionEvents(uid any, opt *ListContributionEventsOptions, options ...RequestOptionFunc) ([]*ContributionEvent, *Response, error) { user, err := parseID(uid) if err != nil { return nil, nil, err } - u := fmt.Sprintf("users/%s/events", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var cs []*ContributionEvent - resp, err := s.client.Do(req, &cs) - if err != nil { - return nil, resp, err - } - return cs, resp, nil + return do[[]*ContributionEvent](s.client, + withPath("users/%s/events", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListCurrentUserContributionEvents gets a list currently authenticated user's events -// -// GitLab API docs: https://docs.gitlab.com/api/events/#list-currently-authenticated-users-events func (s *EventsService) ListCurrentUserContributionEvents(opt *ListContributionEventsOptions, options ...RequestOptionFunc) ([]*ContributionEvent, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "events", opt, options) - if err != nil { - return nil, nil, err - } - - var cs []*ContributionEvent - resp, err := s.client.Do(req, &cs) - if err != nil { - return nil, resp, err - } - - return cs, resp, nil + return do[[]*ContributionEvent](s.client, + withPath("events"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectEvent represents a GitLab project event. // // GitLab API docs: -// https://docs.gitlab.com/api/events/#list-a-projects-visible-events +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project type ProjectEvent struct { - ID int `json:"id"` - Title string `json:"title"` - ProjectID int `json:"project_id"` - ActionName string `json:"action_name"` - TargetID int `json:"target_id"` - TargetIID int `json:"target_iid"` - TargetType string `json:"target_type"` - AuthorID int `json:"author_id"` - TargetTitle string `json:"target_title"` - CreatedAt string `json:"created_at"` - Author struct { - Name string `json:"name"` - Username string `json:"username"` - ID int `json:"id"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"author"` - AuthorUsername string `json:"author_username"` - Data struct { - Before string `json:"before"` - After string `json:"after"` - Ref string `json:"ref"` - UserID int `json:"user_id"` - UserName string `json:"user_name"` - Repository *Repository `json:"repository"` - Commits []*Commit `json:"commits"` - TotalCommitsCount int `json:"total_commits_count"` - } `json:"data"` - Note struct { - ID int `json:"id"` - Body string `json:"body"` - Attachment string `json:"attachment"` - Author struct { - ID int `json:"id"` - Username string `json:"username"` - Email string `json:"email"` - Name string `json:"name"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"author"` - CreatedAt *time.Time `json:"created_at"` - System bool `json:"system"` - NoteableID int `json:"noteable_id"` - NoteableType string `json:"noteable_type"` - NoteableIID int `json:"noteable_iid"` - } `json:"note"` - PushData struct { - CommitCount int `json:"commit_count"` - Action string `json:"action"` - RefType string `json:"ref_type"` - CommitFrom string `json:"commit_from"` - CommitTo string `json:"commit_to"` - Ref string `json:"ref"` - CommitTitle string `json:"commit_title"` - } `json:"push_data"` + ID int64 `json:"id"` + Title string `json:"title"` + ProjectID int64 `json:"project_id"` + ActionName string `json:"action_name"` + TargetID int64 `json:"target_id"` + TargetIID int64 `json:"target_iid"` + TargetType string `json:"target_type"` + AuthorID int64 `json:"author_id"` + TargetTitle string `json:"target_title"` + CreatedAt string `json:"created_at"` + Author BasicUser `json:"author"` + AuthorUsername string `json:"author_username"` + Data ProjectEventData `json:"data"` + Note ProjectEventNote `json:"note"` + PushData ProjectEventPushData `json:"push_data"` } func (s ProjectEvent) String() string { return Stringify(s) } +// ProjectEventData represents the GitLab project event data. +// +// GitLab API docs: +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project +type ProjectEventData struct { + Before string `json:"before"` + After string `json:"after"` + Ref string `json:"ref"` + UserID int64 `json:"user_id"` + UserName string `json:"user_name"` + Repository *Repository `json:"repository"` + Commits []*Commit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` +} + +func (d ProjectEventData) String() string { + return Stringify(d) +} + +// ProjectEventNote represents a GitLab project event note. +// +// GitLab API docs: +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project +type ProjectEventNote struct { + ID int64 `json:"id"` + Body string `json:"body"` + Attachment string `json:"attachment"` + Author ProjectEventNoteAuthor `json:"author"` + CreatedAt *time.Time `json:"created_at"` + System bool `json:"system"` + NoteableID int64 `json:"noteable_id"` + NoteableType string `json:"noteable_type"` + NoteableIID int64 `json:"noteable_iid"` +} + +func (n ProjectEventNote) String() string { + return Stringify(n) +} + +// ProjectEventNoteAuthor represents a GitLab project event note author. +// +// GitLab API docs: +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project +type ProjectEventNoteAuthor struct { + ID int64 `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` +} + +func (a ProjectEventNoteAuthor) String() string { + return Stringify(a) +} + +// ProjectEventPushData represents a GitLab project event push data. +// +// GitLab API docs: +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project +type ProjectEventPushData struct { + CommitCount int64 `json:"commit_count"` + Action string `json:"action"` + RefType string `json:"ref_type"` + CommitFrom string `json:"commit_from"` + CommitTo string `json:"commit_to"` + Ref string `json:"ref"` + CommitTitle string `json:"commit_title"` +} + +func (d ProjectEventPushData) String() string { + return Stringify(d) +} + // ListProjectVisibleEventsOptions represents the available // ListProjectVisibleEvents() options. // // GitLab API docs: -// https://docs.gitlab.com/api/events/#list-a-projects-visible-events +// https://docs.gitlab.com/api/events/#list-all-visible-events-for-a-project type ListProjectVisibleEventsOptions struct { ListOptions Action *EventTypeValue `url:"action,omitempty" json:"action,omitempty"` @@ -215,27 +233,10 @@ type ListProjectVisibleEventsOptions struct { Sort *string `url:"sort,omitempty" json:"sort,omitempty"` } -// ListProjectVisibleEvents gets the events for the specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/events/#list-a-projects-visible-events func (s *EventsService) ListProjectVisibleEvents(pid any, opt *ListProjectVisibleEventsOptions, options ...RequestOptionFunc) ([]*ProjectEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/events", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*ProjectEvent - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*ProjectEvent](s.client, + withPath("projects/%s/events", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/external_status_checks.go b/vendor/gitlab.com/gitlab-org/api/client-go/external_status_checks.go index aff042add..227f17bfb 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/external_status_checks.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/external_status_checks.go @@ -1,7 +1,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -9,28 +8,98 @@ import ( type ( // ExternalStatusChecksServiceInterface defines all the API methods for the ExternalStatusChecksService ExternalStatusChecksServiceInterface interface { + // CreateExternalStatusCheck creates an external status check. // Deprecated: to be removed in 1.0; use CreateProjectExternalStatusCheck instead + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#create-external-status-check-service CreateExternalStatusCheck(pid any, opt *CreateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) + + // DeleteExternalStatusCheck deletes an external status check. // Deprecated: to be removed in 1.0; use DeleteProjectExternalStatusCheck instead - DeleteExternalStatusCheck(pid any, check int, options ...RequestOptionFunc) (*Response, error) + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#delete-external-status-check-service + DeleteExternalStatusCheck(pid any, check int64, options ...RequestOptionFunc) (*Response, error) + + // UpdateExternalStatusCheck updates an external status check. // Deprecated: to be removed in 1.0; use UpdateProjectExternalStatusCheck instead - UpdateExternalStatusCheck(pid any, check int, opt *UpdateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service + UpdateExternalStatusCheck(pid any, check int64, opt *UpdateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) + + // ListMergeStatusChecks lists the external status checks that apply to it + // and their status for a single merge request. // Deprecated: to be removed in 1.0; use ListProjectMergeRequestExternalStatusChecks instead - ListMergeStatusChecks(pid any, mr int, opt *ListOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#list-status-checks-for-a-merge-request + ListMergeStatusChecks(pid any, mr int64, opt *ListOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) + + // ListProjectStatusChecks lists the project external status checks. // Deprecated: to be removed in 1.0; use ListProjectExternalStatusChecks instead + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#get-project-external-status-check-services ListProjectStatusChecks(pid any, opt *ListOptions, options ...RequestOptionFunc) ([]*ProjectStatusCheck, *Response, error) + + // RetryFailedStatusCheckForAMergeRequest retries the specified failed external status check. // Deprecated: to be removed in 1.0; use RetryFailedExternalStatusCheckForProjectMergeRequest instead - RetryFailedStatusCheckForAMergeRequest(pid any, mergeRequest int, externalStatusCheck int, options ...RequestOptionFunc) (*Response, error) - // Deprecated: to be removed in 1.0; use SetProjectMergeRequestExternalStatusCheckStatus instead - SetExternalStatusCheckStatus(pid any, mergeRequest int, opt *SetExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#retry-failed-status-check-for-a-merge-request + RetryFailedStatusCheckForAMergeRequest(pid any, mergeRequest int64, externalStatusCheck int64, options ...RequestOptionFunc) (*Response, error) - ListProjectMergeRequestExternalStatusChecks(pid any, mr int, opt *ListProjectMergeRequestExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) + // SetExternalStatusCheckStatus sets the status of an external status check. + // Deprecated: to be removed in 1.0; use SetProjectMergeRequestExternalStatusCheckStatus instead + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check + SetExternalStatusCheckStatus(pid any, mergeRequest int64, opt *SetExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) + + // ListProjectMergeRequestExternalStatusChecks lists the external status checks that apply to it + // and their status for a single merge request. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#list-status-checks-for-a-merge-request + ListProjectMergeRequestExternalStatusChecks(pid any, mr int64, opt *ListProjectMergeRequestExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) + + // ListProjectExternalStatusChecks lists the project external status checks. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#get-project-external-status-check-services ListProjectExternalStatusChecks(pid any, opt *ListProjectExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*ProjectStatusCheck, *Response, error) - RetryFailedExternalStatusCheckForProjectMergeRequest(pid any, mergeRequest int, externalStatusCheck int, opt *RetryFailedExternalStatusCheckForProjectMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) + + // RetryFailedExternalStatusCheckForProjectMergeRequest retries the specified failed external status check. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#retry-failed-status-check-for-a-merge-request + RetryFailedExternalStatusCheckForProjectMergeRequest(pid any, mergeRequest int64, externalStatusCheck int64, opt *RetryFailedExternalStatusCheckForProjectMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) + + // CreateProjectExternalStatusCheck creates an external status check. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#create-external-status-check-service CreateProjectExternalStatusCheck(pid any, opt *CreateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) - UpdateProjectExternalStatusCheck(pid any, check int, opt *UpdateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) - DeleteProjectExternalStatusCheck(pid any, check int, opt *DeleteProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) - SetProjectMergeRequestExternalStatusCheckStatus(pid any, mergeRequest int, opt *SetProjectMergeRequestExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) + + // UpdateProjectExternalStatusCheck updates an external status check. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service + UpdateProjectExternalStatusCheck(pid any, check int64, opt *UpdateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) + + // DeleteProjectExternalStatusCheck deletes an external status check. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#delete-external-status-check-service + DeleteProjectExternalStatusCheck(pid any, check int64, opt *DeleteProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) + + // SetProjectMergeRequestExternalStatusCheckStatus sets the status of an external status check. + // + // GitLab API docs: + // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check + SetProjectMergeRequestExternalStatusCheckStatus(pid any, mergeRequest int64, opt *SetProjectMergeRequestExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) } // ExternalStatusChecksService handles communication with the external @@ -45,24 +114,24 @@ type ( var _ ExternalStatusChecksServiceInterface = (*ExternalStatusChecksService)(nil) type MergeStatusCheck struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` ExternalURL string `json:"external_url"` Status string `json:"status"` } type ProjectStatusCheck struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` ExternalURL string `json:"external_url"` HMAC bool `json:"hmac"` ProtectedBranches []StatusCheckProtectedBranch `json:"protected_branches"` } type StatusCheckProtectedBranch struct { - ID int `json:"id"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` Name string `json:"name"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` @@ -75,25 +144,12 @@ type StatusCheckProtectedBranch struct { // // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#list-status-checks-for-a-merge-request -func (s *ExternalStatusChecksService) ListMergeStatusChecks(pid any, mr int, opt *ListOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_checks", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mscs []*MergeStatusCheck - resp, err := s.client.Do(req, &mscs) - if err != nil { - return nil, resp, err - } - - return mscs, resp, nil +func (s *ExternalStatusChecksService) ListMergeStatusChecks(pid any, mr int64, opt *ListOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) { + return do[[]*MergeStatusCheck](s.client, + withPath("projects/%s/merge_requests/%d/status_checks", ProjectID{pid}, mr), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SetExternalStatusCheckStatusOptions represents the available @@ -104,7 +160,7 @@ func (s *ExternalStatusChecksService) ListMergeStatusChecks(pid any, mr int, opt // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check type SetExternalStatusCheckStatusOptions struct { SHA *string `url:"sha,omitempty" json:"sha,omitempty"` - ExternalStatusCheckID *int `url:"external_status_check_id,omitempty" json:"external_status_check_id,omitempty"` + ExternalStatusCheckID *int64 `url:"external_status_check_id,omitempty" json:"external_status_check_id,omitempty"` Status *string `url:"status,omitempty" json:"status,omitempty"` } @@ -113,45 +169,22 @@ type SetExternalStatusCheckStatusOptions struct { // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check -func (s *ExternalStatusChecksService) SetExternalStatusCheckStatus(pid any, mergeRequest int, opt *SetExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_check_responses", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) SetExternalStatusCheckStatus(pid any, mergeRequest int64, opt *SetExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/status_check_responses", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// ListProjectStatusChecks lists the project external status checks. -// Deprecated: to be removed in 1.0; use ListProjectExternalStatusChecks instead -// -// GitLab API docs: -// https://docs.gitlab.com/api/status_checks/#get-project-external-status-check-services func (s *ExternalStatusChecksService) ListProjectStatusChecks(pid any, opt *ListOptions, options ...RequestOptionFunc) ([]*ProjectStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pscs []*ProjectStatusCheck - resp, err := s.client.Do(req, &pscs) - if err != nil { - return nil, resp, err - } - - return pscs, resp, nil + return do[[]*ProjectStatusCheck](s.client, + withPath("projects/%s/external_status_checks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateExternalStatusCheckOptions represents the available @@ -161,29 +194,19 @@ func (s *ExternalStatusChecksService) ListProjectStatusChecks(pid any, opt *List // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#create-external-status-check-service type CreateExternalStatusCheckOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` } -// CreateExternalStatusCheck creates an external status check. -// Deprecated: to be removed in 1.0; use CreateProjectExternalStatusCheck instead -// -// Gitlab API docs: -// https://docs.gitlab.com/api/status_checks/#create-external-status-check-service func (s *ExternalStatusChecksService) CreateExternalStatusCheck(pid any, opt *CreateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/external_status_checks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // DeleteExternalStatusCheck deletes an external status check. @@ -191,19 +214,13 @@ func (s *ExternalStatusChecksService) CreateExternalStatusCheck(pid any, opt *Cr // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#delete-external-status-check-service -func (s *ExternalStatusChecksService) DeleteExternalStatusCheck(pid any, check int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks/%d", PathEscape(project), check) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) DeleteExternalStatusCheck(pid any, check int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/external_status_checks/%d", ProjectID{pid}, check), + withRequestOpts(options...), + ) + return resp, err } // UpdateExternalStatusCheckOptions represents the available @@ -213,9 +230,9 @@ func (s *ExternalStatusChecksService) DeleteExternalStatusCheck(pid any, check i // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service type UpdateExternalStatusCheckOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` } // UpdateExternalStatusCheck updates an external status check. @@ -223,19 +240,14 @@ type UpdateExternalStatusCheckOptions struct { // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service -func (s *ExternalStatusChecksService) UpdateExternalStatusCheck(pid any, check int, opt *UpdateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks/%d", PathEscape(project), check) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) UpdateExternalStatusCheck(pid any, check int64, opt *UpdateExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/external_status_checks/%d", ProjectID{pid}, check), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // RetryFailedStatusCheckForAMergeRequest retries the specified failed external status check. @@ -243,19 +255,13 @@ func (s *ExternalStatusChecksService) UpdateExternalStatusCheck(pid any, check i // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#retry-failed-status-check-for-a-merge-request -func (s *ExternalStatusChecksService) RetryFailedStatusCheckForAMergeRequest(pid any, mergeRequest int, externalStatusCheck int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_checks/%d/retry", PathEscape(project), mergeRequest, externalStatusCheck) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) RetryFailedStatusCheckForAMergeRequest(pid any, mergeRequest int64, externalStatusCheck int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/status_checks/%d/retry", ProjectID{pid}, mergeRequest, externalStatusCheck), + withRequestOpts(options...), + ) + return resp, err } // ListProjectMergeRequestExternalStatusChecksOptions represents the available @@ -272,25 +278,12 @@ type ListProjectMergeRequestExternalStatusChecksOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#list-status-checks-for-a-merge-request -func (s *ExternalStatusChecksService) ListProjectMergeRequestExternalStatusChecks(pid any, mr int, opt *ListProjectMergeRequestExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_checks", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mscs []*MergeStatusCheck - resp, err := s.client.Do(req, &mscs) - if err != nil { - return nil, resp, err - } - - return mscs, resp, nil +func (s *ExternalStatusChecksService) ListProjectMergeRequestExternalStatusChecks(pid any, mr int64, opt *ListProjectMergeRequestExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*MergeStatusCheck, *Response, error) { + return do[[]*MergeStatusCheck](s.client, + withPath("projects/%s/merge_requests/%d/status_checks", ProjectID{pid}, mr), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListProjectExternalStatusChecksOptions represents the available @@ -302,29 +295,12 @@ type ListProjectExternalStatusChecksOptions struct { ListOptions } -// ListProjectExternalStatusChecks lists the project external status checks. -// -// GitLab API docs: -// https://docs.gitlab.com/api/status_checks/#get-project-external-status-check-services func (s *ExternalStatusChecksService) ListProjectExternalStatusChecks(pid any, opt *ListProjectExternalStatusChecksOptions, options ...RequestOptionFunc) ([]*ProjectStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pscs []*ProjectStatusCheck - resp, err := s.client.Do(req, &pscs) - if err != nil { - return nil, resp, err - } - - return pscs, resp, nil + return do[[]*ProjectStatusCheck](s.client, + withPath("projects/%s/external_status_checks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateProjectExternalStatusCheckOptions represents the available @@ -333,35 +309,19 @@ func (s *ExternalStatusChecksService) ListProjectExternalStatusChecks(pid any, o // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#create-external-status-check-service type CreateProjectExternalStatusCheckOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` - SharedSecret *string `url:"shared_secret,omitempty" json:"shared_secret,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` + SharedSecret *string `url:"shared_secret,omitempty" json:"shared_secret,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` } -// CreateProjectExternalStatusCheck creates an external status check. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/status_checks/#create-external-status-check-service func (s *ExternalStatusChecksService) CreateProjectExternalStatusCheck(pid any, opt *CreateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - statusCheck := new(ProjectStatusCheck) - resp, err := s.client.Do(req, statusCheck) - if err != nil { - return nil, resp, err - } - - return statusCheck, resp, nil + return do[*ProjectStatusCheck](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/external_status_checks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteProjectExternalStatusCheckOptions represents the available @@ -375,19 +335,14 @@ type DeleteProjectExternalStatusCheckOptions struct{} // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#delete-external-status-check-service -func (s *ExternalStatusChecksService) DeleteProjectExternalStatusCheck(pid any, check int, opt *DeleteProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks/%d", PathEscape(project), check) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) DeleteProjectExternalStatusCheck(pid any, check int64, opt *DeleteProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/external_status_checks/%d", ProjectID{pid}, check), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // UpdateProjectExternalStatusCheckOptions represents the available @@ -396,35 +351,23 @@ func (s *ExternalStatusChecksService) DeleteProjectExternalStatusCheck(pid any, // GitLab API docs: // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service type UpdateProjectExternalStatusCheckOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` - SharedSecret *string `url:"shared_secret,omitempty" json:"shared_secret,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"` + SharedSecret *string `url:"shared_secret,omitempty" json:"shared_secret,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` } // UpdateProjectExternalStatusCheck updates an external status check. // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#update-external-status-check-service -func (s *ExternalStatusChecksService) UpdateProjectExternalStatusCheck(pid any, check int, opt *UpdateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/external_status_checks/%d", PathEscape(project), check) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - statusCheck := new(ProjectStatusCheck) - resp, err := s.client.Do(req, statusCheck) - if err != nil { - return nil, resp, err - } - - return statusCheck, resp, nil +func (s *ExternalStatusChecksService) UpdateProjectExternalStatusCheck(pid any, check int64, opt *UpdateProjectExternalStatusCheckOptions, options ...RequestOptionFunc) (*ProjectStatusCheck, *Response, error) { + return do[*ProjectStatusCheck](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/external_status_checks/%d", ProjectID{pid}, check), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RetryFailedExternalStatusCheckForProjectMergeRequestOptions represents the available @@ -438,19 +381,14 @@ type RetryFailedExternalStatusCheckForProjectMergeRequestOptions struct{} // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#retry-failed-status-check-for-a-merge-request -func (s *ExternalStatusChecksService) RetryFailedExternalStatusCheckForProjectMergeRequest(pid any, mergeRequest int, externalStatusCheck int, opt *RetryFailedExternalStatusCheckForProjectMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_checks/%d/retry", PathEscape(project), mergeRequest, externalStatusCheck) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) RetryFailedExternalStatusCheckForProjectMergeRequest(pid any, mergeRequest int64, externalStatusCheck int64, opt *RetryFailedExternalStatusCheckForProjectMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/status_checks/%d/retry", ProjectID{pid}, mergeRequest, externalStatusCheck), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // SetProjectMergeRequestExternalStatusCheckStatusOptions represents the available @@ -460,7 +398,7 @@ func (s *ExternalStatusChecksService) RetryFailedExternalStatusCheckForProjectMe // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check type SetProjectMergeRequestExternalStatusCheckStatusOptions struct { SHA *string `url:"sha,omitempty" json:"sha,omitempty"` - ExternalStatusCheckID *int `url:"external_status_check_id,omitempty" json:"external_status_check_id,omitempty"` + ExternalStatusCheckID *int64 `url:"external_status_check_id,omitempty" json:"external_status_check_id,omitempty"` Status *string `url:"status,omitempty" json:"status,omitempty"` } @@ -468,17 +406,12 @@ type SetProjectMergeRequestExternalStatusCheckStatusOptions struct { // // Gitlab API docs: // https://docs.gitlab.com/api/status_checks/#set-status-of-an-external-status-check -func (s *ExternalStatusChecksService) SetProjectMergeRequestExternalStatusCheckStatus(pid any, mergeRequest int, opt *SetProjectMergeRequestExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/status_check_responses", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ExternalStatusChecksService) SetProjectMergeRequestExternalStatusCheckStatus(pid any, mergeRequest int64, opt *SetProjectMergeRequestExternalStatusCheckStatusOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/status_check_responses", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/feature_flag_user_lists.go b/vendor/gitlab.com/gitlab-org/api/client-go/feature_flag_user_lists.go index 6208158c6..e0445460f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/feature_flag_user_lists.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/feature_flag_user_lists.go @@ -15,7 +15,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -24,9 +23,9 @@ type ( FeatureFlagUserListsServiceInterface interface { ListFeatureFlagUserLists(pid any, opt *ListFeatureFlagUserListsOptions, options ...RequestOptionFunc) ([]*FeatureFlagUserList, *Response, error) CreateFeatureFlagUserList(pid any, opt *CreateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) - GetFeatureFlagUserList(pid any, iid int, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) - UpdateFeatureFlagUserList(pid any, iid int, opt *UpdateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) - DeleteFeatureFlagUserList(pid any, iid int, options ...RequestOptionFunc) (*Response, error) + GetFeatureFlagUserList(pid any, iid int64, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) + UpdateFeatureFlagUserList(pid any, iid int64, opt *UpdateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) + DeleteFeatureFlagUserList(pid any, iid int64, options ...RequestOptionFunc) (*Response, error) } // FeatureFlagUserListsService handles communication with the feature flag @@ -46,9 +45,9 @@ var _ FeatureFlagUserListsServiceInterface = (*FeatureFlagUserListsService)(nil) type FeatureFlagUserList struct { Name string `url:"name" json:"name"` UserXIDs string `url:"user_xids" json:"user_xids"` - ID int `url:"id" json:"id"` - IID int `url:"iid" json:"iid"` - ProjectID int `url:"project_id" json:"project_id"` + ID int64 `url:"id" json:"id"` + IID int64 `url:"iid" json:"iid"` + ProjectID int64 `url:"project_id" json:"project_id"` CreatedAt *time.Time `url:"created_at" json:"created_at"` UpdatedAt *time.Time `url:"updated_at" json:"updated_at"` } @@ -69,24 +68,11 @@ type ListFeatureFlagUserListsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/feature_flag_user_lists/#list-all-feature-flag-user-lists-for-a-project func (s *FeatureFlagUserListsService) ListFeatureFlagUserLists(pid any, opt *ListFeatureFlagUserListsOptions, options ...RequestOptionFunc) ([]*FeatureFlagUserList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags_user_lists", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var lists []*FeatureFlagUserList - resp, err := s.client.Do(req, &lists) - if err != nil { - return nil, resp, err - } - - return lists, resp, nil + return do[[]*FeatureFlagUserList](s.client, + withPath("projects/%s/feature_flags_user_lists", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateFeatureFlagUserListOptions represents the available @@ -104,49 +90,23 @@ type CreateFeatureFlagUserListOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/feature_flag_user_lists/#create-a-feature-flag-user-list func (s *FeatureFlagUserListsService) CreateFeatureFlagUserList(pid any, opt *CreateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags_user_lists", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - list := new(FeatureFlagUserList) - resp, err := s.client.Do(req, list) - if err != nil { - return nil, resp, err - } - - return list, resp, nil + return do[*FeatureFlagUserList](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/feature_flags_user_lists", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetFeatureFlagUserList gets a feature flag user list. // // GitLab API docs: // https://docs.gitlab.com/api/feature_flag_user_lists/#get-a-feature-flag-user-list -func (s *FeatureFlagUserListsService) GetFeatureFlagUserList(pid any, iid int, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags_user_lists/%d", PathEscape(project), iid) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - list := new(FeatureFlagUserList) - resp, err := s.client.Do(req, list) - if err != nil { - return nil, resp, err - } - - return list, resp, nil +func (s *FeatureFlagUserListsService) GetFeatureFlagUserList(pid any, iid int64, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) { + return do[*FeatureFlagUserList](s.client, + withPath("projects/%s/feature_flags_user_lists/%d", ProjectID{pid}, iid), + withRequestOpts(options...), + ) } // UpdateFeatureFlagUserListOptions represents the available @@ -163,42 +123,24 @@ type UpdateFeatureFlagUserListOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/feature_flag_user_lists/#update-a-feature-flag-user-list -func (s *FeatureFlagUserListsService) UpdateFeatureFlagUserList(pid any, iid int, opt *UpdateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags_user_lists/%d", PathEscape(project), iid) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - list := new(FeatureFlagUserList) - resp, err := s.client.Do(req, list) - if err != nil { - return nil, resp, err - } - - return list, resp, nil +func (s *FeatureFlagUserListsService) UpdateFeatureFlagUserList(pid any, iid int64, opt *UpdateFeatureFlagUserListOptions, options ...RequestOptionFunc) (*FeatureFlagUserList, *Response, error) { + return do[*FeatureFlagUserList](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/feature_flags_user_lists/%d", ProjectID{pid}, iid), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteFeatureFlagUserList deletes a feature flag user list. // // GitLab API docs: // https://docs.gitlab.com/api/feature_flag_user_lists/#delete-feature-flag-user-list -func (s *FeatureFlagUserListsService) DeleteFeatureFlagUserList(pid any, iid int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags_user_lists/%d", PathEscape(project), iid) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *FeatureFlagUserListsService) DeleteFeatureFlagUserList(pid any, iid int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/feature_flags_user_lists/%d", ProjectID{pid}, iid), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/feature_flags.go b/vendor/gitlab.com/gitlab-org/api/client-go/feature_flags.go index d0a5d84d7..9fa0d30a9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/feature_flags.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/feature_flags.go @@ -16,11 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" - "net/url" -) +import "net/http" type ( // FeaturesServiceInterface defines all the API methods for the FeaturesService @@ -69,17 +65,10 @@ func (f Feature) String() string { // GitLab API docs: // https://docs.gitlab.com/api/features/#list-all-features func (s *FeaturesService) ListFeatures(options ...RequestOptionFunc) ([]*Feature, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "features", nil, options) - if err != nil { - return nil, nil, err - } - - var f []*Feature - resp, err := s.client.Do(req, &f) - if err != nil { - return nil, resp, err - } - return f, resp, nil + return do[[]*Feature](s.client, + withPath("features"), + withRequestOpts(options...), + ) } // FeatureDefinition represents a Feature Definition. @@ -106,17 +95,10 @@ func (fd FeatureDefinition) String() string { // GitLab API docs: // https://docs.gitlab.com/api/features/#list-all-feature-definitions func (s *FeaturesService) ListFeatureDefinitions(options ...RequestOptionFunc) ([]*FeatureDefinition, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "features/definitions", nil, options) - if err != nil { - return nil, nil, err - } - - var fd []*FeatureDefinition - resp, err := s.client.Do(req, &fd) - if err != nil { - return nil, resp, err - } - return fd, resp, nil + return do[[]*FeatureDefinition](s.client, + withPath("features/definitions"), + withRequestOpts(options...), + ) } // SetFeatureFlagOptions represents the available options for @@ -141,19 +123,12 @@ type SetFeatureFlagOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/features/#set-or-create-a-feature func (s *FeaturesService) SetFeatureFlag(name string, opt *SetFeatureFlagOptions, options ...RequestOptionFunc) (*Feature, *Response, error) { - u := fmt.Sprintf("features/%s", url.PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - f := &Feature{} - resp, err := s.client.Do(req, f) - if err != nil { - return nil, resp, err - } - return f, resp, nil + return do[*Feature](s.client, + withMethod(http.MethodPost), + withPath("features/%s", name), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteFeatureFlag deletes a feature flag. @@ -161,12 +136,10 @@ func (s *FeaturesService) SetFeatureFlag(name string, opt *SetFeatureFlagOptions // GitLab API docs: // https://docs.gitlab.com/api/features/#delete-a-feature func (s *FeaturesService) DeleteFeatureFlag(name string, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("features/%s", url.PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("features/%s", name), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/freeze_periods.go b/vendor/gitlab.com/gitlab-org/api/client-go/freeze_periods.go index 8662ac4df..bb41500c7 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/freeze_periods.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/freeze_periods.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -30,10 +29,10 @@ type ( // FreezePeriodsServiceInterface defines all the API methods for the FreezePeriodsService FreezePeriodsServiceInterface interface { ListFreezePeriods(pid any, opt *ListFreezePeriodsOptions, options ...RequestOptionFunc) ([]*FreezePeriod, *Response, error) - GetFreezePeriod(pid any, freezePeriod int, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) + GetFreezePeriod(pid any, freezePeriod int64, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) CreateFreezePeriodOptions(pid any, opt *CreateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) - UpdateFreezePeriodOptions(pid any, freezePeriod int, opt *UpdateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) - DeleteFreezePeriod(pid any, freezePeriod int, options ...RequestOptionFunc) (*Response, error) + UpdateFreezePeriodOptions(pid any, freezePeriod int64, opt *UpdateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) + DeleteFreezePeriod(pid any, freezePeriod int64, options ...RequestOptionFunc) (*Response, error) } // FreezePeriodsService handles the communication with the freeze periods @@ -52,7 +51,7 @@ var _ FreezePeriodsServiceInterface = (*FreezePeriodsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#list-freeze-periods type FreezePeriod struct { - ID int `json:"id"` + ID int64 `json:"id"` FreezeStart string `json:"freeze_start"` FreezeEnd string `json:"freeze_end"` CronTimezone string `json:"cron_timezone"` @@ -65,56 +64,31 @@ type FreezePeriod struct { // // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#list-freeze-periods -type ListFreezePeriodsOptions ListOptions +type ListFreezePeriodsOptions struct { + ListOptions +} // ListFreezePeriods gets a list of project freeze periods. // // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#list-freeze-periods func (s *FreezePeriodsService) ListFreezePeriods(pid any, opt *ListFreezePeriodsOptions, options ...RequestOptionFunc) ([]*FreezePeriod, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/freeze_periods", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var fp []*FreezePeriod - resp, err := s.client.Do(req, &fp) - if err != nil { - return nil, resp, err - } - - return fp, resp, nil + return do[[]*FreezePeriod](s.client, + withPath("projects/%s/freeze_periods", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetFreezePeriod gets a specific freeze period for a project. // // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#get-a-freeze-period-by-a-freeze_period_id -func (s *FreezePeriodsService) GetFreezePeriod(pid any, freezePeriod int, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/freeze_periods/%d", PathEscape(project), freezePeriod) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - fp := new(FreezePeriod) - resp, err := s.client.Do(req, fp) - if err != nil { - return nil, resp, err - } - - return fp, resp, nil +func (s *FreezePeriodsService) GetFreezePeriod(pid any, freezePeriod int64, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) { + return do[*FreezePeriod](s.client, + withPath("projects/%s/freeze_periods/%d", ProjectID{pid}, freezePeriod), + withRequestOpts(options...), + ) } // CreateFreezePeriodOptions represents the available CreateFreezePeriodOptions() @@ -133,24 +107,12 @@ type CreateFreezePeriodOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#create-a-freeze-period func (s *FreezePeriodsService) CreateFreezePeriodOptions(pid any, opt *CreateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/freeze_periods", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - fp := new(FreezePeriod) - resp, err := s.client.Do(req, fp) - if err != nil { - return nil, resp, err - } - - return fp, resp, nil + return do[*FreezePeriod](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/freeze_periods", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateFreezePeriodOptions represents the available UpdateFreezePeriodOptions() @@ -168,25 +130,13 @@ type UpdateFreezePeriodOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#update-a-freeze-period -func (s *FreezePeriodsService) UpdateFreezePeriodOptions(pid any, freezePeriod int, opt *UpdateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/freeze_periods/%d", PathEscape(project), freezePeriod) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - fp := new(FreezePeriod) - resp, err := s.client.Do(req, fp) - if err != nil { - return nil, resp, err - } - - return fp, resp, nil +func (s *FreezePeriodsService) UpdateFreezePeriodOptions(pid any, freezePeriod int64, opt *UpdateFreezePeriodOptions, options ...RequestOptionFunc) (*FreezePeriod, *Response, error) { + return do[*FreezePeriod](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/freeze_periods/%d", ProjectID{pid}, freezePeriod), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteFreezePeriod removes a freeze period from a project. This is an @@ -195,17 +145,11 @@ func (s *FreezePeriodsService) UpdateFreezePeriodOptions(pid any, freezePeriod i // // GitLab API docs: // https://docs.gitlab.com/api/freeze_periods/#delete-a-freeze-period -func (s *FreezePeriodsService) DeleteFreezePeriod(pid any, freezePeriod int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/freeze_periods/%d", PathEscape(project), freezePeriod) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *FreezePeriodsService) DeleteFreezePeriod(pid any, freezePeriod int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/freeze_periods/%d", ProjectID{pid}, freezePeriod), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/generic_packages.go b/vendor/gitlab.com/gitlab-org/api/client-go/generic_packages.go index e80fb5bbd..e9771e57b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/generic_packages.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/generic_packages.go @@ -49,27 +49,33 @@ var _ GenericPackagesServiceInterface = (*GenericPackagesService)(nil) // GitLab API docs: // https://docs.gitlab.com/user/packages/generic_packages/#publish-a-single-file type GenericPackagesFile struct { - ID int `json:"id"` - PackageID int `json:"package_id"` - CreatedAt *time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at"` - Size int `json:"size"` - FileStore int `json:"file_store"` - FileMD5 string `json:"file_md5"` - FileSHA1 string `json:"file_sha1"` - FileName string `json:"file_name"` - File struct { - URL string `json:"url"` - } `json:"file"` - FileSHA256 string `json:"file_sha256"` - VerificationRetryAt *time.Time `json:"verification_retry_at"` - VerifiedAt *time.Time `json:"verified_at"` - VerificationFailure bool `json:"verification_failure"` - VerificationRetryCount int `json:"verification_retry_count"` - VerificationChecksum string `json:"verification_checksum"` - VerificationState int `json:"verification_state"` - VerificationStartedAt *time.Time `json:"verification_started_at"` - NewFilePath string `json:"new_file_path"` + ID int64 `json:"id"` + PackageID int64 `json:"package_id"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Size int64 `json:"size"` + FileStore int64 `json:"file_store"` + FileMD5 string `json:"file_md5"` + FileSHA1 string `json:"file_sha1"` + FileName string `json:"file_name"` + File GenericPackagesFileURL `json:"file"` + FileSHA256 string `json:"file_sha256"` + VerificationRetryAt *time.Time `json:"verification_retry_at"` + VerifiedAt *time.Time `json:"verified_at"` + VerificationFailure bool `json:"verification_failure"` + VerificationRetryCount int64 `json:"verification_retry_count"` + VerificationChecksum string `json:"verification_checksum"` + VerificationState int64 `json:"verification_state"` + VerificationStartedAt *time.Time `json:"verification_started_at"` + NewFilePath string `json:"new_file_path"` +} + +// GenericPackagesFileURL represents a GitLab generic package file URL. +// +// GitLab API docs: +// https://docs.gitlab.com/user/packages/generic_packages/#publish-a-single-file +type GenericPackagesFileURL struct { + URL string `json:"url"` } // FormatPackageURL returns the GitLab Package Registry URL for the given artifact metadata, without the BaseURL. @@ -142,28 +148,12 @@ func (s *GenericPackagesService) PublishPackageFile(pid any, packageName, packag // GitLab docs: // https://docs.gitlab.com/user/packages/generic_packages/#download-a-single-file func (s *GenericPackagesService) DownloadPackageFile(pid any, packageName, packageVersion, fileName string, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/packages/generic/%s/%s/%s", - PathEscape(project), - PathEscape(packageName), - PathEscape(packageVersion), - PathEscape(fileName), + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/packages/generic/%s/%s/%s", ProjectID{pid}, packageName, packageVersion, fileName), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var f bytes.Buffer - resp, err := s.client.Do(req, &f) if err != nil { return nil, resp, err } - - return f.Bytes(), resp, err + return buf.Bytes(), resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/geo_nodes.go b/vendor/gitlab.com/gitlab-org/api/client-go/geo_nodes.go index 124cc8312..670343a1a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/geo_nodes.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/geo_nodes.go @@ -16,10 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( // Deprecated: will be removed in v5 of the API, use Geo Sites API instead @@ -29,17 +26,17 @@ type ( // Deprecated: will be removed in v5 of the API, use Geo Sites API instead ListGeoNodes(*ListGeoNodesOptions, ...RequestOptionFunc) ([]*GeoNode, *Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead - GetGeoNode(int, ...RequestOptionFunc) (*GeoNode, *Response, error) + GetGeoNode(int64, ...RequestOptionFunc) (*GeoNode, *Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead - EditGeoNode(int, *UpdateGeoNodesOptions, ...RequestOptionFunc) (*GeoNode, *Response, error) + EditGeoNode(int64, *UpdateGeoNodesOptions, ...RequestOptionFunc) (*GeoNode, *Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead - DeleteGeoNode(int, ...RequestOptionFunc) (*Response, error) + DeleteGeoNode(int64, ...RequestOptionFunc) (*Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead - RepairGeoNode(int, ...RequestOptionFunc) (*GeoNode, *Response, error) + RepairGeoNode(int64, ...RequestOptionFunc) (*GeoNode, *Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead RetrieveStatusOfAllGeoNodes(...RequestOptionFunc) ([]*GeoNodeStatus, *Response, error) // Deprecated: will be removed in v5 of the API, use Geo Sites API instead - RetrieveStatusOfGeoNode(int, ...RequestOptionFunc) (*GeoNodeStatus, *Response, error) + RetrieveStatusOfGeoNode(int64, ...RequestOptionFunc) (*GeoNodeStatus, *Response, error) } // GeoNodesService handles communication with Geo Nodes related methods @@ -60,21 +57,21 @@ var _ GeoNodesServiceInterface = (*GeoNodesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/geo_nodes/ type GeoNode struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` URL string `json:"url"` InternalURL string `json:"internal_url"` Primary bool `json:"primary"` Enabled bool `json:"enabled"` Current bool `json:"current"` - FilesMaxCapacity int `json:"files_max_capacity"` - ReposMaxCapacity int `json:"repos_max_capacity"` - VerificationMaxCapacity int `json:"verification_max_capacity"` + FilesMaxCapacity int64 `json:"files_max_capacity"` + ReposMaxCapacity int64 `json:"repos_max_capacity"` + VerificationMaxCapacity int64 `json:"verification_max_capacity"` SelectiveSyncType string `json:"selective_sync_type"` SelectiveSyncShards []string `json:"selective_sync_shards"` - SelectiveSyncNamespaceIds []int `json:"selective_sync_namespace_ids"` - MinimumReverificationInterval int `json:"minimum_reverification_interval"` - ContainerRepositoriesMaxCapacity int `json:"container_repositories_max_capacity"` + SelectiveSyncNamespaceIDs []int64 `json:"selective_sync_namespace_ids"` + MinimumReverificationInterval int64 `json:"minimum_reverification_interval"` + ContainerRepositoriesMaxCapacity int64 `json:"container_repositories_max_capacity"` SyncObjectStorage bool `json:"sync_object_storage"` CloneProtocol string `json:"clone_protocol"` WebEditURL string `json:"web_edit_url"` @@ -103,15 +100,15 @@ type CreateGeoNodesOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` InternalURL *string `url:"internal_url,omitempty" json:"internal_url,omitempty"` - FilesMaxCapacity *int `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` - ReposMaxCapacity *int `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` - VerificationMaxCapacity *int `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` - ContainerRepositoriesMaxCapacity *int `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` + FilesMaxCapacity *int64 `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` + ReposMaxCapacity *int64 `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` + VerificationMaxCapacity *int64 `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` + ContainerRepositoriesMaxCapacity *int64 `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` SyncObjectStorage *bool `url:"sync_object_storage,omitempty" json:"sync_object_storage,omitempty"` SelectiveSyncType *string `url:"selective_sync_type,omitempty" json:"selective_sync_type,omitempty"` SelectiveSyncShards *[]string `url:"selective_sync_shards,omitempty" json:"selective_sync_shards,omitempty"` - SelectiveSyncNamespaceIds *[]int `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` - MinimumReverificationInterval *int `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` + SelectiveSyncNamespaceIDs *[]int64 `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` + MinimumReverificationInterval *int64 `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` } // CreateGeoNode creates a new Geo Node. @@ -120,18 +117,12 @@ type CreateGeoNodesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#create-a-new-geo-node func (s *GeoNodesService) CreateGeoNode(opt *CreateGeoNodesOptions, options ...RequestOptionFunc) (*GeoNode, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "geo_nodes", opt, options) - if err != nil { - return nil, nil, err - } - - g := new(GeoNode) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*GeoNode](s.client, + withMethod(http.MethodPost), + withPath("geo_nodes"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListGeoNodesOptions represents the available ListGeoNodes() options. @@ -139,7 +130,9 @@ func (s *GeoNodesService) CreateGeoNode(opt *CreateGeoNodesOptions, options ...R // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-configuration-about-all-geo-nodes -type ListGeoNodesOptions ListOptions +type ListGeoNodesOptions struct { + ListOptions +} // ListGeoNodes gets a list of geo nodes. // Deprecated: will be removed in v5 of the API, use Geo Sites API instead @@ -147,18 +140,11 @@ type ListGeoNodesOptions ListOptions // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-configuration-about-all-geo-nodes func (s *GeoNodesService) ListGeoNodes(opt *ListGeoNodesOptions, options ...RequestOptionFunc) ([]*GeoNode, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "geo_nodes", opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*GeoNode - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*GeoNode](s.client, + withPath("geo_nodes"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGeoNode gets a specific geo node. @@ -166,21 +152,11 @@ func (s *GeoNodesService) ListGeoNodes(opt *ListGeoNodesOptions, options ...Requ // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-configuration-about-a-specific-geo-node -func (s *GeoNodesService) GetGeoNode(id int, options ...RequestOptionFunc) (*GeoNode, *Response, error) { - u := fmt.Sprintf("geo_nodes/%d", id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(GeoNode) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil +func (s *GeoNodesService) GetGeoNode(id int64, options ...RequestOptionFunc) (*GeoNode, *Response, error) { + return do[*GeoNode](s.client, + withPath("geo_nodes/%d", id), + withRequestOpts(options...), + ) } // UpdateGeoNodesOptions represents the available EditGeoNode() options. @@ -189,20 +165,20 @@ func (s *GeoNodesService) GetGeoNode(id int, options ...RequestOptionFunc) (*Geo // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#edit-a-geo-node type UpdateGeoNodesOptions struct { - ID *int `url:"primary,omitempty" json:"primary,omitempty"` + ID *int64 `url:"primary,omitempty" json:"primary,omitempty"` Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` InternalURL *string `url:"internal_url,omitempty" json:"internal_url,omitempty"` - FilesMaxCapacity *int `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` - ReposMaxCapacity *int `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` - VerificationMaxCapacity *int `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` - ContainerRepositoriesMaxCapacity *int `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` + FilesMaxCapacity *int64 `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` + ReposMaxCapacity *int64 `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` + VerificationMaxCapacity *int64 `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` + ContainerRepositoriesMaxCapacity *int64 `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` SyncObjectStorage *bool `url:"sync_object_storage,omitempty" json:"sync_object_storage,omitempty"` SelectiveSyncType *string `url:"selective_sync_type,omitempty" json:"selective_sync_type,omitempty"` SelectiveSyncShards *[]string `url:"selective_sync_shards,omitempty" json:"selective_sync_shards,omitempty"` - SelectiveSyncNamespaceIds *[]int `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` - MinimumReverificationInterval *int `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` + SelectiveSyncNamespaceIDs *[]int64 `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` + MinimumReverificationInterval *int64 `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` } // EditGeoNode updates settings of an existing Geo node. @@ -210,21 +186,13 @@ type UpdateGeoNodesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#edit-a-geo-node -func (s *GeoNodesService) EditGeoNode(id int, opt *UpdateGeoNodesOptions, options ...RequestOptionFunc) (*GeoNode, *Response, error) { - u := fmt.Sprintf("geo_nodes/%d", id) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - g := new(GeoNode) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil +func (s *GeoNodesService) EditGeoNode(id int64, opt *UpdateGeoNodesOptions, options ...RequestOptionFunc) (*GeoNode, *Response, error) { + return do[*GeoNode](s.client, + withMethod(http.MethodPut), + withPath("geo_nodes/%d", id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGeoNode removes the Geo node. @@ -232,15 +200,13 @@ func (s *GeoNodesService) EditGeoNode(id int, opt *UpdateGeoNodesOptions, option // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#delete-a-geo-node -func (s *GeoNodesService) DeleteGeoNode(id int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("geo_nodes/%d", id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GeoNodesService) DeleteGeoNode(id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("geo_nodes/%d", id), + withRequestOpts(options...), + ) + return resp, err } // RepairGeoNode to repair the OAuth authentication of a Geo node. @@ -248,21 +214,12 @@ func (s *GeoNodesService) DeleteGeoNode(id int, options ...RequestOptionFunc) (* // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#repair-a-geo-node -func (s *GeoNodesService) RepairGeoNode(id int, options ...RequestOptionFunc) (*GeoNode, *Response, error) { - u := fmt.Sprintf("geo_nodes/%d/repair", id) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(GeoNode) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil +func (s *GeoNodesService) RepairGeoNode(id int64, options ...RequestOptionFunc) (*GeoNode, *Response, error) { + return do[*GeoNode](s.client, + withMethod(http.MethodPost), + withPath("geo_nodes/%d/repair", id), + withRequestOpts(options...), + ) } // GeoNodeStatus represents the status of Geo Node. @@ -271,162 +228,162 @@ func (s *GeoNodesService) RepairGeoNode(id int, options ...RequestOptionFunc) (* // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-status-about-all-geo-nodes type GeoNodeStatus struct { - GeoNodeID int `json:"geo_node_id"` + GeoNodeID int64 `json:"geo_node_id"` Healthy bool `json:"healthy"` Health string `json:"health"` HealthStatus string `json:"health_status"` MissingOauthApplication bool `json:"missing_oauth_application"` - AttachmentsCount int `json:"attachments_count"` - AttachmentsSyncedCount int `json:"attachments_synced_count"` - AttachmentsFailedCount int `json:"attachments_failed_count"` - AttachmentsSyncedMissingOnPrimaryCount int `json:"attachments_synced_missing_on_primary_count"` + AttachmentsCount int64 `json:"attachments_count"` + AttachmentsSyncedCount int64 `json:"attachments_synced_count"` + AttachmentsFailedCount int64 `json:"attachments_failed_count"` + AttachmentsSyncedMissingOnPrimaryCount int64 `json:"attachments_synced_missing_on_primary_count"` AttachmentsSyncedInPercentage string `json:"attachments_synced_in_percentage"` - DbReplicationLagSeconds int `json:"db_replication_lag_seconds"` - LfsObjectsCount int `json:"lfs_objects_count"` - LfsObjectsSyncedCount int `json:"lfs_objects_synced_count"` - LfsObjectsFailedCount int `json:"lfs_objects_failed_count"` - LfsObjectsSyncedMissingOnPrimaryCount int `json:"lfs_objects_synced_missing_on_primary_count"` + DbReplicationLagSeconds int64 `json:"db_replication_lag_seconds"` + LfsObjectsCount int64 `json:"lfs_objects_count"` + LfsObjectsSyncedCount int64 `json:"lfs_objects_synced_count"` + LfsObjectsFailedCount int64 `json:"lfs_objects_failed_count"` + LfsObjectsSyncedMissingOnPrimaryCount int64 `json:"lfs_objects_synced_missing_on_primary_count"` LfsObjectsSyncedInPercentage string `json:"lfs_objects_synced_in_percentage"` - JobArtifactsCount int `json:"job_artifacts_count"` - JobArtifactsSyncedCount int `json:"job_artifacts_synced_count"` - JobArtifactsFailedCount int `json:"job_artifacts_failed_count"` - JobArtifactsSyncedMissingOnPrimaryCount int `json:"job_artifacts_synced_missing_on_primary_count"` + JobArtifactsCount int64 `json:"job_artifacts_count"` + JobArtifactsSyncedCount int64 `json:"job_artifacts_synced_count"` + JobArtifactsFailedCount int64 `json:"job_artifacts_failed_count"` + JobArtifactsSyncedMissingOnPrimaryCount int64 `json:"job_artifacts_synced_missing_on_primary_count"` JobArtifactsSyncedInPercentage string `json:"job_artifacts_synced_in_percentage"` - ContainerRepositoriesCount int `json:"container_repositories_count"` - ContainerRepositoriesSyncedCount int `json:"container_repositories_synced_count"` - ContainerRepositoriesFailedCount int `json:"container_repositories_failed_count"` + ContainerRepositoriesCount int64 `json:"container_repositories_count"` + ContainerRepositoriesSyncedCount int64 `json:"container_repositories_synced_count"` + ContainerRepositoriesFailedCount int64 `json:"container_repositories_failed_count"` ContainerRepositoriesSyncedInPercentage string `json:"container_repositories_synced_in_percentage"` - DesignRepositoriesCount int `json:"design_repositories_count"` - DesignRepositoriesSyncedCount int `json:"design_repositories_synced_count"` - DesignRepositoriesFailedCount int `json:"design_repositories_failed_count"` + DesignRepositoriesCount int64 `json:"design_repositories_count"` + DesignRepositoriesSyncedCount int64 `json:"design_repositories_synced_count"` + DesignRepositoriesFailedCount int64 `json:"design_repositories_failed_count"` DesignRepositoriesSyncedInPercentage string `json:"design_repositories_synced_in_percentage"` - ProjectsCount int `json:"projects_count"` - RepositoriesCount int `json:"repositories_count"` - RepositoriesFailedCount int `json:"repositories_failed_count"` - RepositoriesSyncedCount int `json:"repositories_synced_count"` + ProjectsCount int64 `json:"projects_count"` + RepositoriesCount int64 `json:"repositories_count"` + RepositoriesFailedCount int64 `json:"repositories_failed_count"` + RepositoriesSyncedCount int64 `json:"repositories_synced_count"` RepositoriesSyncedInPercentage string `json:"repositories_synced_in_percentage"` - WikisCount int `json:"wikis_count"` - WikisFailedCount int `json:"wikis_failed_count"` - WikisSyncedCount int `json:"wikis_synced_count"` + WikisCount int64 `json:"wikis_count"` + WikisFailedCount int64 `json:"wikis_failed_count"` + WikisSyncedCount int64 `json:"wikis_synced_count"` WikisSyncedInPercentage string `json:"wikis_synced_in_percentage"` - ReplicationSlotsCount int `json:"replication_slots_count"` - ReplicationSlotsUsedCount int `json:"replication_slots_used_count"` + ReplicationSlotsCount int64 `json:"replication_slots_count"` + ReplicationSlotsUsedCount int64 `json:"replication_slots_used_count"` ReplicationSlotsUsedInPercentage string `json:"replication_slots_used_in_percentage"` - ReplicationSlotsMaxRetainedWalBytes int `json:"replication_slots_max_retained_wal_bytes"` - RepositoriesCheckedCount int `json:"repositories_checked_count"` - RepositoriesCheckedFailedCount int `json:"repositories_checked_failed_count"` + ReplicationSlotsMaxRetainedWalBytes int64 `json:"replication_slots_max_retained_wal_bytes"` + RepositoriesCheckedCount int64 `json:"repositories_checked_count"` + RepositoriesCheckedFailedCount int64 `json:"repositories_checked_failed_count"` RepositoriesCheckedInPercentage string `json:"repositories_checked_in_percentage"` - RepositoriesChecksummedCount int `json:"repositories_checksummed_count"` - RepositoriesChecksumFailedCount int `json:"repositories_checksum_failed_count"` + RepositoriesChecksummedCount int64 `json:"repositories_checksummed_count"` + RepositoriesChecksumFailedCount int64 `json:"repositories_checksum_failed_count"` RepositoriesChecksummedInPercentage string `json:"repositories_checksummed_in_percentage"` - WikisChecksummedCount int `json:"wikis_checksummed_count"` - WikisChecksumFailedCount int `json:"wikis_checksum_failed_count"` + WikisChecksummedCount int64 `json:"wikis_checksummed_count"` + WikisChecksumFailedCount int64 `json:"wikis_checksum_failed_count"` WikisChecksummedInPercentage string `json:"wikis_checksummed_in_percentage"` - RepositoriesVerifiedCount int `json:"repositories_verified_count"` - RepositoriesVerificationFailedCount int `json:"repositories_verification_failed_count"` + RepositoriesVerifiedCount int64 `json:"repositories_verified_count"` + RepositoriesVerificationFailedCount int64 `json:"repositories_verification_failed_count"` RepositoriesVerifiedInPercentage string `json:"repositories_verified_in_percentage"` - RepositoriesChecksumMismatchCount int `json:"repositories_checksum_mismatch_count"` - WikisVerifiedCount int `json:"wikis_verified_count"` - WikisVerificationFailedCount int `json:"wikis_verification_failed_count"` + RepositoriesChecksumMismatchCount int64 `json:"repositories_checksum_mismatch_count"` + WikisVerifiedCount int64 `json:"wikis_verified_count"` + WikisVerificationFailedCount int64 `json:"wikis_verification_failed_count"` WikisVerifiedInPercentage string `json:"wikis_verified_in_percentage"` - WikisChecksumMismatchCount int `json:"wikis_checksum_mismatch_count"` - RepositoriesRetryingVerificationCount int `json:"repositories_retrying_verification_count"` - WikisRetryingVerificationCount int `json:"wikis_retrying_verification_count"` - LastEventID int `json:"last_event_id"` - LastEventTimestamp int `json:"last_event_timestamp"` - CursorLastEventID int `json:"cursor_last_event_id"` - CursorLastEventTimestamp int `json:"cursor_last_event_timestamp"` - LastSuccessfulStatusCheckTimestamp int `json:"last_successful_status_check_timestamp"` + WikisChecksumMismatchCount int64 `json:"wikis_checksum_mismatch_count"` + RepositoriesRetryingVerificationCount int64 `json:"repositories_retrying_verification_count"` + WikisRetryingVerificationCount int64 `json:"wikis_retrying_verification_count"` + LastEventID int64 `json:"last_event_id"` + LastEventTimestamp int64 `json:"last_event_timestamp"` + CursorLastEventID int64 `json:"cursor_last_event_id"` + CursorLastEventTimestamp int64 `json:"cursor_last_event_timestamp"` + LastSuccessfulStatusCheckTimestamp int64 `json:"last_successful_status_check_timestamp"` Version string `json:"version"` Revision string `json:"revision"` - MergeRequestDiffsCount int `json:"merge_request_diffs_count"` - MergeRequestDiffsChecksumTotalCount int `json:"merge_request_diffs_checksum_total_count"` - MergeRequestDiffsChecksummedCount int `json:"merge_request_diffs_checksummed_count"` - MergeRequestDiffsChecksumFailedCount int `json:"merge_request_diffs_checksum_failed_count"` - MergeRequestDiffsSyncedCount int `json:"merge_request_diffs_synced_count"` - MergeRequestDiffsFailedCount int `json:"merge_request_diffs_failed_count"` - MergeRequestDiffsRegistryCount int `json:"merge_request_diffs_registry_count"` - MergeRequestDiffsVerificationTotalCount int `json:"merge_request_diffs_verification_total_count"` - MergeRequestDiffsVerifiedCount int `json:"merge_request_diffs_verified_count"` - MergeRequestDiffsVerificationFailedCount int `json:"merge_request_diffs_verification_failed_count"` + MergeRequestDiffsCount int64 `json:"merge_request_diffs_count"` + MergeRequestDiffsChecksumTotalCount int64 `json:"merge_request_diffs_checksum_total_count"` + MergeRequestDiffsChecksummedCount int64 `json:"merge_request_diffs_checksummed_count"` + MergeRequestDiffsChecksumFailedCount int64 `json:"merge_request_diffs_checksum_failed_count"` + MergeRequestDiffsSyncedCount int64 `json:"merge_request_diffs_synced_count"` + MergeRequestDiffsFailedCount int64 `json:"merge_request_diffs_failed_count"` + MergeRequestDiffsRegistryCount int64 `json:"merge_request_diffs_registry_count"` + MergeRequestDiffsVerificationTotalCount int64 `json:"merge_request_diffs_verification_total_count"` + MergeRequestDiffsVerifiedCount int64 `json:"merge_request_diffs_verified_count"` + MergeRequestDiffsVerificationFailedCount int64 `json:"merge_request_diffs_verification_failed_count"` MergeRequestDiffsSyncedInPercentage string `json:"merge_request_diffs_synced_in_percentage"` MergeRequestDiffsVerifiedInPercentage string `json:"merge_request_diffs_verified_in_percentage"` - PackageFilesCount int `json:"package_files_count"` - PackageFilesChecksumTotalCount int `json:"package_files_checksum_total_count"` - PackageFilesChecksummedCount int `json:"package_files_checksummed_count"` - PackageFilesChecksumFailedCount int `json:"package_files_checksum_failed_count"` - PackageFilesSyncedCount int `json:"package_files_synced_count"` - PackageFilesFailedCount int `json:"package_files_failed_count"` - PackageFilesRegistryCount int `json:"package_files_registry_count"` - PackageFilesVerificationTotalCount int `json:"package_files_verification_total_count"` - PackageFilesVerifiedCount int `json:"package_files_verified_count"` - PackageFilesVerificationFailedCount int `json:"package_files_verification_failed_count"` + PackageFilesCount int64 `json:"package_files_count"` + PackageFilesChecksumTotalCount int64 `json:"package_files_checksum_total_count"` + PackageFilesChecksummedCount int64 `json:"package_files_checksummed_count"` + PackageFilesChecksumFailedCount int64 `json:"package_files_checksum_failed_count"` + PackageFilesSyncedCount int64 `json:"package_files_synced_count"` + PackageFilesFailedCount int64 `json:"package_files_failed_count"` + PackageFilesRegistryCount int64 `json:"package_files_registry_count"` + PackageFilesVerificationTotalCount int64 `json:"package_files_verification_total_count"` + PackageFilesVerifiedCount int64 `json:"package_files_verified_count"` + PackageFilesVerificationFailedCount int64 `json:"package_files_verification_failed_count"` PackageFilesSyncedInPercentage string `json:"package_files_synced_in_percentage"` PackageFilesVerifiedInPercentage string `json:"package_files_verified_in_percentage"` - PagesDeploymentsCount int `json:"pages_deployments_count"` - PagesDeploymentsChecksumTotalCount int `json:"pages_deployments_checksum_total_count"` - PagesDeploymentsChecksummedCount int `json:"pages_deployments_checksummed_count"` - PagesDeploymentsChecksumFailedCount int `json:"pages_deployments_checksum_failed_count"` - PagesDeploymentsSyncedCount int `json:"pages_deployments_synced_count"` - PagesDeploymentsFailedCount int `json:"pages_deployments_failed_count"` - PagesDeploymentsRegistryCount int `json:"pages_deployments_registry_count"` - PagesDeploymentsVerificationTotalCount int `json:"pages_deployments_verification_total_count"` - PagesDeploymentsVerifiedCount int `json:"pages_deployments_verified_count"` - PagesDeploymentsVerificationFailedCount int `json:"pages_deployments_verification_failed_count"` + PagesDeploymentsCount int64 `json:"pages_deployments_count"` + PagesDeploymentsChecksumTotalCount int64 `json:"pages_deployments_checksum_total_count"` + PagesDeploymentsChecksummedCount int64 `json:"pages_deployments_checksummed_count"` + PagesDeploymentsChecksumFailedCount int64 `json:"pages_deployments_checksum_failed_count"` + PagesDeploymentsSyncedCount int64 `json:"pages_deployments_synced_count"` + PagesDeploymentsFailedCount int64 `json:"pages_deployments_failed_count"` + PagesDeploymentsRegistryCount int64 `json:"pages_deployments_registry_count"` + PagesDeploymentsVerificationTotalCount int64 `json:"pages_deployments_verification_total_count"` + PagesDeploymentsVerifiedCount int64 `json:"pages_deployments_verified_count"` + PagesDeploymentsVerificationFailedCount int64 `json:"pages_deployments_verification_failed_count"` PagesDeploymentsSyncedInPercentage string `json:"pages_deployments_synced_in_percentage"` PagesDeploymentsVerifiedInPercentage string `json:"pages_deployments_verified_in_percentage"` - TerraformStateVersionsCount int `json:"terraform_state_versions_count"` - TerraformStateVersionsChecksumTotalCount int `json:"terraform_state_versions_checksum_total_count"` - TerraformStateVersionsChecksummedCount int `json:"terraform_state_versions_checksummed_count"` - TerraformStateVersionsChecksumFailedCount int `json:"terraform_state_versions_checksum_failed_count"` - TerraformStateVersionsSyncedCount int `json:"terraform_state_versions_synced_count"` - TerraformStateVersionsFailedCount int `json:"terraform_state_versions_failed_count"` - TerraformStateVersionsRegistryCount int `json:"terraform_state_versions_registry_count"` - TerraformStateVersionsVerificationTotalCount int `json:"terraform_state_versions_verification_total_count"` - TerraformStateVersionsVerifiedCount int `json:"terraform_state_versions_verified_count"` - TerraformStateVersionsVerificationFailedCount int `json:"terraform_state_versions_verification_failed_count"` + TerraformStateVersionsCount int64 `json:"terraform_state_versions_count"` + TerraformStateVersionsChecksumTotalCount int64 `json:"terraform_state_versions_checksum_total_count"` + TerraformStateVersionsChecksummedCount int64 `json:"terraform_state_versions_checksummed_count"` + TerraformStateVersionsChecksumFailedCount int64 `json:"terraform_state_versions_checksum_failed_count"` + TerraformStateVersionsSyncedCount int64 `json:"terraform_state_versions_synced_count"` + TerraformStateVersionsFailedCount int64 `json:"terraform_state_versions_failed_count"` + TerraformStateVersionsRegistryCount int64 `json:"terraform_state_versions_registry_count"` + TerraformStateVersionsVerificationTotalCount int64 `json:"terraform_state_versions_verification_total_count"` + TerraformStateVersionsVerifiedCount int64 `json:"terraform_state_versions_verified_count"` + TerraformStateVersionsVerificationFailedCount int64 `json:"terraform_state_versions_verification_failed_count"` TerraformStateVersionsSyncedInPercentage string `json:"terraform_state_versions_synced_in_percentage"` TerraformStateVersionsVerifiedInPercentage string `json:"terraform_state_versions_verified_in_percentage"` - SnippetRepositoriesCount int `json:"snippet_repositories_count"` - SnippetRepositoriesChecksumTotalCount int `json:"snippet_repositories_checksum_total_count"` - SnippetRepositoriesChecksummedCount int `json:"snippet_repositories_checksummed_count"` - SnippetRepositoriesChecksumFailedCount int `json:"snippet_repositories_checksum_failed_count"` - SnippetRepositoriesSyncedCount int `json:"snippet_repositories_synced_count"` - SnippetRepositoriesFailedCount int `json:"snippet_repositories_failed_count"` - SnippetRepositoriesRegistryCount int `json:"snippet_repositories_registry_count"` - SnippetRepositoriesVerificationTotalCount int `json:"snippet_repositories_verification_total_count"` - SnippetRepositoriesVerifiedCount int `json:"snippet_repositories_verified_count"` - SnippetRepositoriesVerificationFailedCount int `json:"snippet_repositories_verification_failed_count"` + SnippetRepositoriesCount int64 `json:"snippet_repositories_count"` + SnippetRepositoriesChecksumTotalCount int64 `json:"snippet_repositories_checksum_total_count"` + SnippetRepositoriesChecksummedCount int64 `json:"snippet_repositories_checksummed_count"` + SnippetRepositoriesChecksumFailedCount int64 `json:"snippet_repositories_checksum_failed_count"` + SnippetRepositoriesSyncedCount int64 `json:"snippet_repositories_synced_count"` + SnippetRepositoriesFailedCount int64 `json:"snippet_repositories_failed_count"` + SnippetRepositoriesRegistryCount int64 `json:"snippet_repositories_registry_count"` + SnippetRepositoriesVerificationTotalCount int64 `json:"snippet_repositories_verification_total_count"` + SnippetRepositoriesVerifiedCount int64 `json:"snippet_repositories_verified_count"` + SnippetRepositoriesVerificationFailedCount int64 `json:"snippet_repositories_verification_failed_count"` SnippetRepositoriesSyncedInPercentage string `json:"snippet_repositories_synced_in_percentage"` SnippetRepositoriesVerifiedInPercentage string `json:"snippet_repositories_verified_in_percentage"` - GroupWikiRepositoriesCount int `json:"group_wiki_repositories_count"` - GroupWikiRepositoriesChecksumTotalCount int `json:"group_wiki_repositories_checksum_total_count"` - GroupWikiRepositoriesChecksummedCount int `json:"group_wiki_repositories_checksummed_count"` - GroupWikiRepositoriesChecksumFailedCount int `json:"group_wiki_repositories_checksum_failed_count"` - GroupWikiRepositoriesSyncedCount int `json:"group_wiki_repositories_synced_count"` - GroupWikiRepositoriesFailedCount int `json:"group_wiki_repositories_failed_count"` - GroupWikiRepositoriesRegistryCount int `json:"group_wiki_repositories_registry_count"` - GroupWikiRepositoriesVerificationTotalCount int `json:"group_wiki_repositories_verification_total_count"` - GroupWikiRepositoriesVerifiedCount int `json:"group_wiki_repositories_verified_count"` - GroupWikiRepositoriesVerificationFailedCount int `json:"group_wiki_repositories_verification_failed_count"` + GroupWikiRepositoriesCount int64 `json:"group_wiki_repositories_count"` + GroupWikiRepositoriesChecksumTotalCount int64 `json:"group_wiki_repositories_checksum_total_count"` + GroupWikiRepositoriesChecksummedCount int64 `json:"group_wiki_repositories_checksummed_count"` + GroupWikiRepositoriesChecksumFailedCount int64 `json:"group_wiki_repositories_checksum_failed_count"` + GroupWikiRepositoriesSyncedCount int64 `json:"group_wiki_repositories_synced_count"` + GroupWikiRepositoriesFailedCount int64 `json:"group_wiki_repositories_failed_count"` + GroupWikiRepositoriesRegistryCount int64 `json:"group_wiki_repositories_registry_count"` + GroupWikiRepositoriesVerificationTotalCount int64 `json:"group_wiki_repositories_verification_total_count"` + GroupWikiRepositoriesVerifiedCount int64 `json:"group_wiki_repositories_verified_count"` + GroupWikiRepositoriesVerificationFailedCount int64 `json:"group_wiki_repositories_verification_failed_count"` GroupWikiRepositoriesSyncedInPercentage string `json:"group_wiki_repositories_synced_in_percentage"` GroupWikiRepositoriesVerifiedInPercentage string `json:"group_wiki_repositories_verified_in_percentage"` - PipelineArtifactsCount int `json:"pipeline_artifacts_count"` - PipelineArtifactsChecksumTotalCount int `json:"pipeline_artifacts_checksum_total_count"` - PipelineArtifactsChecksummedCount int `json:"pipeline_artifacts_checksummed_count"` - PipelineArtifactsChecksumFailedCount int `json:"pipeline_artifacts_checksum_failed_count"` - PipelineArtifactsSyncedCount int `json:"pipeline_artifacts_synced_count"` - PipelineArtifactsFailedCount int `json:"pipeline_artifacts_failed_count"` - PipelineArtifactsRegistryCount int `json:"pipeline_artifacts_registry_count"` - PipelineArtifactsVerificationTotalCount int `json:"pipeline_artifacts_verification_total_count"` - PipelineArtifactsVerifiedCount int `json:"pipeline_artifacts_verified_count"` - PipelineArtifactsVerificationFailedCount int `json:"pipeline_artifacts_verification_failed_count"` + PipelineArtifactsCount int64 `json:"pipeline_artifacts_count"` + PipelineArtifactsChecksumTotalCount int64 `json:"pipeline_artifacts_checksum_total_count"` + PipelineArtifactsChecksummedCount int64 `json:"pipeline_artifacts_checksummed_count"` + PipelineArtifactsChecksumFailedCount int64 `json:"pipeline_artifacts_checksum_failed_count"` + PipelineArtifactsSyncedCount int64 `json:"pipeline_artifacts_synced_count"` + PipelineArtifactsFailedCount int64 `json:"pipeline_artifacts_failed_count"` + PipelineArtifactsRegistryCount int64 `json:"pipeline_artifacts_registry_count"` + PipelineArtifactsVerificationTotalCount int64 `json:"pipeline_artifacts_verification_total_count"` + PipelineArtifactsVerifiedCount int64 `json:"pipeline_artifacts_verified_count"` + PipelineArtifactsVerificationFailedCount int64 `json:"pipeline_artifacts_verification_failed_count"` PipelineArtifactsSyncedInPercentage string `json:"pipeline_artifacts_synced_in_percentage"` PipelineArtifactsVerifiedInPercentage string `json:"pipeline_artifacts_verified_in_percentage"` - UploadsCount int `json:"uploads_count"` - UploadsSyncedCount int `json:"uploads_synced_count"` - UploadsFailedCount int `json:"uploads_failed_count"` - UploadsRegistryCount int `json:"uploads_registry_count"` + UploadsCount int64 `json:"uploads_count"` + UploadsSyncedCount int64 `json:"uploads_synced_count"` + UploadsFailedCount int64 `json:"uploads_failed_count"` + UploadsRegistryCount int64 `json:"uploads_registry_count"` UploadsSyncedInPercentage string `json:"uploads_synced_in_percentage"` } @@ -436,18 +393,10 @@ type GeoNodeStatus struct { // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-status-about-all-geo-nodes func (s *GeoNodesService) RetrieveStatusOfAllGeoNodes(options ...RequestOptionFunc) ([]*GeoNodeStatus, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "geo_nodes/status", nil, options) - if err != nil { - return nil, nil, err - } - - var gnss []*GeoNodeStatus - resp, err := s.client.Do(req, &gnss) - if err != nil { - return nil, resp, err - } - - return gnss, resp, nil + return do[[]*GeoNodeStatus](s.client, + withPath("geo_nodes/status"), + withRequestOpts(options...), + ) } // RetrieveStatusOfGeoNode get the of status of a specific Geo Nodes. @@ -455,19 +404,9 @@ func (s *GeoNodesService) RetrieveStatusOfAllGeoNodes(options ...RequestOptionFu // // GitLab API docs: // https://docs.gitlab.com/api/geo_nodes/#retrieve-status-about-a-specific-geo-node -func (s *GeoNodesService) RetrieveStatusOfGeoNode(id int, options ...RequestOptionFunc) (*GeoNodeStatus, *Response, error) { - u := fmt.Sprintf("geo_nodes/%d/status", id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gns := new(GeoNodeStatus) - resp, err := s.client.Do(req, gns) - if err != nil { - return nil, resp, err - } - - return gns, resp, nil +func (s *GeoNodesService) RetrieveStatusOfGeoNode(id int64, options ...RequestOptionFunc) (*GeoNodeStatus, *Response, error) { + return do[*GeoNodeStatus](s.client, + withPath("geo_nodes/%d/status", id), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/geo_sites.go b/vendor/gitlab.com/gitlab-org/api/client-go/geo_sites.go index bd0f9f2b3..f5818a3bc 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/geo_sites.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/geo_sites.go @@ -15,21 +15,52 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( GeoSitesServiceInterface interface { + // CreateGeoSite creates a new Geo Site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#create-a-new-geo-site CreateGeoSite(*CreateGeoSitesOptions, ...RequestOptionFunc) (*GeoSite, *Response, error) + // ListGeoSites gets a list of geo sites. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#retrieve-configuration-about-all-geo-sites ListGeoSites(*ListGeoSitesOptions, ...RequestOptionFunc) ([]*GeoSite, *Response, error) - GetGeoSite(int, ...RequestOptionFunc) (*GeoSite, *Response, error) - EditGeoSite(int, *EditGeoSiteOptions, ...RequestOptionFunc) (*GeoSite, *Response, error) - DeleteGeoSite(int, ...RequestOptionFunc) (*Response, error) - RepairGeoSite(int, ...RequestOptionFunc) (*GeoSite, *Response, error) + // GetGeoSite gets a specific geo site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#retrieve-configuration-about-a-specific-geo-site + GetGeoSite(int64, ...RequestOptionFunc) (*GeoSite, *Response, error) + // EditGeoSite updates settings of an existing Geo site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#edit-a-geo-site + EditGeoSite(int64, *EditGeoSiteOptions, ...RequestOptionFunc) (*GeoSite, *Response, error) + // DeleteGeoSite removes the Geo site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#delete-a-geo-site + DeleteGeoSite(int64, ...RequestOptionFunc) (*Response, error) + // RepairGeoSite to repair the OAuth authentication of a Geo site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#repair-a-geo-site + RepairGeoSite(int64, ...RequestOptionFunc) (*GeoSite, *Response, error) + // ListStatusOfAllGeoSites get the list of status of all Geo Sites. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-all-geo-sites ListStatusOfAllGeoSites(*ListStatusOfAllGeoSitesOptions, ...RequestOptionFunc) ([]*GeoSiteStatus, *Response, error) - GetStatusOfGeoSite(int, ...RequestOptionFunc) (*GeoSiteStatus, *Response, error) + // GetStatusOfGeoSite gets the status of a specific Geo Site. + // + // GitLab API docs: + // https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-a-specific-geo-site + GetStatusOfGeoSite(int64, ...RequestOptionFunc) (*GeoSiteStatus, *Response, error) } // GeoSitesService handles communication with Geo Sites related methods @@ -47,21 +78,21 @@ var _ GeoSitesServiceInterface = (*GeoSitesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/geo_sites/ type GeoSite struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` URL string `json:"url"` InternalURL string `json:"internal_url"` Primary bool `json:"primary"` Enabled bool `json:"enabled"` Current bool `json:"current"` - FilesMaxCapacity int `json:"files_max_capacity"` - ReposMaxCapacity int `json:"repos_max_capacity"` - VerificationMaxCapacity int `json:"verification_max_capacity"` - ContainerRepositoriesMaxCapacity int `json:"container_repositories_max_capacity"` + FilesMaxCapacity int64 `json:"files_max_capacity"` + ReposMaxCapacity int64 `json:"repos_max_capacity"` + VerificationMaxCapacity int64 `json:"verification_max_capacity"` + ContainerRepositoriesMaxCapacity int64 `json:"container_repositories_max_capacity"` SelectiveSyncType string `json:"selective_sync_type"` SelectiveSyncShards []string `json:"selective_sync_shards"` - SelectiveSyncNamespaceIDs []int `json:"selective_sync_namespace_ids"` - MinimumReverificationInterval int `json:"minimum_reverification_interval"` + SelectiveSyncNamespaceIDs []int64 `json:"selective_sync_namespace_ids"` + MinimumReverificationInterval int64 `json:"minimum_reverification_interval"` SyncObjectStorage bool `json:"sync_object_storage"` WebEditURL string `json:"web_edit_url"` WebGeoReplicationDetailsURL string `json:"web_geo_replication_details_url"` @@ -80,327 +111,263 @@ type GeoSiteLinks struct { // CreateGeoSitesOptions represents the available CreateGeoSite() options. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#create-a-new-geo-site +// https://docs.gitlab.com/api/geo_sites/#create-a-geo-site type CreateGeoSitesOptions struct { Primary *bool `url:"primary,omitempty" json:"primary,omitempty"` Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` InternalURL *string `url:"internal_url,omitempty" json:"internal_url,omitempty"` - FilesMaxCapacity *int `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` - ReposMaxCapacity *int `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` - VerificationMaxCapacity *int `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` - ContainerRepositoriesMaxCapacity *int `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` + FilesMaxCapacity *int64 `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` + ReposMaxCapacity *int64 `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` + VerificationMaxCapacity *int64 `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` + ContainerRepositoriesMaxCapacity *int64 `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` SyncObjectStorage *bool `url:"sync_object_storage,omitempty" json:"sync_object_storage,omitempty"` SelectiveSyncType *string `url:"selective_sync_type,omitempty" json:"selective_sync_type,omitempty"` SelectiveSyncShards *[]string `url:"selective_sync_shards,omitempty" json:"selective_sync_shards,omitempty"` - SelectiveSyncNamespaceIDs *[]int `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` - MinimumReverificationInterval *int `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` + SelectiveSyncNamespaceIDs *[]int64 `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` + MinimumReverificationInterval *int64 `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` } -// CreateGeoSite creates a new Geo Site. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#create-a-new-geo-site func (s *GeoSitesService) CreateGeoSite(opt *CreateGeoSitesOptions, options ...RequestOptionFunc) (*GeoSite, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "geo_sites", opt, options) - if err != nil { - return nil, nil, err - } - - site := new(GeoSite) - resp, err := s.client.Do(req, site) - if err != nil { - return nil, resp, err - } - - return site, resp, nil + return do[*GeoSite](s.client, + withMethod(http.MethodPost), + withPath("geo_sites"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListGeoSitesOptions represents the available ListGeoSites() options. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-configuration-about-all-geo-sites -type ListGeoSitesOptions ListOptions +// https://docs.gitlab.com/api/geo_sites/#list-all-geo-sites +type ListGeoSitesOptions struct { + ListOptions +} -// ListGeoSites gets a list of geo sites. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-configuration-about-all-geo-sites func (s *GeoSitesService) ListGeoSites(opt *ListGeoSitesOptions, options ...RequestOptionFunc) ([]*GeoSite, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "geo_sites", opt, options) - if err != nil { - return nil, nil, err - } - - var sites []*GeoSite - resp, err := s.client.Do(req, &sites) - if err != nil { - return nil, resp, err - } - - return sites, resp, nil + return do[[]*GeoSite](s.client, + withPath("geo_sites"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetGeoSite gets a specific geo site. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-configuration-about-a-specific-geo-site -func (s *GeoSitesService) GetGeoSite(id int, options ...RequestOptionFunc) (*GeoSite, *Response, error) { - u := fmt.Sprintf("geo_sites/%d", id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - site := new(GeoSite) - resp, err := s.client.Do(req, site) - if err != nil { - return nil, resp, err - } - - return site, resp, nil +func (s *GeoSitesService) GetGeoSite(id int64, options ...RequestOptionFunc) (*GeoSite, *Response, error) { + return do[*GeoSite](s.client, + withPath("geo_sites/%d", id), + withRequestOpts(options...), + ) } // EditGeoSiteOptions represents the available EditGeoSite() options. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#edit-a-geo-site +// https://docs.gitlab.com/api/geo_sites/#update-a-geo-site type EditGeoSiteOptions struct { Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` InternalURL *string `url:"internal_url,omitempty" json:"internal_url,omitempty"` - FilesMaxCapacity *int `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` - ReposMaxCapacity *int `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` - VerificationMaxCapacity *int `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` - ContainerRepositoriesMaxCapacity *int `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` + FilesMaxCapacity *int64 `url:"files_max_capacity,omitempty" json:"files_max_capacity,omitempty"` + ReposMaxCapacity *int64 `url:"repos_max_capacity,omitempty" json:"repos_max_capacity,omitempty"` + VerificationMaxCapacity *int64 `url:"verification_max_capacity,omitempty" json:"verification_max_capacity,omitempty"` + ContainerRepositoriesMaxCapacity *int64 `url:"container_repositories_max_capacity,omitempty" json:"container_repositories_max_capacity,omitempty"` SelectiveSyncType *string `url:"selective_sync_type,omitempty" json:"selective_sync_type,omitempty"` SelectiveSyncShards *[]string `url:"selective_sync_shards,omitempty" json:"selective_sync_shards,omitempty"` - SelectiveSyncNamespaceIDs *[]int `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` - MinimumReverificationInterval *int `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` + SelectiveSyncNamespaceIDs *[]int64 `url:"selective_sync_namespace_ids,omitempty" json:"selective_sync_namespace_ids,omitempty"` + MinimumReverificationInterval *int64 `url:"minimum_reverification_interval,omitempty" json:"minimum_reverification_interval,omitempty"` } -// EditGeoSite updates settings of an existing Geo site. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#edit-a-geo-site -func (s *GeoSitesService) EditGeoSite(id int, opt *EditGeoSiteOptions, options ...RequestOptionFunc) (*GeoSite, *Response, error) { - u := fmt.Sprintf("geo_sites/%d", id) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - site := new(GeoSite) - resp, err := s.client.Do(req, site) - if err != nil { - return nil, resp, err - } - - return site, resp, nil +func (s *GeoSitesService) EditGeoSite(id int64, opt *EditGeoSiteOptions, options ...RequestOptionFunc) (*GeoSite, *Response, error) { + return do[*GeoSite](s.client, + withMethod(http.MethodPut), + withPath("geo_sites/%d", id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteGeoSite removes the Geo site. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#delete-a-geo-site -func (s *GeoSitesService) DeleteGeoSite(id int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("geo_sites/%d", id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GeoSitesService) DeleteGeoSite(id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("geo_sites/%d", id), + withRequestOpts(options...), + ) + return resp, err } -// RepairGeoSite to repair the OAuth authentication of a Geo site. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#repair-a-geo-site -func (s *GeoSitesService) RepairGeoSite(id int, options ...RequestOptionFunc) (*GeoSite, *Response, error) { - u := fmt.Sprintf("geo_sites/%d/repair", id) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - site := new(GeoSite) - resp, err := s.client.Do(req, site) - if err != nil { - return nil, resp, err - } - - return site, resp, nil +func (s *GeoSitesService) RepairGeoSite(id int64, options ...RequestOptionFunc) (*GeoSite, *Response, error) { + return do[*GeoSite](s.client, + withMethod(http.MethodPost), + withPath("geo_sites/%d/repair", id), + withRequestOpts(options...), + ) } // GeoSiteStatus represents the status of Geo Site. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-all-geo-sites +// https://docs.gitlab.com/api/geo_sites/#list-all-geo-site-statuses type GeoSiteStatus struct { - GeoNodeID int `json:"geo_node_id"` - ProjectsCount int `json:"projects_count"` + GeoNodeID int64 `json:"geo_node_id"` + ProjectsCount int64 `json:"projects_count"` ContainerRepositoriesReplicationEnabled bool `json:"container_repositories_replication_enabled"` - LFSObjectsCount int `json:"lfs_objects_count"` - LFSObjectsChecksumTotalCount int `json:"lfs_objects_checksum_total_count"` - LFSObjectsChecksummedCount int `json:"lfs_objects_checksummed_count"` - LFSObjectsChecksumFailedCount int `json:"lfs_objects_checksum_failed_count"` - LFSObjectsSyncedCount int `json:"lfs_objects_synced_count"` - LFSObjectsFailedCount int `json:"lfs_objects_failed_count"` - LFSObjectsRegistryCount int `json:"lfs_objects_registry_count"` - LFSObjectsVerificationTotalCount int `json:"lfs_objects_verification_total_count"` - LFSObjectsVerifiedCount int `json:"lfs_objects_verified_count"` - LFSObjectsVerificationFailedCount int `json:"lfs_objects_verification_failed_count"` - MergeRequestDiffsCount int `json:"merge_request_diffs_count"` - MergeRequestDiffsChecksumTotalCount int `json:"merge_request_diffs_checksum_total_count"` - MergeRequestDiffsChecksummedCount int `json:"merge_request_diffs_checksummed_count"` - MergeRequestDiffsChecksumFailedCount int `json:"merge_request_diffs_checksum_failed_count"` - MergeRequestDiffsSyncedCount int `json:"merge_request_diffs_synced_count"` - MergeRequestDiffsFailedCount int `json:"merge_request_diffs_failed_count"` - MergeRequestDiffsRegistryCount int `json:"merge_request_diffs_registry_count"` - MergeRequestDiffsVerificationTotalCount int `json:"merge_request_diffs_verification_total_count"` - MergeRequestDiffsVerifiedCount int `json:"merge_request_diffs_verified_count"` - MergeRequestDiffsVerificationFailedCount int `json:"merge_request_diffs_verification_failed_count"` - PackageFilesCount int `json:"package_files_count"` - PackageFilesChecksumTotalCount int `json:"package_files_checksum_total_count"` - PackageFilesChecksummedCount int `json:"package_files_checksummed_count"` - PackageFilesChecksumFailedCount int `json:"package_files_checksum_failed_count"` - PackageFilesSyncedCount int `json:"package_files_synced_count"` - PackageFilesFailedCount int `json:"package_files_failed_count"` - PackageFilesRegistryCount int `json:"package_files_registry_count"` - PackageFilesVerificationTotalCount int `json:"package_files_verification_total_count"` - PackageFilesVerifiedCount int `json:"package_files_verified_count"` - PackageFilesVerificationFailedCount int `json:"package_files_verification_failed_count"` - TerraformStateVersionsCount int `json:"terraform_state_versions_count"` - TerraformStateVersionsChecksumTotalCount int `json:"terraform_state_versions_checksum_total_count"` - TerraformStateVersionsChecksummedCount int `json:"terraform_state_versions_checksummed_count"` - TerraformStateVersionsChecksumFailedCount int `json:"terraform_state_versions_checksum_failed_count"` - TerraformStateVersionsSyncedCount int `json:"terraform_state_versions_synced_count"` - TerraformStateVersionsFailedCount int `json:"terraform_state_versions_failed_count"` - TerraformStateVersionsRegistryCount int `json:"terraform_state_versions_registry_count"` - TerraformStateVersionsVerificationTotalCount int `json:"terraform_state_versions_verification_total_count"` - TerraformStateVersionsVerifiedCount int `json:"terraform_state_versions_verified_count"` - TerraformStateVersionsVerificationFailedCount int `json:"terraform_state_versions_verification_failed_count"` - SnippetRepositoriesCount int `json:"snippet_repositories_count"` - SnippetRepositoriesChecksumTotalCount int `json:"snippet_repositories_checksum_total_count"` - SnippetRepositoriesChecksummedCount int `json:"snippet_repositories_checksummed_count"` - SnippetRepositoriesChecksumFailedCount int `json:"snippet_repositories_checksum_failed_count"` - SnippetRepositoriesSyncedCount int `json:"snippet_repositories_synced_count"` - SnippetRepositoriesFailedCount int `json:"snippet_repositories_failed_count"` - SnippetRepositoriesRegistryCount int `json:"snippet_repositories_registry_count"` - SnippetRepositoriesVerificationTotalCount int `json:"snippet_repositories_verification_total_count"` - SnippetRepositoriesVerifiedCount int `json:"snippet_repositories_verified_count"` - SnippetRepositoriesVerificationFailedCount int `json:"snippet_repositories_verification_failed_count"` - GroupWikiRepositoriesCount int `json:"group_wiki_repositories_count"` - GroupWikiRepositoriesChecksumTotalCount int `json:"group_wiki_repositories_checksum_total_count"` - GroupWikiRepositoriesChecksummedCount int `json:"group_wiki_repositories_checksummed_count"` - GroupWikiRepositoriesChecksumFailedCount int `json:"group_wiki_repositories_checksum_failed_count"` - GroupWikiRepositoriesSyncedCount int `json:"group_wiki_repositories_synced_count"` - GroupWikiRepositoriesFailedCount int `json:"group_wiki_repositories_failed_count"` - GroupWikiRepositoriesRegistryCount int `json:"group_wiki_repositories_registry_count"` - GrupWikiRepositoriesVerificationTotalCount int `json:"group_wiki_repositories_verification_total_count"` - GroupWikiRepositoriesVerifiedCount int `json:"group_wiki_repositories_verified_count"` - GroupWikiRepositoriesVerificationFailedCount int `json:"group_wiki_repositories_verification_failed_count"` - PipelineArtifactsCount int `json:"pipeline_artifacts_count"` - PipelineArtifactsChecksumTotalCount int `json:"pipeline_artifacts_checksum_total_count"` - PipelineArtifactsChecksummedCount int `json:"pipeline_artifacts_checksummed_count"` - PipelineArtifactsChecksumFailedCount int `json:"pipeline_artifacts_checksum_failed_count"` - PipelineArtifactsSyncedCount int `json:"pipeline_artifacts_synced_count"` - PipelineArtifactsFailedCount int `json:"pipeline_artifacts_failed_count"` - PipelineArtifactsRegistryCount int `json:"pipeline_artifacts_registry_count"` - PipelineArtifactsVerificationTotalCount int `json:"pipeline_artifacts_verification_total_count"` - PipelineArtifactsVerifiedCount int `json:"pipeline_artifacts_verified_count"` - PipelineArtifactsVerificationFailedCount int `json:"pipeline_artifacts_verification_failed_count"` - PagesDeploymentsCount int `json:"pages_deployments_count"` - PagesDeploymentsChecksumTotalCount int `json:"pages_deployments_checksum_total_count"` - PagesDeploymentsChecksummedCount int `json:"pages_deployments_checksummed_count"` - PagesDeploymentsChecksumFailedCount int `json:"pages_deployments_checksum_failed_count"` - PagesDeploymentsSyncedCount int `json:"pages_deployments_synced_count"` - PagesDeploymentsFailedCount int `json:"pages_deployments_failed_count"` - PagesDeploymentsRegistryCount int `json:"pages_deployments_registry_count"` - PagesDeploymentsVerificationTotalCount int `json:"pages_deployments_verification_total_count"` - PagesDeploymentsVerifiedCount int `json:"pages_deployments_verified_count"` - PagesDeploymentsVerificationFailedCount int `json:"pages_deployments_verification_failed_count"` - UploadsCount int `json:"uploads_count"` - UploadsChecksumTotalCount int `json:"uploads_checksum_total_count"` - UploadsChecksummedCount int `json:"uploads_checksummed_count"` - UploadsChecksumFailedCount int `json:"uploads_checksum_failed_count"` - UploadsSyncedCount int `json:"uploads_synced_count"` - UploadsFailedCount int `json:"uploads_failed_count"` - UploadsRegistryCount int `json:"uploads_registry_count"` - UploadsVerificationTotalCount int `json:"uploads_verification_total_count"` - UploadsVerifiedCount int `json:"uploads_verified_count"` - UploadsVerificationFailedCount int `json:"uploads_verification_failed_count"` - JobArtifactsCount int `json:"job_artifacts_count"` - JobArtifactsChecksumTotalCount int `json:"job_artifacts_checksum_total_count"` - JobArtifactsChecksummedCount int `json:"job_artifacts_checksummed_count"` - JobArtifactsChecksumFailedCount int `json:"job_artifacts_checksum_failed_count"` - JobArtifactsSyncedCount int `json:"job_artifacts_synced_count"` - JobArtifactsFailedCount int `json:"job_artifacts_failed_count"` - JobArtifactsRegistryCount int `json:"job_artifacts_registry_count"` - JobArtifactsVerificationTotalCount int `json:"job_artifacts_verification_total_count"` - JobArtifactsVerifiedCount int `json:"job_artifacts_verified_count"` - JobArtifactsVerificationFailedCount int `json:"job_artifacts_verification_failed_count"` - CISecureFilesCount int `json:"ci_secure_files_count"` - CISecureFilesChecksumTotalCount int `json:"ci_secure_files_checksum_total_count"` - CISecureFilesChecksummedCount int `json:"ci_secure_files_checksummed_count"` - CISecureFilesChecksumFailedCount int `json:"ci_secure_files_checksum_failed_count"` - CISecureFilesSyncedCount int `json:"ci_secure_files_synced_count"` - CISecureFilesFailedCount int `json:"ci_secure_files_failed_count"` - CISecureFilesRegistryCount int `json:"ci_secure_files_registry_count"` - CISecureFilesVerificationTotalCount int `json:"ci_secure_files_verification_total_count"` - CISecureFilesVerifiedCount int `json:"ci_secure_files_verified_count"` - CISecureFilesVerificationFailedCount int `json:"ci_secure_files_verification_failed_count"` - ContainerRepositoriesCount int `json:"container_repositories_count"` - ContainerRepositoriesChecksumTotalCount int `json:"container_repositories_checksum_total_count"` - ContainerRepositoriesChecksummedCount int `json:"container_repositories_checksummed_count"` - ContainerRepositoriesChecksumFailedCount int `json:"container_repositories_checksum_failed_count"` - ContainerRepositoriesSyncedCount int `json:"container_repositories_synced_count"` - ContainerRepositoriesFailedCount int `json:"container_repositories_failed_count"` - ContainerRepositoriesRegistryCount int `json:"container_repositories_registry_count"` - ContainerRepositoriesVerificationTotalCount int `json:"container_repositories_verification_total_count"` - ContainerRepositoriesVerifiedCount int `json:"container_repositories_verified_count"` - ContainerRepositoriesVerificationFailedCount int `json:"container_repositories_verification_failed_count"` - DependencyProxyBlobsCount int `json:"dependency_proxy_blobs_count"` - DependencyProxyBlobsChecksumTotalCount int `json:"dependency_proxy_blobs_checksum_total_count"` - DependencyProxyBlobsChecksummedCount int `json:"dependency_proxy_blobs_checksummed_count"` - DependencyProxyBlobsChecksumFailedCount int `json:"dependency_proxy_blobs_checksum_failed_count"` - DependencyProxyBlobsSyncedCount int `json:"dependency_proxy_blobs_synced_count"` - DependencyProxyBlobsFailedCount int `json:"dependency_proxy_blobs_failed_count"` - DependencyProxyBlobsRegistryCount int `json:"dependency_proxy_blobs_registry_count"` - DependencyProxyBlobsVerificationTotalCount int `json:"dependency_proxy_blobs_verification_total_count"` - DependencyProxyBlobsVerifiedCount int `json:"dependency_proxy_blobs_verified_count"` - DependencyProxyBlobsVerificationFailedCount int `json:"dependency_proxy_blobs_verification_failed_count"` - DependencyProxyManifestsCount int `json:"dependency_proxy_manifests_count"` - DependencyProxyManifestsChecksumTotalCount int `json:"dependency_proxy_manifests_checksum_total_count"` - DependencyProxyManifestsChecksummedCount int `json:"dependency_proxy_manifests_checksummed_count"` - DependencyProxyManifestsChecksumFailedCount int `json:"dependency_proxy_manifests_checksum_failed_count"` - DependencyProxyManifestsSyncedCount int `json:"dependency_proxy_manifests_synced_count"` - DependencyProxyManifestsFailedCount int `json:"dependency_proxy_manifests_failed_count"` - DependencyProxyManifestsRegistryCount int `json:"dependency_proxy_manifests_registry_count"` - DependencyProxyManifestsVerificationTotalCount int `json:"dependency_proxy_manifests_verification_total_count"` - DependencyProxyManifestsVerifiedCount int `json:"dependency_proxy_manifests_verified_count"` - DependencyProxyManifestsVerificationFailedCount int `json:"dependency_proxy_manifests_verification_failed_count"` - ProjectWikiRepositoriesCount int `json:"project_wiki_repositories_count"` - ProjectWikiRepositoriesChecksumTotalCount int `json:"project_wiki_repositories_checksum_total_count"` - ProjectWikiRepositoriesChecksummedCount int `json:"project_wiki_repositories_checksummed_count"` - ProjectWikiRepositoriesChecksumFailedCount int `json:"project_wiki_repositories_checksum_failed_count"` - ProjectWikiRepositoriesSyncedCount int `json:"project_wiki_repositories_synced_count"` - ProjectWikiRepositoriesFailedCount int `json:"project_wiki_repositories_failed_count"` - ProjectWikiRepositoriesRegistryCount int `json:"project_wiki_repositories_registry_count"` - ProjectWikiRepositoriesVerificationTotalCount int `json:"project_wiki_repositories_verification_total_count"` - ProjectWikiRepositoriesVerifiedCount int `json:"project_wiki_repositories_verified_count"` - ProjectWikiRepositoriesVerificationFailedCount int `json:"project_wiki_repositories_verification_failed_count"` - GitFetchEventCountWeekly int `json:"git_fetch_event_count_weekly"` - GitPushEventCountWeekly int `json:"git_push_event_count_weekly"` - ProxyRemoteRequestsEventCountWeekly int `json:"proxy_remote_requests_event_count_weekly"` - ProxyLocalRequestsEventCountWeekly int `json:"proxy_local_requests_event_count_weekly"` + LFSObjectsCount int64 `json:"lfs_objects_count"` + LFSObjectsChecksumTotalCount int64 `json:"lfs_objects_checksum_total_count"` + LFSObjectsChecksummedCount int64 `json:"lfs_objects_checksummed_count"` + LFSObjectsChecksumFailedCount int64 `json:"lfs_objects_checksum_failed_count"` + LFSObjectsSyncedCount int64 `json:"lfs_objects_synced_count"` + LFSObjectsFailedCount int64 `json:"lfs_objects_failed_count"` + LFSObjectsRegistryCount int64 `json:"lfs_objects_registry_count"` + LFSObjectsVerificationTotalCount int64 `json:"lfs_objects_verification_total_count"` + LFSObjectsVerifiedCount int64 `json:"lfs_objects_verified_count"` + LFSObjectsVerificationFailedCount int64 `json:"lfs_objects_verification_failed_count"` + MergeRequestDiffsCount int64 `json:"merge_request_diffs_count"` + MergeRequestDiffsChecksumTotalCount int64 `json:"merge_request_diffs_checksum_total_count"` + MergeRequestDiffsChecksummedCount int64 `json:"merge_request_diffs_checksummed_count"` + MergeRequestDiffsChecksumFailedCount int64 `json:"merge_request_diffs_checksum_failed_count"` + MergeRequestDiffsSyncedCount int64 `json:"merge_request_diffs_synced_count"` + MergeRequestDiffsFailedCount int64 `json:"merge_request_diffs_failed_count"` + MergeRequestDiffsRegistryCount int64 `json:"merge_request_diffs_registry_count"` + MergeRequestDiffsVerificationTotalCount int64 `json:"merge_request_diffs_verification_total_count"` + MergeRequestDiffsVerifiedCount int64 `json:"merge_request_diffs_verified_count"` + MergeRequestDiffsVerificationFailedCount int64 `json:"merge_request_diffs_verification_failed_count"` + PackageFilesCount int64 `json:"package_files_count"` + PackageFilesChecksumTotalCount int64 `json:"package_files_checksum_total_count"` + PackageFilesChecksummedCount int64 `json:"package_files_checksummed_count"` + PackageFilesChecksumFailedCount int64 `json:"package_files_checksum_failed_count"` + PackageFilesSyncedCount int64 `json:"package_files_synced_count"` + PackageFilesFailedCount int64 `json:"package_files_failed_count"` + PackageFilesRegistryCount int64 `json:"package_files_registry_count"` + PackageFilesVerificationTotalCount int64 `json:"package_files_verification_total_count"` + PackageFilesVerifiedCount int64 `json:"package_files_verified_count"` + PackageFilesVerificationFailedCount int64 `json:"package_files_verification_failed_count"` + TerraformStateVersionsCount int64 `json:"terraform_state_versions_count"` + TerraformStateVersionsChecksumTotalCount int64 `json:"terraform_state_versions_checksum_total_count"` + TerraformStateVersionsChecksummedCount int64 `json:"terraform_state_versions_checksummed_count"` + TerraformStateVersionsChecksumFailedCount int64 `json:"terraform_state_versions_checksum_failed_count"` + TerraformStateVersionsSyncedCount int64 `json:"terraform_state_versions_synced_count"` + TerraformStateVersionsFailedCount int64 `json:"terraform_state_versions_failed_count"` + TerraformStateVersionsRegistryCount int64 `json:"terraform_state_versions_registry_count"` + TerraformStateVersionsVerificationTotalCount int64 `json:"terraform_state_versions_verification_total_count"` + TerraformStateVersionsVerifiedCount int64 `json:"terraform_state_versions_verified_count"` + TerraformStateVersionsVerificationFailedCount int64 `json:"terraform_state_versions_verification_failed_count"` + SnippetRepositoriesCount int64 `json:"snippet_repositories_count"` + SnippetRepositoriesChecksumTotalCount int64 `json:"snippet_repositories_checksum_total_count"` + SnippetRepositoriesChecksummedCount int64 `json:"snippet_repositories_checksummed_count"` + SnippetRepositoriesChecksumFailedCount int64 `json:"snippet_repositories_checksum_failed_count"` + SnippetRepositoriesSyncedCount int64 `json:"snippet_repositories_synced_count"` + SnippetRepositoriesFailedCount int64 `json:"snippet_repositories_failed_count"` + SnippetRepositoriesRegistryCount int64 `json:"snippet_repositories_registry_count"` + SnippetRepositoriesVerificationTotalCount int64 `json:"snippet_repositories_verification_total_count"` + SnippetRepositoriesVerifiedCount int64 `json:"snippet_repositories_verified_count"` + SnippetRepositoriesVerificationFailedCount int64 `json:"snippet_repositories_verification_failed_count"` + GroupWikiRepositoriesCount int64 `json:"group_wiki_repositories_count"` + GroupWikiRepositoriesChecksumTotalCount int64 `json:"group_wiki_repositories_checksum_total_count"` + GroupWikiRepositoriesChecksummedCount int64 `json:"group_wiki_repositories_checksummed_count"` + GroupWikiRepositoriesChecksumFailedCount int64 `json:"group_wiki_repositories_checksum_failed_count"` + GroupWikiRepositoriesSyncedCount int64 `json:"group_wiki_repositories_synced_count"` + GroupWikiRepositoriesFailedCount int64 `json:"group_wiki_repositories_failed_count"` + GroupWikiRepositoriesRegistryCount int64 `json:"group_wiki_repositories_registry_count"` + GrupWikiRepositoriesVerificationTotalCount int64 `json:"group_wiki_repositories_verification_total_count"` + GroupWikiRepositoriesVerifiedCount int64 `json:"group_wiki_repositories_verified_count"` + GroupWikiRepositoriesVerificationFailedCount int64 `json:"group_wiki_repositories_verification_failed_count"` + PipelineArtifactsCount int64 `json:"pipeline_artifacts_count"` + PipelineArtifactsChecksumTotalCount int64 `json:"pipeline_artifacts_checksum_total_count"` + PipelineArtifactsChecksummedCount int64 `json:"pipeline_artifacts_checksummed_count"` + PipelineArtifactsChecksumFailedCount int64 `json:"pipeline_artifacts_checksum_failed_count"` + PipelineArtifactsSyncedCount int64 `json:"pipeline_artifacts_synced_count"` + PipelineArtifactsFailedCount int64 `json:"pipeline_artifacts_failed_count"` + PipelineArtifactsRegistryCount int64 `json:"pipeline_artifacts_registry_count"` + PipelineArtifactsVerificationTotalCount int64 `json:"pipeline_artifacts_verification_total_count"` + PipelineArtifactsVerifiedCount int64 `json:"pipeline_artifacts_verified_count"` + PipelineArtifactsVerificationFailedCount int64 `json:"pipeline_artifacts_verification_failed_count"` + PagesDeploymentsCount int64 `json:"pages_deployments_count"` + PagesDeploymentsChecksumTotalCount int64 `json:"pages_deployments_checksum_total_count"` + PagesDeploymentsChecksummedCount int64 `json:"pages_deployments_checksummed_count"` + PagesDeploymentsChecksumFailedCount int64 `json:"pages_deployments_checksum_failed_count"` + PagesDeploymentsSyncedCount int64 `json:"pages_deployments_synced_count"` + PagesDeploymentsFailedCount int64 `json:"pages_deployments_failed_count"` + PagesDeploymentsRegistryCount int64 `json:"pages_deployments_registry_count"` + PagesDeploymentsVerificationTotalCount int64 `json:"pages_deployments_verification_total_count"` + PagesDeploymentsVerifiedCount int64 `json:"pages_deployments_verified_count"` + PagesDeploymentsVerificationFailedCount int64 `json:"pages_deployments_verification_failed_count"` + UploadsCount int64 `json:"uploads_count"` + UploadsChecksumTotalCount int64 `json:"uploads_checksum_total_count"` + UploadsChecksummedCount int64 `json:"uploads_checksummed_count"` + UploadsChecksumFailedCount int64 `json:"uploads_checksum_failed_count"` + UploadsSyncedCount int64 `json:"uploads_synced_count"` + UploadsFailedCount int64 `json:"uploads_failed_count"` + UploadsRegistryCount int64 `json:"uploads_registry_count"` + UploadsVerificationTotalCount int64 `json:"uploads_verification_total_count"` + UploadsVerifiedCount int64 `json:"uploads_verified_count"` + UploadsVerificationFailedCount int64 `json:"uploads_verification_failed_count"` + JobArtifactsCount int64 `json:"job_artifacts_count"` + JobArtifactsChecksumTotalCount int64 `json:"job_artifacts_checksum_total_count"` + JobArtifactsChecksummedCount int64 `json:"job_artifacts_checksummed_count"` + JobArtifactsChecksumFailedCount int64 `json:"job_artifacts_checksum_failed_count"` + JobArtifactsSyncedCount int64 `json:"job_artifacts_synced_count"` + JobArtifactsFailedCount int64 `json:"job_artifacts_failed_count"` + JobArtifactsRegistryCount int64 `json:"job_artifacts_registry_count"` + JobArtifactsVerificationTotalCount int64 `json:"job_artifacts_verification_total_count"` + JobArtifactsVerifiedCount int64 `json:"job_artifacts_verified_count"` + JobArtifactsVerificationFailedCount int64 `json:"job_artifacts_verification_failed_count"` + CISecureFilesCount int64 `json:"ci_secure_files_count"` + CISecureFilesChecksumTotalCount int64 `json:"ci_secure_files_checksum_total_count"` + CISecureFilesChecksummedCount int64 `json:"ci_secure_files_checksummed_count"` + CISecureFilesChecksumFailedCount int64 `json:"ci_secure_files_checksum_failed_count"` + CISecureFilesSyncedCount int64 `json:"ci_secure_files_synced_count"` + CISecureFilesFailedCount int64 `json:"ci_secure_files_failed_count"` + CISecureFilesRegistryCount int64 `json:"ci_secure_files_registry_count"` + CISecureFilesVerificationTotalCount int64 `json:"ci_secure_files_verification_total_count"` + CISecureFilesVerifiedCount int64 `json:"ci_secure_files_verified_count"` + CISecureFilesVerificationFailedCount int64 `json:"ci_secure_files_verification_failed_count"` + ContainerRepositoriesCount int64 `json:"container_repositories_count"` + ContainerRepositoriesChecksumTotalCount int64 `json:"container_repositories_checksum_total_count"` + ContainerRepositoriesChecksummedCount int64 `json:"container_repositories_checksummed_count"` + ContainerRepositoriesChecksumFailedCount int64 `json:"container_repositories_checksum_failed_count"` + ContainerRepositoriesSyncedCount int64 `json:"container_repositories_synced_count"` + ContainerRepositoriesFailedCount int64 `json:"container_repositories_failed_count"` + ContainerRepositoriesRegistryCount int64 `json:"container_repositories_registry_count"` + ContainerRepositoriesVerificationTotalCount int64 `json:"container_repositories_verification_total_count"` + ContainerRepositoriesVerifiedCount int64 `json:"container_repositories_verified_count"` + ContainerRepositoriesVerificationFailedCount int64 `json:"container_repositories_verification_failed_count"` + DependencyProxyBlobsCount int64 `json:"dependency_proxy_blobs_count"` + DependencyProxyBlobsChecksumTotalCount int64 `json:"dependency_proxy_blobs_checksum_total_count"` + DependencyProxyBlobsChecksummedCount int64 `json:"dependency_proxy_blobs_checksummed_count"` + DependencyProxyBlobsChecksumFailedCount int64 `json:"dependency_proxy_blobs_checksum_failed_count"` + DependencyProxyBlobsSyncedCount int64 `json:"dependency_proxy_blobs_synced_count"` + DependencyProxyBlobsFailedCount int64 `json:"dependency_proxy_blobs_failed_count"` + DependencyProxyBlobsRegistryCount int64 `json:"dependency_proxy_blobs_registry_count"` + DependencyProxyBlobsVerificationTotalCount int64 `json:"dependency_proxy_blobs_verification_total_count"` + DependencyProxyBlobsVerifiedCount int64 `json:"dependency_proxy_blobs_verified_count"` + DependencyProxyBlobsVerificationFailedCount int64 `json:"dependency_proxy_blobs_verification_failed_count"` + DependencyProxyManifestsCount int64 `json:"dependency_proxy_manifests_count"` + DependencyProxyManifestsChecksumTotalCount int64 `json:"dependency_proxy_manifests_checksum_total_count"` + DependencyProxyManifestsChecksummedCount int64 `json:"dependency_proxy_manifests_checksummed_count"` + DependencyProxyManifestsChecksumFailedCount int64 `json:"dependency_proxy_manifests_checksum_failed_count"` + DependencyProxyManifestsSyncedCount int64 `json:"dependency_proxy_manifests_synced_count"` + DependencyProxyManifestsFailedCount int64 `json:"dependency_proxy_manifests_failed_count"` + DependencyProxyManifestsRegistryCount int64 `json:"dependency_proxy_manifests_registry_count"` + DependencyProxyManifestsVerificationTotalCount int64 `json:"dependency_proxy_manifests_verification_total_count"` + DependencyProxyManifestsVerifiedCount int64 `json:"dependency_proxy_manifests_verified_count"` + DependencyProxyManifestsVerificationFailedCount int64 `json:"dependency_proxy_manifests_verification_failed_count"` + ProjectWikiRepositoriesCount int64 `json:"project_wiki_repositories_count"` + ProjectWikiRepositoriesChecksumTotalCount int64 `json:"project_wiki_repositories_checksum_total_count"` + ProjectWikiRepositoriesChecksummedCount int64 `json:"project_wiki_repositories_checksummed_count"` + ProjectWikiRepositoriesChecksumFailedCount int64 `json:"project_wiki_repositories_checksum_failed_count"` + ProjectWikiRepositoriesSyncedCount int64 `json:"project_wiki_repositories_synced_count"` + ProjectWikiRepositoriesFailedCount int64 `json:"project_wiki_repositories_failed_count"` + ProjectWikiRepositoriesRegistryCount int64 `json:"project_wiki_repositories_registry_count"` + ProjectWikiRepositoriesVerificationTotalCount int64 `json:"project_wiki_repositories_verification_total_count"` + ProjectWikiRepositoriesVerifiedCount int64 `json:"project_wiki_repositories_verified_count"` + ProjectWikiRepositoriesVerificationFailedCount int64 `json:"project_wiki_repositories_verification_failed_count"` + GitFetchEventCountWeekly int64 `json:"git_fetch_event_count_weekly"` + GitPushEventCountWeekly int64 `json:"git_push_event_count_weekly"` + ProxyRemoteRequestsEventCountWeekly int64 `json:"proxy_remote_requests_event_count_weekly"` + ProxyLocalRequestsEventCountWeekly int64 `json:"proxy_local_requests_event_count_weekly"` RepositoriesCheckedInPercentage string `json:"repositories_checked_in_percentage"` ReplicationSlotsUsedInPercentage string `json:"replication_slots_used_in_percentage"` LFSObjectsSyncedInPercentage string `json:"lfs_objects_synced_in_percentage"` @@ -433,21 +400,21 @@ type GeoSiteStatus struct { DependencyProxyManifestsVerifiedInPercentage string `json:"dependency_proxy_manifests_verified_in_percentage"` ProjectWikiRepositoriesSyncedInPercentage string `json:"project_wiki_repositories_synced_in_percentage"` ProjectWikiRepositoriesVerifiedInPercentage string `json:"project_wiki_repositories_verified_in_percentage"` - ReplicationSlotsCount int `json:"replication_slots_count"` - ReplicationSlotsUsedCount int `json:"replication_slots_used_count"` + ReplicationSlotsCount int64 `json:"replication_slots_count"` + ReplicationSlotsUsedCount int64 `json:"replication_slots_used_count"` Healthy bool `json:"healthy"` Health string `json:"health"` HealthStatus string `json:"health_status"` MissingOAuthApplication bool `json:"missing_oauth_application"` - DBReplicationLagSeconds int `json:"db_replication_lag_seconds"` - ReplicationSlotsMaxRetainedWalBytes int `json:"replication_slots_max_retained_wal_bytes"` - RepositoriesCheckedCount int `json:"repositories_checked_count"` - RepositoriesCheckedFailedCount int `json:"repositories_checked_failed_count"` - LastEventID int `json:"last_event_id"` - LastEventTimestamp int `json:"last_event_timestamp"` - CursorLastEventID int `json:"cursor_last_event_id"` - CursorLastEventTimestamp int `json:"cursor_last_event_timestamp"` - LastSuccessfulStatusCheckTimestamp int `json:"last_successful_status_check_timestamp"` + DBReplicationLagSeconds int64 `json:"db_replication_lag_seconds"` + ReplicationSlotsMaxRetainedWalBytes int64 `json:"replication_slots_max_retained_wal_bytes"` + RepositoriesCheckedCount int64 `json:"repositories_checked_count"` + RepositoriesCheckedFailedCount int64 `json:"repositories_checked_failed_count"` + LastEventID int64 `json:"last_event_id"` + LastEventTimestamp int64 `json:"last_event_timestamp"` + CursorLastEventID int64 `json:"cursor_last_event_id"` + CursorLastEventTimestamp int64 `json:"cursor_last_event_timestamp"` + LastSuccessfulStatusCheckTimestamp int64 `json:"last_successful_status_check_timestamp"` Version string `json:"version"` Revision string `json:"revision"` SelectiveSyncType string `json:"selective_sync_type"` @@ -460,7 +427,7 @@ type GeoSiteStatus struct { // GeoSiteStatusLink represents the links for a GitLab Geo Site status. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-all-geo-sites +// https://docs.gitlab.com/api/geo_sites/#list-all-geo-site-statuses type GeoSiteStatusLink struct { Self string `json:"self"` Site string `json:"site"` @@ -469,45 +436,22 @@ type GeoSiteStatusLink struct { // ListStatusOfAllGeoSitesOptions represents the available ListStatusOfAllGeoSites() options. // // GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-all-geo-sites -type ListStatusOfAllGeoSitesOptions ListOptions +// https://docs.gitlab.com/api/geo_sites/#list-all-geo-site-statuses +type ListStatusOfAllGeoSitesOptions struct { + ListOptions +} -// ListStatusOfAllGeoSites get the list of status of all Geo Sites. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-all-geo-sites func (s *GeoSitesService) ListStatusOfAllGeoSites(opt *ListStatusOfAllGeoSitesOptions, options ...RequestOptionFunc) ([]*GeoSiteStatus, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "geo_sites/status", nil, options) - if err != nil { - return nil, nil, err - } - - var statuses []*GeoSiteStatus - resp, err := s.client.Do(req, &statuses) - if err != nil { - return nil, resp, err - } - - return statuses, resp, nil + return do[[]*GeoSiteStatus](s.client, + withPath("geo_sites/status"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetStatusOfGeoSite get the of status of a specific Geo Sites. -// -// GitLab API docs: -// https://docs.gitlab.com/api/geo_sites/#retrieve-status-about-a-specific-geo-site -func (s *GeoSitesService) GetStatusOfGeoSite(id int, options ...RequestOptionFunc) (*GeoSiteStatus, *Response, error) { - u := fmt.Sprintf("geo_sites/%d/status", id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - status := new(GeoSiteStatus) - resp, err := s.client.Do(req, status) - if err != nil { - return nil, resp, err - } - - return status, resp, nil +func (s *GeoSitesService) GetStatusOfGeoSite(id int64, options ...RequestOptionFunc) (*GeoSiteStatus, *Response, error) { + return do[*GeoSiteStatus](s.client, + withPath("geo_sites/%d/status", id), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/gitignore_templates.go b/vendor/gitlab.com/gitlab-org/api/client-go/gitignore_templates.go index 7ffbede55..44b9b4778 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/gitignore_templates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/gitignore_templates.go @@ -16,12 +16,6 @@ package gitlab -import ( - "fmt" - "net/http" - "net/url" -) - type ( // GitIgnoreTemplatesServiceInterface defines all the API methods for the GitIgnoreTemplatesService GitIgnoreTemplatesServiceInterface interface { @@ -60,25 +54,20 @@ type GitIgnoreTemplateListItem struct { // // GitLab API docs: // https://docs.gitlab.com/api/templates/gitignores/#get-all-gitignore-templates -type ListTemplatesOptions ListOptions +type ListTemplatesOptions struct { + ListOptions +} // ListTemplates get a list of available git ignore templates // // GitLab API docs: // https://docs.gitlab.com/api/templates/gitignores/#get-all-gitignore-templates func (s *GitIgnoreTemplatesService) ListTemplates(opt *ListTemplatesOptions, options ...RequestOptionFunc) ([]*GitIgnoreTemplateListItem, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "templates/gitignores", opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*GitIgnoreTemplateListItem - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*GitIgnoreTemplateListItem](s.client, + withPath("templates/gitignores"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetTemplate get a git ignore template @@ -86,18 +75,8 @@ func (s *GitIgnoreTemplatesService) ListTemplates(opt *ListTemplatesOptions, opt // GitLab API docs: // https://docs.gitlab.com/api/templates/gitignores/#get-a-single-gitignore-template func (s *GitIgnoreTemplatesService) GetTemplate(key string, options ...RequestOptionFunc) (*GitIgnoreTemplate, *Response, error) { - u := fmt.Sprintf("templates/gitignores/%s", url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(GitIgnoreTemplate) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*GitIgnoreTemplate](s.client, + withPath("templates/gitignores/%s", key), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/gitlab.go b/vendor/gitlab.com/gitlab-org/api/client-go/gitlab.go index 0f86dd3e2..53ea1d447 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/gitlab.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/gitlab.go @@ -24,10 +24,12 @@ import ( "errors" "fmt" "io" + "log/slog" "maps" "math" - "math/rand" + "math/rand/v2" "mime/multipart" + "net" "net/http" "net/url" "sort" @@ -49,11 +51,11 @@ const ( apiVersionPath = "api/v4/" userAgent = "go-gitlab" - headerRateLimit = "RateLimit-Limit" - headerRateReset = "RateLimit-Reset" + headerRateLimit = "Ratelimit-Limit" + headerRateReset = "Ratelimit-Reset" - AccessTokenHeaderName = "PRIVATE-TOKEN" - JobTokenHeaderName = "JOB-TOKEN" + AccessTokenHeaderName = "Private-Token" + JobTokenHeaderName = "Job-Token" ) // AuthType represents an authentication type within GitLab. @@ -71,7 +73,28 @@ const ( PrivateToken ) -var ErrNotFound = errors.New("404 Not Found") +var ( + // ErrNotFound is returned for 404 Not Found errors + ErrNotFound = errors.New("404 Not Found") + + // errUnauthenticated is an internal sentinel error to indicate that the auth source doesn't use any authentication + errUnauthenticated = errors.New("unauthenticated") +) + +// URLValidationError wraps URL parsing errors with helpful context +type URLValidationError struct { + URL string + Err error + Hint string +} + +func (e *URLValidationError) Error() string { + msg := fmt.Sprintf("invalid base URL %q: %v", e.URL, e.Err) + if e.Hint != "" { + msg += fmt.Sprintf(" (hint: %s)", e.Hint) + } + return msg +} // A Client manages communication with the GitLab API. type Client struct { @@ -110,6 +133,9 @@ type Client struct { // which are used to decorate the http.Client#Transport value. interceptors []Interceptor + // urlWarningLogger is used to print URL validation warnings + urlWarningLogger *slog.Logger + // User agent used when communicating with the GitLab API. UserAgent string @@ -118,10 +144,12 @@ type Client struct { // Services used for talking to different parts of the GitLab API. AccessRequests AccessRequestsServiceInterface + AdminCompliancePolicySettings AdminCompliancePolicySettingsServiceInterface AlertManagement AlertManagementServiceInterface Appearance AppearanceServiceInterface Applications ApplicationsServiceInterface ApplicationStatistics ApplicationStatisticsServiceInterface + Attestations AttestationsServiceInterface AuditEvents AuditEventsServiceInterface Avatar AvatarRequestsServiceInterface AwardEmoji AwardEmojiServiceInterface @@ -165,6 +193,7 @@ type Client struct { GroupActivityAnalytics GroupActivityAnalyticsServiceInterface GroupBadges GroupBadgesServiceInterface GroupCluster GroupClustersServiceInterface + GroupCredentials GroupCredentialsServiceInterface GroupEpicBoards GroupEpicBoardsServiceInterface GroupImportExport GroupImportExportServiceInterface Integrations IntegrationsServiceInterface @@ -175,6 +204,8 @@ type Client struct { GroupMembers GroupMembersServiceInterface GroupMilestones GroupMilestonesServiceInterface GroupProtectedEnvironments GroupProtectedEnvironmentsServiceInterface + GroupProtectedBranches GroupProtectedBranchesServiceInterface + GroupRelationsExport GroupRelationsExportServiceInterface GroupReleases GroupReleasesServiceInterface GroupRepositoryStorageMove GroupRepositoryStorageMoveServiceInterface GroupSCIM GroupSCIMServiceInterface @@ -200,10 +231,12 @@ type Client struct { MemberRolesService MemberRolesServiceInterface MergeRequestApprovals MergeRequestApprovalsServiceInterface MergeRequestApprovalSettings MergeRequestApprovalSettingsServiceInterface + MergeRequestContextCommits MergeRequestContextCommitsServiceInterface MergeRequests MergeRequestsServiceInterface MergeTrains MergeTrainsServiceInterface Metadata MetadataServiceInterface Milestones MilestonesServiceInterface + ModelRegistry ModelRegistryServiceInterface Namespaces NamespacesServiceInterface Notes NotesServiceInterface NotificationSettings NotificationSettingsServiceInterface @@ -216,6 +249,7 @@ type Client struct { Pipelines PipelinesServiceInterface PlanLimits PlanLimitsServiceInterface ProjectAccessTokens ProjectAccessTokensServiceInterface + ProjectAliases ProjectAliasesServiceInterface ProjectBadges ProjectBadgesServiceInterface ProjectCluster ProjectClustersServiceInterface ProjectFeatureFlags ProjectFeatureFlagServiceInterface @@ -227,12 +261,14 @@ type Client struct { ProjectRepositoryStorageMove ProjectRepositoryStorageMoveServiceInterface ProjectSecuritySettings ProjectSecuritySettingsServiceInterface ProjectSnippets ProjectSnippetsServiceInterface + ProjectStatistics ProjectStatisticsServiceInterface ProjectTemplates ProjectTemplatesServiceInterface ProjectVariables ProjectVariablesServiceInterface ProjectVulnerabilities ProjectVulnerabilitiesServiceInterface Projects ProjectsServiceInterface ProtectedBranches ProtectedBranchesServiceInterface ProtectedEnvironments ProtectedEnvironmentsServiceInterface + ProtectedPackages ProtectedPackagesServiceInterface ProtectedTags ProtectedTagsServiceInterface ReleaseLinks ReleaseLinksServiceInterface Releases ReleasesServiceInterface @@ -245,6 +281,9 @@ type Client struct { ResourceMilestoneEvents ResourceMilestoneEventsServiceInterface ResourceStateEvents ResourceStateEventsServiceInterface ResourceWeightEvents ResourceWeightEventsServiceInterface + RunnerControllers RunnerControllersServiceInterface + RunnerControllerScopes RunnerControllerScopesServiceInterface + RunnerControllerTokens RunnerControllerTokensServiceInterface Runners RunnersServiceInterface Search SearchServiceInterface SecureFiles SecureFilesServiceInterface @@ -263,6 +302,7 @@ type Client struct { Validate ValidateServiceInterface Version VersionServiceInterface Wikis WikisServiceInterface + WorkItems WorkItemsServiceInterface } // Interceptor is used to build a *http.Client request pipeline, @@ -297,9 +337,9 @@ type ListOptions struct { // For keyset-based paginated result sets, the value must be `"keyset"` Pagination string `url:"pagination,omitempty" json:"pagination,omitempty"` // For offset-based and keyset-based paginated result sets, the number of results to include per page. - PerPage int `url:"per_page,omitempty" json:"per_page,omitempty"` + PerPage int64 `url:"per_page,omitempty" json:"per_page,omitempty"` // For offset-based paginated result sets, page of results to retrieve. - Page int `url:"page,omitempty" json:"page,omitempty"` + Page int64 `url:"page,omitempty" json:"page,omitempty"` // For keyset-based paginated result sets, tree record ID at which to fetch the next page. PageToken string `url:"page_token,omitempty" json:"page_token,omitempty"` // For keyset-based paginated result sets, name of the column by which to order @@ -367,8 +407,9 @@ func NewOAuthClient(token string, options ...ClientOptionFunc) (*Client, error) // NewAuthSourceClient returns a new GitLab API client that uses the AuthSource for authentication. func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, error) { c := &Client{ - UserAgent: userAgent, - authSource: as, + UserAgent: userAgent, + authSource: as, + urlWarningLogger: slog.Default(), } // Configure the HTTP client. @@ -425,10 +466,12 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e // Create all the public services. c.AccessRequests = &AccessRequestsService{client: c} + c.AdminCompliancePolicySettings = &AdminCompliancePolicySettingsService{client: c} c.AlertManagement = &AlertManagementService{client: c} c.Appearance = &AppearanceService{client: c} c.Applications = &ApplicationsService{client: c} c.ApplicationStatistics = &ApplicationStatisticsService{client: c} + c.Attestations = &AttestationsService{client: c} c.AuditEvents = &AuditEventsService{client: c} c.Avatar = &AvatarRequestsService{client: c} c.AwardEmoji = &AwardEmojiService{client: c} @@ -472,6 +515,7 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.GroupActivityAnalytics = &GroupActivityAnalyticsService{client: c} c.GroupBadges = &GroupBadgesService{client: c} c.GroupCluster = &GroupClustersService{client: c} + c.GroupCredentials = &GroupCredentialsService{client: c} c.GroupEpicBoards = &GroupEpicBoardsService{client: c} c.GroupImportExport = &GroupImportExportService{client: c} c.Integrations = &IntegrationsService{client: c} @@ -482,6 +526,8 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.GroupMembers = &GroupMembersService{client: c} c.GroupMilestones = &GroupMilestonesService{client: c} c.GroupProtectedEnvironments = &GroupProtectedEnvironmentsService{client: c} + c.GroupProtectedBranches = &GroupProtectedBranchesService{client: c} + c.GroupRelationsExport = &GroupRelationsExportService{client: c} c.GroupReleases = &GroupReleasesService{client: c} c.GroupRepositoryStorageMove = &GroupRepositoryStorageMoveService{client: c} c.GroupSCIM = &GroupSCIMService{client: c} @@ -507,10 +553,12 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.MemberRolesService = &MemberRolesService{client: c} c.MergeRequestApprovals = &MergeRequestApprovalsService{client: c} c.MergeRequestApprovalSettings = &MergeRequestApprovalSettingsService{client: c} + c.MergeRequestContextCommits = &MergeRequestContextCommitsService{client: c} c.MergeRequests = &MergeRequestsService{client: c, timeStats: timeStats} c.MergeTrains = &MergeTrainsService{client: c} c.Metadata = &MetadataService{client: c} c.Milestones = &MilestonesService{client: c} + c.ModelRegistry = &ModelRegistryService{client: c} c.Namespaces = &NamespacesService{client: c} c.Notes = &NotesService{client: c} c.NotificationSettings = &NotificationSettingsService{client: c} @@ -523,6 +571,7 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.Pipelines = &PipelinesService{client: c} c.PlanLimits = &PlanLimitsService{client: c} c.ProjectAccessTokens = &ProjectAccessTokensService{client: c} + c.ProjectAliases = &ProjectAliasesService{client: c} c.ProjectBadges = &ProjectBadgesService{client: c} c.ProjectCluster = &ProjectClustersService{client: c} c.ProjectFeatureFlags = &ProjectFeatureFlagService{client: c} @@ -534,12 +583,14 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.ProjectRepositoryStorageMove = &ProjectRepositoryStorageMoveService{client: c} c.ProjectSecuritySettings = &ProjectSecuritySettingsService{client: c} c.ProjectSnippets = &ProjectSnippetsService{client: c} + c.ProjectStatistics = &ProjectStatisticsService{client: c} c.ProjectTemplates = &ProjectTemplatesService{client: c} c.ProjectVariables = &ProjectVariablesService{client: c} c.ProjectVulnerabilities = &ProjectVulnerabilitiesService{client: c} c.Projects = &ProjectsService{client: c} c.ProtectedBranches = &ProtectedBranchesService{client: c} c.ProtectedEnvironments = &ProtectedEnvironmentsService{client: c} + c.ProtectedPackages = &ProtectedPackagesService{client: c} c.ProtectedTags = &ProtectedTagsService{client: c} c.ReleaseLinks = &ReleaseLinksService{client: c} c.Releases = &ReleasesService{client: c} @@ -552,6 +603,9 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.ResourceMilestoneEvents = &ResourceMilestoneEventsService{client: c} c.ResourceStateEvents = &ResourceStateEventsService{client: c} c.ResourceWeightEvents = &ResourceWeightEventsService{client: c} + c.RunnerControllers = &RunnerControllersService{client: c} + c.RunnerControllerScopes = &RunnerControllerScopesService{client: c} + c.RunnerControllerTokens = &RunnerControllerTokensService{client: c} c.Runners = &RunnersService{client: c} c.Search = &SearchService{client: c} c.SecureFiles = &SecureFilesService{client: c} @@ -570,6 +624,7 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e c.Validate = &ValidateService{client: c} c.Version = &VersionService{client: c} c.Wikis = &WikisService{client: c} + c.WorkItems = &WorkItemsService{client: c} return c, nil } @@ -593,17 +648,100 @@ func (c *Client) HTTPClient() *http.Client { } // retryHTTPCheck provides a callback for Client.CheckRetry which -// will retry both rate limit (429) and server (>= 500) errors. +// respects default retries and retries what is safe to retry. func (c *Client) retryHTTPCheck(ctx context.Context, resp *http.Response, err error) (bool, error) { + // do not retry if retries are disabled completely + if c.disableRetries { + return false, nil + } + + // do not retry on context.Canceled or context.DeadlineExceeded if ctx.Err() != nil { return false, ctx.Err() } + if err != nil { - return false, err + // We should be able to retry requests with assumed idempotent HTTP methods. + // In a future iteration we might want to annotate requests that are idempotent + // to further improve this logic here. + if resp != nil && resp.Request != nil { + switch resp.Request.Method { + case http.MethodConnect, http.MethodOptions, http.MethodTrace, http.MethodHead, http.MethodGet: + return true, nil + } + } + + // Only retry errors that we know happened before writing to the wire + var urlErr *url.Error + var netOpErr *net.OpError + var dnsErr *net.DNSError + // see Go src/net/http/transport.go + var potentialTLSHandshakeErr interface { + Timeout() bool + Temporary() bool + } + + switch { + // DNS errors are safe - they happen before any connection + case errors.As(err, &dnsErr): + // NXDOMAIN should not be retried + if dnsErr.IsNotFound { + return false, err + } + // Other DNS errors are safe to retry + return true, nil + + // Direct net.OpError for dial operations + case errors.As(err, &netOpErr): + // from the comments in the implementation of net.OpError.Temporary + // it seems that it's safe to retry temporary OpErrors. + if netOpErr.Temporary() { + return true, nil + } + + if strings.EqualFold(netOpErr.Op, "dial") { + return true, nil + } + + // Connection refused errors are safe - they happen at TCP establishment + case errors.As(err, &urlErr): + if strings.Contains(urlErr.Error(), "connection refused") { + return true, nil + } + + // TLS handshake errors are safe if we can identify them + case errors.As(err, &potentialTLSHandshakeErr): + // Check if this is a TLS handshake timeout specifically + if strings.Contains(err.Error(), "net/http: TLS handshake timeout") { + return true, nil + } + } + + // we are conservative here and do not want to retry any "unknown" errors, because + // they could have happened when the connection was already established and the request + // partially fulfilled. We don't have the insights here if the request + // was idempotent or not, so we reject a retry. + return false, nil + } + + // 429 Too Many Requests is recoverable. Sometimes the server puts + // a Retry-After response header to indicate when the server is + // available to start processing request from client. + if resp.StatusCode == http.StatusTooManyRequests { + return true, nil } - if !c.disableRetries && (resp.StatusCode == 429 || resp.StatusCode >= 500) { + + // Check the response code. We retry on 500-range responses to allow + // the server time to recover, as 500's are typically not permanent + // errors and may relate to outages on the server side. This will catch + // invalid response codes as well, like 0 and 999. + // Status code 0 is especially important for AWS ALB: + // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#response-code-000 + if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != http.StatusNotImplemented) { + // return true, fmt.Errorf("unexpected HTTP status %s", resp.Status) return true, nil } + return false, nil } @@ -623,18 +761,15 @@ func (c *Client) retryHTTPBackoff(min, max time.Duration, attemptNum int, resp * } // rateLimitBackoff provides a callback for Client.Backoff which will use the -// RateLimit-Reset header to determine the time to wait. We add some jitter +// Ratelimit-Reset header to determine the time to wait. We add some jitter // to prevent a thundering herd. // // min and max are mainly used for bounding the jitter that will be added to // the reset time retrieved from the headers. But if the final wait time is // less then min, min will be used instead. func rateLimitBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { - // rnd is used to generate pseudo-random numbers. - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // First create some jitter bounded by the min and max durations. - jitter := time.Duration(rnd.Float64() * float64(max-min)) + jitter := time.Duration(rand.Float64() * float64(max-min)) if resp != nil { if v := resp.Header.Get(headerRateReset); v != "" { @@ -645,7 +780,7 @@ func rateLimitBackoff(min, max time.Duration, attemptNum int, resp *http.Respons } } } else { - // In case the RateLimit-Reset header is not set, back off an additional + // In case the Ratelimit-Reset header is not set, back off an additional // 100% exponentially. With the default milliseconds being set to 100 for // `min`, this makes the 5th retry wait 3.2 seconds (3,200 ms) by default. min = time.Duration(float64(min) * math.Pow(2, float64(attemptNum))) @@ -692,16 +827,71 @@ func (c *Client) BaseURL() *url.URL { return &u } +// validateBaseURL checks for common real-world mistakes and returns them as errors. +// Returns the parsed URL if validation succeeds. +func validateBaseURL(baseURL string) (*url.URL, error) { + if baseURL == "" { + return nil, &URLValidationError{ + URL: baseURL, + Err: errors.New("empty URL"), + Hint: `provide a valid GitLab instance URL (e.g., "https://gitlab.com")`, + } + } + + if !strings.Contains(baseURL, "://") { + return nil, &URLValidationError{ + URL: baseURL, + Err: errors.New("missing scheme"), + Hint: fmt.Sprintf(`try "https://%s"`, baseURL), + } + } + + parsedURL, err := url.Parse(baseURL) + if err != nil { + return nil, &URLValidationError{ + URL: baseURL, + Err: err, + Hint: `possible issues: + - missing hostname + - invalid characters/spaces + - invalid port (must be 1-65535) + - query parameters (?) + - fragments (#) + - invalid URL encoding`, + } + } + + if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { + return nil, &URLValidationError{ + URL: baseURL, + Err: fmt.Errorf("unsupported scheme %q", parsedURL.Scheme), + Hint: fmt.Sprintf(`GitLab API requires http or https (try "https://%s")`, parsedURL.Host), + } + } + + return parsedURL, nil +} + // setBaseURL sets the base URL for API requests to a custom endpoint. func (c *Client) setBaseURL(urlStr string) error { - // Make sure the given URL end with a slash + // Make sure the given URL ends with a slash if !strings.HasSuffix(urlStr, "/") { urlStr += "/" } - baseURL, err := url.Parse(urlStr) + // Validate and parse + baseURL, err := validateBaseURL(urlStr) if err != nil { - return err + // Log the validation warning + c.urlWarningLogger.Warn("URL validation warning", "error", err) + + // Don't return the error - just warn and continue + // Try to parse anyway as a fallback + baseURL, err = url.Parse(urlStr) + if err != nil { + // If we really can't parse it, we have to give up + return fmt.Errorf("failed to parse base URL: %w", err) + } } if !strings.HasSuffix(baseURL.Path, apiVersionPath) { @@ -780,8 +970,12 @@ func (c *Client) NewRequestToURL(method string, u *url.URL, opt any, options []R } } - // Set the request specific headers. - maps.Copy(req.Header, reqHeaders) + // Set the request specific headers if they don't yet exist. + for k, v := range reqHeaders { + if _, ok := req.Header[k]; !ok { + req.Header[k] = v + } + } return req, nil } @@ -867,18 +1061,21 @@ type Response struct { *http.Response // Fields used for offset-based pagination. - TotalItems int - TotalPages int - ItemsPerPage int - CurrentPage int - NextPage int - PreviousPage int + TotalItems int64 + TotalPages int64 + ItemsPerPage int64 + CurrentPage int64 + NextPage int64 + PreviousPage int64 // Fields used for keyset-based pagination. PreviousLink string NextLink string FirstLink string LastLink string + + // GraphQL pagination. + PageInfo *PageInfo } // newResponse creates a new Response for the provided http.Response. @@ -909,28 +1106,28 @@ const ( // various pagination link values in the Response. func (r *Response) populatePageValues() { if totalItems := r.Header.Get(xTotal); totalItems != "" { - r.TotalItems, _ = strconv.Atoi(totalItems) + r.TotalItems, _ = strconv.ParseInt(totalItems, 10, 64) } if totalPages := r.Header.Get(xTotalPages); totalPages != "" { - r.TotalPages, _ = strconv.Atoi(totalPages) + r.TotalPages, _ = strconv.ParseInt(totalPages, 10, 64) } if itemsPerPage := r.Header.Get(xPerPage); itemsPerPage != "" { - r.ItemsPerPage, _ = strconv.Atoi(itemsPerPage) + r.ItemsPerPage, _ = strconv.ParseInt(itemsPerPage, 10, 64) } if currentPage := r.Header.Get(xPage); currentPage != "" { - r.CurrentPage, _ = strconv.Atoi(currentPage) + r.CurrentPage, _ = strconv.ParseInt(currentPage, 10, 64) } if nextPage := r.Header.Get(xNextPage); nextPage != "" { - r.NextPage, _ = strconv.Atoi(nextPage) + r.NextPage, _ = strconv.ParseInt(nextPage, 10, 64) } if previousPage := r.Header.Get(xPrevPage); previousPage != "" { - r.PreviousPage, _ = strconv.Atoi(previousPage) + r.PreviousPage, _ = strconv.ParseInt(previousPage, 10, 64) } } func (r *Response) populateLinkValues() { if link := r.Header.Get("Link"); link != "" { - for _, link := range strings.Split(link, ",") { + for link := range strings.SplitSeq(link, ",") { parts := strings.Split(link, ";") if len(parts) < 2 { continue @@ -973,14 +1170,17 @@ func (c *Client) Do(req *retryablehttp.Request, v any) (*Response, error) { } authKey, authValue, err := c.authSource.Header(req.Context()) - if err != nil { + switch err { + case nil: + if v := req.Header.Values(authKey); len(v) == 0 { + req.Header.Set(authKey, authValue) + } + case errUnauthenticated: //nolint:errorlint + // we simply skip using an auth header + default: // err != nil return nil, err } - if v := req.Header.Values(authKey); len(v) == 0 { - req.Header.Set(authKey, authValue) - } - client := c.client if cr := checkRetryFromContext(req.Context()); cr != nil { @@ -1045,6 +1245,8 @@ func parseID(id any) (string, error) { switch v := id.(type) { case int: return strconv.Itoa(v), nil + case int64: + return strconv.FormatInt(v, 10), nil case string: return v, nil default: @@ -1076,9 +1278,8 @@ func (e *ErrorResponse) Error() string { if e.Message == "" { return fmt.Sprintf("%s %s: %d", e.Response.Request.Method, url, e.Response.StatusCode) - } else { - return fmt.Sprintf("%s %s: %d %s", e.Response.Request.Method, url, e.Response.StatusCode, e.Message) } + return fmt.Sprintf("%s %s: %d %s", e.Response.Request.Method, url, e.Response.StatusCode, e.Message) } func (e *ErrorResponse) HasStatusCode(statusCode int) bool { @@ -1263,3 +1464,14 @@ func (as *PasswordCredentialsAuthSource) Init(ctx context.Context, client *Clien return nil } + +// Unauthenticated is an authentication source for unauthenticated clients +type Unauthenticated struct{} + +func (Unauthenticated) Init(context.Context, *Client) error { + return nil +} + +func (u Unauthenticated) Header(context.Context) (string, string, error) { + return "", "", errUnauthenticated +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/graphql.go b/vendor/gitlab.com/gitlab-org/api/client-go/graphql.go index 41c64d069..251c99827 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/graphql.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/graphql.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "net/http" + "regexp" + "strconv" "strings" ) @@ -22,7 +24,8 @@ type ( } GraphQLQuery struct { - Query string `json:"query"` + Query string `json:"query"` + Variables map[string]any `json:"variables,omitempty"` } GenericGraphQLErrors struct { @@ -86,7 +89,7 @@ func (g *GraphQL) Do(query GraphQLQuery, response any, options ...RequestOptionF resp, err := g.client.Do(request, response) if err != nil { // return error, details can be read from Response - if errResp, ok := err.(*ErrorResponse); ok { //nolint: errorlint + if errResp, ok := err.(*ErrorResponse); ok { //nolint:errorlint var v GenericGraphQLErrors if json.Unmarshal(errResp.Body, &v) == nil { return resp, &GraphQLResponseError{ @@ -99,3 +102,90 @@ func (g *GraphQL) Do(query GraphQLQuery, response any, options ...RequestOptionF } return resp, nil } + +// gidGQL is a global ID. It is used by GraphQL to uniquely identify resources. +type gidGQL struct { + Type string + Int64 int64 +} + +var gidGQLRegex = regexp.MustCompile(`^gid://gitlab/([^/]+)/(\d+)$`) + +func (id *gidGQL) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + m := gidGQLRegex.FindStringSubmatch(s) + if len(m) != 3 { + return fmt.Errorf("invalid global ID format: %q", s) + } + + i, err := strconv.ParseInt(m[2], 10, 64) + if err != nil { + return fmt.Errorf("failed parsing %q as numeric ID: %w", s, err) + } + + id.Type = m[1] + id.Int64 = i + + return nil +} + +func (id gidGQL) String() string { + return fmt.Sprintf("gid://gitlab/%s/%d", id.Type, id.Int64) +} + +// iidGQL represents an int64 ID that is encoded by GraphQL as a string. +// This type is used unmarshal the string response into an int64 type. +type iidGQL int64 + +func (id *iidGQL) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + i, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return fmt.Errorf("failed parsing %q as numeric ID: %w", s, err) + } + + *id = iidGQL(i) + return nil +} + +// PageInfo contains cursor-based pagination metadata for GraphQL connections following the Relay +// cursor pagination specification. Use EndCursor and HasNextPage for forward pagination +// (most common), or StartCursor and HasPreviousPage for backward pagination. +// +// Cursors are opaque strings that should not be parsed or constructed manually - always +// use the cursors returned by the API. +// +// Note: GraphQL cursor pagination differs from GitLab's REST API keyset pagination. +// In REST, the pagination link points to the first item of the next page. In GraphQL, +// EndCursor points to the last item of the current page - you pass this to the "after" +// parameter to fetch items after it (essentially an off-by-one difference in semantics). +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#pageinfo +type PageInfo struct { + EndCursor string `json:"endCursor"` // Cursor of the last item in this page (pass to "after" for next page) + HasNextPage bool `json:"hasNextPage"` // True if more items exist after this page + StartCursor string `json:"startCursor"` // Cursor of the first item in this page (pass to "before" for previous page) + HasPreviousPage bool `json:"hasPreviousPage"` // True if items exist before this page +} + +// connectionGQL represents a paginated GraphQL connection response following the Relay +// cursor pagination specification. It wraps a list of nodes of any type T along with +// pagination metadata. This type is used internally to unmarshal GraphQL responses from +// GitLab's API, which consistently uses this connection pattern for all paginated fields. +// +// The PageInfo field provides cursors and flags for iterating through pages, while Nodes +// contains the actual data items for the current page. +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#connection-fields +type connectionGQL[T any] struct { + PageInfo PageInfo `json:"pageInfo"` + Nodes []T `json:"nodes"` +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_access_tokens.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_access_tokens.go index 08946643d..755609d45 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_access_tokens.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_access_tokens.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -25,11 +24,11 @@ type ( // GroupAccessTokensServiceInterface defines all the API methods for the GroupAccessTokensService GroupAccessTokensServiceInterface interface { ListGroupAccessTokens(gid any, opt *ListGroupAccessTokensOptions, options ...RequestOptionFunc) ([]*GroupAccessToken, *Response, error) - GetGroupAccessToken(gid any, id int, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) + GetGroupAccessToken(gid any, id int64, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) CreateGroupAccessToken(gid any, opt *CreateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) - RotateGroupAccessToken(gid any, id int, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) + RotateGroupAccessToken(gid any, id int64, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) RotateGroupAccessTokenSelf(gid any, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) - RevokeGroupAccessToken(gid any, id int, options ...RequestOptionFunc) (*Response, error) + RevokeGroupAccessToken(gid any, id int64, options ...RequestOptionFunc) (*Response, error) } // GroupAccessTokensService handles communication with the @@ -68,6 +67,9 @@ type ListGroupAccessTokensOptions struct { Revoked *bool `url:"revoked,omitempty" json:"revoked,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` State *AccessTokenState `url:"state,omitempty" json:"state,omitempty"` + ExpiresAfter *ISOTime `url:"expires_after,omitempty" json:"expires_after,omitempty"` + ExpiresBefore *ISOTime `url:"expires_before,omitempty" json:"expires_before,omitempty"` + Sort *AccessTokenSort `url:"sort,omitempty" json:"sort,omitempty"` } // ListGroupAccessTokens gets a list of all group access tokens in a group. @@ -75,49 +77,25 @@ type ListGroupAccessTokensOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#list-all-group-access-tokens func (s *GroupAccessTokensService) ListGroupAccessTokens(gid any, opt *ListGroupAccessTokensOptions, options ...RequestOptionFunc) ([]*GroupAccessToken, *Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens", PathEscape(groups)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gats []*GroupAccessToken - resp, err := s.client.Do(req, &gats) - if err != nil { - return nil, resp, err - } - - return gats, resp, nil + return do[[]*GroupAccessToken](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/access_tokens", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupAccessToken gets a single group access tokens in a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#get-details-on-a-group-access-token -func (s *GroupAccessTokensService) GetGroupAccessToken(gid any, id int, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens/%d", PathEscape(groups), id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gat := new(GroupAccessToken) - resp, err := s.client.Do(req, &gat) - if err != nil { - return nil, resp, err - } - - return gat, resp, nil +func (s *GroupAccessTokensService) GetGroupAccessToken(gid any, id int64, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { + return do[*GroupAccessToken](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/access_tokens/%d", GroupID{gid}, id), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // CreateGroupAccessTokenOptions represents the available CreateVariable() @@ -138,24 +116,12 @@ type CreateGroupAccessTokenOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#create-a-group-access-token func (s *GroupAccessTokensService) CreateGroupAccessToken(gid any, opt *CreateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens", PathEscape(groups)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(GroupAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil + return do[*GroupAccessToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/access_tokens", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RotateGroupAccessTokenOptions represents the available RotateGroupAccessToken() @@ -172,24 +138,13 @@ type RotateGroupAccessTokenOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#rotate-a-group-access-token -func (s *GroupAccessTokensService) RotateGroupAccessToken(gid any, id int, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens/%d/rotate", PathEscape(groups), id) - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gat := new(GroupAccessToken) - resp, err := s.client.Do(req, gat) - if err != nil { - return nil, resp, err - } - - return gat, resp, nil +func (s *GroupAccessTokensService) RotateGroupAccessToken(gid any, id int64, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { + return do[*GroupAccessToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/access_tokens/%d/rotate", GroupID{gid}, id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RotateGroupAccessTokenSelf revokes the group access token used for the request @@ -198,40 +153,24 @@ func (s *GroupAccessTokensService) RotateGroupAccessToken(gid any, id int, opt * // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#self-rotate func (s *GroupAccessTokensService) RotateGroupAccessTokenSelf(gid any, opt *RotateGroupAccessTokenOptions, options ...RequestOptionFunc) (*GroupAccessToken, *Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens/self/rotate", PathEscape(groups)) - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gat := new(GroupAccessToken) - resp, err := s.client.Do(req, gat) - if err != nil { - return nil, resp, err - } - - return gat, resp, nil + return do[*GroupAccessToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/access_tokens/self/rotate", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RevokeGroupAccessToken revokes a group access token. // // GitLab API docs: // https://docs.gitlab.com/api/group_access_tokens/#revoke-a-group-access-token -func (s *GroupAccessTokensService) RevokeGroupAccessToken(gid any, id int, options ...RequestOptionFunc) (*Response, error) { - groups, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/access_tokens/%d", PathEscape(groups), id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupAccessTokensService) RevokeGroupAccessToken(gid any, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/access_tokens/%d", GroupID{gid}, id), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_activity_analytics.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_activity_analytics.go index 9824f4d63..3c5e9bea9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_activity_analytics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_activity_analytics.go @@ -18,8 +18,21 @@ import "net/http" type ( GroupActivityAnalyticsServiceInterface interface { + // GetRecentlyCreatedIssuesCount gets the count of recently created issues for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-issues-for-group GetRecentlyCreatedIssuesCount(opt *GetRecentlyCreatedIssuesCountOptions, options ...RequestOptionFunc) (*IssuesCount, *Response, error) + // GetRecentlyCreatedMergeRequestsCount gets the count of recently created merge + // requests for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-merge-requests-for-group GetRecentlyCreatedMergeRequestsCount(opt *GetRecentlyCreatedMergeRequestsCountOptions, options ...RequestOptionFunc) (*MergeRequestsCount, *Response, error) + // GetRecentlyAddedMembersCount gets the count of recently added members to a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-members-recently-added-to-group GetRecentlyAddedMembersCount(opt *GetRecentlyAddedMembersCountOptions, options ...RequestOptionFunc) (*NewMembersCount, *Response, error) } @@ -39,7 +52,7 @@ var _ GroupActivityAnalyticsServiceInterface = (*GroupActivityAnalyticsService)( // GitLab API docs: // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-issues-for-group type IssuesCount struct { - IssuesCount int `url:"issues_count" json:"issues_count"` + IssuesCount int64 `url:"issues_count" json:"issues_count"` } // GetRecentlyCreatedIssuesCountOptions represents the available @@ -51,24 +64,13 @@ type GetRecentlyCreatedIssuesCountOptions struct { GroupPath string `url:"group_path" json:"group_path"` } -// GetRecentlyCreatedIssuesCount gets the count of recently created issues for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-issues-for-group func (s *GroupActivityAnalyticsService) GetRecentlyCreatedIssuesCount(opt *GetRecentlyCreatedIssuesCountOptions, options ...RequestOptionFunc) (*IssuesCount, *Response, error) { - u := "analytics/group_activity/issues_count" - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - res := new(IssuesCount) - resp, err := s.client.Do(req, res) - if err != nil { - return nil, resp, err - } - - return res, resp, nil + return do[*IssuesCount](s.client, + withMethod(http.MethodGet), + withPath("analytics/group_activity/issues_count"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // MergeRequestsCount represents the total count of recently created merge requests @@ -77,7 +79,7 @@ func (s *GroupActivityAnalyticsService) GetRecentlyCreatedIssuesCount(opt *GetRe // GitLab API docs: // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-merge-requests-for-group type MergeRequestsCount struct { - MergeRequestsCount int `url:"merge_requests_count" json:"merge_requests_count"` + MergeRequestsCount int64 `url:"merge_requests_count" json:"merge_requests_count"` } // GetRecentlyCreatedMergeRequestsCountOptions represents the available @@ -89,25 +91,13 @@ type GetRecentlyCreatedMergeRequestsCountOptions struct { GroupPath string `url:"group_path" json:"group_path"` } -// GetRecentlyCreatedMergeRequestsCount gets the count of recently created merge -// requests for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-recently-created-merge-requests-for-group func (s *GroupActivityAnalyticsService) GetRecentlyCreatedMergeRequestsCount(opt *GetRecentlyCreatedMergeRequestsCountOptions, options ...RequestOptionFunc) (*MergeRequestsCount, *Response, error) { - u := "analytics/group_activity/merge_requests_count" - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - res := new(MergeRequestsCount) - resp, err := s.client.Do(req, res) - if err != nil { - return nil, resp, err - } - - return res, resp, nil + return do[*MergeRequestsCount](s.client, + withMethod(http.MethodGet), + withPath("analytics/group_activity/merge_requests_count"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // NewMembersCount represents the total count of recently added members to a group. @@ -115,7 +105,7 @@ func (s *GroupActivityAnalyticsService) GetRecentlyCreatedMergeRequestsCount(opt // GitLab API docs: // https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-members-recently-added-to-group type NewMembersCount struct { - NewMembersCount int `url:"new_members_count" json:"new_members_count"` + NewMembersCount int64 `url:"new_members_count" json:"new_members_count"` } // GetRecentlyAddedMembersCountOptions represents the available @@ -127,22 +117,11 @@ type GetRecentlyAddedMembersCountOptions struct { GroupPath string `url:"group_path" json:"group_path"` } -// GetRecentlyAddedMembersCount gets the count of recently added members to a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_activity_analytics/#get-count-of-members-recently-added-to-group func (s *GroupActivityAnalyticsService) GetRecentlyAddedMembersCount(opt *GetRecentlyAddedMembersCountOptions, options ...RequestOptionFunc) (*NewMembersCount, *Response, error) { - u := "analytics/group_activity/new_members_count" - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - res := new(NewMembersCount) - resp, err := s.client.Do(req, res) - if err != nil { - return nil, resp, err - } - - return res, resp, nil + return do[*NewMembersCount](s.client, + withMethod(http.MethodGet), + withPath("analytics/group_activity/new_members_count"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_badges.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_badges.go index b56c58264..614fe0249 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_badges.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_badges.go @@ -16,19 +16,16 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( // GroupBadgesServiceInterface defines all the API methods for the GroupBadgesService GroupBadgesServiceInterface interface { ListGroupBadges(gid any, opt *ListGroupBadgesOptions, options ...RequestOptionFunc) ([]*GroupBadge, *Response, error) - GetGroupBadge(gid any, badge int, options ...RequestOptionFunc) (*GroupBadge, *Response, error) + GetGroupBadge(gid any, badge int64, options ...RequestOptionFunc) (*GroupBadge, *Response, error) AddGroupBadge(gid any, opt *AddGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) - EditGroupBadge(gid any, badge int, opt *EditGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) - DeleteGroupBadge(gid any, badge int, options ...RequestOptionFunc) (*Response, error) + EditGroupBadge(gid any, badge int64, opt *EditGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) + DeleteGroupBadge(gid any, badge int64, options ...RequestOptionFunc) (*Response, error) PreviewGroupBadge(gid any, opt *GroupBadgePreviewOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) } @@ -57,7 +54,7 @@ const ( // GitLab API docs: // https://docs.gitlab.com/api/group_badges/ type GroupBadge struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` LinkURL string `json:"link_url"` ImageURL string `json:"image_url"` @@ -80,49 +77,22 @@ type ListGroupBadgesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#list-all-badges-of-a-group func (s *GroupBadgesService) ListGroupBadges(gid any, opt *ListGroupBadgesOptions, options ...RequestOptionFunc) ([]*GroupBadge, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/badges", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gb []*GroupBadge - resp, err := s.client.Do(req, &gb) - if err != nil { - return nil, resp, err - } - - return gb, resp, nil + return do[[]*GroupBadge](s.client, + withPath("groups/%s/badges", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupBadge gets a group badge. // // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#get-a-badge-of-a-group -func (s *GroupBadgesService) GetGroupBadge(gid any, badge int, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/badges/%d", PathEscape(group), badge) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gb := new(GroupBadge) - resp, err := s.client.Do(req, gb) - if err != nil { - return nil, resp, err - } - - return gb, resp, nil +func (s *GroupBadgesService) GetGroupBadge(gid any, badge int64, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { + return do[*GroupBadge](s.client, + withPath("groups/%s/badges/%d", GroupID{gid}, badge), + withRequestOpts(options...), + ) } // AddGroupBadgeOptions represents the available AddGroupBadge() options. @@ -140,24 +110,12 @@ type AddGroupBadgeOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#add-a-badge-to-a-group func (s *GroupBadgesService) AddGroupBadge(gid any, opt *AddGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/badges", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gb := new(GroupBadge) - resp, err := s.client.Do(req, gb) - if err != nil { - return nil, resp, err - } - - return gb, resp, nil + return do[*GroupBadge](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/badges", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditGroupBadgeOptions represents the available EditGroupBadge() options. @@ -174,44 +132,26 @@ type EditGroupBadgeOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#edit-a-badge-of-a-group -func (s *GroupBadgesService) EditGroupBadge(gid any, badge int, opt *EditGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/badges/%d", PathEscape(group), badge) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gb := new(GroupBadge) - resp, err := s.client.Do(req, gb) - if err != nil { - return nil, resp, err - } - - return gb, resp, nil +func (s *GroupBadgesService) EditGroupBadge(gid any, badge int64, opt *EditGroupBadgeOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { + return do[*GroupBadge](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/badges/%d", GroupID{gid}, badge), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupBadge removes a badge from a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#remove-a-badge-from-a-group -func (s *GroupBadgesService) DeleteGroupBadge(gid any, badge int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/badges/%d", PathEscape(group), badge) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupBadgesService) DeleteGroupBadge(gid any, badge int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/badges/%d", GroupID{gid}, badge), + withRequestOpts(options...), + ) + return resp, err } // GroupBadgePreviewOptions represents the available PreviewGroupBadge() options. @@ -230,22 +170,9 @@ type GroupBadgePreviewOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_badges/#preview-a-badge-from-a-group func (s *GroupBadgesService) PreviewGroupBadge(gid any, opt *GroupBadgePreviewOptions, options ...RequestOptionFunc) (*GroupBadge, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/badges/render", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - gb := new(GroupBadge) - resp, err := s.client.Do(req, &gb) - if err != nil { - return nil, resp, err - } - - return gb, resp, nil + return do[*GroupBadge](s.client, + withPath("groups/%s/badges/render", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_boards.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_boards.go index c5d7e77d2..63f0986c4 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_boards.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_boards.go @@ -17,22 +17,58 @@ package gitlab import ( - "fmt" "net/http" ) type ( GroupIssueBoardsServiceInterface interface { + // ListGroupIssueBoards gets a list of all issue boards in a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#list-all-group-issue-boards-in-a-group ListGroupIssueBoards(gid any, opt *ListGroupIssueBoardsOptions, options ...RequestOptionFunc) ([]*GroupIssueBoard, *Response, error) + // CreateGroupIssueBoard creates a new issue board. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#create-a-group-issue-board CreateGroupIssueBoard(gid any, opt *CreateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) - GetGroupIssueBoard(gid any, board int, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) - UpdateIssueBoard(gid any, board int, opt *UpdateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) - DeleteIssueBoard(gid any, board int, options ...RequestOptionFunc) (*Response, error) - ListGroupIssueBoardLists(gid any, board int, opt *ListGroupIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) - GetGroupIssueBoardList(gid any, board, list int, options ...RequestOptionFunc) (*BoardList, *Response, error) - CreateGroupIssueBoardList(gid any, board int, opt *CreateGroupIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) - UpdateIssueBoardList(gid any, board, list int, opt *UpdateGroupIssueBoardListOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) - DeleteGroupIssueBoardList(gid any, board, list int, options ...RequestOptionFunc) (*Response, error) + // GetGroupIssueBoard gets a single issue board of a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#single-group-issue-board + GetGroupIssueBoard(gid any, board int64, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) + // UpdateIssueBoard updates a single issue board of a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#update-a-group-issue-board + UpdateIssueBoard(gid any, board int64, opt *UpdateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) + // DeleteIssueBoard deletes a single issue board of a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#delete-a-group-issue-board + DeleteIssueBoard(gid any, board int64, options ...RequestOptionFunc) (*Response, error) + // ListGroupIssueBoardLists gets a list of the issue board's lists. Does not include + // backlog and closed lists. + // + // GitLab API docs: https://docs.gitlab.com/api/group_boards/#list-group-issue-board-lists + ListGroupIssueBoardLists(gid any, board int64, opt *ListGroupIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) + // GetGroupIssueBoardList gets a single issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#single-group-issue-board-list + GetGroupIssueBoardList(gid any, board, list int64, options ...RequestOptionFunc) (*BoardList, *Response, error) + // CreateGroupIssueBoardList creates a new issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#new-group-issue-board-list + CreateGroupIssueBoardList(gid any, board int64, opt *CreateGroupIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) + // UpdateIssueBoardList updates the position of an existing + // group issue board list. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_boards/#edit-group-issue-board-list + UpdateIssueBoardList(gid any, board, list int64, opt *UpdateGroupIssueBoardListOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) + DeleteGroupIssueBoardList(gid any, board, list int64, options ...RequestOptionFunc) (*Response, error) } // GroupIssueBoardsService handles communication with the group issue board @@ -52,7 +88,7 @@ var _ GroupIssueBoardsServiceInterface = (*GroupIssueBoardsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/group_boards/ type GroupIssueBoard struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Group *Group `json:"group"` Milestone *Milestone `json:"milestone"` @@ -69,31 +105,17 @@ func (b GroupIssueBoard) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/group_boards/#list-all-group-issue-boards-in-a-group -type ListGroupIssueBoardsOptions ListOptions +type ListGroupIssueBoardsOptions struct { + ListOptions +} -// ListGroupIssueBoards gets a list of all issue boards in a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#list-all-group-issue-boards-in-a-group func (s *GroupIssueBoardsService) ListGroupIssueBoards(gid any, opt *ListGroupIssueBoardsOptions, options ...RequestOptionFunc) ([]*GroupIssueBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*GroupIssueBoard - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*GroupIssueBoard](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/boards", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateGroupIssueBoardOptions represents the available @@ -105,54 +127,21 @@ type CreateGroupIssueBoardOptions struct { Name *string `url:"name" json:"name"` } -// CreateGroupIssueBoard creates a new issue board. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#create-a-group-issue-board func (s *GroupIssueBoardsService) CreateGroupIssueBoard(gid any, opt *CreateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gib := new(GroupIssueBoard) - resp, err := s.client.Do(req, gib) - if err != nil { - return nil, resp, err - } - - return gib, resp, nil + return do[*GroupIssueBoard](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/boards", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetGroupIssueBoard gets a single issue board of a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#single-group-issue-board -func (s *GroupIssueBoardsService) GetGroupIssueBoard(gid any, board int, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gib := new(GroupIssueBoard) - resp, err := s.client.Do(req, gib) - if err != nil { - return nil, resp, err - } - - return gib, resp, nil +func (s *GroupIssueBoardsService) GetGroupIssueBoard(gid any, board int64, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) { + return do[*GroupIssueBoard](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/boards/%d", GroupID{gid}, board), + withRequestOpts(options...), + ) } // UpdateGroupIssueBoardOptions represents a group issue board. @@ -161,54 +150,28 @@ func (s *GroupIssueBoardsService) GetGroupIssueBoard(gid any, board int, options // https://docs.gitlab.com/api/group_boards/#update-a-group-issue-board type UpdateGroupIssueBoardOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` - Weight *int `url:"weight,omitempty" json:"weight,omitempty"` + Weight *int64 `url:"weight,omitempty" json:"weight,omitempty"` } -// UpdateIssueBoard updates a single issue board of a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#update-a-group-issue-board -func (s *GroupIssueBoardsService) UpdateIssueBoard(gid any, board int, opt *UpdateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gib := new(GroupIssueBoard) - resp, err := s.client.Do(req, gib) - if err != nil { - return nil, resp, err - } - - return gib, resp, nil +func (s *GroupIssueBoardsService) UpdateIssueBoard(gid any, board int64, opt *UpdateGroupIssueBoardOptions, options ...RequestOptionFunc) (*GroupIssueBoard, *Response, error) { + return do[*GroupIssueBoard](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/boards/%d", GroupID{gid}, board), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteIssueBoard delete a single issue board of a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#delete-a-group-issue-board -func (s *GroupIssueBoardsService) DeleteIssueBoard(gid any, board int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupIssueBoardsService) DeleteIssueBoard(gid any, board int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/boards/%d", GroupID{gid}, board), + withRequestOpts(options...), + ) + return resp, err } // ListGroupIssueBoardListsOptions represents the available @@ -216,60 +179,25 @@ func (s *GroupIssueBoardsService) DeleteIssueBoard(gid any, board int, options . // // GitLab API docs: // https://docs.gitlab.com/api/group_boards/#list-group-issue-board-lists -type ListGroupIssueBoardListsOptions ListOptions - -// ListGroupIssueBoardLists gets a list of the issue board's lists. Does not include -// backlog and closed lists. -// -// GitLab API docs: https://docs.gitlab.com/api/group_boards/#list-group-issue-board-lists -func (s *GroupIssueBoardsService) ListGroupIssueBoardLists(gid any, board int, opt *ListGroupIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d/lists", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gbl []*BoardList - resp, err := s.client.Do(req, &gbl) - if err != nil { - return nil, resp, err - } - - return gbl, resp, nil +type ListGroupIssueBoardListsOptions struct { + ListOptions } -// GetGroupIssueBoardList gets a single issue board list. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#single-group-issue-board-list -func (s *GroupIssueBoardsService) GetGroupIssueBoardList(gid any, board, list int, options ...RequestOptionFunc) (*BoardList, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d/lists/%d", - PathEscape(group), - board, - list, +func (s *GroupIssueBoardsService) ListGroupIssueBoardLists(gid any, board int64, opt *ListGroupIssueBoardListsOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { + return do[[]*BoardList](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/boards/%d/lists", GroupID{gid}, board), + withAPIOpts(opt), + withRequestOpts(options...), ) +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gbl := new(BoardList) - resp, err := s.client.Do(req, gbl) - if err != nil { - return nil, resp, err - } - - return gbl, resp, nil +func (s *GroupIssueBoardsService) GetGroupIssueBoardList(gid any, board, list int64, options ...RequestOptionFunc) (*BoardList, *Response, error) { + return do[*BoardList](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/boards/%d/lists/%d", GroupID{gid}, board, list), + withRequestOpts(options...), + ) } // CreateGroupIssueBoardListOptions represents the available @@ -278,32 +206,16 @@ func (s *GroupIssueBoardsService) GetGroupIssueBoardList(gid any, board, list in // GitLab API docs: // https://docs.gitlab.com/api/group_boards/#new-group-issue-board-list type CreateGroupIssueBoardListOptions struct { - LabelID *int `url:"label_id" json:"label_id"` + LabelID *int64 `url:"label_id" json:"label_id"` } -// CreateGroupIssueBoardList creates a new issue board list. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#new-group-issue-board-list -func (s *GroupIssueBoardsService) CreateGroupIssueBoardList(gid any, board int, opt *CreateGroupIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d/lists", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gbl := new(BoardList) - resp, err := s.client.Do(req, gbl) - if err != nil { - return nil, resp, err - } - - return gbl, resp, nil +func (s *GroupIssueBoardsService) CreateGroupIssueBoardList(gid any, board int64, opt *CreateGroupIssueBoardListOptions, options ...RequestOptionFunc) (*BoardList, *Response, error) { + return do[*BoardList](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/boards/%d/lists", GroupID{gid}, board), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateGroupIssueBoardListOptions represents the available @@ -312,59 +224,23 @@ func (s *GroupIssueBoardsService) CreateGroupIssueBoardList(gid any, board int, // GitLab API docs: // https://docs.gitlab.com/api/group_boards/#edit-group-issue-board-list type UpdateGroupIssueBoardListOptions struct { - Position *int `url:"position" json:"position"` + Position *int64 `url:"position" json:"position"` } -// UpdateIssueBoardList updates the position of an existing -// group issue board list. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#edit-group-issue-board-list -func (s *GroupIssueBoardsService) UpdateIssueBoardList(gid any, board, list int, opt *UpdateGroupIssueBoardListOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d/lists/%d", - PathEscape(group), - board, - list, +func (s *GroupIssueBoardsService) UpdateIssueBoardList(gid any, board, list int64, opt *UpdateGroupIssueBoardListOptions, options ...RequestOptionFunc) ([]*BoardList, *Response, error) { + return do[[]*BoardList](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/boards/%d/lists/%d", GroupID{gid}, board, list), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gbl []*BoardList - resp, err := s.client.Do(req, &gbl) - if err != nil { - return nil, resp, err - } - - return gbl, resp, nil } -// DeleteGroupIssueBoardList soft deletes a group issue board list. -// Only for admins and group owners. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_boards/#delete-a-group-issue-board-list -func (s *GroupIssueBoardsService) DeleteGroupIssueBoardList(gid any, board, list int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/boards/%d/lists/%d", - PathEscape(group), - board, - list, +func (s *GroupIssueBoardsService) DeleteGroupIssueBoardList(gid any, board, list int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/boards/%d/lists/%d", GroupID{gid}, board, list), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_clusters.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_clusters.go index 145f56ea4..7bb5e4f92 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_clusters.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_clusters.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -28,13 +27,13 @@ type ( // Deprecated: in GitLab 14.5, to be removed in 19.0 ListClusters(pid any, options ...RequestOptionFunc) ([]*GroupCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - GetCluster(pid any, cluster int, options ...RequestOptionFunc) (*GroupCluster, *Response, error) + GetCluster(pid any, cluster int64, options ...RequestOptionFunc) (*GroupCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 AddCluster(pid any, opt *AddGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - EditCluster(pid any, cluster int, opt *EditGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) + EditCluster(pid any, cluster int64, opt *EditGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - DeleteCluster(pid any, cluster int, options ...RequestOptionFunc) (*Response, error) + DeleteCluster(pid any, cluster int64, options ...RequestOptionFunc) (*Response, error) } // GroupClustersService handles communication with the @@ -56,7 +55,7 @@ var _ GroupClustersServiceInterface = (*GroupClustersService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/group_clusters/ type GroupCluster struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Domain string `json:"domain"` CreatedAt *time.Time `json:"created_at"` @@ -83,24 +82,10 @@ func (v GroupCluster) String() string { // GitLab API docs: // https://docs.gitlab.com/api/group_clusters/#list-group-clusters func (s *GroupClustersService) ListClusters(pid any, options ...RequestOptionFunc) ([]*GroupCluster, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/clusters", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var pcs []*GroupCluster - resp, err := s.client.Do(req, &pcs) - if err != nil { - return nil, resp, err - } - - return pcs, resp, nil + return do[[]*GroupCluster](s.client, + withPath("groups/%s/clusters", GroupID{pid}), + withRequestOpts(options...), + ) } // GetCluster gets a cluster. @@ -108,25 +93,11 @@ func (s *GroupClustersService) ListClusters(pid any, options ...RequestOptionFun // // GitLab API docs: // https://docs.gitlab.com/api/group_clusters/#get-a-single-group-cluster -func (s *GroupClustersService) GetCluster(pid any, cluster int, options ...RequestOptionFunc) (*GroupCluster, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/clusters/%d", PathEscape(group), cluster) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gc := new(GroupCluster) - resp, err := s.client.Do(req, &gc) - if err != nil { - return nil, resp, err - } - - return gc, resp, nil +func (s *GroupClustersService) GetCluster(pid any, cluster int64, options ...RequestOptionFunc) (*GroupCluster, *Response, error) { + return do[*GroupCluster](s.client, + withPath("groups/%s/clusters/%d", GroupID{pid}, cluster), + withRequestOpts(options...), + ) } // AddGroupClusterOptions represents the available AddCluster() options. @@ -160,24 +131,12 @@ type AddGroupPlatformKubernetesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_clusters/#add-existing-cluster-to-group func (s *GroupClustersService) AddCluster(pid any, opt *AddGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/clusters/user", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gc := new(GroupCluster) - resp, err := s.client.Do(req, gc) - if err != nil { - return nil, resp, err - } - - return gc, resp, nil + return do[*GroupCluster](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/clusters/user", GroupID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditGroupClusterOptions represents the available EditCluster() options. @@ -206,25 +165,13 @@ type EditGroupPlatformKubernetesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_clusters/#edit-group-cluster -func (s *GroupClustersService) EditCluster(pid any, cluster int, opt *EditGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/clusters/%d", PathEscape(group), cluster) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gc := new(GroupCluster) - resp, err := s.client.Do(req, gc) - if err != nil { - return nil, resp, err - } - - return gc, resp, nil +func (s *GroupClustersService) EditCluster(pid any, cluster int64, opt *EditGroupClusterOptions, options ...RequestOptionFunc) (*GroupCluster, *Response, error) { + return do[*GroupCluster](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/clusters/%d", GroupID{pid}, cluster), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteCluster deletes an existing group cluster. @@ -232,17 +179,11 @@ func (s *GroupClustersService) EditCluster(pid any, cluster int, opt *EditGroupC // // GitLab API docs: // https://docs.gitlab.com/api/group_clusters/#delete-group-cluster -func (s *GroupClustersService) DeleteCluster(pid any, cluster int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/clusters/%d", PathEscape(group), cluster) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupClustersService) DeleteCluster(pid any, cluster int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/clusters/%d", GroupID{pid}, cluster), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_credentials.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_credentials.go new file mode 100644 index 000000000..bea0fff68 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_credentials.go @@ -0,0 +1,140 @@ +package gitlab + +import ( + "net/http" + "time" +) + +type ( + GroupCredentialsServiceInterface interface { + // ListGroupPersonalAccessTokens lists all personal access tokens + // associated with enterprise users in a top-level group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#list-all-personal-access-tokens-for-a-group + ListGroupPersonalAccessTokens(gid any, opt *ListGroupPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*GroupPersonalAccessToken, *Response, error) + // ListGroupSSHKeys lists all SSH public keys associated with + // enterprise users in a top-level group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#list-all-ssh-keys-for-a-group + ListGroupSSHKeys(gid any, opt *ListGroupSSHKeysOptions, options ...RequestOptionFunc) ([]*GroupSSHKey, *Response, error) + // RevokeGroupPersonalAccessToken revokes a specified personal access token + // for an enterprise user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#revoke-a-personal-access-token-for-an-enterprise-user + RevokeGroupPersonalAccessToken(gid any, tokenID int64, options ...RequestOptionFunc) (*Response, error) + // DeleteGroupSSHKey deletes a specified SSH public key for an + // enterprise user associated with the top-level group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#delete-an-ssh-key-for-an-enterprise-user + DeleteGroupSSHKey(gid any, keyID int64, options ...RequestOptionFunc) (*Response, error) + } + + // GroupCredentialsService handles communication with the top-level group + // credentials inventory management endpoints of the GitLab API. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#credentials-inventory-management + GroupCredentialsService struct { + client *Client + } +) + +// GroupPersonalAccessToken represents a group enterprise users personal access token. +// +// GitLab API docs: +// https://docs.gitlab.com/api/groups/#list-all-personal-access-tokens-for-a-group +type GroupPersonalAccessToken struct { + ID int64 `json:"id"` + Name string `json:"name"` + Revoked bool `json:"revoked"` + CreatedAt *time.Time `json:"created_at"` + Description string `json:"description"` + Scopes []string `json:"scopes"` + UserID int64 `json:"user_id"` + LastUsedAt *time.Time `json:"last_used_at,omitempty"` + Active bool `json:"active"` + ExpiresAt *ISOTime `json:"expires_at"` +} + +// ListGroupPersonalAccessTokensOptions represents the available +// ListGroupPersonalAccessTokens() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/groups/#list-all-personal-access-tokens-for-a-group +type ListGroupPersonalAccessTokensOptions struct { + ListOptions + CreatedAfter *ISOTime `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *ISOTime `url:"created_before,omitempty" json:"created_before,omitempty"` + LastUsedAfter *ISOTime `url:"last_used_after,omitempty" json:"last_used_after,omitempty"` + LastUsedBefore *ISOTime `url:"last_used_before,omitempty" json:"last_used_before,omitempty"` + Revoked *bool `url:"revoked,omitempty" json:"revoked,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` +} + +func (g *GroupCredentialsService) ListGroupPersonalAccessTokens(gid any, opt *ListGroupPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*GroupPersonalAccessToken, *Response, error) { + return do[[]*GroupPersonalAccessToken](g.client, + withMethod(http.MethodGet), + withPath("groups/%s/manage/personal_access_tokens", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// GroupSSHKey represents a group enterprise users public SSH key. +// +// GitLab API docs: +// https://docs.gitlab.com/api/groups/#list-all-ssh-keys-for-a-group +type GroupSSHKey struct { + ID int64 `json:"id"` + Title string `json:"title"` + CreatedAt *time.Time `json:"created_at"` + ExpiresAt *time.Time `json:"expires_at"` + LastUsedAt *time.Time `json:"last_used_at"` + UsageType string `json:"usage_type"` + UserID int64 `json:"user_id"` +} + +// ListGroupSSHKeysOptions represents the available +// ListGroupSSHKeys() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/groups/#list-all-ssh-keys-for-a-group +type ListGroupSSHKeysOptions struct { + ListOptions + CreatedAfter *ISOTime `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *ISOTime `url:"created_before,omitempty" json:"created_before,omitempty"` + ExpiresBefore *ISOTime `url:"expires_before,omitempty" json:"expires_before,omitempty"` + ExpiresAfter *ISOTime `url:"expires_after,omitempty" json:"expires_after,omitempty"` +} + +func (g *GroupCredentialsService) ListGroupSSHKeys(gid any, opt *ListGroupSSHKeysOptions, options ...RequestOptionFunc) ([]*GroupSSHKey, *Response, error) { + return do[[]*GroupSSHKey](g.client, + withMethod(http.MethodGet), + withPath("groups/%s/manage/ssh_keys", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (g *GroupCredentialsService) RevokeGroupPersonalAccessToken(gid any, tokenID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](g.client, + withMethod(http.MethodDelete), + withPath("groups/%s/manage/personal_access_tokens/%d", GroupID{gid}, tokenID), + withRequestOpts(options...), + ) + return resp, err +} + +func (g *GroupCredentialsService) DeleteGroupSSHKey(gid any, keyID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](g.client, + withMethod(http.MethodDelete), + withPath("groups/%s/manage/ssh_keys/%d", GroupID{gid}, keyID), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_epic_boards.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_epic_boards.go index 23097312e..d3dacf7df 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_epic_boards.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_epic_boards.go @@ -16,15 +16,10 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( GroupEpicBoardsServiceInterface interface { ListGroupEpicBoards(gid any, opt *ListGroupEpicBoardsOptions, options ...RequestOptionFunc) ([]*GroupEpicBoard, *Response, error) - GetGroupEpicBoard(gid any, board int, options ...RequestOptionFunc) (*GroupEpicBoard, *Response, error) + GetGroupEpicBoard(gid any, board int64, options ...RequestOptionFunc) (*GroupEpicBoard, *Response, error) } // GroupEpicBoardsService handles communication with the group epic board @@ -44,7 +39,7 @@ var _ GroupEpicBoardsServiceInterface = (*GroupEpicBoardsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/group_epic_boards/ type GroupEpicBoard struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Group *Group `json:"group"` Labels []*LabelDetails `json:"labels"` @@ -60,54 +55,29 @@ func (b GroupEpicBoard) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/group_epic_boards/#list-all-epic-boards-in-a-group -type ListGroupEpicBoardsOptions ListOptions +type ListGroupEpicBoardsOptions struct { + ListOptions +} // ListGroupEpicBoards gets a list of all epic boards in a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_epic_boards/#list-all-epic-boards-in-a-group func (s *GroupEpicBoardsService) ListGroupEpicBoards(gid any, opt *ListGroupEpicBoardsOptions, options ...RequestOptionFunc) ([]*GroupEpicBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epic_boards", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*GroupEpicBoard - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*GroupEpicBoard](s.client, + withPath("groups/%s/epic_boards", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupEpicBoard gets a single epic board of a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_epic_boards/#single-group-epic-board -func (s *GroupEpicBoardsService) GetGroupEpicBoard(gid any, board int, options ...RequestOptionFunc) (*GroupEpicBoard, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epic_boards/%d", PathEscape(group), board) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gib := new(GroupEpicBoard) - resp, err := s.client.Do(req, gib) - if err != nil { - return nil, resp, err - } - - return gib, resp, nil +func (s *GroupEpicBoardsService) GetGroupEpicBoard(gid any, board int64, options ...RequestOptionFunc) (*GroupEpicBoard, *Response, error) { + return do[*GroupEpicBoard](s.client, + withPath("groups/%s/epic_boards/%d", GroupID{gid}, board), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_hooks.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_hooks.go index cd7117c84..666ddb292 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_hooks.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_hooks.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -27,7 +26,7 @@ import ( // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/ type GroupHook struct { - ID int `json:"id"` + ID int64 `json:"id"` URL string `json:"url"` Name string `json:"name"` Description string `json:"description"` @@ -42,7 +41,7 @@ type GroupHook struct { BranchFilterStrategy string `json:"branch_filter_strategy"` CustomWebhookTemplate string `json:"custom_webhook_template"` CustomHeaders []*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` IssuesEvents bool `json:"issues_events"` ConfidentialIssuesEvents bool `json:"confidential_issues_events"` NoteEvents bool `json:"note_events"` @@ -57,80 +56,53 @@ type GroupHook struct { EmojiEvents bool `json:"emoji_events"` ResourceAccessTokenEvents bool `json:"resource_access_token_events"` MemberEvents bool `json:"member_events"` + ProjectEvents bool `json:"project_events"` + MilestoneEvents bool `json:"milestone_events"` + VulnerabilityEvents bool `json:"vulnerability_events"` } // ListGroupHooksOptions represents the available ListGroupHooks() options. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#list-group-hooks -type ListGroupHooksOptions ListOptions +type ListGroupHooksOptions struct { + ListOptions +} // ListGroupHooks gets a list of group hooks. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#list-group-hooks func (s *GroupsService) ListGroupHooks(gid any, opt *ListGroupHooksOptions, options ...RequestOptionFunc) ([]*GroupHook, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/hooks", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - var gh []*GroupHook - resp, err := s.client.Do(req, &gh) - if err != nil { - return nil, resp, err - } - - return gh, resp, nil + return do[[]*GroupHook](s.client, + withPath("groups/%s/hooks", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupHook gets a specific hook for a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#get-a-group-hook -func (s *GroupsService) GetGroupHook(gid any, hook int, options ...RequestOptionFunc) (*GroupHook, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d", PathEscape(group), hook) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gh := new(GroupHook) - resp, err := s.client.Do(req, gh) - if err != nil { - return nil, resp, err - } - - return gh, resp, nil +func (s *GroupsService) GetGroupHook(gid any, hook int64, options ...RequestOptionFunc) (*GroupHook, *Response, error) { + return do[*GroupHook](s.client, + withPath("groups/%s/hooks/%d", GroupID{gid}, hook), + withRequestOpts(options...), + ) } // ResendGroupHookEvent resends a specific hook event. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#resend-group-hook-event -func (s *GroupsService) ResendGroupHookEvent(gid any, hook int, hookEventID int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/events/%d/resend", PathEscape(group), hook, hookEventID) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) ResendGroupHookEvent(gid any, hook int64, hookEventID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/hooks/%d/events/%d/resend", GroupID{gid}, hook, hookEventID), + withRequestOpts(options...), + ) + return resp, err } // AddGroupHookOptions represents the available AddGroupHook() options. @@ -152,13 +124,16 @@ type AddGroupHookOptions struct { ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"` PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + ProjectEvents *bool `url:"project_events,omitempty" json:"project_events,omitempty"` WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"` FeatureFlagEvents *bool `url:"feature_flag_events,omitempty" json:"feature_flag_events,omitempty"` ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"` + MilestoneEvents *bool `url:"milestone_events,omitempty" json:"milestone_events,omitempty"` SubGroupEvents *bool `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"` EmojiEvents *bool `url:"emoji_events,omitempty" json:"emoji_events,omitempty"` MemberEvents *bool `url:"member_events,omitempty" json:"member_events,omitempty"` + VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"` EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` Token *string `url:"token,omitempty" json:"token,omitempty"` ResourceAccessTokenEvents *bool `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"` @@ -171,24 +146,12 @@ type AddGroupHookOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#add-a-group-hook func (s *GroupsService) AddGroupHook(gid any, opt *AddGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/hooks", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gh := new(GroupHook) - resp, err := s.client.Do(req, gh) - if err != nil { - return nil, resp, err - } - - return gh, resp, nil + return do[*GroupHook](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/hooks", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditGroupHookOptions represents the available EditGroupHook() options. @@ -210,13 +173,16 @@ type EditGroupHookOptions struct { ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"` PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + ProjectEvents *bool `url:"project_events,omitempty" json:"project_events,omitempty"` WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"` FeatureFlagEvents *bool `url:"feature_flag_events,omitempty" json:"feature_flag_events,omitempty"` ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"` + MilestoneEvents *bool `url:"milestone_events,omitempty" json:"milestone_events,omitempty"` SubGroupEvents *bool `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"` EmojiEvents *bool `url:"emoji_events,omitempty" json:"emoji_events,omitempty"` MemberEvents *bool `url:"member_events,omitempty" json:"member_events,omitempty"` + VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"` EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` ServiceAccessTokensExpirationEnforced *bool `url:"service_access_tokens_expiration_enforced,omitempty" json:"service_access_tokens_expiration_enforced,omitempty"` Token *string `url:"token,omitempty" json:"token,omitempty"` @@ -227,27 +193,15 @@ type EditGroupHookOptions struct { // EditGroupHook edits a hook for a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#edit-group-hook -func (s *GroupsService) EditGroupHook(gid any, hook int, opt *EditGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d", PathEscape(group), hook) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gh := new(GroupHook) - resp, err := s.client.Do(req, gh) - if err != nil { - return nil, resp, err - } - - return gh, resp, nil +func (s *GroupsService) EditGroupHook(gid any, hook int64, opt *EditGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) { + return do[*GroupHook](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/hooks/%d", GroupID{gid}, hook), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupHook removes a hook from a group. This is an idempotent @@ -255,76 +209,53 @@ func (s *GroupsService) EditGroupHook(gid any, hook int, opt *EditGroupHookOptio // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#delete-a-group-hook -func (s *GroupsService) DeleteGroupHook(gid any, hook int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d", PathEscape(group), hook) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) DeleteGroupHook(gid any, hook int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/hooks/%d", GroupID{gid}, hook), + withRequestOpts(options...), + ) + return resp, err } // TriggerTestGroupHook triggers a test hook for a specified group. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#trigger-a-test-group-hook -func (s *GroupsService) TriggerTestGroupHook(pid any, hook int, trigger GroupHookTrigger, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/test/%s", PathEscape(group), hook, trigger) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) TriggerTestGroupHook(pid any, hook int64, trigger GroupHookTrigger, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/hooks/%d/test/%s", GroupID{pid}, hook, NoEscape{string(trigger)}), + withRequestOpts(options...), + ) + return resp, err } // SetGroupCustomHeader creates or updates a group custom webhook header. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#set-a-custom-header -func (s *GroupsService) SetGroupCustomHeader(gid any, hook int, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/custom_headers/%s", PathEscape(group), hook, key) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) SetGroupCustomHeader(gid any, hook int64, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/hooks/%d/custom_headers/%s", GroupID{gid}, hook, NoEscape{key}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // DeleteGroupCustomHeader deletes a group custom webhook header. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#delete-a-custom-header -func (s *GroupsService) DeleteGroupCustomHeader(gid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/custom_headers/%s", PathEscape(group), hook, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) DeleteGroupCustomHeader(gid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/hooks/%d/custom_headers/%s", GroupID{gid}, hook, NoEscape{key}), + withRequestOpts(options...), + ) + return resp, err } // SetHookURLVariableOptions represents the available SetGroupHookURLVariable() @@ -340,36 +271,25 @@ type SetHookURLVariableOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#set-a-url-variable -func (s *GroupsService) SetGroupHookURLVariable(gid any, hook int, key string, opt *SetHookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/url_variables/%s", PathEscape(group), hook, key) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) SetGroupHookURLVariable(gid any, hook int64, key string, opt *SetHookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/hooks/%d/url_variables/%s", GroupID{gid}, hook, NoEscape{key}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // DeleteGroupHookURLVariable sets a group hook URL variable. // // GitLab API docs: // https://docs.gitlab.com/api/group_webhooks/#delete-a-url-variable -func (s *GroupsService) DeleteGroupHookURLVariable(gid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/hooks/%d/url_variables/%s", PathEscape(group), hook, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) DeleteGroupHookURLVariable(gid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/hooks/%d/url_variables/%s", GroupID{gid}, hook, NoEscape{key}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_import_export.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_import_export.go index 406480040..5b54c2fcd 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_import_export.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_import_export.go @@ -18,7 +18,7 @@ package gitlab import ( "bytes" - "fmt" + "errors" "io" "mime/multipart" "net/http" @@ -50,18 +50,13 @@ var _ GroupImportExportServiceInterface = (*GroupImportExportService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/group_import_export/#schedule-new-export func (s *GroupImportExportService) ScheduleExport(gid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/export", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/export", GroupID{gid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // ExportDownload downloads the finished export. @@ -69,24 +64,14 @@ func (s *GroupImportExportService) ScheduleExport(gid any, options ...RequestOpt // GitLab API docs: // https://docs.gitlab.com/api/group_import_export/#export-download func (s *GroupImportExportService) ExportDownload(gid any, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/export/download", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - exportDownload := new(bytes.Buffer) - resp, err := s.client.Do(req, exportDownload) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("groups/%s/export/download", GroupID{gid}), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return bytes.NewReader(exportDownload.Bytes()), resp, err + return bytes.NewReader(buf.Bytes()), resp, nil } // GroupImportFileOptions represents the available ImportFile() options. @@ -97,7 +82,7 @@ type GroupImportFileOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Path *string `url:"path,omitempty" json:"path,omitempty"` File *string `url:"file,omitempty" json:"file,omitempty"` - ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` + ParentID *int64 `url:"parent_id,omitempty" json:"parent_id,omitempty"` } // ImportFile imports a file. @@ -107,13 +92,13 @@ type GroupImportFileOptions struct { func (s *GroupImportExportService) ImportFile(opt *GroupImportFileOptions, options ...RequestOptionFunc) (*Response, error) { // First check if we got all required options. if opt.Name == nil || *opt.Name == "" { - return nil, fmt.Errorf("missing required option: Name") + return nil, errors.New("missing required option: Name") } if opt.Path == nil || *opt.Path == "" { - return nil, fmt.Errorf("missing required option: Path") + return nil, errors.New("missing required option: Path") } if opt.File == nil || *opt.File == "" { - return nil, fmt.Errorf("missing required option: File") + return nil, errors.New("missing required option: File") } f, err := os.Open(*opt.File) @@ -163,7 +148,7 @@ func (s *GroupImportExportService) ImportFile(opt *GroupImportFileOptions, optio return nil, err } - _, err = fw.Write([]byte(strconv.Itoa(*opt.ParentID))) + _, err = fw.Write([]byte(strconv.FormatInt(*opt.ParentID, 10))) if err != nil { return nil, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_integrations.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_integrations.go new file mode 100644 index 000000000..bf3f87e69 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_integrations.go @@ -0,0 +1,184 @@ +package gitlab + +import ( + "net/http" + "time" +) + +// GroupMattermostIntegration represents a Mattermost integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +type GroupMattermostIntegration struct { + Integration + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines"` + BranchesToBeNotified string `json:"branches_to_be_notified"` + LabelsToBeNotified string `json:"labels_to_be_notified"` + LabelsToBeNotifiedBehavior string `json:"labels_to_be_notified_behavior"` + NotifyOnlyDefaultBranch bool `json:"notify_only_default_branch"` + Properties *GroupMattermostIntegrationProperties `json:"properties"` +} + +type GroupMattermostIntegrationProperties struct { + WebHook string `json:"webhook"` + Username string `json:"username"` + Channel string `json:"channel"` + PushChannel string `json:"push_channel"` + IssueChannel string `json:"issue_channel"` + ConfidentialIssueChannel string `json:"confidential_issue_channel"` + MergeRequestChannel string `json:"merge_request_channel"` + NoteChannel string `json:"note_channel"` + ConfidentialNoteChannel string `json:"confidential_note_channel"` + TagPushChannel string `json:"tag_push_channel"` + PipelineChannel string `json:"pipeline_channel"` + WikiPageChannel string `json:"wiki_page_channel"` + DeploymentChannel string `json:"deployment_channel"` + AlertChannel string `json:"alert_channel"` + VulnerabilityChannel string `json:"vulnerability_channel"` +} + +// GroupMattermostIntegrationOptions represents the available options for +// creating or updating a Mattermost integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +type GroupMattermostIntegrationOptions struct { + WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Channel *string `url:"channel,omitempty" json:"channel,omitempty"` + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"` + AlertEvents *bool `url:"alert_events,omitempty" json:"alert_events,omitempty"` + VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"` + PushChannel *string `url:"push_channel,omitempty" json:"push_channel,omitempty"` + IssueChannel *string `url:"issue_channel,omitempty" json:"issue_channel,omitempty"` + ConfidentialIssueChannel *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"` + MergeRequestChannel *string `url:"merge_request_channel,omitempty" json:"merge_request_channel,omitempty"` + NoteChannel *string `url:"note_channel,omitempty" json:"note_channel,omitempty"` + ConfidentialNoteChannel *string `url:"confidential_note_channel,omitempty" json:"confidential_note_channel,omitempty"` + TagPushChannel *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"` + PipelineChannel *string `url:"pipeline_channel,omitempty" json:"pipeline_channel,omitempty"` + WikiPageChannel *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"` + DeploymentChannel *string `url:"deployment_channel,omitempty" json:"deployment_channel,omitempty"` + AlertChannel *string `url:"alert_channel,omitempty" json:"alert_channel,omitempty"` + VulnerabilityChannel *string `url:"vulnerability_channel,omitempty" json:"vulnerability_channel,omitempty"` + LabelsToBeNotified *string `url:"labels_to_be_notified,omitempty" json:"labels_to_be_notified,omitempty"` + LabelsToBeNotifiedBehavior *string `url:"labels_to_be_notified_behavior,omitempty" json:"labels_to_be_notified_behavior,omitempty"` + NotifyOnlyDefaultBranch *bool `url:"notify_only_default_branch,omitempty" json:"notify_only_default_branch,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} + +// GetGroupMattermostIntegration retrieves the Mattermost integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +func (s *IntegrationsService) GetGroupMattermostIntegration(gid any, options ...RequestOptionFunc) (*GroupMattermostIntegration, *Response, error) { + return do[*GroupMattermostIntegration]( + s.client, + withPath("groups/%s/integrations/mattermost", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +// SetGroupMattermostIntegration creates or updates the Mattermost integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +func (s *IntegrationsService) SetGroupMattermostIntegration(gid any, opt *GroupMattermostIntegrationOptions, options ...RequestOptionFunc) (*GroupMattermostIntegration, *Response, error) { + return do[*GroupMattermostIntegration]( + s.client, + withPath("groups/%s/integrations/mattermost", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// DeleteGroupMattermostIntegration removes the Mattermost integration from a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +func (s *IntegrationsService) DeleteGroupMattermostIntegration(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/mattermost", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} + +// GroupMattermostSlashCommandsIntegration represents a Mattermost slash commands integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands +type GroupMattermostSlashCommandsIntegration struct { + ID int `json:"id"` + Title string `json:"title"` + Slug string `json:"slug"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Token string `json:"token"` +} + +// GroupMattermostSlashCommandsIntegrationOptions represents the available options for +// creating or updating a Mattermost slash commands integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands +type GroupMattermostSlashCommandsIntegrationOptions struct { + Token *string `url:"token,omitempty" json:"token,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} + +// GetGroupMattermostSlashCommandsIntegration retrieves the Mattermost slash commands integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands +func (s *IntegrationsService) GetGroupMattermostSlashCommandsIntegration(gid any, options ...RequestOptionFunc) (*GroupMattermostSlashCommandsIntegration, *Response, error) { + return do[*GroupMattermostSlashCommandsIntegration]( + s.client, + withPath("groups/%s/integrations/mattermost-slash-commands", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +// SetGroupMattermostSlashCommandsIntegration creates or updates the Mattermost slash commands integration for a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands +func (s *IntegrationsService) SetGroupMattermostSlashCommandsIntegration(gid any, opt *GroupMattermostSlashCommandsIntegrationOptions, options ...RequestOptionFunc) (*GroupMattermostSlashCommandsIntegration, *Response, error) { + return do[*GroupMattermostSlashCommandsIntegration]( + s.client, + withPath("groups/%s/integrations/mattermost-slash-commands", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// DeleteGroupMattermostSlashCommandsIntegration removes the Mattermost slash commands integration from a group. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands +func (s *IntegrationsService) DeleteGroupMattermostSlashCommandsIntegration(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/mattermost-slash-commands", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_iterations.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_iterations.go index 0a5e235e1..2b14b1bd0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_iterations.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_iterations.go @@ -16,11 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" - "time" -) +import "time" type ( GroupIterationsServiceInterface interface { @@ -42,13 +38,13 @@ var _ GroupIterationsServiceInterface = (*GroupIterationsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/group_iterations/ type GroupIteration struct { - ID int `json:"id"` - IID int `json:"iid"` - Sequence int `json:"sequence"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + Sequence int64 `json:"sequence"` + GroupID int64 `json:"group_id"` Title string `json:"title"` Description string `json:"description"` - State int `json:"state"` + State int64 `json:"state"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` DueDate *ISOTime `json:"due_date"` @@ -77,22 +73,9 @@ type ListGroupIterationsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_iterations/#list-group-iterations func (s *GroupIterationsService) ListGroupIterations(gid any, opt *ListGroupIterationsOptions, options ...RequestOptionFunc) ([]*GroupIteration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/iterations", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gis []*GroupIteration - resp, err := s.client.Do(req, &gis) - if err != nil { - return nil, nil, err - } - - return gis, resp, nil + return do[[]*GroupIteration](s.client, + withPath("groups/%s/iterations", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_labels.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_labels.go index 7bd4d1df8..838acda6c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_labels.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_labels.go @@ -16,10 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( GroupLabelsServiceInterface interface { @@ -57,11 +54,11 @@ func (l GroupLabel) String() string { // GitLab API docs: https://docs.gitlab.com/api/group_labels/#list-group-labels type ListGroupLabelsOptions struct { ListOptions - WithCounts *bool `url:"with_counts,omitempty" json:"with_counts,omitempty"` - IncludeAncestorGroups *bool `url:"include_ancestor_groups,omitempty" json:"include_ancestor_groups,omitempty"` - IncludeDescendantGrouops *bool `url:"include_descendant_groups,omitempty" json:"include_descendant_groups,omitempty"` - OnlyGroupLabels *bool `url:"only_group_labels,omitempty" json:"only_group_labels,omitempty"` - Search *string `url:"search,omitempty" json:"search,omitempty"` + WithCounts *bool `url:"with_counts,omitempty" json:"with_counts,omitempty"` + IncludeAncestorGroups *bool `url:"include_ancestor_groups,omitempty" json:"include_ancestor_groups,omitempty"` + IncludeDescendantGroups *bool `url:"include_descendant_groups,omitempty" json:"include_descendant_groups,omitempty"` + OnlyGroupLabels *bool `url:"only_group_labels,omitempty" json:"only_group_labels,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` } // ListGroupLabels gets all labels for given group. @@ -69,24 +66,11 @@ type ListGroupLabelsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#list-group-labels func (s *GroupLabelsService) ListGroupLabels(gid any, opt *ListGroupLabelsOptions, options ...RequestOptionFunc) ([]*GroupLabel, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/labels", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var l []*GroupLabel - resp, err := s.client.Do(req, &l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[[]*GroupLabel](s.client, + withPath("groups/%s/labels", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupLabel get a single label for a given group. @@ -94,28 +78,10 @@ func (s *GroupLabelsService) ListGroupLabels(gid any, opt *ListGroupLabelsOption // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#get-a-single-group-label func (s *GroupLabelsService) GetGroupLabel(gid any, lid any, options ...RequestOptionFunc) (*GroupLabel, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/labels/%s", PathEscape(group), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var l *GroupLabel - resp, err := s.client.Do(req, &l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*GroupLabel](s.client, + withPath("groups/%s/labels/%s", GroupID{gid}, LabelID{lid}), + withRequestOpts(options...), + ) } // CreateGroupLabelOptions represents the available CreateGroupLabel() options. @@ -126,7 +92,7 @@ type CreateGroupLabelOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Color *string `url:"color,omitempty" json:"color,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` - Priority *int `url:"priority,omitempty" json:"priority,omitempty"` + Priority *int64 `url:"priority,omitempty" json:"priority,omitempty"` } // CreateGroupLabel creates a new label for given group with given name and @@ -135,24 +101,12 @@ type CreateGroupLabelOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#create-a-new-group-label func (s *GroupLabelsService) CreateGroupLabel(gid any, opt *CreateGroupLabelOptions, options ...RequestOptionFunc) (*GroupLabel, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/labels", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - l := new(GroupLabel) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*GroupLabel](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/labels", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupLabelOptions represents the available DeleteGroupLabel() options. @@ -168,26 +122,21 @@ type DeleteGroupLabelOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#delete-a-group-label func (s *GroupLabelsService) DeleteGroupLabel(gid any, lid any, opt *DeleteGroupLabelOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/labels", PathEscape(group)) + reqOpts := make([]doOption, 0, 4) + reqOpts = append(reqOpts, + withMethod(http.MethodDelete), + withAPIOpts(opt), + withRequestOpts(options...), + ) if lid != nil { - label, err := parseID(lid) - if err != nil { - return nil, err - } - u = fmt.Sprintf("groups/%s/labels/%s", PathEscape(group), PathEscape(label)) - } - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err + reqOpts = append(reqOpts, withPath("groups/%s/labels/%s", GroupID{gid}, LabelID{lid})) + } else { + reqOpts = append(reqOpts, withPath("groups/%s/labels", GroupID{gid})) } - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, reqOpts...) + return resp, err } // UpdateGroupLabelOptions represents the available UpdateGroupLabel() options. @@ -199,7 +148,7 @@ type UpdateGroupLabelOptions struct { NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"` Color *string `url:"color,omitempty" json:"color,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` - Priority *int `url:"priority,omitempty" json:"priority,omitempty"` + Priority *int64 `url:"priority,omitempty" json:"priority,omitempty"` } // UpdateGroupLabel updates an existing label with new name or now color. At least @@ -208,32 +157,20 @@ type UpdateGroupLabelOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#update-a-group-label func (s *GroupLabelsService) UpdateGroupLabel(gid any, lid any, opt *UpdateGroupLabelOptions, options ...RequestOptionFunc) (*GroupLabel, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/labels", PathEscape(group)) + reqOpts := make([]doOption, 0, 4) + reqOpts = append(reqOpts, + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) if lid != nil { - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u = fmt.Sprintf("groups/%s/labels/%s", PathEscape(group), PathEscape(label)) - } - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - l := new(GroupLabel) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err + reqOpts = append(reqOpts, withPath("groups/%s/labels/%s", GroupID{gid}, LabelID{lid})) + } else { + reqOpts = append(reqOpts, withPath("groups/%s/labels", GroupID{gid})) } - return l, resp, nil + return do[*GroupLabel](s.client, reqOpts...) } // SubscribeToGroupLabel subscribes the authenticated user to a label to receive @@ -243,28 +180,11 @@ func (s *GroupLabelsService) UpdateGroupLabel(gid any, lid any, opt *UpdateGroup // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#subscribe-to-a-group-label func (s *GroupLabelsService) SubscribeToGroupLabel(gid any, lid any, options ...RequestOptionFunc) (*GroupLabel, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/labels/%s/subscribe", PathEscape(group), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - l := new(GroupLabel) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*GroupLabel](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/labels/%s/subscribe", GroupID{gid}, LabelID{lid}), + withRequestOpts(options...), + ) } // UnsubscribeFromGroupLabel unsubscribes the authenticated user from a label to not @@ -274,20 +194,10 @@ func (s *GroupLabelsService) SubscribeToGroupLabel(gid any, lid any, options ... // GitLab API docs: // https://docs.gitlab.com/api/group_labels/#unsubscribe-from-a-group-label func (s *GroupLabelsService) UnsubscribeFromGroupLabel(gid any, lid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/labels/%s/unsubscribe", PathEscape(group), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/labels/%s/unsubscribe", GroupID{gid}, LabelID{lid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_markdown_uploads.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_markdown_uploads.go index 5c0afc849..6d12350a9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_markdown_uploads.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_markdown_uploads.go @@ -22,10 +22,32 @@ import ( type ( GroupMarkdownUploadsServiceInterface interface { + // ListGroupMarkdownUploads gets all markdown uploads for a group. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/group_markdown_uploads/#list-uploads ListGroupMarkdownUploads(gid any, opt *ListMarkdownUploadsOptions, options ...RequestOptionFunc) ([]*GroupMarkdownUpload, *Response, error) - DownloadGroupMarkdownUploadByID(gid any, uploadID int, options ...RequestOptionFunc) (io.Reader, *Response, error) + // DownloadGroupMarkdownUploadByID downloads a specific upload by ID. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/group_markdown_uploads/#download-an-uploaded-file-by-id + DownloadGroupMarkdownUploadByID(gid any, uploadID int64, options ...RequestOptionFunc) (io.Reader, *Response, error) + // DownloadGroupMarkdownUploadBySecretAndFilename downloads a specific upload + // by secret and filename. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/group_markdown_uploads/#download-an-uploaded-file-by-secret-and-filename DownloadGroupMarkdownUploadBySecretAndFilename(gid any, secret string, filename string, options ...RequestOptionFunc) (io.Reader, *Response, error) - DeleteGroupMarkdownUploadByID(gid any, uploadID int, options ...RequestOptionFunc) (*Response, error) + // DeleteGroupMarkdownUploadByID deletes an upload by ID. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/group_markdown_uploads/#delete-an-uploaded-file-by-id + DeleteGroupMarkdownUploadByID(gid any, uploadID int64, options ...RequestOptionFunc) (*Response, error) + // DeleteGroupMarkdownUploadBySecretAndFilename deletes an upload + // by secret and filename. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/group_markdown_uploads/#delete-an-uploaded-file-by-secret-and-filename DeleteGroupMarkdownUploadBySecretAndFilename(gid any, secret string, filename string, options ...RequestOptionFunc) (*Response, error) } @@ -46,52 +68,30 @@ type ( GroupMarkdownUpload = MarkdownUpload ) -// ListGroupMarkdownUploads gets all markdown uploads for a group. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/group_markdown_uploads/#list-uploads func (s *GroupMarkdownUploadsService) ListGroupMarkdownUploads(gid any, opt *ListMarkdownUploadsOptions, options ...RequestOptionFunc) ([]*GroupMarkdownUpload, *Response, error) { - return listMarkdownUploads[GroupMarkdownUpload](s.client, GroupResource, gid, opt, options) + return listMarkdownUploads[GroupMarkdownUpload](s.client, GroupResource, GroupID{gid}, opt, options) } -// DownloadGroupMarkdownUploadByID downloads a specific upload by ID. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/group_markdown_uploads/#download-an-uploaded-file-by-id -func (s *GroupMarkdownUploadsService) DownloadGroupMarkdownUploadByID(gid any, uploadID int, options ...RequestOptionFunc) (io.Reader, *Response, error) { - buffer, resp, err := downloadMarkdownUploadByID(s.client, GroupResource, gid, uploadID, options) +func (s *GroupMarkdownUploadsService) DownloadGroupMarkdownUploadByID(gid any, uploadID int64, options ...RequestOptionFunc) (io.Reader, *Response, error) { + buffer, resp, err := downloadMarkdownUploadByID(s.client, GroupResource, GroupID{gid}, uploadID, options) if err != nil { return nil, resp, err } return buffer, resp, nil } -// DownloadGroupMarkdownUploadBySecretAndFilename downloads a specific upload -// by secret and filename. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/group_markdown_uploads/#download-an-uploaded-file-by-secret-and-filename func (s *GroupMarkdownUploadsService) DownloadGroupMarkdownUploadBySecretAndFilename(gid any, secret string, filename string, options ...RequestOptionFunc) (io.Reader, *Response, error) { - buffer, resp, err := downloadMarkdownUploadBySecretAndFilename(s.client, GroupResource, gid, secret, filename, options) + buffer, resp, err := downloadMarkdownUploadBySecretAndFilename(s.client, GroupResource, GroupID{gid}, secret, filename, options) if err != nil { return nil, resp, err } return buffer, resp, nil } -// DeleteGroupMarkdownUploadByID deletes an upload by ID. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/group_markdown_uploads/#delete-an-uploaded-file-by-id -func (s *GroupMarkdownUploadsService) DeleteGroupMarkdownUploadByID(gid any, uploadID int, options ...RequestOptionFunc) (*Response, error) { - return deleteMarkdownUploadByID(s.client, GroupResource, gid, uploadID, options) +func (s *GroupMarkdownUploadsService) DeleteGroupMarkdownUploadByID(gid any, uploadID int64, options ...RequestOptionFunc) (*Response, error) { + return deleteMarkdownUploadByID(s.client, GroupResource, GroupID{gid}, uploadID, options) } -// DeleteGroupMarkdownUploadBySecretAndFilename deletes an upload -// by secret and filename. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/group_markdown_uploads/#delete-an-uploaded-file-by-secret-and-filename func (s *GroupMarkdownUploadsService) DeleteGroupMarkdownUploadBySecretAndFilename(gid any, secret string, filename string, options ...RequestOptionFunc) (*Response, error) { - return deleteMarkdownUploadBySecretAndFilename(s.client, GroupResource, gid, secret, filename, options) + return deleteMarkdownUploadBySecretAndFilename(s.client, GroupResource, GroupID{gid}, secret, filename, options) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_members.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_members.go index 14f835e95..c5ab2003f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_members.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_members.go @@ -17,20 +17,48 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( GroupMembersServiceInterface interface { - GetGroupMember(gid any, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) - GetInheritedGroupMember(gid any, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) + // GetGroupMember gets a member of a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project + GetGroupMember(gid any, user int64, options ...RequestOptionFunc) (*GroupMember, *Response, error) + // GetInheritedGroupMember gets a member of a group or project, including + // inherited and invited members + // + // GitLab API docs: + // https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project-including-inherited-and-invited-members + GetInheritedGroupMember(gid any, user int64, options ...RequestOptionFunc) (*GroupMember, *Response, error) + // AddGroupMember adds a user to the list of group members. + // + // GitLab API docs: + // https://docs.gitlab.com/api/members/#add-a-member-to-a-group-or-project AddGroupMember(gid any, opt *AddGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) + // ShareWithGroup shares a group with the group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#create-a-link-to-share-a-group-with-another-group ShareWithGroup(gid any, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) - DeleteShareWithGroup(gid any, groupID int, options ...RequestOptionFunc) (*Response, error) - EditGroupMember(gid any, user int, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) - RemoveGroupMember(gid any, user int, opt *RemoveGroupMemberOptions, options ...RequestOptionFunc) (*Response, error) + // DeleteShareWithGroup allows to unshare a group from a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/groups/#delete-the-link-that-shares-a-group-with-another-group + DeleteShareWithGroup(gid any, groupID int64, options ...RequestOptionFunc) (*Response, error) + // EditGroupMember updates a member of a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/members/#edit-a-member-of-a-group-or-project + EditGroupMember(gid any, user int64, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) + // RemoveGroupMember removes user from user team. + // + // GitLab API docs: + // https://docs.gitlab.com/api/members/#remove-a-member-from-a-group-or-project + RemoveGroupMember(gid any, user int64, opt *RemoveGroupMemberOptions, options ...RequestOptionFunc) (*Response, error) } // GroupMembersService handles communication with the group members @@ -48,7 +76,7 @@ var _ GroupMembersServiceInterface = (*GroupMembersService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/members/ type GroupMember struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Name string `json:"name"` State string `json:"state"` @@ -62,6 +90,7 @@ type GroupMember struct { PublicEmail string `json:"public_email,omitempty"` GroupSAMLIdentity *GroupMemberSAMLIdentity `json:"group_saml_identity"` MemberRole *MemberRole `json:"member_role"` + IsUsingSeat bool `json:"is_using_seat,omitempty"` } // GroupMemberSAMLIdentity represents the SAML Identity link for the group member. @@ -71,7 +100,7 @@ type GroupMember struct { type GroupMemberSAMLIdentity struct { ExternUID string `json:"extern_uid"` Provider string `json:"provider"` - SAMLProviderID int `json:"saml_provider_id"` + SAMLProviderID int64 `json:"saml_provider_id"` } // BillableGroupMember represents a GitLab billable group member. @@ -79,7 +108,7 @@ type GroupMemberSAMLIdentity struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-billable-members-of-a-group type BillableGroupMember struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Name string `json:"name"` State string `json:"state"` @@ -99,8 +128,8 @@ type BillableGroupMember struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#list-memberships-for-a-billable-member-of-a-group type BillableUserMembership struct { - ID int `json:"id"` - SourceID int `json:"source_id"` + ID int64 `json:"id"` + SourceID int64 `json:"source_id"` SourceFullName string `json:"source_full_name"` SourceMembersURL string `json:"source_members_url"` CreatedAt *time.Time `json:"created_at"` @@ -115,8 +144,9 @@ type BillableUserMembership struct { // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project type ListGroupMembersOptions struct { ListOptions - Query *string `url:"query,omitempty" json:"query,omitempty"` - UserIDs *[]int `url:"user_ids[],omitempty" json:"user_ids,omitempty"` + Query *string `url:"query,omitempty" json:"query,omitempty"` + UserIDs *[]int64 `url:"user_ids[],omitempty" json:"user_ids,omitempty"` + ShowSeatInfo *bool `url:"show_seat_info,omitempty" json:"show_seat_info,omitempty"` } // ListGroupMembers get a list of group members viewable by the authenticated @@ -125,24 +155,11 @@ type ListGroupMembersOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project func (s *GroupsService) ListGroupMembers(gid any, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gm []*GroupMember - resp, err := s.client.Do(req, &gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, nil + return do[[]*GroupMember](s.client, + withPath("groups/%s/members", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListAllGroupMembers get a list of group members viewable by the authenticated @@ -151,24 +168,11 @@ func (s *GroupsService) ListGroupMembers(gid any, opt *ListGroupMembersOptions, // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project-including-inherited-and-invited-members func (s *GroupsService) ListAllGroupMembers(gid any, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members/all", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gm []*GroupMember - resp, err := s.client.Do(req, &gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, nil + return do[[]*GroupMember](s.client, + withPath("groups/%s/members/all", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddGroupMemberOptions represents the available AddGroupMember() options. @@ -176,62 +180,25 @@ func (s *GroupsService) ListAllGroupMembers(gid any, opt *ListGroupMembersOption // GitLab API docs: // https://docs.gitlab.com/api/members/#add-a-member-to-a-group-or-project type AddGroupMemberOptions struct { - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` Username *string `url:"username,omitempty" json:"username,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` } -// GetGroupMember gets a member of a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project -func (s *GroupMembersService) GetGroupMember(gid any, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gm := new(GroupMember) - resp, err := s.client.Do(req, gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, nil +func (s *GroupMembersService) GetGroupMember(gid any, user int64, options ...RequestOptionFunc) (*GroupMember, *Response, error) { + return do[*GroupMember](s.client, + withPath("groups/%s/members/%d", GroupID{gid}, user), + withRequestOpts(options...), + ) } -// GetInheritedGroupMember get a member of a group or project, including -// inherited and invited members -// -// GitLab API docs: -// https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project-including-inherited-and-invited-members -func (s *GroupMembersService) GetInheritedGroupMember(gid any, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members/all/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gm := new(GroupMember) - resp, err := s.client.Do(req, gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, err +func (s *GroupMembersService) GetInheritedGroupMember(gid any, user int64, options ...RequestOptionFunc) (*GroupMember, *Response, error) { + return do[*GroupMember](s.client, + withPath("groups/%s/members/all/%d", GroupID{gid}, user), + withRequestOpts(options...), + ) } // ListBillableGroupMembersOptions represents the available @@ -251,24 +218,11 @@ type ListBillableGroupMembersOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-billable-members-of-a-group func (s *GroupsService) ListBillableGroupMembers(gid any, opt *ListBillableGroupMembersOptions, options ...RequestOptionFunc) ([]*BillableGroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/billable_members", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var bgm []*BillableGroupMember - resp, err := s.client.Do(req, &bgm) - if err != nil { - return nil, resp, err - } - - return bgm, resp, nil + return do[[]*BillableGroupMember](s.client, + withPath("groups/%s/billable_members", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListMembershipsForBillableGroupMemberOptions represents the available @@ -276,120 +230,61 @@ func (s *GroupsService) ListBillableGroupMembers(gid any, opt *ListBillableGroup // // GitLab API docs: // https://docs.gitlab.com/api/members/#list-memberships-for-a-billable-member-of-a-group -type ListMembershipsForBillableGroupMemberOptions = ListOptions +type ListMembershipsForBillableGroupMemberOptions struct { + ListOptions +} // ListMembershipsForBillableGroupMember gets a list of memberships for a // billable member of a group. // // GitLab API docs: // https://docs.gitlab.com/api/members/#list-memberships-for-a-billable-member-of-a-group -func (s *GroupsService) ListMembershipsForBillableGroupMember(gid any, user int, opt *ListMembershipsForBillableGroupMemberOptions, options ...RequestOptionFunc) ([]*BillableUserMembership, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/billable_members/%d/memberships", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var bum []*BillableUserMembership - resp, err := s.client.Do(req, &bum) - if err != nil { - return nil, resp, err - } - - return bum, resp, nil +func (s *GroupsService) ListMembershipsForBillableGroupMember(gid any, user int64, opt *ListMembershipsForBillableGroupMemberOptions, options ...RequestOptionFunc) ([]*BillableUserMembership, *Response, error) { + return do[[]*BillableUserMembership](s.client, + withPath("groups/%s/billable_members/%d/memberships", GroupID{gid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveBillableGroupMember removes a given group members that count as billable. // // GitLab API docs: // https://docs.gitlab.com/api/members/#remove-a-billable-member-from-a-group -func (s *GroupsService) RemoveBillableGroupMember(gid any, user int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/billable_members/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) RemoveBillableGroupMember(gid any, user int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/billable_members/%d", GroupID{gid}, user), + withRequestOpts(options...), + ) + return resp, err } -// AddGroupMember adds a user to the list of group members. -// -// GitLab API docs: -// https://docs.gitlab.com/api/members/#add-a-member-to-a-group-or-project func (s *GroupMembersService) AddGroupMember(gid any, opt *AddGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gm := new(GroupMember) - resp, err := s.client.Do(req, gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, nil + return do[*GroupMember](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/members", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ShareWithGroup shares a group with the group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/groups/#create-a-link-to-share-a-group-with-another-group func (s *GroupMembersService) ShareWithGroup(gid any, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/share", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/share", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteShareWithGroup allows to unshare a group from a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/groups/#delete-the-link-that-shares-a-group-with-another-group -func (s *GroupMembersService) DeleteShareWithGroup(gid any, groupID int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/share/%d", PathEscape(group), groupID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupMembersService) DeleteShareWithGroup(gid any, groupID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/share/%d", GroupID{gid}, groupID), + withRequestOpts(options...), + ) + return resp, err } // EditGroupMemberOptions represents the available EditGroupMember() @@ -400,32 +295,16 @@ func (s *GroupMembersService) DeleteShareWithGroup(gid any, groupID int, options type EditGroupMemberOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at,omitempty"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` } -// EditGroupMember updates a member of a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/members/#edit-a-member-of-a-group-or-project -func (s *GroupMembersService) EditGroupMember(gid any, user int, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/members/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gm := new(GroupMember) - resp, err := s.client.Do(req, gm) - if err != nil { - return nil, resp, err - } - - return gm, resp, nil +func (s *GroupMembersService) EditGroupMember(gid any, user int64, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) { + return do[*GroupMember](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/members/%d", GroupID{gid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveGroupMemberOptions represents the available options to remove a group member. @@ -437,21 +316,12 @@ type RemoveGroupMemberOptions struct { UnassignIssuables *bool `url:"unassign_issuables,omitempty" json:"unassign_issuables,omitempty"` } -// RemoveGroupMember removes user from user team. -// -// GitLab API docs: -// https://docs.gitlab.com/api/members/#remove-a-member-from-a-group-or-project -func (s *GroupMembersService) RemoveGroupMember(gid any, user int, opt *RemoveGroupMemberOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/members/%d", PathEscape(group), user) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupMembersService) RemoveGroupMember(gid any, user int64, opt *RemoveGroupMemberOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/members/%d", GroupID{gid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_milestones.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_milestones.go index 8ae487a12..0607e2539 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_milestones.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_milestones.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,13 +24,13 @@ import ( type ( GroupMilestonesServiceInterface interface { ListGroupMilestones(gid any, opt *ListGroupMilestonesOptions, options ...RequestOptionFunc) ([]*GroupMilestone, *Response, error) - GetGroupMilestone(gid any, milestone int, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) + GetGroupMilestone(gid any, milestone int64, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) CreateGroupMilestone(gid any, opt *CreateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) - UpdateGroupMilestone(gid any, milestone int, opt *UpdateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) - DeleteGroupMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Response, error) - GetGroupMilestoneIssues(gid any, milestone int, opt *GetGroupMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) - GetGroupMilestoneMergeRequests(gid any, milestone int, opt *GetGroupMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) - GetGroupMilestoneBurndownChartEvents(gid any, milestone int, opt *GetGroupMilestoneBurndownChartEventsOptions, options ...RequestOptionFunc) ([]*BurndownChartEvent, *Response, error) + UpdateGroupMilestone(gid any, milestone int64, opt *UpdateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) + DeleteGroupMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Response, error) + GetGroupMilestoneIssues(gid any, milestone int64, opt *GetGroupMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + GetGroupMilestoneMergeRequests(gid any, milestone int64, opt *GetGroupMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) + GetGroupMilestoneBurndownChartEvents(gid any, milestone int64, opt *GetGroupMilestoneBurndownChartEventsOptions, options ...RequestOptionFunc) ([]*BurndownChartEvent, *Response, error) } // GroupMilestonesService handles communication with the milestone related @@ -49,9 +48,9 @@ var _ GroupMilestonesServiceInterface = (*GroupMilestonesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/group_milestones/ type GroupMilestone struct { - ID int `json:"id"` - IID int `json:"iid"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + GroupID int64 `json:"group_id"` Title string `json:"title"` Description string `json:"description"` StartDate *ISOTime `json:"start_date"` @@ -73,7 +72,7 @@ func (m GroupMilestone) String() string { // https://docs.gitlab.com/api/group_milestones/#list-group-milestones type ListGroupMilestonesOptions struct { ListOptions - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` State *string `url:"state,omitempty" json:"state,omitempty"` Title *string `url:"title,omitempty" json:"title,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` @@ -95,49 +94,22 @@ type ListGroupMilestonesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#list-group-milestones func (s *GroupMilestonesService) ListGroupMilestones(gid any, opt *ListGroupMilestonesOptions, options ...RequestOptionFunc) ([]*GroupMilestone, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*GroupMilestone - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil + return do[[]*GroupMilestone](s.client, + withPath("groups/%s/milestones", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupMilestone gets a single group milestone. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-single-milestone -func (s *GroupMilestonesService) GetGroupMilestone(gid any, milestone int, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d", PathEscape(group), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(GroupMilestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *GroupMilestonesService) GetGroupMilestone(gid any, milestone int64, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) { + return do[*GroupMilestone](s.client, + withPath("groups/%s/milestones/%d", GroupID{gid}, milestone), + withRequestOpts(options...), + ) } // CreateGroupMilestoneOptions represents the available CreateGroupMilestone() options. @@ -156,24 +128,12 @@ type CreateGroupMilestoneOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#create-new-milestone func (s *GroupMilestonesService) CreateGroupMilestone(gid any, opt *CreateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(GroupMilestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil + return do[*GroupMilestone](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/milestones", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateGroupMilestoneOptions represents the available UpdateGroupMilestone() options. @@ -192,74 +152,46 @@ type UpdateGroupMilestoneOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#edit-milestone -func (s *GroupMilestonesService) UpdateGroupMilestone(gid any, milestone int, opt *UpdateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d", PathEscape(group), milestone) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(GroupMilestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *GroupMilestonesService) UpdateGroupMilestone(gid any, milestone int64, opt *UpdateGroupMilestoneOptions, options ...RequestOptionFunc) (*GroupMilestone, *Response, error) { + return do[*GroupMilestone](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/milestones/%d", GroupID{gid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupMilestone deletes a specified group milestone. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#delete-group-milestone -func (s *GroupMilestonesService) DeleteGroupMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - return s.client.Do(req, nil) +func (s *GroupMilestonesService) DeleteGroupMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/milestones/%d", GroupID{pid}, milestone), + withRequestOpts(options...), + ) + return resp, err } // GetGroupMilestoneIssuesOptions represents the available GetGroupMilestoneIssues() options. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-issues-assigned-to-a-single-milestone -type GetGroupMilestoneIssuesOptions ListOptions +type GetGroupMilestoneIssuesOptions struct { + ListOptions +} // GetGroupMilestoneIssues gets all issues assigned to a single group milestone. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-issues-assigned-to-a-single-milestone -func (s *GroupMilestonesService) GetGroupMilestoneIssues(gid any, milestone int, opt *GetGroupMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d/issues", PathEscape(group), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *GroupMilestonesService) GetGroupMilestoneIssues(gid any, milestone int64, opt *GetGroupMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withPath("groups/%s/milestones/%d/issues", GroupID{gid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupMilestoneMergeRequestsOptions represents the available @@ -267,32 +199,21 @@ func (s *GroupMilestonesService) GetGroupMilestoneIssues(gid any, milestone int, // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-merge-requests-assigned-to-a-single-milestone -type GetGroupMilestoneMergeRequestsOptions ListOptions +type GetGroupMilestoneMergeRequestsOptions struct { + ListOptions +} // GetGroupMilestoneMergeRequests gets all merge requests assigned to a // single group milestone. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-merge-requests-assigned-to-a-single-milestone -func (s *GroupMilestonesService) GetGroupMilestoneMergeRequests(gid any, milestone int, opt *GetGroupMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d/merge_requests", PathEscape(group), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mr []*BasicMergeRequest - resp, err := s.client.Do(req, &mr) - if err != nil { - return nil, resp, err - } - - return mr, resp, nil +func (s *GroupMilestonesService) GetGroupMilestoneMergeRequests(gid any, milestone int64, opt *GetGroupMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { + return do[[]*BasicMergeRequest](s.client, + withPath("groups/%s/milestones/%d/merge_requests", GroupID{gid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // BurndownChartEvent represents a burnout chart event. @@ -301,7 +222,7 @@ func (s *GroupMilestonesService) GetGroupMilestoneMergeRequests(gid any, milesto // https://docs.gitlab.com/api/group_milestones/#get-all-burndown-chart-events-for-a-single-milestone type BurndownChartEvent struct { CreatedAt *time.Time `json:"created_at"` - Weight *int `json:"weight"` + Weight *int64 `json:"weight"` Action *string `json:"action"` } @@ -310,30 +231,19 @@ type BurndownChartEvent struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-burndown-chart-events-for-a-single-milestone -type GetGroupMilestoneBurndownChartEventsOptions ListOptions +type GetGroupMilestoneBurndownChartEventsOptions struct { + ListOptions +} // GetGroupMilestoneBurndownChartEvents gets all merge requests assigned to a // single group milestone. // // GitLab API docs: // https://docs.gitlab.com/api/group_milestones/#get-all-burndown-chart-events-for-a-single-milestone -func (s *GroupMilestonesService) GetGroupMilestoneBurndownChartEvents(gid any, milestone int, opt *GetGroupMilestoneBurndownChartEventsOptions, options ...RequestOptionFunc) ([]*BurndownChartEvent, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/milestones/%d/burndown_events", PathEscape(group), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var be []*BurndownChartEvent - resp, err := s.client.Do(req, &be) - if err != nil { - return nil, resp, err - } - - return be, resp, nil +func (s *GroupMilestonesService) GetGroupMilestoneBurndownChartEvents(gid any, milestone int64, opt *GetGroupMilestoneBurndownChartEventsOptions, options ...RequestOptionFunc) ([]*BurndownChartEvent, *Response, error) { + return do[[]*BurndownChartEvent](s.client, + withPath("groups/%s/milestones/%d/burndown_events", GroupID{gid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_branches.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_branches.go new file mode 100644 index 000000000..f43c6ed66 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_branches.go @@ -0,0 +1,177 @@ +package gitlab + +import ( + "net/http" + "net/url" +) + +type ( + GroupProtectedBranchesServiceInterface interface { + // ListProtectedBranches returns a list of protected branches from a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/#list-protected-branches + ListProtectedBranches(gid any, opt *ListGroupProtectedBranchesOptions, options ...RequestOptionFunc) ([]*GroupProtectedBranch, *Response, error) + + // GetProtectedBranch returns a single group-level protected branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/#get-a-single-protected-branch-or-wildcard-protected-branch + GetProtectedBranch(gid any, branch string, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) + + // ProtectRepositoryBranches protects a single group-level branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/#protect-repository-branches + ProtectRepositoryBranches(gid any, opt *ProtectGroupRepositoryBranchesOptions, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) + + // UpdateProtectedBranch updates a single group-level protected branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/#update-a-protected-branch + UpdateProtectedBranch(gid any, branch string, opt *UpdateGroupProtectedBranchOptions, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) + + // UnprotectRepositoryBranches unprotects the given protected group-level branch. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/#unprotect-repository-branches + UnprotectRepositoryBranches(gid any, branch string, options ...RequestOptionFunc) (*Response, error) + } + + // GroupProtectedBranchesService handles communication with the group-level + // protected branch methods of the GitLab API. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_protected_branches/ + GroupProtectedBranchesService struct { + client *Client + } +) + +var _ GroupProtectedBranchesServiceInterface = (*GroupProtectedBranchesService)(nil) + +// GroupProtectedBranch represents a group protected branch. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#list-protected-branches +type GroupProtectedBranch struct { + ID int64 `json:"id"` + Name string `json:"name"` + PushAccessLevels []*GroupBranchAccessDescription `json:"push_access_levels"` + MergeAccessLevels []*GroupBranchAccessDescription `json:"merge_access_levels"` + UnprotectAccessLevels []*GroupBranchAccessDescription `json:"unprotect_access_levels"` + AllowForcePush bool `json:"allow_force_push"` + CodeOwnerApprovalRequired bool `json:"code_owner_approval_required"` +} + +// GroupBranchAccessDescription represents the access description for a group protected +// branch. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#list-protected-branches +type GroupBranchAccessDescription struct { + ID int64 `json:"id"` + AccessLevel AccessLevelValue `json:"access_level"` + AccessLevelDescription string `json:"access_level_description"` + DeployKeyID int64 `json:"deploy_key_id"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` +} + +// ListGroupProtectedBranchesOptions represents the available ListProtectedBranches() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#list-protected-branches +type ListGroupProtectedBranchesOptions struct { + ListOptions + Search *string `url:"search,omitempty" json:"search,omitempty"` +} + +func (s *GroupProtectedBranchesService) ListProtectedBranches(gid any, opt *ListGroupProtectedBranchesOptions, options ...RequestOptionFunc) ([]*GroupProtectedBranch, *Response, error) { + return do[[]*GroupProtectedBranch](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/protected_branches", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *GroupProtectedBranchesService) GetProtectedBranch(gid any, branch string, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) { + return do[*GroupProtectedBranch](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/protected_branches/%s", GroupID{gid}, url.PathEscape(branch)), + withRequestOpts(options...), + ) +} + +// ProtectGroupRepositoryBranchesOptions represents the available +// ProtectRepositoryBranches() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#protect-repository-branches +type ProtectGroupRepositoryBranchesOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + PushAccessLevel *AccessLevelValue `url:"push_access_level,omitempty" json:"push_access_level,omitempty"` + MergeAccessLevel *AccessLevelValue `url:"merge_access_level,omitempty" json:"merge_access_level,omitempty"` + UnprotectAccessLevel *AccessLevelValue `url:"unprotect_access_level,omitempty" json:"unprotect_access_level,omitempty"` + AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` + AllowedToPush *[]*GroupBranchPermissionOptions `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` + AllowedToMerge *[]*GroupBranchPermissionOptions `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` + AllowedToUnprotect *[]*GroupBranchPermissionOptions `url:"allowed_to_unprotect,omitempty" json:"allowed_to_unprotect,omitempty"` + CodeOwnerApprovalRequired *bool `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"` +} + +// GroupBranchPermissionOptions represents a branch permission option. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#protect-repository-branches +type GroupBranchPermissionOptions struct { + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + DeployKeyID *int64 `url:"deploy_key_id,omitempty" json:"deploy_key_id,omitempty"` + AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` + Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` +} + +func (s *GroupProtectedBranchesService) ProtectRepositoryBranches(gid any, opt *ProtectGroupRepositoryBranchesOptions, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) { + return do[*GroupProtectedBranch](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/protected_branches", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// UpdateGroupProtectedBranchOptions represents the available +// UpdateProtectedBranch() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_protected_branches/#update-a-protected-branch +type UpdateGroupProtectedBranchOptions struct { + Name *string `url:"name,omitempty" json:"name,omitempty"` + AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` + CodeOwnerApprovalRequired *bool `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"` + AllowedToPush *[]*GroupBranchPermissionOptions `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` + AllowedToMerge *[]*GroupBranchPermissionOptions `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` + AllowedToUnprotect *[]*GroupBranchPermissionOptions `url:"allowed_to_unprotect,omitempty" json:"allowed_to_unprotect,omitempty"` +} + +func (s *GroupProtectedBranchesService) UpdateProtectedBranch(gid any, branch string, opt *UpdateGroupProtectedBranchOptions, options ...RequestOptionFunc) (*GroupProtectedBranch, *Response, error) { + return do[*GroupProtectedBranch](s.client, + withMethod(http.MethodPatch), + withPath("groups/%s/protected_branches/%s", GroupID{gid}, url.PathEscape(branch)), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *GroupProtectedBranchesService) UnprotectRepositoryBranches(gid any, branch string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/protected_branches/%s", GroupID{gid}, url.PathEscape(branch)), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_environments.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_environments.go index 211201164..681d9c9bc 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_environments.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_protected_environments.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -49,7 +48,7 @@ var _ GroupProtectedEnvironmentsServiceInterface = (*GroupProtectedEnvironmentsS type GroupProtectedEnvironment struct { Name string `json:"name"` DeployAccessLevels []*GroupEnvironmentAccessDescription `json:"deploy_access_levels"` - RequiredApprovalCount int `json:"required_approval_count"` + RequiredApprovalCount int64 `json:"required_approval_count"` ApprovalRules []*GroupEnvironmentApprovalRule `json:"approval_rules"` } @@ -59,12 +58,12 @@ type GroupProtectedEnvironment struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/ type GroupEnvironmentAccessDescription struct { - ID int `json:"id"` + ID int64 `json:"id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` - GroupInheritanceType int `json:"group_inheritance_type"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` + GroupInheritanceType int64 `json:"group_inheritance_type"` } // GroupEnvironmentApprovalRule represents the approval rules for a group-level @@ -73,13 +72,13 @@ type GroupEnvironmentAccessDescription struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#protect-a-single-environment type GroupEnvironmentApprovalRule struct { - ID int `json:"id"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` - RequiredApprovalCount int `json:"required_approvals"` - GroupInheritanceType int `json:"group_inheritance_type"` + RequiredApprovalCount int64 `json:"required_approvals"` + GroupInheritanceType int64 `json:"group_inheritance_type"` } // ListGroupProtectedEnvironmentsOptions represents the available @@ -87,7 +86,9 @@ type GroupEnvironmentApprovalRule struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#list-group-level-protected-environments -type ListGroupProtectedEnvironmentsOptions ListOptions +type ListGroupProtectedEnvironmentsOptions struct { + ListOptions +} // ListGroupProtectedEnvironments returns a list of protected environments from // a group. @@ -95,24 +96,11 @@ type ListGroupProtectedEnvironmentsOptions ListOptions // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#list-group-level-protected-environments func (s *GroupProtectedEnvironmentsService) ListGroupProtectedEnvironments(gid any, opt *ListGroupProtectedEnvironmentsOptions, options ...RequestOptionFunc) ([]*GroupProtectedEnvironment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/protected_environments", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pes []*GroupProtectedEnvironment - resp, err := s.client.Do(req, &pes) - if err != nil { - return nil, resp, err - } - - return pes, resp, nil + return do[[]*GroupProtectedEnvironment](s.client, + withPath("groups/%s/protected_environments", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupProtectedEnvironment returns a single group-level protected @@ -121,24 +109,10 @@ func (s *GroupProtectedEnvironmentsService) ListGroupProtectedEnvironments(gid a // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#get-a-single-protected-environment func (s *GroupProtectedEnvironmentsService) GetGroupProtectedEnvironment(gid any, environment string, options ...RequestOptionFunc) (*GroupProtectedEnvironment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/protected_environments/%s", PathEscape(group), environment) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pe := new(GroupProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*GroupProtectedEnvironment](s.client, + withPath("groups/%s/protected_environments/%s", GroupID{gid}, environment), + withRequestOpts(options...), + ) } // ProtectGroupEnvironmentOptions represents the available @@ -149,7 +123,7 @@ func (s *GroupProtectedEnvironmentsService) GetGroupProtectedEnvironment(gid any type ProtectGroupEnvironmentOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` DeployAccessLevels *[]*GroupEnvironmentAccessOptions `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"` - RequiredApprovalCount *int `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` + RequiredApprovalCount *int64 `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` ApprovalRules *[]*GroupEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"` } @@ -160,9 +134,9 @@ type ProtectGroupEnvironmentOptions struct { // https://docs.gitlab.com/api/group_protected_environments/#protect-a-single-environment type GroupEnvironmentAccessOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` } // GroupEnvironmentApprovalRuleOptions represents the approval rules for a @@ -171,12 +145,12 @@ type GroupEnvironmentAccessOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#protect-a-single-environment type GroupEnvironmentApprovalRuleOptions struct { - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` AccessLevelDescription *string `url:"access_level_description,omitempty" json:"access_level_description,omitempty"` - RequiredApprovalCount *int `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + RequiredApprovalCount *int64 `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` } // ProtectGroupEnvironment protects a single group-level environment. @@ -184,24 +158,12 @@ type GroupEnvironmentApprovalRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#protect-a-single-environment func (s *GroupProtectedEnvironmentsService) ProtectGroupEnvironment(gid any, opt *ProtectGroupEnvironmentOptions, options ...RequestOptionFunc) (*GroupProtectedEnvironment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/protected_environments", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pe := new(GroupProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*GroupProtectedEnvironment](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/protected_environments", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateGroupProtectedEnvironmentOptions represents the available @@ -212,7 +174,7 @@ func (s *GroupProtectedEnvironmentsService) ProtectGroupEnvironment(gid any, opt type UpdateGroupProtectedEnvironmentOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` DeployAccessLevels *[]*UpdateGroupEnvironmentAccessOptions `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"` - RequiredApprovalCount *int `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` + RequiredApprovalCount *int64 `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` ApprovalRules *[]*UpdateGroupEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"` } @@ -223,10 +185,10 @@ type UpdateGroupProtectedEnvironmentOptions struct { // https://docs.gitlab.com/api/group_protected_environments/#update-a-protected-environment type UpdateGroupEnvironmentAccessOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` - ID *int `url:"id,omitempty" json:"id,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` } @@ -236,13 +198,13 @@ type UpdateGroupEnvironmentAccessOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#update-a-protected-environment type UpdateGroupEnvironmentApprovalRuleOptions struct { - ID *int `url:"id,omitempty" json:"id,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` AccessLevelDescription *string `url:"access_level_description,omitempty" json:"access_level_description,omitempty"` - RequiredApprovalCount *int `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + RequiredApprovalCount *int64 `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` } @@ -252,24 +214,12 @@ type UpdateGroupEnvironmentApprovalRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#update-a-protected-environment func (s *GroupProtectedEnvironmentsService) UpdateGroupProtectedEnvironment(gid any, environment string, opt *UpdateGroupProtectedEnvironmentOptions, options ...RequestOptionFunc) (*GroupProtectedEnvironment, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/protected_environments/%s", PathEscape(group), environment) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pe := new(GroupProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*GroupProtectedEnvironment](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/protected_environments/%s", GroupID{gid}, environment), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnprotectGroupEnvironment unprotects the given protected group-level @@ -278,16 +228,10 @@ func (s *GroupProtectedEnvironmentsService) UpdateGroupProtectedEnvironment(gid // GitLab API docs: // https://docs.gitlab.com/api/group_protected_environments/#unprotect-a-single-environment func (s *GroupProtectedEnvironmentsService) UnprotectGroupEnvironment(gid any, environment string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/protected_environments/%s", PathEscape(group), environment) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/protected_environments/%s", GroupID{gid}, environment), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_relations_export.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_relations_export.go new file mode 100644 index 000000000..4574f90e4 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_relations_export.go @@ -0,0 +1,110 @@ +package gitlab + +import ( + "bytes" + "net/http" + "time" +) + +// GroupRelationsScheduleExportOptions represents the available ScheduleExport() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_relations_export/#schedule-new-export +type GroupRelationsScheduleExportOptions struct { + Batched *bool `url:"batched,omitempty" json:"batched,omitempty"` +} + +// ListGroupRelationsStatusOptions represents the available ListExportStatus() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_relations_export/#export-status +type ListGroupRelationsStatusOptions struct { + ListOptions + + Relation *string `url:"relation,omitempty" json:"relation,omitempty"` +} + +// GroupRelationsDownloadOptions represents the available ExportDownload() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_relations_export/#download-exported-relations +type GroupRelationsDownloadOptions struct { + Relation *string `url:"relation,omitempty" json:"relation,omitempty"` + Batched *bool `url:"batched,omitempty" json:"batched,omitempty"` + BatchNumber *int64 `url:"batch_number,omitempty" json:"batch_number,omitempty"` +} + +type GroupRelationStatus struct { + Relation string `json:"relation"` + Status int64 `json:"status"` + Error string `json:"error"` + UpdatedAt time.Time `json:"updated_at"` + Batched bool `json:"batched"` + BatchesCount int64 `json:"batches_count"` + Batches []Batch `json:"batches,omitempty"` +} + +type Batch struct { + Status int64 `json:"status"` + BatchNumber int64 `json:"batch_number"` + ObjectsCount int64 `json:"objects_count"` + Error string `json:"error"` + UpdatedAt time.Time `json:"updated_at"` +} + +type ( + GroupRelationsExportServiceInterface interface { + // ScheduleExport schedules a new export of group relations. + // + // GitLab API docs: https://docs.gitlab.com/api/group_relations_export/#schedule-new-export + ScheduleExport(gid any, opt *GroupRelationsScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) + // ListExportStatus gets the status of group relations export. + // + // GitLab API docs: https://docs.gitlab.com/api/group_relations_export/#export-status + ListExportStatus(gid any, opt *ListGroupRelationsStatusOptions, options ...RequestOptionFunc) ([]*GroupRelationStatus, *Response, error) + // ExportDownload downloads the exported group relations. + // + // GitLab API docs: https://docs.gitlab.com/api/group_relations_export/#download-exported-relations + ExportDownload(gid any, opt *GroupRelationsDownloadOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + } + + // GroupRelationsExportService handles communication with the group relations export related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/group_relations_export + GroupRelationsExportService struct { + client *Client + } +) + +var _ GroupRelationsExportServiceInterface = (*GroupRelationsExportService)(nil) + +func (s *GroupRelationsExportService) ScheduleExport(gid any, opt *GroupRelationsScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/export_relations", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *GroupRelationsExportService) ListExportStatus(gid any, opt *ListGroupRelationsStatusOptions, options ...RequestOptionFunc) ([]*GroupRelationStatus, *Response, error) { + return do[[]*GroupRelationStatus](s.client, + withPath("groups/%s/export_relations/status", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *GroupRelationsExportService) ExportDownload(gid any, opt *GroupRelationsDownloadOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("groups/%s/export_relations/download", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + if err != nil { + return nil, resp, err + } + return bytes.NewReader(buf.Bytes()), resp, nil +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_releases.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_releases.go index da52ce9e2..ce0126788 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_releases.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_releases.go @@ -13,11 +13,6 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( GroupReleasesServiceInterface interface { ListGroupReleases(gid any, opts *ListGroupReleasesOptions, options ...RequestOptionFunc) ([]*Release, *Response, error) @@ -49,21 +44,9 @@ type ListGroupReleasesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_releases.html#list-group-releases func (s *GroupReleasesService) ListGroupReleases(gid any, opts *ListGroupReleasesOptions, options ...RequestOptionFunc) ([]*Release, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/releases", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var releases []*Release - resp, err := s.client.Do(req, &releases) - if err != nil { - return nil, resp, err - } - return releases, resp, nil + return do[[]*Release](s.client, + withPath("groups/%s/releases", GroupID{gid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_repository_storage_move.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_repository_storage_move.go index 01996cd09..fc5bb52ad 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_repository_storage_move.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_repository_storage_move.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,10 +24,10 @@ import ( type ( GroupRepositoryStorageMoveServiceInterface interface { RetrieveAllStorageMoves(opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) - RetrieveAllStorageMovesForGroup(group int, opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) - GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) - GetStorageMoveForGroup(group int, repositoryStorage int, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) - ScheduleStorageMoveForGroup(group int, opts ScheduleStorageMoveForGroupOptions, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) + RetrieveAllStorageMovesForGroup(group int64, opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) + GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) + GetStorageMoveForGroup(group int64, repositoryStorage int64, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) + ScheduleStorageMoveForGroup(group int64, opts ScheduleStorageMoveForGroupOptions, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) ScheduleAllStorageMoves(opts ScheduleAllGroupStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) } @@ -47,7 +46,7 @@ type ( // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/ type GroupRepositoryStorageMove struct { - ID int `json:"id"` + ID int64 `json:"id"` CreatedAt *time.Time `json:"created_at"` State string `json:"state"` SourceStorageName string `json:"source_storage_name"` @@ -56,7 +55,7 @@ type GroupRepositoryStorageMove struct { } type RepositoryGroup struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` WebURL string `json:"web_url"` } @@ -66,7 +65,9 @@ type RepositoryGroup struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#retrieve-all-group-repository-storage-moves -type RetrieveAllGroupStorageMovesOptions ListOptions +type RetrieveAllGroupStorageMovesOptions struct { + ListOptions +} // RetrieveAllStorageMoves retrieves all group repository storage moves // accessible by the authenticated user. @@ -74,18 +75,11 @@ type RetrieveAllGroupStorageMovesOptions ListOptions // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#retrieve-all-group-repository-storage-moves func (g GroupRepositoryStorageMoveService) RetrieveAllStorageMoves(opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) { - req, err := g.client.NewRequest(http.MethodGet, "group_repository_storage_moves", opts, options) - if err != nil { - return nil, nil, err - } - - var gsms []*GroupRepositoryStorageMove - resp, err := g.client.Do(req, &gsms) - if err != nil { - return nil, resp, err - } - - return gsms, resp, err + return do[[]*GroupRepositoryStorageMove](g.client, + withPath("group_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // RetrieveAllStorageMovesForGroup retrieves all repository storage moves for @@ -93,63 +87,34 @@ func (g GroupRepositoryStorageMoveService) RetrieveAllStorageMoves(opts Retrieve // // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#retrieve-all-repository-storage-moves-for-a-single-group -func (g GroupRepositoryStorageMoveService) RetrieveAllStorageMovesForGroup(group int, opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("groups/%d/repository_storage_moves", group) - - req, err := g.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var gsms []*GroupRepositoryStorageMove - resp, err := g.client.Do(req, &gsms) - if err != nil { - return nil, resp, err - } - - return gsms, resp, err +func (g GroupRepositoryStorageMoveService) RetrieveAllStorageMovesForGroup(group int64, opts RetrieveAllGroupStorageMovesOptions, options ...RequestOptionFunc) ([]*GroupRepositoryStorageMove, *Response, error) { + return do[[]*GroupRepositoryStorageMove](g.client, + withPath("groups/%d/repository_storage_moves", group), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // GetStorageMove gets a single group repository storage move. // // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#get-a-single-group-repository-storage-move -func (g GroupRepositoryStorageMoveService) GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("group_repository_storage_moves/%d", repositoryStorage) - - req, err := g.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gsm := new(GroupRepositoryStorageMove) - resp, err := g.client.Do(req, gsm) - if err != nil { - return nil, resp, err - } - - return gsm, resp, err +func (g GroupRepositoryStorageMoveService) GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { + return do[*GroupRepositoryStorageMove](g.client, + withPath("group_repository_storage_moves/%d", repositoryStorage), + withRequestOpts(options...), + ) } // GetStorageMoveForGroup gets a single repository storage move for a group. // // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#get-a-single-repository-storage-move-for-a-group -func (g GroupRepositoryStorageMoveService) GetStorageMoveForGroup(group int, repositoryStorage int, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("groups/%d/repository_storage_moves/%d", group, repositoryStorage) - - req, err := g.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gsm := new(GroupRepositoryStorageMove) - resp, err := g.client.Do(req, gsm) - if err != nil { - return nil, resp, err - } - - return gsm, resp, err +func (g GroupRepositoryStorageMoveService) GetStorageMoveForGroup(group int64, repositoryStorage int64, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { + return do[*GroupRepositoryStorageMove](g.client, + withPath("groups/%d/repository_storage_moves/%d", group, repositoryStorage), + withRequestOpts(options...), + ) } // ScheduleStorageMoveForGroupOptions represents the available @@ -165,21 +130,13 @@ type ScheduleStorageMoveForGroupOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#schedule-a-repository-storage-move-for-a-group -func (g GroupRepositoryStorageMoveService) ScheduleStorageMoveForGroup(group int, opts ScheduleStorageMoveForGroupOptions, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("groups/%d/repository_storage_moves", group) - - req, err := g.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - gsm := new(GroupRepositoryStorageMove) - resp, err := g.client.Do(req, gsm) - if err != nil { - return nil, resp, err - } - - return gsm, resp, err +func (g GroupRepositoryStorageMoveService) ScheduleStorageMoveForGroup(group int64, opts ScheduleStorageMoveForGroupOptions, options ...RequestOptionFunc) (*GroupRepositoryStorageMove, *Response, error) { + return do[*GroupRepositoryStorageMove](g.client, + withMethod(http.MethodPost), + withPath("groups/%d/repository_storage_moves", group), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // ScheduleAllGroupStorageMovesOptions represents the available @@ -197,10 +154,11 @@ type ScheduleAllGroupStorageMovesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_repository_storage_moves/#schedule-repository-storage-moves-for-all-groups-on-a-storage-shard func (g GroupRepositoryStorageMoveService) ScheduleAllStorageMoves(opts ScheduleAllGroupStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := g.client.NewRequest(http.MethodPost, "group_repository_storage_moves", opts, options) - if err != nil { - return nil, err - } - - return g.client.Do(req, nil) + _, resp, err := do[none](g.client, + withMethod(http.MethodPost), + withPath("group_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_scim.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_scim.go index e99a266e8..936290e52 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_scim.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_scim.go @@ -14,7 +14,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -51,23 +50,10 @@ type GroupSCIMIdentity struct { // GitLab API docs: // https://docs.gitlab.com/api/scim/#get-scim-identities-for-a-group func (s *GroupSCIMService) GetSCIMIdentitiesForGroup(gid any, options ...RequestOptionFunc) ([]*GroupSCIMIdentity, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/scim/identities", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var identities []*GroupSCIMIdentity - resp, err := s.client.Do(req, &identities) - if err != nil { - return nil, resp, err - } - return identities, resp, nil + return do[[]*GroupSCIMIdentity](s.client, + withPath("groups/%s/scim/identities", GroupID{gid}), + withRequestOpts(options...), + ) } // GetSCIMIdentity gets a SCIM identity for a group. @@ -75,23 +61,10 @@ func (s *GroupSCIMService) GetSCIMIdentitiesForGroup(gid any, options ...Request // GitLab API docs: // https://docs.gitlab.com/api/scim/#get-a-single-scim-identity func (s *GroupSCIMService) GetSCIMIdentity(gid any, uid string, options ...RequestOptionFunc) (*GroupSCIMIdentity, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/scim/%s", PathEscape(group), uid) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - identity := new(GroupSCIMIdentity) - resp, err := s.client.Do(req, identity) - if err != nil { - return nil, resp, err - } - return identity, resp, nil + return do[*GroupSCIMIdentity](s.client, + withPath("groups/%s/scim/%s", GroupID{gid}, uid), + withRequestOpts(options...), + ) } // UpdateSCIMIdentityOptions represent the request options for @@ -108,18 +81,13 @@ type UpdateSCIMIdentityOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/scim/#update-extern_uid-field-for-a-scim-identity func (s *GroupSCIMService) UpdateSCIMIdentity(gid any, uid string, opt *UpdateSCIMIdentityOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/scim/%s", PathEscape(group), uid) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPatch), + withPath("groups/%s/scim/%s", GroupID{gid}, uid), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // DeleteSCIMIdentity deletes a SCIM identity. @@ -127,16 +95,10 @@ func (s *GroupSCIMService) UpdateSCIMIdentity(gid any, uid string, opt *UpdateSC // GitLab API docs: // https://docs.gitlab.com/api/scim/#delete-a-single-scim-identity func (s *GroupSCIMService) DeleteSCIMIdentity(gid any, uid string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/scim/%s", PathEscape(group), uid) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/scim/%s", GroupID{gid}, uid), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_security_settings.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_security_settings.go index cab9c6a1f..445e757f7 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_security_settings.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_security_settings.go @@ -16,7 +16,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -28,7 +27,7 @@ type ( // GroupSecuritySettingsService handles communication with the Group Security Settings // related methods of the GitLab API. // - // Gitlab API docs: + // GitLab API docs: // https://docs.gitlab.com/api/group_security_settings/ GroupSecuritySettingsService struct { client *Client @@ -39,7 +38,7 @@ var _ GroupSecuritySettingsServiceInterface = (*GroupSecuritySettingsService)(ni // GroupSecuritySettings represents the group security settings data. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/group_security_settings/ type GroupSecuritySettings struct { SecretPushProtectionEnabled bool `json:"secret_push_protection_enabled"` @@ -60,8 +59,8 @@ func (s GroupSecuritySettings) String() string { // GitLab API docs: // https://docs.gitlab.com/api/group_security_settings/#update-secret_push_protection_enabled-setting type UpdateGroupSecuritySettingsOptions struct { - SecretPushProtectionEnabled *bool `url:"secret_push_protection_enabled,omitempty" json:"secret_push_protection_enabled,omitempty"` - ProjectsToExclude *[]int `url:"projects_to_exclude,omitempty" json:"projects_to_exclude,omitempty"` + SecretPushProtectionEnabled *bool `url:"secret_push_protection_enabled,omitempty" json:"secret_push_protection_enabled,omitempty"` + ProjectsToExclude *[]int64 `url:"projects_to_exclude,omitempty" json:"projects_to_exclude,omitempty"` } // UpdateSecretPushProtectionEnabledSetting updates the secret_push_protection_enabled @@ -70,21 +69,10 @@ type UpdateGroupSecuritySettingsOptions struct { // GitLab API Docs: // https://docs.gitlab.com/api/group_security_settings/#update-secret_push_protection_enabled-setting func (s *GroupSecuritySettingsService) UpdateSecretPushProtectionEnabledSetting(gid any, opt UpdateGroupSecuritySettingsOptions, options ...RequestOptionFunc) (*GroupSecuritySettings, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/security_settings", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - settings := new(GroupSecuritySettings) - resp, err := s.client.Do(req, &settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, err + return do[*GroupSecuritySettings](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/security_settings", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_serviceaccounts.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_serviceaccounts.go index 8021b56de..f8cd5bf37 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_serviceaccounts.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_serviceaccounts.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,9 +24,9 @@ import ( // GroupServiceAccount represents a GitLab service account user. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#create-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#create-a-group-service-account type GroupServiceAccount struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` UserName string `json:"username"` Email string `json:"email"` @@ -36,7 +35,7 @@ type GroupServiceAccount struct { // ListServiceAccountsOptions represents the available ListServiceAccounts() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#list-all-service-account-users +// https://docs.gitlab.com/api/service_accounts/#list-all-group-service-accounts type ListServiceAccountsOptions struct { ListOptions OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` @@ -46,32 +45,19 @@ type ListServiceAccountsOptions struct { // ListServiceAccounts gets a list of service accounts. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#list-all-service-account-users +// https://docs.gitlab.com/api/service_accounts/#list-all-group-service-accounts func (s *GroupsService) ListServiceAccounts(gid any, opt *ListServiceAccountsOptions, options ...RequestOptionFunc) ([]*GroupServiceAccount, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var sa []*GroupServiceAccount - resp, err := s.client.Do(req, &sa) - if err != nil { - return nil, resp, err - } - - return sa, resp, nil + return do[[]*GroupServiceAccount](s.client, + withPath("groups/%s/service_accounts", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateServiceAccountOptions represents the available CreateServiceAccount() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#create-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#create-a-group-service-account type CreateServiceAccountOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Username *string `url:"username,omitempty" json:"username,omitempty"` @@ -83,35 +69,24 @@ type CreateServiceAccountOptions struct { // This API endpoint works on top-level groups only. It does not work on subgroups. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#create-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#create-a-group-service-account func (s *GroupsService) CreateServiceAccount(gid any, opt *CreateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - sa := new(GroupServiceAccount) - resp, err := s.client.Do(req, sa) - if err != nil { - return nil, resp, err - } - - return sa, resp, nil + return do[*GroupServiceAccount](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/service_accounts", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateServiceAccountOptions represents the available UpdateServiceAccount() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#update-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#update-a-group-service-account type UpdateServiceAccountOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Username *string `url:"username,omitempty" json:"username,omitempty"` + Email *string `url:"email,omitempty" json:"email,omitempty"` } // UpdateServiceAccount updates a service account user. @@ -119,32 +94,20 @@ type UpdateServiceAccountOptions struct { // This API endpoint works on top-level groups only. It does not work on subgroups. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#update-a-service-account-user -func (s *GroupsService) UpdateServiceAccount(gid any, serviceAccount int, opt *UpdateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d", PathEscape(group), serviceAccount) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, nil, err - } - - sa := new(GroupServiceAccount) - resp, err := s.client.Do(req, sa) - if err != nil { - return nil, resp, err - } - - return sa, resp, nil +// https://docs.gitlab.com/api/service_accounts/#update-a-group-service-account +func (s *GroupsService) UpdateServiceAccount(gid any, serviceAccount int64, opt *UpdateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) { + return do[*GroupServiceAccount](s.client, + withMethod(http.MethodPatch), + withPath("groups/%s/service_accounts/%d", GroupID{gid}, serviceAccount), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteServiceAccountOptions represents the available DeleteServiceAccount() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#delete-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#delete-a-group-service-account type DeleteServiceAccountOptions struct { HardDelete *bool `url:"hard_delete,omitempty" json:"hard_delete,omitempty"` } @@ -154,27 +117,22 @@ type DeleteServiceAccountOptions struct { // This API endpoint works on top-level groups only. It does not work on subgroups. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#delete-a-service-account-user -func (s *GroupsService) DeleteServiceAccount(gid any, serviceAccount int, opt *DeleteServiceAccountOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d", PathEscape(group), serviceAccount) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +// https://docs.gitlab.com/api/service_accounts/#delete-a-group-service-account +func (s *GroupsService) DeleteServiceAccount(gid any, serviceAccount int64, opt *DeleteServiceAccountOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/service_accounts/%d", GroupID{gid}, serviceAccount), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // ListServiceAccountPersonalAccessTokensOptions represents the available // ListServiceAccountPersonalAccessTokens() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#list-all-personal-access-tokens-for-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#list-all-personal-access-tokens-for-a-group-service-account type ListServiceAccountPersonalAccessTokensOptions struct { ListOptions CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` @@ -184,7 +142,7 @@ type ListServiceAccountPersonalAccessTokensOptions struct { LastUsedAfter *time.Time `url:"last_used_after,omitempty" json:"last_used_after,omitempty"` LastUsedBefore *time.Time `url:"last_used_before,omitempty" json:"last_used_before,omitempty"` Revoked *bool `url:"revoked,omitempty" json:"revoked,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` State *string `url:"state,omitempty" json:"state,omitempty"` @@ -194,33 +152,20 @@ type ListServiceAccountPersonalAccessTokensOptions struct { // service account user for a group. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#list-all-personal-access-tokens-for-a-service-account-user -func (s *GroupsService) ListServiceAccountPersonalAccessTokens(gid any, serviceAccount int, opt *ListServiceAccountPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d/personal_access_tokens", PathEscape(group), serviceAccount) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pats []*PersonalAccessToken - resp, err := s.client.Do(req, &pats) - if err != nil { - return nil, resp, err - } - - return pats, resp, nil +// https://docs.gitlab.com/api/service_accounts/#list-all-personal-access-tokens-for-a-group-service-account +func (s *GroupsService) ListServiceAccountPersonalAccessTokens(gid any, serviceAccount int64, opt *ListServiceAccountPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) { + return do[[]*PersonalAccessToken](s.client, + withPath("groups/%s/service_accounts/%d/personal_access_tokens", GroupID{gid}, serviceAccount), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateServiceAccountPersonalAccessTokenOptions represents the available // CreateServiceAccountPersonalAccessToken() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#create-a-personal-access-token-for-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#create-a-personal-access-token-for-a-group-service-account type CreateServiceAccountPersonalAccessTokenOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` @@ -232,53 +177,35 @@ type CreateServiceAccountPersonalAccessTokenOptions struct { // service account user for a group. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#create-a-personal-access-token-for-a-service-account-user -func (s *GroupsService) CreateServiceAccountPersonalAccessToken(gid any, serviceAccount int, opt *CreateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d/personal_access_tokens", PathEscape(group), serviceAccount) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +// https://docs.gitlab.com/api/service_accounts/#create-a-personal-access-token-for-a-group-service-account +func (s *GroupsService) CreateServiceAccountPersonalAccessToken(gid any, serviceAccount int64, opt *CreateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/service_accounts/%d/personal_access_tokens", GroupID{gid}, serviceAccount), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RevokeServiceAccountPersonalAccessToken revokes a personal access token for an // existing service account user in a given top-level group. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#revoke-a-personal-access-token-for-a-service-account-user -func (s *GroupsService) RevokeServiceAccountPersonalAccessToken(gid any, serviceAccount, token int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d/personal_access_tokens/%d", PathEscape(group), serviceAccount, token) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +// https://docs.gitlab.com/api/service_accounts/#revoke-a-personal-access-token-for-a-group-service-account +func (s *GroupsService) RevokeServiceAccountPersonalAccessToken(gid any, serviceAccount, token int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/service_accounts/%d/personal_access_tokens/%d", GroupID{gid}, serviceAccount, token), + withRequestOpts(options...), + ) + return resp, err } // RotateServiceAccountPersonalAccessTokenOptions represents the available RotateServiceAccountPersonalAccessToken() // options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#rotate-a-personal-access-token-for-a-service-account-user +// https://docs.gitlab.com/api/service_accounts/#rotate-a-personal-access-token-for-a-group-service-account type RotateServiceAccountPersonalAccessTokenOptions struct { ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"` } @@ -287,24 +214,12 @@ type RotateServiceAccountPersonalAccessTokenOptions struct { // service account user for a group. // // GitLab API docs: -// https://docs.gitlab.com/api/group_service_accounts/#rotate-a-personal-access-token-for-a-service-account-user -func (s *GroupsService) RotateServiceAccountPersonalAccessToken(gid any, serviceAccount, token int, opt *RotateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/service_accounts/%d/personal_access_tokens/%d/rotate", PathEscape(group), serviceAccount, token) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +// https://docs.gitlab.com/api/service_accounts/#rotate-a-personal-access-token-for-a-group-service-account +func (s *GroupsService) RotateServiceAccountPersonalAccessToken(gid any, serviceAccount, token int64, opt *RotateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/service_accounts/%d/personal_access_tokens/%d/rotate", GroupID{gid}, serviceAccount, token), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_ssh_certificates.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_ssh_certificates.go index 62774048d..1be649ad9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_ssh_certificates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_ssh_certificates.go @@ -1,7 +1,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -11,7 +10,7 @@ type ( GroupSSHCertificatesServiceInterface interface { ListGroupSSHCertificates(gid any, options ...RequestOptionFunc) ([]*GroupSSHCertificate, *Response, error) CreateGroupSSHCertificate(gid any, opt *CreateGroupSSHCertificateOptions, options ...RequestOptionFunc) (*GroupSSHCertificate, *Response, error) - DeleteGroupSSHCertificate(gid any, cert int, options ...RequestOptionFunc) (*Response, error) + DeleteGroupSSHCertificate(gid any, cert int64, options ...RequestOptionFunc) (*Response, error) } // GroupSSHCertificatesService handles communication with the group @@ -29,7 +28,7 @@ var _ GroupSSHCertificatesServiceInterface = (*GroupSSHCertificatesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/group_ssh_certificates/ type GroupSSHCertificate struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Key string `json:"key"` CreatedAt *time.Time `json:"created_at"` @@ -38,27 +37,13 @@ type GroupSSHCertificate struct { // ListGroupSSHCertificates gets a list of SSH certificates for a specified // group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/group_ssh_certificates/#get-all-ssh-certificates-for-a-particular-group func (s *GroupSSHCertificatesService) ListGroupSSHCertificates(gid any, options ...RequestOptionFunc) ([]*GroupSSHCertificate, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/ssh_certificates", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var certs []*GroupSSHCertificate - resp, err := s.client.Do(req, &certs) - if err != nil { - return nil, resp, err - } - - return certs, resp, nil + return do[[]*GroupSSHCertificate](s.client, + withPath("groups/%s/ssh_certificates", GroupID{gid}), + withRequestOpts(options...), + ) } // CreateGroupSSHCertificateOptions represents the available @@ -73,44 +58,26 @@ type CreateGroupSSHCertificateOptions struct { // CreateGroupSSHCertificate creates a new SSH certificate in the group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/group_ssh_certificates/#create-ssh-certificate func (s *GroupSSHCertificatesService) CreateGroupSSHCertificate(gid any, opt *CreateGroupSSHCertificateOptions, options ...RequestOptionFunc) (*GroupSSHCertificate, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/ssh_certificates", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - cert := new(GroupSSHCertificate) - resp, err := s.client.Do(req, cert) - if err != nil { - return nil, resp, err - } - - return cert, resp, nil + return do[*GroupSSHCertificate](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/ssh_certificates", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupSSHCertificate deletes a SSH certificate from a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/group_ssh_certificates/#delete-group-ssh-certificate -func (s *GroupSSHCertificatesService) DeleteGroupSSHCertificate(gid any, cert int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/ssh_certificates/%d", PathEscape(group), cert) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupSSHCertificatesService) DeleteGroupSSHCertificate(gid any, cert int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/ssh_certificates/%d", GroupID{gid}, cert), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_variables.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_variables.go index ae643a264..f85db4ef6 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_variables.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_variables.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "net/url" ) @@ -25,10 +24,30 @@ import ( type ( // GroupVariablesServiceInterface defines methods for the GroupVariablesService. GroupVariablesServiceInterface interface { + // ListVariables gets a list of all variables for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_level_variables/#list-group-variables ListVariables(gid any, opt *ListGroupVariablesOptions, options ...RequestOptionFunc) ([]*GroupVariable, *Response, error) + // GetVariable gets a variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_level_variables/#show-variable-details GetVariable(gid any, key string, opt *GetGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) + // CreateVariable creates a new group variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_level_variables/#create-variable CreateVariable(gid any, opt *CreateGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) + // UpdateVariable updates an existing group variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_level_variables/#update-variable UpdateVariable(gid any, key string, opt *UpdateGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) + // RemoveVariable removes a group's variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_level_variables/#remove-variable RemoveVariable(gid any, key string, opt *RemoveGroupVariableOptions, options ...RequestOptionFunc) (*Response, error) } @@ -69,31 +88,16 @@ func (v GroupVariable) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/group_level_variables/#list-group-variables -type ListGroupVariablesOptions ListOptions +type ListGroupVariablesOptions struct { + ListOptions +} -// ListVariables gets a list of all variables for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_level_variables/#list-group-variables func (s *GroupVariablesService) ListVariables(gid any, opt *ListGroupVariablesOptions, options ...RequestOptionFunc) ([]*GroupVariable, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/variables", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var vs []*GroupVariable - resp, err := s.client.Do(req, &vs) - if err != nil { - return nil, resp, err - } - - return vs, resp, nil + return do[[]*GroupVariable](s.client, + withPath("groups/%s/variables", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupVariableOptions represents the available GetVariable() @@ -105,29 +109,12 @@ type GetGroupVariableOptions struct { Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"` } -// GetVariable gets a variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_level_variables/#show-variable-details func (s *GroupVariablesService) GetVariable(gid any, key string, opt *GetGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/variables/%s", PathEscape(group), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(GroupVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*GroupVariable](s.client, + withPath("groups/%s/variables/%s", GroupID{gid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateGroupVariableOptions represents the available CreateVariable() @@ -147,29 +134,13 @@ type CreateGroupVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// CreateVariable creates a new group variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_level_variables/#create-variable func (s *GroupVariablesService) CreateVariable(gid any, opt *CreateGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/variables", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(GroupVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*GroupVariable](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/variables", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateGroupVariableOptions represents the available UpdateVariable() @@ -188,30 +159,13 @@ type UpdateGroupVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// UpdateVariable updates the position of an existing -// group issue board list. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_level_variables/#update-variable func (s *GroupVariablesService) UpdateVariable(gid any, key string, opt *UpdateGroupVariableOptions, options ...RequestOptionFunc) (*GroupVariable, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/variables/%s", PathEscape(group), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(GroupVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*GroupVariable](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/variables/%s", GroupID{gid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveGroupVariableOptions represents the available RemoveVariable() @@ -223,21 +177,12 @@ type RemoveGroupVariableOptions struct { Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"` } -// RemoveVariable removes a group's variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_level_variables/#remove-variable func (s *GroupVariablesService) RemoveVariable(gid any, key string, opt *RemoveGroupVariableOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/variables/%s", PathEscape(group), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/variables/%s", GroupID{gid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/group_wikis.go b/vendor/gitlab.com/gitlab-org/api/client-go/group_wikis.go index b04fd9983..c78eedbc1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/group_wikis.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/group_wikis.go @@ -16,9 +16,7 @@ package gitlab import ( - "fmt" "net/http" - "net/url" ) type ( @@ -32,7 +30,7 @@ type ( } // GroupWikisService handles communication with the group wikis related methods of - // the Gitlab API. + // the GitLab API. // // GitLab API docs: https://docs.gitlab.com/api/group_wikis/ GroupWikisService struct { @@ -71,24 +69,11 @@ type ListGroupWikisOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_wikis/#list-wiki-pages func (s *GroupWikisService) ListGroupWikis(gid any, opt *ListGroupWikisOptions, options ...RequestOptionFunc) ([]*GroupWiki, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/wikis", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gws []*GroupWiki - resp, err := s.client.Do(req, &gws) - if err != nil { - return nil, resp, err - } - - return gws, resp, nil + return do[[]*GroupWiki](s.client, + withPath("groups/%s/wikis", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupWikiPageOptions represents options to GetGroupWikiPage @@ -105,24 +90,11 @@ type GetGroupWikiPageOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_wikis/#get-a-wiki-page func (s *GroupWikisService) GetGroupWikiPage(gid any, slug string, opt *GetGroupWikiPageOptions, options ...RequestOptionFunc) (*GroupWiki, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/wikis/%s", PathEscape(group), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - gw := new(GroupWiki) - resp, err := s.client.Do(req, gw) - if err != nil { - return nil, resp, err - } - - return gw, resp, nil + return do[*GroupWiki](s.client, + withPath("groups/%s/wikis/%s", GroupID{gid}, slug), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateGroupWikiPageOptions represents options to CreateGroupWikiPage. @@ -141,24 +113,12 @@ type CreateGroupWikiPageOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_wikis/#create-a-new-wiki-page func (s *GroupWikisService) CreateGroupWikiPage(gid any, opt *CreateGroupWikiPageOptions, options ...RequestOptionFunc) (*GroupWiki, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/wikis", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - w := new(GroupWiki) - resp, err := s.client.Do(req, w) - if err != nil { - return nil, resp, err - } - - return w, resp, nil + return do[*GroupWiki](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/wikis", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditGroupWikiPageOptions represents options to EditGroupWikiPage. @@ -177,24 +137,12 @@ type EditGroupWikiPageOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_wikis/#edit-an-existing-wiki-page func (s *GroupWikisService) EditGroupWikiPage(gid any, slug string, opt *EditGroupWikiPageOptions, options ...RequestOptionFunc) (*GroupWiki, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/wikis/%s", PathEscape(group), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - w := new(GroupWiki) - resp, err := s.client.Do(req, w) - if err != nil { - return nil, resp, err - } - - return w, resp, nil + return do[*GroupWiki](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/wikis/%s", GroupID{gid}, slug), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupWikiPage deletes a wiki page with a given slug. @@ -202,16 +150,10 @@ func (s *GroupWikisService) EditGroupWikiPage(gid any, slug string, opt *EditGro // GitLab API docs: // https://docs.gitlab.com/api/group_wikis/#delete-a-wiki-page func (s *GroupWikisService) DeleteGroupWikiPage(gid any, slug string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/wikis/%s", PathEscape(group), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/wikis/%s", GroupID{gid}, slug), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/groups.go b/vendor/gitlab.com/gitlab-org/api/client-go/groups.go index a45313428..c288b455c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/groups.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/groups.go @@ -19,14 +19,12 @@ package gitlab import ( "bytes" "encoding/json" - "fmt" + "errors" "io" "net/http" "net/url" "strconv" "time" - - retryablehttp "github.com/hashicorp/go-retryablehttp" ) type ( @@ -57,7 +55,7 @@ type ( AddGroupSAMLLink(gid any, opt *AddGroupSAMLLinkOptions, options ...RequestOptionFunc) (*SAMLGroupLink, *Response, error) DeleteGroupSAMLLink(gid any, samlGroupName string, options ...RequestOptionFunc) (*Response, error) ShareGroupWithGroup(gid any, opt *ShareGroupWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) - UnshareGroupFromGroup(gid any, groupID int, options ...RequestOptionFunc) (*Response, error) + UnshareGroupFromGroup(gid any, groupID int64, options ...RequestOptionFunc) (*Response, error) GetGroupPushRules(gid any, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) AddGroupPushRule(gid any, opt *AddGroupPushRuleOptions, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) EditGroupPushRule(gid any, opt *EditGroupPushRuleOptions, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) @@ -65,33 +63,33 @@ type ( // group_hooks.go ListGroupHooks(gid any, opt *ListGroupHooksOptions, options ...RequestOptionFunc) ([]*GroupHook, *Response, error) - GetGroupHook(gid any, hook int, options ...RequestOptionFunc) (*GroupHook, *Response, error) - ResendGroupHookEvent(gid any, hook int, hookEventID int, options ...RequestOptionFunc) (*Response, error) + GetGroupHook(gid any, hook int64, options ...RequestOptionFunc) (*GroupHook, *Response, error) + ResendGroupHookEvent(gid any, hook int64, hookEventID int64, options ...RequestOptionFunc) (*Response, error) AddGroupHook(gid any, opt *AddGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) - EditGroupHook(gid any, hook int, opt *EditGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) - DeleteGroupHook(gid any, hook int, options ...RequestOptionFunc) (*Response, error) - TriggerTestGroupHook(pid any, hook int, trigger GroupHookTrigger, options ...RequestOptionFunc) (*Response, error) - SetGroupCustomHeader(gid any, hook int, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) - DeleteGroupCustomHeader(gid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) - SetGroupHookURLVariable(gid any, hook int, key string, opt *SetHookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) - DeleteGroupHookURLVariable(gid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) + EditGroupHook(gid any, hook int64, opt *EditGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) + DeleteGroupHook(gid any, hook int64, options ...RequestOptionFunc) (*Response, error) + TriggerTestGroupHook(pid any, hook int64, trigger GroupHookTrigger, options ...RequestOptionFunc) (*Response, error) + SetGroupCustomHeader(gid any, hook int64, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) + DeleteGroupCustomHeader(gid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) + SetGroupHookURLVariable(gid any, hook int64, key string, opt *SetHookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) + DeleteGroupHookURLVariable(gid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) // group_serviceaccounts.go ListServiceAccounts(gid any, opt *ListServiceAccountsOptions, options ...RequestOptionFunc) ([]*GroupServiceAccount, *Response, error) CreateServiceAccount(gid any, opt *CreateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) - UpdateServiceAccount(gid any, serviceAccount int, opt *UpdateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) - DeleteServiceAccount(gid any, serviceAccount int, opt *DeleteServiceAccountOptions, options ...RequestOptionFunc) (*Response, error) - ListServiceAccountPersonalAccessTokens(gid any, serviceAccount int, opt *ListServiceAccountPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) - CreateServiceAccountPersonalAccessToken(gid any, serviceAccount int, opt *CreateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) - RevokeServiceAccountPersonalAccessToken(gid any, serviceAccount, token int, options ...RequestOptionFunc) (*Response, error) - RotateServiceAccountPersonalAccessToken(gid any, serviceAccount, token int, opt *RotateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + UpdateServiceAccount(gid any, serviceAccount int64, opt *UpdateServiceAccountOptions, options ...RequestOptionFunc) (*GroupServiceAccount, *Response, error) + DeleteServiceAccount(gid any, serviceAccount int64, opt *DeleteServiceAccountOptions, options ...RequestOptionFunc) (*Response, error) + ListServiceAccountPersonalAccessTokens(gid any, serviceAccount int64, opt *ListServiceAccountPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) + CreateServiceAccountPersonalAccessToken(gid any, serviceAccount int64, opt *CreateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + RevokeServiceAccountPersonalAccessToken(gid any, serviceAccount, token int64, options ...RequestOptionFunc) (*Response, error) + RotateServiceAccountPersonalAccessToken(gid any, serviceAccount, token int64, opt *RotateServiceAccountPersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) // group_members.go ListGroupMembers(gid any, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) ListAllGroupMembers(gid any, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) ListBillableGroupMembers(gid any, opt *ListBillableGroupMembersOptions, options ...RequestOptionFunc) ([]*BillableGroupMember, *Response, error) - ListMembershipsForBillableGroupMember(gid any, user int, opt *ListMembershipsForBillableGroupMemberOptions, options ...RequestOptionFunc) ([]*BillableUserMembership, *Response, error) - RemoveBillableGroupMember(gid any, user int, options ...RequestOptionFunc) (*Response, error) + ListMembershipsForBillableGroupMember(gid any, user int64, opt *ListMembershipsForBillableGroupMemberOptions, options ...RequestOptionFunc) ([]*BillableUserMembership, *Response, error) + RemoveBillableGroupMember(gid any, user int64, options ...RequestOptionFunc) (*Response, error) } // GroupsService handles communication with the group related methods of @@ -109,13 +107,14 @@ var _ GroupsServiceInterface = (*GroupsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/groups/ type Group struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Path string `json:"path"` Description string `json:"description"` MembershipLock bool `json:"membership_lock"` Visibility VisibilityValue `json:"visibility"` LFSEnabled bool `json:"lfs_enabled"` + MaxArtifactsSize int64 `json:"max_artifacts_size"` DefaultBranch string `json:"default_branch"` DefaultBranchProtectionDefaults *BranchProtectionDefaults `json:"default_branch_protection_defaults"` AvatarURL string `json:"avatar_url"` @@ -124,13 +123,13 @@ type Group struct { RepositoryStorage string `json:"repository_storage"` FullName string `json:"full_name"` FullPath string `json:"full_path"` - FileTemplateProjectID int `json:"file_template_project_id"` - ParentID int `json:"parent_id"` + FileTemplateProjectID int64 `json:"file_template_project_id"` + ParentID int64 `json:"parent_id"` Statistics *Statistics `json:"statistics"` CustomAttributes []*CustomAttribute `json:"custom_attributes"` ShareWithGroupLock bool `json:"share_with_group_lock"` RequireTwoFactorAuth bool `json:"require_two_factor_authentication"` - TwoFactorGracePeriod int `json:"two_factor_grace_period"` + TwoFactorGracePeriod int64 `json:"two_factor_grace_period"` ProjectCreationLevel ProjectCreationLevelValue `json:"project_creation_level"` AutoDevopsEnabled bool `json:"auto_devops_enabled"` SubGroupCreationLevel SubGroupCreationLevelValue `json:"subgroup_creation_level"` @@ -143,8 +142,8 @@ type Group struct { LDAPAccess AccessLevelValue `json:"ldap_access"` LDAPGroupLinks []*LDAPGroupLink `json:"ldap_group_links"` SAMLGroupLinks []*SAMLGroupLink `json:"saml_group_links"` - SharedRunnersMinutesLimit int `json:"shared_runners_minutes_limit"` - ExtraSharedRunnersMinutesLimit int `json:"extra_shared_runners_minutes_limit"` + SharedRunnersMinutesLimit int64 `json:"shared_runners_minutes_limit"` + ExtraSharedRunnersMinutesLimit int64 `json:"extra_shared_runners_minutes_limit"` PreventForkingOutsideGroup bool `json:"prevent_forking_outside_group"` MarkedForDeletionOn *ISOTime `json:"marked_for_deletion_on"` CreatedAt *time.Time `json:"created_at"` @@ -152,6 +151,10 @@ type Group struct { AllowedEmailDomainsList string `json:"allowed_email_domains_list"` WikiAccessLevel AccessControlValue `json:"wiki_access_level"` + OnlyAllowMergeIfPipelineSucceeds bool `json:"only_allow_merge_if_pipeline_succeeds"` + AllowMergeOnSkippedPipeline bool `json:"allow_merge_on_skipped_pipeline"` + OnlyAllowMergeIfAllDiscussionsAreResolved bool `json:"only_allow_merge_if_all_discussions_are_resolved"` + // Deprecated: will be removed in v5 of the API, use ListGroupProjects instead Projects []*Project `json:"projects"` @@ -162,19 +165,19 @@ type Group struct { EmailsDisabled bool `json:"emails_disabled"` // Deprecated: Use DefaultBranchProtectionDefaults instead - DefaultBranchProtection int `json:"default_branch_protection"` + DefaultBranchProtection int64 `json:"default_branch_protection"` } // SharedWithGroup represents a GitLab group shared with a group. // // GitLab API docs: https://docs.gitlab.com/api/groups/ type SharedWithGroup struct { - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` GroupName string `json:"group_name"` GroupFullPath string `json:"group_full_path"` - GroupAccessLevel int `json:"group_access_level"` + GroupAccessLevel int64 `json:"group_access_level"` ExpiresAt *ISOTime `json:"expires_at"` - MemberRoleID int `json:"member_role_id"` + MemberRoleID int64 `json:"member_role_id"` } // BranchProtectionDefaults represents default Git protected branch permissions. @@ -182,10 +185,11 @@ type SharedWithGroup struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#options-for-default_branch_protection_defaults type BranchProtectionDefaults struct { - AllowedToPush []*GroupAccessLevel `json:"allowed_to_push,omitempty"` - AllowForcePush bool `json:"allow_force_push,omitempty"` - AllowedToMerge []*GroupAccessLevel `json:"allowed_to_merge,omitempty"` - DeveloperCanInitialPush bool `json:"developer_can_initial_push,omitempty"` + AllowedToPush []*GroupAccessLevel `json:"allowed_to_push,omitempty"` + AllowForcePush bool `json:"allow_force_push,omitempty"` + AllowedToMerge []*GroupAccessLevel `json:"allowed_to_merge,omitempty"` + DeveloperCanInitialPush bool `json:"developer_can_initial_push,omitempty"` + CodeOwnerApprovalRequired bool `json:"code_owner_approval_required,omitempty"` } // GroupAccessLevel represents default branch protection defaults access levels. @@ -231,7 +235,8 @@ type LDAPGroupLink struct { type SAMLGroupLink struct { Name string `json:"name"` AccessLevel AccessLevelValue `json:"access_level"` - MemberRoleID int `json:"member_role_id,omitempty"` + MemberRoleID int64 `json:"member_role_id,omitempty"` + Provider string `json:"provider,omitempty"` } // ListGroupsOptions represents the available ListGroups() options. @@ -239,17 +244,21 @@ type SAMLGroupLink struct { // GitLab API docs: https://docs.gitlab.com/api/groups/#list-groups type ListGroupsOptions struct { ListOptions - SkipGroups *[]int `url:"skip_groups,omitempty" del:"," json:"skip_groups,omitempty"` + SkipGroups *[]int64 `url:"skip_groups,omitempty" del:"," json:"skip_groups,omitempty"` AllAvailable *bool `url:"all_available,omitempty" json:"all_available,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"` + Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"` Owned *bool `url:"owned,omitempty" json:"owned,omitempty"` MinAccessLevel *AccessLevelValue `url:"min_access_level,omitempty" json:"min_access_level,omitempty"` TopLevelOnly *bool `url:"top_level_only,omitempty" json:"top_level_only,omitempty"` RepositoryStorage *string `url:"repository_storage,omitempty" json:"repository_storage,omitempty"` + MarkedForDeletionOn *ISOTime `url:"marked_for_deletion_on,omitempty" json:"marked_for_deletion_on,omitempty"` + Active *bool `url:"active,omitempty" json:"active,omitempty"` + Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` } // ListGroups gets a list of groups (as user: my groups, as admin: all groups). @@ -257,18 +266,11 @@ type ListGroupsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-groups func (s *GroupsService) ListGroups(opt *ListGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "groups", opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*Group - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*Group](s.client, + withPath("groups"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListSubGroupsOptions represents the available ListSubGroups() options. @@ -282,24 +284,11 @@ type ListSubGroupsOptions ListGroupsOptions // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-subgroups func (s *GroupsService) ListSubGroups(gid any, opt *ListSubGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/subgroups", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*Group - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*Group](s.client, + withPath("groups/%s/subgroups", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListDescendantGroupsOptions represents the available ListDescendantGroups() @@ -314,32 +303,20 @@ type ListDescendantGroupsOptions ListGroupsOptions // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-descendant-groups func (s *GroupsService) ListDescendantGroups(gid any, opt *ListDescendantGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/descendant_groups", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var gs []*Group - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*Group](s.client, + withPath("groups/%s/descendant_groups", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListGroupProjectsOptions represents the available ListGroup() options. +// ListGroupProjectsOptions represents the available ListGroupProjects() options. // // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-projects type ListGroupProjectsOptions struct { ListOptions + Active *bool `url:"active,omitempty" json:"active,omitempty"` Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` IncludeSubGroups *bool `url:"include_subgroups,omitempty" json:"include_subgroups,omitempty"` MinAccessLevel *AccessLevelValue `url:"min_access_level,omitempty" json:"min_access_level,omitempty"` @@ -363,24 +340,11 @@ type ListGroupProjectsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-projects func (s *GroupsService) ListGroupProjects(gid any, opt *ListGroupProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/projects", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Project - resp, err := s.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*Project](s.client, + withPath("groups/%s/projects", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupOptions represents the available GetGroup() options. @@ -398,24 +362,11 @@ type GetGroupOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/groups/#get-a-single-group func (s *GroupsService) GetGroup(gid any, opt *GetGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withPath("groups/%s", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DownloadAvatar downloads a group avatar. @@ -423,24 +374,14 @@ func (s *GroupsService) GetGroup(gid any, opt *GetGroupOptions, options ...Reque // GitLab API docs: // https://docs.gitlab.com/api/groups/#download-a-group-avatar func (s *GroupsService) DownloadAvatar(gid any, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/avatar", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - avatar := new(bytes.Buffer) - resp, err := s.client.Do(req, avatar) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("groups/%s/avatar", GroupID{gid}), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return bytes.NewReader(avatar.Bytes()), resp, err + return bytes.NewReader(buf.Bytes()), resp, nil } // CreateGroupOptions represents the available CreateGroup() options. @@ -456,7 +397,7 @@ type CreateGroupOptions struct { Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` ShareWithGroupLock *bool `url:"share_with_group_lock,omitempty" json:"share_with_group_lock,omitempty"` RequireTwoFactorAuth *bool `url:"require_two_factor_authentication,omitempty" json:"require_two_factor_authentication,omitempty"` - TwoFactorGracePeriod *int `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` + TwoFactorGracePeriod *int64 `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` ProjectCreationLevel *ProjectCreationLevelValue `url:"project_creation_level,omitempty" json:"project_creation_level,omitempty"` AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"` SubGroupCreationLevel *SubGroupCreationLevelValue `url:"subgroup_creation_level,omitempty" json:"subgroup_creation_level,omitempty"` @@ -465,16 +406,21 @@ type CreateGroupOptions struct { LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` DefaultBranchProtectionDefaults *DefaultBranchProtectionDefaultsOptions `url:"default_branch_protection_defaults,omitempty" json:"default_branch_protection_defaults,omitempty"` RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"` - ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` - SharedRunnersMinutesLimit *int `url:"shared_runners_minutes_limit,omitempty" json:"shared_runners_minutes_limit,omitempty"` - ExtraSharedRunnersMinutesLimit *int `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"` + ParentID *int64 `url:"parent_id,omitempty" json:"parent_id,omitempty"` + SharedRunnersMinutesLimit *int64 `url:"shared_runners_minutes_limit,omitempty" json:"shared_runners_minutes_limit,omitempty"` + ExtraSharedRunnersMinutesLimit *int64 `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"` WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"` // Deprecated: Use EmailsEnabled instead EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"` // Deprecated: User DefaultBranchProtectionDefaults instead - DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + DefaultBranchProtection *int64 `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + + EnabledGitAccessProtocol *EnabledGitAccessProtocolValue `url:"enabled_git_access_protocol,omitempty" json:"enabled_git_access_protocol,omitempty"` + OrganizationID *int64 `url:"organization_id,omitempty" json:"organization_id,omitempty"` + DuoAvailability *DuoAvailabilityValue `url:"duo_availability,omitempty" json:"duo_availability,omitempty"` + ExperimentFeaturesEnabled *bool `url:"experiment_features_enabled,omitempty" json:"experiment_features_enabled,omitempty"` } // DefaultBranchProtectionDefaultsOptions represents the available options for @@ -483,10 +429,11 @@ type CreateGroupOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#options-for-default_branch_protection_defaults type DefaultBranchProtectionDefaultsOptions struct { - AllowedToPush *[]*GroupAccessLevel `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` - AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` - AllowedToMerge *[]*GroupAccessLevel `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` - DeveloperCanInitialPush *bool `url:"developer_can_initial_push,omitempty" json:"developer_can_initial_push,omitempty"` + AllowedToPush *[]*GroupAccessLevel `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` + AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` + AllowedToMerge *[]*GroupAccessLevel `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` + DeveloperCanInitialPush *bool `url:"developer_can_initial_push,omitempty" json:"developer_can_initial_push,omitempty"` + CodeOwnerApprovalRequired *bool `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"` } // EncodeValues implements the query.Encoder interface @@ -497,13 +444,16 @@ func (d *DefaultBranchProtectionDefaultsOptions) EncodeValues(key string, v *url if d.DeveloperCanInitialPush != nil { v.Add(key+"[developer_can_initial_push]", strconv.FormatBool(*d.DeveloperCanInitialPush)) } + if d.CodeOwnerApprovalRequired != nil { + v.Add(key+"[code_owner_approval_required]", strconv.FormatBool(*d.CodeOwnerApprovalRequired)) + } // The GitLab API only accepts one value for `allowed_to_merge` even when multiples are // provided on the request. The API will take the highest permission level. For instance, // if 'developer' and 'maintainer' are provided, the API will take 'maintainer'. if d.AllowedToMerge != nil { for _, atm := range *d.AllowedToMerge { if atm != nil { - v.Add(key+"[allowed_to_merge][][access_level]", strconv.Itoa((int)(*atm.AccessLevel))) + v.Add(key+"[allowed_to_merge][][access_level]", strconv.FormatInt((int64)(*atm.AccessLevel), 10)) } } } @@ -513,10 +463,11 @@ func (d *DefaultBranchProtectionDefaultsOptions) EncodeValues(key string, v *url if d.AllowedToPush != nil { for _, atp := range *d.AllowedToPush { if atp != nil { - v.Add(key+"[allowed_to_push][][access_level]", strconv.Itoa((int)(*atp.AccessLevel))) + v.Add(key+"[allowed_to_push][][access_level]", strconv.FormatInt((int64)(*atp.AccessLevel), 10)) } } } + return nil } @@ -531,38 +482,19 @@ func (d *DefaultBranchProtectionDefaultsOptions) EncodeValues(key string, v *url // // GitLab API docs: https://docs.gitlab.com/api/groups/#create-a-group func (s *GroupsService) CreateGroup(opt *CreateGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - var err error - var req *retryablehttp.Request - - if opt.Avatar == nil { - req, err = s.client.NewRequest(http.MethodPost, "groups", opt, options) - } else { - // since the Avatar is provided, check allowed_to_push and - // allowed_to_merge access levels and error if multiples are provided + reqOpts := []doOption{ + withMethod(http.MethodPost), + withPath("groups"), + withAPIOpts(opt), + withRequestOpts(options...), + } + if opt.Avatar != nil { if opt.DefaultBranchProtectionDefaults != nil && (len(*opt.DefaultBranchProtectionDefaults.AllowedToMerge) > 1 || len(*opt.DefaultBranchProtectionDefaults.AllowedToPush) > 1) { - return nil, nil, fmt.Errorf("multiple access levels for allowed_to_merge or allowed_to_push are not permitted when an Avatar is also specified as it will result in unexpected behavior") + return nil, nil, errors.New("multiple access levels for allowed_to_merge or allowed_to_push are not permitted when an Avatar is also specified as it will result in unexpected behavior") } - req, err = s.client.UploadRequest( - http.MethodPost, - "groups", - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) - } - if err != nil { - return nil, nil, err + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, reqOpts...) } // TransferGroup transfers a project to the Group namespace. Available only @@ -571,28 +503,11 @@ func (s *GroupsService) CreateGroup(opt *CreateGroupOptions, options ...RequestO // GitLab API docs: // https://docs.gitlab.com/api/groups/#transfer-a-project-to-a-group func (s *GroupsService) TransferGroup(gid any, pid any, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/projects/%s", PathEscape(group), PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/projects/%s", GroupID{gid}, ProjectID{pid}), + withRequestOpts(options...), + ) } // TransferSubGroupOptions represents the available TransferSubGroup() options. @@ -600,7 +515,7 @@ func (s *GroupsService) TransferGroup(gid any, pid any, options ...RequestOption // GitLab API docs: // https://docs.gitlab.com/api/groups/#transfer-a-group type TransferSubGroupOptions struct { - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` } // TransferSubGroup transfers a group to a new parent group or turn a subgroup @@ -609,24 +524,12 @@ type TransferSubGroupOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#transfer-a-group func (s *GroupsService) TransferSubGroup(gid any, opt *TransferSubGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/transfer", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/transfer", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateGroupOptions represents the available UpdateGroup() options. @@ -642,18 +545,19 @@ type UpdateGroupOptions struct { Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` ShareWithGroupLock *bool `url:"share_with_group_lock,omitempty" json:"share_with_group_lock,omitempty"` RequireTwoFactorAuth *bool `url:"require_two_factor_authentication,omitempty" json:"require_two_factor_authentication,omitempty"` - TwoFactorGracePeriod *int `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` + TwoFactorGracePeriod *int64 `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` ProjectCreationLevel *ProjectCreationLevelValue `url:"project_creation_level,omitempty" json:"project_creation_level,omitempty"` AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"` SubGroupCreationLevel *SubGroupCreationLevelValue `url:"subgroup_creation_level,omitempty" json:"subgroup_creation_level,omitempty"` EmailsEnabled *bool `url:"emails_enabled,omitempty" json:"emails_enabled,omitempty"` MentionsDisabled *bool `url:"mentions_disabled,omitempty" json:"mentions_disabled,omitempty"` LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` + MaxArtifactsSize *int64 `url:"max_artifacts_size,omitempty" json:"max_artifacts_size,omitempty"` RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"` DefaultBranchProtectionDefaults *DefaultBranchProtectionDefaultsOptions `url:"default_branch_protection_defaults,omitempty" json:"default_branch_protection_defaults,omitempty"` - FileTemplateProjectID *int `url:"file_template_project_id,omitempty" json:"file_template_project_id,omitempty"` - SharedRunnersMinutesLimit *int `url:"shared_runners_minutes_limit,omitempty" json:"shared_runners_minutes_limit,omitempty"` - ExtraSharedRunnersMinutesLimit *int `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"` + FileTemplateProjectID *int64 `url:"file_template_project_id,omitempty" json:"file_template_project_id,omitempty"` + SharedRunnersMinutesLimit *int64 `url:"shared_runners_minutes_limit,omitempty" json:"shared_runners_minutes_limit,omitempty"` + ExtraSharedRunnersMinutesLimit *int64 `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"` PreventForkingOutsideGroup *bool `url:"prevent_forking_outside_group,omitempty" json:"prevent_forking_outside_group,omitempty"` SharedRunnersSetting *SharedRunnersSettingValue `url:"shared_runners_setting,omitempty" json:"shared_runners_setting,omitempty"` PreventSharingGroupsOutsideHierarchy *bool `url:"prevent_sharing_groups_outside_hierarchy,omitempty" json:"prevent_sharing_groups_outside_hierarchy,omitempty"` @@ -661,11 +565,33 @@ type UpdateGroupOptions struct { AllowedEmailDomainsList *string `url:"allowed_email_domains_list,omitempty" json:"allowed_email_domains_list,omitempty"` WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"` + OnlyAllowMergeIfPipelineSucceeds *bool `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"` + AllowMergeOnSkippedPipeline *bool `url:"allow_merge_on_skipped_pipeline,omitempty" json:"allow_merge_on_skipped_pipeline,omitempty"` + OnlyAllowMergeIfAllDiscussionsAreResolved *bool `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"` + // Deprecated: Use EmailsEnabled instead EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"` // Deprecated: Use DefaultBranchProtectionDefaults instead - DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + DefaultBranchProtection *int64 `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + EnabledGitAccessProtocol *EnabledGitAccessProtocolValue `url:"enabled_git_access_protocol,omitempty" json:"enabled_git_access_protocol,omitempty"` + StepUpAuthRequiredOAuthProvider *string `url:"step_up_auth_required_oauth_provider,omitempty" json:"step_up_auth_required_oauth_provider,omitempty"` + // The following fields are Premium and Ultimate only. + UniqueProjectDownloadLimit *int64 `url:"unique_project_download_limit,omitempty" json:"unique_project_download_limit,omitempty"` + UniqueProjectDownloadLimitIntervalInSeconds *int64 `url:"unique_project_download_limit_interval_in_seconds,omitempty" json:"unique_project_download_limit_interval_in_seconds,omitempty"` + UniqueProjectDownloadLimitAllowlist *[]string `url:"unique_project_download_limit_allowlist,omitempty" json:"unique_project_download_limit_allowlist,omitempty"` + UniqueProjectDownloadLimitAlertlist *[]int64 `url:"unique_project_download_limit_alertlist,omitempty" json:"unique_project_download_limit_alertlist,omitempty"` + AutoBanUserOnExcessiveProjectsDownload *bool `url:"auto_ban_user_on_excessive_projects_download,omitempty" json:"auto_ban_user_on_excessive_projects_download,omitempty"` + + DuoAvailability *DuoAvailabilityValue `url:"duo_availability,omitempty" json:"duo_availability,omitempty"` + ExperimentFeaturesEnabled *bool `url:"experiment_features_enabled,omitempty" json:"experiment_features_enabled,omitempty"` + MathRenderingLimitsEnabled *bool `url:"math_rendering_limits_enabled,omitempty" json:"math_rendering_limits_enabled,omitempty"` + LockMathRenderingLimitsEnabled *bool `url:"lock_math_rendering_limits_enabled,omitempty" json:"lock_math_rendering_limits_enabled,omitempty"` + DuoFeaturesEnabled *bool `url:"duo_features_enabled,omitempty" json:"duo_features_enabled,omitempty"` + LockDuoFeaturesEnabled *bool `url:"lock_duo_features_enabled,omitempty" json:"lock_duo_features_enabled,omitempty"` + + WebBasedCommitSigningEnabled *bool `url:"web_based_commit_signing_enabled,omitempty" json:"web_based_commit_signing_enabled,omitempty"` + AllowPersonalSnippets *bool `url:"allow_personal_snippets,omitempty" json:"allow_personal_snippets,omitempty"` } // UpdateGroup updates an existing group; only available to group owners and @@ -679,43 +605,19 @@ type UpdateGroupOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/groups/#update-group-attributes func (s *GroupsService) UpdateGroup(gid any, opt *UpdateGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err + reqOpts := []doOption{ + withMethod(http.MethodPut), + withPath("groups/%s", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), } - u := fmt.Sprintf("groups/%s", PathEscape(group)) - - var req *retryablehttp.Request - - if opt.Avatar == nil || (opt.Avatar.Filename == "" && opt.Avatar.Image == nil) { - req, err = s.client.NewRequest(http.MethodPut, u, opt, options) - } else { - // since the Avatar is provided, check allowed_to_push and - // allowed_to_merge access levels and error if multiples are provided + if opt.Avatar != nil && (opt.Avatar.Filename != "" || opt.Avatar.Image != nil) { if opt.DefaultBranchProtectionDefaults != nil && (len(*opt.DefaultBranchProtectionDefaults.AllowedToMerge) > 1 || len(*opt.DefaultBranchProtectionDefaults.AllowedToPush) > 1) { - return nil, nil, fmt.Errorf("multiple access levels for allowed_to_merge or allowed_to_push are not permitted when an Avatar is also specified as it will result in unexpected behavior") + return nil, nil, errors.New("multiple access levels for allowed_to_merge or allowed_to_push are not permitted when an Avatar is also specified as it will result in unexpected behavior") } - req, err = s.client.UploadRequest( - http.MethodPut, - u, - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, reqOpts...) } // UploadAvatar uploads a group avatar. @@ -723,32 +625,12 @@ func (s *GroupsService) UpdateGroup(gid any, opt *UpdateGroupOptions, options .. // GitLab API docs: // https://docs.gitlab.com/api/groups/#upload-a-group-avatar func (s *GroupsService) UploadAvatar(gid any, avatar io.Reader, filename string, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s", PathEscape(group)) - - req, err := s.client.UploadRequest( - http.MethodPut, - u, - avatar, - filename, - UploadAvatar, - nil, - options, + return do[*Group](s.client, + withMethod(http.MethodPut), + withPath("groups/%s", GroupID{gid}), + withUpload(avatar, filename, UploadAvatar), + withRequestOpts(options...), ) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil } // DeleteGroupOptions represents the available DeleteGroup() options. @@ -763,18 +645,13 @@ type DeleteGroupOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/groups/#delete-a-group func (s *GroupsService) DeleteGroup(gid any, opt *DeleteGroupOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // RestoreGroup restores a previously deleted group @@ -782,24 +659,11 @@ func (s *GroupsService) DeleteGroup(gid any, opt *DeleteGroupOptions, options .. // GitLab API docs: // https://docs.gitlab.com/api/groups/#restore-a-group-marked-for-deletion func (s *GroupsService) RestoreGroup(gid any, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/restore", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/restore", GroupID{gid}), + withRequestOpts(options...), + ) } // SearchGroup get all groups that match your string in their name or path. @@ -811,18 +675,11 @@ func (s *GroupsService) SearchGroup(query string, options ...RequestOptionFunc) } q.Search = query - req, err := s.client.NewRequest(http.MethodGet, "groups", &q, options) - if err != nil { - return nil, nil, err - } - - var gs []*Group - resp, err := s.client.Do(req, &gs) - if err != nil { - return nil, resp, err - } - - return gs, resp, nil + return do[[]*Group](s.client, + withPath("groups"), + withAPIOpts(&q), + withRequestOpts(options...), + ) } // ListProvisionedUsersOptions represents the available ListProvisionedUsers() @@ -845,24 +702,11 @@ type ListProvisionedUsersOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-provisioned-users func (s *GroupsService) ListProvisionedUsers(gid any, opt *ListProvisionedUsersOptions, options ...RequestOptionFunc) ([]*User, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/provisioned_users", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var us []*User - resp, err := s.client.Do(req, &us) - if err != nil { - return nil, resp, err - } - - return us, resp, nil + return do[[]*User](s.client, + withPath("groups/%s/provisioned_users", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListGroupLDAPLinks lists the group's LDAP links. Available only for users who @@ -871,24 +715,10 @@ func (s *GroupsService) ListProvisionedUsers(gid any, opt *ListProvisionedUsersO // GitLab API docs: // https://docs.gitlab.com/api/group_ldap_links/#list-ldap-group-links func (s *GroupsService) ListGroupLDAPLinks(gid any, options ...RequestOptionFunc) ([]*LDAPGroupLink, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/ldap_group_links", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var gls []*LDAPGroupLink - resp, err := s.client.Do(req, &gls) - if err != nil { - return nil, resp, err - } - - return gls, resp, nil + return do[[]*LDAPGroupLink](s.client, + withPath("groups/%s/ldap_group_links", GroupID{gid}), + withRequestOpts(options...), + ) } // AddGroupLDAPLinkOptions represents the available AddGroupLDAPLink() options. @@ -909,24 +739,12 @@ type AddGroupLDAPLinkOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_ldap_links/#add-an-ldap-group-link-with-cn-or-filter func (s *GroupsService) AddGroupLDAPLink(gid any, opt *AddGroupLDAPLinkOptions, options ...RequestOptionFunc) (*LDAPGroupLink, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/ldap_group_links", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gl := new(LDAPGroupLink) - resp, err := s.client.Do(req, gl) - if err != nil { - return nil, resp, err - } - - return gl, resp, nil + return do[*LDAPGroupLink](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/ldap_group_links", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupLDAPLink deletes a group LDAP link. Available only for users who @@ -936,18 +754,12 @@ func (s *GroupsService) AddGroupLDAPLink(gid any, opt *AddGroupLDAPLinkOptions, // GitLab API docs: // https://docs.gitlab.com/api/group_ldap_links/#delete-an-ldap-group-link-deprecated func (s *GroupsService) DeleteGroupLDAPLink(gid any, cn string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/ldap_group_links/%s", PathEscape(group), PathEscape(cn)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/ldap_group_links/%s", GroupID{gid}, cn), + withRequestOpts(options...), + ) + return resp, err } // DeleteGroupLDAPLinkWithCNOrFilterOptions represents the available DeleteGroupLDAPLinkWithCNOrFilter() options. @@ -966,18 +778,13 @@ type DeleteGroupLDAPLinkWithCNOrFilterOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_ldap_links/#delete-an-ldap-group-link-with-cn-or-filter func (s *GroupsService) DeleteGroupLDAPLinkWithCNOrFilter(gid any, opts *DeleteGroupLDAPLinkWithCNOrFilterOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/ldap_group_links", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodDelete, u, opts, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/ldap_group_links", GroupID{gid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) + return resp, err } // DeleteGroupLDAPLinkForProvider deletes a group LDAP link from a specific @@ -986,23 +793,12 @@ func (s *GroupsService) DeleteGroupLDAPLinkWithCNOrFilter(gid any, opts *DeleteG // GitLab API docs: // https://docs.gitlab.com/api/group_ldap_links/#delete-an-ldap-group-link-deprecated func (s *GroupsService) DeleteGroupLDAPLinkForProvider(gid any, provider, cn string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf( - "groups/%s/ldap_group_links/%s/%s", - PathEscape(group), - PathEscape(provider), - PathEscape(cn), + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/ldap_group_links/%s/%s", GroupID{gid}, provider, cn), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } // ListGroupSAMLLinks lists the group's SAML links. Available only for users who @@ -1011,24 +807,10 @@ func (s *GroupsService) DeleteGroupLDAPLinkForProvider(gid any, provider, cn str // GitLab API docs: // https://docs.gitlab.com/api/saml/#list-saml-group-links func (s *GroupsService) ListGroupSAMLLinks(gid any, options ...RequestOptionFunc) ([]*SAMLGroupLink, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/saml_group_links", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var gl []*SAMLGroupLink - resp, err := s.client.Do(req, &gl) - if err != nil { - return nil, resp, err - } - - return gl, resp, nil + return do[[]*SAMLGroupLink](s.client, + withPath("groups/%s/saml_group_links", GroupID{gid}), + withRequestOpts(options...), + ) } // ListGroupSharedProjectsOptions represents the available ListGroupSharedProjects() options. @@ -1055,24 +837,11 @@ type ListGroupSharedProjectsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#list-shared-projects func (s *GroupsService) ListGroupSharedProjects(gid any, opt *ListGroupSharedProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/projects/shared", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Project - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*Project](s.client, + withPath("groups/%s/projects/shared", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupSAMLLink get a specific group SAML link. Available only for users who @@ -1081,24 +850,10 @@ func (s *GroupsService) ListGroupSharedProjects(gid any, opt *ListGroupSharedPro // GitLab API docs: // https://docs.gitlab.com/api/saml/#get-a-saml-group-link func (s *GroupsService) GetGroupSAMLLink(gid any, samlGroupName string, options ...RequestOptionFunc) (*SAMLGroupLink, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/saml_group_links/%s", PathEscape(group), PathEscape(samlGroupName)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gl := new(SAMLGroupLink) - resp, err := s.client.Do(req, &gl) - if err != nil { - return nil, resp, err - } - - return gl, resp, nil + return do[*SAMLGroupLink](s.client, + withPath("groups/%s/saml_group_links/%s", GroupID{gid}, samlGroupName), + withRequestOpts(options...), + ) } // AddGroupSAMLLinkOptions represents the available AddGroupSAMLLink() options. @@ -1108,7 +863,8 @@ func (s *GroupsService) GetGroupSAMLLink(gid any, samlGroupName string, options type AddGroupSAMLLinkOptions struct { SAMLGroupName *string `url:"saml_group_name,omitempty" json:"saml_group_name,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + Provider *string `url:"provider,omitempty" json:"provider,omitempty"` } // AddGroupSAMLLink creates a new group SAML link. Available only for users who @@ -1117,24 +873,12 @@ type AddGroupSAMLLinkOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/saml/#add-a-saml-group-link func (s *GroupsService) AddGroupSAMLLink(gid any, opt *AddGroupSAMLLinkOptions, options ...RequestOptionFunc) (*SAMLGroupLink, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/saml_group_links", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gl := new(SAMLGroupLink) - resp, err := s.client.Do(req, &gl) - if err != nil { - return nil, resp, err - } - - return gl, resp, nil + return do[*SAMLGroupLink](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/saml_group_links", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupSAMLLink deletes a group SAML link. Available only for users who @@ -1143,18 +887,12 @@ func (s *GroupsService) AddGroupSAMLLink(gid any, opt *AddGroupSAMLLinkOptions, // GitLab API docs: // https://docs.gitlab.com/api/saml/#delete-a-saml-group-link func (s *GroupsService) DeleteGroupSAMLLink(gid any, samlGroupName string, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/saml_group_links/%s", PathEscape(group), PathEscape(samlGroupName)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/saml_group_links/%s", GroupID{gid}, samlGroupName), + withRequestOpts(options...), + ) + return resp, err } // ShareGroupWithGroupOptions represents the available ShareGroupWithGroup() options. @@ -1162,10 +900,10 @@ func (s *GroupsService) DeleteGroupSAMLLink(gid any, samlGroupName string, optio // GitLab API docs: // https://docs.gitlab.com/api/groups/#share-groups-with-groups type ShareGroupWithGroupOptions struct { - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` GroupAccess *AccessLevelValue `url:"group_access,omitempty" json:"group_access,omitempty"` ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` } // ShareGroupWithGroup shares a group with another group. @@ -1173,43 +911,25 @@ type ShareGroupWithGroupOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#create-a-link-to-share-a-group-with-another-group func (s *GroupsService) ShareGroupWithGroup(gid any, opt *ShareGroupWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/share", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - g := new(Group) - resp, err := s.client.Do(req, g) - if err != nil { - return nil, resp, err - } - - return g, resp, nil + return do[*Group](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/share", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnshareGroupFromGroup unshares a group from another group. // // GitLab API docs: // https://docs.gitlab.com/api/groups/#delete-the-link-that-shares-a-group-with-another-group -func (s *GroupsService) UnshareGroupFromGroup(gid any, groupID int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/share/%d", PathEscape(group), groupID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *GroupsService) UnshareGroupFromGroup(gid any, groupID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/share/%d", GroupID{gid}, groupID), + withRequestOpts(options...), + ) + return resp, err } // GroupPushRules represents a group push rule. @@ -1217,7 +937,7 @@ func (s *GroupsService) UnshareGroupFromGroup(gid any, groupID int, options ...R // GitLab API docs: // https://docs.gitlab.com/api/group_push_rules/#get-the-push-rules-of-a-group type GroupPushRules struct { - ID int `json:"id"` + ID int64 `json:"id"` CreatedAt *time.Time `json:"created_at"` CommitMessageRegex string `json:"commit_message_regex"` CommitMessageNegativeRegex string `json:"commit_message_negative_regex"` @@ -1227,7 +947,7 @@ type GroupPushRules struct { PreventSecrets bool `json:"prevent_secrets"` AuthorEmailRegex string `json:"author_email_regex"` FileNameRegex string `json:"file_name_regex"` - MaxFileSize int `json:"max_file_size"` + MaxFileSize int64 `json:"max_file_size"` CommitCommitterCheck bool `json:"commit_committer_check"` CommitCommitterNameCheck bool `json:"commit_committer_name_check"` RejectUnsignedCommits bool `json:"reject_unsigned_commits"` @@ -1239,24 +959,10 @@ type GroupPushRules struct { // GitLab API docs: // https://docs.gitlab.com/api/group_push_rules/#get-the-push-rules-of-a-group func (s *GroupsService) GetGroupPushRules(gid any, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/push_rule", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - gpr := new(GroupPushRules) - resp, err := s.client.Do(req, gpr) - if err != nil { - return nil, resp, err - } - - return gpr, resp, nil + return do[*GroupPushRules](s.client, + withPath("groups/%s/push_rule", GroupID{gid}), + withRequestOpts(options...), + ) } // AddGroupPushRuleOptions represents the available AddGroupPushRule() @@ -1273,7 +979,7 @@ type AddGroupPushRuleOptions struct { CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"` DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"` FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"` - MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` + MaxFileSize *int64 `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"` PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"` RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"` @@ -1285,24 +991,12 @@ type AddGroupPushRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_push_rules/#add-push-rules-to-a-group func (s *GroupsService) AddGroupPushRule(gid any, opt *AddGroupPushRuleOptions, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/push_rule", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - gpr := new(GroupPushRules) - resp, err := s.client.Do(req, gpr) - if err != nil { - return nil, resp, err - } - - return gpr, resp, nil + return do[*GroupPushRules](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/push_rule", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditGroupPushRuleOptions represents the available EditGroupPushRule() @@ -1319,7 +1013,7 @@ type EditGroupPushRuleOptions struct { CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"` DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"` FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"` - MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` + MaxFileSize *int64 `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"` PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"` RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"` @@ -1331,24 +1025,12 @@ type EditGroupPushRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/group_push_rules/#edit-the-push-rules-of-a-group func (s *GroupsService) EditGroupPushRule(gid any, opt *EditGroupPushRuleOptions, options ...RequestOptionFunc) (*GroupPushRules, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/push_rule", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - gpr := new(GroupPushRules) - resp, err := s.client.Do(req, gpr) - if err != nil { - return nil, resp, err - } - - return gpr, resp, nil + return do[*GroupPushRules](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/push_rule", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGroupPushRule deletes the push rules of a group. @@ -1356,16 +1038,10 @@ func (s *GroupsService) EditGroupPushRule(gid any, opt *EditGroupPushRuleOptions // GitLab API docs: // https://docs.gitlab.com/api/group_push_rules/#delete-the-push-rules-of-a-group func (s *GroupsService) DeleteGroupPushRule(gid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/push_rule", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/push_rule", GroupID{gid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/import.go b/vendor/gitlab.com/gitlab-org/api/client-go/import.go index 019c4b726..68424b690 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/import.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/import.go @@ -46,11 +46,11 @@ var _ ImportServiceInterface = (*ImportService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-github type GitHubImport struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` FullPath string `json:"full_path"` FullName string `json:"full_name"` - RefsUrl string `json:"refs_url"` + RefsURL string `json:"refs_url"` ImportSource string `json:"import_source"` ImportStatus string `json:"import_status"` HumanImportStatusName string `json:"human_import_status_name"` @@ -69,17 +69,19 @@ func (s GitHubImport) String() string { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-github type ImportRepositoryFromGitHubOptions struct { - PersonalAccessToken *string `url:"personal_access_token,omitempty" json:"personal_access_token,omitempty"` - RepoID *int `url:"repo_id,omitempty" json:"repo_id,omitempty"` - NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"` - TargetNamespace *string `url:"target_namespace,omitempty" json:"target_namespace,omitempty"` - GitHubHostname *string `url:"github_hostname,omitempty" json:"github_hostname,omitempty"` - OptionalStages struct { - SingleEndpointNotesImport *bool `url:"single_endpoint_notes_import,omitempty" json:"single_endpoint_notes_import,omitempty"` - AttachmentsImport *bool `url:"attachments_import,omitempty" json:"attachments_import,omitempty"` - CollaboratorsImport *bool `url:"collaborators_import,omitempty" json:"collaborators_import,omitempty"` - } `url:"optional_stages,omitempty" json:"optional_stages,omitempty"` - TimeoutStrategy *string `url:"timeout_strategy,omitempty" json:"timeout_strategy,omitempty"` + PersonalAccessToken *string `url:"personal_access_token,omitempty" json:"personal_access_token,omitempty"` + RepoID *int64 `url:"repo_id,omitempty" json:"repo_id,omitempty"` + NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"` + TargetNamespace *string `url:"target_namespace,omitempty" json:"target_namespace,omitempty"` + GitHubHostname *string `url:"github_hostname,omitempty" json:"github_hostname,omitempty"` + OptionalStages ImportRepositoryFromGitHubOptionalStagesOptions `url:"optional_stages,omitempty" json:"optional_stages,omitempty"` + TimeoutStrategy *string `url:"timeout_strategy,omitempty" json:"timeout_strategy,omitempty"` +} + +type ImportRepositoryFromGitHubOptionalStagesOptions struct { + SingleEndpointNotesImport *bool `url:"single_endpoint_notes_import,omitempty" json:"single_endpoint_notes_import,omitempty"` + AttachmentsImport *bool `url:"attachments_import,omitempty" json:"attachments_import,omitempty"` + CollaboratorsImport *bool `url:"collaborators_import,omitempty" json:"collaborators_import,omitempty"` } // ImportRepositoryFromGitHub imports a repository from GitHub. @@ -87,18 +89,12 @@ type ImportRepositoryFromGitHubOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-github func (s *ImportService) ImportRepositoryFromGitHub(opt *ImportRepositoryFromGitHubOptions, options ...RequestOptionFunc) (*GitHubImport, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "import/github", opt, options) - if err != nil { - return nil, nil, err - } - - gi := new(GitHubImport) - resp, err := s.client.Do(req, gi) - if err != nil { - return nil, resp, err - } - - return gi, resp, nil + return do[*GitHubImport](s.client, + withMethod(http.MethodPost), + withPath("import/github"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CancelledGitHubImport represents the response when canceling @@ -107,7 +103,7 @@ func (s *ImportService) ImportRepositoryFromGitHub(opt *ImportRepositoryFromGitH // GitLab API docs: // https://docs.gitlab.com/api/import/#cancel-github-project-import type CancelledGitHubImport struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` FullPath string `json:"full_path"` FullName string `json:"full_name"` @@ -127,7 +123,7 @@ func (s CancelledGitHubImport) String() string { // GitLab API docs: // https://docs.gitlab.com/api/import/#cancel-github-project-import type CancelGitHubProjectImportOptions struct { - ProjectID *int `url:"project_id,omitempty" json:"project_id,omitempty"` + ProjectID *int64 `url:"project_id,omitempty" json:"project_id,omitempty"` } // CancelGitHubProjectImport cancels an import of a repository from GitHub. @@ -135,18 +131,12 @@ type CancelGitHubProjectImportOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/import/#cancel-github-project-import func (s *ImportService) CancelGitHubProjectImport(opt *CancelGitHubProjectImportOptions, options ...RequestOptionFunc) (*CancelledGitHubImport, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "import/github/cancel", opt, options) - if err != nil { - return nil, nil, err - } - - cgi := new(CancelledGitHubImport) - resp, err := s.client.Do(req, cgi) - if err != nil { - return nil, resp, err - } - - return cgi, resp, nil + return do[*CancelledGitHubImport](s.client, + withMethod(http.MethodPost), + withPath("import/github/cancel"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ImportGitHubGistsIntoGitLabSnippetsOptions represents the available @@ -163,12 +153,13 @@ type ImportGitHubGistsIntoGitLabSnippetsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-github-gists-into-gitlab-snippets func (s *ImportService) ImportGitHubGistsIntoGitLabSnippets(opt *ImportGitHubGistsIntoGitLabSnippetsOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "import/github/gists", opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("import/github/gists"), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // BitbucketServerImport represents the response from an import from Bitbucket @@ -177,11 +168,11 @@ func (s *ImportService) ImportGitHubGistsIntoGitLabSnippets(opt *ImportGitHubGis // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-bitbucket-server type BitbucketServerImport struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` FullPath string `json:"full_path"` FullName string `json:"full_name"` - RefsUrl string `json:"refs_url"` + RefsURL string `json:"refs_url"` } func (s BitbucketServerImport) String() string { @@ -193,7 +184,7 @@ func (s BitbucketServerImport) String() string { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-bitbucket-server type ImportRepositoryFromBitbucketServerOptions struct { - BitbucketServerUrl *string `url:"bitbucket_server_url,omitempty" json:"bitbucket_server_url,omitempty"` + BitbucketServerURL *string `url:"bitbucket_server_url,omitempty" json:"bitbucket_server_url,omitempty"` BitbucketServerUsername *string `url:"bitbucket_server_username,omitempty" json:"bitbucket_server_username,omitempty"` PersonalAccessToken *string `url:"personal_access_token,omitempty" json:"personal_access_token,omitempty"` BitbucketServerProject *string `url:"bitbucket_server_project,omitempty" json:"bitbucket_server_project,omitempty"` @@ -208,18 +199,12 @@ type ImportRepositoryFromBitbucketServerOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-bitbucket-server func (s *ImportService) ImportRepositoryFromBitbucketServer(opt *ImportRepositoryFromBitbucketServerOptions, options ...RequestOptionFunc) (*BitbucketServerImport, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "import/bitbucket_server", opt, options) - if err != nil { - return nil, nil, err - } - - bsi := new(BitbucketServerImport) - resp, err := s.client.Do(req, bsi) - if err != nil { - return nil, resp, err - } - - return bsi, resp, nil + return do[*BitbucketServerImport](s.client, + withMethod(http.MethodPost), + withPath("import/bitbucket_server"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // BitbucketCloudImport represents the response from an import from Bitbucket @@ -228,11 +213,11 @@ func (s *ImportService) ImportRepositoryFromBitbucketServer(opt *ImportRepositor // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-bitbucket-cloud type BitbucketCloudImport struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` FullPath string `json:"full_path"` FullName string `json:"full_name"` - RefsUrl string `json:"refs_url"` + RefsURL string `json:"refs_url"` ImportSource string `json:"import_source"` ImportStatus string `json:"import_status"` HumanImportStatusName string `json:"human_import_status_name"` @@ -263,16 +248,10 @@ type ImportRepositoryFromBitbucketCloudOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/import/#import-repository-from-bitbucket-cloud func (s *ImportService) ImportRepositoryFromBitbucketCloud(opt *ImportRepositoryFromBitbucketCloudOptions, options ...RequestOptionFunc) (*BitbucketCloudImport, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "import/bitbucket", opt, options) - if err != nil { - return nil, nil, err - } - - bci := new(BitbucketCloudImport) - resp, err := s.client.Do(req, bci) - if err != nil { - return nil, resp, err - } - - return bci, resp, nil + return do[*BitbucketCloudImport](s.client, + withMethod(http.MethodPost), + withPath("import/bitbucket"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/instance_clusters.go b/vendor/gitlab.com/gitlab-org/api/client-go/instance_clusters.go index fd4bce6be..cc06e9dbe 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/instance_clusters.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/instance_clusters.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -28,13 +27,13 @@ type ( // Deprecated: in GitLab 14.5, to be removed in 19.0 ListClusters(options ...RequestOptionFunc) ([]*InstanceCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - GetCluster(cluster int, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) + GetCluster(cluster int64, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 AddCluster(opt *AddClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - EditCluster(cluster int, opt *EditClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) + EditCluster(cluster int64, opt *EditClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - DeleteCluster(cluster int, options ...RequestOptionFunc) (*Response, error) + DeleteCluster(cluster int64, options ...RequestOptionFunc) (*Response, error) } // InstanceClustersService handles communication with the @@ -56,7 +55,7 @@ var _ InstanceClustersServiceInterface = (*InstanceClustersService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/instance_clusters/ type InstanceCluster struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Domain string `json:"domain"` Managed bool `json:"managed"` @@ -81,20 +80,10 @@ func (v InstanceCluster) String() string { // GitLab API docs: // https://docs.gitlab.com/api/instance_clusters/#list-instance-clusters func (s *InstanceClustersService) ListClusters(options ...RequestOptionFunc) ([]*InstanceCluster, *Response, error) { - u := "admin/clusters" - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var ics []*InstanceCluster - resp, err := s.client.Do(req, &ics) - if err != nil { - return nil, resp, err - } - - return ics, resp, nil + return do[[]*InstanceCluster](s.client, + withPath("admin/clusters"), + withRequestOpts(options...), + ) } // GetCluster gets an instance cluster. @@ -102,21 +91,11 @@ func (s *InstanceClustersService) ListClusters(options ...RequestOptionFunc) ([] // // GitLab API docs: // https://docs.gitlab.com/api/instance_clusters/#get-a-single-instance-cluster -func (s *InstanceClustersService) GetCluster(cluster int, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) { - u := fmt.Sprintf("admin/clusters/%d", cluster) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ic := new(InstanceCluster) - resp, err := s.client.Do(req, &ic) - if err != nil { - return nil, resp, err - } - - return ic, resp, nil +func (s *InstanceClustersService) GetCluster(cluster int64, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) { + return do[*InstanceCluster](s.client, + withPath("admin/clusters/%d", cluster), + withRequestOpts(options...), + ) } // AddCluster adds an existing cluster to the instance. @@ -125,20 +104,12 @@ func (s *InstanceClustersService) GetCluster(cluster int, options ...RequestOpti // GitLab API docs: // https://docs.gitlab.com/api/instance_clusters/#add-existing-instance-cluster func (s *InstanceClustersService) AddCluster(opt *AddClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) { - u := "admin/clusters/add" - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ic := new(InstanceCluster) - resp, err := s.client.Do(req, ic) - if err != nil { - return nil, resp, err - } - - return ic, resp, nil + return do[*InstanceCluster](s.client, + withMethod(http.MethodPost), + withPath("admin/clusters/add"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditCluster updates an existing instance cluster. @@ -146,21 +117,13 @@ func (s *InstanceClustersService) AddCluster(opt *AddClusterOptions, options ... // // GitLab API docs: // https://docs.gitlab.com/api/instance_clusters/#edit-instance-cluster -func (s *InstanceClustersService) EditCluster(cluster int, opt *EditClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) { - u := fmt.Sprintf("admin/clusters/%d", cluster) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ic := new(InstanceCluster) - resp, err := s.client.Do(req, ic) - if err != nil { - return nil, resp, err - } - - return ic, resp, nil +func (s *InstanceClustersService) EditCluster(cluster int64, opt *EditClusterOptions, options ...RequestOptionFunc) (*InstanceCluster, *Response, error) { + return do[*InstanceCluster](s.client, + withMethod(http.MethodPut), + withPath("admin/clusters/%d", cluster), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteCluster deletes an existing instance cluster. @@ -168,13 +131,11 @@ func (s *InstanceClustersService) EditCluster(cluster int, opt *EditClusterOptio // // GitLab API docs: // https://docs.gitlab.com/api/instance_clusters/#delete-instance-cluster -func (s *InstanceClustersService) DeleteCluster(cluster int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("admin/clusters/%d", cluster) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *InstanceClustersService) DeleteCluster(cluster int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("admin/clusters/%d", cluster), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/instance_variables.go b/vendor/gitlab.com/gitlab-org/api/client-go/instance_variables.go index 235a333e3..2a4c05c37 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/instance_variables.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/instance_variables.go @@ -17,17 +17,36 @@ package gitlab import ( - "fmt" "net/http" "net/url" ) type ( InstanceVariablesServiceInterface interface { + // ListVariables gets a list of all variables for an instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/instance_level_ci_variables/#list-all-instance-variables ListVariables(opt *ListInstanceVariablesOptions, options ...RequestOptionFunc) ([]*InstanceVariable, *Response, error) + // GetVariable gets a variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/instance_level_ci_variables/#show-instance-variable-details GetVariable(key string, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) + // CreateVariable creates a new instance level CI variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/instance_level_ci_variables/#create-instance-variable CreateVariable(opt *CreateInstanceVariableOptions, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) + // UpdateVariable updates an existing instance level CI variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/instance_level_ci_variables/#update-instance-variable UpdateVariable(key string, opt *UpdateInstanceVariableOptions, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) + // RemoveVariable removes an instance level CI variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/instance_level_ci_variables/#remove-instance-variable RemoveVariable(key string, options ...RequestOptionFunc) (*Response, error) } @@ -66,48 +85,23 @@ func (v InstanceVariable) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/instance_level_ci_variables/#list-all-instance-variables -type ListInstanceVariablesOptions ListOptions +type ListInstanceVariablesOptions struct { + ListOptions +} -// ListVariables gets a list of all variables for an instance. -// -// GitLab API docs: -// https://docs.gitlab.com/api/instance_level_ci_variables/#list-all-instance-variables func (s *InstanceVariablesService) ListVariables(opt *ListInstanceVariablesOptions, options ...RequestOptionFunc) ([]*InstanceVariable, *Response, error) { - u := "admin/ci/variables" - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var vs []*InstanceVariable - resp, err := s.client.Do(req, &vs) - if err != nil { - return nil, resp, err - } - - return vs, resp, nil + return do[[]*InstanceVariable](s.client, + withPath("admin/ci/variables"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetVariable gets a variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/instance_level_ci_variables/#show-instance-variable-details func (s *InstanceVariablesService) GetVariable(key string, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) { - u := fmt.Sprintf("admin/ci/variables/%s", url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - v := new(InstanceVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*InstanceVariable](s.client, + withPath("admin/ci/variables/%s", url.PathEscape(key)), + withRequestOpts(options...), + ) } // CreateInstanceVariableOptions represents the available CreateVariable() @@ -125,25 +119,13 @@ type CreateInstanceVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// CreateVariable creates a new instance level CI variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/instance_level_ci_variables/#create-instance-variable func (s *InstanceVariablesService) CreateVariable(opt *CreateInstanceVariableOptions, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) { - u := "admin/ci/variables" - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(InstanceVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*InstanceVariable](s.client, + withMethod(http.MethodPost), + withPath("admin/ci/variables"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateInstanceVariableOptions represents the available UpdateVariable() @@ -160,39 +142,20 @@ type UpdateInstanceVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// UpdateVariable updates the position of an existing -// instance level CI variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/instance_level_ci_variables/#update-instance-variable func (s *InstanceVariablesService) UpdateVariable(key string, opt *UpdateInstanceVariableOptions, options ...RequestOptionFunc) (*InstanceVariable, *Response, error) { - u := fmt.Sprintf("admin/ci/variables/%s", url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(InstanceVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*InstanceVariable](s.client, + withMethod(http.MethodPut), + withPath("admin/ci/variables/%s", url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// RemoveVariable removes an instance level CI variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/instance_level_ci_variables/#remove-instance-variable func (s *InstanceVariablesService) RemoveVariable(key string, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("admin/ci/variables/%s", url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("admin/ci/variables/%s", url.PathEscape(key)), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/integrations.go b/vendor/gitlab.com/gitlab-org/api/client-go/integrations.go index 2e4357ada..c6921da98 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/integrations.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/integrations.go @@ -14,20 +14,198 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( IntegrationsServiceInterface interface { + // ListActiveGroupIntegrations gets a list of all active group integrations. + // The vulnerability_events field is only available for GitLab Enterprise Edition. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#list-all-active-integrations ListActiveGroupIntegrations(gid any, opt *ListActiveIntegrationsOptions, options ...RequestOptionFunc) ([]*Integration, *Response, error) + + // SetUpGroupHarbor sets up the Harbor integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#set-up-harbor SetUpGroupHarbor(gid any, opt *SetUpHarborOptions, options ...RequestOptionFunc) (*Integration, *Response, error) + + // DisableGroupHarbor disables the Harbor integration for a group. + // Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#disable-harbor DisableGroupHarbor(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupHarborSettings gets the Harbor integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#get-harbor-settings GetGroupHarborSettings(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) + + // SetGroupMicrosoftTeamsNotifications sets up Microsoft Teams notifications for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#set-up-microsoft-teams-notifications SetGroupMicrosoftTeamsNotifications(gid any, opt *SetMicrosoftTeamsNotificationsOptions, options ...RequestOptionFunc) (*Integration, *Response, error) + + // DisableGroupMicrosoftTeamsNotifications disables Microsoft Teams notifications + // for a group. Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#disable-microsoft-teams-notifications DisableGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupMicrosoftTeamsNotifications gets the Microsoft Teams notifications for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#get-microsoft-teams-notifications-settings GetGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) + + // SetUpGroupJira sets up the Jira integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#set-up-jira + SetUpGroupJira(gid any, opt *SetUpJiraOptions, options ...RequestOptionFunc) (*Integration, *Response, error) + + // DisableGroupJira disables the Jira integration for a group. + // Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#disable-jira + DisableGroupJira(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupJiraSettings gets the Jira integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#get-jira-settings + GetGroupJiraSettings(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) + + // GetGroupSlackSettings gets the Slack integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#get-slack-settings + GetGroupSlackSettings(gid any, options ...RequestOptionFunc) (*SlackIntegration, *Response, error) + + // SetGroupSlackSettings sets up the Slack integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#set-up-slack + SetGroupSlackSettings(gid any, opt *SetGroupSlackOptions, options ...RequestOptionFunc) (*SlackIntegration, *Response, error) + + // DisableGroupSlack disables the Slack integration for a group. + // Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#disable-slack + DisableGroupSlack(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupDiscordSettings gets the Discord integration settings for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#discord + GetGroupDiscordSettings(gid any, options ...RequestOptionFunc) (*DiscordIntegration, *Response, error) + + // GetGroupTelegramSettings gets the Telegram integration settings for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#telegram + GetGroupTelegramSettings(gid any, options ...RequestOptionFunc) (*TelegramIntegration, *Response, error) + + // GetGroupMattermostSettings gets the Mattermost integration settings for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-notifications + GetGroupMattermostSettings(gid any, options ...RequestOptionFunc) (*MattermostIntegration, *Response, error) + + // GetGroupMatrixSettings gets the Matrix integration settings for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#matrix-notifications + GetGroupMatrixSettings(gid any, options ...RequestOptionFunc) (*MatrixIntegration, *Response, error) + + // GetGroupGoogleChatSettings gets the Google Chat integration settings for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#google-chat + GetGroupGoogleChatSettings(gid any, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) + + // SetProjectGoogleChatSettings sets up the Google Chat integration for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/integrations.html#set-up-google-chat + SetProjectGoogleChatSettings(pid any, opt *SetProjectGoogleChatOptions, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) + + // DisableProjectGoogleChat disables the Google Chat integration for a project. + // Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/integrations.html#disable-google-chat + DisableProjectGoogleChat(pid any, options ...RequestOptionFunc) (*Response, error) + + // GetProjectGoogleChatSettings gets the Google Chat integration settings for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/integrations.html#get-google-chat-settings + GetProjectGoogleChatSettings(pid any, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) + + // GetGroupMattermostIntegration retrieves the Mattermost integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-notifications + GetGroupMattermostIntegration(gid any, options ...RequestOptionFunc) (*GroupMattermostIntegration, *Response, error) + + // SetGroupMattermostIntegration creates or updates the Mattermost integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-notifications + SetGroupMattermostIntegration(gid any, opt *GroupMattermostIntegrationOptions, options ...RequestOptionFunc) (*GroupMattermostIntegration, *Response, error) + + // DeleteGroupMattermostIntegration removes the Mattermost integration from a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-notifications + DeleteGroupMattermostIntegration(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupMattermostSlashCommandsIntegration retrieves the Mattermost slash commands integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands + GetGroupMattermostSlashCommandsIntegration(gid any, options ...RequestOptionFunc) (*GroupMattermostSlashCommandsIntegration, *Response, error) + + // SetGroupMattermostSlashCommandsIntegration creates or updates the Mattermost slash commands integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands + SetGroupMattermostSlashCommandsIntegration(gid any, opt *GroupMattermostSlashCommandsIntegrationOptions, options ...RequestOptionFunc) (*GroupMattermostSlashCommandsIntegration, *Response, error) + + // DeleteGroupMattermostSlashCommandsIntegration removes the Mattermost slash commands integration from a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#mattermost-slash-commands + DeleteGroupMattermostSlashCommandsIntegration(gid any, options ...RequestOptionFunc) (*Response, error) + + // GetGroupWebexTeamsSettings gets the Webex Teams integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#get-webex-teams-settings + GetGroupWebexTeamsSettings(gid any, options ...RequestOptionFunc) (*WebexTeamsIntegration, *Response, error) + + // SetGroupWebexTeamsSettings sets up the Webex Teams integration for a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#set-up-webex-teams + SetGroupWebexTeamsSettings(gid any, opt *SetGroupWebexTeamsOptions, options ...RequestOptionFunc) (*WebexTeamsIntegration, *Response, error) + + // DisableGroupWebexTeams disables the Webex Teams integration for a group. + // Integration settings are reset. + // + // GitLab API docs: + // https://docs.gitlab.com/api/group_integrations/#disable-webex-teams + DisableGroupWebexTeams(gid any, options ...RequestOptionFunc) (*Response, error) } // IntegrationsService handles communication with the group @@ -47,7 +225,7 @@ var _ IntegrationsServiceInterface = (*IntegrationsService)(nil) // https://docs.gitlab.com/api/group_integrations/ // https://docs.gitlab.com/api/project_integrations/ type Integration struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Slug string `json:"slug"` CreatedAt *time.Time `json:"created_at"` @@ -74,6 +252,196 @@ type Integration struct { Inherited bool `json:"inherited"` } +// SlackIntegration represents the Slack integration settings. +// It embeds the generic Integration struct and adds Slack-specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#get-slack-settings +type SlackIntegration struct { + Integration + Properties SlackIntegrationProperties `json:"properties"` +} + +// SlackIntegrationProperties represents Slack specific properties +// returned by the GitLab API. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#get-slack-settings +type SlackIntegrationProperties struct { + Username string `json:"username"` + Channel string `json:"channel"` + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines"` + BranchesToBeNotified string `json:"branches_to_be_notified"` + LabelsToBeNotified string `json:"labels_to_be_notified"` + LabelsToBeNotifiedBehavior string `json:"labels_to_be_notified_behavior"` + PushChannel string `json:"push_channel"` + IssueChannel string `json:"issue_channel"` + ConfidentialIssueChannel string `json:"confidential_issue_channel"` + MergeRequestChannel string `json:"merge_request_channel"` + NoteChannel string `json:"note_channel"` + ConfidentialNoteChannel string `json:"confidential_note_channel"` + TagPushChannel string `json:"tag_push_channel"` + PipelineChannel string `json:"pipeline_channel"` + WikiPageChannel string `json:"wiki_page_channel"` + DeploymentChannel string `json:"deployment_channel"` + IncidentChannel string `json:"incident_channel"` + AlertChannel string `json:"alert_channel"` + GroupMentionChannel string `json:"group_mention_channel"` + GroupConfidentialMentionChannel string `json:"group_confidential_mention_channel"` +} + +// DiscordIntegration represents the Discord integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#discord +type DiscordIntegration struct { + Integration + Properties DiscordIntegrationProperties `json:"properties"` +} + +// DiscordIntegrationProperties represents Discord specific properties. +type DiscordIntegrationProperties struct { + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` +} + +// TelegramIntegration represents the Telegram integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#telegram +type TelegramIntegration struct { + Integration + Properties TelegramIntegrationProperties `json:"properties"` +} + +// TelegramIntegrationProperties represents Telegram specific properties. +type TelegramIntegrationProperties struct { + Hostname string `json:"hostname,omitempty"` + Room string `json:"room,omitempty"` + Thread string `json:"thread,omitempty"` + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` +} + +// MattermostIntegration represents the Mattermost integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#mattermost-notifications +type MattermostIntegration struct { + Integration + Properties MattermostIntegrationProperties `json:"properties"` +} + +// MattermostIntegrationProperties represents Mattermost specific properties. +type MattermostIntegrationProperties struct { + Username string `json:"username,omitempty"` + Channel string `json:"channel,omitempty"` + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` + LabelsToBeNotified string `json:"labels_to_be_notified,omitempty"` + LabelsToBeNotifiedBehavior string `json:"labels_to_be_notified_behavior,omitempty"` + PushChannel string `json:"push_channel,omitempty"` + IssueChannel string `json:"issue_channel,omitempty"` + ConfidentialIssueChannel string `json:"confidential_issue_channel,omitempty"` + MergeRequestChannel string `json:"merge_request_channel,omitempty"` + NoteChannel string `json:"note_channel,omitempty"` + ConfidentialNoteChannel string `json:"confidential_note_channel,omitempty"` + TagPushChannel string `json:"tag_push_channel,omitempty"` + PipelineChannel string `json:"pipeline_channel,omitempty"` + WikiPageChannel string `json:"wiki_page_channel,omitempty"` + DeploymentChannel string `json:"deployment_channel,omitempty"` + IncidentChannel string `json:"incident_channel,omitempty"` +} + +// MatrixIntegration represents the Matrix integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#matrix-notifications +type MatrixIntegration struct { + Integration + Properties MatrixIntegrationProperties `json:"properties"` +} + +// MatrixIntegrationProperties represents Matrix specific properties. +type MatrixIntegrationProperties struct { + Hostname string `json:"hostname,omitempty"` + Room string `json:"room,omitempty"` + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` +} + +// GoogleChatIntegration represents the Google Chat integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#google-chat +type GoogleChatIntegration struct { + Integration + Properties GoogleChatIntegrationProperties `json:"properties"` +} + +// GoogleChatIntegrationProperties represents Google Chat specific properties. +type GoogleChatIntegrationProperties struct { + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + NotifyOnlyWhenPipelineStatusChanges bool `json:"notify_only_when_pipeline_status_changes,omitempty"` + NotifyOnlyDefaultBranch bool `json:"notify_only_default_branch,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` + PushEvents bool `json:"push_events,omitempty"` + IssuesEvents bool `json:"issues_events,omitempty"` + ConfidentialIssuesEvents bool `json:"confidential_issues_events,omitempty"` + MergeRequestsEvents bool `json:"merge_requests_events,omitempty"` + TagPushEvents bool `json:"tag_push_events,omitempty"` + NoteEvents bool `json:"note_events,omitempty"` + ConfidentialNoteEvents bool `json:"confidential_note_events,omitempty"` + PipelineEvents bool `json:"pipeline_events,omitempty"` + WikiPageEvents bool `json:"wiki_page_events,omitempty"` +} + +// WebexTeamsIntegration represents the WebexTeams integration settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#get-webex-teams-settings +type WebexTeamsIntegration struct { + Integration + Properties WebexTeamsIntegrationProperties `json:"properties"` +} + +// WebexTeamsIntegrationProperties represents WebexTeams specific properties +type WebexTeamsIntegrationProperties struct { + NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified string `json:"branches_to_be_notified,omitempty"` +} + +// SetGroupWebexTeamsOptions represents the available SetGroupWebexTeamsSettings() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_integrations/#set-up-webex-teams +type SetGroupWebexTeamsOptions struct { + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` +} + +// SetProjectGoogleChatOptions represents the available SetProjectGoogleChatSettings() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/integrations.html#set-up-google-chat +type SetProjectGoogleChatOptions struct { + Webhook *string `url:"webhook,omitempty" json:"webhook,omitempty"` + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + NotifyOnlyWhenPipelineStatusChanges *bool `url:"notify_only_when_pipeline_status_changes,omitempty" json:"notify_only_when_pipeline_status_changes,omitempty"` + NotifyOnlyDefaultBranch *bool `url:"notify_only_default_branch,omitempty" json:"notify_only_default_branch,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} + // ListActiveIntegrationsOptions represents the available // ListActiveIntegrations() options. // @@ -83,30 +451,14 @@ type ListActiveIntegrationsOptions struct { ListOptions } -// ListActiveGroupIntegrations gets a list of all active group integrations. -// The vulnerability_events field is only available for GitLab Enterprise Edition. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#list-all-active-integrations func (s *IntegrationsService) ListActiveGroupIntegrations(gid any, opt *ListActiveIntegrationsOptions, options ...RequestOptionFunc) ([]*Integration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/integrations", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var integrations []*Integration - resp, err := s.client.Do(req, &integrations) - if err != nil { - return nil, resp, err - } - - return integrations, resp, nil + return do[[]*Integration]( + s.client, + withPath("groups/%s/integrations", GroupID{gid}), + withMethod(http.MethodGet), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SetUpHarborOptions represents the available SetUpGroupHarbor() @@ -122,76 +474,33 @@ type SetUpHarborOptions struct { UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` } -// SetUpGroupHarbor sets up the Harbor integration for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#set-up-harbor func (s *IntegrationsService) SetUpGroupHarbor(gid any, opt *SetUpHarborOptions, options ...RequestOptionFunc) (*Integration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/integrations/harbor", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - integration := new(Integration) - resp, err := s.client.Do(req, integration) - if err != nil { - return nil, resp, err - } - return integration, resp, nil + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/harbor", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DisableGroupHarbor disables the Harbor integration for a group. -// Integration settings are reset. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#disable-harbor func (s *IntegrationsService) DisableGroupHarbor(gid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/integrations/harbor", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - resp, err := s.client.Do(req, nil) - if err != nil { - return nil, err - } - return resp, nil + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/harbor", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err } -// GetGroupHarborSettings gets the Harbor integration for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#get-harbor-settings func (s *IntegrationsService) GetGroupHarborSettings(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/integrations/harbor", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - integration := new(Integration) - resp, err := s.client.Do(req, integration) - if err != nil { - return nil, nil, err - } - return integration, resp, nil + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/harbor", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) } // SetMicrosoftTeamsNotificationsOptions represents the available @@ -200,91 +509,276 @@ func (s *IntegrationsService) GetGroupHarborSettings(gid any, options ...Request // GitLab API docs: // https://docs.gitlab.com/api/group_integrations/#set-up-microsoft-teams-notifications type SetMicrosoftTeamsNotificationsOptions struct { - Targets *string `url:"targets,omitempty"` - Webhook *string `url:"webhook,omitempty"` - NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty"` - NotifyOnlyDefaultBranch *bool `url:"notify_only_default_branch,omitempty"` - BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty"` - PushEvents *bool `url:"push_events,omitempty"` - IssuesEvents *bool `url:"issues_events,omitempty"` - ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty"` - MergeRequestsEvents *bool `url:"merge_requests_events,omitempty"` - TagPushEvents *bool `url:"tag_push_events,omitempty"` - NoteEvents *bool `url:"note_events,omitempty"` - ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty"` - PipelineEvents *bool `url:"pipeline_events,omitempty"` - WikiPageEvents *bool `url:"wiki_page_events,omitempty"` - UseInheritedSettings *bool `url:"use_inherited_settings,omitempty"` -} - -// SetGroupMicrosoftTeamsNotifications sets up Microsoft Teams notifications for a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#set-up-microsoft-teams-notifications + Targets *string `url:"targets,omitempty" json:"targets,omitempty"` + Webhook *string `url:"webhook,omitempty" json:"webhook,omitempty"` + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + NotifyOnlyDefaultBranch *bool `url:"notify_only_default_branch,omitempty" json:"notify_only_default_branch,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} + func (s *IntegrationsService) SetGroupMicrosoftTeamsNotifications(gid any, opt *SetMicrosoftTeamsNotificationsOptions, options ...RequestOptionFunc) (*Integration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/integrations/microsoft_teams", PathEscape(group)) + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/microsoft-teams", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } +func (s *IntegrationsService) DisableGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/microsoft-teams", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} - integration := new(Integration) - resp, err := s.client.Do(req, integration) - if err != nil { - return nil, resp, err - } - return integration, resp, nil +func (s *IntegrationsService) GetGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) { + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/microsoft-teams", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) } -// DisableGroupMicrosoftTeamsNotifications disables Microsoft Teams notifications -// for a group. Integration settings are reset. +// SetUpJiraOptions represents the available SetUpJira() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#disable-microsoft-teams-notifications -func (s *IntegrationsService) DisableGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/integrations/microsoft_teams", PathEscape(group)) +// https://docs.gitlab.com/api/group_integrations/#set-up-jira +type SetUpJiraOptions struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` + APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` + Active *bool `url:"active,omitempty" json:"active,omitempty"` + JiraAuthType *int64 `url:"jira_auth_type,omitempty" json:"jira_auth_type,omitempty"` + JiraIssuePrefix *string `url:"jira_issue_prefix,omitempty" json:"jira_issue_prefix,omitempty"` + JiraIssueRegex *string `url:"jira_issue_regex,omitempty" json:"jira_issue_regex,omitempty"` + JiraIssueTransitionAutomatic *bool `url:"jira_issue_transition_automatic,omitempty" json:"jira_issue_transition_automatic,omitempty"` + JiraIssueTransitionID *string `url:"jira_issue_transition_id,omitempty" json:"jira_issue_transition_id,omitempty"` + CommitEvents *bool `url:"commit_events,omitempty" json:"commit_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + CommentOnEventEnabled *bool `url:"comment_on_event_enabled,omitempty" json:"comment_on_event_enabled,omitempty"` + IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"` + ProjectKeys *[]string `url:"project_keys,omitempty" json:"project_keys,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } +func (s *IntegrationsService) SetUpGroupJira(gid any, opt *SetUpJiraOptions, options ...RequestOptionFunc) (*Integration, *Response, error) { + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/jira", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - resp, err := s.client.Do(req, nil) - if err != nil { - return nil, err - } - return resp, nil +func (s *IntegrationsService) DisableGroupJira(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/jira", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *IntegrationsService) GetGroupJiraSettings(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) { + return do[*Integration]( + s.client, + withPath("groups/%s/integrations/jira", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) } -// GetGroupMicrosoftTeamsNotifications gets the Microsoft Teams notifications for a group. +// SetGroupSlackOptions represents the available SetGroupSlackSettings() options. // // GitLab API docs: -// https://docs.gitlab.com/api/group_integrations/#get-microsoft-teams-notifications-settings -func (s *IntegrationsService) GetGroupMicrosoftTeamsNotifications(gid any, options ...RequestOptionFunc) (*Integration, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/integrations/microsoft_teams", PathEscape(group)) +// https://docs.gitlab.com/api/group_integrations/#set-up-slack-notifications +type SetGroupSlackOptions struct { + Webhook *string `url:"webhook,omitempty" json:"webhook,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + Channel *string `url:"channel,omitempty" json:"channel,omitempty"` + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + NotifyOnlyWhenPipelineStatusChanges *bool `url:"notify_only_when_pipeline_status_changes,omitempty" json:"notify_only_when_pipeline_status_changes,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` + LabelsToBeNotified *string `url:"labels_to_be_notified,omitempty" json:"labels_to_be_notified,omitempty"` + LabelsToBeNotifiedBehavior *string `url:"labels_to_be_notified_behavior,omitempty" json:"labels_to_be_notified_behavior,omitempty"` + AlertEvents *bool `url:"alert_events,omitempty" json:"alert_events,omitempty"` + CommitEvents *bool `url:"commit_events,omitempty" json:"commit_events,omitempty"` + PushChannel *string `url:"push_channel,omitempty" json:"push_channel,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssueChannel *string `url:"issue_channel,omitempty" json:"issue_channel,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"` + ConfidentialIssueChannel *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestChannel *string `url:"merge_request_channel,omitempty" json:"merge_request_channel,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + NoteChannel *string `url:"note_channel,omitempty" json:"note_channel,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + ConfidentialNoteChannel *string `url:"confidential_note_channel,omitempty" json:"confidential_note_channel,omitempty"` + ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` + TagPushChannel *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + PipelineChannel *string `url:"pipeline_channel,omitempty" json:"pipeline_channel,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageChannel *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + DeploymentChannel *string `url:"deployment_channel,omitempty" json:"deployment_channel,omitempty"` + DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"` + IncidentChannel *string `url:"incident_channel,omitempty" json:"incident_channel,omitempty"` + IncidentEvents *bool `url:"incident_events,omitempty" json:"incident_events,omitempty"` + AlertChannel *string `url:"alert_channel,omitempty" json:"alert_channel,omitempty"` + GroupMentionChannel *string `url:"group_mention_channel,omitempty" json:"group_mention_channel,omitempty"` + GroupConfidentialMentionChannel *string `url:"group_confidential_mention_channel,omitempty" json:"group_confidential_mention_channel,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } +func (s *IntegrationsService) SetGroupSlackSettings(gid any, opt *SetGroupSlackOptions, options ...RequestOptionFunc) (*SlackIntegration, *Response, error) { + return do[*SlackIntegration]( + s.client, + withPath("groups/%s/integrations/slack", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - integration := new(Integration) - resp, err := s.client.Do(req, integration) - if err != nil { - return nil, nil, err - } - return integration, resp, nil +func (s *IntegrationsService) DisableGroupSlack(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/slack", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *IntegrationsService) GetGroupSlackSettings(gid any, options ...RequestOptionFunc) (*SlackIntegration, *Response, error) { + return do[*SlackIntegration]( + s.client, + withPath("groups/%s/integrations/slack", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupDiscordSettings(gid any, options ...RequestOptionFunc) (*DiscordIntegration, *Response, error) { + return do[*DiscordIntegration]( + s.client, + withPath("groups/%s/integrations/discord", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupTelegramSettings(gid any, options ...RequestOptionFunc) (*TelegramIntegration, *Response, error) { + return do[*TelegramIntegration]( + s.client, + withPath("groups/%s/integrations/telegram", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupMattermostSettings(gid any, options ...RequestOptionFunc) (*MattermostIntegration, *Response, error) { + return do[*MattermostIntegration]( + s.client, + withPath("groups/%s/integrations/mattermost", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupMatrixSettings(gid any, options ...RequestOptionFunc) (*MatrixIntegration, *Response, error) { + return do[*MatrixIntegration]( + s.client, + withPath("groups/%s/integrations/matrix", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupGoogleChatSettings(gid any, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) { + return do[*GoogleChatIntegration]( + s.client, + withPath("groups/%s/integrations/hangouts-chat", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) SetProjectGoogleChatSettings(pid any, opt *SetProjectGoogleChatOptions, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) { + return do[*GoogleChatIntegration]( + s.client, + withPath("projects/%s/integrations/hangouts-chat", ProjectID{pid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) DisableProjectGoogleChat(pid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("projects/%s/integrations/hangouts-chat", ProjectID{pid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *IntegrationsService) GetProjectGoogleChatSettings(pid any, options ...RequestOptionFunc) (*GoogleChatIntegration, *Response, error) { + return do[*GoogleChatIntegration]( + s.client, + withPath("projects/%s/integrations/hangouts-chat", ProjectID{pid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) GetGroupWebexTeamsSettings(gid any, options ...RequestOptionFunc) (*WebexTeamsIntegration, *Response, error) { + return do[*WebexTeamsIntegration]( + s.client, + withPath("groups/%s/integrations/webex-teams", GroupID{gid}), + withMethod(http.MethodGet), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) SetGroupWebexTeamsSettings(gid any, opt *SetGroupWebexTeamsOptions, options ...RequestOptionFunc) (*WebexTeamsIntegration, *Response, error) { + return do[*WebexTeamsIntegration]( + s.client, + withPath("groups/%s/integrations/webex-teams", GroupID{gid}), + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *IntegrationsService) DisableGroupWebexTeams(gid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none]( + s.client, + withPath("groups/%s/integrations/webex-teams", GroupID{gid}), + withMethod(http.MethodDelete), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/invites.go b/vendor/gitlab.com/gitlab-org/api/client-go/invites.go index 71b64e078..5be8babe4 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/invites.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/invites.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -45,7 +44,7 @@ var _ InvitesServiceInterface = (*InvitesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/invitations/ type PendingInvite struct { - ID int `json:"id"` + ID int64 `json:"id"` InviteEmail string `json:"invite_email"` CreatedAt *time.Time `json:"created_at"` AccessLevel AccessLevelValue `json:"access_level"` @@ -69,24 +68,11 @@ type ListPendingInvitationsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/invitations/#list-all-invitations-pending-for-a-group-or-project func (s *InvitesService) ListPendingGroupInvitations(gid any, opt *ListPendingInvitationsOptions, options ...RequestOptionFunc) ([]*PendingInvite, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/invitations", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pis []*PendingInvite - resp, err := s.client.Do(req, &pis) - if err != nil { - return nil, resp, err - } - - return pis, resp, nil + return do[[]*PendingInvite](s.client, + withPath("groups/%s/invitations", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListPendingProjectInvitations gets a list of invited project members. @@ -94,24 +80,11 @@ func (s *InvitesService) ListPendingGroupInvitations(gid any, opt *ListPendingIn // GitLab API docs: // https://docs.gitlab.com/api/invitations/#list-all-invitations-pending-for-a-group-or-project func (s *InvitesService) ListPendingProjectInvitations(pid any, opt *ListPendingInvitationsOptions, options ...RequestOptionFunc) ([]*PendingInvite, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/invitations", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pis []*PendingInvite - resp, err := s.client.Do(req, &pis) - if err != nil { - return nil, resp, err - } - - return pis, resp, nil + return do[[]*PendingInvite](s.client, + withPath("projects/%s/invitations", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // InvitesOptions represents the available GroupInvites() and ProjectInvites() @@ -141,24 +114,12 @@ type InvitesResult struct { // GitLab API docs: // https://docs.gitlab.com/api/invitations/#add-a-member-to-a-group-or-project func (s *InvitesService) GroupInvites(gid any, opt *InvitesOptions, options ...RequestOptionFunc) (*InvitesResult, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/invitations", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ir := new(InvitesResult) - resp, err := s.client.Do(req, ir) - if err != nil { - return nil, resp, err - } - - return ir, resp, nil + return do[*InvitesResult](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/invitations", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectInvites invites new users by email to join a project. @@ -166,22 +127,10 @@ func (s *InvitesService) GroupInvites(gid any, opt *InvitesOptions, options ...R // GitLab API docs: // https://docs.gitlab.com/api/invitations/#add-a-member-to-a-group-or-project func (s *InvitesService) ProjectInvites(pid any, opt *InvitesOptions, options ...RequestOptionFunc) (*InvitesResult, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/invitations", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ir := new(InvitesResult) - resp, err := s.client.Do(req, ir) - if err != nil { - return nil, resp, err - } - - return ir, resp, nil + return do[*InvitesResult](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/invitations", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/issue_links.go b/vendor/gitlab.com/gitlab-org/api/client-go/issue_links.go index 78b3877ba..2cf4ce4bf 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/issue_links.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/issue_links.go @@ -17,17 +17,16 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( IssueLinksServiceInterface interface { - ListIssueRelations(pid any, issue int, options ...RequestOptionFunc) ([]*IssueRelation, *Response, error) - GetIssueLink(pid any, issue, issueLink int, options ...RequestOptionFunc) (*IssueLink, *Response, error) - CreateIssueLink(pid any, issue int, opt *CreateIssueLinkOptions, options ...RequestOptionFunc) (*IssueLink, *Response, error) - DeleteIssueLink(pid any, issue, issueLink int, options ...RequestOptionFunc) (*IssueLink, *Response, error) + ListIssueRelations(pid any, issue int64, options ...RequestOptionFunc) ([]*IssueRelation, *Response, error) + GetIssueLink(pid any, issue, issueLink int64, options ...RequestOptionFunc) (*IssueLink, *Response, error) + CreateIssueLink(pid any, issue int64, opt *CreateIssueLinkOptions, options ...RequestOptionFunc) (*IssueLink, *Response, error) + DeleteIssueLink(pid any, issue, issueLink int64, options ...RequestOptionFunc) (*IssueLink, *Response, error) } // IssueLinksService handles communication with the issue relations related methods @@ -45,6 +44,7 @@ var _ IssueLinksServiceInterface = (*IssueLinksService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/issue_links/ type IssueLink struct { + ID int64 `json:"id"` SourceIssue *Issue `json:"source_issue"` TargetIssue *Issue `json:"target_issue"` LinkType string `json:"link_type"` @@ -55,14 +55,14 @@ type IssueLink struct { // GitLab API docs: // https://docs.gitlab.com/api/issue_links/#list-issue-relations type IssueRelation struct { - ID int `json:"id"` - IID int `json:"iid"` + ID int64 `json:"id"` + IID int64 `json:"iid"` State string `json:"state"` Description string `json:"description"` Confidential bool `json:"confidential"` Author *IssueAuthor `json:"author"` Milestone *Milestone `json:"milestone"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Assignees []*IssueAssignee `json:"assignees"` Assignee *IssueAssignee `json:"assignee"` UpdatedAt *time.Time `json:"updated_at"` @@ -72,9 +72,9 @@ type IssueRelation struct { DueDate *ISOTime `json:"due_date"` WebURL string `json:"web_url"` References *IssueReferences `json:"references"` - Weight int `json:"weight"` - UserNotesCount int `json:"user_notes_count"` - IssueLinkID int `json:"issue_link_id"` + Weight int64 `json:"weight"` + UserNotesCount int64 `json:"user_notes_count"` + IssueLinkID int64 `json:"issue_link_id"` LinkType string `json:"link_type"` LinkCreatedAt *time.Time `json:"link_created_at"` LinkUpdatedAt *time.Time `json:"link_updated_at"` @@ -87,50 +87,24 @@ type IssueRelation struct { // // GitLab API docs: // https://docs.gitlab.com/api/issue_links/#list-issue-relations -func (s *IssueLinksService) ListIssueRelations(pid any, issue int, options ...RequestOptionFunc) ([]*IssueRelation, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/links", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var is []*IssueRelation - resp, err := s.client.Do(req, &is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil +func (s *IssueLinksService) ListIssueRelations(pid any, issue int64, options ...RequestOptionFunc) ([]*IssueRelation, *Response, error) { + // Use explicit format string for the path + return do[[]*IssueRelation](s.client, + withPath("projects/%s/issues/%d/links", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } // GetIssueLink gets a specific issue link. // // GitLab API docs: // https://docs.gitlab.com/api/issue_links/#get-an-issue-link -func (s *IssueLinksService) GetIssueLink(pid any, issue, issueLink int, options ...RequestOptionFunc) (*IssueLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/links/%d", PathEscape(project), issue, issueLink) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - il := new(IssueLink) - resp, err := s.client.Do(req, il) - if err != nil { - return nil, resp, err - } - - return il, resp, nil +func (s *IssueLinksService) GetIssueLink(pid any, issue, issueLink int64, options ...RequestOptionFunc) (*IssueLink, *Response, error) { + // Use explicit format string for the path + return do[*IssueLink](s.client, + withPath("projects/%s/issues/%d/links/%d", ProjectID{pid}, issue, issueLink), + withRequestOpts(options...), + ) } // CreateIssueLinkOptions represents the available CreateIssueLink() options. @@ -147,51 +121,23 @@ type CreateIssueLinkOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/issue_links/#create-an-issue-link -func (s *IssueLinksService) CreateIssueLink(pid any, issue int, opt *CreateIssueLinkOptions, options ...RequestOptionFunc) (*IssueLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/links", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - i := new(IssueLink) - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssueLinksService) CreateIssueLink(pid any, issue int64, opt *CreateIssueLinkOptions, options ...RequestOptionFunc) (*IssueLink, *Response, error) { + return do[*IssueLink](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/links", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteIssueLink deletes an issue link, thus removes the two-way relationship. // // GitLab API docs: // https://docs.gitlab.com/api/issue_links/#delete-an-issue-link -func (s *IssueLinksService) DeleteIssueLink(pid any, issue, issueLink int, options ...RequestOptionFunc) (*IssueLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/links/%d", - PathEscape(project), - issue, - issueLink) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, nil, err - } - - il := new(IssueLink) - resp, err := s.client.Do(req, &il) - if err != nil { - return nil, resp, err - } - - return il, resp, nil +func (s *IssueLinksService) DeleteIssueLink(pid any, issue, issueLink int64, options ...RequestOptionFunc) (*IssueLink, *Response, error) { + return do[*IssueLink](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/issues/%d/links/%d", ProjectID{pid}, issue, issueLink), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/issues.go b/vendor/gitlab.com/gitlab-org/api/client-go/issues.go index cd2564e50..71aa93bec 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/issues.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/issues.go @@ -18,7 +18,6 @@ package gitlab import ( "encoding/json" - "fmt" "net/http" "reflect" "strings" @@ -30,24 +29,24 @@ type ( ListIssues(opt *ListIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) ListGroupIssues(pid any, opt *ListGroupIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) ListProjectIssues(pid any, opt *ListProjectIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) - GetIssueByID(issue int, options ...RequestOptionFunc) (*Issue, *Response, error) - GetIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) + GetIssueByID(issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) + GetIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) CreateIssue(pid any, opt *CreateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) - UpdateIssue(pid any, issue int, opt *UpdateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) - DeleteIssue(pid any, issue int, options ...RequestOptionFunc) (*Response, error) - ReorderIssue(pid any, issue int, opt *ReorderIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) - MoveIssue(pid any, issue int, opt *MoveIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) - SubscribeToIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) - UnsubscribeFromIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) - CreateTodo(pid any, issue int, options ...RequestOptionFunc) (*Todo, *Response, error) - ListMergeRequestsClosingIssue(pid any, issue int, opt *ListMergeRequestsClosingIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) - ListMergeRequestsRelatedToIssue(pid any, issue int, opt *ListMergeRequestsRelatedToIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) - SetTimeEstimate(pid any, issue int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) - ResetTimeEstimate(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - AddSpentTime(pid any, issue int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) - ResetSpentTime(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - GetTimeSpent(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - GetParticipants(pid any, issue int, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) + UpdateIssue(pid any, issue int64, opt *UpdateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) + DeleteIssue(pid any, issue int64, options ...RequestOptionFunc) (*Response, error) + ReorderIssue(pid any, issue int64, opt *ReorderIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) + MoveIssue(pid any, issue int64, opt *MoveIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) + SubscribeToIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) + UnsubscribeFromIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) + CreateTodo(pid any, issue int64, options ...RequestOptionFunc) (*Todo, *Response, error) + ListMergeRequestsClosingIssue(pid any, issue int64, opt *ListMergeRequestsClosingIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) + ListMergeRequestsRelatedToIssue(pid any, issue int64, opt *ListMergeRequestsRelatedToIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) + SetTimeEstimate(pid any, issue int64, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) + ResetTimeEstimate(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + AddSpentTime(pid any, issue int64, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) + ResetSpentTime(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + GetTimeSpent(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + GetParticipants(pid any, issue int64, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) } // IssuesService handles communication with the issue related methods @@ -64,7 +63,7 @@ var _ IssuesServiceInterface = (*IssuesService)(nil) // IssueAuthor represents a author of the issue. type IssueAuthor struct { - ID int `json:"id"` + ID int64 `json:"id"` State string `json:"state"` WebURL string `json:"web_url"` Name string `json:"name"` @@ -74,7 +73,7 @@ type IssueAuthor struct { // IssueAssignee represents a assignee of the issue. type IssueAssignee struct { - ID int `json:"id"` + ID int64 `json:"id"` State string `json:"state"` WebURL string `json:"web_url"` Name string `json:"name"` @@ -91,7 +90,7 @@ type IssueReferences struct { // IssueCloser represents a closer of the issue. type IssueCloser struct { - ID int `json:"id"` + ID int64 `json:"id"` State string `json:"state"` WebURL string `json:"web_url"` Name string `json:"name"` @@ -111,40 +110,40 @@ type IssueLinks struct { // // GitLab API docs: https://docs.gitlab.com/api/issues/ type Issue struct { - ID int `json:"id"` - IID int `json:"iid"` + ID int64 `json:"id"` + IID int64 `json:"iid"` ExternalID string `json:"external_id"` State string `json:"state"` Description string `json:"description"` HealthStatus string `json:"health_status"` Author *IssueAuthor `json:"author"` Milestone *Milestone `json:"milestone"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Assignees []*IssueAssignee `json:"assignees"` UpdatedAt *time.Time `json:"updated_at"` ClosedAt *time.Time `json:"closed_at"` ClosedBy *IssueCloser `json:"closed_by"` Title string `json:"title"` CreatedAt *time.Time `json:"created_at"` - MovedToID int `json:"moved_to_id"` + MovedToID int64 `json:"moved_to_id"` Labels Labels `json:"labels"` LabelDetails []*LabelDetails `json:"label_details"` - Upvotes int `json:"upvotes"` - Downvotes int `json:"downvotes"` + Upvotes int64 `json:"upvotes"` + Downvotes int64 `json:"downvotes"` DueDate *ISOTime `json:"due_date"` WebURL string `json:"web_url"` References *IssueReferences `json:"references"` TimeStats *TimeStats `json:"time_stats"` Confidential bool `json:"confidential"` - Weight int `json:"weight"` + Weight int64 `json:"weight"` DiscussionLocked bool `json:"discussion_locked"` IssueType *string `json:"issue_type,omitempty"` Subscribed bool `json:"subscribed"` - UserNotesCount int `json:"user_notes_count"` + UserNotesCount int64 `json:"user_notes_count"` Links *IssueLinks `json:"_links"` - IssueLinkID int `json:"issue_link_id"` - MergeRequestCount int `json:"merge_requests_count"` - EpicIssueID int `json:"epic_issue_id"` + IssueLinkID int64 `json:"issue_link_id"` + MergeRequestCount int64 `json:"merge_requests_count"` + EpicIssueID int64 `json:"epic_issue_id"` Epic *Epic `json:"epic"` Iteration *GroupIteration `json:"iteration"` TaskCompletionStatus *TasksCompletionStatus `json:"task_completion_status"` @@ -198,7 +197,7 @@ func (i *Issue) UnmarshalJSON(data []byte) error { // LabelDetails represents detailed label information. type LabelDetails struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Color string `json:"color"` Description string `json:"description"` @@ -218,17 +217,17 @@ type ListIssuesOptions struct { Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` NotMilestone *string `url:"not[milestone],omitempty" json:"not[milestone],omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` - NotAuthorID *[]int `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` + NotAuthorID *[]int64 `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - NotAssigneeID *[]int `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` + NotAssigneeID *[]int64 `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` AssigneeUsername *string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` NotAssigneeUsername *string `url:"not[assignee_username],omitempty" json:"not[assignee_username],omitempty"` MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` NotMyReactionEmoji *[]string `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"` - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` In *string `url:"in,omitempty" json:"in,omitempty"` NotIn *string `url:"not[in],omitempty" json:"not[in],omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` @@ -242,7 +241,7 @@ type ListIssuesOptions struct { UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` - IterationID *int `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` + IterationID *int64 `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` } // ListIssues gets all issues created by authenticated user. This function @@ -250,18 +249,11 @@ type ListIssuesOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/issues/#list-issues func (s *IssuesService) ListIssues(opt *ListIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "issues", opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil + return do[[]*Issue](s.client, + withPath("issues"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListGroupIssuesOptions represents the available ListGroupIssues() options. @@ -273,20 +265,20 @@ type ListGroupIssuesOptions struct { Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` NotLabels *LabelOptions `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"` WithLabelDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"` - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` NotMilestone *string `url:"not[milestone],omitempty" json:"not[milestone],omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` - NotAuthorID *int `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` + NotAuthorID *int64 `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` - // AssigneeID is defined as an int in the documentation, however, the field + // AssigneeID is defined as an int64 in the documentation, however, the field // must be able to accept Assignee IDs and the words 'None' and 'Any'. Use - // *AssigneeIDValue instead of *int. + // *AssigneeIDValue instead of *int64. AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - NotAssigneeID *int `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` + NotAssigneeID *int64 `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` AssigneeUsername *string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` NotAssigneeUsername *string `url:"not[assignee_username],omitempty" json:"not[assignee_username],omitempty"` MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` @@ -304,7 +296,7 @@ type ListGroupIssuesOptions struct { UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` - IterationID *int `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` + IterationID *int64 `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` } // ListGroupIssues gets a list of group issues. This function accepts @@ -312,24 +304,11 @@ type ListGroupIssuesOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/issues/#list-group-issues func (s *IssuesService) ListGroupIssues(pid any, opt *ListGroupIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/issues", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil + return do[[]*Issue](s.client, + withPath("groups/%s/issues", GroupID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListProjectIssuesOptions represents the available ListProjectIssues() options. @@ -337,37 +316,41 @@ func (s *IssuesService) ListGroupIssues(pid any, opt *ListGroupIssuesOptions, op // GitLab API docs: https://docs.gitlab.com/api/issues/#list-project-issues type ListProjectIssuesOptions struct { ListOptions - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` - State *string `url:"state,omitempty" json:"state,omitempty"` - Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` - NotLabels *LabelOptions `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"` - WithLabelDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"` - Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` - NotMilestone *string `url:"not[milestone],omitempty" json:"not[milestone],omitempty"` - Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` - AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` - NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` - NotAuthorID *int `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - NotAssigneeID *int `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` - AssigneeUsername *string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` - NotAssigneeUsername *string `url:"not[assignee_username],omitempty" json:"not[assignee_username],omitempty"` - MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` - NotMyReactionEmoji *string `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"` - OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` - Sort *string `url:"sort,omitempty" json:"sort,omitempty"` - Search *string `url:"search,omitempty" json:"search,omitempty"` - In *string `url:"in,omitempty" json:"in,omitempty"` - NotIn *string `url:"not[in],omitempty" json:"not[in],omitempty"` - CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` - CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` - DueDate *string `url:"due_date,omitempty" json:"due_date,omitempty"` - UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` - UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` - Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` - IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` - IterationID *int `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` + Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` + NotLabels *LabelOptions `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"` + WithLabelDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"` + Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` + NotMilestone *string `url:"not[milestone],omitempty" json:"not[milestone],omitempty"` + Scope *string `url:"scope,omitempty" json:"scope,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` + NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` + NotAuthorID *int64 `url:"not[author_id],omitempty" json:"not[author_id],omitempty"` + + // AssigneeID is defined as an int in the documentation, however, the field + // must be able to accept Assignee IDs and the words 'None' and 'Any'. Use + // *AssigneeIDValue instead of *int. + AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + NotAssigneeID *int64 `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"` + AssigneeUsername *string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` + NotAssigneeUsername *string `url:"not[assignee_username],omitempty" json:"not[assignee_username],omitempty"` + MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` + NotMyReactionEmoji *string `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"` + OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` + Sort *string `url:"sort,omitempty" json:"sort,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + In *string `url:"in,omitempty" json:"in,omitempty"` + NotIn *string `url:"not[in],omitempty" json:"not[in],omitempty"` + CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` + CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` + DueDate *string `url:"due_date,omitempty" json:"due_date,omitempty"` + UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` + UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` + Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` + IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` + IterationID *int64 `url:"iteration_id,omitempty" json:"iteration_id,omitempty"` } // ListProjectIssues gets a list of project issues. This function accepts @@ -375,87 +358,53 @@ type ListProjectIssuesOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/issues/#list-project-issues func (s *IssuesService) ListProjectIssues(pid any, opt *ListProjectIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil + return do[[]*Issue](s.client, + withPath("projects/%s/issues", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueByID gets a single issue. // // GitLab API docs: https://docs.gitlab.com/api/issues/#single-issue -func (s *IssuesService) GetIssueByID(issue int, options ...RequestOptionFunc) (*Issue, *Response, error) { - u := fmt.Sprintf("issues/%d", issue) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) GetIssueByID(issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withPath("issues/%d", issue), + withRequestOpts(options...), + ) } // GetIssue gets a single project issue. // // GitLab API docs: https://docs.gitlab.com/api/issues/#single-project-issue -func (s *IssuesService) GetIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) GetIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withPath("projects/%s/issues/%d", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } // CreateIssueOptions represents the available CreateIssue() options. // // GitLab API docs: https://docs.gitlab.com/api/issues/#new-issue type CreateIssueOptions struct { - IID *int `url:"iid,omitempty" json:"iid,omitempty"` - Title *string `url:"title,omitempty" json:"title,omitempty"` - Description *string `url:"description,omitempty" json:"description,omitempty"` - Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` - AssigneeIDs *[]int `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + IID *int64 `url:"iid,omitempty" json:"iid,omitempty"` + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` + // AssigneeID is a CE-only attribute. For EE, use AssigneeIDs instead. + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + // AssigneeIDs is a EE-only attribute. For CE, use AssigneeID instead. + AssigneeIDs *[]int64 `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"` DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` - EpicID *int `url:"epic_id,omitempty" json:"epic_id,omitempty"` - MergeRequestToResolveDiscussionsOf *int `url:"merge_request_to_resolve_discussions_of,omitempty" json:"merge_request_to_resolve_discussions_of,omitempty"` + EpicID *int64 `url:"epic_id,omitempty" json:"epic_id,omitempty"` + MergeRequestToResolveDiscussionsOf *int64 `url:"merge_request_to_resolve_discussions_of,omitempty" json:"merge_request_to_resolve_discussions_of,omitempty"` DiscussionToResolve *string `url:"discussion_to_resolve,omitempty" json:"discussion_to_resolve,omitempty"` - Weight *int `url:"weight,omitempty" json:"weight,omitempty"` + Weight *int64 `url:"weight,omitempty" json:"weight,omitempty"` IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` } @@ -463,24 +412,12 @@ type CreateIssueOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/issues/#new-issue func (s *IssuesService) CreateIssue(pid any, opt *CreateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil + return do[*Issue](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateIssueOptions represents the available UpdateIssue() options. @@ -490,19 +427,22 @@ func (s *IssuesService) CreateIssue(pid any, opt *CreateIssueOptions, options .. // // GitLab API docs: https://docs.gitlab.com/api/issues/#edit-an-issue type UpdateIssueOptions struct { - Title *string `url:"title,omitempty" json:"title,omitempty"` - Description *string `url:"description,omitempty" json:"description,omitempty"` - Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` - AssigneeIDs *[]int `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + Title *string `url:"title,omitempty" json:"title,omitempty"` + Description *string `url:"description,omitempty" json:"description,omitempty"` + Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` + // AssigneeID is a CE-only attribute. For EE, use AssigneeIDs instead. + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + // AssigneeIDs is a EE-only attribute. For CE, use AssigneeID instead. + AssigneeIDs *[]int64 `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` AddLabels *LabelOptions `url:"add_labels,comma,omitempty" json:"add_labels,omitempty"` RemoveLabels *LabelOptions `url:"remove_labels,comma,omitempty" json:"remove_labels,omitempty"` StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` UpdatedAt *time.Time `url:"updated_at,omitempty" json:"updated_at,omitempty"` DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` - EpicID *int `url:"epic_id,omitempty" json:"epic_id,omitempty"` - Weight *int `url:"weight,omitempty" json:"weight,omitempty"` + EpicID *int64 `url:"epic_id,omitempty" json:"epic_id,omitempty"` + Weight *int64 `url:"weight,omitempty" json:"weight,omitempty"` DiscussionLocked *bool `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"` IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"` @@ -568,107 +508,65 @@ func (o UpdateIssueOptions) MarshalJSON() ([]byte, error) { // to mark an issue as closed. // // GitLab API docs: https://docs.gitlab.com/api/issues/#edit-an-issue -func (s *IssuesService) UpdateIssue(pid any, issue int, opt *UpdateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) UpdateIssue(pid any, issue int64, opt *UpdateIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/issues/%d", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteIssue deletes a single project issue. // // GitLab API docs: https://docs.gitlab.com/api/issues/#delete-an-issue -func (s *IssuesService) DeleteIssue(pid any, issue int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *IssuesService) DeleteIssue(pid any, issue int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/issues/%d", ProjectID{pid}, issue), + withRequestOpts(options...), + ) + return resp, err } // ReorderIssueOptions represents the available ReorderIssue() options. // // GitLab API docs: https://docs.gitlab.com/api/issues/#reorder-an-issue type ReorderIssueOptions struct { - MoveAfterID *int `url:"move_after_id,omitempty" json:"move_after_id,omitempty"` - MoveBeforeID *int `url:"move_before_id,omitempty" json:"move_before_id,omitempty"` + MoveAfterID *int64 `url:"move_after_id,omitempty" json:"move_after_id,omitempty"` + MoveBeforeID *int64 `url:"move_before_id,omitempty" json:"move_before_id,omitempty"` } // ReorderIssue reorders an issue. // // GitLab API docs: https://docs.gitlab.com/api/issues/#reorder-an-issue -func (s *IssuesService) ReorderIssue(pid any, issue int, opt *ReorderIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/reorder", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) ReorderIssue(pid any, issue int64, opt *ReorderIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/issues/%d/reorder", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // MoveIssueOptions represents the available MoveIssue() options. // // GitLab API docs: https://docs.gitlab.com/api/issues/#move-an-issue type MoveIssueOptions struct { - ToProjectID *int `url:"to_project_id,omitempty" json:"to_project_id,omitempty"` + ToProjectID *int64 `url:"to_project_id,omitempty" json:"to_project_id,omitempty"` } // MoveIssue updates an existing project issue. This function is also used // to mark an issue as closed. // // GitLab API docs: https://docs.gitlab.com/api/issues/#move-an-issue -func (s *IssuesService) MoveIssue(pid any, issue int, opt *MoveIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/move", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) MoveIssue(pid any, issue int64, opt *MoveIssueOptions, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/move", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SubscribeToIssue subscribes the authenticated user to the given issue to @@ -677,25 +575,12 @@ func (s *IssuesService) MoveIssue(pid any, issue int, opt *MoveIssueOptions, opt // // GitLab API docs: // https://docs.gitlab.com/api/issues/#subscribe-to-an-issue -func (s *IssuesService) SubscribeToIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/subscribe", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) SubscribeToIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/subscribe", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } // UnsubscribeFromIssue unsubscribes the authenticated user from the given @@ -704,25 +589,12 @@ func (s *IssuesService) SubscribeToIssue(pid any, issue int, options ...RequestO // // GitLab API docs: // https://docs.gitlab.com/api/issues/#unsubscribe-from-an-issue -func (s *IssuesService) UnsubscribeFromIssue(pid any, issue int, options ...RequestOptionFunc) (*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/unsubscribe", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - i := new(Issue) - resp, err := s.client.Do(req, i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *IssuesService) UnsubscribeFromIssue(pid any, issue int64, options ...RequestOptionFunc) (*Issue, *Response, error) { + return do[*Issue](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/unsubscribe", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } // CreateTodo creates a todo for the current user for an issue. @@ -731,25 +603,12 @@ func (s *IssuesService) UnsubscribeFromIssue(pid any, issue int, options ...Requ // // GitLab API docs: // https://docs.gitlab.com/api/issues/#create-a-to-do-item -func (s *IssuesService) CreateTodo(pid any, issue int, options ...RequestOptionFunc) (*Todo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/todo", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(Todo) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *IssuesService) CreateTodo(pid any, issue int64, options ...RequestOptionFunc) (*Todo, *Response, error) { + return do[*Todo](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/todo", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } // ListMergeRequestsClosingIssueOptions represents the available @@ -757,32 +616,21 @@ func (s *IssuesService) CreateTodo(pid any, issue int, options ...RequestOptionF // // GitLab API docs: // https://docs.gitlab.com/api/issues/#list-merge-requests-that-close-a-particular-issue-on-merge -type ListMergeRequestsClosingIssueOptions ListOptions +type ListMergeRequestsClosingIssueOptions struct { + ListOptions +} // ListMergeRequestsClosingIssue gets all the merge requests that will close // issue when merged. // // GitLab API docs: // https://docs.gitlab.com/api/issues/#list-merge-requests-that-close-a-particular-issue-on-merge -func (s *IssuesService) ListMergeRequestsClosingIssue(pid any, issue int, opt *ListMergeRequestsClosingIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/closed_by", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*BasicMergeRequest - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *IssuesService) ListMergeRequestsClosingIssue(pid any, issue int64, opt *ListMergeRequestsClosingIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { + return do[[]*BasicMergeRequest](s.client, + withPath("projects/%s/issues/%d/closed_by", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListMergeRequestsRelatedToIssueOptions represents the available @@ -790,42 +638,28 @@ func (s *IssuesService) ListMergeRequestsClosingIssue(pid any, issue int, opt *L // // GitLab API docs: // https://docs.gitlab.com/api/issues/#list-merge-requests-related-to-issue -type ListMergeRequestsRelatedToIssueOptions ListOptions +type ListMergeRequestsRelatedToIssueOptions struct { + ListOptions +} // ListMergeRequestsRelatedToIssue gets all the merge requests that are // related to the issue // // GitLab API docs: // https://docs.gitlab.com/api/issues/#list-merge-requests-related-to-issue -func (s *IssuesService) ListMergeRequestsRelatedToIssue(pid any, issue int, opt *ListMergeRequestsRelatedToIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/related_merge_requests", - PathEscape(project), - issue, +func (s *IssuesService) ListMergeRequestsRelatedToIssue(pid any, issue int64, opt *ListMergeRequestsRelatedToIssueOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { + return do[[]*BasicMergeRequest](s.client, + withPath("projects/%s/issues/%d/related_merge_requests", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*BasicMergeRequest - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil } // SetTimeEstimate sets the time estimate for a single project issue. // // GitLab API docs: // https://docs.gitlab.com/api/issues/#set-a-time-estimate-for-an-issue -func (s *IssuesService) SetTimeEstimate(pid any, issue int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *IssuesService) SetTimeEstimate(pid any, issue int64, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.setTimeEstimate(pid, "issues", issue, opt, options...) } @@ -833,7 +667,7 @@ func (s *IssuesService) SetTimeEstimate(pid any, issue int, opt *SetTimeEstimate // // GitLab API docs: // https://docs.gitlab.com/api/issues/#reset-the-time-estimate-for-an-issue -func (s *IssuesService) ResetTimeEstimate(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *IssuesService) ResetTimeEstimate(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.resetTimeEstimate(pid, "issues", issue, options...) } @@ -841,7 +675,7 @@ func (s *IssuesService) ResetTimeEstimate(pid any, issue int, options ...Request // // GitLab API docs: // https://docs.gitlab.com/api/issues/#add-spent-time-for-an-issue -func (s *IssuesService) AddSpentTime(pid any, issue int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *IssuesService) AddSpentTime(pid any, issue int64, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.addSpentTime(pid, "issues", issue, opt, options...) } @@ -849,7 +683,7 @@ func (s *IssuesService) AddSpentTime(pid any, issue int, opt *AddSpentTimeOption // // GitLab API docs: // https://docs.gitlab.com/api/issues/#reset-spent-time-for-an-issue -func (s *IssuesService) ResetSpentTime(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *IssuesService) ResetSpentTime(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.resetSpentTime(pid, "issues", issue, options...) } @@ -857,7 +691,7 @@ func (s *IssuesService) ResetSpentTime(pid any, issue int, options ...RequestOpt // // GitLab API docs: // https://docs.gitlab.com/api/issues/#get-time-tracking-stats -func (s *IssuesService) GetTimeSpent(pid any, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *IssuesService) GetTimeSpent(pid any, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.getTimeSpent(pid, "issues", issue, options...) } @@ -865,23 +699,9 @@ func (s *IssuesService) GetTimeSpent(pid any, issue int, options ...RequestOptio // // GitLab API docs: // https://docs.gitlab.com/api/issues/#list-participants-in-an-issue -func (s *IssuesService) GetParticipants(pid any, issue int, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/participants", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var bu []*BasicUser - resp, err := s.client.Do(req, &bu) - if err != nil { - return nil, resp, err - } - - return bu, resp, nil +func (s *IssuesService) GetParticipants(pid any, issue int64, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) { + return do[[]*BasicUser](s.client, + withPath("projects/%s/issues/%d/participants", ProjectID{pid}, issue), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/issues_statistics.go b/vendor/gitlab.com/gitlab-org/api/client-go/issues_statistics.go index 23f68169a..b3d13b183 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/issues_statistics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/issues_statistics.go @@ -17,15 +17,26 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( IssuesStatisticsServiceInterface interface { + // GetIssuesStatistics gets issues statistics on all issues the authenticated + // user has access to. + // + // GitLab API docs: + // https://docs.gitlab.com/api/issues_statistics/#get-issues-statistics GetIssuesStatistics(opt *GetIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) + // GetGroupIssuesStatistics gets issues count statistics for given group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/issues_statistics/#get-group-issues-statistics GetGroupIssuesStatistics(gid any, opt *GetGroupIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) + // GetProjectIssuesStatistics gets issues count statistics for given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/issues_statistics/#get-project-issues-statistics GetProjectIssuesStatistics(pid any, opt *GetProjectIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) } @@ -44,19 +55,29 @@ var _ IssuesStatisticsServiceInterface = (*IssuesStatisticsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/issues_statistics/ type IssuesStatistics struct { - Statistics struct { - Counts struct { - All int `json:"all"` - Closed int `json:"closed"` - Opened int `json:"opened"` - } `json:"counts"` - } `json:"statistics"` + Statistics IssuesStatisticsStatistics `json:"statistics"` } func (n IssuesStatistics) String() string { return Stringify(n) } +// IssuesStatisticsStatistics represents a GitLab issues statistic statistics. +// +// GitLab API docs: https://docs.gitlab.com/api/issues_statistics/ +type IssuesStatisticsStatistics struct { + Counts IssuesStatisticsCounts `json:"counts"` +} + +// IssuesStatisticsCounts represents a GitLab issues statistic counts. +// +// GitLab API docs: https://docs.gitlab.com/api/issues_statistics/ +type IssuesStatisticsCounts struct { + All int64 `json:"all"` + Closed int64 `json:"closed"` + Opened int64 `json:"opened"` +} + // GetIssuesStatisticsOptions represents the available GetIssuesStatistics() options. // // GitLab API docs: @@ -65,12 +86,12 @@ type GetIssuesStatisticsOptions struct { Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` AssigneeUsername *[]string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` In *string `url:"in,omitempty" json:"in,omitempty"` CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` @@ -80,24 +101,12 @@ type GetIssuesStatisticsOptions struct { Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` } -// GetIssuesStatistics gets issues statistics on all issues the authenticated -// user has access to. -// -// GitLab API docs: -// https://docs.gitlab.com/api/issues_statistics/#get-issues-statistics func (s *IssuesStatisticsService) GetIssuesStatistics(opt *GetIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "issues_statistics", opt, options) - if err != nil { - return nil, nil, err - } - - is := new(IssuesStatistics) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil + return do[*IssuesStatistics](s.client, + withPath("issues_statistics"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupIssuesStatisticsOptions represents the available GetGroupIssuesStatistics() @@ -107,12 +116,12 @@ func (s *IssuesStatisticsService) GetIssuesStatistics(opt *GetIssuesStatisticsOp // https://docs.gitlab.com/api/issues_statistics/#get-group-issues-statistics type GetGroupIssuesStatisticsOptions struct { Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` AssigneeUsername *[]string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` @@ -123,29 +132,12 @@ type GetGroupIssuesStatisticsOptions struct { Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` } -// GetGroupIssuesStatistics gets issues count statistics for given group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/issues_statistics/#get-group-issues-statistics func (s *IssuesStatisticsService) GetGroupIssuesStatistics(gid any, opt *GetGroupIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/issues_statistics", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - is := new(IssuesStatistics) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil + return do[*IssuesStatistics](s.client, + withPath("groups/%s/issues_statistics", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectIssuesStatisticsOptions represents the available @@ -154,13 +146,13 @@ func (s *IssuesStatisticsService) GetGroupIssuesStatistics(gid any, opt *GetGrou // GitLab API docs: // https://docs.gitlab.com/api/issues_statistics/#get-project-issues-statistics type GetProjectIssuesStatisticsOptions struct { - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"` Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` AssigneeUsername *[]string `url:"assignee_username,omitempty" json:"assignee_username,omitempty"` MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` @@ -171,27 +163,10 @@ type GetProjectIssuesStatisticsOptions struct { Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"` } -// GetProjectIssuesStatistics gets issues count statistics for given project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/issues_statistics/#get-project-issues-statistics func (s *IssuesStatisticsService) GetProjectIssuesStatistics(pid any, opt *GetProjectIssuesStatisticsOptions, options ...RequestOptionFunc) (*IssuesStatistics, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues_statistics", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - is := new(IssuesStatistics) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil + return do[*IssuesStatistics](s.client, + withPath("projects/%s/issues_statistics", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/job_token_scope.go b/vendor/gitlab.com/gitlab-org/api/client-go/job_token_scope.go index 6c2fa0ca0..7d418a677 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/job_token_scope.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/job_token_scope.go @@ -11,12 +11,10 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( JobTokenScopeServiceInterface interface { @@ -24,10 +22,10 @@ type ( PatchProjectJobTokenAccessSettings(pid any, opt *PatchProjectJobTokenAccessSettingsOptions, options ...RequestOptionFunc) (*Response, error) GetProjectJobTokenInboundAllowList(pid any, opt *GetJobTokenInboundAllowListOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) AddProjectToJobScopeAllowList(pid any, opt *JobTokenInboundAllowOptions, options ...RequestOptionFunc) (*JobTokenInboundAllowItem, *Response, error) - RemoveProjectFromJobScopeAllowList(pid any, targetProject int, options ...RequestOptionFunc) (*Response, error) + RemoveProjectFromJobScopeAllowList(pid any, targetProject int64, options ...RequestOptionFunc) (*Response, error) GetJobTokenAllowlistGroups(pid any, opt *GetJobTokenAllowlistGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) AddGroupToJobTokenAllowlist(pid any, opt *AddGroupToJobTokenAllowlistOptions, options ...RequestOptionFunc) (*JobTokenAllowlistItem, *Response, error) - RemoveGroupFromJobTokenAllowlist(pid any, targetGroup int, options ...RequestOptionFunc) (*Response, error) + RemoveGroupFromJobTokenAllowlist(pid any, targetGroup int64, options ...RequestOptionFunc) (*Response, error) } // JobTokenScopeService handles communication with project CI settings @@ -53,24 +51,10 @@ type JobTokenAccessSettings struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-access-settings func (j *JobTokenScopeService) GetProjectJobTokenAccessSettings(pid any, options ...RequestOptionFunc) (*JobTokenAccessSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - jt := new(JobTokenAccessSettings) - resp, err := j.client.Do(req, jt) - if err != nil { - return nil, resp, err - } - - return jt, resp, err + return do[*JobTokenAccessSettings](j.client, + withPath("projects/%s/job_token_scope", ProjectID{pid}), + withRequestOpts(options...), + ) } // PatchProjectJobTokenAccessSettingsOptions represents the available @@ -87,26 +71,21 @@ type PatchProjectJobTokenAccessSettingsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#patch-a-projects-cicd-job-token-access-settings func (j *JobTokenScopeService) PatchProjectJobTokenAccessSettings(pid any, opt *PatchProjectJobTokenAccessSettingsOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, err - } - - return j.client.Do(req, nil) + _, resp, err := do[none](j.client, + withMethod(http.MethodPatch), + withPath("projects/%s/job_token_scope", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // JobTokenInboundAllowItem represents a single job token inbound allowlist item. // // GitLab API docs: https://docs.gitlab.com/api/project_job_token_scopes/ type JobTokenInboundAllowItem struct { - SourceProjectID int `json:"source_project_id"` - TargetProjectID int `json:"target_project_id"` + SourceProjectID int64 `json:"source_project_id"` + TargetProjectID int64 `json:"target_project_id"` } // GetJobTokenInboundAllowListOptions represents the available @@ -124,24 +103,11 @@ type GetJobTokenInboundAllowListOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-inbound-allowlist func (j *JobTokenScopeService) GetProjectJobTokenInboundAllowList(pid any, opt *GetJobTokenInboundAllowListOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/allowlist`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Project - resp, err := j.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*Project](j.client, + withPath("projects/%s/job_token_scope/allowlist", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // JobTokenInboundAllowOptions represents the available @@ -150,7 +116,7 @@ func (j *JobTokenScopeService) GetProjectJobTokenInboundAllowList(pid any, opt * // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#add-a-project-to-a-cicd-job-token-inbound-allowlist type JobTokenInboundAllowOptions struct { - TargetProjectID *int `url:"target_project_id,omitempty" json:"target_project_id,omitempty"` + TargetProjectID *int64 `url:"target_project_id,omitempty" json:"target_project_id,omitempty"` } // AddProjectToJobScopeAllowList adds a new project to a project's job token @@ -159,24 +125,12 @@ type JobTokenInboundAllowOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#add-a-project-to-a-cicd-job-token-inbound-allowlist func (j *JobTokenScopeService) AddProjectToJobScopeAllowList(pid any, opt *JobTokenInboundAllowOptions, options ...RequestOptionFunc) (*JobTokenInboundAllowItem, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/allowlist`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - jt := new(JobTokenInboundAllowItem) - resp, err := j.client.Do(req, jt) - if err != nil { - return nil, resp, err - } - - return jt, resp, nil + return do[*JobTokenInboundAllowItem](j.client, + withMethod(http.MethodPost), + withPath("projects/%s/job_token_scope/allowlist", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveProjectFromJobScopeAllowList removes a project from a project's job @@ -184,27 +138,21 @@ func (j *JobTokenScopeService) AddProjectToJobScopeAllowList(pid any, opt *JobTo // // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#remove-a-project-from-a-cicd-job-token-inbound-allowlist -func (j *JobTokenScopeService) RemoveProjectFromJobScopeAllowList(pid any, targetProject int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/allowlist/%d`, PathEscape(project), targetProject) - - req, err := j.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return j.client.Do(req, nil) +func (j *JobTokenScopeService) RemoveProjectFromJobScopeAllowList(pid any, targetProject int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](j.client, + withMethod(http.MethodDelete), + withPath("projects/%s/job_token_scope/allowlist/%d", ProjectID{pid}, targetProject), + withRequestOpts(options...), + ) + return resp, err } // JobTokenAllowlistItem represents a single job token allowlist item. // // GitLab API docs: https://docs.gitlab.com/api/project_job_token_scopes/ type JobTokenAllowlistItem struct { - SourceProjectID int `json:"source_project_id"` - TargetGroupID int `json:"target_group_id"` + SourceProjectID int64 `json:"source_project_id"` + TargetGroupID int64 `json:"target_group_id"` } // GetJobTokenAllowlistGroupsOptions represents the available @@ -222,24 +170,11 @@ type GetJobTokenAllowlistGroupsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#get-a-projects-cicd-job-token-allowlist-of-groups func (j *JobTokenScopeService) GetJobTokenAllowlistGroups(pid any, opt *GetJobTokenAllowlistGroupsOptions, options ...RequestOptionFunc) ([]*Group, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Group - resp, err := j.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*Group](j.client, + withPath("projects/%s/job_token_scope/groups_allowlist", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddGroupToJobTokenAllowlistOptions represents the available @@ -248,7 +183,7 @@ func (j *JobTokenScopeService) GetJobTokenAllowlistGroups(pid any, opt *GetJobTo // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#add-a-group-to-a-cicd-job-token-allowlist type AddGroupToJobTokenAllowlistOptions struct { - TargetGroupID *int `url:"target_group_id,omitempty" json:"target_group_id,omitempty"` + TargetGroupID *int64 `url:"target_group_id,omitempty" json:"target_group_id,omitempty"` } // AddGroupToJobTokenAllowlist adds a new group to a project's job token @@ -257,24 +192,12 @@ type AddGroupToJobTokenAllowlistOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#add-a-group-to-a-cicd-job-token-allowlist func (j *JobTokenScopeService) AddGroupToJobTokenAllowlist(pid any, opt *AddGroupToJobTokenAllowlistOptions, options ...RequestOptionFunc) (*JobTokenAllowlistItem, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist`, PathEscape(project)) - - req, err := j.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - jt := new(JobTokenAllowlistItem) - resp, err := j.client.Do(req, jt) - if err != nil { - return nil, resp, err - } - - return jt, resp, nil + return do[*JobTokenAllowlistItem](j.client, + withMethod(http.MethodPost), + withPath("projects/%s/job_token_scope/groups_allowlist", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveGroupFromJobTokenAllowlist removes a group from a project's job @@ -282,17 +205,11 @@ func (j *JobTokenScopeService) AddGroupToJobTokenAllowlist(pid any, opt *AddGrou // // GitLab API docs: // https://docs.gitlab.com/api/project_job_token_scopes/#remove-a-group-from-a-cicd-job-token-allowlist -func (j *JobTokenScopeService) RemoveGroupFromJobTokenAllowlist(pid any, targetGroup int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf(`projects/%s/job_token_scope/groups_allowlist/%d`, PathEscape(project), targetGroup) - - req, err := j.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return j.client.Do(req, nil) +func (j *JobTokenScopeService) RemoveGroupFromJobTokenAllowlist(pid any, targetGroup int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](j.client, + withMethod(http.MethodDelete), + withPath("projects/%s/job_token_scope/groups_allowlist/%d", ProjectID{pid}, targetGroup), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/jobs.go b/vendor/gitlab.com/gitlab-org/api/client-go/jobs.go index 94aef9540..de69815d8 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/jobs.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/jobs.go @@ -18,29 +18,108 @@ package gitlab import ( "bytes" - "fmt" "net/http" "time" ) type ( JobsServiceInterface interface { + // ListProjectJobs gets a list of jobs in a project. + // + // The scope of jobs to show, one or array of: created, pending, running, + // failed, success, canceled, skipped; showing all jobs if none provided + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#list-project-jobs ListProjectJobs(pid any, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) - ListPipelineJobs(pid any, pipelineID int, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) - ListPipelineBridges(pid any, pipelineID int, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Bridge, *Response, error) + // ListPipelineJobs gets a list of jobs for specific pipeline in a + // project. If the pipeline ID is not found, it will respond with 404. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#list-pipeline-jobs + ListPipelineJobs(pid any, pipelineID int64, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) + // ListPipelineBridges gets a list of bridges for specific pipeline in a + // project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#list-pipeline-trigger-jobs + ListPipelineBridges(pid any, pipelineID int64, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Bridge, *Response, error) + // GetJobTokensJob retrieves the job that generated a job token. + // + // GitLab API docs: https://docs.gitlab.com/api/jobs/#get-job-tokens-job GetJobTokensJob(opts *GetJobTokensJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) - GetJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) - GetJobArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // GetJob gets a single job of a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#get-a-single-job + GetJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) + // GetJobArtifacts gets jobs artifacts of a project + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#get-job-artifacts + GetJobArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // DownloadArtifactsFile downloads the artifacts file from the given + // reference name and job provided the job finished successfully. + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#download-the-artifacts-archive DownloadArtifactsFile(pid any, refName string, opt *DownloadArtifactsFileOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) - DownloadSingleArtifactsFile(pid any, jobID int, artifactPath string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // DownloadSingleArtifactsFile downloads a file from the artifacts from the + // given reference name and job provided the job finished successfully. + // Only a single file is going to be extracted from the archive and streamed + // to a client. + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#download-a-single-artifact-file-by-job-id + DownloadSingleArtifactsFile(pid any, jobID int64, artifactPath string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // DownloadSingleArtifactsFileByTagOrBranch downloads a single file from + // a job's artifacts in the latest successful pipeline using the reference name. + // The file is extracted from the archive and streamed to the client. + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#download-a-single-artifact-file-from-specific-tag-or-branch DownloadSingleArtifactsFileByTagOrBranch(pid any, refName string, artifactPath string, opt *DownloadArtifactsFileOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) - GetTraceFile(pid any, jobID int, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) - CancelJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) - RetryJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) - EraseJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) - KeepArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) - PlayJob(pid any, jobID int, opt *PlayJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) - DeleteArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*Response, error) + // GetTraceFile gets a trace of a specific job of a project + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#get-a-log-file + GetTraceFile(pid any, jobID int64, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // CancelJob cancels a single job of a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#cancel-a-job + CancelJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) + // RetryJob retries a single job of a project + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#retry-a-job + RetryJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) + // EraseJob erases a single job of a project, removes a job + // artifacts and a job trace. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#erase-a-job + EraseJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) + // KeepArtifacts prevents artifacts from being deleted when + // expiration is set. + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#keep-artifacts + KeepArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) + // PlayJob triggers a manual action to start a job. + // + // GitLab API docs: + // https://docs.gitlab.com/api/jobs/#run-a-job + PlayJob(pid any, jobID int64, opt *PlayJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) + // DeleteArtifacts deletes artifacts of a job + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#delete-job-artifacts + DeleteArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*Response, error) + // DeleteProjectArtifacts deletes artifacts eligible for deletion in a project + // + // GitLab API docs: + // https://docs.gitlab.com/api/job_artifacts/#delete-job-artifacts DeleteProjectArtifacts(pid any, options ...RequestOptionFunc) (*Response, error) } @@ -59,51 +138,71 @@ var _ JobsServiceInterface = (*JobsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/jobs/ type Job struct { - Commit *Commit `json:"commit"` - Coverage float64 `json:"coverage"` - AllowFailure bool `json:"allow_failure"` - CreatedAt *time.Time `json:"created_at"` - StartedAt *time.Time `json:"started_at"` - FinishedAt *time.Time `json:"finished_at"` - ErasedAt *time.Time `json:"erased_at"` - Duration float64 `json:"duration"` - QueuedDuration float64 `json:"queued_duration"` - ArtifactsExpireAt *time.Time `json:"artifacts_expire_at"` - TagList []string `json:"tag_list"` - ID int `json:"id"` - Name string `json:"name"` - Pipeline struct { - ID int `json:"id"` - ProjectID int `json:"project_id"` - Ref string `json:"ref"` - Sha string `json:"sha"` - Status string `json:"status"` - } `json:"pipeline"` + Commit *Commit `json:"commit"` + Coverage float64 `json:"coverage"` + AllowFailure bool `json:"allow_failure"` + CreatedAt *time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at"` + FinishedAt *time.Time `json:"finished_at"` + ErasedAt *time.Time `json:"erased_at"` + Duration float64 `json:"duration"` + QueuedDuration float64 `json:"queued_duration"` + ArtifactsExpireAt *time.Time `json:"artifacts_expire_at"` + TagList []string `json:"tag_list"` + ID int64 `json:"id"` + Name string `json:"name"` + Pipeline JobPipeline `json:"pipeline"` + Ref string `json:"ref"` + Artifacts []JobArtifact `json:"artifacts"` + ArtifactsFile JobArtifactsFile `json:"artifacts_file"` + Runner JobRunner `json:"runner"` + Stage string `json:"stage"` + Status string `json:"status"` + FailureReason string `json:"failure_reason"` + Tag bool `json:"tag"` + WebURL string `json:"web_url"` + Project *Project `json:"project"` + User *User `json:"user"` +} + +// JobPipeline represents a ci build pipeline. +// +// GitLab API docs: https://docs.gitlab.com/api/jobs/ +type JobPipeline struct { + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` Ref string `json:"ref"` - Artifacts []struct { - FileType string `json:"file_type"` - Filename string `json:"filename"` - Size int `json:"size"` - FileFormat string `json:"file_format"` - } `json:"artifacts"` - ArtifactsFile struct { - Filename string `json:"filename"` - Size int `json:"size"` - } `json:"artifacts_file"` - Runner struct { - ID int `json:"id"` - Description string `json:"description"` - Active bool `json:"active"` - IsShared bool `json:"is_shared"` - Name string `json:"name"` - } `json:"runner"` - Stage string `json:"stage"` - Status string `json:"status"` - FailureReason string `json:"failure_reason"` - Tag bool `json:"tag"` - WebURL string `json:"web_url"` - Project *Project `json:"project"` - User *User `json:"user"` + Sha string `json:"sha"` + Status string `json:"status"` +} + +// JobArtifact represents a ci build artifact. +// +// GitLab API docs: https://docs.gitlab.com/api/jobs/ +type JobArtifact struct { + FileType string `json:"file_type"` + Filename string `json:"filename"` + Size int64 `json:"size"` + FileFormat string `json:"file_format"` +} + +// JobArtifactsFile represents a ci build artifacts file. +// +// GitLab API docs: https://docs.gitlab.com/api/jobs/ +type JobArtifactsFile struct { + Filename string `json:"filename"` + Size int64 `json:"size"` +} + +// JobRunner represents a ci build runner. +// +// GitLab API docs: https://docs.gitlab.com/api/jobs/ +type JobRunner struct { + ID int64 `json:"id"` + Description string `json:"description"` + Active bool `json:"active"` + IsShared bool `json:"is_shared"` + Name string `json:"name"` } // Bridge represents a pipeline bridge. @@ -119,7 +218,7 @@ type Bridge struct { ErasedAt *time.Time `json:"erased_at"` Duration float64 `json:"duration"` QueuedDuration float64 `json:"queued_duration"` - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Pipeline PipelineInfo `json:"pipeline"` Ref string `json:"ref"` @@ -142,84 +241,31 @@ type ListJobsOptions struct { IncludeRetried *bool `url:"include_retried,omitempty" json:"include_retried,omitempty"` } -// ListProjectJobs gets a list of jobs in a project. -// -// The scope of jobs to show, one or array of: created, pending, running, -// failed, success, canceled, skipped; showing all jobs if none provided -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#list-project-jobs func (s *JobsService) ListProjectJobs(pid any, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var jobs []*Job - resp, err := s.client.Do(req, &jobs) - if err != nil { - return nil, resp, err - } - - return jobs, resp, nil + return do[[]*Job](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/jobs", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// ListPipelineJobs gets a list of jobs for specific pipeline in a -// project. If the pipeline ID is not found, it will respond with 404. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#list-pipeline-jobs -func (s *JobsService) ListPipelineJobs(pid any, pipelineID int, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/jobs", PathEscape(project), pipelineID) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var jobs []*Job - resp, err := s.client.Do(req, &jobs) - if err != nil { - return nil, resp, err - } - - return jobs, resp, nil +func (s *JobsService) ListPipelineJobs(pid any, pipelineID int64, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) { + return do[[]*Job](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/pipelines/%d/jobs", ProjectID{pid}, pipelineID), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// ListPipelineBridges gets a list of bridges for specific pipeline in a -// project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#list-pipeline-trigger-jobs -func (s *JobsService) ListPipelineBridges(pid any, pipelineID int, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Bridge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/bridges", PathEscape(project), pipelineID) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var bridges []*Bridge - resp, err := s.client.Do(req, &bridges) - if err != nil { - return nil, resp, err - } - - return bridges, resp, nil +func (s *JobsService) ListPipelineBridges(pid any, pipelineID int64, opts *ListJobsOptions, options ...RequestOptionFunc) ([]*Bridge, *Response, error) { + return do[[]*Bridge](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/pipelines/%d/bridges", ProjectID{pid}, pipelineID), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // GetJobTokensJobOptions represents the available GetJobTokensJob() options. @@ -229,72 +275,31 @@ type GetJobTokensJobOptions struct { JobToken *string `url:"job_token,omitempty" json:"job_token,omitempty"` } -// GetJobTokensJob retrieves the job that generated a job token. -// -// GitLab API docs: https://docs.gitlab.com/api/jobs/#get-job-tokens-job func (s *JobsService) GetJobTokensJob(opts *GetJobTokensJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "job", opts, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil + return do[*Job](s.client, + withMethod(http.MethodGet), + withPath("job"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// GetJob gets a single job of a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#get-a-single-job -func (s *JobsService) GetJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) GetJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/jobs/%d", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) } -// GetJobArtifacts get jobs artifacts of a project -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#get-job-artifacts -func (s *JobsService) GetJobArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/artifacts", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - artifactsBuf := new(bytes.Buffer) - resp, err := s.client.Do(req, artifactsBuf) - if err != nil { - return nil, resp, err - } +func (s *JobsService) GetJobArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/jobs/%d/artifacts", ProjectID{pid}, jobID), + withRequestOpts(options...), + ) - return bytes.NewReader(artifactsBuf.Bytes()), resp, err + return bytes.NewReader(b.Bytes()), resp, err } // DownloadArtifactsFileOptions represents the available DownloadArtifactsFile() @@ -306,224 +311,78 @@ type DownloadArtifactsFileOptions struct { Job *string `url:"job" json:"job"` } -// DownloadArtifactsFile download the artifacts file from the given -// reference name and job provided the job finished successfully. -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#download-the-artifacts-archive func (s *JobsService) DownloadArtifactsFile(pid any, refName string, opt *DownloadArtifactsFileOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/artifacts/%s/download", PathEscape(project), refName) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - artifactsBuf := new(bytes.Buffer) - resp, err := s.client.Do(req, artifactsBuf) - if err != nil { - return nil, resp, err - } + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/jobs/artifacts/%s/download", ProjectID{pid}, NoEscape{refName}), + withAPIOpts(opt), + withRequestOpts(options...), + ) - return bytes.NewReader(artifactsBuf.Bytes()), resp, err + return bytes.NewReader(b.Bytes()), resp, err } -// DownloadSingleArtifactsFile download a file from the artifacts from the -// given reference name and job provided the job finished successfully. -// Only a single file is going to be extracted from the archive and streamed -// to a client. -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#download-a-single-artifact-file-by-job-id -func (s *JobsService) DownloadSingleArtifactsFile(pid any, jobID int, artifactPath string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - - u := fmt.Sprintf( - "projects/%s/jobs/%d/artifacts/%s", - PathEscape(project), - jobID, - artifactPath, +func (s *JobsService) DownloadSingleArtifactsFile(pid any, jobID int64, artifactPath string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/jobs/%d/artifacts/%s", ProjectID{pid}, jobID, NoEscape{artifactPath}), + withRequestOpts(options...), ) - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - artifactBuf := new(bytes.Buffer) - resp, err := s.client.Do(req, artifactBuf) - if err != nil { - return nil, resp, err - } - - return bytes.NewReader(artifactBuf.Bytes()), resp, err + return bytes.NewReader(b.Bytes()), resp, err } -// DownloadSingleArtifactsFileByTagOrBranch downloads a single file from -// a jobโ€™s artifacts in the latest successful pipeline using the reference name. -// The file is extracted from the archive and streamed to the client. -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#download-a-single-artifact-file-from-specific-tag-or-branch func (s *JobsService) DownloadSingleArtifactsFileByTagOrBranch(pid any, refName string, artifactPath string, opt *DownloadArtifactsFileOptions, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - - u := fmt.Sprintf( - "projects/%s/jobs/artifacts/%s/raw/%s", - PathEscape(project), - PathEscape(refName), - artifactPath, + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/jobs/artifacts/%s/raw/%s", ProjectID{pid}, refName, NoEscape{artifactPath}), + withAPIOpts(opt), + withRequestOpts(options...), ) - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - artifactBuf := new(bytes.Buffer) - resp, err := s.client.Do(req, artifactBuf) - if err != nil { - return nil, resp, err - } - - return bytes.NewReader(artifactBuf.Bytes()), resp, err + return bytes.NewReader(b.Bytes()), resp, err } -// GetTraceFile gets a trace of a specific job of a project -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#get-a-log-file -func (s *JobsService) GetTraceFile(pid any, jobID int, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/trace", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - traceBuf := new(bytes.Buffer) - resp, err := s.client.Do(req, traceBuf) - if err != nil { - return nil, resp, err - } +func (s *JobsService) GetTraceFile(pid any, jobID int64, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/jobs/%d/trace", ProjectID{pid}, jobID), + withRequestOpts(options...), + ) - return bytes.NewReader(traceBuf.Bytes()), resp, err + return bytes.NewReader(b.Bytes()), resp, err } -// CancelJob cancels a single job of a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#cancel-a-job -func (s *JobsService) CancelJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/cancel", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) CancelJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/jobs/%d/cancel", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) } -// RetryJob retries a single job of a project -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#retry-a-job -func (s *JobsService) RetryJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/retry", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) RetryJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/jobs/%d/retry", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) } -// EraseJob erases a single job of a project, removes a job -// artifacts and a job trace. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#erase-a-job -func (s *JobsService) EraseJob(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/erase", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) EraseJob(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/jobs/%d/erase", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) } -// KeepArtifacts prevents artifacts from being deleted when -// expiration is set. -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#keep-artifacts -func (s *JobsService) KeepArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/artifacts/keep", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) KeepArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/jobs/%d/artifacts/keep", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // PlayJobOptions represents the available PlayJob() options. @@ -544,65 +403,31 @@ type JobVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// PlayJob triggers a manual action to start a job. -// -// GitLab API docs: -// https://docs.gitlab.com/api/jobs/#run-a-job -func (s *JobsService) PlayJob(pid any, jobID int, opt *PlayJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/play", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - job := new(Job) - resp, err := s.client.Do(req, job) - if err != nil { - return nil, resp, err - } - - return job, resp, nil +func (s *JobsService) PlayJob(pid any, jobID int64, opt *PlayJobOptions, options ...RequestOptionFunc) (*Job, *Response, error) { + return do[*Job](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/jobs/%d/play", ProjectID{pid}, jobID), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteArtifacts delete artifacts of a job -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#delete-job-artifacts -func (s *JobsService) DeleteArtifacts(pid any, jobID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/jobs/%d/artifacts", PathEscape(project), jobID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *JobsService) DeleteArtifacts(pid any, jobID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/jobs/%d/artifacts", ProjectID{pid}, jobID), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } -// DeleteProjectArtifacts delete artifacts eligible for deletion in a project -// -// GitLab API docs: -// https://docs.gitlab.com/api/job_artifacts/#delete-job-artifacts func (s *JobsService) DeleteProjectArtifacts(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/artifacts", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/artifacts", ProjectID{pid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/keys.go b/vendor/gitlab.com/gitlab-org/api/client-go/keys.go index 3b2187c65..2fde4860b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/keys.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/keys.go @@ -16,15 +16,11 @@ package gitlab -import ( - "fmt" - "net/http" - "time" -) +import "time" type ( KeysServiceInterface interface { - GetKeyWithUser(key int, options ...RequestOptionFunc) (*Key, *Response, error) + GetKeyWithUser(key int64, options ...RequestOptionFunc) (*Key, *Response, error) GetKeyByFingerprint(opt *GetKeyByFingerprintOptions, options ...RequestOptionFunc) (*Key, *Response, error) } @@ -45,7 +41,7 @@ var _ KeysServiceInterface = (*KeysService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/keys/ type Key struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Key string `json:"key"` CreatedAt *time.Time `json:"created_at"` @@ -57,21 +53,11 @@ type Key struct { // // GitLab API docs: // https://docs.gitlab.com/api/keys/#get-ssh-key-with-user-by-id-of-an-ssh-key -func (s *KeysService) GetKeyWithUser(key int, options ...RequestOptionFunc) (*Key, *Response, error) { - u := fmt.Sprintf("keys/%d", key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(Key) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *KeysService) GetKeyWithUser(key int64, options ...RequestOptionFunc) (*Key, *Response, error) { + return do[*Key](s.client, + withPath("keys/%d", key), + withRequestOpts(options...), + ) } // GetKeyByFingerprintOptions represents the available GetKeyByFingerprint() @@ -91,16 +77,9 @@ type GetKeyByFingerprintOptions struct { // https://docs.gitlab.com/api/keys/#get-user-by-fingerprint-of-ssh-key // https://docs.gitlab.com/api/keys/#get-user-by-deploy-key-fingerprint func (s *KeysService) GetKeyByFingerprint(opt *GetKeyByFingerprintOptions, options ...RequestOptionFunc) (*Key, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "keys", opt, options) - if err != nil { - return nil, nil, err - } - - k := new(Key) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[*Key](s.client, + withPath("keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/labels.go b/vendor/gitlab.com/gitlab-org/api/client-go/labels.go index d7eb1e624..1c6a379d0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/labels.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/labels.go @@ -18,7 +18,6 @@ package gitlab import ( "encoding/json" - "fmt" "net/http" ) @@ -49,16 +48,16 @@ var _ LabelsServiceInterface = (*LabelsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/labels/ type Label struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Color string `json:"color"` TextColor string `json:"text_color"` Description string `json:"description"` - OpenIssuesCount int `json:"open_issues_count"` - ClosedIssuesCount int `json:"closed_issues_count"` - OpenMergeRequestsCount int `json:"open_merge_requests_count"` + OpenIssuesCount int64 `json:"open_issues_count"` + ClosedIssuesCount int64 `json:"closed_issues_count"` + OpenMergeRequestsCount int64 `json:"open_merge_requests_count"` Subscribed bool `json:"subscribed"` - Priority int `json:"priority"` + Priority int64 `json:"priority"` IsProjectLabel bool `json:"is_project_label"` } @@ -94,68 +93,39 @@ type ListLabelsOptions struct { WithCounts *bool `url:"with_counts,omitempty" json:"with_counts,omitempty"` IncludeAncestorGroups *bool `url:"include_ancestor_groups,omitempty" json:"include_ancestor_groups,omitempty"` Search *string `url:"search,omitempty" json:"search,omitempty"` + Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` } // ListLabels gets all labels for given project. // // GitLab API docs: https://docs.gitlab.com/api/labels/#list-labels func (s *LabelsService) ListLabels(pid any, opt *ListLabelsOptions, options ...RequestOptionFunc) ([]*Label, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/labels", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var l []*Label - resp, err := s.client.Do(req, &l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[[]*Label](s.client, + withPath("projects/%s/labels", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetLabel get a single label for a given project. // // GitLab API docs: https://docs.gitlab.com/api/labels/#get-a-single-project-label func (s *LabelsService) GetLabel(pid any, lid any, options ...RequestOptionFunc) (*Label, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/labels/%s", PathEscape(project), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var l *Label - resp, err := s.client.Do(req, &l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*Label](s.client, + withPath("projects/%s/labels/%s", ProjectID{pid}, LabelID{lid}), + withRequestOpts(options...), + ) } // CreateLabelOptions represents the available CreateLabel() options. // -// GitLab API docs: https://docs.gitlab.com/api/labels/#create-a-new-label +// GitLab API docs: https://docs.gitlab.com/api/labels/#create-a-project-label type CreateLabelOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` Color *string `url:"color,omitempty" json:"color,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` - Priority *int `url:"priority,omitempty" json:"priority,omitempty"` + Priority *int64 `url:"priority,omitempty" json:"priority,omitempty"` + Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` } // CreateLabel creates a new label for given repository with given name and @@ -163,24 +133,12 @@ type CreateLabelOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/labels/#create-a-new-label func (s *LabelsService) CreateLabel(pid any, opt *CreateLabelOptions, options ...RequestOptionFunc) (*Label, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/labels", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - l := new(Label) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*Label](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/labels", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteLabelOptions represents the available DeleteLabel() options. @@ -194,37 +152,33 @@ type DeleteLabelOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/labels/#delete-a-label func (s *LabelsService) DeleteLabel(pid any, lid any, opt *DeleteLabelOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/labels", PathEscape(project)) + reqOpts := make([]doOption, 0, 4) + reqOpts = append(reqOpts, + withMethod(http.MethodDelete), + withAPIOpts(opt), + withRequestOpts(options...), + ) if lid != nil { - label, err := parseID(lid) - if err != nil { - return nil, err - } - u = fmt.Sprintf("projects/%s/labels/%s", PathEscape(project), PathEscape(label)) - } - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err + reqOpts = append(reqOpts, withPath("projects/%s/labels/%s", ProjectID{pid}, LabelID{lid})) + } else { + reqOpts = append(reqOpts, withPath("projects/%s/labels", ProjectID{pid})) } - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, reqOpts...) + return resp, err } // UpdateLabelOptions represents the available UpdateLabel() options. // -// GitLab API docs: https://docs.gitlab.com/api/labels/#edit-an-existing-label +// GitLab API docs: https://docs.gitlab.com/api/labels/#update-a-project-label type UpdateLabelOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"` Color *string `url:"color,omitempty" json:"color,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` - Priority *int `url:"priority,omitempty" json:"priority,omitempty"` + Priority *int64 `url:"priority,omitempty" json:"priority,omitempty"` + Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` } // UpdateLabel updates an existing label with new name or now color. At least @@ -232,32 +186,20 @@ type UpdateLabelOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/labels/#edit-an-existing-label func (s *LabelsService) UpdateLabel(pid any, lid any, opt *UpdateLabelOptions, options ...RequestOptionFunc) (*Label, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/labels", PathEscape(project)) + reqOpts := make([]doOption, 0, 4) + reqOpts = append(reqOpts, + withMethod(http.MethodPut), + withAPIOpts(opt), + withRequestOpts(options...), + ) if lid != nil { - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u = fmt.Sprintf("projects/%s/labels/%s", PathEscape(project), PathEscape(label)) - } - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - l := new(Label) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err + reqOpts = append(reqOpts, withPath("projects/%s/labels/%s", ProjectID{pid}, LabelID{lid})) + } else { + reqOpts = append(reqOpts, withPath("projects/%s/labels", ProjectID{pid})) } - return l, resp, nil + return do[*Label](s.client, reqOpts...) } // SubscribeToLabel subscribes the authenticated user to a label to receive @@ -267,28 +209,11 @@ func (s *LabelsService) UpdateLabel(pid any, lid any, opt *UpdateLabelOptions, o // GitLab API docs: // https://docs.gitlab.com/api/labels/#subscribe-to-a-label func (s *LabelsService) SubscribeToLabel(pid any, lid any, options ...RequestOptionFunc) (*Label, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/labels/%s/subscribe", PathEscape(project), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - l := new(Label) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*Label](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/labels/%s/subscribe", ProjectID{pid}, LabelID{lid}), + withRequestOpts(options...), + ) } // UnsubscribeFromLabel unsubscribes the authenticated user from a label to not @@ -298,22 +223,12 @@ func (s *LabelsService) SubscribeToLabel(pid any, lid any, options ...RequestOpt // GitLab API docs: // https://docs.gitlab.com/api/labels/#unsubscribe-from-a-label func (s *LabelsService) UnsubscribeFromLabel(pid any, lid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/labels/%s/unsubscribe", PathEscape(project), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/labels/%s/unsubscribe", ProjectID{pid}, LabelID{lid}), + withRequestOpts(options...), + ) + return resp, err } // PromoteLabel Promotes a project label to a group label. @@ -321,20 +236,10 @@ func (s *LabelsService) UnsubscribeFromLabel(pid any, lid any, options ...Reques // GitLab API docs: // https://docs.gitlab.com/api/labels/#promote-a-project-label-to-a-group-label func (s *LabelsService) PromoteLabel(pid any, lid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - label, err := parseID(lid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/labels/%s/promote", PathEscape(project), PathEscape(label)) - - req, err := s.client.NewRequest(http.MethodPut, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/labels/%s/promote", ProjectID{pid}, LabelID{lid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/license.go b/vendor/gitlab.com/gitlab-org/api/client-go/license.go index 9e9d2a068..762454aa2 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/license.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/license.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -26,7 +25,7 @@ type ( LicenseServiceInterface interface { GetLicense(options ...RequestOptionFunc) (*License, *Response, error) AddLicense(opt *AddLicenseOptions, options ...RequestOptionFunc) (*License, *Response, error) - DeleteLicense(licenseID int, options ...RequestOptionFunc) (*Response, error) + DeleteLicense(licenseID int64, options ...RequestOptionFunc) (*Response, error) } // LicenseService handles communication with the license @@ -46,54 +45,66 @@ var _ LicenseServiceInterface = (*LicenseService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/license/ type License struct { - ID int `json:"id"` - Plan string `json:"plan"` - CreatedAt *time.Time `json:"created_at"` - StartsAt *ISOTime `json:"starts_at"` - ExpiresAt *ISOTime `json:"expires_at"` - HistoricalMax int `json:"historical_max"` - MaximumUserCount int `json:"maximum_user_count"` - Expired bool `json:"expired"` - Overage int `json:"overage"` - UserLimit int `json:"user_limit"` - ActiveUsers int `json:"active_users"` - Licensee struct { - Name string `json:"Name"` - Company string `json:"Company"` - Email string `json:"Email"` - } `json:"licensee"` + ID int64 `json:"id"` + Plan string `json:"plan"` + CreatedAt *time.Time `json:"created_at"` + StartsAt *ISOTime `json:"starts_at"` + ExpiresAt *ISOTime `json:"expires_at"` + HistoricalMax int64 `json:"historical_max"` + MaximumUserCount int64 `json:"maximum_user_count"` + Expired bool `json:"expired"` + Overage int64 `json:"overage"` + UserLimit int64 `json:"user_limit"` + ActiveUsers int64 `json:"active_users"` + Licensee LicenseLicensee `json:"licensee"` // Add on codes that may occur in legacy licenses that don't have a plan yet. // https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/license.rb - AddOns struct { - GitLabAuditorUser int `json:"GitLab_Auditor_User"` - GitLabDeployBoard int `json:"GitLab_DeployBoard"` - GitLabFileLocks int `json:"GitLab_FileLocks"` - GitLabGeo int `json:"GitLab_Geo"` - GitLabServiceDesk int `json:"GitLab_ServiceDesk"` - } `json:"add_ons"` + AddOns LicenseAddOns `json:"add_ons"` } func (l License) String() string { return Stringify(l) } +// LicenseLicensee represents a GitLab license licensee. +// +// GitLab API docs: +// https://docs.gitlab.com/api/license/ +type LicenseLicensee struct { + Name string `json:"Name"` + Company string `json:"Company"` + Email string `json:"Email"` +} + +func (l LicenseLicensee) String() string { + return Stringify(l) +} + +// LicenseAddOns represents a GitLab license add ons. +// +// GitLab API docs: +// https://docs.gitlab.com/api/license/ +type LicenseAddOns struct { + GitLabAuditorUser int64 `json:"GitLab_Auditor_User"` + GitLabDeployBoard int64 `json:"GitLab_DeployBoard"` + GitLabFileLocks int64 `json:"GitLab_FileLocks"` + GitLabGeo int64 `json:"GitLab_Geo"` + GitLabServiceDesk int64 `json:"GitLab_ServiceDesk"` +} + +func (a LicenseAddOns) String() string { + return Stringify(a) +} + // GetLicense retrieves information about the current license. // // GitLab API docs: // https://docs.gitlab.com/api/license/#retrieve-information-about-the-current-license func (s *LicenseService) GetLicense(options ...RequestOptionFunc) (*License, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "license", nil, options) - if err != nil { - return nil, nil, err - } - - l := new(License) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*License](s.client, + withPath("license"), + withRequestOpts(options...), + ) } // AddLicenseOptions represents the available AddLicense() options. @@ -108,31 +119,23 @@ type AddLicenseOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/license/#add-a-new-license func (s *LicenseService) AddLicense(opt *AddLicenseOptions, options ...RequestOptionFunc) (*License, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "license", opt, options) - if err != nil { - return nil, nil, err - } - - l := new(License) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*License](s.client, + withMethod(http.MethodPost), + withPath("license"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteLicense deletes an existing license. // // GitLab API docs: // https://docs.gitlab.com/api/license/#delete-a-license -func (s *LicenseService) DeleteLicense(licenseID int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("license/%d", licenseID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *LicenseService) DeleteLicense(licenseID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("license/%d", licenseID), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/license_templates.go b/vendor/gitlab.com/gitlab-org/api/client-go/license_templates.go index 8808f56b5..73939b9b1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/license_templates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/license_templates.go @@ -16,11 +16,6 @@ package gitlab -import ( - "fmt" - "net/http" -) - // LicenseTemplate represents a license template. // // GitLab API docs: @@ -71,18 +66,11 @@ type ListLicenseTemplatesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/templates/licenses/#list-license-templates func (s *LicenseTemplatesService) ListLicenseTemplates(opt *ListLicenseTemplatesOptions, options ...RequestOptionFunc) ([]*LicenseTemplate, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "templates/licenses", opt, options) - if err != nil { - return nil, nil, err - } - - var lts []*LicenseTemplate - resp, err := s.client.Do(req, <s) - if err != nil { - return nil, resp, err - } - - return lts, resp, nil + return do[[]*LicenseTemplate](s.client, + withPath("templates/licenses"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetLicenseTemplateOptions represents the available @@ -101,18 +89,9 @@ type GetLicenseTemplateOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/templates/licenses/#single-license-template func (s *LicenseTemplatesService) GetLicenseTemplate(template string, opt *GetLicenseTemplateOptions, options ...RequestOptionFunc) (*LicenseTemplate, *Response, error) { - u := fmt.Sprintf("templates/licenses/%s", template) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - lt := new(LicenseTemplate) - resp, err := s.client.Do(req, lt) - if err != nil { - return nil, resp, err - } - - return lt, resp, nil + return do[*LicenseTemplate](s.client, + withPath("templates/licenses/%s", NoEscape{template}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/markdown.go b/vendor/gitlab.com/gitlab-org/api/client-go/markdown.go index 8e2e30f65..cf92f1c3a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/markdown.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/markdown.go @@ -20,14 +20,14 @@ var _ MarkdownServiceInterface = (*MarkdownService)(nil) // Markdown represents a markdown document. // -// Gitlab API docs: https://docs.gitlab.com/api/markdown/ +// GitLab API docs: https://docs.gitlab.com/api/markdown/ type Markdown struct { HTML string `json:"html"` } // RenderOptions represents the available Render() options. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/markdown/#render-an-arbitrary-markdown-document type RenderOptions struct { Text *string `url:"text,omitempty" json:"text,omitempty"` @@ -37,19 +37,13 @@ type RenderOptions struct { // Render an arbitrary markdown document. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/markdown/#render-an-arbitrary-markdown-document func (s *MarkdownService) Render(opt *RenderOptions, options ...RequestOptionFunc) (*Markdown, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "markdown", opt, options) - if err != nil { - return nil, nil, err - } - - md := new(Markdown) - response, err := s.client.Do(req, md) - if err != nil { - return nil, response, err - } - - return md, response, nil + return do[*Markdown](s.client, + withMethod(http.MethodPost), + withPath("markdown"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/markdown_uploads.go b/vendor/gitlab.com/gitlab-org/api/client-go/markdown_uploads.go index 9acfe2377..1f45039d2 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/markdown_uploads.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/markdown_uploads.go @@ -18,19 +18,18 @@ package gitlab import ( "bytes" - "fmt" "net/http" "time" ) // MarkdownUpload represents a single markdown upload. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/project_markdown_uploads/ // https://docs.gitlab.com/api/group_markdown_uploads/ type MarkdownUpload struct { - ID int `json:"id"` - Size int `json:"size"` + ID int64 `json:"id"` + Size int64 `json:"size"` Filename string `json:"filename"` CreatedAt *time.Time `json:"created_at"` UploadedBy *User `json:"uploaded_by"` @@ -47,10 +46,10 @@ func (m MarkdownUpload) String() string { // MarkdownUploadedFile represents a single markdown uploaded file. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/project_markdown_uploads/ type MarkdownUploadedFile struct { - ID int `json:"id"` + ID int64 `json:"id"` Alt string `json:"alt"` URL string `json:"url"` FullPath string `json:"full_path"` @@ -70,99 +69,55 @@ type ListMarkdownUploadsOptions struct { } // listMarkdownUploads gets all markdown uploads for a resource -func listMarkdownUploads[T any](client *Client, resourceType ResourceType, id any, opt *ListMarkdownUploadsOptions, options []RequestOptionFunc) ([]*T, *Response, error) { - resourceID, err := parseID(id) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("%s/%s/uploads", resourceType, PathEscape(resourceID)) - - req, err := client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var uploads []*T - resp, err := client.Do(req, &uploads) - if err != nil { - return nil, resp, err - } - - return uploads, resp, err +func listMarkdownUploads[T any](client *Client, resourceType ResourceType, id Pather, opt *ListMarkdownUploadsOptions, options []RequestOptionFunc) ([]*T, *Response, error) { + return do[[]*T](client, + withMethod(http.MethodGet), + withPath("%s/%s/uploads", resourceType, id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // downloadMarkdownUploadByID downloads a specific upload by ID -func downloadMarkdownUploadByID(client *Client, resourceType ResourceType, id any, uploadID int, options []RequestOptionFunc) (*bytes.Buffer, *Response, error) { - resourceID, err := parseID(id) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("%s/%s/uploads/%d", resourceType, PathEscape(resourceID), uploadID) - - req, err := client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var file bytes.Buffer - resp, err := client.Do(req, &file) - if err != nil { - return nil, resp, err - } +func downloadMarkdownUploadByID(client *Client, resourceType ResourceType, id Pather, uploadID int64, options []RequestOptionFunc) (*bytes.Buffer, *Response, error) { + file, resp, err := do[bytes.Buffer](client, + withMethod(http.MethodGet), + withPath("%s/%s/uploads/%d", resourceType, id, uploadID), + withRequestOpts(options...), + ) return &file, resp, err } // downloadMarkdownUploadBySecretAndFilename downloads a specific upload by secret and filename -func downloadMarkdownUploadBySecretAndFilename(client *Client, resourceType ResourceType, id any, secret string, filename string, options []RequestOptionFunc) (*bytes.Buffer, *Response, error) { - resourceID, err := parseID(id) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("%s/%s/uploads/%s/%s", resourceType, PathEscape(resourceID), PathEscape(secret), PathEscape(filename)) - - req, err := client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var file bytes.Buffer - resp, err := client.Do(req, &file) - if err != nil { - return nil, resp, err - } +func downloadMarkdownUploadBySecretAndFilename(client *Client, resourceType ResourceType, id Pather, secret string, filename string, options []RequestOptionFunc) (*bytes.Buffer, *Response, error) { + file, resp, err := do[bytes.Buffer](client, + withMethod(http.MethodGet), + withPath("%s/%s/uploads/%s/%s", resourceType, id, secret, filename), + withRequestOpts(options...), + ) return &file, resp, err } // deleteMarkdownUploadByID deletes an upload by ID -func deleteMarkdownUploadByID(client *Client, resourceType ResourceType, id any, uploadID int, options []RequestOptionFunc) (*Response, error) { - resourceID, err := parseID(id) - if err != nil { - return nil, err - } - u := fmt.Sprintf("%s/%s/uploads/%d", resourceType, PathEscape(resourceID), uploadID) - - req, err := client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return client.Do(req, nil) +func deleteMarkdownUploadByID(client *Client, resourceType ResourceType, id Pather, uploadID int64, options []RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](client, + withMethod(http.MethodDelete), + withPath("%s/%s/uploads/%d", resourceType, id, uploadID), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // deleteMarkdownUploadBySecretAndFilename deletes an upload by secret and filename -func deleteMarkdownUploadBySecretAndFilename(client *Client, resourceType ResourceType, id any, secret string, filename string, options []RequestOptionFunc) (*Response, error) { - resourceID, err := parseID(id) - if err != nil { - return nil, err - } - u := fmt.Sprintf("%s/%s/uploads/%s/%s", resourceType, PathEscape(resourceID), PathEscape(secret), PathEscape(filename)) - - req, err := client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return client.Do(req, nil) +func deleteMarkdownUploadBySecretAndFilename(client *Client, resourceType ResourceType, id Pather, secret string, filename string, options []RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](client, + withMethod(http.MethodDelete), + withPath("%s/%s/uploads/%s/%s", resourceType, id, secret, filename), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/member_roles.go b/vendor/gitlab.com/gitlab-org/api/client-go/member_roles.go index e9fede214..094e3dab9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/member_roles.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/member_roles.go @@ -1,7 +1,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -9,10 +8,10 @@ type ( MemberRolesServiceInterface interface { ListInstanceMemberRoles(options ...RequestOptionFunc) ([]*MemberRole, *Response, error) CreateInstanceMemberRole(opt *CreateMemberRoleOptions, options ...RequestOptionFunc) (*MemberRole, *Response, error) - DeleteInstanceMemberRole(memberRoleID int, options ...RequestOptionFunc) (*Response, error) + DeleteInstanceMemberRole(memberRoleID int64, options ...RequestOptionFunc) (*Response, error) ListMemberRoles(gid any, options ...RequestOptionFunc) ([]*MemberRole, *Response, error) CreateMemberRole(gid any, opt *CreateMemberRoleOptions, options ...RequestOptionFunc) (*MemberRole, *Response, error) - DeleteMemberRole(gid any, memberRole int, options ...RequestOptionFunc) (*Response, error) + DeleteMemberRole(gid any, memberRole int64, options ...RequestOptionFunc) (*Response, error) } // MemberRolesService handles communication with the member roles related @@ -32,10 +31,10 @@ var _ MemberRolesServiceInterface = (*MemberRolesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/member_roles/#list-all-member-roles-of-a-group type MemberRole struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Description string `json:"description,omitempty"` - GroupID int `json:"group_id"` + GroupID int64 `json:"group_id"` BaseAccessLevel AccessLevelValue `json:"base_access_level"` AdminCICDVariables bool `json:"admin_cicd_variables,omitempty"` AdminComplianceFramework bool `json:"admin_compliance_framework,omitempty"` @@ -62,21 +61,15 @@ type MemberRole struct { // ListInstanceMemberRoles gets all member roles in an instance. // Authentication as Administrator is required. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#get-all-instance-member-roles func (s *MemberRolesService) ListInstanceMemberRoles(options ...RequestOptionFunc) ([]*MemberRole, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "member_roles", nil, options) - if err != nil { - return nil, nil, err - } - - var mrs []*MemberRole - resp, err := s.client.Do(req, &mrs) - if err != nil { - return nil, resp, err - } - - return mrs, resp, nil + return do[[]*MemberRole](s.client, + withMethod(http.MethodGet), + withPath("member_roles"), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // CreateMemberRoleOptions represents the available CreateInstanceMemberRole() @@ -113,103 +106,67 @@ type CreateMemberRoleOptions struct { // CreateInstanceMemberRole creates an instance-wide member role. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#create-a-instance-member-role func (s *MemberRolesService) CreateInstanceMemberRole(opt *CreateMemberRoleOptions, options ...RequestOptionFunc) (*MemberRole, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "member_roles", opt, options) - if err != nil { - return nil, nil, err - } - - mr := new(MemberRole) - resp, err := s.client.Do(req, mr) - if err != nil { - return nil, resp, err - } - - return mr, resp, nil + return do[*MemberRole](s.client, + withMethod(http.MethodPost), + withPath("member_roles"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteInstanceMemberRole deletes a member role from a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#delete-an-instance-member-role -func (s *MemberRolesService) DeleteInstanceMemberRole(memberRoleID int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("member_roles/%d", memberRoleID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MemberRolesService) DeleteInstanceMemberRole(memberRoleID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("member_roles/%d", memberRoleID), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // ListMemberRoles gets a list of member roles for a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#get-all-group-member-roles func (s *MemberRolesService) ListMemberRoles(gid any, options ...RequestOptionFunc) ([]*MemberRole, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/member_roles", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var mrs []*MemberRole - resp, err := s.client.Do(req, &mrs) - if err != nil { - return nil, resp, err - } - - return mrs, resp, nil + return do[[]*MemberRole](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/member_roles", GroupID{gid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // CreateMemberRole creates a new member role for a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#add-a-member-role-to-a-group func (s *MemberRolesService) CreateMemberRole(gid any, opt *CreateMemberRoleOptions, options ...RequestOptionFunc) (*MemberRole, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/member_roles", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - mr := new(MemberRole) - resp, err := s.client.Do(req, mr) - if err != nil { - return nil, resp, err - } - - return mr, resp, nil + return do[*MemberRole](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/member_roles", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMemberRole deletes a member role from a specified group. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/member_roles/#remove-member-role-of-a-group -func (s *MemberRolesService) DeleteMemberRole(gid any, memberRole int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/member_roles/%d", PathEscape(group), memberRole) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MemberRolesService) DeleteMemberRole(gid any, memberRole int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/member_roles/%d", GroupID{gid}, memberRole), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approval_settings.go b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approval_settings.go index c1701be22..4c182063d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approval_settings.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approval_settings.go @@ -15,16 +15,15 @@ package gitlab import ( - "fmt" "net/http" ) type ( MergeRequestApprovalSettingsServiceInterface interface { GetGroupMergeRequestApprovalSettings(gid any, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) - UpdateGroupMergeRequestApprovalSettings(gid any, opt *UpdateMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) + UpdateGroupMergeRequestApprovalSettings(gid any, opt *UpdateGroupMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) GetProjectMergeRequestApprovalSettings(pid any, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) - UpdateProjectMergeRequestApprovalSettings(pid any, opt *UpdateMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) + UpdateProjectMergeRequestApprovalSettings(pid any, opt *UpdateProjectMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) } // MergeRequestApprovalSettingsService handles communication with the merge @@ -70,39 +69,38 @@ type MergeRequestApprovalSetting struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approval_settings/#get-group-mr-approval-settings func (s *MergeRequestApprovalSettingsService) GetGroupMergeRequestApprovalSettings(gid any, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/merge_request_approval_setting", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - settings := new(MergeRequestApprovalSettings) - resp, err := s.client.Do(req, settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, nil + return do[*MergeRequestApprovalSettings](s.client, + withPath("groups/%s/merge_request_approval_setting", GroupID{gid}), + withRequestOpts(options...), + ) } -// UpdateMergeRequestApprovalSettingsOptions represents the available -// UpdateGroupMergeRequestApprovalSettings() and UpdateProjectMergeRequestApprovalSettings() +// UpdateProjectMergeRequestApprovalSettingsOptions represents the available +// UpdateProjectMergeRequestApprovalSettings() // options. // // GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approval_settings/#update-group-mr-approval-settings // https://docs.gitlab.com/api/merge_request_approval_settings/#update-project-mr-approval-settings -type UpdateMergeRequestApprovalSettingsOptions struct { +type UpdateProjectMergeRequestApprovalSettingsOptions struct { AllowAuthorApproval *bool `url:"allow_author_approval,omitempty" json:"allow_author_approval,omitempty"` AllowCommitterApproval *bool `url:"allow_committer_approval,omitempty" json:"allow_committer_approval,omitempty"` AllowOverridesToApproverListPerMergeRequest *bool `url:"allow_overrides_to_approver_list_per_merge_request,omitempty" json:"allow_overrides_to_approver_list_per_merge_request,omitempty"` RetainApprovalsOnPush *bool `url:"retain_approvals_on_push,omitempty" json:"retain_approvals_on_push,omitempty"` + RequireReauthenticationToApprove *bool `url:"require_reauthentication_to_approve,omitempty" json:"require_reauthentication_to_approve,omitempty"` SelectiveCodeOwnerRemovals *bool `url:"selective_code_owner_removals,omitempty" json:"selective_code_owner_removals,omitempty"` +} + +// UpdateGroupMergeRequestApprovalSettingsOptions represents the available +// UpdateGroupRequestApprovalSettings() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/merge_request_approval_settings/#update-group-mr-approval-settings +type UpdateGroupMergeRequestApprovalSettingsOptions struct { + AllowAuthorApproval *bool `url:"allow_author_approval,omitempty" json:"allow_author_approval,omitempty"` + AllowCommitterApproval *bool `url:"allow_committer_approval,omitempty" json:"allow_committer_approval,omitempty"` + AllowOverridesToApproverListPerMergeRequest *bool `url:"allow_overrides_to_approver_list_per_merge_request,omitempty" json:"allow_overrides_to_approver_list_per_merge_request,omitempty"` + RetainApprovalsOnPush *bool `url:"retain_approvals_on_push,omitempty" json:"retain_approvals_on_push,omitempty"` RequireReauthenticationToApprove *bool `url:"require_reauthentication_to_approve,omitempty" json:"require_reauthentication_to_approve,omitempty"` } @@ -111,25 +109,13 @@ type UpdateMergeRequestApprovalSettingsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approval_settings/#update-group-mr-approval-settings -func (s *MergeRequestApprovalSettingsService) UpdateGroupMergeRequestApprovalSettings(gid any, opt *UpdateMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/merge_request_approval_setting", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - settings := new(MergeRequestApprovalSettings) - resp, err := s.client.Do(req, settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, nil +func (s *MergeRequestApprovalSettingsService) UpdateGroupMergeRequestApprovalSettings(gid any, opt *UpdateGroupMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { + return do[*MergeRequestApprovalSettings](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/merge_request_approval_setting", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectMergeRequestApprovalSettings gets the merge request approval settings @@ -138,24 +124,10 @@ func (s *MergeRequestApprovalSettingsService) UpdateGroupMergeRequestApprovalSet // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approval_settings/#get-project-mr-approval-settings func (s *MergeRequestApprovalSettingsService) GetProjectMergeRequestApprovalSettings(pid any, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_request_approval_setting", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - settings := new(MergeRequestApprovalSettings) - resp, err := s.client.Do(req, settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, nil + return do[*MergeRequestApprovalSettings](s.client, + withPath("projects/%s/merge_request_approval_setting", ProjectID{pid}), + withRequestOpts(options...), + ) } // UpdateProjectMergeRequestApprovalSettings updates the merge request approval @@ -163,23 +135,11 @@ func (s *MergeRequestApprovalSettingsService) GetProjectMergeRequestApprovalSett // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approval_settings/#update-project-mr-approval-settings -func (s *MergeRequestApprovalSettingsService) UpdateProjectMergeRequestApprovalSettings(pid any, opt *UpdateMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_request_approval_setting", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - settings := new(MergeRequestApprovalSettings) - resp, err := s.client.Do(req, settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, nil +func (s *MergeRequestApprovalSettingsService) UpdateProjectMergeRequestApprovalSettings(pid any, opt *UpdateProjectMergeRequestApprovalSettingsOptions, options ...RequestOptionFunc) (*MergeRequestApprovalSettings, *Response, error) { + return do[*MergeRequestApprovalSettings](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_request_approval_setting", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approvals.go b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approvals.go index 80d16bec6..2cdc06c63 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approvals.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_approvals.go @@ -17,23 +17,22 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( MergeRequestApprovalsServiceInterface interface { - ApproveMergeRequest(pid any, mr int, opt *ApproveMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) - UnapproveMergeRequest(pid any, mr int, options ...RequestOptionFunc) (*Response, error) - ResetApprovalsOfMergeRequest(pid any, mr int, options ...RequestOptionFunc) (*Response, error) - GetConfiguration(pid any, mr int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) - ChangeApprovalConfiguration(pid any, mergeRequest int, opt *ChangeMergeRequestApprovalConfigurationOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - GetApprovalRules(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestApprovalRule, *Response, error) - GetApprovalState(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovalState, *Response, error) - CreateApprovalRule(pid any, mergeRequest int, opt *CreateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) - UpdateApprovalRule(pid any, mergeRequest int, approvalRule int, opt *UpdateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) - DeleteApprovalRule(pid any, mergeRequest int, approvalRule int, options ...RequestOptionFunc) (*Response, error) + ApproveMergeRequest(pid any, mr int64, opt *ApproveMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) + UnapproveMergeRequest(pid any, mr int64, options ...RequestOptionFunc) (*Response, error) + ResetApprovalsOfMergeRequest(pid any, mr int64, options ...RequestOptionFunc) (*Response, error) + GetConfiguration(pid any, mr int64, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) + ChangeApprovalConfiguration(pid any, mergeRequest int64, opt *ChangeMergeRequestApprovalConfigurationOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + GetApprovalRules(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*MergeRequestApprovalRule, *Response, error) + GetApprovalState(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequestApprovalState, *Response, error) + CreateApprovalRule(pid any, mergeRequest int64, opt *CreateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) + UpdateApprovalRule(pid any, mergeRequest int64, approvalRule int64, opt *UpdateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) + DeleteApprovalRule(pid any, mergeRequest int64, approvalRule int64, options ...RequestOptionFunc) (*Response, error) } // MergeRequestApprovalsService handles communication with the merge request @@ -53,9 +52,9 @@ var _ MergeRequestApprovalsServiceInterface = (*MergeRequestApprovalsService)(ni // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#single-merge-request-approval type MergeRequestApprovals struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` Description string `json:"description"` State string `json:"state"` @@ -63,9 +62,9 @@ type MergeRequestApprovals struct { UpdatedAt *time.Time `json:"updated_at"` MergeStatus string `json:"merge_status"` Approved bool `json:"approved"` - ApprovalsBeforeMerge int `json:"approvals_before_merge"` - ApprovalsRequired int `json:"approvals_required"` - ApprovalsLeft int `json:"approvals_left"` + ApprovalsBeforeMerge int64 `json:"approvals_before_merge"` + ApprovalsRequired int64 `json:"approvals_required"` + ApprovalsLeft int64 `json:"approvals_left"` RequirePasswordToApprove bool `json:"require_password_to_approve"` ApprovedBy []*MergeRequestApproverUser `json:"approved_by"` SuggestedApprovers []*BasicUser `json:"suggested_approvers"` @@ -83,24 +82,26 @@ func (m MergeRequestApprovals) String() string { return Stringify(m) } -// MergeRequestApproverGroup represents GitLab project level merge request approver group. +// MergeRequestApproverGroup represents GitLab project level merge request approver group. // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#project-approval-rules type MergeRequestApproverGroup struct { - Group struct { - ID int `json:"id"` - Name string `json:"name"` - Path string `json:"path"` - Description string `json:"description"` - Visibility string `json:"visibility"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - FullName string `json:"full_name"` - FullPath string `json:"full_path"` - LFSEnabled bool `json:"lfs_enabled"` - RequestAccessEnabled bool `json:"request_access_enabled"` - } + Group MergeRequestApproverNestedGroup `json:"group"` +} + +type MergeRequestApproverNestedGroup struct { + ID int64 `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Description string `json:"description"` + Visibility string `json:"visibility"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` + FullName string `json:"full_name"` + FullPath string `json:"full_path"` + LFSEnabled bool `json:"lfs_enabled"` + RequestAccessEnabled bool `json:"request_access_enabled"` } // MergeRequestApprovalRule represents a GitLab merge request approval rule. @@ -108,12 +109,12 @@ type MergeRequestApproverGroup struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#get-merge-request-approval-rules type MergeRequestApprovalRule struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` RuleType string `json:"rule_type"` ReportType string `json:"report_type"` EligibleApprovers []*BasicUser `json:"eligible_approvers"` - ApprovalsRequired int `json:"approvals_required"` + ApprovalsRequired int64 `json:"approvals_required"` SourceRule *ProjectApprovalRule `json:"source_rule"` Users []*BasicUser `json:"users"` Groups []*Group `json:"groups"` @@ -158,44 +159,26 @@ type ApproveMergeRequestOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#approve-merge-request -func (s *MergeRequestApprovalsService) ApproveMergeRequest(pid any, mr int, opt *ApproveMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approve", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequestApprovals) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestApprovalsService) ApproveMergeRequest(pid any, mr int64, opt *ApproveMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { + return do[*MergeRequestApprovals](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/approve", ProjectID{pid}, mr), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnapproveMergeRequest unapproves a previously approved merge request on GitLab. // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#unapprove-merge-request -func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid any, mr int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/unapprove", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid any, mr int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/unapprove", ProjectID{pid}, mr), + withRequestOpts(options...), + ) + return resp, err } // ResetApprovalsOfMergeRequest clear all approvals of merge request on GitLab. @@ -203,44 +186,24 @@ func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid any, mr int, op // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#reset-approvals-of-a-merge-request -func (s *MergeRequestApprovalsService) ResetApprovalsOfMergeRequest(pid any, mr int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/reset_approvals", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodPut, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestApprovalsService) ResetApprovalsOfMergeRequest(pid any, mr int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/reset_approvals", ProjectID{pid}, mr), + withRequestOpts(options...), + ) + return resp, err } // GetConfiguration shows information about single merge request approvals // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#single-merge-request-approval -func (s *MergeRequestApprovalsService) GetConfiguration(pid any, mr int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mr) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequestApprovals) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestApprovalsService) GetConfiguration(pid any, mr int64, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { + return do[*MergeRequestApprovals](s.client, + withPath("projects/%s/merge_requests/%d/approvals", ProjectID{pid}, mr), + withRequestOpts(options...), + ) } // ChangeMergeRequestApprovalConfigurationOptions represents the available @@ -248,81 +211,41 @@ func (s *MergeRequestApprovalsService) GetConfiguration(pid any, mr int, options // // Deprecated: in GitLab 16.0 type ChangeMergeRequestApprovalConfigurationOptions struct { - ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` + ApprovalsRequired *int64 `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` } // ChangeApprovalConfiguration updates the approval configuration of a merge request. // // Deprecated: in GitLab 16.0 -func (s *MergeRequestApprovalsService) ChangeApprovalConfiguration(pid any, mergeRequest int, opt *ChangeMergeRequestApprovalConfigurationOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestApprovalsService) ChangeApprovalConfiguration(pid any, mergeRequest int64, opt *ChangeMergeRequestApprovalConfigurationOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/approvals", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetApprovalRules requests information about a merge requestโ€™s approval rules +// GetApprovalRules requests information about a merge request's approval rules // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#get-merge-request-approval-rules -func (s *MergeRequestApprovalsService) GetApprovalRules(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var par []*MergeRequestApprovalRule - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil +func (s *MergeRequestApprovalsService) GetApprovalRules(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*MergeRequestApprovalRule, *Response, error) { + return do[[]*MergeRequestApprovalRule](s.client, + withPath("projects/%s/merge_requests/%d/approval_rules", ProjectID{pid}, mergeRequest), + withRequestOpts(options...), + ) } -// GetApprovalState requests information about a merge requestโ€™s approval state +// GetApprovalState requests information about a merge request's approval state // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#get-the-approval-state-of-merge-requests -func (s *MergeRequestApprovalsService) GetApprovalState(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovalState, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_state", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var pas *MergeRequestApprovalState - resp, err := s.client.Do(req, &pas) - if err != nil { - return nil, resp, err - } - - return pas, resp, nil +func (s *MergeRequestApprovalsService) GetApprovalState(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequestApprovalState, *Response, error) { + return do[*MergeRequestApprovalState](s.client, + withPath("projects/%s/merge_requests/%d/approval_state", ProjectID{pid}, mergeRequest), + withRequestOpts(options...), + ) } // CreateMergeRequestApprovalRuleOptions represents the available CreateApprovalRule() @@ -331,36 +254,24 @@ func (s *MergeRequestApprovalsService) GetApprovalState(pid any, mergeRequest in // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#create-merge-request-rule type CreateMergeRequestApprovalRuleOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` - ApprovalProjectRuleID *int `url:"approval_project_rule_id,omitempty" json:"approval_project_rule_id,omitempty"` - UserIDs *[]int `url:"user_ids,omitempty" json:"user_ids,omitempty"` - GroupIDs *[]int `url:"group_ids,omitempty" json:"group_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ApprovalsRequired *int64 `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` + ApprovalProjectRuleID *int64 `url:"approval_project_rule_id,omitempty" json:"approval_project_rule_id,omitempty"` + UserIDs *[]int64 `url:"user_ids,omitempty" json:"user_ids,omitempty"` + GroupIDs *[]int64 `url:"group_ids,omitempty" json:"group_ids,omitempty"` } // CreateApprovalRule creates a new MR level approval rule. // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#create-merge-request-rule -func (s *MergeRequestApprovalsService) CreateApprovalRule(pid any, mergeRequest int, opt *CreateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - par := new(MergeRequestApprovalRule) - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil +func (s *MergeRequestApprovalsService) CreateApprovalRule(pid any, mergeRequest int64, opt *CreateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) { + return do[*MergeRequestApprovalRule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/approval_rules", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateMergeRequestApprovalRuleOptions represents the available UpdateApprovalRule() @@ -369,52 +280,34 @@ func (s *MergeRequestApprovalsService) CreateApprovalRule(pid any, mergeRequest // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#update-merge-request-rule type UpdateMergeRequestApprovalRuleOptions struct { - Name *string `url:"name,omitempty" json:"name,omitempty"` - ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` - UserIDs *[]int `url:"user_ids,omitempty" json:"user_ids,omitempty"` - GroupIDs *[]int `url:"group_ids,omitempty" json:"group_ids,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + ApprovalsRequired *int64 `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` + UserIDs *[]int64 `url:"user_ids,omitempty" json:"user_ids,omitempty"` + GroupIDs *[]int64 `url:"group_ids,omitempty" json:"group_ids,omitempty"` } // UpdateApprovalRule updates an existing approval rule with new options. // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#update-merge-request-rule -func (s *MergeRequestApprovalsService) UpdateApprovalRule(pid any, mergeRequest int, approvalRule int, opt *UpdateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules/%d", PathEscape(project), mergeRequest, approvalRule) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - par := new(MergeRequestApprovalRule) - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil +func (s *MergeRequestApprovalsService) UpdateApprovalRule(pid any, mergeRequest int64, approvalRule int64, opt *UpdateMergeRequestApprovalRuleOptions, options ...RequestOptionFunc) (*MergeRequestApprovalRule, *Response, error) { + return do[*MergeRequestApprovalRule](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/approval_rules/%d", ProjectID{pid}, mergeRequest, approvalRule), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteApprovalRule deletes a mr level approval rule. // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#delete-merge-request-rule -func (s *MergeRequestApprovalsService) DeleteApprovalRule(pid any, mergeRequest int, approvalRule int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approval_rules/%d", PathEscape(project), mergeRequest, approvalRule) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestApprovalsService) DeleteApprovalRule(pid any, mergeRequest int64, approvalRule int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/approval_rules/%d", ProjectID{pid}, mergeRequest, approvalRule), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_context_commits.go b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_context_commits.go new file mode 100644 index 000000000..f2240f415 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/merge_request_context_commits.go @@ -0,0 +1,84 @@ +package gitlab + +import ( + "net/http" +) + +type ( + // MergeRequestContextCommitsServiceInterface handles communication with the + // merge request context commits related methods of the GitLab API. + MergeRequestContextCommitsServiceInterface interface { + // ListMergeRequestContextCommits gets a list of merge request context commits. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_context_commits/#list-mr-context-commits + ListMergeRequestContextCommits(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*Commit, *Response, error) + // CreateMergeRequestContextCommits creates a list of merge request context + // commits. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_context_commits/#create-mr-context-commits + CreateMergeRequestContextCommits(pid any, mergeRequest int64, opt *CreateMergeRequestContextCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) + // DeleteMergeRequestContextCommits deletes a list of merge request context + // commits. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_context_commits/#delete-mr-context-commits + DeleteMergeRequestContextCommits(pid any, mergeRequest int64, opt *DeleteMergeRequestContextCommitsOptions, options ...RequestOptionFunc) (*Response, error) + } + + // MergeRequestContextCommitsService handles communication with the merge + // request context commits related methods of the GitLab API. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_context_commits/ + MergeRequestContextCommitsService struct { + client *Client + } +) + +var _ MergeRequestContextCommitsServiceInterface = (*MergeRequestContextCommitsService)(nil) + +func (s *MergeRequestContextCommitsService) ListMergeRequestContextCommits(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*Commit, *Response, error) { + return do[[]*Commit](s.client, + withPath("projects/%s/merge_requests/%d/context_commits", ProjectID{pid}, mergeRequest), + withRequestOpts(options...), + ) +} + +// CreateMergeRequestContextCommitsOptions represents the available +// CreateMergeRequestContextCommits() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/merge_request_context_commits/#create-mr-context-commits +type CreateMergeRequestContextCommitsOptions struct { + Commits *[]string `url:"commits,omitempty" json:"commits,omitempty"` +} + +func (s *MergeRequestContextCommitsService) CreateMergeRequestContextCommits(pid any, mergeRequest int64, opt *CreateMergeRequestContextCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { + return do[[]*Commit](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/context_commits", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// DeleteMergeRequestContextCommitsOptions represents the available +// DeleteMergeRequestContextCommits() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/merge_request_context_commits/#delete-mr-context-commits +type DeleteMergeRequestContextCommitsOptions struct { + Commits *[]string `url:"commits,omitempty" json:"commits,omitempty"` +} + +func (s *MergeRequestContextCommitsService) DeleteMergeRequestContextCommits(pid any, mergeRequest int64, opt *DeleteMergeRequestContextCommitsOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/context_commits", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/merge_requests.go b/vendor/gitlab.com/gitlab-org/api/client-go/merge_requests.go index 33048676e..8bfa7aeff 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/merge_requests.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/merge_requests.go @@ -19,7 +19,6 @@ package gitlab import ( "bytes" "encoding/json" - "fmt" "net/http" "time" ) @@ -29,37 +28,37 @@ type ( ListMergeRequests(opt *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) ListProjectMergeRequests(pid any, opt *ListProjectMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) ListGroupMergeRequests(gid any, opt *ListGroupMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) - GetMergeRequest(pid any, mergeRequest int, opt *GetMergeRequestsOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - GetMergeRequestApprovals(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) - GetMergeRequestCommits(pid any, mergeRequest int, opt *GetMergeRequestCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) - GetMergeRequestChanges(pid any, mergeRequest int, opt *GetMergeRequestChangesOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - ListMergeRequestDiffs(pid any, mergeRequest int, opt *ListMergeRequestDiffsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiff, *Response, error) - ShowMergeRequestRawDiffs(pid any, mergeRequest int, opt *ShowMergeRequestRawDiffsOptions, options ...RequestOptionFunc) ([]byte, *Response, error) - GetMergeRequestParticipants(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) - GetMergeRequestReviewers(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestReviewer, *Response, error) - ListMergeRequestPipelines(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) - CreateMergeRequestPipeline(pid any, mergeRequest int, options ...RequestOptionFunc) (*PipelineInfo, *Response, error) - GetIssuesClosedOnMerge(pid any, mergeRequest int, opt *GetIssuesClosedOnMergeOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) - ListRelatedIssues(pid any, mergeRequest int, opt *ListRelatedIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + GetMergeRequest(pid any, mergeRequest int64, opt *GetMergeRequestsOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + GetMergeRequestApprovals(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) + GetMergeRequestCommits(pid any, mergeRequest int64, opt *GetMergeRequestCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) + GetMergeRequestChanges(pid any, mergeRequest int64, opt *GetMergeRequestChangesOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + ListMergeRequestDiffs(pid any, mergeRequest int64, opt *ListMergeRequestDiffsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiff, *Response, error) + ShowMergeRequestRawDiffs(pid any, mergeRequest int64, opt *ShowMergeRequestRawDiffsOptions, options ...RequestOptionFunc) ([]byte, *Response, error) + GetMergeRequestParticipants(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) + GetMergeRequestReviewers(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*MergeRequestReviewer, *Response, error) + ListMergeRequestPipelines(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) + CreateMergeRequestPipeline(pid any, mergeRequest int64, options ...RequestOptionFunc) (*PipelineInfo, *Response, error) + GetIssuesClosedOnMerge(pid any, mergeRequest int64, opt *GetIssuesClosedOnMergeOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + ListRelatedIssues(pid any, mergeRequest int64, opt *ListRelatedIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) CreateMergeRequest(pid any, opt *CreateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - UpdateMergeRequest(pid any, mergeRequest int, opt *UpdateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - DeleteMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*Response, error) - AcceptMergeRequest(pid any, mergeRequest int, opt *AcceptMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - CancelMergeWhenPipelineSucceeds(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - RebaseMergeRequest(pid any, mergeRequest int, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) - GetMergeRequestDiffVersions(pid any, mergeRequest int, opt *GetMergeRequestDiffVersionsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiffVersion, *Response, error) - GetSingleMergeRequestDiffVersion(pid any, mergeRequest, version int, opt *GetSingleMergeRequestDiffVersionOptions, options ...RequestOptionFunc) (*MergeRequestDiffVersion, *Response, error) - SubscribeToMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - UnsubscribeFromMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) - CreateTodo(pid any, mergeRequest int, options ...RequestOptionFunc) (*Todo, *Response, error) - SetTimeEstimate(pid any, mergeRequest int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) - ResetTimeEstimate(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - AddSpentTime(pid any, mergeRequest int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) - ResetSpentTime(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - GetTimeSpent(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) - CreateMergeRequestDependency(pid any, mergeRequest int, opts CreateMergeRequestDependencyOptions, options ...RequestOptionFunc) (*MergeRequestDependency, *Response, error) - DeleteMergeRequestDependency(pid any, mergeRequest int, blockingMergeRequest int, options ...RequestOptionFunc) (*Response, error) - GetMergeRequestDependencies(pid any, mergeRequest int, options ...RequestOptionFunc) ([]MergeRequestDependency, *Response, error) + UpdateMergeRequest(pid any, mergeRequest int64, opt *UpdateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + DeleteMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Response, error) + AcceptMergeRequest(pid any, mergeRequest int64, opt *AcceptMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + CancelMergeWhenPipelineSucceeds(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + RebaseMergeRequest(pid any, mergeRequest int64, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) + GetMergeRequestDiffVersions(pid any, mergeRequest int64, opt *GetMergeRequestDiffVersionsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiffVersion, *Response, error) + GetSingleMergeRequestDiffVersion(pid any, mergeRequest, version int64, opt *GetSingleMergeRequestDiffVersionOptions, options ...RequestOptionFunc) (*MergeRequestDiffVersion, *Response, error) + SubscribeToMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + UnsubscribeFromMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) + CreateTodo(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Todo, *Response, error) + SetTimeEstimate(pid any, mergeRequest int64, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) + ResetTimeEstimate(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + AddSpentTime(pid any, mergeRequest int64, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) + ResetSpentTime(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + GetTimeSpent(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) + CreateMergeRequestDependency(pid any, mergeRequest int64, opts CreateMergeRequestDependencyOptions, options ...RequestOptionFunc) (*MergeRequestDependency, *Response, error) + DeleteMergeRequestDependency(pid any, mergeRequest int64, blockingMergeRequest int64, options ...RequestOptionFunc) (*Response, error) + GetMergeRequestDependencies(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]MergeRequestDependency, *Response, error) } // MergeRequestsService handles communication with the merge requests related @@ -79,25 +78,25 @@ var _ MergeRequestsServiceInterface = (*MergeRequestsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/ type BasicMergeRequest struct { - ID int `json:"id"` - IID int `json:"iid"` + ID int64 `json:"id"` + IID int64 `json:"iid"` TargetBranch string `json:"target_branch"` SourceBranch string `json:"source_branch"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` State string `json:"state"` Imported bool `json:"imported"` ImportedFrom string `json:"imported_from"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` - Upvotes int `json:"upvotes"` - Downvotes int `json:"downvotes"` + Upvotes int64 `json:"upvotes"` + Downvotes int64 `json:"downvotes"` Author *BasicUser `json:"author"` Assignee *BasicUser `json:"assignee"` Assignees []*BasicUser `json:"assignees"` Reviewers []*BasicUser `json:"reviewers"` - SourceProjectID int `json:"source_project_id"` - TargetProjectID int `json:"target_project_id"` + SourceProjectID int64 `json:"source_project_id"` + TargetProjectID int64 `json:"target_project_id"` Labels Labels `json:"labels"` LabelDetails []*LabelDetails `json:"label_details"` Description string `json:"description"` @@ -114,7 +113,7 @@ type BasicMergeRequest struct { SHA string `json:"sha"` MergeCommitSHA string `json:"merge_commit_sha"` SquashCommitSHA string `json:"squash_commit_sha"` - UserNotesCount int `json:"user_notes_count"` + UserNotesCount int64 `json:"user_notes_count"` ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"` ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` AllowCollaboration bool `json:"allow_collaboration"` @@ -142,25 +141,19 @@ func (m BasicMergeRequest) String() string { // GitLab API docs: https://docs.gitlab.com/api/merge_requests/ type MergeRequest struct { BasicMergeRequest - MergeError string `json:"merge_error"` - Subscribed bool `json:"subscribed"` - ChangesCount string `json:"changes_count"` - User struct { - CanMerge bool `json:"can_merge"` - } `json:"user"` - LatestBuildStartedAt *time.Time `json:"latest_build_started_at"` - LatestBuildFinishedAt *time.Time `json:"latest_build_finished_at"` - FirstDeployedToProductionAt *time.Time `json:"first_deployed_to_production_at"` - Pipeline *PipelineInfo `json:"pipeline"` - HeadPipeline *Pipeline `json:"head_pipeline"` - DiffRefs struct { - BaseSha string `json:"base_sha"` - HeadSha string `json:"head_sha"` - StartSha string `json:"start_sha"` - } `json:"diff_refs"` - RebaseInProgress bool `json:"rebase_in_progress"` - DivergedCommitsCount int `json:"diverged_commits_count"` - FirstContribution bool `json:"first_contribution"` + MergeError string `json:"merge_error"` + Subscribed bool `json:"subscribed"` + ChangesCount string `json:"changes_count"` + User MergeRequestUser `json:"user"` + LatestBuildStartedAt *time.Time `json:"latest_build_started_at"` + LatestBuildFinishedAt *time.Time `json:"latest_build_finished_at"` + FirstDeployedToProductionAt *time.Time `json:"first_deployed_to_production_at"` + Pipeline *PipelineInfo `json:"pipeline"` + HeadPipeline *Pipeline `json:"head_pipeline"` + DiffRefs MergeRequestDiffRefs `json:"diff_refs"` + RebaseInProgress bool `json:"rebase_in_progress"` + DivergedCommitsCount int64 `json:"diverged_commits_count"` + FirstContribution bool `json:"first_contribution"` // Deprecated: use Draft instead WorkInProgress bool `json:"work_in_progress"` @@ -170,6 +163,30 @@ func (m MergeRequest) String() string { return Stringify(m) } +// MergeRequestUser represents a GitLab merge request user. +// +// GitLab API docs: https://docs.gitlab.com/api/merge_requests/ +type MergeRequestUser struct { + CanMerge bool `json:"can_merge"` +} + +func (u MergeRequestUser) String() string { + return Stringify(u) +} + +// MergeRequestDiffRefs represents a GitLab merge request diff refs. +// +// GitLab API docs: https://docs.gitlab.com/api/merge_requests/ +type MergeRequestDiffRefs struct { + BaseSha string `json:"base_sha"` + HeadSha string `json:"head_sha"` + StartSha string `json:"start_sha"` +} + +func (d MergeRequestDiffRefs) String() string { + return Stringify(d) +} + func (m *MergeRequest) UnmarshalJSON(data []byte) error { type alias MergeRequest @@ -204,9 +221,9 @@ func (m *MergeRequest) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, (*alias)(m)) } -// MergeRequestDiff represents Gitlab merge request diff. +// MergeRequestDiff represents GitLab merge request diff. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-merge-request-diffs type MergeRequestDiff struct { OldPath string `json:"old_path"` @@ -218,19 +235,21 @@ type MergeRequestDiff struct { RenamedFile bool `json:"renamed_file"` DeletedFile bool `json:"deleted_file"` GeneratedFile bool `json:"generated_file"` + Collapsed bool `json:"collapsed"` + TooLarge bool `json:"too_large"` } -// MergeRequestDiffVersion represents Gitlab merge request version. +// MergeRequestDiffVersion represents GitLab merge request version. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-merge-request-diff-versions type MergeRequestDiffVersion struct { - ID int `json:"id"` + ID int64 `json:"id"` HeadCommitSHA string `json:"head_commit_sha,omitempty"` BaseCommitSHA string `json:"base_commit_sha,omitempty"` StartCommitSHA string `json:"start_commit_sha,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` - MergeRequestID int `json:"merge_request_id,omitempty"` + MergeRequestID int64 `json:"merge_request_id,omitempty"` State string `json:"state,omitempty"` RealSize string `json:"real_size,omitempty"` Commits []*Commit `json:"commits,omitempty"` @@ -241,6 +260,15 @@ func (m MergeRequestDiffVersion) String() string { return Stringify(m) } +// MergeRequestReviewer represents a reviewer entry returned by the reviewers API. +// Matches the JSON shape used in tests: {"user": {...}, "state": "...", "created_at": "..."} +// Placed here because it's used by MergeRequestsService.GetMergeRequestReviewers and tests/mock. +type MergeRequestReviewer struct { + User *BasicUser `json:"user"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` +} + // ListMergeRequestsOptions represents the available ListMergeRequests() // options. // @@ -263,7 +291,7 @@ type ListMergeRequestsOptions struct { UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` @@ -288,18 +316,17 @@ type ListMergeRequestsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-merge-requests func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "merge_requests", opt, options) - if err != nil { - return nil, nil, err - } - - var m []*BasicMergeRequest - resp, err := s.client.Do(req, &m) + mrs, resp, err := do[[]*MergeRequest](s.client, + withMethod(http.MethodGet), + withPath("merge_requests"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return m, resp, nil + return toBasic(mrs), resp, nil } // ListProjectMergeRequestsOptions represents the available ListMergeRequests() @@ -309,12 +336,13 @@ func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, // https://docs.gitlab.com/api/merge_requests/#list-project-merge-requests type ListProjectMergeRequestsOptions struct { ListOptions - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` State *string `url:"state,omitempty" json:"state,omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` Milestone *string `url:"milestone,omitempty" json:"milestone,omitempty"` View *string `url:"view,omitempty" json:"view,omitempty"` + Environment *string `url:"environment,omitempty" json:"environment,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` NotLabels *LabelOptions `url:"not[labels],comma,omitempty" json:"not[labels],omitempty"` WithLabelsDetails *bool `url:"with_labels_details,omitempty" json:"with_labels_details,omitempty"` @@ -323,8 +351,10 @@ type ListProjectMergeRequestsOptions struct { CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` + DeployedBefore *time.Time `url:"deployed_before,omitempty" json:"deployed_before,omitempty"` + DeployedAfter *time.Time `url:"deployed_after,omitempty" json:"deployed_after,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` @@ -345,24 +375,17 @@ type ListProjectMergeRequestsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-project-merge-requests func (s *MergeRequestsService) ListProjectMergeRequests(pid any, opt *ListProjectMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*BasicMergeRequest - resp, err := s.client.Do(req, &m) + mrs, resp, err := do[[]*MergeRequest](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return m, resp, nil + return toBasic(mrs), resp, nil } // ListGroupMergeRequestsOptions represents the available ListGroupMergeRequests() @@ -386,7 +409,7 @@ type ListGroupMergeRequestsOptions struct { UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"` UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"` Scope *string `url:"scope,omitempty" json:"scope,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"` NotAuthorUsername *string `url:"not[author_username],omitempty" json:"not[author_username],omitempty"` AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` @@ -408,24 +431,17 @@ type ListGroupMergeRequestsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-group-merge-requests func (s *MergeRequestsService) ListGroupMergeRequests(gid any, opt *ListGroupMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/merge_requests", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*BasicMergeRequest - resp, err := s.client.Do(req, &m) + mrs, resp, err := do[[]*MergeRequest](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/merge_requests", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - return m, resp, nil + return toBasic(mrs), resp, nil } // GetMergeRequestsOptions represents the available GetMergeRequests() @@ -443,50 +459,26 @@ type GetMergeRequestsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-mr -func (s *MergeRequestsService) GetMergeRequest(pid any, mergeRequest int, opt *GetMergeRequestsOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) GetMergeRequest(pid any, mergeRequest int64, opt *GetMergeRequestsOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestApprovals gets information about a merge requests approvals // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#single-merge-request-approval -func (s *MergeRequestsService) GetMergeRequestApprovals(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/approvals", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - a := new(MergeRequestApprovals) - resp, err := s.client.Do(req, a) - if err != nil { - return nil, resp, err - } - - return a, resp, nil +func (s *MergeRequestsService) GetMergeRequestApprovals(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequestApprovals, *Response, error) { + return do[*MergeRequestApprovals](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/approvals", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // GetMergeRequestCommitsOptions represents the available GetMergeRequestCommits() @@ -494,31 +486,21 @@ func (s *MergeRequestsService) GetMergeRequestApprovals(pid any, mergeRequest in // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-commits -type GetMergeRequestCommitsOptions ListOptions +type GetMergeRequestCommitsOptions struct { + ListOptions +} // GetMergeRequestCommits gets a list of merge request commits. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-commits -func (s *MergeRequestsService) GetMergeRequestCommits(pid any, mergeRequest int, opt *GetMergeRequestCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/commits", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var c []*Commit - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil +func (s *MergeRequestsService) GetMergeRequestCommits(pid any, mergeRequest int64, opt *GetMergeRequestCommitsOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { + return do[[]*Commit](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/commits", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestChangesOptions represents the available GetMergeRequestChanges() @@ -541,25 +523,13 @@ type GetMergeRequestChangesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-changes -func (s *MergeRequestsService) GetMergeRequestChanges(pid any, mergeRequest int, opt *GetMergeRequestChangesOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/changes", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) GetMergeRequestChanges(pid any, mergeRequest int64, opt *GetMergeRequestChangesOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/changes", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListMergeRequestDiffsOptions represents the available ListMergeRequestDiffs() @@ -576,25 +546,13 @@ type ListMergeRequestDiffsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-merge-request-diffs -func (s *MergeRequestsService) ListMergeRequestDiffs(pid any, mergeRequest int, opt *ListMergeRequestDiffsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiff, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/diffs", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*MergeRequestDiff - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) ListMergeRequestDiffs(pid any, mergeRequest int64, opt *ListMergeRequestDiffsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiff, *Response, error) { + return do[[]*MergeRequestDiff](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/diffs", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ShowMergeRequestRawDiffsOptions represents the available ShowMergeRequestRawDiffs() @@ -608,139 +566,66 @@ type ShowMergeRequestRawDiffsOptions struct{} // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#show-merge-request-raw-diffs -func (s *MergeRequestsService) ShowMergeRequestRawDiffs(pid any, mergeRequest int, opt *ShowMergeRequestRawDiffsOptions, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return []byte{}, nil, err - } - u := fmt.Sprintf( - "projects/%s/merge_requests/%d/raw_diffs", - PathEscape(project), - mergeRequest, +func (s *MergeRequestsService) ShowMergeRequestRawDiffs(pid any, mergeRequest int64, opt *ShowMergeRequestRawDiffsOptions, options ...RequestOptionFunc) ([]byte, *Response, error) { + b, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/merge_requests/%d/raw_diffs", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), ) - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return []byte{}, nil, err - } - - var rd bytes.Buffer - resp, err := s.client.Do(req, &rd) - if err != nil { - return []byte{}, resp, err - } - - return rd.Bytes(), resp, nil + return b.Bytes(), resp, err } // GetMergeRequestParticipants gets a list of merge request participants. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-participants -func (s *MergeRequestsService) GetMergeRequestParticipants(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/participants", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var bu []*BasicUser - resp, err := s.client.Do(req, &bu) - if err != nil { - return nil, resp, err - } - - return bu, resp, nil -} - -// MergeRequestReviewer represents a GitLab merge request reviewer. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-reviewers -type MergeRequestReviewer struct { - User *BasicUser `json:"user"` - State string `json:"state"` - CreatedAt *time.Time `json:"created_at"` +func (s *MergeRequestsService) GetMergeRequestParticipants(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*BasicUser, *Response, error) { + return do[[]*BasicUser](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/participants", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // GetMergeRequestReviewers gets a list of merge request reviewers. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-single-merge-request-reviewers -func (s *MergeRequestsService) GetMergeRequestReviewers(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*MergeRequestReviewer, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/reviewers", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var mrr []*MergeRequestReviewer - resp, err := s.client.Do(req, &mrr) - if err != nil { - return nil, resp, err - } - - return mrr, resp, nil +func (s *MergeRequestsService) GetMergeRequestReviewers(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*MergeRequestReviewer, *Response, error) { + return do[[]*MergeRequestReviewer](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/reviewers", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // ListMergeRequestPipelines gets all pipelines for the provided merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-merge-request-pipelines -func (s *MergeRequestsService) ListMergeRequestPipelines(pid any, mergeRequest int, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var p []*PipelineInfo - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *MergeRequestsService) ListMergeRequestPipelines(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) { + return do[[]*PipelineInfo](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/pipelines", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // CreateMergeRequestPipeline creates a new pipeline for a merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-merge-request-pipeline -func (s *MergeRequestsService) CreateMergeRequestPipeline(pid any, mergeRequest int, options ...RequestOptionFunc) (*PipelineInfo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/pipelines", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineInfo) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *MergeRequestsService) CreateMergeRequestPipeline(pid any, mergeRequest int64, options ...RequestOptionFunc) (*PipelineInfo, *Response, error) { + return do[*PipelineInfo](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/pipelines", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // GetIssuesClosedOnMergeOptions represents the available GetIssuesClosedOnMerge() @@ -748,64 +633,43 @@ func (s *MergeRequestsService) CreateMergeRequestPipeline(pid any, mergeRequest // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-issues-that-close-on-merge -type GetIssuesClosedOnMergeOptions ListOptions +type GetIssuesClosedOnMergeOptions struct { + ListOptions +} // GetIssuesClosedOnMerge gets all the issues that would be closed by merging the // provided merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-issues-that-close-on-merge -func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid any, mergeRequest int, opt *GetIssuesClosedOnMergeOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/closes_issues", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid any, mergeRequest int64, opt *GetIssuesClosedOnMergeOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/closes_issues", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListRelatedIssuesOptions represents the available ListRelatedIssues() options. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-issues-related-to-the-merge-request -type ListRelatedIssuesOptions ListOptions +type ListRelatedIssuesOptions struct { + ListOptions +} // ListRelatedIssues gets all the issues related to provided merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#list-issues-related-to-the-merge-request -func (s *MergeRequestsService) ListRelatedIssues(pid any, mergeRequest int, opt *ListRelatedIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - - u := fmt.Sprintf("projects/%s/merge_requests/%d/related_issues", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } - - return i, resp, nil +func (s *MergeRequestsService) ListRelatedIssues(pid any, mergeRequest int64, opt *ListRelatedIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/related_issues", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateMergeRequestOptions represents the available CreateMergeRequest() @@ -819,17 +683,17 @@ type CreateMergeRequestOptions struct { SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"` TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - AssigneeIDs *[]int `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` - ReviewerIDs *[]int `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"` - TargetProjectID *int `url:"target_project_id,omitempty" json:"target_project_id,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + AssigneeIDs *[]int64 `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` + ReviewerIDs *[]int64 `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"` + TargetProjectID *int64 `url:"target_project_id,omitempty" json:"target_project_id,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` RemoveSourceBranch *bool `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"` Squash *bool `url:"squash,omitempty" json:"squash,omitempty"` AllowCollaboration *bool `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"` // Deprecated: will be removed in v5 of the API, use the Merge Request Approvals API instead - ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` + ApprovalsBeforeMerge *int64 `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` } // CreateMergeRequest creates a new merge request. @@ -837,24 +701,12 @@ type CreateMergeRequestOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-mr func (s *MergeRequestsService) CreateMergeRequest(pid any, opt *CreateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil + return do[*MergeRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateMergeRequestOptions represents the available UpdateMergeRequest() @@ -866,13 +718,13 @@ type UpdateMergeRequestOptions struct { Title *string `url:"title,omitempty" json:"title,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"` - AssigneeID *int `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` - AssigneeIDs *[]int `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` - ReviewerIDs *[]int `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"` + AssigneeID *int64 `url:"assignee_id,omitempty" json:"assignee_id,omitempty"` + AssigneeIDs *[]int64 `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"` + ReviewerIDs *[]int64 `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"` Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"` AddLabels *LabelOptions `url:"add_labels,comma,omitempty" json:"add_labels,omitempty"` RemoveLabels *LabelOptions `url:"remove_labels,comma,omitempty" json:"remove_labels,omitempty"` - MilestoneID *int `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` + MilestoneID *int64 `url:"milestone_id,omitempty" json:"milestone_id,omitempty"` StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` RemoveSourceBranch *bool `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"` Squash *bool `url:"squash,omitempty" json:"squash,omitempty"` @@ -884,44 +736,27 @@ type UpdateMergeRequestOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#update-mr -func (s *MergeRequestsService) UpdateMergeRequest(pid any, mergeRequest int, opt *UpdateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) UpdateMergeRequest(pid any, mergeRequest int64, opt *UpdateMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMergeRequest deletes a merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#delete-a-merge-request -func (s *MergeRequestsService) DeleteMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestsService) DeleteMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // AcceptMergeRequestOptions represents the available AcceptMergeRequest() @@ -948,25 +783,13 @@ type AcceptMergeRequestOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#merge-a-merge-request -func (s *MergeRequestsService) AcceptMergeRequest(pid any, mergeRequest int, opt *AcceptMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/merge", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) AcceptMergeRequest(pid any, mergeRequest int64, opt *AcceptMergeRequestOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/merge", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CancelMergeWhenPipelineSucceeds cancels a merge when pipeline succeeds. If @@ -977,25 +800,13 @@ func (s *MergeRequestsService) AcceptMergeRequest(pid any, mergeRequest int, opt // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#cancel-merge-when-pipeline-succeeds -func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/cancel_merge_when_pipeline_succeeds", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/cancel_merge_when_pipeline_succeeds", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // RebaseMergeRequestOptions represents the available RebaseMergeRequest() @@ -1013,19 +824,14 @@ type RebaseMergeRequestOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#rebase-a-merge-request -func (s *MergeRequestsService) RebaseMergeRequest(pid any, mergeRequest int, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/rebase", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestsService) RebaseMergeRequest(pid any, mergeRequest int64, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/rebase", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // GetMergeRequestDiffVersionsOptions represents the available @@ -1033,31 +839,21 @@ func (s *MergeRequestsService) RebaseMergeRequest(pid any, mergeRequest int, opt // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-merge-request-diff-versions -type GetMergeRequestDiffVersionsOptions ListOptions +type GetMergeRequestDiffVersionsOptions struct { + ListOptions +} // GetMergeRequestDiffVersions get a list of merge request diff versions. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-merge-request-diff-versions -func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid any, mergeRequest int, opt *GetMergeRequestDiffVersionsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiffVersion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/versions", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var v []*MergeRequestDiffVersion - resp, err := s.client.Do(req, &v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil +func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid any, mergeRequest int64, opt *GetMergeRequestDiffVersionsOptions, options ...RequestOptionFunc) ([]*MergeRequestDiffVersion, *Response, error) { + return do[[]*MergeRequestDiffVersion](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/versions", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetSingleMergeRequestDiffVersionOptions represents the available @@ -1073,25 +869,13 @@ type GetSingleMergeRequestDiffVersionOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-a-single-merge-request-diff-version -func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid any, mergeRequest, version int, opt *GetSingleMergeRequestDiffVersionOptions, options ...RequestOptionFunc) (*MergeRequestDiffVersion, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/versions/%d", PathEscape(project), mergeRequest, version) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(MergeRequestDiffVersion) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil +func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid any, mergeRequest, version int64, opt *GetSingleMergeRequestDiffVersionOptions, options ...RequestOptionFunc) (*MergeRequestDiffVersion, *Response, error) { + return do[*MergeRequestDiffVersion](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/versions/%d", ProjectID{pid}, mergeRequest, version), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SubscribeToMergeRequest subscribes the authenticated user to the given merge @@ -1100,25 +884,13 @@ func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid any, mergeRe // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#subscribe-to-a-merge-request -func (s *MergeRequestsService) SubscribeToMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/subscribe", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) SubscribeToMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/subscribe", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // UnsubscribeFromMergeRequest unsubscribes the authenticated user from the @@ -1128,25 +900,13 @@ func (s *MergeRequestsService) SubscribeToMergeRequest(pid any, mergeRequest int // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#unsubscribe-from-a-merge-request -func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/unsubscribe", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(MergeRequest) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeRequest, *Response, error) { + return do[*MergeRequest](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/unsubscribe", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // CreateTodo manually creates a todo for the current user on a merge request. @@ -1155,32 +915,20 @@ func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid any, mergeRequest // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-a-to-do-item -func (s *MergeRequestsService) CreateTodo(pid any, mergeRequest int, options ...RequestOptionFunc) (*Todo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/todo", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(Todo) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *MergeRequestsService) CreateTodo(pid any, mergeRequest int64, options ...RequestOptionFunc) (*Todo, *Response, error) { + return do[*Todo](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/todo", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) } // SetTimeEstimate sets the time estimate for a single project merge request. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#set-a-time-estimate-for-a-merge-request -func (s *MergeRequestsService) SetTimeEstimate(pid any, mergeRequest int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *MergeRequestsService) SetTimeEstimate(pid any, mergeRequest int64, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.setTimeEstimate(pid, "merge_requests", mergeRequest, opt, options...) } @@ -1188,7 +936,7 @@ func (s *MergeRequestsService) SetTimeEstimate(pid any, mergeRequest int, opt *S // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#reset-the-time-estimate-for-a-merge-request -func (s *MergeRequestsService) ResetTimeEstimate(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *MergeRequestsService) ResetTimeEstimate(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.resetTimeEstimate(pid, "merge_requests", mergeRequest, options...) } @@ -1196,7 +944,7 @@ func (s *MergeRequestsService) ResetTimeEstimate(pid any, mergeRequest int, opti // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#add-spent-time-for-a-merge-request -func (s *MergeRequestsService) AddSpentTime(pid any, mergeRequest int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *MergeRequestsService) AddSpentTime(pid any, mergeRequest int64, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.addSpentTime(pid, "merge_requests", mergeRequest, opt, options...) } @@ -1204,7 +952,7 @@ func (s *MergeRequestsService) AddSpentTime(pid any, mergeRequest int, opt *AddS // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#reset-spent-time-for-a-merge-request -func (s *MergeRequestsService) ResetSpentTime(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *MergeRequestsService) ResetSpentTime(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.resetSpentTime(pid, "merge_requests", mergeRequest, options...) } @@ -1212,7 +960,7 @@ func (s *MergeRequestsService) ResetSpentTime(pid any, mergeRequest int, options // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-time-tracking-stats -func (s *MergeRequestsService) GetTimeSpent(pid any, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { +func (s *MergeRequestsService) GetTimeSpent(pid any, mergeRequest int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { return s.timeStats.getTimeSpent(pid, "merge_requests", mergeRequest, options...) } @@ -1221,9 +969,9 @@ func (s *MergeRequestsService) GetTimeSpent(pid any, mergeRequest int, options . // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-a-merge-request-dependency type MergeRequestDependency struct { - ID int `json:"id"` + ID int64 `json:"id"` BlockingMergeRequest BlockingMergeRequest `json:"blocking_merge_request"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` } // BlockingMergeRequest represents a GitLab merge request dependency. @@ -1231,23 +979,23 @@ type MergeRequestDependency struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-a-merge-request-dependency type BlockingMergeRequest struct { - ID int `json:"id"` - Iid int `json:"iid"` + ID int64 `json:"id"` + Iid int64 `json:"iid"` TargetBranch string `json:"target_branch"` SourceBranch string `json:"source_branch"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` State string `json:"state"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` - Upvotes int `json:"upvotes"` - Downvotes int `json:"downvotes"` + Upvotes int64 `json:"upvotes"` + Downvotes int64 `json:"downvotes"` Author *BasicUser `json:"author"` Assignee *BasicUser `json:"assignee"` Assignees []*BasicUser `json:"assignees"` Reviewers []*BasicUser `json:"reviewers"` - SourceProjectID int `json:"source_project_id"` - TargetProjectID int `json:"target_project_id"` + SourceProjectID int64 `json:"source_project_id"` + TargetProjectID int64 `json:"target_project_id"` Labels *LabelOptions `json:"labels"` Description string `json:"description"` Draft bool `json:"draft"` @@ -1260,7 +1008,7 @@ type BlockingMergeRequest struct { Sha string `json:"sha"` MergeCommitSha string `json:"merge_commit_sha"` SquashCommitSha string `json:"squash_commit_sha"` - UserNotesCount int `json:"user_notes_count"` + UserNotesCount int64 `json:"user_notes_count"` ShouldRemoveSourceBranch *bool `json:"should_remove_source_branch"` ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` WebURL string `json:"web_url"` @@ -1285,7 +1033,7 @@ type BlockingMergeRequest struct { // Deprecated: will be removed in v5 of the API, use MergeUser instead MergedBy *BasicUser `json:"merged_by"` // Deprecated: will be removed in v5 of the API, use the Merge Request Approvals API instead - ApprovalsBeforeMerge *int `json:"approvals_before_merge"` + ApprovalsBeforeMerge *int64 `json:"approvals_before_merge"` // Deprecated: will be removed in v5 of the API, use References instead Reference string `json:"reference"` // Deprecated: in 15.6, use DetailedMergeStatus instead @@ -1302,7 +1050,7 @@ func (m MergeRequestDependency) String() string { // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-a-merge-request-dependency type CreateMergeRequestDependencyOptions struct { - BlockingMergeRequestID *int `url:"blocking_merge_request_id,omitempty" json:"blocking_merge_request_id,omitempty"` + BlockingMergeRequestID *int64 `url:"blocking_merge_request_id,omitempty" json:"blocking_merge_request_id,omitempty"` } // CreateMergeRequestDependency creates a new merge request dependency for a given @@ -1310,25 +1058,13 @@ type CreateMergeRequestDependencyOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#create-a-merge-request-dependency -func (s *MergeRequestsService) CreateMergeRequestDependency(pid any, mergeRequest int, opts CreateMergeRequestDependencyOptions, options ...RequestOptionFunc) (*MergeRequestDependency, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/blocks", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - var mrd MergeRequestDependency - resp, err := s.client.Do(req, &mrd) - if err != nil { - return nil, resp, err - } - - return &mrd, resp, err +func (s *MergeRequestsService) CreateMergeRequestDependency(pid any, mergeRequest int64, opts CreateMergeRequestDependencyOptions, options ...RequestOptionFunc) (*MergeRequestDependency, *Response, error) { + return do[*MergeRequestDependency](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/blocks", ProjectID{pid}, mergeRequest), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // DeleteMergeRequestDependency deletes a merge request dependency for a given @@ -1336,42 +1072,35 @@ func (s *MergeRequestsService) CreateMergeRequestDependency(pid any, mergeReques // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#delete-a-merge-request-dependency -func (s *MergeRequestsService) DeleteMergeRequestDependency(pid any, mergeRequest int, blockingMergeRequest int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/blocks/%d", PathEscape(project), mergeRequest, blockingMergeRequest) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *MergeRequestsService) DeleteMergeRequestDependency(pid any, mergeRequest int64, blockingMergeRequest int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/blocks/%d", ProjectID{pid}, mergeRequest, blockingMergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // GetMergeRequestDependencies gets a list of merge request dependencies. // // GitLab API docs: // https://docs.gitlab.com/api/merge_requests/#get-merge-request-dependencies -func (s *MergeRequestsService) GetMergeRequestDependencies(pid any, mergeRequest int, options ...RequestOptionFunc) ([]MergeRequestDependency, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/blocks", PathEscape(project), mergeRequest) +func (s *MergeRequestsService) GetMergeRequestDependencies(pid any, mergeRequest int64, options ...RequestOptionFunc) ([]MergeRequestDependency, *Response, error) { + return do[[]MergeRequestDependency](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_requests/%d/blocks", ProjectID{pid}, mergeRequest), + withAPIOpts(nil), + withRequestOpts(options...), + ) +} - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } +func toBasic(mrs []*MergeRequest) []*BasicMergeRequest { + ret := make([]*BasicMergeRequest, len(mrs)) - var mrd []MergeRequestDependency - resp, err := s.client.Do(req, &mrd) - if err != nil { - return nil, resp, err + for i, mr := range mrs { + ret[i] = &mr.BasicMergeRequest } - return mrd, resp, err + return ret } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/merge_trains.go b/vendor/gitlab.com/gitlab-org/api/client-go/merge_trains.go index 059612e1b..9d807fc3b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/merge_trains.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/merge_trains.go @@ -1,7 +1,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -10,8 +9,8 @@ type ( MergeTrainsServiceInterface interface { ListProjectMergeTrains(pid any, opt *ListMergeTrainsOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) ListMergeRequestInMergeTrain(pid any, targetBranch string, opts *ListMergeTrainsOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) - GetMergeRequestOnAMergeTrain(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeTrain, *Response, error) - AddMergeRequestToMergeTrain(pid any, mergeRequest int, opts *AddMergeRequestToMergeTrainOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) + GetMergeRequestOnAMergeTrain(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeTrain, *Response, error) + AddMergeRequestToMergeTrain(pid any, mergeRequest int64, opts *AddMergeRequestToMergeTrainOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) } // MergeTrainsService handles communication with the merge trains related @@ -25,11 +24,11 @@ type ( var _ MergeTrainsServiceInterface = (*MergeTrainsService)(nil) -// MergeTrain represents a Gitlab merge train. +// MergeTrain represents a GitLab merge train. // // GitLab API docs: https://docs.gitlab.com/api/merge_trains/ type MergeTrain struct { - ID int `json:"id"` + ID int64 `json:"id"` MergeRequest *MergeTrainMergeRequest `json:"merge_request"` User *BasicUser `json:"user"` Pipeline *Pipeline `json:"pipeline"` @@ -38,16 +37,16 @@ type MergeTrain struct { TargetBranch string `json:"target_branch"` Status string `json:"status"` MergedAt *time.Time `json:"merged_at"` - Duration int `json:"duration"` + Duration int64 `json:"duration"` } -// MergeTrainMergeRequest represents a Gitlab merge request inside merge train. +// MergeTrainMergeRequest represents a GitLab merge request inside merge train. // // GitLab API docs: https://docs.gitlab.com/api/merge_trains/ type MergeTrainMergeRequest struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` Description string `json:"description"` State string `json:"state"` @@ -71,24 +70,12 @@ type ListMergeTrainsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/merge_trains/#list-merge-trains-for-a-project func (s *MergeTrainsService) ListProjectMergeTrains(pid any, opt *ListMergeTrainsOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_trains", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mts []*MergeTrain - resp, err := s.client.Do(req, &mts) - if err != nil { - return nil, resp, err - } - - return mts, resp, nil + return do[[]*MergeTrain](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_trains", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListMergeRequestInMergeTrain gets a list of merge requests added to a merge @@ -97,24 +84,12 @@ func (s *MergeTrainsService) ListProjectMergeTrains(pid any, opt *ListMergeTrain // GitLab API docs: // https://docs.gitlab.com/api/merge_trains/#list-merge-requests-in-a-merge-train func (s *MergeTrainsService) ListMergeRequestInMergeTrain(pid any, targetBranch string, opts *ListMergeTrainsOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_trains/%s", PathEscape(project), targetBranch) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var mts []*MergeTrain - resp, err := s.client.Do(req, &mts) - if err != nil { - return nil, resp, err - } - - return mts, resp, nil + return do[[]*MergeTrain](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/merge_trains/%s", ProjectID{pid}, targetBranch), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // GetMergeRequestOnAMergeTrain Get merge train information for the requested @@ -122,25 +97,11 @@ func (s *MergeTrainsService) ListMergeRequestInMergeTrain(pid any, targetBranch // // GitLab API docs: // https://docs.gitlab.com/api/merge_trains/#get-the-status-of-a-merge-request-on-a-merge-train -func (s *MergeTrainsService) GetMergeRequestOnAMergeTrain(pid any, mergeRequest int, options ...RequestOptionFunc) (*MergeTrain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_trains/merge_requests/%d", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - mt := new(MergeTrain) - resp, err := s.client.Do(req, mt) - if err != nil { - return nil, resp, err - } - - return mt, resp, nil +func (s *MergeTrainsService) GetMergeRequestOnAMergeTrain(pid any, mergeRequest int64, options ...RequestOptionFunc) (*MergeTrain, *Response, error) { + return do[*MergeTrain](s.client, + withPath("projects/%s/merge_trains/merge_requests/%d", ProjectID{pid}, mergeRequest), + withRequestOpts(options...), + ) } // AddMergeRequestToMergeTrainOptions represents the available @@ -162,23 +123,11 @@ type AddMergeRequestToMergeTrainOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/merge_trains/#add-a-merge-request-to-a-merge-train -func (s *MergeTrainsService) AddMergeRequestToMergeTrain(pid any, mergeRequest int, opts *AddMergeRequestToMergeTrainOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_trains/merge_requests/%d", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - var mts []*MergeTrain - resp, err := s.client.Do(req, &mts) - if err != nil { - return nil, resp, err - } - - return mts, resp, nil +func (s *MergeTrainsService) AddMergeRequestToMergeTrain(pid any, mergeRequest int64, opts *AddMergeRequestToMergeTrainOptions, options ...RequestOptionFunc) ([]*MergeTrain, *Response, error) { + return do[[]*MergeTrain](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_trains/merge_requests/%d", ProjectID{pid}, mergeRequest), + withAPIOpts(opts), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/metadata.go b/vendor/gitlab.com/gitlab-org/api/client-go/metadata.go index 0a702f8e3..8a79cd392 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/metadata.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/metadata.go @@ -16,8 +16,6 @@ package gitlab -import "net/http" - type ( MetadataServiceInterface interface { GetMetadata(options ...RequestOptionFunc) (*Metadata, *Response, error) @@ -38,35 +36,36 @@ var _ MetadataServiceInterface = (*MetadataService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/metadata/ type Metadata struct { - Version string `json:"version"` - Revision string `json:"revision"` - KAS struct { - Enabled bool `json:"enabled"` - ExternalURL string `json:"externalUrl"` - ExternalK8SProxyURL string `json:"externalK8sProxyUrl"` - Version string `json:"version"` - } `json:"kas"` - Enterprise bool `json:"enterprise"` + Version string `json:"version"` + Revision string `json:"revision"` + KAS MetadataKAS `json:"kas"` + Enterprise bool `json:"enterprise"` } func (s Metadata) String() string { return Stringify(s) } -// GetMetadata gets a GitLab server instance meteadata. +// MetadataKAS represents a GitLab instance version metadata KAS. // // GitLab API docs: https://docs.gitlab.com/api/metadata/ -func (s *MetadataService) GetMetadata(options ...RequestOptionFunc) (*Metadata, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "metadata", nil, options) - if err != nil { - return nil, nil, err - } +type MetadataKAS struct { + Enabled bool `json:"enabled"` + ExternalURL string `json:"externalUrl"` + ExternalK8SProxyURL string `json:"externalK8sProxyUrl"` + Version string `json:"version"` +} - v := new(Metadata) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } +func (k MetadataKAS) String() string { + return Stringify(k) +} - return v, resp, nil +// GetMetadata gets a GitLab server instance meteadata. +// +// GitLab API docs: https://docs.gitlab.com/api/metadata/ +func (s *MetadataService) GetMetadata(options ...RequestOptionFunc) (*Metadata, *Response, error) { + return do[*Metadata](s.client, + withPath("metadata"), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/milestones.go b/vendor/gitlab.com/gitlab-org/api/client-go/milestones.go index 3bcf0657b..f416c6776 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/milestones.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/milestones.go @@ -17,20 +17,48 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( MilestonesServiceInterface interface { + // ListMilestones returns a list of project milestones. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#list-project-milestones ListMilestones(pid any, opt *ListMilestonesOptions, options ...RequestOptionFunc) ([]*Milestone, *Response, error) - GetMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Milestone, *Response, error) + // GetMilestone gets a single project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#get-single-milestone + GetMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Milestone, *Response, error) + // CreateMilestone creates a new project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#create-new-milestone CreateMilestone(pid any, opt *CreateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) - UpdateMilestone(pid any, milestone int, opt *UpdateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) - DeleteMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Response, error) - GetMilestoneIssues(pid any, milestone int, opt *GetMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) - GetMilestoneMergeRequests(pid any, milestone int, opt *GetMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) + // UpdateMilestone updates an existing project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#edit-milestone + UpdateMilestone(pid any, milestone int64, opt *UpdateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) + // DeleteMilestone deletes a specified project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#delete-project-milestone + DeleteMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Response, error) + // GetMilestoneIssues gets all issues assigned to a single project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#get-all-issues-assigned-to-a-single-milestone + GetMilestoneIssues(pid any, milestone int64, opt *GetMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) + // GetMilestoneMergeRequests gets all merge requests assigned to a single + // project milestone. + // + // GitLab API docs: + // https://docs.gitlab.com/api/milestones/#get-all-merge-requests-assigned-to-a-single-milestone + GetMilestoneMergeRequests(pid any, milestone int64, opt *GetMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) } // MilestonesService handles communication with the milestone related methods @@ -48,10 +76,10 @@ var _ MilestonesServiceInterface = (*MilestonesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/milestones/ type Milestone struct { - ID int `json:"id"` - IID int `json:"iid"` - GroupID int `json:"group_id"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + GroupID int64 `json:"group_id"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` Description string `json:"description"` StartDate *ISOTime `json:"start_date"` @@ -73,64 +101,29 @@ func (m Milestone) String() string { // https://docs.gitlab.com/api/milestones/#list-project-milestones type ListMilestonesOptions struct { ListOptions - IIDs *[]int `url:"iids[],omitempty" json:"iids,omitempty"` - Title *string `url:"title,omitempty" json:"title,omitempty"` - State *string `url:"state,omitempty" json:"state,omitempty"` - Search *string `url:"search,omitempty" json:"search,omitempty"` - IncludeAncestors *bool `url:"include_ancestors,omitempty" json:"include_ancestors,omitempty"` + IIDs *[]int64 `url:"iids[],omitempty" json:"iids,omitempty"` + Title *string `url:"title,omitempty" json:"title,omitempty"` + State *string `url:"state,omitempty" json:"state,omitempty"` + Search *string `url:"search,omitempty" json:"search,omitempty"` + IncludeAncestors *bool `url:"include_ancestors,omitempty" json:"include_ancestors,omitempty"` // Deprecated: in GitLab 16,7, use IncludeAncestors instead IncludeParentMilestones *bool `url:"include_parent_milestones,omitempty" json:"include_parent_milestones,omitempty"` } -// ListMilestones returns a list of project milestones. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#list-project-milestones func (s *MilestonesService) ListMilestones(pid any, opt *ListMilestonesOptions, options ...RequestOptionFunc) ([]*Milestone, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*Milestone - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil + return do[[]*Milestone](s.client, + withPath("projects/%s/milestones", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetMilestone gets a single project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#get-single-milestone -func (s *MilestonesService) GetMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Milestone, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones/%d", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - m := new(Milestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MilestonesService) GetMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Milestone, *Response, error) { + return do[*Milestone](s.client, + withPath("projects/%s/milestones/%d", ProjectID{pid}, milestone), + withRequestOpts(options...), + ) } // CreateMilestoneOptions represents the available CreateMilestone() options. @@ -144,29 +137,13 @@ type CreateMilestoneOptions struct { DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"` } -// CreateMilestone creates a new project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#create-new-milestone func (s *MilestonesService) CreateMilestone(pid any, opt *CreateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(Milestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil + return do[*Milestone](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/milestones", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateMilestoneOptions represents the available UpdateMilestone() options. @@ -181,78 +158,38 @@ type UpdateMilestoneOptions struct { StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"` } -// UpdateMilestone updates an existing project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#edit-milestone -func (s *MilestonesService) UpdateMilestone(pid any, milestone int, opt *UpdateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones/%d", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - m := new(Milestone) - resp, err := s.client.Do(req, m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *MilestonesService) UpdateMilestone(pid any, milestone int64, opt *UpdateMilestoneOptions, options ...RequestOptionFunc) (*Milestone, *Response, error) { + return do[*Milestone](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/milestones/%d", ProjectID{pid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteMilestone deletes a specified project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#delete-project-milestone -func (s *MilestonesService) DeleteMilestone(pid any, milestone int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/milestones/%d", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - return s.client.Do(req, nil) +func (s *MilestonesService) DeleteMilestone(pid any, milestone int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/milestones/%d", ProjectID{pid}, milestone), + withRequestOpts(options...), + ) + return resp, err } // GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options. // // GitLab API docs: // https://docs.gitlab.com/api/milestones/#get-all-issues-assigned-to-a-single-milestone -type GetMilestoneIssuesOptions ListOptions - -// GetMilestoneIssues gets all issues assigned to a single project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#get-all-issues-assigned-to-a-single-milestone -func (s *MilestonesService) GetMilestoneIssues(pid any, milestone int, opt *GetMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones/%d/issues", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var i []*Issue - resp, err := s.client.Do(req, &i) - if err != nil { - return nil, resp, err - } +type GetMilestoneIssuesOptions struct { + ListOptions +} - return i, resp, nil +func (s *MilestonesService) GetMilestoneIssues(pid any, milestone int64, opt *GetMilestoneIssuesOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { + return do[[]*Issue](s.client, + withPath("projects/%s/milestones/%d/issues", ProjectID{pid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMilestoneMergeRequestsOptions represents the available @@ -260,30 +197,14 @@ func (s *MilestonesService) GetMilestoneIssues(pid any, milestone int, opt *GetM // // GitLab API docs: // https://docs.gitlab.com/api/milestones/#get-all-merge-requests-assigned-to-a-single-milestone -type GetMilestoneMergeRequestsOptions ListOptions - -// GetMilestoneMergeRequests gets all merge requests assigned to a single -// project milestone. -// -// GitLab API docs: -// https://docs.gitlab.com/api/milestones/#get-all-merge-requests-assigned-to-a-single-milestone -func (s *MilestonesService) GetMilestoneMergeRequests(pid any, milestone int, opt *GetMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/milestones/%d/merge_requests", PathEscape(project), milestone) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mr []*BasicMergeRequest - resp, err := s.client.Do(req, &mr) - if err != nil { - return nil, resp, err - } +type GetMilestoneMergeRequestsOptions struct { + ListOptions +} - return mr, resp, nil +func (s *MilestonesService) GetMilestoneMergeRequests(pid any, milestone int64, opt *GetMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*BasicMergeRequest, *Response, error) { + return do[[]*BasicMergeRequest](s.client, + withPath("projects/%s/milestones/%d/merge_requests", ProjectID{pid}, milestone), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/model_registry.go b/vendor/gitlab.com/gitlab-org/api/client-go/model_registry.go new file mode 100644 index 000000000..876512b6e --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/model_registry.go @@ -0,0 +1,50 @@ +package gitlab + +import ( + "bytes" + "net/url" +) + +type ( + ModelRegistryServiceInterface interface { + DownloadMachineLearningModelPackage(pid, modelVersionID any, path string, filename string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + } + + // ModelRegistryService handles communication with the model registry related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/model_registry/ + ModelRegistryService struct { + client *Client + } +) + +var _ ModelRegistryServiceInterface = (*ModelRegistryService)(nil) + +// DownloadMachineLearningModelPackage downloads a machine learning model package file. +// +// GitLab API docs: https://docs.gitlab.com/api/model_registry/#download-a-model-package-file +func (s *ModelRegistryService) DownloadMachineLearningModelPackage(pid, modelVersionID any, path string, filename string, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { + // The modelVersionID can be an int or a string like "candidate:5", + // so we convert it to a string for the URL. + mvid, err := parseID(modelVersionID) + if err != nil { + return nil, nil, err + } + + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/packages/ml_models/%s/files/%s/%s", + ProjectID{pid}, + // the following URI components must not escape `.` which is what withPath does by default + // without NoEscape. + NoEscape{url.PathEscape(mvid)}, + NoEscape{url.PathEscape(path)}, + NoEscape{url.PathEscape(filename)}, + ), + withRequestOpts(options...), + ) + if err != nil { + return nil, resp, err + } + return bytes.NewReader(buf.Bytes()), resp, nil +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/namespaces.go b/vendor/gitlab.com/gitlab-org/api/client-go/namespaces.go index b4768551c..e9760bc1e 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/namespaces.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/namespaces.go @@ -16,11 +16,6 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( NamespacesServiceInterface interface { ListNamespaces(opt *ListNamespacesOptions, options ...RequestOptionFunc) ([]*Namespace, *Response, error) @@ -44,21 +39,21 @@ var _ NamespacesServiceInterface = (*NamespacesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/namespaces/ type Namespace struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Path string `json:"path"` Kind string `json:"kind"` FullPath string `json:"full_path"` - ParentID int `json:"parent_id"` + ParentID int64 `json:"parent_id"` AvatarURL *string `json:"avatar_url"` WebURL string `json:"web_url"` - MembersCountWithDescendants int `json:"members_count_with_descendants"` - BillableMembersCount int `json:"billable_members_count"` + MembersCountWithDescendants int64 `json:"members_count_with_descendants"` + BillableMembersCount int64 `json:"billable_members_count"` Plan string `json:"plan"` TrialEndsOn *ISOTime `json:"trial_ends_on"` Trial bool `json:"trial"` - MaxSeatsUsed *int `json:"max_seats_used"` - SeatsInUse *int `json:"seats_in_use"` + MaxSeatsUsed *int64 `json:"max_seats_used"` + SeatsInUse *int64 `json:"seats_in_use"` } func (n Namespace) String() string { @@ -79,18 +74,11 @@ type ListNamespacesOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/namespaces/#list-all-namespaces func (s *NamespacesService) ListNamespaces(opt *ListNamespacesOptions, options ...RequestOptionFunc) ([]*Namespace, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "namespaces", opt, options) - if err != nil { - return nil, nil, err - } - - var n []*Namespace - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil + return do[[]*Namespace](s.client, + withPath("namespaces"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // SearchNamespace gets all namespaces that match your string in their name @@ -104,18 +92,11 @@ func (s *NamespacesService) SearchNamespace(query string, options ...RequestOpti } q.Search = query - req, err := s.client.NewRequest(http.MethodGet, "namespaces", &q, options) - if err != nil { - return nil, nil, err - } - - var n []*Namespace - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil + return do[[]*Namespace](s.client, + withPath("namespaces"), + withAPIOpts(&q), + withRequestOpts(options...), + ) } // GetNamespace gets a namespace by id. @@ -127,20 +108,10 @@ func (s *NamespacesService) GetNamespace(id any, options ...RequestOptionFunc) ( if err != nil { return nil, nil, err } - u := fmt.Sprintf("namespaces/%s", PathEscape(namespace)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(Namespace) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil + return do[*Namespace](s.client, + withPath("namespaces/%s", namespace), + withRequestOpts(options...), + ) } // NamespaceExistance represents a namespace exists result. @@ -157,7 +128,7 @@ type NamespaceExistance struct { // GitLab API docs: // https://docs.gitlab.com/api/namespaces/#verify-namespace-availability type NamespaceExistsOptions struct { - ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` + ParentID *int64 `url:"parent_id,omitempty" json:"parent_id,omitempty"` } // NamespaceExists checks the existence of a namespace. @@ -169,18 +140,9 @@ func (s *NamespacesService) NamespaceExists(id any, opt *NamespaceExistsOptions, if err != nil { return nil, nil, err } - u := fmt.Sprintf("namespaces/%s/exists", namespace) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(NamespaceExistance) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil + return do[*NamespaceExistance](s.client, + withPath("namespaces/%s/exists", namespace), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/notes.go b/vendor/gitlab.com/gitlab-org/api/client-go/notes.go index b54b95019..e4dc2f0de 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/notes.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/notes.go @@ -17,33 +17,32 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( NotesServiceInterface interface { - ListIssueNotes(pid any, issue int, opt *ListIssueNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) - GetIssueNote(pid any, issue, note int, options ...RequestOptionFunc) (*Note, *Response, error) - CreateIssueNote(pid any, issue int, opt *CreateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateIssueNote(pid any, issue, note int, opt *UpdateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteIssueNote(pid any, issue, note int, options ...RequestOptionFunc) (*Response, error) - ListSnippetNotes(pid any, snippet int, opt *ListSnippetNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) - GetSnippetNote(pid any, snippet, note int, options ...RequestOptionFunc) (*Note, *Response, error) - CreateSnippetNote(pid any, snippet int, opt *CreateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateSnippetNote(pid any, snippet, note int, opt *UpdateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteSnippetNote(pid any, snippet, note int, options ...RequestOptionFunc) (*Response, error) - ListMergeRequestNotes(pid any, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) - GetMergeRequestNote(pid any, mergeRequest, note int, options ...RequestOptionFunc) (*Note, *Response, error) - CreateMergeRequestNote(pid any, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateMergeRequestNote(pid any, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteMergeRequestNote(pid any, mergeRequest, note int, options ...RequestOptionFunc) (*Response, error) - ListEpicNotes(gid any, epic int, opt *ListEpicNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) - GetEpicNote(gid any, epic, note int, options ...RequestOptionFunc) (*Note, *Response, error) - CreateEpicNote(gid any, epic int, opt *CreateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - UpdateEpicNote(gid any, epic, note int, opt *UpdateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) - DeleteEpicNote(gid any, epic, note int, options ...RequestOptionFunc) (*Response, error) + ListIssueNotes(pid any, issue int64, opt *ListIssueNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) + GetIssueNote(pid any, issue, note int64, options ...RequestOptionFunc) (*Note, *Response, error) + CreateIssueNote(pid any, issue int64, opt *CreateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + UpdateIssueNote(pid any, issue, note int64, opt *UpdateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + DeleteIssueNote(pid any, issue, note int64, options ...RequestOptionFunc) (*Response, error) + ListSnippetNotes(pid any, snippet int64, opt *ListSnippetNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) + GetSnippetNote(pid any, snippet, note int64, options ...RequestOptionFunc) (*Note, *Response, error) + CreateSnippetNote(pid any, snippet int64, opt *CreateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + UpdateSnippetNote(pid any, snippet, note int64, opt *UpdateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + DeleteSnippetNote(pid any, snippet, note int64, options ...RequestOptionFunc) (*Response, error) + ListMergeRequestNotes(pid any, mergeRequest int64, opt *ListMergeRequestNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) + GetMergeRequestNote(pid any, mergeRequest, note int64, options ...RequestOptionFunc) (*Note, *Response, error) + CreateMergeRequestNote(pid any, mergeRequest int64, opt *CreateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + UpdateMergeRequestNote(pid any, mergeRequest, note int64, opt *UpdateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + DeleteMergeRequestNote(pid any, mergeRequest, note int64, options ...RequestOptionFunc) (*Response, error) + ListEpicNotes(gid any, epic int64, opt *ListEpicNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) + GetEpicNote(gid any, epic, note int64, options ...RequestOptionFunc) (*Note, *Response, error) + CreateEpicNote(gid any, epic int64, opt *CreateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + UpdateEpicNote(gid any, epic, note int64, opt *UpdateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) + DeleteEpicNote(gid any, epic, note int64, options ...RequestOptionFunc) (*Response, error) } // NotesService handles communication with the notes related methods @@ -63,44 +62,50 @@ var _ NotesServiceInterface = (*NotesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/notes/ type Note struct { - ID int `json:"id"` - Type NoteTypeValue `json:"type"` - Body string `json:"body"` - Attachment string `json:"attachment"` - Title string `json:"title"` - FileName string `json:"file_name"` - Author NoteAuthor `json:"author"` - System bool `json:"system"` - CreatedAt *time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at"` - ExpiresAt *time.Time `json:"expires_at"` - CommitID string `json:"commit_id"` - Position *NotePosition `json:"position"` - NoteableID int `json:"noteable_id"` - NoteableType string `json:"noteable_type"` - ProjectID int `json:"project_id"` - NoteableIID int `json:"noteable_iid"` - Resolvable bool `json:"resolvable"` - Resolved bool `json:"resolved"` - ResolvedAt *time.Time `json:"resolved_at"` - ResolvedBy struct { - ID int `json:"id"` - Username string `json:"username"` - Email string `json:"email"` - Name string `json:"name"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"resolved_by"` - Internal bool `json:"internal"` + ID int64 `json:"id"` + Type NoteTypeValue `json:"type"` + Body string `json:"body"` + Attachment string `json:"attachment"` + Title string `json:"title"` + FileName string `json:"file_name"` + Author NoteAuthor `json:"author"` + System bool `json:"system"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + ExpiresAt *time.Time `json:"expires_at"` + CommitID string `json:"commit_id"` + Position *NotePosition `json:"position"` + NoteableID int64 `json:"noteable_id"` + NoteableType string `json:"noteable_type"` + ProjectID int64 `json:"project_id"` + NoteableIID int64 `json:"noteable_iid"` + Resolvable bool `json:"resolvable"` + Resolved bool `json:"resolved"` + ResolvedAt *time.Time `json:"resolved_at"` + ResolvedBy NoteResolvedBy `json:"resolved_by"` + Internal bool `json:"internal"` // Deprecated: use Internal instead Confidential bool `json:"confidential"` } +// NoteResolvedBy represents the resolver of a GitLab note. +// +// GitLab API docs: +// https://docs.gitlab.com/api/notes/ +type NoteResolvedBy struct { + ID int64 `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + AvatarURL string `json:"avatar_url"` + WebURL string `json:"web_url"` +} + // NoteAuthor represents the author of a note. type NoteAuthor struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Email string `json:"email"` Name string `json:"name"` @@ -116,9 +121,9 @@ type NotePosition struct { HeadSHA string `json:"head_sha"` PositionType string `json:"position_type"` NewPath string `json:"new_path,omitempty"` - NewLine int `json:"new_line,omitempty"` + NewLine int64 `json:"new_line,omitempty"` OldPath string `json:"old_path,omitempty"` - OldLine int `json:"old_line,omitempty"` + OldLine int64 `json:"old_line,omitempty"` LineRange *LineRange `json:"line_range,omitempty"` } @@ -132,8 +137,8 @@ type LineRange struct { type LinePosition struct { LineCode string `json:"line_code"` Type string `json:"type"` - OldLine int `json:"old_line"` - NewLine int `json:"new_line"` + OldLine int64 `json:"old_line"` + NewLine int64 `json:"new_line"` } func (n Note) String() string { @@ -154,50 +159,23 @@ type ListIssueNotesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#list-project-issue-notes -func (s *NotesService) ListIssueNotes(pid any, issue int, opt *ListIssueNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/notes", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var n []*Note - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) ListIssueNotes(pid any, issue int64, opt *ListIssueNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { + return do[[]*Note](s.client, + withPath("projects/%s/issues/%d/notes", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueNote returns a single note for a specific project issue. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#get-single-issue-note -func (s *NotesService) GetIssueNote(pid any, issue, note int, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", PathEscape(project), issue, note) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) GetIssueNote(pid any, issue, note int64, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withPath("projects/%s/issues/%d/notes/%d", ProjectID{pid}, issue, note), + withRequestOpts(options...), + ) } // CreateIssueNoteOptions represents the available CreateIssueNote() @@ -215,25 +193,13 @@ type CreateIssueNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#create-new-issue-note -func (s *NotesService) CreateIssueNote(pid any, issue int, opt *CreateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/notes", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) CreateIssueNote(pid any, issue int64, opt *CreateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/issues/%d/notes", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateIssueNoteOptions represents the available UpdateIssueNote() @@ -249,44 +215,26 @@ type UpdateIssueNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#modify-existing-issue-note -func (s *NotesService) UpdateIssueNote(pid any, issue, note int, opt *UpdateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", PathEscape(project), issue, note) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) UpdateIssueNote(pid any, issue, note int64, opt *UpdateIssueNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/issues/%d/notes/%d", ProjectID{pid}, issue, note), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteIssueNote deletes an existing note of an issue. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#delete-an-issue-note -func (s *NotesService) DeleteIssueNote(pid any, issue, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", PathEscape(project), issue, note) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *NotesService) DeleteIssueNote(pid any, issue, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/issues/%d/notes/%d", ProjectID{pid}, issue, note), + withRequestOpts(options...), + ) + return resp, err } // ListSnippetNotesOptions represents the available ListSnippetNotes() options. @@ -304,50 +252,23 @@ type ListSnippetNotesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#list-all-snippet-notes -func (s *NotesService) ListSnippetNotes(pid any, snippet int, opt *ListSnippetNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/notes", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var n []*Note - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) ListSnippetNotes(pid any, snippet int64, opt *ListSnippetNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { + return do[[]*Note](s.client, + withPath("projects/%s/snippets/%d/notes", ProjectID{pid}, snippet), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetSnippetNote returns a single note for a given snippet. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#get-single-snippet-note -func (s *NotesService) GetSnippetNote(pid any, snippet, note int, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", PathEscape(project), snippet, note) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) GetSnippetNote(pid any, snippet, note int64, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withPath("projects/%s/snippets/%d/notes/%d", ProjectID{pid}, snippet, note), + withRequestOpts(options...), + ) } // CreateSnippetNoteOptions represents the available CreateSnippetNote() @@ -365,25 +286,13 @@ type CreateSnippetNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#create-new-snippet-note -func (s *NotesService) CreateSnippetNote(pid any, snippet int, opt *CreateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/notes", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) CreateSnippetNote(pid any, snippet int64, opt *CreateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/snippets/%d/notes", ProjectID{pid}, snippet), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateSnippetNoteOptions represents the available UpdateSnippetNote() @@ -399,44 +308,26 @@ type UpdateSnippetNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#modify-existing-snippet-note -func (s *NotesService) UpdateSnippetNote(pid any, snippet, note int, opt *UpdateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", PathEscape(project), snippet, note) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) UpdateSnippetNote(pid any, snippet, note int64, opt *UpdateSnippetNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/snippets/%d/notes/%d", ProjectID{pid}, snippet, note), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteSnippetNote deletes an existing note of a snippet. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#delete-a-snippet-note -func (s *NotesService) DeleteSnippetNote(pid any, snippet, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", PathEscape(project), snippet, note) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *NotesService) DeleteSnippetNote(pid any, snippet, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/snippets/%d/notes/%d", ProjectID{pid}, snippet, note), + withRequestOpts(options...), + ) + return resp, err } // ListMergeRequestNotesOptions represents the available ListMergeRequestNotes() @@ -454,50 +345,23 @@ type ListMergeRequestNotesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#list-all-merge-request-notes -func (s *NotesService) ListMergeRequestNotes(pid any, mergeRequest int, opt *ListMergeRequestNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var n []*Note - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) ListMergeRequestNotes(pid any, mergeRequest int64, opt *ListMergeRequestNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { + return do[[]*Note](s.client, + withPath("projects/%s/merge_requests/%d/notes", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestNote returns a single note for a given merge request. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#get-single-merge-request-note -func (s *NotesService) GetMergeRequestNote(pid any, mergeRequest, note int, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) GetMergeRequestNote(pid any, mergeRequest, note int64, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withPath("projects/%s/merge_requests/%d/notes/%d", ProjectID{pid}, mergeRequest, note), + withRequestOpts(options...), + ) } // CreateMergeRequestNoteOptions represents the available @@ -516,25 +380,13 @@ type CreateMergeRequestNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#create-new-merge-request-note -func (s *NotesService) CreateMergeRequestNote(pid any, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", PathEscape(project), mergeRequest) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) CreateMergeRequestNote(pid any, mergeRequest int64, opt *CreateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/merge_requests/%d/notes", ProjectID{pid}, mergeRequest), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateMergeRequestNoteOptions represents the available @@ -550,45 +402,26 @@ type UpdateMergeRequestNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#modify-existing-merge-request-note -func (s *NotesService) UpdateMergeRequestNote(pid any, mergeRequest, note int, opt *UpdateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/merge_requests/%d/notes/%d", PathEscape(project), mergeRequest, note) - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) UpdateMergeRequestNote(pid any, mergeRequest, note int64, opt *UpdateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/merge_requests/%d/notes/%d", ProjectID{pid}, mergeRequest, note), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMergeRequestNote deletes an existing note of a merge request. // // GitLab API docs: // https://docs.gitlab.com/api/notes/#delete-a-merge-request-note -func (s *NotesService) DeleteMergeRequestNote(pid any, mergeRequest, note int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf( - "projects/%s/merge_requests/%d/notes/%d", PathEscape(project), mergeRequest, note) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *NotesService) DeleteMergeRequestNote(pid any, mergeRequest, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/merge_requests/%d/notes/%d", ProjectID{pid}, mergeRequest, note), + withRequestOpts(options...), + ) + return resp, err } // ListEpicNotesOptions represents the available ListEpicNotes() options. @@ -607,25 +440,12 @@ type ListEpicNotesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#list-all-epic-notes -func (s *NotesService) ListEpicNotes(gid any, epic int, opt *ListEpicNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/notes", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var n []*Note - resp, err := s.client.Do(req, &n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) ListEpicNotes(gid any, epic int64, opt *ListEpicNotesOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { + return do[[]*Note](s.client, + withPath("groups/%s/epics/%d/notes", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetEpicNote returns a single note for an epic. @@ -633,25 +453,11 @@ func (s *NotesService) ListEpicNotes(gid any, epic int, opt *ListEpicNotesOption // // GitLab API docs: // https://docs.gitlab.com/api/notes/#get-single-epic-note -func (s *NotesService) GetEpicNote(gid any, epic, note int, options ...RequestOptionFunc) (*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", PathEscape(group), epic, note) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) GetEpicNote(gid any, epic, note int64, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withPath("groups/%s/epics/%d/notes/%d", GroupID{gid}, epic, note), + withRequestOpts(options...), + ) } // CreateEpicNoteOptions represents the available CreateEpicNote() options. @@ -668,25 +474,13 @@ type CreateEpicNoteOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/notes/#create-new-epic-note -func (s *NotesService) CreateEpicNote(gid any, epic int, opt *CreateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/notes", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) CreateEpicNote(gid any, epic int64, opt *CreateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/epics/%d/notes", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateEpicNoteOptions represents the available UpdateEpicNote() options. @@ -702,42 +496,24 @@ type UpdateEpicNoteOptions struct { // Will be removed in v5 of the API, use Work Items API instead // // https://docs.gitlab.com/api/notes/#modify-existing-epic-note -func (s *NotesService) UpdateEpicNote(gid any, epic, note int, opt *UpdateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", PathEscape(group), epic, note) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - n := new(Note) - resp, err := s.client.Do(req, n) - if err != nil { - return nil, resp, err - } - - return n, resp, nil +func (s *NotesService) UpdateEpicNote(gid any, epic, note int64, opt *UpdateEpicNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) { + return do[*Note](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/epics/%d/notes/%d", GroupID{gid}, epic, note), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteEpicNote deletes an existing note of a merge request. // Will be removed in v5 of the API, use Work Items API instead // // https://docs.gitlab.com/api/notes/#delete-an-epic-note -func (s *NotesService) DeleteEpicNote(gid any, epic, note int, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/notes/%d", PathEscape(group), epic, note) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *NotesService) DeleteEpicNote(gid any, epic, note int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("groups/%s/epics/%d/notes/%d", GroupID{gid}, epic, note), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/notifications.go b/vendor/gitlab.com/gitlab-org/api/client-go/notifications.go index 539600f3c..5f95f6cba 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/notifications.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/notifications.go @@ -18,17 +18,40 @@ package gitlab import ( "errors" - "fmt" "net/http" ) type ( NotificationSettingsServiceInterface interface { + // GetGlobalSettings returns current notification settings and email address. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#global-notification-settings GetGlobalSettings(options ...RequestOptionFunc) (*NotificationSettings, *Response, error) + // UpdateGlobalSettings updates current notification settings and email address. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#update-global-notification-settings UpdateGlobalSettings(opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) + // GetSettingsForGroup returns current group notification settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#group--project-level-notification-settings GetSettingsForGroup(gid any, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) + // GetSettingsForProject returns current project notification settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#group--project-level-notification-settings GetSettingsForProject(pid any, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) + // UpdateSettingsForGroup updates current group notification settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#update-groupproject-level-notification-settings UpdateSettingsForGroup(gid any, opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) + // UpdateSettingsForProject updates current project notification settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/notification_settings/#update-groupproject-level-notification-settings UpdateSettingsForProject(pid any, opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) } @@ -43,7 +66,7 @@ type ( var _ NotificationSettingsServiceInterface = (*NotificationSettingsService)(nil) -// NotificationSettings represents the Gitlab notification setting. +// NotificationSettings represents the GitLab notification setting. // // GitLab API docs: // https://docs.gitlab.com/api/notification_settings/#valid-notification-levels @@ -82,25 +105,11 @@ func (ns NotificationSettings) String() string { return Stringify(ns) } -// GetGlobalSettings returns current notification settings and email address. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#global-notification-settings func (s *NotificationSettingsService) GetGlobalSettings(options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { - u := "notification_settings" - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withPath("notification_settings"), + withRequestOpts(options...), + ) } // NotificationSettingsOptions represents the available options that can be passed @@ -128,128 +137,48 @@ type NotificationSettingsOptions struct { SuccessPipeline *bool `url:"success_pipeline,omitempty" json:"success_pipeline,omitempty"` } -// UpdateGlobalSettings updates current notification settings and email address. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#update-global-notification-settings func (s *NotificationSettingsService) UpdateGlobalSettings(opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { if opt.Level != nil && *opt.Level == GlobalNotificationLevel { return nil, nil, errors.New( "notification level 'global' is not valid for global notification settings") } - u := "notification_settings" - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withMethod(http.MethodPut), + withPath("notification_settings"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetSettingsForGroup returns current group notification settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#group--project-level-notification-settings func (s *NotificationSettingsService) GetSettingsForGroup(gid any, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/notification_settings", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withPath("groups/%s/notification_settings", GroupID{gid}), + withRequestOpts(options...), + ) } -// GetSettingsForProject returns current project notification settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#group--project-level-notification-settings func (s *NotificationSettingsService) GetSettingsForProject(pid any, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/notification_settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withPath("projects/%s/notification_settings", ProjectID{pid}), + withRequestOpts(options...), + ) } -// UpdateSettingsForGroup updates current group notification settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#update-groupproject-level-notification-settings func (s *NotificationSettingsService) UpdateSettingsForGroup(gid any, opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/notification_settings", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withMethod(http.MethodPut), + withPath("groups/%s/notification_settings", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// UpdateSettingsForProject updates current project notification settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/notification_settings/#update-groupproject-level-notification-settings func (s *NotificationSettingsService) UpdateSettingsForProject(pid any, opt *NotificationSettingsOptions, options ...RequestOptionFunc) (*NotificationSettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/notification_settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ns := new(NotificationSettings) - resp, err := s.client.Do(req, ns) - if err != nil { - return nil, resp, err - } - - return ns, resp, nil + return do[*NotificationSettings](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/notification_settings", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/packages.go b/vendor/gitlab.com/gitlab-org/api/client-go/packages.go index f9f3b59af..57e8eee16 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/packages.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/packages.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -26,9 +25,9 @@ type ( PackagesServiceInterface interface { ListProjectPackages(pid any, opt *ListProjectPackagesOptions, options ...RequestOptionFunc) ([]*Package, *Response, error) ListGroupPackages(gid any, opt *ListGroupPackagesOptions, options ...RequestOptionFunc) ([]*GroupPackage, *Response, error) - ListPackageFiles(pid any, pkg int, opt *ListPackageFilesOptions, options ...RequestOptionFunc) ([]*PackageFile, *Response, error) - DeleteProjectPackage(pid any, pkg int, options ...RequestOptionFunc) (*Response, error) - DeletePackageFile(pid any, pkg, file int, options ...RequestOptionFunc) (*Response, error) + ListPackageFiles(pid any, pkg int64, opt *ListPackageFilesOptions, options ...RequestOptionFunc) ([]*PackageFile, *Response, error) + DeleteProjectPackage(pid any, pkg int64, options ...RequestOptionFunc) (*Response, error) + DeletePackageFile(pid any, pkg, file int64, options ...RequestOptionFunc) (*Response, error) } // PackagesService handles communication with the packages related methods @@ -46,7 +45,7 @@ var _ PackagesServiceInterface = (*PackagesService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/packages/ type Package struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Version string `json:"version"` PackageType string `json:"package_type"` @@ -66,7 +65,7 @@ func (s Package) String() string { // GitLab API docs: https://docs.gitlab.com/api/packages/ type GroupPackage struct { Package - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` ProjectPath string `json:"project_path"` } @@ -86,8 +85,8 @@ func (s PackageLinks) String() string { // PackageTag holds label information about the package type PackageTag struct { - ID int `json:"id"` - PackageID int `json:"package_id"` + ID int64 `json:"id"` + PackageID int64 `json:"package_id"` Name string `json:"name"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` @@ -101,11 +100,11 @@ func (s PackageTag) String() string { // // GitLab API docs: https://docs.gitlab.com/api/packages/ type PackageFile struct { - ID int `json:"id"` - PackageID int `json:"package_id"` + ID int64 `json:"id"` + PackageID int64 `json:"package_id"` CreatedAt *time.Time `json:"created_at"` FileName string `json:"file_name"` - Size int `json:"size"` + Size int64 `json:"size"` FileMD5 string `json:"file_md5"` FileSHA1 string `json:"file_sha1"` FileSHA256 string `json:"file_sha256"` @@ -137,24 +136,11 @@ type ListProjectPackagesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/packages/#for-a-project func (s *PackagesService) ListProjectPackages(pid any, opt *ListProjectPackagesOptions, options ...RequestOptionFunc) ([]*Package, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/packages", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Package - resp, err := s.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*Package](s.client, + withPath("projects/%s/packages", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListGroupPackagesOptions represents the available ListGroupPackages() @@ -178,24 +164,11 @@ type ListGroupPackagesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/packages/#for-a-group func (s *PackagesService) ListGroupPackages(gid any, opt *ListGroupPackagesOptions, options ...RequestOptionFunc) ([]*GroupPackage, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/packages", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*GroupPackage - resp, err := s.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*GroupPackage](s.client, + withPath("groups/%s/packages", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListPackageFilesOptions represents the available ListPackageFiles() @@ -203,71 +176,44 @@ func (s *PackagesService) ListGroupPackages(gid any, opt *ListGroupPackagesOptio // // GitLab API docs: // https://docs.gitlab.com/api/packages/#list-package-files -type ListPackageFilesOptions ListOptions +type ListPackageFilesOptions struct { + ListOptions +} // ListPackageFiles gets a list of files that are within a package // // GitLab API docs: // https://docs.gitlab.com/api/packages/#list-package-files -func (s *PackagesService) ListPackageFiles(pid any, pkg int, opt *ListPackageFilesOptions, options ...RequestOptionFunc) ([]*PackageFile, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/packages/%d/package_files", - PathEscape(project), - pkg, +func (s *PackagesService) ListPackageFiles(pid any, pkg int64, opt *ListPackageFilesOptions, options ...RequestOptionFunc) ([]*PackageFile, *Response, error) { + return do[[]*PackageFile](s.client, + withPath("projects/%s/packages/%d/package_files", ProjectID{pid}, pkg), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pfs []*PackageFile - resp, err := s.client.Do(req, &pfs) - if err != nil { - return nil, resp, err - } - - return pfs, resp, nil } // DeleteProjectPackage deletes a package in a project. // // GitLab API docs: // https://docs.gitlab.com/api/packages/#delete-a-project-package -func (s *PackagesService) DeleteProjectPackage(pid any, pkg int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/packages/%d", PathEscape(project), pkg) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PackagesService) DeleteProjectPackage(pid any, pkg int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/packages/%d", ProjectID{pid}, pkg), + withRequestOpts(options...), + ) + return resp, err } // DeletePackageFile deletes a file in project package // // GitLab API docs: // https://docs.gitlab.com/api/packages/#delete-a-package-file -func (s *PackagesService) DeletePackageFile(pid any, pkg, file int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/packages/%d/package_files/%d", PathEscape(project), pkg, file) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PackagesService) DeletePackageFile(pid any, pkg, file int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/packages/%d/package_files/%d", ProjectID{pid}, pkg, file), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pages.go b/vendor/gitlab.com/gitlab-org/api/client-go/pages.go index baffb2559..3b80328ce 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pages.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pages.go @@ -17,15 +17,28 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( PagesServiceInterface interface { + // UnpublishPages unpublishes pages. The user must have admin privileges. + // + // GitLab API docs: + // https://docs.gitlab.com/api/pages/#unpublish-pages UnpublishPages(gid any, options ...RequestOptionFunc) (*Response, error) + // GetPages lists Pages settings for a project. The user must have at least + // maintainer privileges. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/pages/#get-pages-settings-for-a-project GetPages(gid any, options ...RequestOptionFunc) (*Pages, *Response, error) + // UpdatePages updates Pages settings for a project. The user must have + // administrator privileges. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/pages/#update-pages-settings-for-a-project UpdatePages(pid any, opt UpdatePagesOptions, options ...RequestOptionFunc) (*Pages, *Response, error) } @@ -48,6 +61,7 @@ type Pages struct { IsUniqueDomainEnabled bool `json:"is_unique_domain_enabled"` ForceHTTPS bool `json:"force_https"` Deployments []*PagesDeployment `json:"deployments"` + PrimaryDomain string `json:"primary_domain"` } // PagesDeployment represents a Pages deployment. @@ -60,49 +74,20 @@ type PagesDeployment struct { RootDirectory string `json:"root_directory"` } -// UnpublishPages unpublished pages. The user must have admin privileges. -// -// GitLab API docs: -// https://docs.gitlab.com/api/pages/#unpublish-pages func (s *PagesService) UnpublishPages(gid any, options ...RequestOptionFunc) (*Response, error) { - page, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/pages", PathEscape(page)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/pages", ProjectID{gid}), + withRequestOpts(options...), + ) + return resp, err } -// GetPages lists Pages settings for a project. The user must have at least -// maintainer privileges. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/pages/#get-pages-settings-for-a-project func (s *PagesService) GetPages(gid any, options ...RequestOptionFunc) (*Pages, *Response, error) { - project, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Pages) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Pages](s.client, + withPath("projects/%s/pages", ProjectID{gid}), + withRequestOpts(options...), + ) } // UpdatePagesOptions represents the available UpdatePages() options. @@ -110,32 +95,16 @@ func (s *PagesService) GetPages(gid any, options ...RequestOptionFunc) (*Pages, // GitLab API docs: // https://docs.gitlab.com/api/pages/#update-pages-settings-for-a-project type UpdatePagesOptions struct { - PagesUniqueDomainEnabled *bool `url:"pages_unique_domain_enabled,omitempty" json:"pages_unique_domain_enabled,omitempty"` - PagesHTTPSOnly *bool `url:"pages_https_only,omitempty" json:"pages_https_only,omitempty"` + PagesUniqueDomainEnabled *bool `url:"pages_unique_domain_enabled,omitempty" json:"pages_unique_domain_enabled,omitempty"` + PagesHTTPSOnly *bool `url:"pages_https_only,omitempty" json:"pages_https_only,omitempty"` + PagesPrimaryDomain *string `url:"pages_primary_domain,omitempty" json:"pages_primary_domain,omitempty"` } -// UpdatePages updates Pages settings for a project. The user must have -// administrator privileges. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/pages/#update-pages-settings-for-a-project func (s *PagesService) UpdatePages(pid any, opt UpdatePagesOptions, options ...RequestOptionFunc) (*Pages, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Pages) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Pages](s.client, + withMethod(http.MethodPatch), + withPath("projects/%s/pages", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pages_domains.go b/vendor/gitlab.com/gitlab-org/api/client-go/pages_domains.go index de18e4830..745dd3d00 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pages_domains.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pages_domains.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -47,51 +46,45 @@ var _ PagesDomainsServiceInterface = (*PagesDomainsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/pages_domains/ type PagesDomain struct { - Domain string `json:"domain"` - AutoSslEnabled bool `json:"auto_ssl_enabled"` - URL string `json:"url"` - ProjectID int `json:"project_id"` - Verified bool `json:"verified"` - VerificationCode string `json:"verification_code"` - EnabledUntil *time.Time `json:"enabled_until"` - Certificate struct { - Subject string `json:"subject"` - Expired bool `json:"expired"` - Expiration *time.Time `json:"expiration"` - Certificate string `json:"certificate"` - CertificateText string `json:"certificate_text"` - } `json:"certificate"` + Domain string `json:"domain"` + AutoSslEnabled bool `json:"auto_ssl_enabled"` + URL string `json:"url"` + ProjectID int64 `json:"project_id"` + Verified bool `json:"verified"` + VerificationCode string `json:"verification_code"` + EnabledUntil *time.Time `json:"enabled_until"` + Certificate PagesDomainCertificate `json:"certificate"` +} + +// PagesDomainCertificate represents a pages domain certificate. +// +// GitLab API docs: https://docs.gitlab.com/api/pages_domains/ +type PagesDomainCertificate struct { + Subject string `json:"subject"` + Expired bool `json:"expired"` + Expiration *time.Time `json:"expiration"` + Certificate string `json:"certificate"` + CertificateText string `json:"certificate_text"` } // ListPagesDomainsOptions represents the available ListPagesDomains() options. // // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#list-pages-domains -type ListPagesDomainsOptions ListOptions +type ListPagesDomainsOptions struct { + ListOptions +} // ListPagesDomains gets a list of project pages domains. // // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#list-pages-domains func (s *PagesDomainsService) ListPagesDomains(pid any, opt *ListPagesDomainsOptions, options ...RequestOptionFunc) ([]*PagesDomain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages/domains", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pd []*PagesDomain - resp, err := s.client.Do(req, &pd) - if err != nil { - return nil, resp, err - } - - return pd, resp, nil + return do[[]*PagesDomain](s.client, + withPath("projects/%s/pages/domains", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListAllPagesDomains gets a list of all pages domains. @@ -99,18 +92,10 @@ func (s *PagesDomainsService) ListPagesDomains(pid any, opt *ListPagesDomainsOpt // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#list-all-pages-domains func (s *PagesDomainsService) ListAllPagesDomains(options ...RequestOptionFunc) ([]*PagesDomain, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "pages/domains", nil, options) - if err != nil { - return nil, nil, err - } - - var pd []*PagesDomain - resp, err := s.client.Do(req, &pd) - if err != nil { - return nil, resp, err - } - - return pd, resp, nil + return do[[]*PagesDomain](s.client, + withPath("pages/domains"), + withRequestOpts(options...), + ) } // GetPagesDomain get a specific pages domain for a project. @@ -118,24 +103,10 @@ func (s *PagesDomainsService) ListAllPagesDomains(options ...RequestOptionFunc) // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#single-pages-domain func (s *PagesDomainsService) GetPagesDomain(pid any, domain string, options ...RequestOptionFunc) (*PagesDomain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages/domains/%s", PathEscape(project), domain) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pd := new(PagesDomain) - resp, err := s.client.Do(req, pd) - if err != nil { - return nil, resp, err - } - - return pd, resp, nil + return do[*PagesDomain](s.client, + withPath("projects/%s/pages/domains/%s", ProjectID{pid}, domain), + withRequestOpts(options...), + ) } // CreatePagesDomainOptions represents the available CreatePagesDomain() options. @@ -154,24 +125,12 @@ type CreatePagesDomainOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#create-new-pages-domain func (s *PagesDomainsService) CreatePagesDomain(pid any, opt *CreatePagesDomainOptions, options ...RequestOptionFunc) (*PagesDomain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages/domains", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pd := new(PagesDomain) - resp, err := s.client.Do(req, pd) - if err != nil { - return nil, resp, err - } - - return pd, resp, nil + return do[*PagesDomain](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pages/domains", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdatePagesDomainOptions represents the available UpdatePagesDomain() options. @@ -189,24 +148,12 @@ type UpdatePagesDomainOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#update-pages-domain func (s *PagesDomainsService) UpdatePagesDomain(pid any, domain string, opt *UpdatePagesDomainOptions, options ...RequestOptionFunc) (*PagesDomain, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pages/domains/%s", PathEscape(project), domain) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pd := new(PagesDomain) - resp, err := s.client.Do(req, pd) - if err != nil { - return nil, resp, err - } - - return pd, resp, nil + return do[*PagesDomain](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/pages/domains/%s", ProjectID{pid}, domain), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeletePagesDomain deletes an existing project pages domain. @@ -214,16 +161,10 @@ func (s *PagesDomainsService) UpdatePagesDomain(pid any, domain string, opt *Upd // GitLab API docs: // https://docs.gitlab.com/api/pages_domains/#delete-pages-domain func (s *PagesDomainsService) DeletePagesDomain(pid any, domain string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/pages/domains/%s", PathEscape(project), domain) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/pages/domains/%s", ProjectID{pid}, domain), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pagination.go b/vendor/gitlab.com/gitlab-org/api/client-go/pagination.go index 8214e84e3..47dde6ba4 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pagination.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pagination.go @@ -1,12 +1,8 @@ -//go:build go1.23 -// +build go1.23 - package gitlab import ( "fmt" "iter" - "slices" ) type PaginationOptionFunc = RequestOptionFunc @@ -102,11 +98,11 @@ func Scan[T any](f func(p PaginationOptionFunc) ([]T, *Response, error)) (iter.S // Attention: This API is experimental and may be subject to breaking changes to improve the API in the future. func Scan2[T any](f func(p PaginationOptionFunc) ([]T, *Response, error)) iter.Seq2[T, error] { return func(yield func(T, error) bool) { - var nextOpt PaginationOptionFunc + var page PaginationOptionFunc Pagination: for { - ts, resp, err := f(nextOpt) + ts, resp, err := f(page) if err != nil { var t T yield(t, err) @@ -122,15 +118,13 @@ func Scan2[T any](f func(p PaginationOptionFunc) ([]T, *Response, error)) iter.S // the f request function was either configured for offset- or keyset-based // pagination. We support both here, by checking if the next link is provided (keyset) // or not. If both are provided, keyset-based pagination takes precedence. - switch { - case resp.NextLink != "": - nextOpt = WithKeysetPaginationParameters(resp.NextLink) - case resp.NextPage != 0: - nextOpt = WithOffsetPaginationParameters(resp.NextPage) - default: + next, ok := WithNext(resp) + if !ok { // no more pages break Pagination } + + page = next } } } @@ -159,7 +153,7 @@ func Must[T any](it iter.Seq2[T, error]) iter.Seq[T] { } } -// ScanAndCollect is a convenience function that collects all results and returns them as slice as well as an error if one happens. +// ScanAndCollect is a convenience function that collects all results and returns them as a slice as well as an error if one happens. // // opts := &ListProjectsOptions{} // projects, err := ScanAndCollect(func(p PaginationOptionFunc) ([]*Project, *Response, error) { @@ -172,10 +166,38 @@ func Must[T any](it iter.Seq2[T, error]) iter.Seq[T] { // // Attention: This API is experimental and may be subject to breaking changes to improve the API in the future. func ScanAndCollect[T any](f func(p PaginationOptionFunc) ([]T, *Response, error)) ([]T, error) { - it, hasErr := Scan(f) - allItems := slices.Collect(it) - if err := hasErr(); err != nil { - return nil, err + return ScanAndCollectN(f, -1) +} + +// ScanAndCollectN is a convenience function that collects at most n results and +// returns them as a slice as well as an error if one happens. +// +// This is useful when you need a slice, e.g. for marshaling the data +// structures, passing the data to a function expecting a slice, or implementing +// custom sorting logic. If you want to iterate over all items, the iterator +// returned by [Scan2] is a more memory efficient alternative. +// +// n determines the number of items to collect: +// - n > 0: at most n items are returned +// - n == 0: the result is a nil slice (zero items) +// - n < 0: all items are returned (no limit) +// +// Attention: This API is experimental and may be subject to breaking changes to +// improve the API in the future. +func ScanAndCollectN[T any](f func(p PaginationOptionFunc) ([]T, *Response, error), n int) ([]T, error) { + var items []T + + for item, err := range Scan2(f) { + if err != nil { + return nil, err + } + + if n >= 0 && len(items) >= n { + break + } + + items = append(items, item) } - return allItems, nil + + return items, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/personal_access_tokens.go b/vendor/gitlab.com/gitlab-org/api/client-go/personal_access_tokens.go index 9dcbe6872..f840773e8 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/personal_access_tokens.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/personal_access_tokens.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,13 +24,14 @@ import ( type ( PersonalAccessTokensServiceInterface interface { ListPersonalAccessTokens(opt *ListPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) - GetSinglePersonalAccessTokenByID(token int, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + GetSinglePersonalAccessTokenByID(token int64, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) GetSinglePersonalAccessToken(options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) - RotatePersonalAccessToken(token int, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) - RotatePersonalAccessTokenByID(token int, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + RotatePersonalAccessToken(token int64, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + RotatePersonalAccessTokenByID(token int64, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) RotatePersonalAccessTokenSelf(opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) - RevokePersonalAccessToken(token int, options ...RequestOptionFunc) (*Response, error) - RevokePersonalAccessTokenByID(token int, options ...RequestOptionFunc) (*Response, error) + // Deprecated: to be removed in 2.0; use RevokePersonalAccessTokenByID instead + RevokePersonalAccessToken(token int64, options ...RequestOptionFunc) (*Response, error) + RevokePersonalAccessTokenByID(token int64, options ...RequestOptionFunc) (*Response, error) RevokePersonalAccessTokenSelf(options ...RequestOptionFunc) (*Response, error) } @@ -50,13 +50,13 @@ var _ PersonalAccessTokensServiceInterface = (*PersonalAccessTokensService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/personal_access_tokens/ type PersonalAccessToken struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Revoked bool `json:"revoked"` CreatedAt *time.Time `json:"created_at"` Description string `json:"description"` Scopes []string `json:"scopes"` - UserID int `json:"user_id"` + UserID int64 `json:"user_id"` LastUsedAt *time.Time `json:"last_used_at,omitempty"` Active bool `json:"active"` ExpiresAt *ISOTime `json:"expires_at"` @@ -92,7 +92,7 @@ type ListPersonalAccessTokensOptions struct { Search *string `url:"search,omitempty" json:"search,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` State *string `url:"state,omitempty" json:"state,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` } // ListPersonalAccessTokens gets a list of all personal access tokens. @@ -100,38 +100,22 @@ type ListPersonalAccessTokensOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#list-all-personal-access-tokens func (s *PersonalAccessTokensService) ListPersonalAccessTokens(opt *ListPersonalAccessTokensOptions, options ...RequestOptionFunc) ([]*PersonalAccessToken, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "personal_access_tokens", opt, options) - if err != nil { - return nil, nil, err - } - - var pats []*PersonalAccessToken - resp, err := s.client.Do(req, &pats) - if err != nil { - return nil, resp, err - } - - return pats, resp, nil + return do[[]*PersonalAccessToken](s.client, + withPath("personal_access_tokens"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetSinglePersonalAccessTokenByID get a single personal access token by its ID. // // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#get-details-on-a-personal-access-token -func (s *PersonalAccessTokensService) GetSinglePersonalAccessTokenByID(token int, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := fmt.Sprintf("personal_access_tokens/%d", token) - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +func (s *PersonalAccessTokensService) GetSinglePersonalAccessTokenByID(token int64, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { + return do[*PersonalAccessToken](s.client, + withPath("personal_access_tokens/%d", token), + withRequestOpts(options...), + ) } // GetSinglePersonalAccessToken get a single personal access token by using @@ -140,19 +124,10 @@ func (s *PersonalAccessTokensService) GetSinglePersonalAccessTokenByID(token int // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#self-inform func (s *PersonalAccessTokensService) GetSinglePersonalAccessToken(options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := "personal_access_tokens/self" - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil + return do[*PersonalAccessToken](s.client, + withPath("personal_access_tokens/self"), + withRequestOpts(options...), + ) } // RotatePersonalAccessTokenOptions represents the available RotatePersonalAccessToken() @@ -165,7 +140,7 @@ type RotatePersonalAccessTokenOptions struct { } // RotatePersonalAccessToken is a backwards-compat shim for RotatePersonalAccessTokenByID. -func (s *PersonalAccessTokensService) RotatePersonalAccessToken(token int, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { +func (s *PersonalAccessTokensService) RotatePersonalAccessToken(token int64, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { return s.RotatePersonalAccessTokenByID(token, opt, options...) } @@ -174,21 +149,13 @@ func (s *PersonalAccessTokensService) RotatePersonalAccessToken(token int, opt * // // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#rotate-a-personal-access-token -func (s *PersonalAccessTokensService) RotatePersonalAccessTokenByID(token int, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := fmt.Sprintf("personal_access_tokens/%d/rotate", token) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +func (s *PersonalAccessTokensService) RotatePersonalAccessTokenByID(token int64, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("personal_access_tokens/%d/rotate", token), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RotatePersonalAccessTokenSelf revokes the currently authenticated token @@ -197,24 +164,17 @@ func (s *PersonalAccessTokensService) RotatePersonalAccessTokenByID(token int, o // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#self-rotate func (s *PersonalAccessTokensService) RotatePersonalAccessTokenSelf(opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := "personal_access_tokens/self/rotate" - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(PersonalAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("personal_access_tokens/self/rotate"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RevokePersonalAccessToken is a backwards-compat shim for RevokePersonalAccessTokenByID. -func (s *PersonalAccessTokensService) RevokePersonalAccessToken(token int, options ...RequestOptionFunc) (*Response, error) { +// Deprecated: to be removed in 2.0; use RevokePersonalAccessTokenByID instead +func (s *PersonalAccessTokensService) RevokePersonalAccessToken(token int64, options ...RequestOptionFunc) (*Response, error) { return s.RevokePersonalAccessTokenByID(token, options...) } @@ -222,15 +182,13 @@ func (s *PersonalAccessTokensService) RevokePersonalAccessToken(token int, optio // // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#revoke-a-personal-access-token -func (s *PersonalAccessTokensService) RevokePersonalAccessTokenByID(token int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("personal_access_tokens/%d", token) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PersonalAccessTokensService) RevokePersonalAccessTokenByID(token int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("personal_access_tokens/%d", token), + withRequestOpts(options...), + ) + return resp, err } // RevokePersonalAccessTokenSelf revokes the currently authenticated @@ -239,12 +197,10 @@ func (s *PersonalAccessTokensService) RevokePersonalAccessTokenByID(token int, o // GitLab API docs: // https://docs.gitlab.com/api/personal_access_tokens/#self-revoke func (s *PersonalAccessTokensService) RevokePersonalAccessTokenSelf(options ...RequestOptionFunc) (*Response, error) { - u := "personal_access_tokens/self" - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("personal_access_tokens/self"), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_schedules.go b/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_schedules.go index 2e2f156dd..e98e58371 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_schedules.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_schedules.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,16 +24,16 @@ import ( type ( PipelineSchedulesServiceInterface interface { ListPipelineSchedules(pid any, opt *ListPipelineSchedulesOptions, options ...RequestOptionFunc) ([]*PipelineSchedule, *Response, error) - GetPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) - ListPipelinesTriggeredBySchedule(pid any, schedule int, opt *ListPipelinesTriggeredByScheduleOptions, options ...RequestOptionFunc) ([]*Pipeline, *Response, error) + GetPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) + ListPipelinesTriggeredBySchedule(pid any, schedule int64, opt *ListPipelinesTriggeredByScheduleOptions, options ...RequestOptionFunc) ([]*Pipeline, *Response, error) CreatePipelineSchedule(pid any, opt *CreatePipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) - EditPipelineSchedule(pid any, schedule int, opt *EditPipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) - TakeOwnershipOfPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) - DeletePipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*Response, error) - RunPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*Response, error) - CreatePipelineScheduleVariable(pid any, schedule int, opt *CreatePipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) - EditPipelineScheduleVariable(pid any, schedule int, key string, opt *EditPipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) - DeletePipelineScheduleVariable(pid any, schedule int, key string, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) + EditPipelineSchedule(pid any, schedule int64, opt *EditPipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) + TakeOwnershipOfPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) + DeletePipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*Response, error) + RunPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*Response, error) + CreatePipelineScheduleVariable(pid any, schedule int64, opt *CreatePipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) + EditPipelineScheduleVariable(pid any, schedule int64, key string, opt *EditPipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) + DeletePipelineScheduleVariable(pid any, schedule int64, key string, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) } // PipelineSchedulesService handles communication with the pipeline @@ -53,7 +52,7 @@ var _ PipelineSchedulesServiceInterface = (*PipelineSchedulesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/ type PipelineSchedule struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Ref string `json:"ref"` Cron string `json:"cron"` @@ -71,7 +70,7 @@ type PipelineSchedule struct { // LastPipeline represents the last pipeline ran by schedule // this will be returned only for individual schedule get operation type LastPipeline struct { - ID int `json:"id"` + ID int64 `json:"id"` SHA string `json:"sha"` Ref string `json:"ref"` Status string `json:"status"` @@ -92,49 +91,22 @@ type ListPipelineSchedulesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#get-all-pipeline-schedules func (s *PipelineSchedulesService) ListPipelineSchedules(pid any, opt *ListPipelineSchedulesOptions, options ...RequestOptionFunc) ([]*PipelineSchedule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*PipelineSchedule - resp, err := s.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*PipelineSchedule](s.client, + withPath("projects/%s/pipeline_schedules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetPipelineSchedule gets a pipeline schedule. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#get-a-single-pipeline-schedule -func (s *PipelineSchedulesService) GetPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineSchedule) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) GetPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { + return do[*PipelineSchedule](s.client, + withPath("projects/%s/pipeline_schedules/%d", ProjectID{pid}, schedule), + withRequestOpts(options...), + ) } // ListPipelinesTriggeredByScheduleOptions represents the available @@ -142,32 +114,21 @@ func (s *PipelineSchedulesService) GetPipelineSchedule(pid any, schedule int, op // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#get-all-pipelines-triggered-by-a-pipeline-schedule -type ListPipelinesTriggeredByScheduleOptions ListOptions +type ListPipelinesTriggeredByScheduleOptions struct { + ListOptions +} // ListPipelinesTriggeredBySchedule gets all pipelines triggered by a pipeline // schedule. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#get-all-pipelines-triggered-by-a-pipeline-schedule -func (s *PipelineSchedulesService) ListPipelinesTriggeredBySchedule(pid any, schedule int, opt *ListPipelinesTriggeredByScheduleOptions, options ...RequestOptionFunc) ([]*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/pipelines", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Pipeline - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) ListPipelinesTriggeredBySchedule(pid any, schedule int64, opt *ListPipelinesTriggeredByScheduleOptions, options ...RequestOptionFunc) ([]*Pipeline, *Response, error) { + return do[[]*Pipeline](s.client, + withPath("projects/%s/pipeline_schedules/%d/pipelines", ProjectID{pid}, schedule), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreatePipelineScheduleOptions represents the available @@ -189,24 +150,12 @@ type CreatePipelineScheduleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#create-a-new-pipeline-schedule func (s *PipelineSchedulesService) CreatePipelineSchedule(pid any, opt *CreatePipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineSchedule) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*PipelineSchedule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipeline_schedules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditPipelineScheduleOptions represents the available @@ -227,25 +176,13 @@ type EditPipelineScheduleOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#edit-a-pipeline-schedule -func (s *PipelineSchedulesService) EditPipelineSchedule(pid any, schedule int, opt *EditPipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineSchedule) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) EditPipelineSchedule(pid any, schedule int64, opt *EditPipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { + return do[*PipelineSchedule](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/pipeline_schedules/%d", ProjectID{pid}, schedule), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // TakeOwnershipOfPipelineSchedule sets the owner of the specified @@ -253,63 +190,38 @@ func (s *PipelineSchedulesService) EditPipelineSchedule(pid any, schedule int, o // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#take-ownership-of-a-pipeline-schedule -func (s *PipelineSchedulesService) TakeOwnershipOfPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/take_ownership", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineSchedule) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) TakeOwnershipOfPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) { + return do[*PipelineSchedule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipeline_schedules/%d/take_ownership", ProjectID{pid}, schedule), + withRequestOpts(options...), + ) } // DeletePipelineSchedule deletes a pipeline schedule. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#delete-a-pipeline-schedule -func (s *PipelineSchedulesService) DeletePipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PipelineSchedulesService) DeletePipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/pipeline_schedules/%d", ProjectID{pid}, schedule), + withRequestOpts(options...), + ) + return resp, err } // RunPipelineSchedule triggers a new scheduled pipeline to run immediately. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#run-a-scheduled-pipeline-immediately -func (s *PipelineSchedulesService) RunPipelineSchedule(pid any, schedule int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/play", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PipelineSchedulesService) RunPipelineSchedule(pid any, schedule int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipeline_schedules/%d/play", ProjectID{pid}, schedule), + withRequestOpts(options...), + ) + return resp, err } // CreatePipelineScheduleVariableOptions represents the available @@ -327,25 +239,13 @@ type CreatePipelineScheduleVariableOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#create-a-new-pipeline-schedule -func (s *PipelineSchedulesService) CreatePipelineScheduleVariable(pid any, schedule int, opt *CreatePipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables", PathEscape(project), schedule) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineVariable) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) CreatePipelineScheduleVariable(pid any, schedule int64, opt *CreatePipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { + return do[*PipelineVariable](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipeline_schedules/%d/variables", ProjectID{pid}, schedule), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditPipelineScheduleVariableOptions represents the available @@ -362,48 +262,23 @@ type EditPipelineScheduleVariableOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#edit-a-pipeline-schedule-variable -func (s *PipelineSchedulesService) EditPipelineScheduleVariable(pid any, schedule int, key string, opt *EditPipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", PathEscape(project), schedule, key) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineVariable) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) EditPipelineScheduleVariable(pid any, schedule int64, key string, opt *EditPipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { + return do[*PipelineVariable](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/pipeline_schedules/%d/variables/%s", ProjectID{pid}, schedule, NoEscape{key}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeletePipelineScheduleVariable creates a pipeline schedule variable. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_schedules/#delete-a-pipeline-schedule-variable -func (s *PipelineSchedulesService) DeletePipelineScheduleVariable(pid any, schedule int, key string, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", PathEscape(project), schedule, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineVariable) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelineSchedulesService) DeletePipelineScheduleVariable(pid any, schedule int64, key string, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) { + return do[*PipelineVariable](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/pipeline_schedules/%d/variables/%s", ProjectID{pid}, schedule, NoEscape{key}), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_triggers.go b/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_triggers.go index deff0c89f..c540cf3b2 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_triggers.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pipeline_triggers.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,10 +24,10 @@ import ( type ( PipelineTriggersServiceInterface interface { ListPipelineTriggers(pid any, opt *ListPipelineTriggersOptions, options ...RequestOptionFunc) ([]*PipelineTrigger, *Response, error) - GetPipelineTrigger(pid any, trigger int, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) + GetPipelineTrigger(pid any, trigger int64, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) AddPipelineTrigger(pid any, opt *AddPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) - EditPipelineTrigger(pid any, trigger int, opt *EditPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) - DeletePipelineTrigger(pid any, trigger int, options ...RequestOptionFunc) (*Response, error) + EditPipelineTrigger(pid any, trigger int64, opt *EditPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) + DeletePipelineTrigger(pid any, trigger int64, options ...RequestOptionFunc) (*Response, error) RunPipelineTrigger(pid any, opt *RunPipelineTriggerOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) } @@ -48,7 +47,7 @@ var _ PipelineTriggersServiceInterface = (*PipelineTriggersService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/ type PipelineTrigger struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` CreatedAt *time.Time `json:"created_at"` DeletedAt *time.Time `json:"deleted_at"` @@ -62,56 +61,31 @@ type PipelineTrigger struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#list-project-trigger-tokens -type ListPipelineTriggersOptions ListOptions +type ListPipelineTriggersOptions struct { + ListOptions +} // ListPipelineTriggers gets a list of project triggers. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#list-project-trigger-tokens func (s *PipelineTriggersService) ListPipelineTriggers(pid any, opt *ListPipelineTriggersOptions, options ...RequestOptionFunc) ([]*PipelineTrigger, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/triggers", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pt []*PipelineTrigger - resp, err := s.client.Do(req, &pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[[]*PipelineTrigger](s.client, + withPath("projects/%s/triggers", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetPipelineTrigger gets a specific pipeline trigger for a project. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#get-trigger-token-details -func (s *PipelineTriggersService) GetPipelineTrigger(pid any, trigger int, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/triggers/%d", PathEscape(project), trigger) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pt := new(PipelineTrigger) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil +func (s *PipelineTriggersService) GetPipelineTrigger(pid any, trigger int64, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) { + return do[*PipelineTrigger](s.client, + withPath("projects/%s/triggers/%d", ProjectID{pid}, trigger), + withRequestOpts(options...), + ) } // AddPipelineTriggerOptions represents the available AddPipelineTrigger() options. @@ -127,24 +101,12 @@ type AddPipelineTriggerOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#create-a-trigger-token func (s *PipelineTriggersService) AddPipelineTrigger(pid any, opt *AddPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/triggers", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pt := new(PipelineTrigger) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[*PipelineTrigger](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/triggers", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditPipelineTriggerOptions represents the available EditPipelineTrigger() options. @@ -159,44 +121,26 @@ type EditPipelineTriggerOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#update-a-pipeline-trigger-token -func (s *PipelineTriggersService) EditPipelineTrigger(pid any, trigger int, opt *EditPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/triggers/%d", PathEscape(project), trigger) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pt := new(PipelineTrigger) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil +func (s *PipelineTriggersService) EditPipelineTrigger(pid any, trigger int64, opt *EditPipelineTriggerOptions, options ...RequestOptionFunc) (*PipelineTrigger, *Response, error) { + return do[*PipelineTrigger](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/triggers/%d", ProjectID{pid}, trigger), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeletePipelineTrigger removes a trigger from a project. // // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#remove-a-pipeline-trigger-token -func (s *PipelineTriggersService) DeletePipelineTrigger(pid any, trigger int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/triggers/%d", PathEscape(project), trigger) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PipelineTriggersService) DeletePipelineTrigger(pid any, trigger int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/triggers/%d", ProjectID{pid}, trigger), + withRequestOpts(options...), + ) + return resp, err } // RunPipelineTriggerOptions represents the available RunPipelineTrigger() options. @@ -207,6 +151,10 @@ type RunPipelineTriggerOptions struct { Ref *string `url:"ref" json:"ref"` Token *string `url:"token" json:"token"` Variables map[string]string `url:"variables,omitempty" json:"variables,omitempty"` + + // Inputs contains pipeline input parameters. + // See PipelineInputsOption for supported types and usage. + Inputs PipelineInputsOption `url:"inputs,omitempty" json:"inputs,omitempty"` } // RunPipelineTrigger starts a trigger from a project. @@ -214,22 +162,10 @@ type RunPipelineTriggerOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipeline_triggers/#trigger-a-pipeline-with-a-token func (s *PipelineTriggersService) RunPipelineTrigger(pid any, opt *RunPipelineTriggerOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/trigger/pipeline", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pt := new(Pipeline) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[*Pipeline](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/trigger/pipeline", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/pipelines.go b/vendor/gitlab.com/gitlab-org/api/client-go/pipelines.go index 838583688..437dcc9e3 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/pipelines.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/pipelines.go @@ -17,7 +17,7 @@ package gitlab import ( - "fmt" + "encoding/json" "net/http" "time" ) @@ -47,15 +47,16 @@ const ( type ( PipelinesServiceInterface interface { ListProjectPipelines(pid any, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) - GetPipeline(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) - GetPipelineVariables(pid any, pipeline int, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) - GetPipelineTestReport(pid any, pipeline int, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) + GetPipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) + GetPipelineVariables(pid any, pipeline int64, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) + GetPipelineTestReport(pid any, pipeline int64, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) + GetPipelineTestReportSummary(pid any, pipeline int64, options ...RequestOptionFunc) (*PipelineTestReportSummary, *Response, error) GetLatestPipeline(pid any, opt *GetLatestPipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) CreatePipeline(pid any, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) - RetryPipelineBuild(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) - CancelPipelineBuild(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) - DeletePipeline(pid any, pipeline int, options ...RequestOptionFunc) (*Response, error) - UpdatePipelineMetadata(pid any, pipeline int, opt *UpdatePipelineMetadataOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) + RetryPipelineBuild(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) + CancelPipelineBuild(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) + DeletePipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Response, error) + UpdatePipelineMetadata(pid any, pipeline int64, opt *UpdatePipelineMetadataOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) } // PipelinesService handles communication with the repositories related @@ -82,17 +83,18 @@ type PipelineVariable struct { // // GitLab API docs: https://docs.gitlab.com/api/pipelines/ type PipelineInput struct { - Name string `json:"key"` - Value any `json:"value"` + Name string `json:"name"` + Value any `json:"value"` + Destroy *bool `json:"destroy,omitempty"` } // Pipeline represents a GitLab pipeline. // // GitLab API docs: https://docs.gitlab.com/api/pipelines/ type Pipeline struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` Status string `json:"status"` Source PipelineSource `json:"source"` Ref string `json:"ref"` @@ -107,40 +109,51 @@ type Pipeline struct { StartedAt *time.Time `json:"started_at"` FinishedAt *time.Time `json:"finished_at"` CommittedAt *time.Time `json:"committed_at"` - Duration int `json:"duration"` - QueuedDuration int `json:"queued_duration"` + Duration int64 `json:"duration"` + QueuedDuration int64 `json:"queued_duration"` Coverage string `json:"coverage"` WebURL string `json:"web_url"` DetailedStatus *DetailedStatus `json:"detailed_status"` } +func (p Pipeline) String() string { + return Stringify(p) +} + // DetailedStatus contains detailed information about the status of a pipeline. type DetailedStatus struct { - Icon string `json:"icon"` - Text string `json:"text"` - Label string `json:"label"` - Group string `json:"group"` - Tooltip string `json:"tooltip"` - HasDetails bool `json:"has_details"` - DetailsPath string `json:"details_path"` - Illustration struct { - Image string `json:"image"` - } `json:"illustration"` - Favicon string `json:"favicon"` + Icon string `json:"icon"` + Text string `json:"text"` + Label string `json:"label"` + Group string `json:"group"` + Tooltip string `json:"tooltip"` + HasDetails bool `json:"has_details"` + DetailsPath string `json:"details_path"` + Illustration DetailedStatusIllustration `json:"illustration"` + Favicon string `json:"favicon"` } -func (p Pipeline) String() string { - return Stringify(p) +func (s DetailedStatus) String() string { + return Stringify(s) +} + +// DetailedStatusIllustration contains detailed information about the status illustration of a pipeline. +type DetailedStatusIllustration struct { + Image string `json:"image"` +} + +func (i DetailedStatusIllustration) String() string { + return Stringify(i) } // PipelineTestReport contains a detailed report of a test run. type PipelineTestReport struct { TotalTime float64 `json:"total_time"` - TotalCount int `json:"total_count"` - SuccessCount int `json:"success_count"` - FailedCount int `json:"failed_count"` - SkippedCount int `json:"skipped_count"` - ErrorCount int `json:"error_count"` + TotalCount int64 `json:"total_count"` + SuccessCount int64 `json:"success_count"` + FailedCount int64 `json:"failed_count"` + SkippedCount int64 `json:"skipped_count"` + ErrorCount int64 `json:"error_count"` TestSuites []*PipelineTestSuites `json:"test_suites"` } @@ -148,11 +161,11 @@ type PipelineTestReport struct { type PipelineTestSuites struct { Name string `json:"name"` TotalTime float64 `json:"total_time"` - TotalCount int `json:"total_count"` - SuccessCount int `json:"success_count"` - FailedCount int `json:"failed_count"` - SkippedCount int `json:"skipped_count"` - ErrorCount int `json:"error_count"` + TotalCount int64 `json:"total_count"` + SuccessCount int64 `json:"success_count"` + FailedCount int64 `json:"failed_count"` + SkippedCount int64 `json:"skipped_count"` + ErrorCount int64 `json:"error_count"` TestCases []*PipelineTestCases `json:"test_cases"` } @@ -169,9 +182,40 @@ type PipelineTestCases struct { RecentFailures *RecentFailures `json:"recent_failures"` } +// PipelineTestReportSummary contains a summary report of a test run +type PipelineTestReportSummary struct { + Total PipelineTotalSummary `json:"total"` + TestSuites []PipelineTestSuiteSummary `json:"test_suites"` +} + +// PipelineTotalSummary contains a total summary of a test run +type PipelineTotalSummary struct { + // Documentation examples only show whole numbers, but the test specs for GitLab show decimals, so `float64` is the better attribute here. + Time float64 `json:"time"` + Count int64 `json:"count"` + Success int64 `json:"success"` + Failed int64 `json:"failed"` + Skipped int64 `json:"skipped"` + Error int64 `json:"error"` + SuiteError *string `json:"suite_error"` +} + +// PipelineTestSuiteSummary contains a test suite summary of a test run +type PipelineTestSuiteSummary struct { + Name string `json:"name"` + TotalTime float64 `json:"total_time"` + TotalCount int64 `json:"total_count"` + SuccessCount int64 `json:"success_count"` + FailedCount int64 `json:"failed_count"` + SkippedCount int64 `json:"skipped_count"` + ErrorCount int64 `json:"error_count"` + BuildIDs []int64 `json:"build_ids"` + SuiteError *string `json:"suite_error"` +} + // RecentFailures contains failures count for the project's default branch. type RecentFailures struct { - Count int `json:"count"` + Count int64 `json:"count"` BaseBranch string `json:"base_branch"` } @@ -182,9 +226,9 @@ func (p PipelineTestReport) String() string { // PipelineInfo shows the basic entities of a pipeline, mostly used as fields // on other assets, like Commit. type PipelineInfo struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` Status string `json:"status"` Source string `json:"source"` Ref string `json:"ref"` @@ -227,99 +271,55 @@ type ListProjectPipelinesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-project-pipelines func (s *PipelinesService) ListProjectPipelines(pid any, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*PipelineInfo - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*PipelineInfo](s.client, + withPath("projects/%s/pipelines", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetPipeline gets a single project pipeline. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#get-a-single-pipeline -func (s *PipelinesService) GetPipeline(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelinesService) GetPipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) { + return do[*Pipeline](s.client, + withPath("projects/%s/pipelines/%d", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) } // GetPipelineVariables gets the variables of a single project pipeline. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#get-variables-of-a-pipeline -func (s *PipelinesService) GetPipelineVariables(pid any, pipeline int, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/variables", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var p []*PipelineVariable - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelinesService) GetPipelineVariables(pid any, pipeline int64, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) { + return do[[]*PipelineVariable](s.client, + withPath("projects/%s/pipelines/%d/variables", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) } // GetPipelineTestReport gets the test report of a single project pipeline. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#get-a-pipelines-test-report -func (s *PipelinesService) GetPipelineTestReport(pid any, pipeline int, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/test_report", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(PipelineTestReport) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } +func (s *PipelinesService) GetPipelineTestReport(pid any, pipeline int64, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) { + return do[*PipelineTestReport](s.client, + withPath("projects/%s/pipelines/%d/test_report", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) +} - return p, resp, nil +// GetPipelineTestReportSummary gets the test report summary of a single project pipeline. +// +// GitLab API docs: +// https://docs.gitlab.com/api/pipelines/#get-a-test-report-summary-for-a-pipeline +func (s *PipelinesService) GetPipelineTestReportSummary(pid any, pipeline int64, options ...RequestOptionFunc) (*PipelineTestReportSummary, *Response, error) { + return do[*PipelineTestReportSummary](s.client, + withPath("projects/%s/pipelines/%d/test_report_summary", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) } // GetLatestPipelineOptions represents the available GetLatestPipeline() options. @@ -335,24 +335,11 @@ type GetLatestPipelineOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#get-the-latest-pipeline func (s *PipelinesService) GetLatestPipeline(pid any, opt *GetLatestPipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/latest", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Pipeline](s.client, + withPath("projects/%s/pipelines/latest", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreatePipelineOptions represents the available CreatePipeline() options. @@ -362,6 +349,10 @@ func (s *PipelinesService) GetLatestPipeline(pid any, opt *GetLatestPipelineOpti type CreatePipelineOptions struct { Ref *string `url:"ref" json:"ref"` Variables *[]*PipelineVariableOptions `url:"variables,omitempty" json:"variables,omitempty"` + + // Inputs contains pipeline input parameters. + // See PipelineInputsOption for supported types and usage. + Inputs PipelineInputsOption `url:"inputs,omitempty" json:"inputs,omitempty"` } // PipelineVariableOptions represents a pipeline variable option. @@ -373,98 +364,131 @@ type PipelineVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// CreatePipeline creates a new project pipeline. +// PipelineInputsOption represents pipeline input parameters with type-safe values. +// Each value must be wrapped using NewPipelineInputValue() to ensure compile-time type safety. +// +// Supported value types: +// - string +// - integers (int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64) +// - floats (float32, float64) +// - bool +// - []string +// +// Example: +// +// inputs := PipelineInputsOption{ +// "environment": NewPipelineInputValue("production"), +// "replicas": NewPipelineInputValue(3), +// "debug": NewPipelineInputValue(false), +// "regions": NewPipelineInputValue([]string{"us-east", "eu-west"}), +// } // // GitLab API docs: -// https://docs.gitlab.com/api/pipelines/#create-a-new-pipeline -func (s *PipelinesService) CreatePipeline(pid any, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipeline", PathEscape(project)) +// - https://docs.gitlab.com/api/pipelines/#create-a-new-pipeline +// - https://docs.gitlab.com/api/pipeline_triggers/#trigger-a-pipeline-with-a-token +type PipelineInputsOption map[string]PipelineInputValueInterface - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } +// PipelineInputValueInterface is implemented by PipelineInputValue[T] for supported pipeline input types. +// Use NewPipelineInputValue() to create instances - do not implement this interface directly. +// +// See PipelineInputsOption for supported types and usage examples. +type PipelineInputValueInterface interface { + pipelineInputValue() +} + +type constraintSigned interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +type constraintUnsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +type constraintInteger interface { + constraintSigned | constraintUnsigned +} + +type constraintFloat interface { + ~float32 | ~float64 +} + +// PipelineInputValueType is a type constraint for valid pipeline input value types. +// This constraint ensures only supported GitLab pipeline input types can be used. +type PipelineInputValueType interface { + ~string | constraintInteger | constraintFloat | ~bool | []string +} + +// PipelineInputValue wraps a pipeline input value with compile-time type safety. +// Use NewPipelineInputValue() to create instances of this type. +type PipelineInputValue[T PipelineInputValueType] struct { + Value T +} - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err +// MarshalJSON implements the json.Marshaler interface. +func (v PipelineInputValue[T]) MarshalJSON() ([]byte, error) { + return json.Marshal(v.Value) +} + +// pipelineInputValue implements PipelineInputValueInterface. +func (PipelineInputValue[T]) pipelineInputValue() {} + +// NewPipelineInputValue wraps a value for use in pipeline inputs. +// Similar to Ptr(), this ensures type safety at compile time. +// Supported types: string, integers, floats, bool, []string +func NewPipelineInputValue[T PipelineInputValueType](value T) PipelineInputValue[T] { + return PipelineInputValue[T]{ + Value: value, } +} - return p, resp, nil +// CreatePipeline creates a new project pipeline. +// +// GitLab API docs: +// https://docs.gitlab.com/api/pipelines/#create-a-new-pipeline +func (s *PipelinesService) CreatePipeline(pid any, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { + return do[*Pipeline](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipeline", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RetryPipelineBuild retries failed builds in a pipeline. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#retry-jobs-in-a-pipeline -func (s *PipelinesService) RetryPipelineBuild(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/retry", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelinesService) RetryPipelineBuild(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) { + return do[*Pipeline](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipelines/%d/retry", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) } // CancelPipelineBuild cancels a pipeline builds. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#cancel-a-pipelines-jobs -func (s *PipelinesService) CancelPipelineBuild(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/cancel", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelinesService) CancelPipelineBuild(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) { + return do[*Pipeline](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/pipelines/%d/cancel", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) } // DeletePipeline deletes an existing pipeline. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#delete-a-pipeline -func (s *PipelinesService) DeletePipeline(pid any, pipeline int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *PipelinesService) DeletePipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/pipelines/%d", ProjectID{pid}, pipeline), + withRequestOpts(options...), + ) + return resp, err } // UpdatePipelineMetadataOptions represents the available UpdatePipelineMetadata() @@ -481,23 +505,11 @@ type UpdatePipelineMetadataOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#update-pipeline-metadata -func (s *PipelinesService) UpdatePipelineMetadata(pid any, pipeline int, opt *UpdatePipelineMetadataOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/pipelines/%d/metadata", PathEscape(project), pipeline) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Pipeline) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil +func (s *PipelinesService) UpdatePipelineMetadata(pid any, pipeline int64, opt *UpdatePipelineMetadataOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) { + return do[*Pipeline](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/pipelines/%d/metadata", ProjectID{pid}, pipeline), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/plan_limits.go b/vendor/gitlab.com/gitlab-org/api/client-go/plan_limits.go index 53e9c9fd5..d7247fa58 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/plan_limits.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/plan_limits.go @@ -39,14 +39,14 @@ var _ PlanLimitsServiceInterface = (*PlanLimitsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/plan_limits/ type PlanLimit struct { - ConanMaxFileSize int `json:"conan_max_file_size,omitempty"` - GenericPackagesMaxFileSize int `json:"generic_packages_max_file_size,omitempty"` - HelmMaxFileSize int `json:"helm_max_file_size,omitempty"` - MavenMaxFileSize int `json:"maven_max_file_size,omitempty"` - NPMMaxFileSize int `json:"npm_max_file_size,omitempty"` - NugetMaxFileSize int `json:"nuget_max_file_size,omitempty"` - PyPiMaxFileSize int `json:"pypi_max_file_size,omitempty"` - TerraformModuleMaxFileSize int `json:"terraform_module_max_file_size,omitempty"` + ConanMaxFileSize int64 `json:"conan_max_file_size,omitempty"` + GenericPackagesMaxFileSize int64 `json:"generic_packages_max_file_size,omitempty"` + HelmMaxFileSize int64 `json:"helm_max_file_size,omitempty"` + MavenMaxFileSize int64 `json:"maven_max_file_size,omitempty"` + NPMMaxFileSize int64 `json:"npm_max_file_size,omitempty"` + NugetMaxFileSize int64 `json:"nuget_max_file_size,omitempty"` + PyPiMaxFileSize int64 `json:"pypi_max_file_size,omitempty"` + TerraformModuleMaxFileSize int64 `json:"terraform_module_max_file_size,omitempty"` } // GetCurrentPlanLimitsOptions represents the available GetCurrentPlanLimits() @@ -63,18 +63,11 @@ type GetCurrentPlanLimitsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/plan_limits/#get-current-plan-limits func (s *PlanLimitsService) GetCurrentPlanLimits(opt *GetCurrentPlanLimitsOptions, options ...RequestOptionFunc) (*PlanLimit, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "application/plan_limits", opt, options) - if err != nil { - return nil, nil, err - } - - pl := new(PlanLimit) - resp, err := s.client.Do(req, pl) - if err != nil { - return nil, resp, err - } - - return pl, resp, nil + return do[*PlanLimit](s.client, + withPath("application/plan_limits"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ChangePlanLimitOptions represents the available ChangePlanLimits() options. @@ -83,14 +76,14 @@ func (s *PlanLimitsService) GetCurrentPlanLimits(opt *GetCurrentPlanLimitsOption // https://docs.gitlab.com/api/plan_limits/#change-plan-limits type ChangePlanLimitOptions struct { PlanName *string `url:"plan_name,omitempty" json:"plan_name,omitempty"` - ConanMaxFileSize *int `url:"conan_max_file_size,omitempty" json:"conan_max_file_size,omitempty"` - GenericPackagesMaxFileSize *int `url:"generic_packages_max_file_size,omitempty" json:"generic_packages_max_file_size,omitempty"` - HelmMaxFileSize *int `url:"helm_max_file_size,omitempty" json:"helm_max_file_size,omitempty"` - MavenMaxFileSize *int `url:"maven_max_file_size,omitempty" json:"maven_max_file_size,omitempty"` - NPMMaxFileSize *int `url:"npm_max_file_size,omitempty" json:"npm_max_file_size,omitempty"` - NugetMaxFileSize *int `url:"nuget_max_file_size,omitempty" json:"nuget_max_file_size,omitempty"` - PyPiMaxFileSize *int `url:"pypi_max_file_size,omitempty" json:"pypi_max_file_size,omitempty"` - TerraformModuleMaxFileSize *int `url:"terraform_module_max_file_size,omitempty" json:"terraform_module_max_file_size,omitempty"` + ConanMaxFileSize *int64 `url:"conan_max_file_size,omitempty" json:"conan_max_file_size,omitempty"` + GenericPackagesMaxFileSize *int64 `url:"generic_packages_max_file_size,omitempty" json:"generic_packages_max_file_size,omitempty"` + HelmMaxFileSize *int64 `url:"helm_max_file_size,omitempty" json:"helm_max_file_size,omitempty"` + MavenMaxFileSize *int64 `url:"maven_max_file_size,omitempty" json:"maven_max_file_size,omitempty"` + NPMMaxFileSize *int64 `url:"npm_max_file_size,omitempty" json:"npm_max_file_size,omitempty"` + NugetMaxFileSize *int64 `url:"nuget_max_file_size,omitempty" json:"nuget_max_file_size,omitempty"` + PyPiMaxFileSize *int64 `url:"pypi_max_file_size,omitempty" json:"pypi_max_file_size,omitempty"` + TerraformModuleMaxFileSize *int64 `url:"terraform_module_max_file_size,omitempty" json:"terraform_module_max_file_size,omitempty"` } // ChangePlanLimits modifies the limits of a plan on the GitLab instance. @@ -98,16 +91,10 @@ type ChangePlanLimitOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/plan_limits/#change-plan-limits func (s *PlanLimitsService) ChangePlanLimits(opt *ChangePlanLimitOptions, options ...RequestOptionFunc) (*PlanLimit, *Response, error) { - req, err := s.client.NewRequest(http.MethodPut, "application/plan_limits", opt, options) - if err != nil { - return nil, nil, err - } - - pl := new(PlanLimit) - resp, err := s.client.Do(req, pl) - if err != nil { - return nil, resp, err - } - - return pl, resp, nil + return do[*PlanLimit](s.client, + withMethod(http.MethodPut), + withPath("application/plan_limits"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_access_tokens.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_access_tokens.go index e98e65855..4fae8ebf5 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_access_tokens.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_access_tokens.go @@ -17,18 +17,17 @@ package gitlab import ( - "fmt" "net/http" ) type ( ProjectAccessTokensServiceInterface interface { ListProjectAccessTokens(pid any, opt *ListProjectAccessTokensOptions, options ...RequestOptionFunc) ([]*ProjectAccessToken, *Response, error) - GetProjectAccessToken(pid any, id int, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) + GetProjectAccessToken(pid any, id int64, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) CreateProjectAccessToken(pid any, opt *CreateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) - RotateProjectAccessToken(pid any, id int, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) + RotateProjectAccessToken(pid any, id int64, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) RotateProjectAccessTokenSelf(pid any, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) - RevokeProjectAccessToken(pid any, id int, options ...RequestOptionFunc) (*Response, error) + RevokeProjectAccessToken(pid any, id int64, options ...RequestOptionFunc) (*Response, error) } // ProjectAccessTokensService handles communication with the @@ -69,49 +68,22 @@ type ListProjectAccessTokensOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#list-all-project-access-tokens func (s *ProjectAccessTokensService) ListProjectAccessTokens(pid any, opt *ListProjectAccessTokensOptions, options ...RequestOptionFunc) ([]*ProjectAccessToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pats []*ProjectAccessToken - resp, err := s.client.Do(req, &pats) - if err != nil { - return nil, resp, err - } - - return pats, resp, nil + return do[[]*ProjectAccessToken](s.client, + withPath("projects/%s/access_tokens", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectAccessToken gets a single project access tokens in a project. // // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#get-details-on-a-project-access-token -func (s *ProjectAccessTokensService) GetProjectAccessToken(pid any, id int, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pat := new(ProjectAccessToken) - resp, err := s.client.Do(req, &pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +func (s *ProjectAccessTokensService) GetProjectAccessToken(pid any, id int64, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { + return do[*ProjectAccessToken](s.client, + withPath("projects/%s/access_tokens/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) } // CreateProjectAccessTokenOptions represents the available CreateVariable() @@ -132,24 +104,12 @@ type CreateProjectAccessTokenOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#create-a-project-access-token func (s *ProjectAccessTokensService) CreateProjectAccessToken(pid any, opt *CreateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(ProjectAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil + return do[*ProjectAccessToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/access_tokens", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RotateProjectAccessTokenOptions represents the available RotateProjectAccessToken() @@ -166,24 +126,13 @@ type RotateProjectAccessTokenOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#rotate-a-project-access-token -func (s *ProjectAccessTokensService) RotateProjectAccessToken(pid any, id int, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { - projects, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens/%d/rotate", PathEscape(projects), id) - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(ProjectAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil +func (s *ProjectAccessTokensService) RotateProjectAccessToken(pid any, id int64, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { + return do[*ProjectAccessToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/access_tokens/%d/rotate", ProjectID{pid}, id), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RotateProjectAccessTokenSelf revokes the project access token used for the request @@ -192,40 +141,23 @@ func (s *ProjectAccessTokensService) RotateProjectAccessToken(pid any, id int, o // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#self-rotate func (s *ProjectAccessTokensService) RotateProjectAccessTokenSelf(pid any, opt *RotateProjectAccessTokenOptions, options ...RequestOptionFunc) (*ProjectAccessToken, *Response, error) { - projects, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens/self/rotate", PathEscape(projects)) - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pat := new(ProjectAccessToken) - resp, err := s.client.Do(req, pat) - if err != nil { - return nil, resp, err - } - - return pat, resp, nil + return do[*ProjectAccessToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/access_tokens/self/rotate", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RevokeProjectAccessToken revokes a project access token. // // GitLab API docs: // https://docs.gitlab.com/api/project_access_tokens/#revoke-a-project-access-token -func (s *ProjectAccessTokensService) RevokeProjectAccessToken(pid any, id int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/access_tokens/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectAccessTokensService) RevokeProjectAccessToken(pid any, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/access_tokens/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_aliases.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_aliases.go new file mode 100644 index 000000000..9059abbc3 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_aliases.go @@ -0,0 +1,90 @@ +package gitlab + +import ( + "net/http" +) + +type ( + ProjectAliasesServiceInterface interface { + ListProjectAliases(options ...RequestOptionFunc) ([]*ProjectAlias, *Response, error) + GetProjectAlias(name string, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) + CreateProjectAlias(opt *CreateProjectAliasOptions, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) + DeleteProjectAlias(name string, options ...RequestOptionFunc) (*Response, error) + } + + // ProjectAliasesService handles communication with the project aliases related methods of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/project_aliases/ + ProjectAliasesService struct { + client *Client + } +) + +var _ ProjectAliasesServiceInterface = (*ProjectAliasesService)(nil) + +// ProjectAlias represents a GitLab project alias. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/ +type ProjectAlias struct { + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` + Name string `json:"name"` +} + +// CreateProjectAliasOptions represents the options for creating a project alias. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/#create-a-project-alias +type CreateProjectAliasOptions struct { + Name *string `json:"name" url:"name,omitempty"` + ProjectID int64 `json:"project_id" url:"project_id,omitempty"` +} + +// ListProjectAliases gets a list of all project aliases. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/#list-all-project-aliases +func (s *ProjectAliasesService) ListProjectAliases(options ...RequestOptionFunc) ([]*ProjectAlias, *Response, error) { + return do[[]*ProjectAlias](s.client, + withPath("project_aliases"), + withRequestOpts(options...), + ) +} + +// GetProjectAlias gets details of a project alias. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/#get-project-alias-details +func (s *ProjectAliasesService) GetProjectAlias(name string, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) { + return do[*ProjectAlias](s.client, + withPath("project_aliases/%s", name), + withRequestOpts(options...), + ) +} + +// CreateProjectAlias creates a new project alias. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/#create-a-project-alias +func (s *ProjectAliasesService) CreateProjectAlias(opt *CreateProjectAliasOptions, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) { + return do[*ProjectAlias](s.client, + withMethod(http.MethodPost), + withPath("project_aliases"), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// DeleteProjectAlias deletes a project alias. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_aliases/#delete-a-project-alias +func (s *ProjectAliasesService) DeleteProjectAlias(name string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("project_aliases/%s", name), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_badges.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_badges.go index c65daa389..e0b14c948 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_badges.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_badges.go @@ -17,17 +17,16 @@ package gitlab import ( - "fmt" "net/http" ) type ( ProjectBadgesServiceInterface interface { ListProjectBadges(pid any, opt *ListProjectBadgesOptions, options ...RequestOptionFunc) ([]*ProjectBadge, *Response, error) - GetProjectBadge(pid any, badge int, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) + GetProjectBadge(pid any, badge int64, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) AddProjectBadge(pid any, opt *AddProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) - EditProjectBadge(pid any, badge int, opt *EditProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) - DeleteProjectBadge(pid any, badge int, options ...RequestOptionFunc) (*Response, error) + EditProjectBadge(pid any, badge int64, opt *EditProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) + DeleteProjectBadge(pid any, badge int64, options ...RequestOptionFunc) (*Response, error) PreviewProjectBadge(pid any, opt *ProjectBadgePreviewOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) } @@ -47,7 +46,7 @@ var _ ProjectBadgesServiceInterface = (*ProjectBadgesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#list-all-badges-of-a-project type ProjectBadge struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` LinkURL string `json:"link_url"` ImageURL string `json:"image_url"` @@ -72,49 +71,22 @@ type ListProjectBadgesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#list-all-badges-of-a-project func (s *ProjectBadgesService) ListProjectBadges(pid any, opt *ListProjectBadgesOptions, options ...RequestOptionFunc) ([]*ProjectBadge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/badges", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pb []*ProjectBadge - resp, err := s.client.Do(req, &pb) - if err != nil { - return nil, resp, err - } - - return pb, resp, nil + return do[[]*ProjectBadge](s.client, + withPath("projects/%s/badges", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectBadge gets a project badge. // // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#get-a-badge-of-a-project -func (s *ProjectBadgesService) GetProjectBadge(pid any, badge int, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/badges/%d", PathEscape(project), badge) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pb := new(ProjectBadge) - resp, err := s.client.Do(req, pb) - if err != nil { - return nil, resp, err - } - - return pb, resp, nil +func (s *ProjectBadgesService) GetProjectBadge(pid any, badge int64, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { + return do[*ProjectBadge](s.client, + withPath("projects/%s/badges/%d", ProjectID{pid}, badge), + withRequestOpts(options...), + ) } // AddProjectBadgeOptions represents the available AddProjectBadge() options. @@ -132,24 +104,12 @@ type AddProjectBadgeOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#add-a-badge-to-a-project func (s *ProjectBadgesService) AddProjectBadge(pid any, opt *AddProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/badges", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pb := new(ProjectBadge) - resp, err := s.client.Do(req, pb) - if err != nil { - return nil, resp, err - } - - return pb, resp, nil + return do[*ProjectBadge](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/badges", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditProjectBadgeOptions represents the available EditProjectBadge() options. @@ -166,25 +126,13 @@ type EditProjectBadgeOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#edit-a-badge-of-a-project -func (s *ProjectBadgesService) EditProjectBadge(pid any, badge int, opt *EditProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/badges/%d", PathEscape(project), badge) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pb := new(ProjectBadge) - resp, err := s.client.Do(req, pb) - if err != nil { - return nil, resp, err - } - - return pb, resp, nil +func (s *ProjectBadgesService) EditProjectBadge(pid any, badge int64, opt *EditProjectBadgeOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { + return do[*ProjectBadge](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/badges/%d", ProjectID{pid}, badge), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteProjectBadge removes a badge from a project. Only project's @@ -192,19 +140,13 @@ func (s *ProjectBadgesService) EditProjectBadge(pid any, badge int, opt *EditPro // // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#remove-a-badge-from-a-project -func (s *ProjectBadgesService) DeleteProjectBadge(pid any, badge int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/badges/%d", PathEscape(project), badge) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectBadgesService) DeleteProjectBadge(pid any, badge int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/badges/%d", ProjectID{pid}, badge), + withRequestOpts(options...), + ) + return resp, err } // ProjectBadgePreviewOptions represents the available PreviewProjectBadge() options. @@ -222,22 +164,9 @@ type ProjectBadgePreviewOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_badges/#preview-a-badge-from-a-project func (s *ProjectBadgesService) PreviewProjectBadge(pid any, opt *ProjectBadgePreviewOptions, options ...RequestOptionFunc) (*ProjectBadge, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/badges/render", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - pb := new(ProjectBadge) - resp, err := s.client.Do(req, &pb) - if err != nil { - return nil, resp, err - } - - return pb, resp, nil + return do[*ProjectBadge](s.client, + withPath("projects/%s/badges/render", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_clusters.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_clusters.go index 0572e1b61..e62da7580 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_clusters.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_clusters.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -28,13 +27,13 @@ type ( // Deprecated: in GitLab 14.5, to be removed in 19.0 ListClusters(pid any, options ...RequestOptionFunc) ([]*ProjectCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - GetCluster(pid any, cluster int, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) + GetCluster(pid any, cluster int64, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 AddCluster(pid any, opt *AddClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - EditCluster(pid any, cluster int, opt *EditClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) + EditCluster(pid any, cluster int64, opt *EditClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) // Deprecated: in GitLab 14.5, to be removed in 19.0 - DeleteCluster(pid any, cluster int, options ...RequestOptionFunc) (*Response, error) + DeleteCluster(pid any, cluster int64, options ...RequestOptionFunc) (*Response, error) } // ProjectClustersService handles communication with the @@ -56,7 +55,7 @@ var _ ProjectClustersServiceInterface = (*ProjectClustersService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/project_clusters/ type ProjectCluster struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Domain string `json:"domain"` CreatedAt *time.Time `json:"created_at"` @@ -88,7 +87,7 @@ type PlatformKubernetes struct { // ManagementProject represents a GitLab Project Cluster management_project. // Deprecated: in GitLab 14.5, to be removed in 19.0 type ManagementProject struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -103,24 +102,10 @@ type ManagementProject struct { // GitLab API docs: // https://docs.gitlab.com/api/project_clusters/#list-project-clusters func (s *ProjectClustersService) ListClusters(pid any, options ...RequestOptionFunc) ([]*ProjectCluster, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/clusters", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var pcs []*ProjectCluster - resp, err := s.client.Do(req, &pcs) - if err != nil { - return nil, resp, err - } - - return pcs, resp, nil + return do[[]*ProjectCluster](s.client, + withPath("projects/%s/clusters", ProjectID{pid}), + withRequestOpts(options...), + ) } // GetCluster gets a cluster. @@ -128,25 +113,11 @@ func (s *ProjectClustersService) ListClusters(pid any, options ...RequestOptionF // // GitLab API docs: // https://docs.gitlab.com/api/project_clusters/#get-a-single-project-cluster -func (s *ProjectClustersService) GetCluster(pid any, cluster int, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/clusters/%d", PathEscape(project), cluster) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pc := new(ProjectCluster) - resp, err := s.client.Do(req, &pc) - if err != nil { - return nil, resp, err - } - - return pc, resp, nil +func (s *ProjectClustersService) GetCluster(pid any, cluster int64, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) { + return do[*ProjectCluster](s.client, + withPath("projects/%s/clusters/%d", ProjectID{pid}, cluster), + withRequestOpts(options...), + ) } // AddClusterOptions represents the available AddCluster() options. @@ -180,24 +151,12 @@ type AddPlatformKubernetesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_clusters/#add-existing-cluster-to-project func (s *ProjectClustersService) AddCluster(pid any, opt *AddClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/clusters/user", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pc := new(ProjectCluster) - resp, err := s.client.Do(req, pc) - if err != nil { - return nil, resp, err - } - - return pc, resp, nil + return do[*ProjectCluster](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/clusters/user", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditClusterOptions represents the available EditCluster() options. @@ -227,25 +186,13 @@ type EditPlatformKubernetesOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_clusters/#edit-project-cluster -func (s *ProjectClustersService) EditCluster(pid any, cluster int, opt *EditClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/clusters/%d", PathEscape(project), cluster) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pc := new(ProjectCluster) - resp, err := s.client.Do(req, pc) - if err != nil { - return nil, resp, err - } - - return pc, resp, nil +func (s *ProjectClustersService) EditCluster(pid any, cluster int64, opt *EditClusterOptions, options ...RequestOptionFunc) (*ProjectCluster, *Response, error) { + return do[*ProjectCluster](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/clusters/%d", ProjectID{pid}, cluster), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteCluster deletes an existing project cluster. @@ -253,17 +200,11 @@ func (s *ProjectClustersService) EditCluster(pid any, cluster int, opt *EditClus // // GitLab API docs: // https://docs.gitlab.com/api/project_clusters/#delete-project-cluster -func (s *ProjectClustersService) DeleteCluster(pid any, cluster int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/clusters/%d", PathEscape(project), cluster) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectClustersService) DeleteCluster(pid any, cluster int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/clusters/%d", ProjectID{pid}, cluster), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_feature_flags.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_feature_flags.go index 53491bccf..af9c41369 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_feature_flags.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_feature_flags.go @@ -1,17 +1,36 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ProjectFeatureFlagServiceInterface interface { + // ListProjectFeatureFlags returns a list with the feature flags of a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/feature_flags/#list-feature-flags-for-a-project ListProjectFeatureFlags(pid any, opt *ListProjectFeatureFlagOptions, options ...RequestOptionFunc) ([]*ProjectFeatureFlag, *Response, error) + // GetProjectFeatureFlag gets a single feature flag for the specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/feature_flags/#get-a-single-feature-flag GetProjectFeatureFlag(pid any, name string, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) + // CreateProjectFeatureFlag creates a feature flag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/feature_flags/#create-a-feature-flag CreateProjectFeatureFlag(pid any, opt *CreateProjectFeatureFlagOptions, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) + // UpdateProjectFeatureFlag updates a feature flag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/feature_flags/#update-a-feature-flag UpdateProjectFeatureFlag(pid any, name string, opt *UpdateProjectFeatureFlagOptions, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) + // DeleteProjectFeatureFlag deletes a feature flag. + // + // GitLab API docs: + // https://docs.gitlab.com/api/feature_flags/#delete-a-feature-flag DeleteProjectFeatureFlag(pid any, name string, options ...RequestOptionFunc) (*Response, error) } @@ -44,7 +63,7 @@ type ProjectFeatureFlag struct { // // GitLab API docs: https://docs.gitlab.com/api/feature_flags/ type ProjectFeatureFlagScope struct { - ID int `json:"id"` + ID int64 `json:"id"` EnvironmentScope string `json:"environment_scope"` } @@ -52,7 +71,7 @@ type ProjectFeatureFlagScope struct { // // GitLab API docs: https://docs.gitlab.com/api/feature_flags/ type ProjectFeatureFlagStrategy struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Parameters *ProjectFeatureFlagStrategyParameter `json:"parameters"` Scopes []*ProjectFeatureFlagScope `json:"scopes"` @@ -66,8 +85,8 @@ type ProjectFeatureFlagStrategyParameter struct { UserIDs string `json:"userIds,omitempty"` Percentage string `json:"percentage,omitempty"` - // Following fields aren't documented in Gitlab API docs, - // but are present in Gitlab API since 13.5. + // Following fields aren't documented in GitLab API docs, + // but are present in GitLab API since 13.5. // Docs: https://docs.getunleash.io/reference/activation-strategies#gradual-rollout Rollout string `json:"rollout,omitempty"` Stickiness string `json:"stickiness,omitempty"` @@ -86,60 +105,25 @@ type ListProjectFeatureFlagOptions struct { Scope *string `url:"scope,omitempty" json:"scope,omitempty"` } -// ListProjectFeatureFlags returns a list with the feature flags of a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/feature_flags/#list-feature-flags-for-a-project func (s *ProjectFeatureFlagService) ListProjectFeatureFlags(pid any, opt *ListProjectFeatureFlagOptions, options ...RequestOptionFunc) ([]*ProjectFeatureFlag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pffs []*ProjectFeatureFlag - resp, err := s.client.Do(req, &pffs) - if err != nil { - return nil, resp, err - } - - return pffs, resp, nil + return do[[]*ProjectFeatureFlag](s.client, + withPath("projects/%s/feature_flags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectFeatureFlag gets a single feature flag for the specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/feature_flags/#get-a-single-feature-flag func (s *ProjectFeatureFlagService) GetProjectFeatureFlag(pid any, name string, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags/%s", PathEscape(project), name) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - flag := new(ProjectFeatureFlag) - resp, err := s.client.Do(req, flag) - if err != nil { - return nil, resp, err - } - - return flag, resp, nil + return do[*ProjectFeatureFlag](s.client, + withPath("projects/%s/feature_flags/%s", ProjectID{pid}, name), + withRequestOpts(options...), + ) } // CreateProjectFeatureFlagOptions represents the available // CreateProjectFeatureFlag() options. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/feature_flags/#create-a-feature-flag type CreateProjectFeatureFlagOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` @@ -152,10 +136,10 @@ type CreateProjectFeatureFlagOptions struct { // FeatureFlagStrategyOptions represents the available feature flag strategy // options. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/feature_flags/#create-a-feature-flag type FeatureFlagStrategyOptions struct { - ID *int `url:"id,omitempty" json:"id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` Parameters *ProjectFeatureFlagStrategyParameter `url:"parameters,omitempty" json:"parameters,omitempty"` Scopes *[]*ProjectFeatureFlagScope `url:"scopes,omitempty" json:"scopes,omitempty"` @@ -164,44 +148,26 @@ type FeatureFlagStrategyOptions struct { // ProjectFeatureFlagScopeOptions represents the available feature flag scope // options. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/feature_flags/#create-a-feature-flag type ProjectFeatureFlagScopeOptions struct { - ID *int `url:"id,omitempty" json:"id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` EnvironmentScope *string `url:"id,omitempty" json:"environment_scope,omitempty"` } -// CreateProjectFeatureFlag creates a feature flag -// -// Gitlab API docs: -// https://docs.gitlab.com/api/feature_flags/#create-a-feature-flag func (s *ProjectFeatureFlagService) CreateProjectFeatureFlag(pid any, opt *CreateProjectFeatureFlagOptions, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags", - PathEscape(project), + return do[*ProjectFeatureFlag](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/feature_flags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - flag := new(ProjectFeatureFlag) - resp, err := s.client.Do(req, flag) - if err != nil { - return flag, resp, err - } - - return flag, resp, nil } // UpdateProjectFeatureFlagOptions represents the available // UpdateProjectFeatureFlag() options. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/feature_flags/#update-a-feature-flag type UpdateProjectFeatureFlagOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` @@ -210,49 +176,20 @@ type UpdateProjectFeatureFlagOptions struct { Strategies *[]*FeatureFlagStrategyOptions `url:"strategies,omitempty" json:"strategies,omitempty"` } -// UpdateProjectFeatureFlag updates a feature flag -// -// Gitlab API docs: -// https://docs.gitlab.com/api/feature_flags/#update-a-feature-flag func (s *ProjectFeatureFlagService) UpdateProjectFeatureFlag(pid any, name string, opt *UpdateProjectFeatureFlagOptions, options ...RequestOptionFunc) (*ProjectFeatureFlag, *Response, error) { - group, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags/%s", - PathEscape(group), - name, + return do[*ProjectFeatureFlag](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/feature_flags/%s", ProjectID{pid}, name), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - flag := new(ProjectFeatureFlag) - resp, err := s.client.Do(req, flag) - if err != nil { - return flag, resp, err - } - - return flag, resp, nil } -// DeleteProjectFeatureFlag deletes a feature flag -// -// Gitlab API docs: -// https://docs.gitlab.com/api/feature_flags/#delete-a-feature-flag func (s *ProjectFeatureFlagService) DeleteProjectFeatureFlag(pid any, name string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/feature_flags/%s", PathEscape(project), name) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/feature_flags/%s", ProjectID{pid}, name), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_import_export.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_import_export.go index 105ec930c..671804a57 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_import_export.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_import_export.go @@ -18,7 +18,6 @@ package gitlab import ( "bytes" - "fmt" "io" "net/http" "time" @@ -26,10 +25,30 @@ import ( type ( ProjectImportExportServiceInterface interface { + // ScheduleExport schedules a project export. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_import_export/#schedule-an-export ScheduleExport(pid any, opt *ScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) + // ExportStatus gets the status of export. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_import_export/#export-status ExportStatus(pid any, options ...RequestOptionFunc) (*ExportStatus, *Response, error) + // ExportDownload downloads the finished export. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_import_export/#export-download ExportDownload(pid any, options ...RequestOptionFunc) ([]byte, *Response, error) + // ImportFromFile imports a project from an archive file. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_import_export/#import-a-file ImportFromFile(archive io.Reader, opt *ImportFileOptions, options ...RequestOptionFunc) (*ImportStatus, *Response, error) + // ImportStatus gets the status of an import. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_import_export/#import-status ImportStatus(pid any, options ...RequestOptionFunc) (*ImportStatus, *Response, error) } @@ -50,7 +69,7 @@ var _ ProjectImportExportServiceInterface = (*ProjectImportExportService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/project_import_export/#import-status type ImportStatus struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -72,104 +91,75 @@ func (s ImportStatus) String() string { // GitLab API docs: // https://docs.gitlab.com/api/project_import_export/#export-status type ExportStatus struct { - ID int `json:"id"` - Description string `json:"description"` - Name string `json:"name"` - NameWithNamespace string `json:"name_with_namespace"` - Path string `json:"path"` - PathWithNamespace string `json:"path_with_namespace"` - CreatedAt *time.Time `json:"created_at"` - ExportStatus string `json:"export_status"` - Message string `json:"message"` - Links struct { - APIURL string `json:"api_url"` - WebURL string `json:"web_url"` - } `json:"_links"` + ID int64 `json:"id"` + Description string `json:"description"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + CreatedAt *time.Time `json:"created_at"` + ExportStatus string `json:"export_status"` + Message string `json:"message"` + Links ExportStatusLinks `json:"_links"` } func (s ExportStatus) String() string { return Stringify(s) } -// ScheduleExportOptions represents the available ScheduleExport() options. +// ExportStatusLinks represents the project export status links. // // GitLab API docs: -// https://docs.gitlab.com/api/project_import_export/#schedule-an-export -type ScheduleExportOptions struct { - Description *string `url:"description,omitempty" json:"description,omitempty"` - Upload struct { - URL *string `url:"url,omitempty" json:"url,omitempty"` - HTTPMethod *string `url:"http_method,omitempty" json:"http_method,omitempty"` - } `url:"upload,omitempty" json:"upload,omitempty"` +// https://docs.gitlab.com/api/project_import_export/#export-status +type ExportStatusLinks struct { + APIURL string `json:"api_url"` + WebURL string `json:"web_url"` } -// ScheduleExport schedules a project export. +func (l ExportStatusLinks) String() string { + return Stringify(l) +} + +// ScheduleExportOptions represents the available ScheduleExport() options. // // GitLab API docs: // https://docs.gitlab.com/api/project_import_export/#schedule-an-export -func (s *ProjectImportExportService) ScheduleExport(pid any, opt *ScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/export", PathEscape(project)) +type ScheduleExportOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` + Upload ScheduleExportUploadOptions `url:"upload,omitempty" json:"upload,omitempty"` +} - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } +type ScheduleExportUploadOptions struct { + URL *string `url:"url,omitempty" json:"url,omitempty"` + HTTPMethod *string `url:"http_method,omitempty" json:"http_method,omitempty"` +} - return s.client.Do(req, nil) +func (s *ProjectImportExportService) ScheduleExport(pid any, opt *ScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/export", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// ExportStatus get the status of export. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_import_export/#export-status func (s *ProjectImportExportService) ExportStatus(pid any, options ...RequestOptionFunc) (*ExportStatus, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/export", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - es := new(ExportStatus) - resp, err := s.client.Do(req, es) - if err != nil { - return nil, resp, err - } - - return es, resp, nil + return do[*ExportStatus](s.client, + withPath("projects/%s/export", ProjectID{pid}), + withRequestOpts(options...), + ) } -// ExportDownload download the finished export. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_import_export/#export-download func (s *ProjectImportExportService) ExportDownload(pid any, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/export/download", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/export/download", ProjectID{pid}), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } // ImportFileOptions represents the available ImportFile() options. @@ -184,54 +174,19 @@ type ImportFileOptions struct { OverrideParams *CreateProjectOptions `url:"override_params,omitempty" json:"override_params,omitempty"` } -// ImportFromFile imports a project from an archive file. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_import_export/#import-a-file func (s *ProjectImportExportService) ImportFromFile(archive io.Reader, opt *ImportFileOptions, options ...RequestOptionFunc) (*ImportStatus, *Response, error) { - req, err := s.client.UploadRequest( - http.MethodPost, - "projects/import", - archive, - "archive.tar.gz", - UploadFile, - opt, - options, + return do[*ImportStatus](s.client, + withMethod(http.MethodPost), + withPath("projects/import"), + withUpload(archive, "archive.tar.gz", UploadFile), + withAPIOpts(opt), + withRequestOpts(options...), ) - if err != nil { - return nil, nil, err - } - - is := new(ImportStatus) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil } -// ImportStatus get the status of an import. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_import_export/#import-status func (s *ProjectImportExportService) ImportStatus(pid any, options ...RequestOptionFunc) (*ImportStatus, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/import", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - is := new(ImportStatus) - resp, err := s.client.Do(req, is) - if err != nil { - return nil, resp, err - } - - return is, resp, nil + return do[*ImportStatus](s.client, + withPath("projects/%s/import", ProjectID{pid}), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_iterations.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_iterations.go index 2495e4cfa..5f33c6cd1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_iterations.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_iterations.go @@ -16,11 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" - "time" -) +import "time" type ( ProjectIterationsServiceInterface interface { @@ -42,13 +38,13 @@ var _ ProjectIterationsServiceInterface = (*ProjectIterationsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/iterations/ type ProjectIteration struct { - ID int `json:"id"` - IID int `json:"iid"` - Sequence int `json:"sequence"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + Sequence int64 `json:"sequence"` + GroupID int64 `json:"group_id"` Title string `json:"title"` Description string `json:"description"` - State int `json:"state"` + State int64 `json:"state"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` DueDate *ISOTime `json:"due_date"` @@ -77,22 +73,9 @@ type ListProjectIterationsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/iterations/#list-project-iterations func (i *ProjectIterationsService) ListProjectIterations(pid any, opt *ListProjectIterationsOptions, options ...RequestOptionFunc) ([]*ProjectIteration, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/iterations", PathEscape(project)) - - req, err := i.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pis []*ProjectIteration - resp, err := i.client.Do(req, &pis) - if err != nil { - return nil, resp, err - } - - return pis, resp, nil + return do[[]*ProjectIteration](i.client, + withPath("projects/%s/iterations", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_markdown_uploads.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_markdown_uploads.go index 88a39320b..67e23fe9c 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_markdown_uploads.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_markdown_uploads.go @@ -17,18 +17,43 @@ package gitlab import ( - "fmt" "io" "net/http" ) type ( ProjectMarkdownUploadsServiceInterface interface { + // UploadProjectMarkdown uploads a markdown file to a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#upload-a-file UploadProjectMarkdown(pid any, content io.Reader, filename string, options ...RequestOptionFunc) (*ProjectMarkdownUploadedFile, *Response, error) + // ListProjectMarkdownUploads gets all markdown uploads for a project. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#list-uploads ListProjectMarkdownUploads(pid any, options ...RequestOptionFunc) ([]*ProjectMarkdownUpload, *Response, error) - DownloadProjectMarkdownUploadByID(pid any, uploadID int, options ...RequestOptionFunc) ([]byte, *Response, error) + // DownloadProjectMarkdownUploadByID downloads a specific upload by ID. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#download-an-uploaded-file-by-id + DownloadProjectMarkdownUploadByID(pid any, uploadID int64, options ...RequestOptionFunc) ([]byte, *Response, error) + // DownloadProjectMarkdownUploadBySecretAndFilename downloads a specific upload + // by secret and filename. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#download-an-uploaded-file-by-secret-and-filename DownloadProjectMarkdownUploadBySecretAndFilename(pid any, secret string, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) - DeleteProjectMarkdownUploadByID(pid any, uploadID int, options ...RequestOptionFunc) (*Response, error) + // DeleteProjectMarkdownUploadByID deletes an upload by ID. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#delete-an-uploaded-file-by-id + DeleteProjectMarkdownUploadByID(pid any, uploadID int64, options ...RequestOptionFunc) (*Response, error) + // DeleteProjectMarkdownUploadBySecretAndFilename deletes an upload + // by secret and filename. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_markdown_uploads/#delete-an-uploaded-file-by-secret-and-filename DeleteProjectMarkdownUploadBySecretAndFilename(pid any, secret string, filename string, options ...RequestOptionFunc) (*Response, error) } @@ -50,85 +75,39 @@ type ( ProjectMarkdownUploadedFile = MarkdownUploadedFile ) -// UploadProjectMarkdown uploads a markdown file to a project. -// -// GitLab docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#upload-a-file func (s *ProjectMarkdownUploadsService) UploadProjectMarkdown(pid any, content io.Reader, filename string, options ...RequestOptionFunc) (*ProjectMarkdownUploadedFile, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/uploads", PathEscape(project)) - - req, err := s.client.UploadRequest( - http.MethodPost, - u, - content, - filename, - UploadFile, - nil, - options, + return do[*ProjectMarkdownUploadedFile](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/uploads", ProjectID{pid}), + withUpload(content, filename, UploadFile), + withRequestOpts(options...), ) - if err != nil { - return nil, nil, err - } - - f := new(ProjectMarkdownUploadedFile) - resp, err := s.client.Do(req, f) - if err != nil { - return nil, resp, err - } - - return f, resp, nil } -// ListProjectMarkdownUploads gets all markdown uploads for a project. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#list-uploads func (s *ProjectMarkdownUploadsService) ListProjectMarkdownUploads(pid any, options ...RequestOptionFunc) ([]*ProjectMarkdownUpload, *Response, error) { - return listMarkdownUploads[ProjectMarkdownUpload](s.client, ProjectResource, pid, nil, options) + return listMarkdownUploads[ProjectMarkdownUpload](s.client, ProjectResource, ProjectID{pid}, nil, options) } -// DownloadProjectMarkdownUploadByID downloads a specific upload by ID. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#download-an-uploaded-file-by-id -func (s *ProjectMarkdownUploadsService) DownloadProjectMarkdownUploadByID(pid any, uploadID int, options ...RequestOptionFunc) ([]byte, *Response, error) { - buffer, resp, err := downloadMarkdownUploadByID(s.client, ProjectResource, pid, uploadID, options) +func (s *ProjectMarkdownUploadsService) DownloadProjectMarkdownUploadByID(pid any, uploadID int64, options ...RequestOptionFunc) ([]byte, *Response, error) { + buffer, resp, err := downloadMarkdownUploadByID(s.client, ProjectResource, ProjectID{pid}, uploadID, options) if err != nil { return nil, resp, err } return buffer.Bytes(), resp, nil } -// DownloadProjectMarkdownUploadBySecretAndFilename downloads a specific upload -// by secret and filename. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#download-an-uploaded-file-by-secret-and-filename func (s *ProjectMarkdownUploadsService) DownloadProjectMarkdownUploadBySecretAndFilename(pid any, secret string, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) { - buffer, resp, err := downloadMarkdownUploadBySecretAndFilename(s.client, ProjectResource, pid, secret, filename, options) + buffer, resp, err := downloadMarkdownUploadBySecretAndFilename(s.client, ProjectResource, ProjectID{pid}, secret, filename, options) if err != nil { return nil, resp, err } return buffer.Bytes(), resp, nil } -// DeleteProjectMarkdownUploadByID deletes an upload by ID. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#delete-an-uploaded-file-by-id -func (s *ProjectMarkdownUploadsService) DeleteProjectMarkdownUploadByID(pid any, uploadID int, options ...RequestOptionFunc) (*Response, error) { - return deleteMarkdownUploadByID(s.client, ProjectResource, pid, uploadID, options) +func (s *ProjectMarkdownUploadsService) DeleteProjectMarkdownUploadByID(pid any, uploadID int64, options ...RequestOptionFunc) (*Response, error) { + return deleteMarkdownUploadByID(s.client, ProjectResource, ProjectID{pid}, uploadID, options) } -// DeleteProjectMarkdownUploadBySecretAndFilename deletes an upload -// by secret and filename. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_markdown_uploads/#delete-an-uploaded-file-by-secret-and-filename func (s *ProjectMarkdownUploadsService) DeleteProjectMarkdownUploadBySecretAndFilename(pid any, secret string, filename string, options ...RequestOptionFunc) (*Response, error) { - return deleteMarkdownUploadBySecretAndFilename(s.client, ProjectResource, pid, secret, filename, options) + return deleteMarkdownUploadBySecretAndFilename(s.client, ProjectResource, ProjectID{pid}, secret, filename, options) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_members.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_members.go index e12a2fa6f..1d2b6a552 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_members.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_members.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -26,11 +25,11 @@ type ( ProjectMembersServiceInterface interface { ListProjectMembers(pid any, opt *ListProjectMembersOptions, options ...RequestOptionFunc) ([]*ProjectMember, *Response, error) ListAllProjectMembers(pid any, opt *ListProjectMembersOptions, options ...RequestOptionFunc) ([]*ProjectMember, *Response, error) - GetProjectMember(pid any, user int, options ...RequestOptionFunc) (*ProjectMember, *Response, error) - GetInheritedProjectMember(pid any, user int, options ...RequestOptionFunc) (*ProjectMember, *Response, error) + GetProjectMember(pid any, user int64, options ...RequestOptionFunc) (*ProjectMember, *Response, error) + GetInheritedProjectMember(pid any, user int64, options ...RequestOptionFunc) (*ProjectMember, *Response, error) AddProjectMember(pid any, opt *AddProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) - EditProjectMember(pid any, user int, opt *EditProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) - DeleteProjectMember(pid any, user int, options ...RequestOptionFunc) (*Response, error) + EditProjectMember(pid any, user int64, opt *EditProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) + DeleteProjectMember(pid any, user int64, options ...RequestOptionFunc) (*Response, error) } // ProjectMembersService handles communication with the project members @@ -49,7 +48,7 @@ var _ ProjectMembersServiceInterface = (*ProjectMembersService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/members/ type ProjectMember struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Email string `json:"email"` Name string `json:"name"` @@ -61,10 +60,11 @@ type ProjectMember struct { WebURL string `json:"web_url"` AvatarURL string `json:"avatar_url"` MemberRole *MemberRole `json:"member_role"` + IsUsingSeat bool `json:"is_using_seat,omitempty"` } type MemberCreatedBy struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Name string `json:"name"` State string `json:"state"` @@ -79,8 +79,9 @@ type MemberCreatedBy struct { // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project type ListProjectMembersOptions struct { ListOptions - Query *string `url:"query,omitempty" json:"query,omitempty"` - UserIDs *[]int `url:"user_ids[],omitempty" json:"user_ids,omitempty"` + Query *string `url:"query,omitempty" json:"query,omitempty"` + UserIDs *[]int64 `url:"user_ids[],omitempty" json:"user_ids,omitempty"` + ShowSeatInfo *bool `url:"show_seat_info,omitempty" json:"show_seat_info,omitempty"` } // ListProjectMembers gets a list of a project's team members viewable by the @@ -90,24 +91,11 @@ type ListProjectMembersOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project func (s *ProjectMembersService) ListProjectMembers(pid any, opt *ListProjectMembersOptions, options ...RequestOptionFunc) ([]*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pm []*ProjectMember - resp, err := s.client.Do(req, &pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil + return do[[]*ProjectMember](s.client, + withPath("projects/%s/members", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListAllProjectMembers gets a list of a project's team members viewable by the @@ -117,74 +105,33 @@ func (s *ProjectMembersService) ListProjectMembers(pid any, opt *ListProjectMemb // GitLab API docs: // https://docs.gitlab.com/api/members/#list-all-members-of-a-group-or-project-including-inherited-and-invited-members func (s *ProjectMembersService) ListAllProjectMembers(pid any, opt *ListProjectMembersOptions, options ...RequestOptionFunc) ([]*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members/all", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pm []*ProjectMember - resp, err := s.client.Do(req, &pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil + return do[[]*ProjectMember](s.client, + withPath("projects/%s/members/all", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectMember gets a project team member. // // GitLab API docs: // https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project -func (s *ProjectMembersService) GetProjectMember(pid any, user int, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members/%d", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMember) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil +func (s *ProjectMembersService) GetProjectMember(pid any, user int64, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { + return do[*ProjectMember](s.client, + withPath("projects/%s/members/%d", ProjectID{pid}, user), + withRequestOpts(options...), + ) } // GetInheritedProjectMember gets a project team member, including inherited // // GitLab API docs: // https://docs.gitlab.com/api/members/#get-a-member-of-a-group-or-project-including-inherited-and-invited-members -func (s *ProjectMembersService) GetInheritedProjectMember(pid any, user int, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members/all/%d", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMember) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil +func (s *ProjectMembersService) GetInheritedProjectMember(pid any, user int64, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { + return do[*ProjectMember](s.client, + withPath("projects/%s/members/all/%d", ProjectID{pid}, user), + withRequestOpts(options...), + ) } // AddProjectMemberOptions represents the available AddProjectMember() options. @@ -196,7 +143,7 @@ type AddProjectMemberOptions struct { Username *string `url:"username,omitempty" json:"username,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` } // AddProjectMember adds a user to a project team. This is an idempotent @@ -207,24 +154,12 @@ type AddProjectMemberOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/members/#add-a-member-to-a-group-or-project func (s *ProjectMembersService) AddProjectMember(pid any, opt *AddProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMember) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil + return do[*ProjectMember](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/members", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditProjectMemberOptions represents the available EditProjectMember() options. @@ -234,49 +169,31 @@ func (s *ProjectMembersService) AddProjectMember(pid any, opt *AddProjectMemberO type EditProjectMemberOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` ExpiresAt *string `url:"expires_at,omitempty" json:"expires_at,omitempty"` - MemberRoleID *int `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` + MemberRoleID *int64 `url:"member_role_id,omitempty" json:"member_role_id,omitempty"` } // EditProjectMember updates a project team member to a specified access level.. // // GitLab API docs: // https://docs.gitlab.com/api/members/#edit-a-member-of-a-group-or-project -func (s *ProjectMembersService) EditProjectMember(pid any, user int, opt *EditProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/members/%d", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMember) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil +func (s *ProjectMembersService) EditProjectMember(pid any, user int64, opt *EditProjectMemberOptions, options ...RequestOptionFunc) (*ProjectMember, *Response, error) { + return do[*ProjectMember](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/members/%d", ProjectID{pid}, user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteProjectMember removes a user from a project team. // // GitLab API docs: // https://docs.gitlab.com/api/members/#remove-a-member-from-a-group-or-project -func (s *ProjectMembersService) DeleteProjectMember(pid any, user int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/members/%d", PathEscape(project), user) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectMembersService) DeleteProjectMember(pid any, user int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/members/%d", ProjectID{pid}, user), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_mirror.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_mirror.go index c8ef60970..51cf3eaa1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_mirror.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_mirror.go @@ -17,19 +17,47 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ProjectMirrorServiceInterface interface { + // ListProjectMirror gets a list of mirrors configured on the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#list-a-projects-remote-mirrors ListProjectMirror(pid any, opt *ListProjectMirrorOptions, options ...RequestOptionFunc) ([]*ProjectMirror, *Response, error) - GetProjectMirror(pid any, mirror int, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) - GetProjectMirrorPublicKey(pid any, mirror int, options ...RequestOptionFunc) (*ProjectMirrorPublicKey, *Response, error) + // GetProjectMirror gets a single mirror configured on the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#get-a-single-projects-remote-mirror + GetProjectMirror(pid any, mirror int64, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) + // GetProjectMirrorPublicKey gets the SSH public key for a single mirror configured on the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#get-a-single-projects-remote-mirror-public-key + GetProjectMirrorPublicKey(pid any, mirror int64, options ...RequestOptionFunc) (*ProjectMirrorPublicKey, *Response, error) + // AddProjectMirror creates a new mirror on the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#create-a-push-mirror AddProjectMirror(pid any, opt *AddProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) - EditProjectMirror(pid any, mirror int, opt *EditProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) - DeleteProjectMirror(pid any, mirror int, options ...RequestOptionFunc) (*Response, error) + // EditProjectMirror updates a remote mirror's attributes. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#update-a-remote-mirrors-attributes + EditProjectMirror(pid any, mirror int64, opt *EditProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) + // DeleteProjectMirror deletes a project mirror. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#delete-a-remote-mirror + DeleteProjectMirror(pid any, mirror int64, options ...RequestOptionFunc) (*Response, error) + // ForcePushMirrorUpdate triggers a manual update for a project mirror. + // + // GitLab API docs: + // https://docs.gitlab.com/api/remote_mirrors/#force-push-mirror-update + ForcePushMirrorUpdate(pid any, mirror int64, options ...RequestOptionFunc) (*Response, error) } // ProjectMirrorService handles communication with the project mirror @@ -48,7 +76,7 @@ var _ ProjectMirrorServiceInterface = (*ProjectMirrorService)(nil) // GitLAb API docs: https://docs.gitlab.com/api/remote_mirrors/ type ProjectMirror struct { Enabled bool `json:"enabled"` - ID int `json:"id"` + ID int64 `json:"id"` LastError string `json:"last_error"` LastSuccessfulUpdateAt *time.Time `json:"last_successful_update_at"` LastUpdateAt *time.Time `json:"last_update_at"` @@ -66,81 +94,30 @@ type ProjectMirrorPublicKey struct { } // ListProjectMirrorOptions represents the available ListProjectMirror() options. -type ListProjectMirrorOptions ListOptions +type ListProjectMirrorOptions struct { + ListOptions +} -// ListProjectMirror gets a list of mirrors configured on the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#list-a-projects-remote-mirrors func (s *ProjectMirrorService) ListProjectMirror(pid any, opt *ListProjectMirrorOptions, options ...RequestOptionFunc) ([]*ProjectMirror, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pm []*ProjectMirror - resp, err := s.client.Do(req, &pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil + return do[[]*ProjectMirror](s.client, + withPath("projects/%s/remote_mirrors", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectMirror gets a single mirror configured on the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#get-a-single-projects-remote-mirror -func (s *ProjectMirrorService) GetProjectMirror(pid any, mirror int, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors/%d", PathEscape(project), mirror) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMirror) - resp, err := s.client.Do(req, &pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil +func (s *ProjectMirrorService) GetProjectMirror(pid any, mirror int64, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) { + return do[*ProjectMirror](s.client, + withPath("projects/%s/remote_mirrors/%d", ProjectID{pid}, mirror), + withRequestOpts(options...), + ) } -// GetProjectMirrorPublicKey gets the SSH public key for a single mirror configured on the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#get-a-single-projects-remote-mirror-public-key -func (s *ProjectMirrorService) GetProjectMirrorPublicKey(pid any, mirror int, options ...RequestOptionFunc) (*ProjectMirrorPublicKey, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors/%d/public_key", PathEscape(project), mirror) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pmpk := new(ProjectMirrorPublicKey) - resp, err := s.client.Do(req, &pmpk) - if err != nil { - return nil, resp, err - } - - return pmpk, resp, nil +func (s *ProjectMirrorService) GetProjectMirrorPublicKey(pid any, mirror int64, options ...RequestOptionFunc) (*ProjectMirrorPublicKey, *Response, error) { + return do[*ProjectMirrorPublicKey](s.client, + withPath("projects/%s/remote_mirrors/%d/public_key", ProjectID{pid}, mirror), + withRequestOpts(options...), + ) } // AddProjectMirrorOptions contains the properties requires to create @@ -157,29 +134,13 @@ type AddProjectMirrorOptions struct { AuthMethod *string `url:"auth_method,omitempty" json:"auth_method,omitempty"` } -// AddProjectMirror creates a new mirror on the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#create-a-push-mirror func (s *ProjectMirrorService) AddProjectMirror(pid any, opt *AddProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMirror) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil + return do[*ProjectMirror](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/remote_mirrors", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditProjectMirrorOptions contains the properties requires to edit @@ -195,46 +156,29 @@ type EditProjectMirrorOptions struct { AuthMethod *string `url:"auth_method,omitempty" json:"auth_method,omitempty"` } -// EditProjectMirror updates a project team member to a specified access level.. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#update-a-remote-mirrors-attributes -func (s *ProjectMirrorService) EditProjectMirror(pid any, mirror int, opt *EditProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors/%d", PathEscape(project), mirror) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pm := new(ProjectMirror) - resp, err := s.client.Do(req, pm) - if err != nil { - return nil, resp, err - } - - return pm, resp, nil +func (s *ProjectMirrorService) EditProjectMirror(pid any, mirror int64, opt *EditProjectMirrorOptions, options ...RequestOptionFunc) (*ProjectMirror, *Response, error) { + return do[*ProjectMirror](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/remote_mirrors/%d", ProjectID{pid}, mirror), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteProjectMirror deletes a project mirror. -// -// GitLab API docs: -// https://docs.gitlab.com/api/remote_mirrors/#delete-a-remote-mirror -func (s *ProjectMirrorService) DeleteProjectMirror(pid any, mirror int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/remote_mirrors/%d", PathEscape(project), mirror) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } +func (s *ProjectMirrorService) DeleteProjectMirror(pid any, mirror int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/remote_mirrors/%d", ProjectID{pid}, mirror), + withRequestOpts(options...), + ) + return resp, err +} - return s.client.Do(req, nil) +func (s *ProjectMirrorService) ForcePushMirrorUpdate(pid any, mirror int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/remote_mirrors/%d/sync", ProjectID{pid}, mirror), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_repository_storage_move.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_repository_storage_move.go index fe23dfbc8..a3411ed3d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_repository_storage_move.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_repository_storage_move.go @@ -17,18 +17,43 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ProjectRepositoryStorageMoveServiceInterface interface { + // RetrieveAllStorageMoves retrieves all project repository storage moves + // accessible by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#retrieve-all-project-repository-storage-moves RetrieveAllStorageMoves(opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) - RetrieveAllStorageMovesForProject(project int, opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) - GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) - GetStorageMoveForProject(project int, repositoryStorage int, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) - ScheduleStorageMoveForProject(project int, opts ScheduleStorageMoveForProjectOptions, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) + // RetrieveAllStorageMovesForProject retrieves all repository storage moves for + // a single project accessible by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#retrieve-all-repository-storage-moves-for-a-project + RetrieveAllStorageMovesForProject(project int64, opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) + // GetStorageMove gets a single project repository storage move. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#get-a-single-project-repository-storage-move + GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) + // GetStorageMoveForProject gets a single repository storage move for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#get-a-single-repository-storage-move-for-a-project + GetStorageMoveForProject(project int64, repositoryStorage int64, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) + // ScheduleStorageMoveForProject schedule a repository to be moved for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#schedule-a-repository-storage-move-for-a-project + ScheduleStorageMoveForProject(project int64, opts ScheduleStorageMoveForProjectOptions, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) + // ScheduleAllStorageMoves schedules all repositories to be moved. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_repository_storage_moves/#schedule-repository-storage-moves-for-all-projects-on-a-storage-shard ScheduleAllStorageMoves(opts ScheduleAllProjectStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) } @@ -49,7 +74,7 @@ var _ ProjectRepositoryStorageMoveServiceInterface = (*ProjectRepositoryStorageM // GitLab API docs: // https://docs.gitlab.com/api/project_repository_storage_moves/ type ProjectRepositoryStorageMove struct { - ID int `json:"id"` + ID int64 `json:"id"` CreatedAt *time.Time `json:"created_at"` State string `json:"state"` SourceStorageName string `json:"source_storage_name"` @@ -58,7 +83,7 @@ type ProjectRepositoryStorageMove struct { } type RepositoryProject struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -72,90 +97,38 @@ type RepositoryProject struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_repository_storage_moves/#retrieve-all-project-repository-storage-moves -type RetrieveAllProjectStorageMovesOptions ListOptions +type RetrieveAllProjectStorageMovesOptions struct { + ListOptions +} -// RetrieveAllStorageMoves retrieves all project repository storage moves -// accessible by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#retrieve-all-project-repository-storage-moves func (p ProjectRepositoryStorageMoveService) RetrieveAllStorageMoves(opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) { - req, err := p.client.NewRequest(http.MethodGet, "project_repository_storage_moves", opts, options) - if err != nil { - return nil, nil, err - } - - var psms []*ProjectRepositoryStorageMove - resp, err := p.client.Do(req, &psms) - if err != nil { - return nil, resp, err - } - - return psms, resp, err + return do[[]*ProjectRepositoryStorageMove](p.client, + withPath("project_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// RetrieveAllStorageMovesForProject retrieves all repository storage moves for -// a single project accessible by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#retrieve-all-repository-storage-moves-for-a-project -func (p ProjectRepositoryStorageMoveService) RetrieveAllStorageMovesForProject(project int, opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("projects/%d/repository_storage_moves", project) - - req, err := p.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var psms []*ProjectRepositoryStorageMove - resp, err := p.client.Do(req, &psms) - if err != nil { - return nil, resp, err - } - - return psms, resp, err +func (p ProjectRepositoryStorageMoveService) RetrieveAllStorageMovesForProject(project int64, opts RetrieveAllProjectStorageMovesOptions, options ...RequestOptionFunc) ([]*ProjectRepositoryStorageMove, *Response, error) { + return do[[]*ProjectRepositoryStorageMove](p.client, + withPath("projects/%d/repository_storage_moves", project), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// GetStorageMove gets a single project repository storage move. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#get-a-single-project-repository-storage-move -func (p ProjectRepositoryStorageMoveService) GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("project_repository_storage_moves/%d", repositoryStorage) - - req, err := p.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - psm := new(ProjectRepositoryStorageMove) - resp, err := p.client.Do(req, psm) - if err != nil { - return nil, resp, err - } - - return psm, resp, err +func (p ProjectRepositoryStorageMoveService) GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { + return do[*ProjectRepositoryStorageMove](p.client, + withPath("project_repository_storage_moves/%d", repositoryStorage), + withRequestOpts(options...), + ) } -// GetStorageMoveForProject gets a single repository storage move for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#get-a-single-repository-storage-move-for-a-project -func (p ProjectRepositoryStorageMoveService) GetStorageMoveForProject(project int, repositoryStorage int, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("projects/%d/repository_storage_moves/%d", project, repositoryStorage) - - req, err := p.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - psm := new(ProjectRepositoryStorageMove) - resp, err := p.client.Do(req, psm) - if err != nil { - return nil, resp, err - } - - return psm, resp, err +func (p ProjectRepositoryStorageMoveService) GetStorageMoveForProject(project int64, repositoryStorage int64, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { + return do[*ProjectRepositoryStorageMove](p.client, + withPath("projects/%d/repository_storage_moves/%d", project, repositoryStorage), + withRequestOpts(options...), + ) } // ScheduleStorageMoveForProjectOptions represents the available @@ -167,25 +140,13 @@ type ScheduleStorageMoveForProjectOptions struct { DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"` } -// ScheduleStorageMoveForProject schedule a repository to be moved for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#schedule-a-repository-storage-move-for-a-project -func (p ProjectRepositoryStorageMoveService) ScheduleStorageMoveForProject(project int, opts ScheduleStorageMoveForProjectOptions, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("projects/%d/repository_storage_moves", project) - - req, err := p.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - psm := new(ProjectRepositoryStorageMove) - resp, err := p.client.Do(req, psm) - if err != nil { - return nil, resp, err - } - - return psm, resp, err +func (p ProjectRepositoryStorageMoveService) ScheduleStorageMoveForProject(project int64, opts ScheduleStorageMoveForProjectOptions, options ...RequestOptionFunc) (*ProjectRepositoryStorageMove, *Response, error) { + return do[*ProjectRepositoryStorageMove](p.client, + withMethod(http.MethodPost), + withPath("projects/%d/repository_storage_moves", project), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // ScheduleAllProjectStorageMovesOptions represents the available @@ -198,15 +159,12 @@ type ScheduleAllProjectStorageMovesOptions struct { DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"` } -// ScheduleAllStorageMoves schedules all repositories to be moved. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_repository_storage_moves/#schedule-repository-storage-moves-for-all-projects-on-a-storage-shard func (p ProjectRepositoryStorageMoveService) ScheduleAllStorageMoves(opts ScheduleAllProjectStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := p.client.NewRequest(http.MethodPost, "project_repository_storage_moves", opts, options) - if err != nil { - return nil, err - } - - return p.client.Do(req, nil) + _, resp, err := do[none](p.client, + withMethod(http.MethodPost), + withPath("project_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_security_settings.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_security_settings.go index 64768ca0a..d200c576a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_security_settings.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_security_settings.go @@ -16,21 +16,29 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( ProjectSecuritySettingsServiceInterface interface { + // ListProjectSecuritySettings lists all of a project's security settings. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_security_settings/#list-project-security-settings ListProjectSecuritySettings(pid any, options ...RequestOptionFunc) (*ProjectSecuritySettings, *Response, error) + // UpdateSecretPushProtectionEnabledSetting updates the secret_push_protection_enabled + // setting for a project to the provided value. + // + // GitLab API Docs: + // https://docs.gitlab.com/api/project_security_settings/#update-secret_push_protection_enabled-setting UpdateSecretPushProtectionEnabledSetting(pid any, opt UpdateProjectSecuritySettingsOptions, options ...RequestOptionFunc) (*ProjectSecuritySettings, *Response, error) } // ProjectSecuritySettingsService handles communication with the Project Security Settings // related methods of the GitLab API. // - // Gitlab API docs: + // GitLab API docs: // https://docs.gitlab.com/api/project_security_settings/ ProjectSecuritySettingsService struct { client *Client @@ -41,7 +49,7 @@ var _ ProjectSecuritySettingsServiceInterface = (*ProjectSecuritySettingsService // ProjectSecuritySettings represents the project security settings data. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/project_security_settings/ type ProjectSecuritySettings struct { ProjectID int64 `json:"project_id"` @@ -64,28 +72,11 @@ func (s ProjectSecuritySettings) String() string { return Stringify(s) } -// ListProjectSecuritySettings lists all of a project's security settings. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_security_settings/#list-project-security-settings func (s *ProjectSecuritySettingsService) ListProjectSecuritySettings(pid any, options ...RequestOptionFunc) (*ProjectSecuritySettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/security_settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - settings := new(ProjectSecuritySettings) - resp, err := s.client.Do(req, &settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, err + return do[*ProjectSecuritySettings](s.client, + withPath("projects/%s/security_settings", ProjectID{pid}), + withRequestOpts(options...), + ) } // UpdateProjectSecuritySettingsOptions represent the request options for updating @@ -97,27 +88,11 @@ type UpdateProjectSecuritySettingsOptions struct { SecretPushProtectionEnabled *bool `url:"secret_push_protection_enabled,omitempty" json:"secret_push_protection_enabled,omitempty"` } -// UpdateSecretPushProtectionEnabledSetting updates the secret_push_protection_enabled -// setting for the all projects in a project to the provided value. -// -// GitLab API Docs: -// https://docs.gitlab.com/api/project_security_settings/#update-secret_push_protection_enabled-setting func (s *ProjectSecuritySettingsService) UpdateSecretPushProtectionEnabledSetting(pid any, opt UpdateProjectSecuritySettingsOptions, options ...RequestOptionFunc) (*ProjectSecuritySettings, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/security_settings", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - settings := new(ProjectSecuritySettings) - resp, err := s.client.Do(req, &settings) - if err != nil { - return nil, resp, err - } - - return settings, resp, err + return do[*ProjectSecuritySettings](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/security_settings", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_snippets.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_snippets.go index 61c7e59e2..b35e2a7cf 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_snippets.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_snippets.go @@ -18,18 +18,17 @@ package gitlab import ( "bytes" - "fmt" "net/http" ) type ( ProjectSnippetsServiceInterface interface { ListSnippets(pid any, opt *ListProjectSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) - GetSnippet(pid any, snippet int, options ...RequestOptionFunc) (*Snippet, *Response, error) + GetSnippet(pid any, snippet int64, options ...RequestOptionFunc) (*Snippet, *Response, error) CreateSnippet(pid any, opt *CreateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) - UpdateSnippet(pid any, snippet int, opt *UpdateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) - DeleteSnippet(pid any, snippet int, options ...RequestOptionFunc) (*Response, error) - SnippetContent(pid any, snippet int, options ...RequestOptionFunc) ([]byte, *Response, error) + UpdateSnippet(pid any, snippet int64, opt *UpdateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) + DeleteSnippet(pid any, snippet int64, options ...RequestOptionFunc) (*Response, error) + SnippetContent(pid any, snippet int64, options ...RequestOptionFunc) ([]byte, *Response, error) } // ProjectSnippetsService handles communication with the project snippets @@ -46,55 +45,30 @@ var _ ProjectSnippetsServiceInterface = (*ProjectSnippetsService)(nil) // ListProjectSnippetsOptions represents the available ListSnippets() options. // // GitLab API docs: https://docs.gitlab.com/api/project_snippets/#list-snippets -type ListProjectSnippetsOptions ListOptions +type ListProjectSnippetsOptions struct { + ListOptions +} // ListSnippets gets a list of project snippets. // // GitLab API docs: https://docs.gitlab.com/api/project_snippets/#list-snippets func (s *ProjectSnippetsService) ListSnippets(pid any, opt *ListProjectSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Snippet - resp, err := s.client.Do(req, &ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[[]*Snippet](s.client, + withPath("projects/%s/snippets", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetSnippet gets a single project snippet // // GitLab API docs: // https://docs.gitlab.com/api/project_snippets/#single-snippet -func (s *ProjectSnippetsService) GetSnippet(pid any, snippet int, options ...RequestOptionFunc) (*Snippet, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil +func (s *ProjectSnippetsService) GetSnippet(pid any, snippet int64, options ...RequestOptionFunc) (*Snippet, *Response, error) { + return do[*Snippet](s.client, + withPath("projects/%s/snippets/%d", ProjectID{pid}, snippet), + withRequestOpts(options...), + ) } // CreateProjectSnippetOptions represents the available CreateSnippet() options. @@ -119,24 +93,12 @@ type CreateProjectSnippetOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_snippets/#create-new-snippet func (s *ProjectSnippetsService) CreateSnippet(pid any, opt *CreateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil + return do[*Snippet](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/snippets", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateProjectSnippetOptions represents the available UpdateSnippet() options. @@ -160,25 +122,13 @@ type UpdateProjectSnippetOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_snippets/#update-snippet -func (s *ProjectSnippetsService) UpdateSnippet(pid any, snippet int, opt *UpdateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) - if err != nil { - return nil, resp, err - } - - return ps, resp, nil +func (s *ProjectSnippetsService) UpdateSnippet(pid any, snippet int64, opt *UpdateProjectSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { + return do[*Snippet](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/snippets/%d", ProjectID{pid}, snippet), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteSnippet deletes an existing project snippet. This is an idempotent @@ -187,42 +137,26 @@ func (s *ProjectSnippetsService) UpdateSnippet(pid any, snippet int, opt *Update // // GitLab API docs: // https://docs.gitlab.com/api/project_snippets/#delete-snippet -func (s *ProjectSnippetsService) DeleteSnippet(pid any, snippet int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectSnippetsService) DeleteSnippet(pid any, snippet int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/snippets/%d", ProjectID{pid}, snippet), + withRequestOpts(options...), + ) + return resp, err } // SnippetContent returns the raw project snippet as plain text. // // GitLab API docs: // https://docs.gitlab.com/api/project_snippets/#snippet-content -func (s *ProjectSnippetsService) SnippetContent(pid any, snippet int, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/snippets/%d/raw", PathEscape(project), snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) +func (s *ProjectSnippetsService) SnippetContent(pid any, snippet int64, options ...RequestOptionFunc) ([]byte, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/snippets/%d/raw", ProjectID{pid}, snippet), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_statistics.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_statistics.go new file mode 100644 index 000000000..86dfd022e --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_statistics.go @@ -0,0 +1,44 @@ +package gitlab + +type ( + ProjectStatisticsServiceInterface interface { + // Last30DaysStatistics gets the project statistics for the last 30 days. + // + // GitLab API docs: https://docs.gitlab.com/api/project_statistics/#get-the-statistics-of-the-last-30-days + Last30DaysStatistics(pid any, options ...RequestOptionFunc) (*ProjectStatistics, *Response, error) + } + + // ProjectStatisticsService handles communication with the project statistics related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/project_statistics + ProjectStatisticsService struct { + client *Client + } +) + +// ProjectStatistics represents the Project Statistics. +// +// GitLab API docs: https://docs.gitlab.com/api/project_statistics +type ProjectStatistics struct { + Fetches FetchStats `json:"fetches"` +} + +type FetchStats struct { + Total int64 `json:"total"` + Days []DayStats `json:"days"` +} + +type DayStats struct { + Count int64 `json:"count"` + Date string `json:"date"` +} + +var _ ProjectStatisticsServiceInterface = (*ProjectStatisticsService)(nil) + +func (s *ProjectStatisticsService) Last30DaysStatistics(pid any, options ...RequestOptionFunc) (*ProjectStatistics, *Response, error) { + return do[*ProjectStatistics](s.client, + withPath("projects/%s/statistics", ProjectID{pid}), + withRequestOpts(options...), + ) +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_templates.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_templates.go index 1e7c6489a..081127084 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_templates.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_templates.go @@ -16,14 +16,16 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( ProjectTemplatesServiceInterface interface { + // ListTemplates gets a list of project templates. + // + // GitLab API docs: https://docs.gitlab.com/api/project_templates/#get-all-templates-of-a-particular-type ListTemplates(pid any, templateType string, opt *ListProjectTemplatesOptions, options ...RequestOptionFunc) ([]*ProjectTemplate, *Response, error) + // GetProjectTemplate gets a single project template. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_templates/#get-one-template-of-a-particular-type GetProjectTemplate(pid any, templateType string, templateName string, options ...RequestOptionFunc) (*ProjectTemplate, *Response, error) } @@ -65,55 +67,21 @@ func (s ProjectTemplate) String() string { // https://docs.gitlab.com/api/project_templates/#get-all-templates-of-a-particular-type type ListProjectTemplatesOptions struct { ListOptions - ID *int `url:"id,omitempty" json:"id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` Type *string `url:"type,omitempty" json:"type,omitempty"` } -// ListTemplates gets a list of project templates. -// -// GitLab API docs: https://docs.gitlab.com/api/project_templates/#get-all-templates-of-a-particular-type func (s *ProjectTemplatesService) ListTemplates(pid any, templateType string, opt *ListProjectTemplatesOptions, options ...RequestOptionFunc) ([]*ProjectTemplate, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/templates/%s", PathEscape(project), templateType) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pt []*ProjectTemplate - resp, err := s.client.Do(req, &pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[[]*ProjectTemplate](s.client, + withPath("projects/%s/templates/%s", ProjectID{pid}, NoEscape{templateType}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectTemplate gets a single project template. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_templates/#get-one-template-of-a-particular-type func (s *ProjectTemplatesService) GetProjectTemplate(pid any, templateType string, templateName string, options ...RequestOptionFunc) (*ProjectTemplate, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/templates/%s/%s", PathEscape(project), templateType, templateName) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ptd := new(ProjectTemplate) - resp, err := s.client.Do(req, ptd) - if err != nil { - return nil, resp, err - } - - return ptd, resp, nil + return do[*ProjectTemplate](s.client, + withPath("projects/%s/templates/%s/%s", ProjectID{pid}, NoEscape{templateType}, NoEscape{templateName}), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_variables.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_variables.go index 870837ec6..d2b356e36 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_variables.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_variables.go @@ -17,17 +17,36 @@ package gitlab import ( - "fmt" "net/http" "net/url" ) type ( ProjectVariablesServiceInterface interface { + // ListVariables gets a list of all variables in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_level_variables/#list-project-variables ListVariables(pid any, opt *ListProjectVariablesOptions, options ...RequestOptionFunc) ([]*ProjectVariable, *Response, error) + // GetVariable gets a variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_level_variables/#get-a-single-variable GetVariable(pid any, key string, opt *GetProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) + // CreateVariable creates a new project variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_level_variables/#create-a-variable CreateVariable(pid any, opt *CreateProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) + // UpdateVariable updates a project's variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_level_variables/#update-a-variable UpdateVariable(pid any, key string, opt *UpdateProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) + // RemoveVariable removes a project's variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_level_variables/#delete-a-variable RemoveVariable(pid any, key string, opt *RemoveProjectVariableOptions, options ...RequestOptionFunc) (*Response, error) } @@ -65,7 +84,7 @@ func (v ProjectVariable) String() string { // VariableFilter filters available for project variable related functions type VariableFilter struct { - EnvironmentScope string `url:"environment_scope, omitempty" json:"environment_scope,omitempty"` + EnvironmentScope string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"` } // ListProjectVariablesOptions represents the available options for listing variables @@ -73,31 +92,16 @@ type VariableFilter struct { // // GitLab API docs: // https://docs.gitlab.com/api/project_level_variables/#list-project-variables -type ListProjectVariablesOptions ListOptions +type ListProjectVariablesOptions struct { + ListOptions +} -// ListVariables gets a list of all variables in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_level_variables/#list-project-variables func (s *ProjectVariablesService) ListVariables(pid any, opt *ListProjectVariablesOptions, options ...RequestOptionFunc) ([]*ProjectVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/variables", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var vs []*ProjectVariable - resp, err := s.client.Do(req, &vs) - if err != nil { - return nil, resp, err - } - - return vs, resp, nil + return do[[]*ProjectVariable](s.client, + withPath("projects/%s/variables", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectVariableOptions represents the available GetVariable() @@ -109,29 +113,12 @@ type GetProjectVariableOptions struct { Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"` } -// GetVariable gets a variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_level_variables/#get-a-single-variable func (s *ProjectVariablesService) GetVariable(pid any, key string, opt *GetProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/variables/%s", PathEscape(project), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(ProjectVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*ProjectVariable](s.client, + withPath("projects/%s/variables/%s", ProjectID{pid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateProjectVariableOptions represents the available CreateVariable() @@ -151,29 +138,13 @@ type CreateProjectVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// CreateVariable creates a new project variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_level_variables/#create-a-variable func (s *ProjectVariablesService) CreateVariable(pid any, opt *CreateProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/variables", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(ProjectVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*ProjectVariable](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/variables", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateProjectVariableOptions represents the available UpdateVariable() @@ -192,29 +163,13 @@ type UpdateProjectVariableOptions struct { VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"` } -// UpdateVariable updates a project's variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_level_variables/#update-a-variable func (s *ProjectVariablesService) UpdateVariable(pid any, key string, opt *UpdateProjectVariableOptions, options ...RequestOptionFunc) (*ProjectVariable, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/variables/%s", PathEscape(project), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - v := new(ProjectVariable) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*ProjectVariable](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/variables/%s", ProjectID{pid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // RemoveProjectVariableOptions represents the available RemoveVariable() @@ -226,21 +181,12 @@ type RemoveProjectVariableOptions struct { Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"` } -// RemoveVariable removes a project's variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_level_variables/#delete-a-variable func (s *ProjectVariablesService) RemoveVariable(pid any, key string, opt *RemoveProjectVariableOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/variables/%s", PathEscape(project), url.PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/variables/%s", ProjectID{pid}, url.PathEscape(key)), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/project_vulnerabilities.go b/vendor/gitlab.com/gitlab-org/api/client-go/project_vulnerabilities.go index aa85f43ba..783adf6c1 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/project_vulnerabilities.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/project_vulnerabilities.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -49,29 +48,29 @@ var _ ProjectVulnerabilitiesServiceInterface = (*ProjectVulnerabilitiesService)( // // GitLab API docs: https://docs.gitlab.com/api/project_vulnerabilities/ type ProjectVulnerability struct { - AuthorID int `json:"author_id"` + AuthorID int64 `json:"author_id"` Confidence string `json:"confidence"` CreatedAt *time.Time `json:"created_at"` Description string `json:"description"` DismissedAt *time.Time `json:"dismissed_at"` - DismissedByID int `json:"dismissed_by_id"` + DismissedByID int64 `json:"dismissed_by_id"` DueDate *time.Time `json:"due_date"` Finding *Finding `json:"finding"` - ID int `json:"id"` + ID int64 `json:"id"` LastEditedAt *time.Time `json:"last_edited_at"` - LastEditedByID int `json:"last_edited_by_id"` + LastEditedByID int64 `json:"last_edited_by_id"` Project *Project `json:"project"` ProjectDefaultBranch string `json:"project_default_branch"` ReportType string `json:"report_type"` ResolvedAt *time.Time `json:"resolved_at"` - ResolvedByID int `json:"resolved_by_id"` + ResolvedByID int64 `json:"resolved_by_id"` ResolvedOnDefaultBranch bool `json:"resolved_on_default_branch"` Severity string `json:"severity"` StartDate *time.Time `json:"start_date"` State string `json:"state"` Title string `json:"title"` UpdatedAt *time.Time `json:"updated_at"` - UpdatedByID int `json:"updated_by_id"` + UpdatedByID int64 `json:"updated_by_id"` } // Finding represents a GitLab project vulnerability finding. @@ -81,20 +80,20 @@ type ProjectVulnerability struct { type Finding struct { Confidence string `json:"confidence"` CreatedAt *time.Time `json:"created_at"` - ID int `json:"id"` + ID int64 `json:"id"` LocationFingerprint string `json:"location_fingerprint"` MetadataVersion string `json:"metadata_version"` Name string `json:"name"` - PrimaryIdentifierID int `json:"primary_identifier_id"` + PrimaryIdentifierID int64 `json:"primary_identifier_id"` ProjectFingerprint string `json:"project_fingerprint"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` RawMetadata string `json:"raw_metadata"` ReportType string `json:"report_type"` - ScannerID int `json:"scanner_id"` + ScannerID int64 `json:"scanner_id"` Severity string `json:"severity"` UpdatedAt *time.Time `json:"updated_at"` UUID string `json:"uuid"` - VulnerabilityID int `json:"vulnerability_id"` + VulnerabilityID int64 `json:"vulnerability_id"` } // ListProjectVulnerabilitiesOptions represents the available @@ -113,24 +112,11 @@ type ListProjectVulnerabilitiesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_vulnerabilities/#list-project-vulnerabilities func (s *ProjectVulnerabilitiesService) ListProjectVulnerabilities(pid any, opt *ListProjectVulnerabilitiesOptions, options ...RequestOptionFunc) ([]*ProjectVulnerability, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/vulnerabilities", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*ProjectVulnerability - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*ProjectVulnerability](s.client, + withPath("projects/%s/vulnerabilities", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateVulnerabilityOptions represents the available CreateVulnerability() @@ -140,7 +126,7 @@ func (s *ProjectVulnerabilitiesService) ListProjectVulnerabilities(pid any, opt // GitLab API docs: // https://docs.gitlab.com/api/project_vulnerabilities/#new-vulnerability type CreateVulnerabilityOptions struct { - FindingID *int `url:"finding_id,omitempty" json:"finding_id,omitempty"` + FindingID *int64 `url:"finding_id,omitempty" json:"finding_id,omitempty"` } // CreateVulnerability creates a new vulnerability on the selected project. @@ -149,22 +135,10 @@ type CreateVulnerabilityOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_vulnerabilities/#new-vulnerability func (s *ProjectVulnerabilitiesService) CreateVulnerability(pid any, opt *CreateVulnerabilityOptions, options ...RequestOptionFunc) (*ProjectVulnerability, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/vulnerabilities", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(ProjectVulnerability) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProjectVulnerability](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/vulnerabilities", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/projects.go b/vendor/gitlab.com/gitlab-org/api/client-go/projects.go index 92423a2f3..27c5af9aa 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/projects.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/projects.go @@ -19,12 +19,9 @@ package gitlab import ( "bytes" "encoding/json" - "fmt" "io" "net/http" "time" - - "github.com/hashicorp/go-retryablehttp" ) type ( @@ -33,59 +30,296 @@ type ( // // GitLab API docs: https://docs.gitlab.com/api/projects/ ProjectsServiceInterface interface { + // ListProjects gets a list of projects accessible by the authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/projects/#list-all-projects ListProjects(opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) + // ListUserProjects gets a list of projects for the given user. + // + // uid can be either a user ID (int) or a username (string). If a username + // is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-a-users-projects ListUserProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) + // ListUserContributedProjects gets a list of visible projects a given user + // has contributed to. + // + // uid can be either a user ID (int) or a username (string). If a username + // is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-projects-a-user-has-contributed-to ListUserContributedProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) + // ListUserStarredProjects gets a list of projects starred by the given user. + // + // uid can be either a user ID (int) or a username (string). If a username + // is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. + // GitLab API docs: + // https://docs.gitlab.com/api/project_starring/#list-projects-starred-by-a-user ListUserStarredProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) + // ListProjectsUsers gets a list of users for the given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-users ListProjectsUsers(pid any, opt *ListProjectUserOptions, options ...RequestOptionFunc) ([]*ProjectUser, *Response, error) + // ListProjectsGroups gets a list of groups for the given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-groups ListProjectsGroups(pid any, opt *ListProjectGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) + // GetProjectLanguages gets a list of languages used by the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-programming-languages-used GetProjectLanguages(pid any, options ...RequestOptionFunc) (*ProjectLanguages, *Response, error) + // GetProject gets a specific project, identified by project ID or + // NAMESPACE/PROJECT_NAME, which is owned by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#get-a-single-project GetProject(pid any, opt *GetProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // CreateProject creates a new project owned by the authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/projects/#create-a-project CreateProject(opt *CreateProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) - CreateProjectForUser(user int, opt *CreateProjectForUserOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // CreateProjectForUser creates a new project owned by the specified user. + // Available only for admins. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#create-a-project-for-a-user + CreateProjectForUser(user int64, opt *CreateProjectForUserOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // EditProject updates an existing project. + // + // GitLab API docs: https://docs.gitlab.com/api/projects/#edit-a-project EditProject(pid any, opt *EditProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // ForkProject forks a project into the user namespace of the authenticated + // user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_forks/#fork-a-project ForkProject(pid any, opt *ForkProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // StarProject stars a given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_starring/#star-a-project StarProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) - ListProjectsInvitedGroups(pid any, opt *ListProjectInvidedGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) + // ListProjectsInvitedGroups lists invited groups of a project + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#list-a-projects-invited-groups + ListProjectsInvitedGroups(pid any, opt *ListProjectInvitedGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) + // UnstarProject unstars a given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_starring/#unstar-a-project UnstarProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) + // ArchiveProject archives the project if the user is either admin or the + // project owner of this project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#archive-a-project ArchiveProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) + // UnarchiveProject unarchives the project if the user is either admin or + // the project owner of this project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#unarchive-a-project UnarchiveProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) + // RestoreProject restores a project that is marked for deletion. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#restore-a-project-marked-for-deletion RestoreProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) + // DeleteProject removes a project including all associated resources + // (issues, merge requests etc.) + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#delete-a-project DeleteProject(pid any, opt *DeleteProjectOptions, options ...RequestOptionFunc) (*Response, error) + // ShareProjectWithGroup allows to share a project with a group. + // + // GitLab API docs: https://docs.gitlab.com/api/projects/#share-a-project-with-a-group ShareProjectWithGroup(pid any, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Response, error) - DeleteSharedProjectFromGroup(pid any, groupID int, options ...RequestOptionFunc) (*Response, error) + // DeleteSharedProjectFromGroup allows to unshare a project from a group. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#delete-a-shared-project-link-in-a-group + DeleteSharedProjectFromGroup(pid any, groupID int64, options ...RequestOptionFunc) (*Response, error) + // ListProjectHooks gets a list of project hooks. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#list-webhooks-for-a-project ListProjectHooks(pid any, opt *ListProjectHooksOptions, options ...RequestOptionFunc) ([]*ProjectHook, *Response, error) - GetProjectHook(pid any, hook int, options ...RequestOptionFunc) (*ProjectHook, *Response, error) + // GetProjectHook gets a specific hook for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#get-a-project-webhook + GetProjectHook(pid any, hook int64, options ...RequestOptionFunc) (*ProjectHook, *Response, error) + // AddProjectHook adds a hook to a specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#add-a-webhook-to-a-project AddProjectHook(pid any, opt *AddProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) - EditProjectHook(pid any, hook int, opt *EditProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) - DeleteProjectHook(pid any, hook int, options ...RequestOptionFunc) (*Response, error) - TriggerTestProjectHook(pid any, hook int, event ProjectHookEvent, options ...RequestOptionFunc) (*Response, error) - SetProjectCustomHeader(pid any, hook int, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) - DeleteProjectCustomHeader(pid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) - SetProjectWebhookURLVariable(pid any, hook int, key string, opt *SetProjectWebhookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) - DeleteProjectWebhookURLVariable(pid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) - CreateProjectForkRelation(pid any, fork int, options ...RequestOptionFunc) (*ProjectForkRelation, *Response, error) + // EditProjectHook edits a hook for a specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#edit-a-project-webhook + EditProjectHook(pid any, hook int64, opt *EditProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) + // DeleteProjectHook removes a hook from a project. This is an idempotent + // method and can be called multiple times. Either the hook is available or not. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#delete-project-webhook + DeleteProjectHook(pid any, hook int64, options ...RequestOptionFunc) (*Response, error) + // TriggerTestProjectHook Trigger a test hook for a specified project. + // + // In GitLab 17.0 and later, this endpoint has a special rate limit. + // In GitLab 17.0 the rate was three requests per minute for each project hook. + // In GitLab 17.1 this was changed to five requests per minute for each project + // and authenticated user. + // + // To disable this limit on self-managed GitLab and GitLab Dedicated, + // an administrator can disable the feature flag named web_hook_test_api_endpoint_rate_limit. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#trigger-a-test-project-webhook + TriggerTestProjectHook(pid any, hook int64, event ProjectHookEvent, options ...RequestOptionFunc) (*Response, error) + // SetProjectCustomHeader creates or updates a project custom webhook header. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#set-a-custom-header + SetProjectCustomHeader(pid any, hook int64, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) + // DeleteProjectCustomHeader deletes a project custom webhook header. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#delete-a-custom-header + DeleteProjectCustomHeader(pid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) + // SetProjectWebhookURLVariable creates or updates a project webhook URL variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#set-a-url-variable + SetProjectWebhookURLVariable(pid any, hook int64, key string, opt *SetProjectWebhookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) + // DeleteProjectWebhookURLVariable deletes a project webhook URL variable. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_webhooks/#delete-a-url-variable + DeleteProjectWebhookURLVariable(pid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) + // CreateProjectForkRelation creates a forked from/to relation between + // existing projects. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_forks/#create-a-fork-relationship-between-projects + CreateProjectForkRelation(pid any, fork int64, options ...RequestOptionFunc) (*ProjectForkRelation, *Response, error) + // DeleteProjectForkRelation deletes an existing forked from relationship. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_forks/#delete-a-fork-relationship-between-projects DeleteProjectForkRelation(pid any, options ...RequestOptionFunc) (*Response, error) + // UploadAvatar uploads an avatar. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#upload-a-project-avatar UploadAvatar(pid any, avatar io.Reader, filename string, options ...RequestOptionFunc) (*Project, *Response, error) + // DownloadAvatar downloads an avatar. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#download-a-project-avatar DownloadAvatar(pid any, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) + // ListProjectForks gets a list of project forks. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_forks/#list-forks-of-a-project ListProjectForks(pid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) + // GetProjectPushRules gets the push rules of a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_push_rules/#get-project-push-rules GetProjectPushRules(pid any, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) + // AddProjectPushRule adds a push rule to a specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_push_rules/#add-a-project-push-rule AddProjectPushRule(pid any, opt *AddProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) + // EditProjectPushRule edits a push rule for a specified project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_push_rules/#edit-project-push-rule EditProjectPushRule(pid any, opt *EditProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) + // DeleteProjectPushRule removes a push rule from a project. This is an + // idempotent method and can be called multiple times. Either the push rule is + // available or not. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_push_rules/#delete-project-push-rule DeleteProjectPushRule(pid any, options ...RequestOptionFunc) (*Response, error) + // GetApprovalConfiguration get the approval configuration for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#project-approval-rules GetApprovalConfiguration(pid any, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) + // ChangeApprovalConfiguration updates the approval configuration for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#change-configuration ChangeApprovalConfiguration(pid any, opt *ChangeApprovalConfigurationOptions, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) + // GetProjectApprovalRules looks up the list of project level approver rules. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#get-all-approval-rules-for-project GetProjectApprovalRules(pid any, opt *GetProjectApprovalRulesListsOptions, options ...RequestOptionFunc) ([]*ProjectApprovalRule, *Response, error) - GetProjectApprovalRule(pid any, ruleID int, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) + // GetProjectApprovalRule gets the project level approvers. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#get-single-approval-rule-for-project + GetProjectApprovalRule(pid any, ruleID int64, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) + // CreateProjectApprovalRule creates a new project-level approval rule. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#create-project-approval-rule CreateProjectApprovalRule(pid any, opt *CreateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) - UpdateProjectApprovalRule(pid any, approvalRule int, opt *UpdateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) - DeleteProjectApprovalRule(pid any, approvalRule int, options ...RequestOptionFunc) (*Response, error) + // UpdateProjectApprovalRule updates an existing approval rule with new options. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#update-project-approval-rule + UpdateProjectApprovalRule(pid any, approvalRule int64, opt *UpdateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) + // DeleteProjectApprovalRule deletes a project-level approval rule. + // + // GitLab API docs: + // https://docs.gitlab.com/api/merge_request_approvals/#delete-project-approval-rule + DeleteProjectApprovalRule(pid any, approvalRule int64, options ...RequestOptionFunc) (*Response, error) + // GetProjectPullMirrorDetails returns the pull mirror details. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_pull_mirroring/#get-a-projects-pull-mirror-details GetProjectPullMirrorDetails(pid any, options ...RequestOptionFunc) (*ProjectPullMirrorDetails, *Response, error) + // ConfigureProjectPullMirror configures pull mirroring settings. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_pull_mirroring/#configure-pull-mirroring-for-a-project ConfigureProjectPullMirror(pid any, opt *ConfigureProjectPullMirrorOptions, options ...RequestOptionFunc) (*ProjectPullMirrorDetails, *Response, error) + // StartMirroringProject start the pull mirroring process for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_pull_mirroring/#start-the-pull-mirroring-process-for-a-project StartMirroringProject(pid any, options ...RequestOptionFunc) (*Response, error) + // TransferProject transfer a project into the specified namespace + // + // GitLab API docs: https://docs.gitlab.com/api/projects/#transfer-a-project-to-a-new-namespace TransferProject(pid any, opt *TransferProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) + // StartHousekeepingProject start the Housekeeping task for a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#start-the-housekeeping-task-for-a-project StartHousekeepingProject(pid any, options ...RequestOptionFunc) (*Response, error) - GetRepositoryStorage(pid any, options ...RequestOptionFunc) (*ProjectReposityStorage, *Response, error) + // GetRepositoryStorage Get the path to repository storage. + // + // GitLab API docs: + // https://docs.gitlab.com/api/projects/#get-the-path-to-repository-storage + GetRepositoryStorage(pid any, options ...RequestOptionFunc) (*ProjectRepositoryStorage, *Response, error) + // ListProjectStarrers gets users who starred a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_starring/#list-users-who-starred-a-project + ListProjectStarrers(pid any, opts *ListProjectStarrersOptions, options ...RequestOptionFunc) ([]*ProjectStarrer, *Response, error) } // ProjectsService handles communication with the repositories related methods @@ -103,137 +337,134 @@ var _ ProjectsServiceInterface = (*ProjectsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/projects/ type Project struct { - ID int `json:"id"` - Description string `json:"description"` - DefaultBranch string `json:"default_branch"` - Visibility VisibilityValue `json:"visibility"` - SSHURLToRepo string `json:"ssh_url_to_repo"` - HTTPURLToRepo string `json:"http_url_to_repo"` - WebURL string `json:"web_url"` - ReadmeURL string `json:"readme_url"` - Topics []string `json:"topics"` - Owner *User `json:"owner"` - Name string `json:"name"` - NameWithNamespace string `json:"name_with_namespace"` - Path string `json:"path"` - PathWithNamespace string `json:"path_with_namespace"` - OpenIssuesCount int `json:"open_issues_count"` - ResolveOutdatedDiffDiscussions bool `json:"resolve_outdated_diff_discussions"` - ContainerExpirationPolicy *ContainerExpirationPolicy `json:"container_expiration_policy,omitempty"` - ContainerRegistryAccessLevel AccessControlValue `json:"container_registry_access_level"` - ContainerRegistryImagePrefix string `json:"container_registry_image_prefix,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - LastActivityAt *time.Time `json:"last_activity_at,omitempty"` - CreatorID int `json:"creator_id"` - Namespace *ProjectNamespace `json:"namespace"` - Permissions *Permissions `json:"permissions"` - MarkedForDeletionOn *ISOTime `json:"marked_for_deletion_on"` - EmptyRepo bool `json:"empty_repo"` - Archived bool `json:"archived"` - AvatarURL string `json:"avatar_url"` - LicenseURL string `json:"license_url"` - License *ProjectLicense `json:"license"` - SharedRunnersEnabled bool `json:"shared_runners_enabled"` - GroupRunnersEnabled bool `json:"group_runners_enabled"` - RunnerTokenExpirationInterval int `json:"runner_token_expiration_interval"` - ForksCount int `json:"forks_count"` - StarCount int `json:"star_count"` - RunnersToken string `json:"runners_token"` - AllowMergeOnSkippedPipeline bool `json:"allow_merge_on_skipped_pipeline"` - AllowPipelineTriggerApproveDeployment bool `json:"allow_pipeline_trigger_approve_deployment"` - OnlyAllowMergeIfPipelineSucceeds bool `json:"only_allow_merge_if_pipeline_succeeds"` - OnlyAllowMergeIfAllDiscussionsAreResolved bool `json:"only_allow_merge_if_all_discussions_are_resolved"` - RemoveSourceBranchAfterMerge bool `json:"remove_source_branch_after_merge"` - PreventMergeWithoutJiraIssue bool `json:"prevent_merge_without_jira_issue"` - PrintingMergeRequestLinkEnabled bool `json:"printing_merge_request_link_enabled"` - LFSEnabled bool `json:"lfs_enabled"` - RepositoryStorage string `json:"repository_storage"` - RequestAccessEnabled bool `json:"request_access_enabled"` - MergeMethod MergeMethodValue `json:"merge_method"` - CanCreateMergeRequestIn bool `json:"can_create_merge_request_in"` - ForkedFromProject *ForkParent `json:"forked_from_project"` - Mirror bool `json:"mirror"` - MirrorUserID int `json:"mirror_user_id"` - MirrorTriggerBuilds bool `json:"mirror_trigger_builds"` - OnlyMirrorProtectedBranches bool `json:"only_mirror_protected_branches"` - MirrorOverwritesDivergedBranches bool `json:"mirror_overwrites_diverged_branches"` - PackagesEnabled bool `json:"packages_enabled"` - ServiceDeskEnabled bool `json:"service_desk_enabled"` - ServiceDeskAddress string `json:"service_desk_address"` - IssuesAccessLevel AccessControlValue `json:"issues_access_level"` - ReleasesAccessLevel AccessControlValue `json:"releases_access_level,omitempty"` - RepositoryAccessLevel AccessControlValue `json:"repository_access_level"` - MergeRequestsAccessLevel AccessControlValue `json:"merge_requests_access_level"` - ForkingAccessLevel AccessControlValue `json:"forking_access_level"` - WikiAccessLevel AccessControlValue `json:"wiki_access_level"` - BuildsAccessLevel AccessControlValue `json:"builds_access_level"` - SnippetsAccessLevel AccessControlValue `json:"snippets_access_level"` - PagesAccessLevel AccessControlValue `json:"pages_access_level"` - OperationsAccessLevel AccessControlValue `json:"operations_access_level"` - AnalyticsAccessLevel AccessControlValue `json:"analytics_access_level"` - EnvironmentsAccessLevel AccessControlValue `json:"environments_access_level"` - FeatureFlagsAccessLevel AccessControlValue `json:"feature_flags_access_level"` - InfrastructureAccessLevel AccessControlValue `json:"infrastructure_access_level"` - MonitorAccessLevel AccessControlValue `json:"monitor_access_level"` - AutocloseReferencedIssues bool `json:"autoclose_referenced_issues"` - SuggestionCommitMessage string `json:"suggestion_commit_message"` - SquashOption SquashOptionValue `json:"squash_option"` - EnforceAuthChecksOnUploads bool `json:"enforce_auth_checks_on_uploads,omitempty"` - SharedWithGroups []struct { - GroupID int `json:"group_id"` - GroupName string `json:"group_name"` - GroupFullPath string `json:"group_full_path"` - GroupAccessLevel int `json:"group_access_level"` - } `json:"shared_with_groups"` - Statistics *Statistics `json:"statistics"` - Links *Links `json:"_links,omitempty"` - ImportURL string `json:"import_url"` - ImportType string `json:"import_type"` - ImportStatus string `json:"import_status"` - ImportError string `json:"import_error"` - CIDefaultGitDepth int `json:"ci_default_git_depth"` - CIDeletePipelinesInSeconds int `json:"ci_delete_pipelines_in_seconds,omitempty"` - CIForwardDeploymentEnabled bool `json:"ci_forward_deployment_enabled"` - CIForwardDeploymentRollbackAllowed bool `json:"ci_forward_deployment_rollback_allowed"` - CIPushRepositoryForJobTokenAllowed bool `json:"ci_push_repository_for_job_token_allowed"` - CIIdTokenSubClaimComponents []string `json:"ci_id_token_sub_claim_components"` - CISeperateCache bool `json:"ci_separated_caches"` - CIJobTokenScopeEnabled bool `json:"ci_job_token_scope_enabled"` - CIOptInJWT bool `json:"ci_opt_in_jwt"` - CIAllowForkPipelinesToRunInParentProject bool `json:"ci_allow_fork_pipelines_to_run_in_parent_project"` - CIRestrictPipelineCancellationRole AccessControlValue `json:"ci_restrict_pipeline_cancellation_role"` - PublicJobs bool `json:"public_jobs"` - BuildTimeout int `json:"build_timeout"` - AutoCancelPendingPipelines string `json:"auto_cancel_pending_pipelines"` - CIConfigPath string `json:"ci_config_path"` - CustomAttributes []*CustomAttribute `json:"custom_attributes"` - ComplianceFrameworks []string `json:"compliance_frameworks"` - BuildCoverageRegex string `json:"build_coverage_regex"` - IssuesTemplate string `json:"issues_template"` - MergeRequestsTemplate string `json:"merge_requests_template"` - IssueBranchTemplate string `json:"issue_branch_template"` - KeepLatestArtifact bool `json:"keep_latest_artifact"` - MergePipelinesEnabled bool `json:"merge_pipelines_enabled"` - MergeTrainsEnabled bool `json:"merge_trains_enabled"` - MergeTrainsSkipTrainAllowed bool `json:"merge_trains_skip_train_allowed"` - CIPipelineVariablesMinimumOverrideRole CIPipelineVariablesMinimumOverrideRoleValue `json:"ci_pipeline_variables_minimum_override_role"` - MergeCommitTemplate string `json:"merge_commit_template"` - SquashCommitTemplate string `json:"squash_commit_template"` - AutoDevopsDeployStrategy string `json:"auto_devops_deploy_strategy"` - AutoDevopsEnabled bool `json:"auto_devops_enabled"` - BuildGitStrategy string `json:"build_git_strategy"` - EmailsEnabled bool `json:"emails_enabled"` - ExternalAuthorizationClassificationLabel string `json:"external_authorization_classification_label"` - RequirementsEnabled bool `json:"requirements_enabled"` - RequirementsAccessLevel AccessControlValue `json:"requirements_access_level"` - SecurityAndComplianceEnabled bool `json:"security_and_compliance_enabled"` - SecurityAndComplianceAccessLevel AccessControlValue `json:"security_and_compliance_access_level"` - MergeRequestDefaultTargetSelf bool `json:"mr_default_target_self"` - ModelExperimentsAccessLevel AccessControlValue `json:"model_experiments_access_level"` - ModelRegistryAccessLevel AccessControlValue `json:"model_registry_access_level"` - PreReceiveSecretDetectionEnabled bool `json:"pre_receive_secret_detection_enabled"` - AutoDuoCodeReviewEnabled bool `json:"auto_duo_code_review_enabled"` + ID int64 `json:"id"` + Description string `json:"description"` + DefaultBranch string `json:"default_branch"` + Visibility VisibilityValue `json:"visibility"` + SSHURLToRepo string `json:"ssh_url_to_repo"` + HTTPURLToRepo string `json:"http_url_to_repo"` + WebURL string `json:"web_url"` + ReadmeURL string `json:"readme_url"` + Topics []string `json:"topics"` + Owner *User `json:"owner"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + OpenIssuesCount int64 `json:"open_issues_count"` + ResolveOutdatedDiffDiscussions bool `json:"resolve_outdated_diff_discussions"` + ContainerExpirationPolicy *ContainerExpirationPolicy `json:"container_expiration_policy,omitempty"` + ContainerRegistryAccessLevel AccessControlValue `json:"container_registry_access_level"` + ContainerRegistryImagePrefix string `json:"container_registry_image_prefix,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + LastActivityAt *time.Time `json:"last_activity_at,omitempty"` + CreatorID int64 `json:"creator_id"` + Namespace *ProjectNamespace `json:"namespace"` + Permissions *Permissions `json:"permissions"` + MarkedForDeletionOn *ISOTime `json:"marked_for_deletion_on"` + EmptyRepo bool `json:"empty_repo"` + Archived bool `json:"archived"` + AvatarURL string `json:"avatar_url"` + LicenseURL string `json:"license_url"` + License *ProjectLicense `json:"license"` + SharedRunnersEnabled bool `json:"shared_runners_enabled"` + GroupRunnersEnabled bool `json:"group_runners_enabled"` + ResourceGroupDefaultProcessMode ResourceGroupProcessMode `json:"resource_group_default_process_mode"` + RunnerTokenExpirationInterval int64 `json:"runner_token_expiration_interval"` + ForksCount int64 `json:"forks_count"` + StarCount int64 `json:"star_count"` + RunnersToken string `json:"runners_token"` + AllowMergeOnSkippedPipeline bool `json:"allow_merge_on_skipped_pipeline"` + AllowPipelineTriggerApproveDeployment bool `json:"allow_pipeline_trigger_approve_deployment"` + OnlyAllowMergeIfPipelineSucceeds bool `json:"only_allow_merge_if_pipeline_succeeds"` + OnlyAllowMergeIfAllDiscussionsAreResolved bool `json:"only_allow_merge_if_all_discussions_are_resolved"` + RemoveSourceBranchAfterMerge bool `json:"remove_source_branch_after_merge"` + PreventMergeWithoutJiraIssue bool `json:"prevent_merge_without_jira_issue"` + PrintingMergeRequestLinkEnabled bool `json:"printing_merge_request_link_enabled"` + LFSEnabled bool `json:"lfs_enabled"` + MaxArtifactsSize int64 `json:"max_artifacts_size"` + RepositoryStorage string `json:"repository_storage"` + RequestAccessEnabled bool `json:"request_access_enabled"` + MergeMethod MergeMethodValue `json:"merge_method"` + CanCreateMergeRequestIn bool `json:"can_create_merge_request_in"` + ForkedFromProject *ForkParent `json:"forked_from_project"` + Mirror bool `json:"mirror"` + MirrorUserID int64 `json:"mirror_user_id"` + MirrorTriggerBuilds bool `json:"mirror_trigger_builds"` + OnlyMirrorProtectedBranches bool `json:"only_mirror_protected_branches"` + MirrorOverwritesDivergedBranches bool `json:"mirror_overwrites_diverged_branches"` + PackagesEnabled bool `json:"packages_enabled"` + ServiceDeskEnabled bool `json:"service_desk_enabled"` + ServiceDeskAddress string `json:"service_desk_address"` + IssuesAccessLevel AccessControlValue `json:"issues_access_level"` + ReleasesAccessLevel AccessControlValue `json:"releases_access_level,omitempty"` + RepositoryAccessLevel AccessControlValue `json:"repository_access_level"` + MergeRequestsAccessLevel AccessControlValue `json:"merge_requests_access_level"` + ForkingAccessLevel AccessControlValue `json:"forking_access_level"` + WikiAccessLevel AccessControlValue `json:"wiki_access_level"` + BuildsAccessLevel AccessControlValue `json:"builds_access_level"` + SnippetsAccessLevel AccessControlValue `json:"snippets_access_level"` + PagesAccessLevel AccessControlValue `json:"pages_access_level"` + OperationsAccessLevel AccessControlValue `json:"operations_access_level"` + AnalyticsAccessLevel AccessControlValue `json:"analytics_access_level"` + EnvironmentsAccessLevel AccessControlValue `json:"environments_access_level"` + FeatureFlagsAccessLevel AccessControlValue `json:"feature_flags_access_level"` + InfrastructureAccessLevel AccessControlValue `json:"infrastructure_access_level"` + MonitorAccessLevel AccessControlValue `json:"monitor_access_level"` + AutocloseReferencedIssues bool `json:"autoclose_referenced_issues"` + SuggestionCommitMessage string `json:"suggestion_commit_message"` + SquashOption SquashOptionValue `json:"squash_option"` + EnforceAuthChecksOnUploads bool `json:"enforce_auth_checks_on_uploads,omitempty"` + SharedWithGroups []ProjectSharedWithGroup `json:"shared_with_groups"` + Statistics *Statistics `json:"statistics"` + Links *Links `json:"_links,omitempty"` + ImportURL string `json:"import_url"` + ImportType string `json:"import_type"` + ImportStatus string `json:"import_status"` + ImportError string `json:"import_error"` + CIDefaultGitDepth int64 `json:"ci_default_git_depth"` + CIDeletePipelinesInSeconds int64 `json:"ci_delete_pipelines_in_seconds,omitempty"` + CIForwardDeploymentEnabled bool `json:"ci_forward_deployment_enabled"` + CIForwardDeploymentRollbackAllowed bool `json:"ci_forward_deployment_rollback_allowed"` + CIPushRepositoryForJobTokenAllowed bool `json:"ci_push_repository_for_job_token_allowed"` + CIIdTokenSubClaimComponents []string `json:"ci_id_token_sub_claim_components"` + CISeparatedCaches bool `json:"ci_separated_caches"` + CIJobTokenScopeEnabled bool `json:"ci_job_token_scope_enabled"` + CIOptInJWT bool `json:"ci_opt_in_jwt"` + CIAllowForkPipelinesToRunInParentProject bool `json:"ci_allow_fork_pipelines_to_run_in_parent_project"` + CIRestrictPipelineCancellationRole AccessControlValue `json:"ci_restrict_pipeline_cancellation_role"` + PublicJobs bool `json:"public_jobs"` + BuildTimeout int64 `json:"build_timeout"` + AutoCancelPendingPipelines string `json:"auto_cancel_pending_pipelines"` + CIConfigPath string `json:"ci_config_path"` + CustomAttributes []*CustomAttribute `json:"custom_attributes"` + ComplianceFrameworks []string `json:"compliance_frameworks"` + BuildCoverageRegex string `json:"build_coverage_regex"` + IssuesTemplate string `json:"issues_template"` + MergeRequestsTemplate string `json:"merge_requests_template"` + IssueBranchTemplate string `json:"issue_branch_template"` + KeepLatestArtifact bool `json:"keep_latest_artifact"` + MergePipelinesEnabled bool `json:"merge_pipelines_enabled"` + MergeTrainsEnabled bool `json:"merge_trains_enabled"` + MergeTrainsSkipTrainAllowed bool `json:"merge_trains_skip_train_allowed"` + CIPipelineVariablesMinimumOverrideRole CIPipelineVariablesMinimumOverrideRoleValue `json:"ci_pipeline_variables_minimum_override_role"` + MergeCommitTemplate string `json:"merge_commit_template"` + SquashCommitTemplate string `json:"squash_commit_template"` + AutoDevopsDeployStrategy string `json:"auto_devops_deploy_strategy"` + AutoDevopsEnabled bool `json:"auto_devops_enabled"` + BuildGitStrategy string `json:"build_git_strategy"` + EmailsEnabled bool `json:"emails_enabled"` + ExternalAuthorizationClassificationLabel string `json:"external_authorization_classification_label"` + RequirementsEnabled bool `json:"requirements_enabled"` + RequirementsAccessLevel AccessControlValue `json:"requirements_access_level"` + SecurityAndComplianceEnabled bool `json:"security_and_compliance_enabled"` + SecurityAndComplianceAccessLevel AccessControlValue `json:"security_and_compliance_access_level"` + MergeRequestDefaultTargetSelf bool `json:"mr_default_target_self"` + ModelExperimentsAccessLevel AccessControlValue `json:"model_experiments_access_level"` + ModelRegistryAccessLevel AccessControlValue `json:"model_registry_access_level"` + PreReceiveSecretDetectionEnabled bool `json:"pre_receive_secret_detection_enabled"` + AutoDuoCodeReviewEnabled bool `json:"auto_duo_code_review_enabled"` // Deprecated: use Topics instead TagList []string `json:"tag_list"` @@ -242,7 +473,7 @@ type Project struct { // Deprecated: use MergeRequestsAccessLevel instead MergeRequestsEnabled bool `json:"merge_requests_enabled"` // Deprecated: use Merge Request Approvals API instead - ApprovalsBeforeMerge int `json:"approvals_before_merge"` + ApprovalsBeforeMerge int64 `json:"approvals_before_merge"` // Deprecated: use BuildsAccessLevel instead JobsEnabled bool `json:"jobs_enabled"` // Deprecated: use WikiAccessLevel instead @@ -261,9 +492,20 @@ type Project struct { PublicBuilds bool `json:"public_builds"` } +// ProjectSharedWithGroup represents a GitLab project shared group. +// +// GitLab API docs: https://docs.gitlab.com/api/projects/ +type ProjectSharedWithGroup struct { + GroupID int64 `json:"group_id"` + GroupName string `json:"group_name"` + GroupFullPath string `json:"group_full_path"` + GroupAccessLevel int64 `json:"group_access_level"` + ExpiresAt *ISOTime `json:"expires_at"` +} + // BasicProject included in other service responses (such as todos). type BasicProject struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` @@ -275,7 +517,7 @@ type BasicProject struct { // ContainerExpirationPolicy represents the container expiration policy. type ContainerExpirationPolicy struct { Cadence string `json:"cadence"` - KeepN int `json:"keep_n"` + KeepN int64 `json:"keep_n"` OlderThan string `json:"older_than"` NameRegexDelete string `json:"name_regex_delete"` NameRegexKeep string `json:"name_regex_keep"` @@ -288,7 +530,7 @@ type ContainerExpirationPolicy struct { // ForkParent represents the parent project when this is a fork. type ForkParent struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` NameWithNamespace string `json:"name_with_namespace"` Path string `json:"path"` @@ -340,12 +582,12 @@ type ProjectLicense struct { // ProjectNamespace represents a project namespace. type ProjectNamespace struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Path string `json:"path"` Kind string `json:"kind"` FullPath string `json:"full_path"` - ParentID int `json:"parent_id"` + ParentID int64 `json:"parent_id"` AvatarURL string `json:"avatar_url"` WebURL string `json:"web_url"` } @@ -392,12 +634,12 @@ func (s Project) String() string { // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#get-all-approval-rules-for-project type ProjectApprovalRule struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` RuleType string `json:"rule_type"` ReportType string `json:"report_type"` EligibleApprovers []*BasicUser `json:"eligible_approvers"` - ApprovalsRequired int `json:"approvals_required"` + ApprovalsRequired int64 `json:"approvals_required"` Users []*BasicUser `json:"users"` Groups []*Group `json:"groups"` ContainsHiddenGroups bool `json:"contains_hidden_groups"` @@ -416,8 +658,8 @@ type ListProjectsOptions struct { ListOptions Active *bool `url:"active,omitempty" json:"active,omitempty"` Archived *bool `url:"archived,omitempty" json:"archived,omitempty"` - IDAfter *int `url:"id_after,omitempty" json:"id_after,omitempty"` - IDBefore *int `url:"id_before,omitempty" json:"id_before,omitempty"` + IDAfter *int64 `url:"id_after,omitempty" json:"id_after,omitempty"` + IDBefore *int64 `url:"id_before,omitempty" json:"id_before,omitempty"` Imported *bool `url:"imported,omitempty" json:"imported,omitempty"` IncludeHidden *bool `url:"include_hidden,omitempty" json:"include_hidden,omitempty"` IncludePendingDelete *bool `url:"include_pending_delete,omitempty" json:"include_pending_delete,omitempty"` @@ -444,102 +686,49 @@ type ListProjectsOptions struct { WithProgrammingLanguage *string `url:"with_programming_language,omitempty" json:"with_programming_language,omitempty"` } -// ListProjects gets a list of projects accessible by the authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/projects/#list-all-projects func (s *ProjectsService) ListProjects(opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "projects", opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Project - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*Project](s.client, + withPath("projects"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListUserProjects gets a list of projects for the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#list-a-users-projects func (s *ProjectsService) ListUserProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("users/%s/projects", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Project - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*Project](s.client, + withPath("users/%s/projects", UserID{uid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListUserContributedProjects gets a list of visible projects a given user has contributed to. +// ListUserContributedProjects gets a list of visible projects a given user has +// contributed to. +// +// uid can be either a user ID (int) or a username (string). If a username +// is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. // // GitLab API docs: // https://docs.gitlab.com/api/projects/#list-projects-a-user-has-contributed-to func (s *ProjectsService) ListUserContributedProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("users/%s/contributed_projects", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Project - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*Project](s.client, + withPath("users/%s/contributed_projects", UserID{uid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// ListUserStarredProjects gets a list of projects starred by the given user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_starring/#list-projects-starred-by-a-user func (s *ProjectsService) ListUserStarredProjects(uid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("users/%s/starred_projects", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*Project - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*Project](s.client, + withPath("users/%s/starred_projects", UserID{uid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectUser represents a GitLab project user. type ProjectUser struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Username string `json:"username"` State string `json:"state"` @@ -555,35 +744,18 @@ type ListProjectUserOptions struct { Search *string `url:"search,omitempty" json:"search,omitempty"` } -// ListProjectsUsers gets a list of users for the given project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#list-users func (s *ProjectsService) ListProjectsUsers(pid any, opt *ListProjectUserOptions, options ...RequestOptionFunc) ([]*ProjectUser, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/users", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*ProjectUser - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*ProjectUser](s.client, + withPath("projects/%s/users", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectGroup represents a GitLab project group. // GitLab API docs: https://docs.gitlab.com/api/projects/#list-groups type ProjectGroup struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` AvatarURL string `json:"avatar_url"` WebURL string `json:"web_url"` @@ -598,65 +770,30 @@ type ListProjectGroupOptions struct { ListOptions Search *string `url:"search,omitempty" json:"search,omitempty"` SharedMinAccessLevel *AccessLevelValue `url:"shared_min_access_level,omitempty" json:"shared_min_access_level,omitempty"` - SharedVisiableOnly *bool `url:"shared_visible_only,omitempty" json:"shared_visible_only,omitempty"` - SkipGroups *[]int `url:"skip_groups,omitempty" json:"skip_groups,omitempty"` + SharedVisibleOnly *bool `url:"shared_visible_only,omitempty" json:"shared_visible_only,omitempty"` + SkipGroups *[]int64 `url:"skip_groups,omitempty" json:"skip_groups,omitempty"` WithShared *bool `url:"with_shared,omitempty" json:"with_shared,omitempty"` } -// ListProjectsGroups gets a list of groups for the given project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#list-groups func (s *ProjectsService) ListProjectsGroups(pid any, opt *ListProjectGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/groups", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*ProjectGroup - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*ProjectGroup](s.client, + withPath("projects/%s/groups", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectLanguages is a map of strings because the response is arbitrary // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/projects/#list-programming-languages-used type ProjectLanguages map[string]float32 -// GetProjectLanguages gets a list of languages used by the project -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#list-programming-languages-used func (s *ProjectsService) GetProjectLanguages(pid any, options ...RequestOptionFunc) (*ProjectLanguages, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/languages", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(ProjectLanguages) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProjectLanguages](s.client, + withPath("projects/%s/languages", ProjectID{pid}), + withRequestOpts(options...), + ) } // GetProjectOptions represents the available GetProject() options. @@ -668,30 +805,12 @@ type GetProjectOptions struct { WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"` } -// GetProject gets a specific project, identified by project ID or -// NAMESPACE/PROJECT_NAME, which is owned by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#get-a-single-project func (s *ProjectsService) GetProject(pid any, opt *GetProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withPath("projects/%s", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateProjectOptions represents the available CreateProject() options. @@ -708,7 +827,7 @@ type CreateProjectOptions struct { Avatar *ProjectAvatar `url:"-" json:"-"` BuildCoverageRegex *string `url:"build_coverage_regex,omitempty" json:"build_coverage_regex,omitempty"` BuildGitStrategy *string `url:"build_git_strategy,omitempty" json:"build_git_strategy,omitempty"` - BuildTimeout *int `url:"build_timeout,omitempty" json:"build_timeout,omitempty"` + BuildTimeout *int64 `url:"build_timeout,omitempty" json:"build_timeout,omitempty"` BuildsAccessLevel *AccessControlValue `url:"builds_access_level,omitempty" json:"builds_access_level,omitempty"` CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"` ContainerExpirationPolicyAttributes *ContainerExpirationPolicyAttributes `url:"container_expiration_policy_attributes,omitempty" json:"container_expiration_policy_attributes,omitempty"` @@ -719,7 +838,7 @@ type CreateProjectOptions struct { EnforceAuthChecksOnUploads *bool `url:"enforce_auth_checks_on_uploads,omitempty" json:"enforce_auth_checks_on_uploads,omitempty"` ExternalAuthorizationClassificationLabel *string `url:"external_authorization_classification_label,omitempty" json:"external_authorization_classification_label,omitempty"` ForkingAccessLevel *AccessControlValue `url:"forking_access_level,omitempty" json:"forking_access_level,omitempty"` - GroupWithProjectTemplatesID *int `url:"group_with_project_templates_id,omitempty" json:"group_with_project_templates_id,omitempty"` + GroupWithProjectTemplatesID *int64 `url:"group_with_project_templates_id,omitempty" json:"group_with_project_templates_id,omitempty"` ImportURL *string `url:"import_url,omitempty" json:"import_url,omitempty"` InitializeWithReadme *bool `url:"initialize_with_readme,omitempty" json:"initialize_with_readme,omitempty"` IssuesAccessLevel *AccessControlValue `url:"issues_access_level,omitempty" json:"issues_access_level,omitempty"` @@ -736,7 +855,7 @@ type CreateProjectOptions struct { ModelExperimentsAccessLevel *AccessControlValue `url:"model_experiments_access_level,omitempty" json:"model_experiments_access_level,omitempty"` ModelRegistryAccessLevel *AccessControlValue `url:"model_registry_access_level,omitempty" json:"model_registry_access_level,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` - NamespaceID *int `url:"namespace_id,omitempty" json:"namespace_id,omitempty"` + NamespaceID *int64 `url:"namespace_id,omitempty" json:"namespace_id,omitempty"` OnlyAllowMergeIfAllDiscussionsAreResolved *bool `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"` OnlyAllowMergeIfPipelineSucceeds *bool `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"` OperationsAccessLevel *AccessControlValue `url:"operations_access_level,omitempty" json:"operations_access_level,omitempty"` @@ -758,20 +877,21 @@ type CreateProjectOptions struct { SecurityAndComplianceAccessLevel *AccessControlValue `url:"security_and_compliance_access_level,omitempty" json:"security_and_compliance_access_level,omitempty"` SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"` GroupRunnersEnabled *bool `url:"group_runners_enabled,omitempty" json:"group_runners_enabled,omitempty"` + ResourceGroupDefaultProcessMode *ResourceGroupProcessMode `url:"resource_group_default_process_mode,omitempty" json:"resource_group_default_process_mode,omitempty"` ShowDefaultAwardEmojis *bool `url:"show_default_award_emojis,omitempty" json:"show_default_award_emojis,omitempty"` SnippetsAccessLevel *AccessControlValue `url:"snippets_access_level,omitempty" json:"snippets_access_level,omitempty"` SquashCommitTemplate *string `url:"squash_commit_template,omitempty" json:"squash_commit_template,omitempty"` SquashOption *SquashOptionValue `url:"squash_option,omitempty" json:"squash_option,omitempty"` SuggestionCommitMessage *string `url:"suggestion_commit_message,omitempty" json:"suggestion_commit_message,omitempty"` TemplateName *string `url:"template_name,omitempty" json:"template_name,omitempty"` - TemplateProjectID *int `url:"template_project_id,omitempty" json:"template_project_id,omitempty"` + TemplateProjectID *int64 `url:"template_project_id,omitempty" json:"template_project_id,omitempty"` Topics *[]string `url:"topics,omitempty" json:"topics,omitempty"` UseCustomTemplate *bool `url:"use_custom_template,omitempty" json:"use_custom_template,omitempty"` Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"` // Deprecated: use Merge Request Approvals API instead - ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` + ApprovalsBeforeMerge *int64 `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` // Deprecated: use PublicJobs instead PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"` // Deprecated: No longer supported in recent versions. @@ -806,7 +926,7 @@ type CreateProjectOptions struct { // GitLab API docs: https://docs.gitlab.com/api/projects/#create-a-project type ContainerExpirationPolicyAttributes struct { Cadence *string `url:"cadence,omitempty" json:"cadence,omitempty"` - KeepN *int `url:"keep_n,omitempty" json:"keep_n,omitempty"` + KeepN *int64 `url:"keep_n,omitempty" json:"keep_n,omitempty"` OlderThan *string `url:"older_than,omitempty" json:"older_than,omitempty"` NameRegexDelete *string `url:"name_regex_delete,omitempty" json:"name_regex_delete,omitempty"` NameRegexKeep *string `url:"name_regex_keep,omitempty" json:"name_regex_keep,omitempty"` @@ -833,9 +953,6 @@ func (a *ProjectAvatar) MarshalJSON() ([]byte, error) { return json.Marshal((*alias)(a)) } -// CreateProject creates a new project owned by the authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/projects/#create-a-project func (s *ProjectsService) CreateProject(opt *CreateProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) { if opt.ContainerExpirationPolicyAttributes != nil { // This is needed to satisfy the API. Should be deleted @@ -843,33 +960,16 @@ func (s *ProjectsService) CreateProject(opt *CreateProjectOptions, options ...Re opt.ContainerExpirationPolicyAttributes.NameRegex = opt.ContainerExpirationPolicyAttributes.NameRegexDelete } - var err error - var req *retryablehttp.Request - - if opt.Avatar == nil { - req, err = s.client.NewRequest(http.MethodPost, "projects", opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPost, - "projects", - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) - } - if err != nil { - return nil, nil, err + reqOpts := []doOption{ + withMethod(http.MethodPost), + withPath("projects"), + withAPIOpts(opt), + withRequestOpts(options...), } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err + if opt.Avatar != nil { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - return p, resp, nil + return do[*Project](s.client, reqOpts...) } // CreateProjectForUserOptions represents the available CreateProjectForUser() @@ -879,46 +979,23 @@ func (s *ProjectsService) CreateProject(opt *CreateProjectOptions, options ...Re // https://docs.gitlab.com/api/projects/#create-a-project-for-a-user type CreateProjectForUserOptions CreateProjectOptions -// CreateProjectForUser creates a new project owned by the specified user. -// Available only for admins. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#create-a-project-for-a-user -func (s *ProjectsService) CreateProjectForUser(user int, opt *CreateProjectForUserOptions, options ...RequestOptionFunc) (*Project, *Response, error) { +func (s *ProjectsService) CreateProjectForUser(user int64, opt *CreateProjectForUserOptions, options ...RequestOptionFunc) (*Project, *Response, error) { if opt.ContainerExpirationPolicyAttributes != nil { // This is needed to satisfy the API. Should be deleted // when NameRegex is removed (it's now deprecated). opt.ContainerExpirationPolicyAttributes.NameRegex = opt.ContainerExpirationPolicyAttributes.NameRegexDelete } - var err error - var req *retryablehttp.Request - u := fmt.Sprintf("projects/user/%d", user) - - if opt.Avatar == nil { - req, err = s.client.NewRequest(http.MethodPost, u, opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPost, - u, - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) - } - if err != nil { - return nil, nil, err + reqOpts := []doOption{ + withMethod(http.MethodPost), + withPath("projects/user/%d", user), + withAPIOpts(opt), + withRequestOpts(options...), } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err + if opt.Avatar != nil { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - return p, resp, nil + return do[*Project](s.client, reqOpts...) } // EditProjectOptions represents the available EditProject() options. @@ -937,16 +1014,16 @@ type EditProjectOptions struct { Avatar *ProjectAvatar `url:"-" json:"avatar,omitempty"` BuildCoverageRegex *string `url:"build_coverage_regex,omitempty" json:"build_coverage_regex,omitempty"` BuildGitStrategy *string `url:"build_git_strategy,omitempty" json:"build_git_strategy,omitempty"` - BuildTimeout *int `url:"build_timeout,omitempty" json:"build_timeout,omitempty"` + BuildTimeout *int64 `url:"build_timeout,omitempty" json:"build_timeout,omitempty"` BuildsAccessLevel *AccessControlValue `url:"builds_access_level,omitempty" json:"builds_access_level,omitempty"` CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"` - CIDefaultGitDepth *int `url:"ci_default_git_depth,omitempty" json:"ci_default_git_depth,omitempty"` - CIDeletePipelinesInSeconds *int `url:"ci_delete_pipelines_in_seconds,omitempty" json:"ci_delete_pipelines_in_seconds,omitempty"` + CIDefaultGitDepth *int64 `url:"ci_default_git_depth,omitempty" json:"ci_default_git_depth,omitempty"` + CIDeletePipelinesInSeconds *int64 `url:"ci_delete_pipelines_in_seconds,omitempty" json:"ci_delete_pipelines_in_seconds,omitempty"` CIForwardDeploymentEnabled *bool `url:"ci_forward_deployment_enabled,omitempty" json:"ci_forward_deployment_enabled,omitempty"` CIForwardDeploymentRollbackAllowed *bool `url:"ci_forward_deployment_rollback_allowed,omitempty" json:"ci_forward_deployment_rollback_allowed,omitempty"` CIPushRepositoryForJobTokenAllowed *bool `url:"ci_push_repository_for_job_token_allowed,omitempty" json:"ci_push_repository_for_job_token_allowed,omitempty"` CIIdTokenSubClaimComponents *[]string `url:"ci_id_token_sub_claim_components,omitempty" json:"ci_id_token_sub_claim_components,omitempty"` - CISeperateCache *bool `url:"ci_separated_caches,omitempty" json:"ci_separated_caches,omitempty"` + CISeparatedCaches *bool `url:"ci_separated_caches,omitempty" json:"ci_separated_caches,omitempty"` CIRestrictPipelineCancellationRole *AccessControlValue `url:"ci_restrict_pipeline_cancellation_role,omitempty" json:"ci_restrict_pipeline_cancellation_role,omitempty"` CIPipelineVariablesMinimumOverrideRole *CIPipelineVariablesMinimumOverrideRoleValue `url:"ci_pipeline_variables_minimum_override_role,omitempty" json:"ci_pipeline_variables_minimum_override_role,omitempty"` ContainerExpirationPolicyAttributes *ContainerExpirationPolicyAttributes `url:"container_expiration_policy_attributes,omitempty" json:"container_expiration_policy_attributes,omitempty"` @@ -963,6 +1040,7 @@ type EditProjectOptions struct { IssuesTemplate *string `url:"issues_template,omitempty" json:"issues_template,omitempty"` KeepLatestArtifact *bool `url:"keep_latest_artifact,omitempty" json:"keep_latest_artifact,omitempty"` LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` + MaxArtifactsSize *int64 `url:"max_artifacts_size,omitempty" json:"max_artifacts_size,omitempty"` MergeCommitTemplate *string `url:"merge_commit_template,omitempty" json:"merge_commit_template,omitempty"` MergeRequestDefaultTargetSelf *bool `url:"mr_default_target_self,omitempty" json:"mr_default_target_self,omitempty"` MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"` @@ -975,7 +1053,7 @@ type EditProjectOptions struct { MirrorBranchRegex *string `url:"mirror_branch_regex,omitempty" json:"mirror_branch_regex,omitempty"` MirrorOverwritesDivergedBranches *bool `url:"mirror_overwrites_diverged_branches,omitempty" json:"mirror_overwrites_diverged_branches,omitempty"` MirrorTriggerBuilds *bool `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,omitempty"` - MirrorUserID *int `url:"mirror_user_id,omitempty" json:"mirror_user_id,omitempty"` + MirrorUserID *int64 `url:"mirror_user_id,omitempty" json:"mirror_user_id,omitempty"` ModelExperimentsAccessLevel *AccessControlValue `url:"model_experiments_access_level,omitempty" json:"model_experiments_access_level,omitempty"` ModelRegistryAccessLevel *AccessControlValue `url:"model_registry_access_level,omitempty" json:"model_registry_access_level,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` @@ -1004,6 +1082,7 @@ type EditProjectOptions struct { ServiceDeskEnabled *bool `url:"service_desk_enabled,omitempty" json:"service_desk_enabled,omitempty"` SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"` GroupRunnersEnabled *bool `url:"group_runners_enabled,omitempty" json:"group_runners_enabled,omitempty"` + ResourceGroupDefaultProcessMode *ResourceGroupProcessMode `url:"resource_group_default_process_mode,omitempty" json:"resource_group_default_process_mode,omitempty"` ShowDefaultAwardEmojis *bool `url:"show_default_award_emojis,omitempty" json:"show_default_award_emojis,omitempty"` SnippetsAccessLevel *AccessControlValue `url:"snippets_access_level,omitempty" json:"snippets_access_level,omitempty"` SquashCommitTemplate *string `url:"squash_commit_template,omitempty" json:"squash_commit_template,omitempty"` @@ -1014,7 +1093,7 @@ type EditProjectOptions struct { WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"` // Deprecated: use Merge Request Approvals API instead - ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` + ApprovalsBeforeMerge *int64 `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` // Deprecated: use PublicJobs instead PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"` // Deprecated: use CIPipelineVariablesMinimumOverrideRole instead @@ -1037,9 +1116,6 @@ type EditProjectOptions struct { WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"` } -// EditProject updates an existing project. -// -// GitLab API docs: https://docs.gitlab.com/api/projects/#edit-a-project func (s *ProjectsService) EditProject(pid any, opt *EditProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) { if opt.ContainerExpirationPolicyAttributes != nil { // This is needed to satisfy the API. Should be deleted @@ -1047,38 +1123,16 @@ func (s *ProjectsService) EditProject(pid any, opt *EditProjectOptions, options opt.ContainerExpirationPolicyAttributes.NameRegex = opt.ContainerExpirationPolicyAttributes.NameRegexDelete } - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s", PathEscape(project)) - - var req *retryablehttp.Request - - if opt.Avatar == nil || (opt.Avatar.Filename == "" && opt.Avatar.Image == nil) { - req, err = s.client.NewRequest(http.MethodPut, u, opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPut, - u, - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) + reqOpts := []doOption{ + withMethod(http.MethodPut), + withPath("projects/%s", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), } - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err + if opt.Avatar != nil && (opt.Avatar.Filename != "" || opt.Avatar.Image != nil) { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - return p, resp, nil + return do[*Project](s.client, reqOpts...) } // ForkProjectOptions represents the available ForkProject() options. @@ -1090,7 +1144,7 @@ type ForkProjectOptions struct { Description *string `url:"description,omitempty" json:"description,omitempty"` MergeRequestDefaultTargetSelf *bool `url:"mr_default_target_self,omitempty" json:"mr_default_target_self,omitempty"` Name *string `url:"name,omitempty" json:"name,omitempty"` - NamespaceID *int `url:"namespace_id,omitempty" json:"namespace_id,omitempty"` + NamespaceID *int64 `url:"namespace_id,omitempty" json:"namespace_id,omitempty"` NamespacePath *string `url:"namespace_path,omitempty" json:"namespace_path,omitempty"` Path *string `url:"path,omitempty" json:"path,omitempty"` Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"` @@ -1099,55 +1153,21 @@ type ForkProjectOptions struct { Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"` } -// ForkProject forks a project into the user namespace of the authenticated -// user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_forks/#fork-a-project func (s *ProjectsService) ForkProject(pid any, opt *ForkProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/fork", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/fork", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// StarProject stars a given the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_starring/#star-a-project func (s *ProjectsService) StarProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/star", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/star", ProjectID{pid}), + withRequestOpts(options...), + ) } // ListProjectInvitedGroupOptions represents the available @@ -1163,136 +1183,44 @@ type ListProjectInvitedGroupOptions struct { WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"` } -// ListProjectInvidedGroupOptions is kept for backwards compatibility. -// -// Deprecated: use ListProjectInvitedGroupOptions instead. The ListProjectInvidedGroupOptions type will be removed in the next release. -type ListProjectInvidedGroupOptions = ListProjectInvitedGroupOptions - -// ListProjectsInvitedGroups lists invited groups of a project -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#list-a-projects-invited-groups -func (s *ProjectsService) ListProjectsInvitedGroups(pid any, opt *ListProjectInvidedGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/invited_groups", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pg []*ProjectGroup - resp, err := s.client.Do(req, &pg) - if err != nil { - return nil, resp, err - } - - return pg, resp, nil +func (s *ProjectsService) ListProjectsInvitedGroups(pid any, opt *ListProjectInvitedGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) { + return do[[]*ProjectGroup](s.client, + withPath("projects/%s/invited_groups", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// UnstarProject unstars a given project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_starring/#unstar-a-project func (s *ProjectsService) UnstarProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/unstar", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/unstar", ProjectID{pid}), + withRequestOpts(options...), + ) } -// ArchiveProject archives the project if the user is either admin or the -// project owner of this project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#archive-a-project func (s *ProjectsService) ArchiveProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/archive", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/archive", ProjectID{pid}), + withRequestOpts(options...), + ) } -// UnarchiveProject unarchives the project if the user is either admin or -// the project owner of this project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#unarchive-a-project func (s *ProjectsService) UnarchiveProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/unarchive", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/unarchive", ProjectID{pid}), + withRequestOpts(options...), + ) } -// RestoreProject restores a project that is marked for deletion. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#restore-a-project-marked-for-deletion func (s *ProjectsService) RestoreProject(pid any, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/restore", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/restore", ProjectID{pid}), + withRequestOpts(options...), + ) } // DeleteProjectOptions represents the available DeleteProject() options. @@ -1304,24 +1232,14 @@ type DeleteProjectOptions struct { PermanentlyRemove *bool `url:"permanently_remove" json:"permanently_remove"` } -// DeleteProject removes a project including all associated resources -// (issues, merge requests etc.) -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#delete-a-project func (s *ProjectsService) DeleteProject(pid any, opt *DeleteProjectOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // ShareWithGroupOptions represents the available SharedWithGroup() options. @@ -1330,53 +1248,35 @@ func (s *ProjectsService) DeleteProject(pid any, opt *DeleteProjectOptions, opti type ShareWithGroupOptions struct { ExpiresAt *string `url:"expires_at" json:"expires_at"` GroupAccess *AccessLevelValue `url:"group_access" json:"group_access"` - GroupID *int `url:"group_id" json:"group_id"` + GroupID *int64 `url:"group_id" json:"group_id"` } -// ShareProjectWithGroup allows to share a project with a group. -// -// GitLab API docs: https://docs.gitlab.com/api/projects/#share-a-project-with-a-group func (s *ProjectsService) ShareProjectWithGroup(pid any, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/share", PathEscape(project)) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/share", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err +} - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } +func (s *ProjectsService) DeleteSharedProjectFromGroup(pid any, groupID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/share/%d", ProjectID{pid}, groupID), + withRequestOpts(options...), + ) + return resp, err +} - return s.client.Do(req, nil) -} - -// DeleteSharedProjectFromGroup allows to unshare a project from a group. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#delete-a-shared-project-link-in-a-group -func (s *ProjectsService) DeleteSharedProjectFromGroup(pid any, groupID int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/share/%d", PathEscape(project), groupID) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) -} - -// HookCustomHeader represents a project or group hook custom header -// Note: "Key" is returned from the Get operation, but "Value" is not -// The List operation doesn't return any headers at all for Projects, -// but does return headers for Groups -type HookCustomHeader struct { - Key string `json:"key"` - Value string `json:"value"` +// HookCustomHeader represents a project or group hook custom header +// Note: "Key" is returned from the Get operation, but "Value" is not +// The List operation doesn't return any headers at all for Projects, +// but does return headers for Groups +type HookCustomHeader struct { + Key string `json:"key"` + Value string `json:"value"` } // HookURLVariable represents a project or group hook URL variable @@ -1390,11 +1290,11 @@ type HookURLVariable struct { // GitLab API docs: // https://docs.gitlab.com/api/project_webhooks/#list-webhooks-for-a-project type ProjectHook struct { - ID int `json:"id"` + ID int64 `json:"id"` URL string `json:"url"` Name string `json:"name"` Description string `json:"description"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` PushEvents bool `json:"push_events"` PushEventsBranchFilter string `json:"push_events_branch_filter"` IssuesEvents bool `json:"issues_events"` @@ -1410,6 +1310,7 @@ type ProjectHook struct { ReleasesEvents bool `json:"releases_events"` MilestoneEvents bool `json:"milestone_events"` FeatureFlagEvents bool `json:"feature_flag_events"` + EmojiEvents bool `json:"emoji_events"` EnableSSLVerification bool `json:"enable_ssl_verification"` RepositoryUpdateEvents bool `json:"repository_update_events"` AlertStatus string `json:"alert_status"` @@ -1419,62 +1320,31 @@ type ProjectHook struct { ResourceAccessTokenEvents bool `json:"resource_access_token_events"` CustomWebhookTemplate string `json:"custom_webhook_template"` CustomHeaders []*HookCustomHeader `json:"custom_headers"` + VulnerabilityEvents bool `json:"vulnerability_events"` + BranchFilterStrategy string `json:"branch_filter_strategy"` } // ListProjectHooksOptions represents the available ListProjectHooks() options. // // GitLab API docs: // https://docs.gitlab.com/api/project_webhooks/#list-webhooks-for-a-project -type ListProjectHooksOptions ListOptions +type ListProjectHooksOptions struct { + ListOptions +} -// ListProjectHooks gets a list of project hooks. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#list-webhooks-for-a-project func (s *ProjectsService) ListProjectHooks(pid any, opt *ListProjectHooksOptions, options ...RequestOptionFunc) ([]*ProjectHook, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/hooks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ph []*ProjectHook - resp, err := s.client.Do(req, &ph) - if err != nil { - return nil, resp, err - } - - return ph, resp, nil + return do[[]*ProjectHook](s.client, + withPath("projects/%s/hooks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectHook gets a specific hook for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#get-a-project-webhook -func (s *ProjectsService) GetProjectHook(pid any, hook int, options ...RequestOptionFunc) (*ProjectHook, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d", PathEscape(project), hook) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ph := new(ProjectHook) - resp, err := s.client.Do(req, ph) - if err != nil { - return nil, resp, err - } - - return ph, resp, nil +func (s *ProjectsService) GetProjectHook(pid any, hook int64, options ...RequestOptionFunc) (*ProjectHook, *Response, error) { + return do[*ProjectHook](s.client, + withPath("projects/%s/hooks/%d", ProjectID{pid}, hook), + withRequestOpts(options...), + ) } // AddProjectHookOptions represents the available AddProjectHook() options. @@ -1496,6 +1366,7 @@ type AddProjectHookOptions struct { PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"` ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"` + EmojiEvents *bool `url:"emoji_events,omitempty" json:"emoji_events,omitempty"` TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` Token *string `url:"token,omitempty" json:"token,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` @@ -1503,31 +1374,17 @@ type AddProjectHookOptions struct { ResourceAccessTokenEvents *bool `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"` CustomWebhookTemplate *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"` CustomHeaders *[]*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"` + VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"` + BranchFilterStrategy *string `url:"branch_filter_strategy,omitempty" json:"branch_filter_strategy,omitempty"` } -// AddProjectHook adds a hook to a specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#add-a-webhook-to-a-project func (s *ProjectsService) AddProjectHook(pid any, opt *AddProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/hooks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ph := new(ProjectHook) - resp, err := s.client.Do(req, ph) - if err != nil { - return nil, resp, err - } - - return ph, resp, nil + return do[*ProjectHook](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/hooks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditProjectHookOptions represents the available EditProjectHook() options. @@ -1549,6 +1406,7 @@ type EditProjectHookOptions struct { PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"` ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"` + EmojiEvents *bool `url:"emoji_events,omitempty" json:"emoji_events,omitempty"` TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` Token *string `url:"token,omitempty" json:"token,omitempty"` URL *string `url:"url,omitempty" json:"url,omitempty"` @@ -1556,51 +1414,26 @@ type EditProjectHookOptions struct { ResourceAccessTokenEvents *bool `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"` CustomWebhookTemplate *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"` CustomHeaders *[]*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"` + VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"` + BranchFilterStrategy *string `url:"branch_filter_strategy,omitempty" json:"branch_filter_strategy,omitempty"` } -// EditProjectHook edits a hook for a specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#edit-a-project-webhook -func (s *ProjectsService) EditProjectHook(pid any, hook int, opt *EditProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d", PathEscape(project), hook) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ph := new(ProjectHook) - resp, err := s.client.Do(req, ph) - if err != nil { - return nil, resp, err - } - - return ph, resp, nil +func (s *ProjectsService) EditProjectHook(pid any, hook int64, opt *EditProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) { + return do[*ProjectHook](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/hooks/%d", ProjectID{pid}, hook), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteProjectHook removes a hook from a project. This is an idempotent -// method and can be called multiple times. Either the hook is available or not. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#delete-project-webhook -func (s *ProjectsService) DeleteProjectHook(pid any, hook int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d", PathEscape(project), hook) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) DeleteProjectHook(pid any, hook int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/hooks/%d", ProjectID{pid}, hook), + withRequestOpts(options...), + ) + return resp, err } // TriggerTestProjectHook Trigger a test hook for a specified project. @@ -1615,19 +1448,13 @@ func (s *ProjectsService) DeleteProjectHook(pid any, hook int, options ...Reques // // GitLab API docs: // https://docs.gitlab.com/api/project_webhooks/#trigger-a-test-project-webhook -func (s *ProjectsService) TriggerTestProjectHook(pid any, hook int, event ProjectHookEvent, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d/test/%s", PathEscape(project), hook, string(event)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) TriggerTestProjectHook(pid any, hook int64, event ProjectHookEvent, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/hooks/%d/test/%s", ProjectID{pid}, hook, string(event)), + withRequestOpts(options...), + ) + return resp, err } // SetHookCustomHeaderOptions represents the available SetProjectCustomHeader() @@ -1639,42 +1466,23 @@ type SetHookCustomHeaderOptions struct { Value *string `json:"value,omitempty"` } -// SetProjectCustomHeader creates or updates a project custom webhook header. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#set-a-custom-header -func (s *ProjectsService) SetProjectCustomHeader(pid any, hook int, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d/custom_headers/%s", PathEscape(project), hook, key) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) SetProjectCustomHeader(pid any, hook int64, key string, opt *SetHookCustomHeaderOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/hooks/%d/custom_headers/%s", ProjectID{pid}, hook, key), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// DeleteProjectCustomHeader deletes a project custom webhook header. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#delete-a-custom-header -func (s *ProjectsService) DeleteProjectCustomHeader(pid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d/custom_headers/%s", PathEscape(project), hook, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) DeleteProjectCustomHeader(pid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/hooks/%d/custom_headers/%s", ProjectID{pid}, hook, key), + withRequestOpts(options...), + ) + return resp, err } // SetProjectWebhookURLVariableOptions represents the available @@ -1686,42 +1494,23 @@ type SetProjectWebhookURLVariableOptions struct { Value *string `json:"value,omitempty"` } -// SetProjectWebhookURLVariable creates or updates a project webhook URL variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#set-a-url-variable -func (s *ProjectsService) SetProjectWebhookURLVariable(pid any, hook int, key string, opt *SetProjectWebhookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d/url_variables/%s", PathEscape(project), hook, PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) SetProjectWebhookURLVariable(pid any, hook int64, key string, opt *SetProjectWebhookURLVariableOptions, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/hooks/%d/url_variables/%s", ProjectID{pid}, hook, key), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// DeleteProjectWebhookURLVariable deletes a project webhook URL variable. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_webhooks/#delete-a-url-variable -func (s *ProjectsService) DeleteProjectWebhookURLVariable(pid any, hook int, key string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/hooks/%d/url_variables/%s", PathEscape(project), hook, PathEscape(key)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) DeleteProjectWebhookURLVariable(pid any, hook int64, key string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/hooks/%d/url_variables/%s", ProjectID{pid}, hook, key), + withRequestOpts(options...), + ) + return resp, err } // ProjectForkRelation represents a project fork relationship. @@ -1729,139 +1518,56 @@ func (s *ProjectsService) DeleteProjectWebhookURLVariable(pid any, hook int, key // GitLab API docs: // https://docs.gitlab.com/api/project_forks/#create-a-fork-relationship-between-projects type ProjectForkRelation struct { - ID int `json:"id"` - ForkedToProjectID int `json:"forked_to_project_id"` - ForkedFromProjectID int `json:"forked_from_project_id"` + ID int64 `json:"id"` + ForkedToProjectID int64 `json:"forked_to_project_id"` + ForkedFromProjectID int64 `json:"forked_from_project_id"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` } -// CreateProjectForkRelation creates a forked from/to relation between -// existing projects. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_forks/#create-a-fork-relationship-between-projects -func (s *ProjectsService) CreateProjectForkRelation(pid any, fork int, options ...RequestOptionFunc) (*ProjectForkRelation, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/fork/%d", PathEscape(project), fork) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - pfr := new(ProjectForkRelation) - resp, err := s.client.Do(req, pfr) - if err != nil { - return nil, resp, err - } - - return pfr, resp, nil +func (s *ProjectsService) CreateProjectForkRelation(pid any, fork int64, options ...RequestOptionFunc) (*ProjectForkRelation, *Response, error) { + return do[*ProjectForkRelation](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/fork/%d", ProjectID{pid}, fork), + withRequestOpts(options...), + ) } -// DeleteProjectForkRelation deletes an existing forked from relationship. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_forks/#delete-a-fork-relationship-between-projects func (s *ProjectsService) DeleteProjectForkRelation(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/fork", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/fork", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } -// UploadAvatar uploads an avatar. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#upload-a-project-avatar func (s *ProjectsService) UploadAvatar(pid any, avatar io.Reader, filename string, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s", PathEscape(project)) - - req, err := s.client.UploadRequest( - http.MethodPut, - u, - avatar, - filename, - UploadAvatar, - nil, - options, + return do[*Project](s.client, + withMethod(http.MethodPut), + withPath("projects/%s", ProjectID{pid}), + withUpload(avatar, filename, UploadAvatar), + withRequestOpts(options...), ) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil } -// DownloadAvatar downloads an avatar. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#download-a-project-avatar func (s *ProjectsService) DownloadAvatar(pid any, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/avatar", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - avatar := new(bytes.Buffer) - resp, err := s.client.Do(req, avatar) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/avatar", ProjectID{pid}), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return bytes.NewReader(avatar.Bytes()), resp, err + return bytes.NewReader(buf.Bytes()), resp, nil } -// ListProjectForks gets a list of project forks. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_forks/#list-forks-of-a-project func (s *ProjectsService) ListProjectForks(pid any, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/forks", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var forks []*Project - resp, err := s.client.Do(req, &forks) - if err != nil { - return nil, resp, err - } - - return forks, resp, nil + return do[[]*Project](s.client, + withPath("projects/%s/forks", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectPushRules represents a project push rule. @@ -1869,8 +1575,8 @@ func (s *ProjectsService) ListProjectForks(pid any, opt *ListProjectsOptions, op // GitLab API docs: // https://docs.gitlab.com/api/project_push_rules/ type ProjectPushRules struct { - ID int `json:"id"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` CommitMessageRegex string `json:"commit_message_regex"` CommitMessageNegativeRegex string `json:"commit_message_negative_regex"` BranchNameRegex string `json:"branch_name_regex"` @@ -1880,36 +1586,18 @@ type ProjectPushRules struct { PreventSecrets bool `json:"prevent_secrets"` AuthorEmailRegex string `json:"author_email_regex"` FileNameRegex string `json:"file_name_regex"` - MaxFileSize int `json:"max_file_size"` + MaxFileSize int64 `json:"max_file_size"` CommitCommitterCheck bool `json:"commit_committer_check"` CommitCommitterNameCheck bool `json:"commit_committer_name_check"` RejectUnsignedCommits bool `json:"reject_unsigned_commits"` RejectNonDCOCommits bool `json:"reject_non_dco_commits"` } -// GetProjectPushRules gets the push rules of a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_push_rules/#get-project-push-rules func (s *ProjectsService) GetProjectPushRules(pid any, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/push_rule", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ppr := new(ProjectPushRules) - resp, err := s.client.Do(req, ppr) - if err != nil { - return nil, resp, err - } - - return ppr, resp, nil + return do[*ProjectPushRules](s.client, + withPath("projects/%s/push_rule", ProjectID{pid}), + withRequestOpts(options...), + ) } // AddProjectPushRuleOptions represents the available AddProjectPushRule() @@ -1926,36 +1614,20 @@ type AddProjectPushRuleOptions struct { CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"` DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"` FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"` - MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` + MaxFileSize *int64 `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"` PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"` RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"` RejectNonDCOCommits *bool `url:"reject_non_dco_commits,omitempty" json:"reject_non_dco_commits,omitempty"` } -// AddProjectPushRule adds a push rule to a specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_push_rules/#add-a-project-push-rule func (s *ProjectsService) AddProjectPushRule(pid any, opt *AddProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/push_rule", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - ppr := new(ProjectPushRules) - resp, err := s.client.Do(req, ppr) - if err != nil { - return nil, resp, err - } - - return ppr, resp, nil + return do[*ProjectPushRules](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/push_rule", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditProjectPushRuleOptions represents the available EditProjectPushRule() @@ -1972,57 +1644,29 @@ type EditProjectPushRuleOptions struct { CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"` DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"` FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"` - MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` + MaxFileSize *int64 `url:"max_file_size,omitempty" json:"max_file_size,omitempty"` MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"` PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"` RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"` RejectNonDCOCommits *bool `url:"reject_non_dco_commits,omitempty" json:"reject_non_dco_commits,omitempty"` } -// EditProjectPushRule edits a push rule for a specified project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_push_rules/#edit-project-push-rule func (s *ProjectsService) EditProjectPushRule(pid any, opt *EditProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/push_rule", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ppr := new(ProjectPushRules) - resp, err := s.client.Do(req, ppr) - if err != nil { - return nil, resp, err - } - - return ppr, resp, nil + return do[*ProjectPushRules](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/push_rule", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteProjectPushRule removes a push rule from a project. This is an -// idempotent method and can be called multiple times. Either the push rule is -// available or not. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_push_rules/#delete-project-push-rule func (s *ProjectsService) DeleteProjectPushRule(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/push_rule", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/push_rule", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // ProjectApprovals represents GitLab project level merge request approvals. @@ -2040,32 +1684,14 @@ type ProjectApprovals struct { SelectiveCodeOwnerRemovals bool `json:"selective_code_owner_removals,omitempty"` // Deprecated: use Merge Request Approvals API instead - ApprovalsBeforeMerge int `json:"approvals_before_merge"` + ApprovalsBeforeMerge int64 `json:"approvals_before_merge"` } -// GetApprovalConfiguration get the approval configuration for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#project-approval-rules func (s *ProjectsService) GetApprovalConfiguration(pid any, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approvals", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pa := new(ProjectApprovals) - resp, err := s.client.Do(req, pa) - if err != nil { - return nil, resp, err - } - - return pa, resp, nil + return do[*ProjectApprovals](s.client, + withPath("projects/%s/approvals", ProjectID{pid}), + withRequestOpts(options...), + ) } // ChangeApprovalConfigurationOptions represents the available @@ -2082,32 +1708,16 @@ type ChangeApprovalConfigurationOptions struct { SelectiveCodeOwnerRemovals *bool `url:"selective_code_owner_removals,omitempty" json:"selective_code_owner_removals,omitempty"` // Deprecated: use Merge Request Approvals API instead - ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` + ApprovalsBeforeMerge *int64 `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"` } -// ChangeApprovalConfiguration updates the approval configuration for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#change-configuration func (s *ProjectsService) ChangeApprovalConfiguration(pid any, opt *ChangeApprovalConfigurationOptions, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approvals", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pa := new(ProjectApprovals) - resp, err := s.client.Do(req, pa) - if err != nil { - return nil, resp, err - } - - return pa, resp, nil + return do[*ProjectApprovals](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/approvals", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProjectApprovalRulesListsOptions represents the available @@ -2115,56 +1725,23 @@ func (s *ProjectsService) ChangeApprovalConfiguration(pid any, opt *ChangeApprov // // GitLab API docs: // https://docs.gitlab.com/api/merge_request_approvals/#get-all-approval-rules-for-project -type GetProjectApprovalRulesListsOptions ListOptions +type GetProjectApprovalRulesListsOptions struct { + ListOptions +} -// GetProjectApprovalRules looks up the list of project level approver rules. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#get-all-approval-rules-for-project func (s *ProjectsService) GetProjectApprovalRules(pid any, opt *GetProjectApprovalRulesListsOptions, options ...RequestOptionFunc) ([]*ProjectApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approval_rules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var par []*ProjectApprovalRule - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil + return do[[]*ProjectApprovalRule](s.client, + withPath("projects/%s/approval_rules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetProjectApprovalRule gets the project level approvers. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#get-single-approval-rule-for-project -func (s *ProjectsService) GetProjectApprovalRule(pid any, ruleID int, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approval_rules/%d", PathEscape(project), ruleID) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - par := new(ProjectApprovalRule) - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil +func (s *ProjectsService) GetProjectApprovalRule(pid any, ruleID int64, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) { + return do[*ProjectApprovalRule](s.client, + withPath("projects/%s/approval_rules/%d", ProjectID{pid}, ruleID), + withRequestOpts(options...), + ) } // CreateProjectLevelRuleOptions represents the available CreateProjectApprovalRule() @@ -2174,39 +1751,23 @@ func (s *ProjectsService) GetProjectApprovalRule(pid any, ruleID int, options .. // https://docs.gitlab.com/api/merge_request_approvals/#create-project-approval-rule type CreateProjectLevelRuleOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` - ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` + ApprovalsRequired *int64 `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` ReportType *string `url:"report_type,omitempty" json:"report_type,omitempty"` RuleType *string `url:"rule_type,omitempty" json:"rule_type,omitempty"` - UserIDs *[]int `url:"user_ids,omitempty" json:"user_ids,omitempty"` - GroupIDs *[]int `url:"group_ids,omitempty" json:"group_ids,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + UserIDs *[]int64 `url:"user_ids,omitempty" json:"user_ids,omitempty"` + GroupIDs *[]int64 `url:"group_ids,omitempty" json:"group_ids,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` AppliesToAllProtectedBranches *bool `url:"applies_to_all_protected_branches,omitempty" json:"applies_to_all_protected_branches,omitempty"` Usernames *[]string `url:"usernames,omitempty" json:"usernames,omitempty"` } -// CreateProjectApprovalRule creates a new project-level approval rule. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#create-project-approval-rule func (s *ProjectsService) CreateProjectApprovalRule(pid any, opt *CreateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approval_rules", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - par := new(ProjectApprovalRule) - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil + return do[*ProjectApprovalRule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/approval_rules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateProjectLevelRuleOptions represents the available UpdateProjectApprovalRule() @@ -2216,56 +1777,30 @@ func (s *ProjectsService) CreateProjectApprovalRule(pid any, opt *CreateProjectL // https://docs.gitlab.com/api/merge_request_approvals/#update-project-approval-rule type UpdateProjectLevelRuleOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` - ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` - UserIDs *[]int `url:"user_ids,omitempty" json:"user_ids,omitempty"` - GroupIDs *[]int `url:"group_ids,omitempty" json:"group_ids,omitempty"` - ProtectedBranchIDs *[]int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` + ApprovalsRequired *int64 `url:"approvals_required,omitempty" json:"approvals_required,omitempty"` + UserIDs *[]int64 `url:"user_ids,omitempty" json:"user_ids,omitempty"` + GroupIDs *[]int64 `url:"group_ids,omitempty" json:"group_ids,omitempty"` + ProtectedBranchIDs *[]int64 `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"` AppliesToAllProtectedBranches *bool `url:"applies_to_all_protected_branches,omitempty" json:"applies_to_all_protected_branches,omitempty"` Usernames *[]string `url:"usernames,omitempty" json:"usernames,omitempty"` } -// UpdateProjectApprovalRule updates an existing approval rule with new options. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#update-project-approval-rule -func (s *ProjectsService) UpdateProjectApprovalRule(pid any, approvalRule int, opt *UpdateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/approval_rules/%d", PathEscape(project), approvalRule) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - par := new(ProjectApprovalRule) - resp, err := s.client.Do(req, &par) - if err != nil { - return nil, resp, err - } - - return par, resp, nil +func (s *ProjectsService) UpdateProjectApprovalRule(pid any, approvalRule int64, opt *UpdateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) { + return do[*ProjectApprovalRule](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/approval_rules/%d", ProjectID{pid}, approvalRule), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteProjectApprovalRule deletes a project-level approval rule. -// -// GitLab API docs: -// https://docs.gitlab.com/api/merge_request_approvals/#delete-project-approval-rule -func (s *ProjectsService) DeleteProjectApprovalRule(pid any, approvalRule int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/approval_rules/%d", PathEscape(project), approvalRule) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *ProjectsService) DeleteProjectApprovalRule(pid any, approvalRule int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/approval_rules/%d", ProjectID{pid}, approvalRule), + withRequestOpts(options...), + ) + return resp, err } // ProjectPullMirrorDetails represent the details of the configuration pull @@ -2274,38 +1809,25 @@ func (s *ProjectsService) DeleteProjectApprovalRule(pid any, approvalRule int, o // GitLab API docs: // https://docs.gitlab.com/api/project_pull_mirroring/ type ProjectPullMirrorDetails struct { - ID int `json:"id"` - LastError string `json:"last_error"` - LastSuccessfulUpdateAt *time.Time `json:"last_successful_update_at"` - LastUpdateAt *time.Time `json:"last_update_at"` - LastUpdateStartedAt *time.Time `json:"last_update_started_at"` - UpdateStatus string `json:"update_status"` - URL string `json:"url"` + ID int64 `json:"id"` + LastError string `json:"last_error"` + LastSuccessfulUpdateAt *time.Time `json:"last_successful_update_at"` + LastUpdateAt *time.Time `json:"last_update_at"` + LastUpdateStartedAt *time.Time `json:"last_update_started_at"` + UpdateStatus string `json:"update_status"` + URL string `json:"url"` + Enabled bool `json:"enabled"` + MirrorTriggerBuilds bool `json:"mirror_trigger_builds"` + OnlyMirrorProtectedBranches bool `json:"only_mirror_protected_branches"` + MirrorOverwritesDivergedBranches bool `json:"mirror_overwrites_diverged_branches"` + MirrorBranchRegex string `json:"mirror_branch_regex"` } -// GetProjectPullMirrorDetails returns the pull mirror details. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_pull_mirroring/#get-a-projects-pull-mirror-details func (s *ProjectsService) GetProjectPullMirrorDetails(pid any, options ...RequestOptionFunc) (*ProjectPullMirrorDetails, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/mirror/pull", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pmd := new(ProjectPullMirrorDetails) - resp, err := s.client.Do(req, pmd) - if err != nil { - return nil, resp, err - } - - return pmd, resp, nil + return do[*ProjectPullMirrorDetails](s.client, + withPath("projects/%s/mirror/pull", ProjectID{pid}), + withRequestOpts(options...), + ) } // ConfigureProjectPullMirrorOptions represents the available ConfigureProjectPullMirror() options. @@ -2323,48 +1845,22 @@ type ConfigureProjectPullMirrorOptions struct { MirrorBranchRegex *string `url:"mirror_branch_regex,omitempty" json:"mirror_branch_regex,omitempty"` } -// ConfigureProjectPullMirror configures pull mirroring settings. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_pull_mirroring/#configure-pull-mirroring-for-a-project func (s *ProjectsService) ConfigureProjectPullMirror(pid any, opt *ConfigureProjectPullMirrorOptions, options ...RequestOptionFunc) (*ProjectPullMirrorDetails, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/mirror/pull", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pmd := new(ProjectPullMirrorDetails) - resp, err := s.client.Do(req, pmd) - if err != nil { - return nil, resp, err - } - - return pmd, resp, nil + return do[*ProjectPullMirrorDetails](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/mirror/pull", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// StartMirroringProject start the pull mirroring process for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/project_pull_mirroring/#start-the-pull-mirroring-process-for-a-project func (s *ProjectsService) StartMirroringProject(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/mirror/pull", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/mirror/pull", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // TransferProjectOptions represents the available TransferProject() options. @@ -2375,47 +1871,22 @@ type TransferProjectOptions struct { Namespace any `url:"namespace,omitempty" json:"namespace,omitempty"` } -// TransferProject transfer a project into the specified namespace -// -// GitLab API docs: https://docs.gitlab.com/api/projects/#transfer-a-project-to-a-new-namespace func (s *ProjectsService) TransferProject(pid any, opt *TransferProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/transfer", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(Project) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*Project](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/transfer", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// StartHousekeepingProject start the Housekeeping task for a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/projects/#start-the-housekeeping-task-for-a-project func (s *ProjectsService) StartHousekeepingProject(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/housekeeping", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/housekeeping", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // ProjectRepositoryStorage represents the repository storage information for a project. @@ -2423,38 +1894,41 @@ func (s *ProjectsService) StartHousekeepingProject(pid any, options ...RequestOp // GitLab API docs: // https://docs.gitlab.com/api/projects/#get-the-path-to-repository-storage type ProjectRepositoryStorage struct { - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` DiskPath string `json:"disk_path"` CreatedAt *time.Time `json:"created_at"` RepositoryStorage string `json:"repository_storage"` } -// ProjectReposityStorage is kept for backwards compatibility. -// -// Deprecated: use ProjectRepositoryStorage instead. The ProjectReposityStorage type will be removed in the next release. -type ProjectReposityStorage = ProjectRepositoryStorage +func (s *ProjectsService) GetRepositoryStorage(pid any, options ...RequestOptionFunc) (*ProjectRepositoryStorage, *Response, error) { + return do[*ProjectRepositoryStorage](s.client, + withPath("projects/%s/storage", ProjectID{pid}), + withRequestOpts(options...), + ) +} -// GetRepositoryStorage Get the path to repository storage. +// ProjectStarrer represents a user who starred a project. // // GitLab API docs: -// https://docs.gitlab.com/api/projects/#get-the-path-to-repository-storage -func (s *ProjectsService) GetRepositoryStorage(pid any, options ...RequestOptionFunc) (*ProjectReposityStorage, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/storage", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } +// https://docs.gitlab.com/api/project_starring/#list-users-who-starred-a-project +type ProjectStarrer struct { + StarredSince time.Time `json:"starred_since"` + User ProjectUser `json:"user"` +} - prs := new(ProjectReposityStorage) - resp, err := s.client.Do(req, prs) - if err != nil { - return nil, resp, err - } +// ListProjectStarrersOptions represents the available ListProjectStarrers() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_starring/#list-users-who-starred-a-project +type ListProjectStarrersOptions struct { + ListOptions + Search *string `url:"search,omitempty" json:"search,omitempty"` +} - return prs, resp, nil +func (s *ProjectsService) ListProjectStarrers(pid any, opts *ListProjectStarrersOptions, options ...RequestOptionFunc) ([]*ProjectStarrer, *Response, error) { + return do[[]*ProjectStarrer](s.client, + withPath("projects/%s/starrers", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/protected_branches.go b/vendor/gitlab.com/gitlab-org/api/client-go/protected_branches.go index d3c1aaa76..0fd162ffd 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/protected_branches.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/protected_branches.go @@ -16,11 +16,7 @@ package gitlab -import ( - "fmt" - "net/http" - "net/url" -) +import "net/http" type ( ProtectedBranchesServiceInterface interface { @@ -48,7 +44,7 @@ var _ ProtectedBranchesServiceInterface = (*ProtectedBranchesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#list-protected-branches type ProtectedBranch struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` PushAccessLevels []*BranchAccessDescription `json:"push_access_levels"` MergeAccessLevels []*BranchAccessDescription `json:"merge_access_levels"` @@ -63,12 +59,12 @@ type ProtectedBranch struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#list-protected-branches type BranchAccessDescription struct { - ID int `json:"id"` + ID int64 `json:"id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` - DeployKeyID int `json:"deploy_key_id"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` + DeployKeyID int64 `json:"deploy_key_id"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` } // ListProtectedBranchesOptions represents the available ListProtectedBranches() @@ -86,24 +82,11 @@ type ListProtectedBranchesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#list-protected-branches func (s *ProtectedBranchesService) ListProtectedBranches(pid any, opt *ListProtectedBranchesOptions, options ...RequestOptionFunc) ([]*ProtectedBranch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_branches", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var p []*ProtectedBranch - resp, err := s.client.Do(req, &p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[[]*ProtectedBranch](s.client, + withPath("projects/%s/protected_branches", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProtectedBranch gets a single protected branch or wildcard protected branch. @@ -111,24 +94,10 @@ func (s *ProtectedBranchesService) ListProtectedBranches(pid any, opt *ListProte // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#get-a-single-protected-branch-or-wildcard-protected-branch func (s *ProtectedBranchesService) GetProtectedBranch(pid any, branch string, options ...RequestOptionFunc) (*ProtectedBranch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_branches/%s", PathEscape(project), url.PathEscape(branch)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - p := new(ProtectedBranch) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProtectedBranch](s.client, + withPath("projects/%s/protected_branches/%s", ProjectID{pid}, branch), + withRequestOpts(options...), + ) } // ProtectRepositoryBranchesOptions represents the available @@ -153,10 +122,10 @@ type ProtectRepositoryBranchesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#protect-repository-branches type BranchPermissionOptions struct { - ID *int `url:"id,omitempty" json:"id,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - DeployKeyID *int `url:"deploy_key_id,omitempty" json:"deploy_key_id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + DeployKeyID *int64 `url:"deploy_key_id,omitempty" json:"deploy_key_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` } @@ -167,24 +136,12 @@ type BranchPermissionOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#protect-repository-branches func (s *ProtectedBranchesService) ProtectRepositoryBranches(pid any, opt *ProtectRepositoryBranchesOptions, options ...RequestOptionFunc) (*ProtectedBranch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_branches", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(ProtectedBranch) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProtectedBranch](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/protected_branches", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnprotectRepositoryBranches unprotects the given protected branch or wildcard @@ -193,18 +150,12 @@ func (s *ProtectedBranchesService) ProtectRepositoryBranches(pid any, opt *Prote // GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#unprotect-repository-branches func (s *ProtectedBranchesService) UnprotectRepositoryBranches(pid any, branch string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/protected_branches/%s", PathEscape(project), url.PathEscape(branch)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/protected_branches/%s", ProjectID{pid}, branch), + withRequestOpts(options...), + ) + return resp, err } // UpdateProtectedBranchOptions represents the available @@ -223,25 +174,13 @@ type UpdateProtectedBranchOptions struct { // UpdateProtectedBranch updates a protected branch. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/protected_branches/#update-a-protected-branch func (s *ProtectedBranchesService) UpdateProtectedBranch(pid any, branch string, opt *UpdateProtectedBranchOptions, options ...RequestOptionFunc) (*ProtectedBranch, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_branches/%s", PathEscape(project), url.PathEscape(branch)) - - req, err := s.client.NewRequest(http.MethodPatch, u, opt, options) - if err != nil { - return nil, nil, err - } - - p := new(ProtectedBranch) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProtectedBranch](s.client, + withMethod(http.MethodPatch), + withPath("projects/%s/protected_branches/%s", ProjectID{pid}, branch), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/protected_environments.go b/vendor/gitlab.com/gitlab-org/api/client-go/protected_environments.go index 17a440d1a..57363ef0d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/protected_environments.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/protected_environments.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -49,7 +48,7 @@ var _ ProtectedEnvironmentsServiceInterface = (*ProtectedEnvironmentsService)(ni type ProtectedEnvironment struct { Name string `json:"name"` DeployAccessLevels []*EnvironmentAccessDescription `json:"deploy_access_levels"` - RequiredApprovalCount int `json:"required_approval_count"` + RequiredApprovalCount int64 `json:"required_approval_count"` ApprovalRules []*EnvironmentApprovalRule `json:"approval_rules"` } @@ -59,12 +58,12 @@ type ProtectedEnvironment struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/ type EnvironmentAccessDescription struct { - ID int `json:"id"` + ID int64 `json:"id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` - GroupInheritanceType int `json:"group_inheritance_type"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` + GroupInheritanceType int64 `json:"group_inheritance_type"` } // EnvironmentApprovalRule represents the approval rules for a protected @@ -73,13 +72,13 @@ type EnvironmentAccessDescription struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#protect-a-single-environment type EnvironmentApprovalRule struct { - ID int `json:"id"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` - RequiredApprovalCount int `json:"required_approvals"` - GroupInheritanceType int `json:"group_inheritance_type"` + RequiredApprovalCount int64 `json:"required_approvals"` + GroupInheritanceType int64 `json:"group_inheritance_type"` } // ListProtectedEnvironmentsOptions represents the available @@ -87,7 +86,9 @@ type EnvironmentApprovalRule struct { // // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#list-protected-environments -type ListProtectedEnvironmentsOptions ListOptions +type ListProtectedEnvironmentsOptions struct { + ListOptions +} // ListProtectedEnvironments returns a list of protected environments from a // project. @@ -95,24 +96,11 @@ type ListProtectedEnvironmentsOptions ListOptions // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#list-protected-environments func (s *ProtectedEnvironmentsService) ListProtectedEnvironments(pid any, opt *ListProtectedEnvironmentsOptions, options ...RequestOptionFunc) ([]*ProtectedEnvironment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_environments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pes []*ProtectedEnvironment - resp, err := s.client.Do(req, &pes) - if err != nil { - return nil, resp, err - } - - return pes, resp, nil + return do[[]*ProtectedEnvironment](s.client, + withPath("projects/%s/protected_environments", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProtectedEnvironment returns a single protected environment or wildcard @@ -121,24 +109,10 @@ func (s *ProtectedEnvironmentsService) ListProtectedEnvironments(pid any, opt *L // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#get-a-single-protected-environment func (s *ProtectedEnvironmentsService) GetProtectedEnvironment(pid any, environment string, options ...RequestOptionFunc) (*ProtectedEnvironment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_environments/%s", PathEscape(project), PathEscape(environment)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pe := new(ProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*ProtectedEnvironment](s.client, + withPath("projects/%s/protected_environments/%s", ProjectID{pid}, environment), + withRequestOpts(options...), + ) } // ProtectRepositoryEnvironmentsOptions represents the available @@ -149,7 +123,7 @@ func (s *ProtectedEnvironmentsService) GetProtectedEnvironment(pid any, environm type ProtectRepositoryEnvironmentsOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` DeployAccessLevels *[]*EnvironmentAccessOptions `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"` - RequiredApprovalCount *int `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` + RequiredApprovalCount *int64 `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` ApprovalRules *[]*EnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"` } @@ -160,9 +134,9 @@ type ProtectRepositoryEnvironmentsOptions struct { // https://docs.gitlab.com/api/protected_environments/#protect-a-single-environment type EnvironmentAccessOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` } // EnvironmentApprovalRuleOptions represents the approval rules for a protected @@ -171,12 +145,12 @@ type EnvironmentAccessOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#protect-a-single-environment type EnvironmentApprovalRuleOptions struct { - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` AccessLevelDescription *string `url:"access_level_description,omitempty" json:"access_level_description,omitempty"` - RequiredApprovalCount *int `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + RequiredApprovalCount *int64 `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` } // ProtectRepositoryEnvironments protects a single repository environment or @@ -185,24 +159,12 @@ type EnvironmentApprovalRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#protect-a-single-environment func (s *ProtectedEnvironmentsService) ProtectRepositoryEnvironments(pid any, opt *ProtectRepositoryEnvironmentsOptions, options ...RequestOptionFunc) (*ProtectedEnvironment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_environments", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pe := new(ProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*ProtectedEnvironment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/protected_environments", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateProtectedEnvironmentsOptions represents the available @@ -213,7 +175,7 @@ func (s *ProtectedEnvironmentsService) ProtectRepositoryEnvironments(pid any, op type UpdateProtectedEnvironmentsOptions struct { Name *string `url:"name,omitempty" json:"name,omitempty"` DeployAccessLevels *[]*UpdateEnvironmentAccessOptions `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"` - RequiredApprovalCount *int `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` + RequiredApprovalCount *int64 `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"` ApprovalRules *[]*UpdateEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"` } @@ -224,10 +186,10 @@ type UpdateProtectedEnvironmentsOptions struct { // https://docs.gitlab.com/api/protected_environments/#update-a-protected-environment type UpdateEnvironmentAccessOptions struct { AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` - ID *int `url:"id,omitempty" json:"id,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` } @@ -237,13 +199,13 @@ type UpdateEnvironmentAccessOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#update-a-protected-environment type UpdateEnvironmentApprovalRuleOptions struct { - ID *int `url:"id,omitempty" json:"id,omitempty"` - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + ID *int64 `url:"id,omitempty" json:"id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` AccessLevelDescription *string `url:"access_level_description,omitempty" json:"access_level_description,omitempty"` - RequiredApprovalCount *int `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` - GroupInheritanceType *int `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` + RequiredApprovalCount *int64 `url:"required_approvals,omitempty" json:"required_approvals,omitempty"` + GroupInheritanceType *int64 `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"` Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"` } @@ -253,24 +215,12 @@ type UpdateEnvironmentApprovalRuleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#update-a-protected-environment func (s *ProtectedEnvironmentsService) UpdateProtectedEnvironments(pid any, environment string, opt *UpdateProtectedEnvironmentsOptions, options ...RequestOptionFunc) (*ProtectedEnvironment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_environments/%s", PathEscape(project), PathEscape(environment)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - pe := new(ProtectedEnvironment) - resp, err := s.client.Do(req, pe) - if err != nil { - return nil, resp, err - } - - return pe, resp, nil + return do[*ProtectedEnvironment](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/protected_environments/%s", ProjectID{pid}, environment), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnprotectEnvironment unprotects the given protected environment or wildcard @@ -279,16 +229,10 @@ func (s *ProtectedEnvironmentsService) UpdateProtectedEnvironments(pid any, envi // GitLab API docs: // https://docs.gitlab.com/api/protected_environments/#unprotect-a-single-environment func (s *ProtectedEnvironmentsService) UnprotectEnvironment(pid any, environment string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/protected_environments/%s", PathEscape(project), PathEscape(environment)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/protected_environments/%s", ProjectID{pid}, environment), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/protected_packages.go b/vendor/gitlab.com/gitlab-org/api/client-go/protected_packages.go new file mode 100644 index 000000000..bca13f1b1 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/protected_packages.go @@ -0,0 +1,120 @@ +package gitlab + +import ( + "net/http" +) + +type ( + ProtectedPackagesServiceInterface interface { + // ListPackageProtectionRules gets a list of project package protection rules. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_packages_protection_rules/#list-package-protection-rules + ListPackageProtectionRules(pid any, opt *ListPackageProtectionRulesOptions, options ...RequestOptionFunc) ([]*PackageProtectionRule, *Response, error) + // CreatePackageProtectionRules creates a new package protection rules. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_packages_protection_rules/#create-a-package-protection-rule + CreatePackageProtectionRules(pid any, opt *CreatePackageProtectionRulesOptions, options ...RequestOptionFunc) (*PackageProtectionRule, *Response, error) + // UpdatePackageProtectionRules updates an existing package protection rule. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_packages_protection_rules/#update-a-package-protection-rule + UpdatePackageProtectionRules(pid any, packageProtectionRule int64, opt *UpdatePackageProtectionRulesOptions, options ...RequestOptionFunc) (*PackageProtectionRule, *Response, error) + // DeletePackageProtectionRules deletes an existing package protection rules. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_packages_protection_rules/#delete-a-package-protection-rule + DeletePackageProtectionRules(pid any, packageProtectionRule int64, options ...RequestOptionFunc) (*Response, error) + } + + // ProtectedPackagesService handles communication with the protected packages related methods + // of the GitLab API. + // + // GitLab API docs: + // https://docs.gitlab.com/api/project_packages_protection_rules/ + ProtectedPackagesService struct { + client *Client + } +) + +var _ ProtectedPackagesServiceInterface = (*ProtectedPackagesService)(nil) + +// PackageProtectionRule represents a GitLab package protection rule. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_packages_protection_rules +type PackageProtectionRule struct { + ID int64 `json:"id"` + ProjectID int64 `json:"project_id"` + PackageNamePattern string `json:"package_name_pattern"` + PackageType string `json:"package_type"` + MinimumAccessLevelForDelete string `json:"minimum_access_level_for_delete"` + MinimumAccessLevelForPush string `json:"minimum_access_level_for_push"` +} + +// ListPackageProtectionRulesOptions represents the available ListPackageProtectionRules() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_packages_protection_rules/#list-package-protection-rules +type ListPackageProtectionRulesOptions struct { + ListOptions +} + +// CreatePackageProtectionRulesOptions represents the available CreatePackageProtectionRules() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_packages_protection_rules/#create-a-package-protection-rule +type CreatePackageProtectionRulesOptions struct { + PackageNamePattern *string `url:"package_name_pattern" json:"package_name_pattern"` + PackageType *string `url:"package_type" json:"package_type"` + MinimumAccessLevelForDelete *int64 `url:"minimum_access_level_for_delete" json:"minimum_access_level_for_delete"` + MinimumAccessLevelForPush *int64 `url:"minimum_access_level_for_push" json:"minimum_access_level_for_push"` +} + +// UpdatePackageProtectionRulesOptions represents the available +// UpdatePackageProtectionRules() options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_packages_protection_rules/#update-a-package-protection-rule +type UpdatePackageProtectionRulesOptions struct { + PackageNamePattern *string `url:"package_name_pattern" json:"package_name_pattern"` + PackageType *string `url:"package_type" json:"package_type"` + MinimumAccessLevelForDelete *int64 `url:"minimum_access_level_for_delete" json:"minimum_access_level_for_delete"` + MinimumAccessLevelForPush *int64 `url:"minimum_access_level_for_push" json:"minimum_access_level_for_push"` +} + +func (s *ProtectedPackagesService) ListPackageProtectionRules(pid any, opts *ListPackageProtectionRulesOptions, options ...RequestOptionFunc) ([]*PackageProtectionRule, *Response, error) { + return do[[]*PackageProtectionRule](s.client, + withPath("projects/%s/packages/protection/rules", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) +} + +func (s *ProtectedPackagesService) CreatePackageProtectionRules(pid any, opt *CreatePackageProtectionRulesOptions, options ...RequestOptionFunc) (*PackageProtectionRule, *Response, error) { + return do[*PackageProtectionRule](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/packages/protection/rules", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *ProtectedPackagesService) DeletePackageProtectionRules(pid any, packageProtectionRule int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/packages/protection/rules/%d", ProjectID{pid}, packageProtectionRule), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *ProtectedPackagesService) UpdatePackageProtectionRules(pid any, packageProtectionRule int64, opt *UpdatePackageProtectionRulesOptions, options ...RequestOptionFunc) (*PackageProtectionRule, *Response, error) { + return do[*PackageProtectionRule](s.client, + withMethod(http.MethodPatch), + withPath("projects/%s/packages/protection/rules/%d", ProjectID{pid}, packageProtectionRule), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/protected_tags.go b/vendor/gitlab.com/gitlab-org/api/client-go/protected_tags.go index 2d776eed9..78d0be82f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/protected_tags.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/protected_tags.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -55,9 +54,10 @@ type ProtectedTag struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/ type TagAccessDescription struct { - ID int `json:"id"` - UserID int `json:"user_id"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + GroupID int64 `json:"group_id"` + DeployKeyID int64 `json:"deploy_key_id"` AccessLevel AccessLevelValue `json:"access_level"` AccessLevelDescription string `json:"access_level_description"` } @@ -67,31 +67,20 @@ type TagAccessDescription struct { // // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#list-protected-tags -type ListProtectedTagsOptions ListOptions +type ListProtectedTagsOptions struct { + ListOptions +} // ListProtectedTags returns a list of protected tags from a project. // // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#list-protected-tags func (s *ProtectedTagsService) ListProtectedTags(pid any, opt *ListProtectedTagsOptions, options ...RequestOptionFunc) ([]*ProtectedTag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_tags", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var pts []*ProtectedTag - resp, err := s.client.Do(req, &pts) - if err != nil { - return nil, resp, err - } - - return pts, resp, nil + return do[[]*ProtectedTag](s.client, + withPath("projects/%s/protected_tags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetProtectedTag returns a single protected tag or wildcard protected tag. @@ -99,24 +88,10 @@ func (s *ProtectedTagsService) ListProtectedTags(pid any, opt *ListProtectedTags // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#get-a-single-protected-tag-or-wildcard-protected-tag func (s *ProtectedTagsService) GetProtectedTag(pid any, tag string, options ...RequestOptionFunc) (*ProtectedTag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_tags/%s", PathEscape(project), PathEscape(tag)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - pt := new(ProtectedTag) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[*ProtectedTag](s.client, + withPath("projects/%s/protected_tags/%s", ProjectID{pid}, tag), + withRequestOpts(options...), + ) } // ProtectRepositoryTagsOptions represents the available ProtectRepositoryTags() @@ -135,8 +110,9 @@ type ProtectRepositoryTagsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#protect-repository-tags type TagsPermissionOptions struct { - UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + UserID *int64 `url:"user_id,omitempty" json:"user_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + DeployKeyID *int64 `url:"deploy_key_id,omitempty" json:"deploy_key_id,omitempty"` AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"` } @@ -146,24 +122,12 @@ type TagsPermissionOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#protect-repository-tags func (s *ProtectedTagsService) ProtectRepositoryTags(pid any, opt *ProtectRepositoryTagsOptions, options ...RequestOptionFunc) (*ProtectedTag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/protected_tags", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - pt := new(ProtectedTag) - resp, err := s.client.Do(req, pt) - if err != nil { - return nil, resp, err - } - - return pt, resp, nil + return do[*ProtectedTag](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/protected_tags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UnprotectRepositoryTags unprotects the given protected tag or wildcard @@ -172,16 +136,10 @@ func (s *ProtectedTagsService) ProtectRepositoryTags(pid any, opt *ProtectReposi // GitLab API docs: // https://docs.gitlab.com/api/protected_tags/#unprotect-repository-tags func (s *ProtectedTagsService) UnprotectRepositoryTags(pid any, tag string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/protected_tags/%s", PathEscape(project), PathEscape(tag)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/protected_tags/%s", ProjectID{pid}, tag), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/releaselinks.go b/vendor/gitlab.com/gitlab-org/api/client-go/releaselinks.go index 804e1ae51..dce9cd3be 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/releaselinks.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/releaselinks.go @@ -16,18 +16,15 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( ReleaseLinksServiceInterface interface { ListReleaseLinks(pid any, tagName string, opt *ListReleaseLinksOptions, options ...RequestOptionFunc) ([]*ReleaseLink, *Response, error) - GetReleaseLink(pid any, tagName string, link int, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) + GetReleaseLink(pid any, tagName string, link int64, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) CreateReleaseLink(pid any, tagName string, opt *CreateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) - UpdateReleaseLink(pid any, tagName string, link int, opt *UpdateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) - DeleteReleaseLink(pid any, tagName string, link int, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) + UpdateReleaseLink(pid any, tagName string, link int64, opt *UpdateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) + DeleteReleaseLink(pid any, tagName string, link int64, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) } // ReleaseLinksService handles communication with the release link methods @@ -45,7 +42,7 @@ var _ ReleaseLinksServiceInterface = (*ReleaseLinksService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/releases/links/ type ReleaseLink struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` URL string `json:"url"` DirectAssetURL string `json:"direct_asset_url"` @@ -56,57 +53,29 @@ type ReleaseLink struct { // ListReleaseLinksOptions represents ListReleaseLinks() options. // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#list-links-of-a-release -type ListReleaseLinksOptions ListOptions +type ListReleaseLinksOptions struct { + ListOptions +} // ListReleaseLinks gets assets as links from a Release. // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#list-links-of-a-release func (s *ReleaseLinksService) ListReleaseLinks(pid any, tagName string, opt *ListReleaseLinksOptions, options ...RequestOptionFunc) ([]*ReleaseLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s/assets/links", PathEscape(project), PathEscape(tagName)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var rls []*ReleaseLink - resp, err := s.client.Do(req, &rls) - if err != nil { - return nil, resp, err - } - - return rls, resp, nil + return do[[]*ReleaseLink](s.client, + withPath("projects/%s/releases/%s/assets/links", ProjectID{pid}, tagName), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetReleaseLink returns a link from release assets. // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#get-a-release-link -func (s *ReleaseLinksService) GetReleaseLink(pid any, tagName string, link int, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", - PathEscape(project), - PathEscape(tagName), - link) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - rl := new(ReleaseLink) - resp, err := s.client.Do(req, rl) - if err != nil { - return nil, resp, err - } - - return rl, resp, nil +func (s *ReleaseLinksService) GetReleaseLink(pid any, tagName string, link int64, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { + return do[*ReleaseLink](s.client, + withPath("projects/%s/releases/%s/assets/links/%d", ProjectID{pid}, tagName, link), + withRequestOpts(options...), + ) } // CreateReleaseLinkOptions represents CreateReleaseLink() options. @@ -124,24 +93,12 @@ type CreateReleaseLinkOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#create-a-release-link func (s *ReleaseLinksService) CreateReleaseLink(pid any, tagName string, opt *CreateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s/assets/links", PathEscape(project), PathEscape(tagName)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - rl := new(ReleaseLink) - resp, err := s.client.Do(req, rl) - if err != nil { - return nil, resp, err - } - - return rl, resp, nil + return do[*ReleaseLink](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/releases/%s/assets/links", ProjectID{pid}, tagName), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UpdateReleaseLinkOptions represents UpdateReleaseLink() options. @@ -160,54 +117,22 @@ type UpdateReleaseLinkOptions struct { // UpdateReleaseLink updates an asset link. // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#update-a-release-link -func (s *ReleaseLinksService) UpdateReleaseLink(pid any, tagName string, link int, opt *UpdateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", - PathEscape(project), - PathEscape(tagName), - link) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - rl := new(ReleaseLink) - resp, err := s.client.Do(req, rl) - if err != nil { - return nil, resp, err - } - - return rl, resp, nil +func (s *ReleaseLinksService) UpdateReleaseLink(pid any, tagName string, link int64, opt *UpdateReleaseLinkOptions, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { + return do[*ReleaseLink](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/releases/%s/assets/links/%d", ProjectID{pid}, tagName, link), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteReleaseLink deletes a link from release. // // GitLab API docs: https://docs.gitlab.com/api/releases/links/#delete-a-release-link -func (s *ReleaseLinksService) DeleteReleaseLink(pid any, tagName string, link int, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s/assets/links/%d", - PathEscape(project), - PathEscape(tagName), - link, +func (s *ReleaseLinksService) DeleteReleaseLink(pid any, tagName string, link int64, options ...RequestOptionFunc) (*ReleaseLink, *Response, error) { + return do[*ReleaseLink](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/releases/%s/assets/links/%d", ProjectID{pid}, tagName, link), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, nil, err - } - - rl := new(ReleaseLink) - resp, err := s.client.Do(req, rl) - if err != nil { - return nil, resp, err - } - - return rl, resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/releases.go b/vendor/gitlab.com/gitlab-org/api/client-go/releases.go index 8810690db..801e890f0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/releases.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/releases.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -48,44 +47,55 @@ var _ ReleasesServiceInterface = (*ReleasesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/releases/#list-releases type Release struct { - TagName string `json:"tag_name"` - Name string `json:"name"` - Description string `json:"description"` - DescriptionHTML string `json:"description_html"` - CreatedAt *time.Time `json:"created_at"` - ReleasedAt *time.Time `json:"released_at"` - Author struct { - ID int `json:"id"` - Name string `json:"name"` - Username string `json:"username"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"author"` + TagName string `json:"tag_name"` + Name string `json:"name"` + Description string `json:"description"` + DescriptionHTML string `json:"description_html"` + CreatedAt *time.Time `json:"created_at"` + ReleasedAt *time.Time `json:"released_at"` + Author BasicUser `json:"author"` Commit Commit `json:"commit"` Milestones []*ReleaseMilestone `json:"milestones"` UpcomingRelease bool `json:"upcoming_release"` CommitPath string `json:"commit_path"` TagPath string `json:"tag_path"` - Assets struct { - Count int `json:"count"` - Sources []struct { - Format string `json:"format"` - URL string `json:"url"` - } `json:"sources"` - Links []*ReleaseLink `json:"links"` - EvidenceFilePath string `json:"evidence_file_path"` - } `json:"assets"` - Evidences []*ReleaseEvidence `json:"evidences"` - Links struct { - ClosedIssueURL string `json:"closed_issues_url"` - ClosedMergeRequest string `json:"closed_merge_requests_url"` - EditURL string `json:"edit_url"` - MergedMergeRequest string `json:"merged_merge_requests_url"` - OpenedIssues string `json:"opened_issues_url"` - OpenedMergeRequest string `json:"opened_merge_requests_url"` - Self string `json:"self"` - } `json:"_links"` + Assets ReleaseAssets `json:"assets"` + Evidences []*ReleaseEvidence `json:"evidences"` + Links ReleaseLinks `json:"_links"` +} + +// ReleaseAssets represents a project release assets. +// +// GitLab API docs: +// https://docs.gitlab.com/api/releases/#list-releases +type ReleaseAssets struct { + Count int64 `json:"count"` + Sources []ReleaseAssetsSource `json:"sources"` + Links []*ReleaseLink `json:"links"` + EvidenceFilePath string `json:"evidence_file_path"` +} + +// ReleaseAssetsSource represents a project release assets source. +// +// GitLab API docs: +// https://docs.gitlab.com/api/releases/#list-releases +type ReleaseAssetsSource struct { + Format string `json:"format"` + URL string `json:"url"` +} + +// ReleaseLinks represents a project release links. +// +// GitLab API docs: +// https://docs.gitlab.com/api/releases/#list-releases +type ReleaseLinks struct { + ClosedIssueURL string `json:"closed_issues_url"` + ClosedMergeRequest string `json:"closed_merge_requests_url"` + EditURL string `json:"edit_url"` + MergedMergeRequest string `json:"merged_merge_requests_url"` + OpenedIssues string `json:"opened_issues_url"` + OpenedMergeRequest string `json:"opened_merge_requests_url"` + Self string `json:"self"` } // ReleaseMilestone represents a project release milestone. @@ -93,9 +103,9 @@ type Release struct { // GitLab API docs: // https://docs.gitlab.com/api/releases/#list-releases type ReleaseMilestone struct { - ID int `json:"id"` - IID int `json:"iid"` - ProjectID int `json:"project_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + ProjectID int64 `json:"project_id"` Title string `json:"title"` Description string `json:"description"` State string `json:"state"` @@ -113,8 +123,8 @@ type ReleaseMilestone struct { // GitLab API docs: // https://docs.gitlab.com/api/releases/#list-releases type ReleaseMilestoneIssueStats struct { - Total int `json:"total"` - Closed int `json:"closed"` + Total int64 `json:"total"` + Closed int64 `json:"closed"` } // ReleaseEvidence represents a project release's evidence. @@ -143,24 +153,11 @@ type ListReleasesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/releases/#list-releases func (s *ReleasesService) ListReleases(pid any, opt *ListReleasesOptions, options ...RequestOptionFunc) ([]*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Release - resp, err := s.client.Do(req, &rs) - if err != nil { - return nil, resp, err - } - - return rs, resp, nil + return do[[]*Release](s.client, + withPath("projects/%s/releases", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetRelease returns a single release, identified by a tag name. @@ -168,24 +165,10 @@ func (s *ReleasesService) ListReleases(pid any, opt *ListReleasesOptions, option // GitLab API docs: // https://docs.gitlab.com/api/releases/#get-a-release-by-a-tag-name func (s *ReleasesService) GetRelease(pid any, tagName string, options ...RequestOptionFunc) (*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s", PathEscape(project), PathEscape(tagName)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(Release) - resp, err := s.client.Do(req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return do[*Release](s.client, + withPath("projects/%s/releases/%s", ProjectID{pid}, tagName), + withRequestOpts(options...), + ) } // GetLatestRelease returns the latest release for the project. @@ -193,24 +176,10 @@ func (s *ReleasesService) GetRelease(pid any, tagName string, options ...Request // GitLab API docs: // https://docs.gitlab.com/api/releases/#get-the-latest-release func (s *ReleasesService) GetLatestRelease(pid any, options ...RequestOptionFunc) (*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/permalink/latest", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(Release) - resp, err := s.client.Do(req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, err + return do[*Release](s.client, + withPath("projects/%s/releases/permalink/latest", ProjectID{pid}), + withRequestOpts(options...), + ) } // CreateReleaseOptions represents CreateRelease() options. @@ -254,24 +223,12 @@ type ReleaseAssetLinkOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/releases/#create-a-release func (s *ReleasesService) CreateRelease(pid any, opts *CreateReleaseOptions, options ...RequestOptionFunc) (*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - r := new(Release) - resp, err := s.client.Do(req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return do[*Release](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/releases", ProjectID{pid}), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // UpdateReleaseOptions represents UpdateRelease() options. @@ -290,24 +247,12 @@ type UpdateReleaseOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/releases/#update-a-release func (s *ReleasesService) UpdateRelease(pid any, tagName string, opts *UpdateReleaseOptions, options ...RequestOptionFunc) (*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s", PathEscape(project), PathEscape(tagName)) - - req, err := s.client.NewRequest(http.MethodPut, u, opts, options) - if err != nil { - return nil, nil, err - } - - r := new(Release) - resp, err := s.client.Do(req, &r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return do[*Release](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/releases/%s", ProjectID{pid}, tagName), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // DeleteRelease deletes a release. @@ -315,22 +260,9 @@ func (s *ReleasesService) UpdateRelease(pid any, tagName string, opts *UpdateRel // GitLab API docs: // https://docs.gitlab.com/api/releases/#delete-a-release func (s *ReleasesService) DeleteRelease(pid any, tagName string, options ...RequestOptionFunc) (*Release, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/releases/%s", PathEscape(project), PathEscape(tagName)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(Release) - resp, err := s.client.Do(req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return do[*Release](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/releases/%s", ProjectID{pid}, tagName), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/repositories.go b/vendor/gitlab.com/gitlab-org/api/client-go/repositories.go index 05e16e6f3..dafbe57d9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/repositories.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/repositories.go @@ -21,20 +21,62 @@ import ( "fmt" "io" "net/http" - "net/url" ) type ( RepositoriesServiceInterface interface { + // ListTree gets a list of repository files and directories in a project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#list-repository-tree ListTree(pid any, opt *ListTreeOptions, options ...RequestOptionFunc) ([]*TreeNode, *Response, error) + // Blob gets information about blob in repository like size and content. Note + // that blob content is Base64 encoded. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#get-a-blob-from-repository Blob(pid any, sha string, options ...RequestOptionFunc) ([]byte, *Response, error) + // RawBlobContent gets the raw file contents for a blob by blob SHA. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#raw-blob-content RawBlobContent(pid any, sha string, options ...RequestOptionFunc) ([]byte, *Response, error) + // Archive gets an archive of the repository. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#get-file-archive Archive(pid any, opt *ArchiveOptions, options ...RequestOptionFunc) ([]byte, *Response, error) + // StreamArchive streams an archive of the repository to the provided + // io.Writer. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#get-file-archive StreamArchive(pid any, w io.Writer, opt *ArchiveOptions, options ...RequestOptionFunc) (*Response, error) + // Compare compares branches, tags or commits. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#compare-branches-tags-or-commits Compare(pid any, opt *CompareOptions, options ...RequestOptionFunc) (*Compare, *Response, error) + // Contributors gets the repository contributors list. + // + // GitLab API docs: https://docs.gitlab.com/api/repositories/#contributors Contributors(pid any, opt *ListContributorsOptions, options ...RequestOptionFunc) ([]*Contributor, *Response, error) + // MergeBase gets the common ancestor for 2 refs (commit SHAs, branch + // names or tags). + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#merge-base MergeBase(pid any, opt *MergeBaseOptions, options ...RequestOptionFunc) (*Commit, *Response, error) + // AddChangelog generates changelog data based on commits in a repository. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#add-changelog-data-to-a-changelog-file AddChangelog(pid any, opt *AddChangelogOptions, options ...RequestOptionFunc) (*Response, error) + // GenerateChangelogData generates changelog data based on commits in a + // repository, without committing them to a changelog file. + // + // GitLab API docs: + // https://docs.gitlab.com/api/repositories/#generate-changelog-data GenerateChangelogData(pid any, opt GenerateChangelogDataOptions, options ...RequestOptionFunc) (*ChangelogData, *Response, error) } @@ -75,80 +117,34 @@ type ListTreeOptions struct { Recursive *bool `url:"recursive,omitempty" json:"recursive,omitempty"` } -// ListTree gets a list of repository files and directories in a project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#list-repository-tree func (s *RepositoriesService) ListTree(pid any, opt *ListTreeOptions, options ...RequestOptionFunc) ([]*TreeNode, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/tree", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var t []*TreeNode - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[[]*TreeNode](s.client, + withPath("projects/%s/repository/tree", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// Blob gets information about blob in repository like size and content. Note -// that blob content is Base64 encoded. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#get-a-blob-from-repository func (s *RepositoriesService) Blob(pid any, sha string, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/blobs/%s", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/repository/blobs/%s", ProjectID{pid}, sha), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } -// RawBlobContent gets the raw file contents for a blob by blob SHA. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#raw-blob-content func (s *RepositoriesService) RawBlobContent(pid any, sha string, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/blobs/%s/raw", PathEscape(project), url.PathEscape(sha)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/repository/blobs/%s/raw", ProjectID{pid}, sha), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } // ArchiveOptions represents the available Archive() options. @@ -161,41 +157,23 @@ type ArchiveOptions struct { SHA *string `url:"sha,omitempty" json:"sha,omitempty"` } -// Archive gets an archive of the repository. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#get-file-archive func (s *RepositoriesService) Archive(pid any, opt *ArchiveOptions, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/archive", PathEscape(project)) - - // Set an optional format for the archive. + suffix := "" if opt != nil && opt.Format != nil { - u = fmt.Sprintf("%s.%s", u, *opt.Format) - } - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err + suffix = "." + *opt.Format } - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/repository/archive%s", ProjectID{pid}, NoEscape{suffix}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } -// StreamArchive streams an archive of the repository to the provided -// io.Writer. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#get-file-archive func (s *RepositoriesService) StreamArchive(pid any, w io.Writer, opt *ArchiveOptions, options ...RequestOptionFunc) (*Response, error) { project, err := parseID(pid) if err != nil { @@ -244,29 +222,12 @@ type CompareOptions struct { Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"` } -// Compare compares branches, tags or commits. -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#compare-branches-tags-or-commits func (s *RepositoriesService) Compare(pid any, opt *CompareOptions, options ...RequestOptionFunc) (*Compare, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/compare", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Compare) - resp, err := s.client.Do(req, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*Compare](s.client, + withPath("projects/%s/repository/compare", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // Contributor represents a GitLab contributor. @@ -275,9 +236,9 @@ func (s *RepositoriesService) Compare(pid any, opt *CompareOptions, options ...R type Contributor struct { Name string `json:"name"` Email string `json:"email"` - Commits int `json:"commits"` - Additions int `json:"additions"` - Deletions int `json:"deletions"` + Commits int64 `json:"commits"` + Additions int64 `json:"additions"` + Deletions int64 `json:"deletions"` } func (c Contributor) String() string { @@ -293,28 +254,12 @@ type ListContributorsOptions struct { Sort *string `url:"sort,omitempty" json:"sort,omitempty"` } -// Contributors gets the repository contributors list. -// -// GitLab API docs: https://docs.gitlab.com/api/repositories/#contributors func (s *RepositoriesService) Contributors(pid any, opt *ListContributorsOptions, options ...RequestOptionFunc) ([]*Contributor, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/contributors", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var c []*Contributor - resp, err := s.client.Do(req, &c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[[]*Contributor](s.client, + withPath("projects/%s/repository/contributors", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // MergeBaseOptions represents the available MergeBase() options. @@ -325,30 +270,12 @@ type MergeBaseOptions struct { Ref *[]string `url:"refs[],omitempty" json:"refs,omitempty"` } -// MergeBase gets the common ancestor for 2 refs (commit SHAs, branch -// names or tags). -// -// GitLab API docs: -// https://docs.gitlab.com/api/repositories/#merge-base func (s *RepositoriesService) MergeBase(pid any, opt *MergeBaseOptions, options ...RequestOptionFunc) (*Commit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/merge_base", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - c := new(Commit) - resp, err := s.client.Do(req, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*Commit](s.client, + withPath("projects/%s/repository/merge_base", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // AddChangelogOptions represents the available AddChangelog() options. @@ -367,23 +294,14 @@ type AddChangelogOptions struct { Trailer *string `url:"trailer,omitempty" json:"trailer,omitempty"` } -// AddChangelog generates changelog data based on commits in a repository. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/repositories/#add-changelog-data-to-a-changelog-file func (s *RepositoriesService) AddChangelog(pid any, opt *AddChangelogOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/repository/changelog", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/changelog", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // ChangelogData represents the generated changelog data. @@ -412,28 +330,10 @@ type GenerateChangelogDataOptions struct { Trailer *string `url:"trailer,omitempty" json:"trailer,omitempty"` } -// GenerateChangelogData generates changelog data based on commits in a -// repository, without committing them to a changelog file. -// -// Gitlab API docs: -// https://docs.gitlab.com/api/repositories/#generate-changelog-data func (s *RepositoriesService) GenerateChangelogData(pid any, opt GenerateChangelogDataOptions, options ...RequestOptionFunc) (*ChangelogData, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/changelog", project) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - cd := new(ChangelogData) - resp, err := s.client.Do(req, cd) - if err != nil { - return nil, resp, err - } - - return cd, resp, nil + return do[*ChangelogData](s.client, + withPath("projects/%s/repository/changelog", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/repository_files.go b/vendor/gitlab.com/gitlab-org/api/client-go/repository_files.go index 32d1a4988..69a022bd5 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/repository_files.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/repository_files.go @@ -18,7 +18,6 @@ package gitlab import ( "bytes" - "fmt" "net/http" "strconv" "time" @@ -53,7 +52,7 @@ var _ RepositoryFilesServiceInterface = (*RepositoryFilesService)(nil) type File struct { FileName string `json:"file_name"` FilePath string `json:"file_path"` - Size int `json:"size"` + Size int64 `json:"size"` Encoding string `json:"encoding"` Content string `json:"content"` ExecuteFilemode bool `json:"execute_filemode"` @@ -82,28 +81,11 @@ type GetFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-file-from-repository func (s *RepositoryFilesService) GetFile(pid any, fileName string, opt *GetFileOptions, options ...RequestOptionFunc) (*File, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s", - PathEscape(project), - PathEscape(fileName), + return do[*File](s.client, + withPath("projects/%s/repository/files/%s", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - f := new(File) - resp, err := s.client.Do(req, f) - if err != nil { - return nil, resp, err - } - - return f, resp, nil } // GetFileMetaDataOptions represents the available GetFileMetaData() options. @@ -120,22 +102,12 @@ type GetFileMetaDataOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-file-from-repository func (s *RepositoryFilesService) GetFileMetaData(pid any, fileName string, opt *GetFileMetaDataOptions, options ...RequestOptionFunc) (*File, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s", - PathEscape(project), - PathEscape(fileName), + _, resp, err := do[none](s.client, + withMethod(http.MethodHead), + withPath("projects/%s/repository/files/%s", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodHead, u, opt, options) - if err != nil { - return nil, nil, err - } - - resp, err := s.client.Do(req, nil) if err != nil { return nil, resp, err } @@ -164,7 +136,7 @@ func getMetaDataFileFromHeaders(resp *Response) (*File, error) { } if sizeString := resp.Header.Get("X-Gitlab-Size"); sizeString != "" { - size, err := strconv.Atoi(sizeString) + size, err := strconv.ParseInt(sizeString, 10, 64) if err != nil { return nil, err } @@ -179,32 +151,42 @@ func getMetaDataFileFromHeaders(resp *Response) (*File, error) { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-file-blame-from-repository type FileBlameRange struct { - Commit struct { - ID string `json:"id"` - ParentIDs []string `json:"parent_ids"` - Message string `json:"message"` - AuthoredDate *time.Time `json:"authored_date"` - AuthorName string `json:"author_name"` - AuthorEmail string `json:"author_email"` - CommittedDate *time.Time `json:"committed_date"` - CommitterName string `json:"committer_name"` - CommitterEmail string `json:"committer_email"` - } `json:"commit"` - Lines []string `json:"lines"` + Commit FileBlameRangeCommit `json:"commit"` + Lines []string `json:"lines"` } func (b FileBlameRange) String() string { return Stringify(b) } +// FileBlameRangeCommit represents one item of blame information's commit. +// +// GitLab API docs: +// https://docs.gitlab.com/api/repository_files/#get-file-blame-from-repository +type FileBlameRangeCommit struct { + ID string `json:"id"` + ParentIDs []string `json:"parent_ids"` + Message string `json:"message"` + AuthoredDate *time.Time `json:"authored_date"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + CommittedDate *time.Time `json:"committed_date"` + CommitterName string `json:"committer_name"` + CommitterEmail string `json:"committer_email"` +} + +func (c FileBlameRangeCommit) String() string { + return Stringify(c) +} + // GetFileBlameOptions represents the available GetFileBlame() options. // // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-file-blame-from-repository type GetFileBlameOptions struct { Ref *string `url:"ref,omitempty" json:"ref,omitempty"` - RangeStart *int `url:"range[start],omitempty" json:"range[start],omitempty"` - RangeEnd *int `url:"range[end],omitempty" json:"range[end],omitempty"` + RangeStart *int64 `url:"range[start],omitempty" json:"range[start],omitempty"` + RangeEnd *int64 `url:"range[end],omitempty" json:"range[end],omitempty"` } // GetFileBlame allows you to receive blame information. Each blame range @@ -213,28 +195,11 @@ type GetFileBlameOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-file-blame-from-repository func (s *RepositoryFilesService) GetFileBlame(pid any, file string, opt *GetFileBlameOptions, options ...RequestOptionFunc) ([]*FileBlameRange, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s/blame", - PathEscape(project), - PathEscape(file), + return do[[]*FileBlameRange](s.client, + withPath("projects/%s/repository/files/%s/blame", ProjectID{pid}, file), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var br []*FileBlameRange - resp, err := s.client.Do(req, &br) - if err != nil { - return nil, resp, err - } - - return br, resp, nil } // GetRawFileOptions represents the available GetRawFile() options. @@ -251,28 +216,15 @@ type GetRawFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-raw-file-from-repository func (s *RepositoryFilesService) GetRawFile(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) ([]byte, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s/raw", - PathEscape(project), - PathEscape(fileName), + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/repository/files/%s/raw", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var f bytes.Buffer - resp, err := s.client.Do(req, &f) if err != nil { return nil, resp, err } - - return f.Bytes(), resp, err + return buf.Bytes(), resp, nil } // GetRawFileMetaData gets the metadata of a raw file from a repository. @@ -280,22 +232,12 @@ func (s *RepositoryFilesService) GetRawFile(pid any, fileName string, opt *GetRa // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-raw-file-from-repository func (s *RepositoryFilesService) GetRawFileMetaData(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (*File, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s/raw", - PathEscape(project), - PathEscape(fileName), + _, resp, err := do[none](s.client, + withMethod(http.MethodHead), + withPath("projects/%s/repository/files/%s/raw", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodHead, u, opt, options) - if err != nil { - return nil, nil, err - } - - resp, err := s.client.Do(req, nil) if err != nil { return nil, resp, err } @@ -340,28 +282,12 @@ type CreateFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#create-new-file-in-repository func (s *RepositoryFilesService) CreateFile(pid any, fileName string, opt *CreateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s", - PathEscape(project), - PathEscape(fileName), + return do[*FileInfo](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/files/%s", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - f := new(FileInfo) - resp, err := s.client.Do(req, f) - if err != nil { - return nil, resp, err - } - - return f, resp, nil } // UpdateFileOptions represents the available UpdateFile() options. @@ -385,28 +311,12 @@ type UpdateFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#update-existing-file-in-repository func (s *RepositoryFilesService) UpdateFile(pid any, fileName string, opt *UpdateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s", - PathEscape(project), - PathEscape(fileName), + return do[*FileInfo](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/repository/files/%s", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - f := new(FileInfo) - resp, err := s.client.Do(req, f) - if err != nil { - return nil, resp, err - } - - return f, resp, nil } // DeleteFileOptions represents the available DeleteFile() options. @@ -427,20 +337,11 @@ type DeleteFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#delete-existing-file-in-repository func (s *RepositoryFilesService) DeleteFile(pid any, fileName string, opt *DeleteFileOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/files/%s", - PathEscape(project), - PathEscape(fileName), + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/repository/files/%s", ProjectID{pid}, fileName), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodDelete, u, opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/repository_submodules.go b/vendor/gitlab.com/gitlab-org/api/client-go/repository_submodules.go index 84a0491d4..7f08fb6a0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/repository_submodules.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/repository_submodules.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -76,26 +75,10 @@ type UpdateSubmoduleOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/repository_submodules/#update-existing-submodule-reference-in-repository func (s *RepositorySubmodulesService) UpdateSubmodule(pid any, submodule string, opt *UpdateSubmoduleOptions, options ...RequestOptionFunc) (*SubmoduleCommit, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf( - "projects/%s/repository/submodules/%s", - PathEscape(project), - PathEscape(submodule), + return do[*SubmoduleCommit](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/repository/submodules/%s", ProjectID{pid}, submodule), + withAPIOpts(opt), + withRequestOpts(options...), ) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - sc := new(SubmoduleCommit) - resp, err := s.client.Do(req, sc) - if err != nil { - return nil, resp, err - } - - return sc, resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/request_handler.go b/vendor/gitlab.com/gitlab-org/api/client-go/request_handler.go new file mode 100644 index 000000000..7ee3b334f --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/request_handler.go @@ -0,0 +1,276 @@ +package gitlab + +import ( + "fmt" + "io" + "net/http" + "reflect" + "strings" + + "github.com/hashicorp/go-retryablehttp" +) + +type Pather interface { + forPath() (string, error) +} + +type ProjectID struct { + Value any +} + +func (i ProjectID) forPath() (string, error) { + id, err := parseID(i.Value) + if err != nil { + return "", err + } + + return PathEscape(id), nil +} + +type GroupID struct { + Value any +} + +func (i GroupID) forPath() (string, error) { + id, err := parseID(i.Value) + if err != nil { + return "", err + } + + return PathEscape(id), nil +} + +type RunnerID struct { + Value any +} + +func (i RunnerID) forPath() (string, error) { + id, err := parseID(i.Value) + if err != nil { + return "", err + } + + return PathEscape(id), nil +} + +// UserID represents a user identifier for API paths. It accepts either a +// numeric user ID or a username string. If a username is provided with a +// leading "@" character (e.g., "@johndoe"), the "@" will be trimmed. +type UserID struct { + Value any +} + +func (i UserID) forPath() (string, error) { + id, err := parseID(i.Value) + if err != nil { + return "", err + } + + return PathEscape(strings.TrimPrefix(id, "@")), nil +} + +type LabelID struct { + Value any +} + +func (i LabelID) forPath() (string, error) { + id, err := parseID(i.Value) + if err != nil { + return "", err + } + + return PathEscape(id), nil +} + +type NoEscape struct { + Value string +} + +func (n NoEscape) forPath() (string, error) { + return n.Value, nil +} + +type doConfig struct { + method string + path string + apiOpts any + requestOpts []RequestOptionFunc + upload *uploadConfig +} + +type uploadConfig struct { + content io.Reader + filename string + uploadType UploadType +} + +type doOption func(c *doConfig) error + +func withMethod(method string) doOption { + return func(c *doConfig) error { + c.method = method + return nil + } +} + +func withPath(path string, args ...any) doOption { + return func(c *doConfig) error { + as := make([]any, len(args)) + for i, a := range args { + switch v := a.(type) { + case Pather: + path, err := v.forPath() + if err != nil { + return err + } + as[i] = path + case string: + as[i] = PathEscape(v) + default: + as[i] = v + } + } + c.path = fmt.Sprintf(path, as...) + + return nil + } +} + +func withAPIOpts(o any) doOption { + return func(c *doConfig) error { + c.apiOpts = o + return nil + } +} + +func withRequestOpts(o ...RequestOptionFunc) doOption { + return func(c *doConfig) error { + c.requestOpts = o + return nil + } +} + +func withUpload(content io.Reader, filename string, uploadType UploadType) doOption { + return func(c *doConfig) error { + c.upload = &uploadConfig{ + content: content, + filename: filename, + uploadType: uploadType, + } + return nil + } +} + +// none is a sentinel type to signal that a request performed with do does not return a value. +type none struct{} + +// do constructs an API requests, performs it and processes the response. +// +// Use the opts to configure the request. +// If the response body shouldn't be handled, use the none sentinel type +// and ignore the first return argument. +// +// Example: +// +// // Get Request to return single *Agent: +// return do[*Agent](s.client, +// +// withPath("projects/%s/cluster_agents/%d", project, id), +// withRequestOpts(options...), +// +// ) +// +// // Get Request to return multiple []*Agents +// return do[[]*Agent](s.client, +// +// withPath("projects/%s/cluster_agents", project), +// withRequestOpts(options...), +// +// ) +// +// // Post Request to create Agent and return *Agents +// return do[*Agent](s.client, +// +// withMethod(http.MethodPost), +// withPath("projects/%s/cluster_agents", project), +// withAPIOpts(opt), +// withRequestOpts(options...), +// +// ) +// +// // Delete Request that returns nothing: +// _, resp, err := do[none](s.client, +// +// withMethod(http.MethodDelete), +// withPath("projects/%s/cluster_agents/%d", project, id), +// withRequestOpts(options...), +// +// ) +// +// // Upload file Request: +// return do[*WikiAttachment](s.client, +// +// withMethod(http.MethodPost), +// withPath("projects/%s/wikis/attachments", project), +// withUpload(content, filename, UploadFile), +// withAPIOpts(opt), +// withRequestOpts(options...), +// +// ) +func do[T any](client *Client, opts ...doOption) (T, *Response, error) { + // default config + config := &doConfig{ + method: http.MethodGet, + apiOpts: nil, + } + + // apply options to config + for _, f := range opts { + err := f(config) + if err != nil { + var z T + return z, nil, err + } + } + + var ( + req *retryablehttp.Request + err error + ) + switch { + case config.upload != nil: + req, err = client.UploadRequest( + config.method, + config.path, + config.upload.content, + config.upload.filename, + config.upload.uploadType, + config.apiOpts, + config.requestOpts, + ) + default: + req, err = client.NewRequest(config.method, config.path, config.apiOpts, config.requestOpts) + } + + if err != nil { + var z T + return z, nil, err + } + + var ( + as T + resp *Response + ) + if reflect.TypeOf(as) == reflect.TypeFor[none]() { + resp, err = client.Do(req, nil) + } else { + resp, err = client.Do(req, &as) + } + + if err != nil { + var z T + return z, resp, err + } + + return as, resp, nil +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/request_options.go b/vendor/gitlab.com/gitlab-org/api/client-go/request_options.go index 166c1d92c..973477e9b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/request_options.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/request_options.go @@ -18,6 +18,8 @@ package gitlab import ( "context" + "encoding/json" + "fmt" "net/url" "strconv" @@ -90,24 +92,92 @@ func WithKeysetPaginationParameters(nextLink string) RequestOptionFunc { // WithOffsetPaginationParameters takes a page number and modifies the request // to use that page for offset-based pagination, overriding any existing page value. -func WithOffsetPaginationParameters(page int) RequestOptionFunc { +func WithOffsetPaginationParameters(page int64) RequestOptionFunc { return func(req *retryablehttp.Request) error { q := req.URL.Query() q.Del("page") - q.Add("page", strconv.Itoa(page)) + q.Add("page", strconv.FormatInt(page, 10)) req.URL.RawQuery = q.Encode() return nil } } -// WithSudo takes either a username or user ID and sets the SUDO request header. +// withGraphQLPaginationParamters takes a PageInfo from a GraphQL response and +// modifies the request to use that cursor for GraphQL pagination, overriding +// any existing "after" variable. +// +// GraphQL API docs: +// https://docs.gitlab.com/development/graphql_guide/pagination/ +func withGraphQLPaginationParamters(pi PageInfo) RequestOptionFunc { + if !pi.HasNextPage { + return nil + } + + return func(req *retryablehttp.Request) error { + var q GraphQLQuery + + data, err := req.BodyBytes() + if err != nil { + return fmt.Errorf("reading request body failed: %w", err) + } + + if err := json.Unmarshal(data, &q); err != nil { + return fmt.Errorf("decoding request body failed: %w", err) + } + + if q.Variables == nil { + q.Variables = make(map[string]any) + } + + q.Variables["after"] = pi.EndCursor + + data, err = json.Marshal(q) + if err != nil { + return fmt.Errorf("encoding request body failed: %w", err) + } + + return req.SetBody(data) + } +} + +// WithNext returns a RequestOptionFunc that configures the next page of a paginated +// request based on pagination metadata from a previous response. It automatically +// detects and handles all three pagination styles used by GitLab's APIs: +// +// - GraphQL cursor pagination: Uses PageInfo.EndCursor with the "after" variable +// - REST keyset pagination: Extracts parameters from the "next" link header +// - REST offset pagination: Uses the NextPage number with "page" parameter +// +// If multiple pagination styles are present in the response, keyset/cursor pagination +// is preferred over offset pagination for better performance and consistency. +// +// The boolean return value indicates whether more pages are available, similar to +// the comma-ok idiom used for map accesses. When false, the returned +// RequestOptionFunc is nil. +func WithNext(resp *Response) (RequestOptionFunc, bool) { + switch { + case resp.PageInfo != nil: + return withGraphQLPaginationParamters(*resp.PageInfo), resp.PageInfo.HasNextPage + + case resp.NextLink != "": + return WithKeysetPaginationParameters(resp.NextLink), true + + case resp.NextPage != 0: + return WithOffsetPaginationParameters(resp.NextPage), true + + default: + return nil, false + } +} + +// WithSudo takes either a username or user ID and sets the Sudo request header. func WithSudo(uid any) RequestOptionFunc { return func(req *retryablehttp.Request) error { user, err := parseID(uid) if err != nil { return err } - req.Header.Set("SUDO", user) + req.Header.Set("Sudo", user) return nil } } @@ -117,11 +187,11 @@ func WithToken(authType AuthType, token string) RequestOptionFunc { return func(req *retryablehttp.Request) error { switch authType { case JobToken: - req.Header.Set("JOB-TOKEN", token) + req.Header.Set("Job-Token", token) case OAuthToken: req.Header.Set("Authorization", "Bearer "+token) case PrivateToken: - req.Header.Set("PRIVATE-TOKEN", token) + req.Header.Set("Private-Token", token) } return nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_group.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_group.go index 6b851143f..b6c3c979f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_group.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_group.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -47,7 +46,7 @@ var _ ResourceGroupServiceInterface = (*ResourceGroupService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/resource_groups/ type ResourceGroup struct { - ID int `json:"id"` + ID int64 `json:"id"` Key string `json:"key"` ProcessMode string `json:"process_mode"` CreatedAt *time.Time `json:"created_at"` @@ -68,24 +67,10 @@ func (rg ResourceGroup) String() string { // GitLab API docs: // https://docs.gitlab.com/api/resource_groups/#get-all-resource-groups-for-a-project func (s *ResourceGroupService) GetAllResourceGroupsForAProject(pid any, options ...RequestOptionFunc) ([]*ResourceGroup, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/resource_groups", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var rgs []*ResourceGroup - resp, err := s.client.Do(req, &rgs) - if err != nil { - return nil, resp, err - } - - return rgs, resp, nil + return do[[]*ResourceGroup](s.client, + withPath("projects/%s/resource_groups", ProjectID{pid}), + withRequestOpts(options...), + ) } // GetASpecificResourceGroup allows you to get a specific @@ -94,24 +79,10 @@ func (s *ResourceGroupService) GetAllResourceGroupsForAProject(pid any, options // GitLab API docs: // https://docs.gitlab.com/api/resource_groups/#get-a-specific-resource-group func (s *ResourceGroupService) GetASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) (*ResourceGroup, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/resource_groups/%s", PathEscape(project), key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - rg := new(ResourceGroup) - resp, err := s.client.Do(req, rg) - if err != nil { - return nil, resp, err - } - - return rg, resp, nil + return do[*ResourceGroup](s.client, + withPath("projects/%s/resource_groups/%s", ProjectID{pid}, key), + withRequestOpts(options...), + ) } // ListUpcomingJobsForASpecificResourceGroup allows you to get all @@ -120,24 +91,10 @@ func (s *ResourceGroupService) GetASpecificResourceGroup(pid any, key string, op // GitLab API docs: // https://docs.gitlab.com/api/resource_groups/#list-upcoming-jobs-for-a-specific-resource-group func (s *ResourceGroupService) ListUpcomingJobsForASpecificResourceGroup(pid any, key string, options ...RequestOptionFunc) ([]*Job, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/resource_groups/%s/upcoming_jobs", PathEscape(project), key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var js []*Job - resp, err := s.client.Do(req, &js) - if err != nil { - return nil, resp, err - } - - return js, resp, nil + return do[[]*Job](s.client, + withPath("projects/%s/resource_groups/%s/upcoming_jobs", ProjectID{pid}, key), + withRequestOpts(options...), + ) } // EditAnExistingResourceGroupOptions represents the available @@ -155,22 +112,10 @@ type EditAnExistingResourceGroupOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/resource_groups/#edit-an-existing-resource-group func (s *ResourceGroupService) EditAnExistingResourceGroup(pid any, key string, opts *EditAnExistingResourceGroupOptions, options ...RequestOptionFunc) (*ResourceGroup, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/resource_groups/%s", PathEscape(project), key) - - req, err := s.client.NewRequest(http.MethodPut, u, opts, options) - if err != nil { - return nil, nil, err - } - - rg := new(ResourceGroup) - resp, err := s.client.Do(req, rg) - if err != nil { - return nil, resp, err - } - - return rg, resp, nil + return do[*ResourceGroup](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/resource_groups/%s", ProjectID{pid}, key), + withAPIOpts(opts), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_iteration_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_iteration_events.go index bb52fc0ee..85499efc6 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_iteration_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_iteration_events.go @@ -17,15 +17,13 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( ResourceIterationEventsServiceInterface interface { - ListIssueIterationEvents(pid any, issue int, opt *ListIterationEventsOptions, options ...RequestOptionFunc) ([]*IterationEvent, *Response, error) - GetIssueIterationEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*IterationEvent, *Response, error) + ListIssueIterationEvents(pid any, issue int64, opt *ListIterationEventsOptions, options ...RequestOptionFunc) ([]*IterationEvent, *Response, error) + GetIssueIterationEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*IterationEvent, *Response, error) } // ResourceIterationEventsService handles communication with the event related @@ -43,11 +41,11 @@ var _ ResourceIterationEventsServiceInterface = (*ResourceIterationEventsService // // GitLab API docs: https://docs.gitlab.com/api/resource_iteration_events/ type IterationEvent struct { - ID int `json:"id"` + ID int64 `json:"id"` User *BasicUser `json:"user"` CreatedAt *time.Time `json:"created_at"` ResourceType string `json:"resource_type"` - ResourceID int `json:"resource_id"` + ResourceID int64 `json:"resource_id"` Iteration *Iteration `json:"iteration"` Action string `json:"action"` } @@ -56,13 +54,13 @@ type IterationEvent struct { // // GitLab API docs: https://docs.gitlab.com/api/resource_iteration_events/ type Iteration struct { - ID int `json:"id"` - IID int `json:"iid"` - Sequence int `json:"sequence"` - GroupID int `json:"group_id"` + ID int64 `json:"id"` + IID int64 `json:"iid"` + Sequence int64 `json:"sequence"` + GroupID int64 `json:"group_id"` Title string `json:"title"` Description string `json:"description"` - State int `json:"state"` + State int64 `json:"state"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` DueDate *ISOTime `json:"due_date"` @@ -84,48 +82,21 @@ type ListIterationEventsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/resource_iteration_events/#list-project-issue-iteration-events -func (s *ResourceIterationEventsService) ListIssueIterationEvents(pid any, issue int, opt *ListIterationEventsOptions, options ...RequestOptionFunc) ([]*IterationEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_iteration_events", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ies []*IterationEvent - resp, err := s.client.Do(req, &ies) - if err != nil { - return nil, resp, err - } - - return ies, resp, nil +func (s *ResourceIterationEventsService) ListIssueIterationEvents(pid any, issue int64, opt *ListIterationEventsOptions, options ...RequestOptionFunc) ([]*IterationEvent, *Response, error) { + return do[[]*IterationEvent](s.client, + withPath("projects/%s/issues/%d/resource_iteration_events", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueIterationEvent gets a single issue iteration event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_iteration_events/#get-single-issue-iteration-event -func (s *ResourceIterationEventsService) GetIssueIterationEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*IterationEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_iteration_events/%d", PathEscape(project), issue, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ie := new(IterationEvent) - resp, err := s.client.Do(req, ie) - if err != nil { - return nil, resp, err - } - - return ie, resp, nil +func (s *ResourceIterationEventsService) GetIssueIterationEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*IterationEvent, *Response, error) { + return do[*IterationEvent](s.client, + withPath("projects/%s/issues/%d/resource_iteration_events/%d", ProjectID{pid}, issue, event), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_label_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_label_events.go index f37296748..4a36332dd 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_label_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_label_events.go @@ -17,22 +17,20 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( ResourceLabelEventsServiceInterface interface { - ListIssueLabelEvents(pid any, issue int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) - GetIssueLabelEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) - ListMergeRequestsLabelEvents(pid any, request int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) - GetMergeRequestLabelEvent(pid any, request int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) + ListIssueLabelEvents(pid any, issue int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) + GetIssueLabelEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) + ListMergeRequestsLabelEvents(pid any, request int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) + GetMergeRequestLabelEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) // Will be removed in v5, use Work Items API instead - ListGroupEpicLabelEvents(gid any, epic int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) + ListGroupEpicLabelEvents(gid any, epic int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) // Will be removed in v5, use Work Items API instead - GetGroupEpicLabelEvent(gid any, epic int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) + GetGroupEpicLabelEvent(gid any, epic int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) } // ResourceLabelEventsService handles communication with the event related @@ -51,26 +49,25 @@ var _ ResourceLabelEventsServiceInterface = (*ResourceLabelEventsService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#get-single-issue-label-event type LabelEvent struct { - ID int `json:"id"` - Action string `json:"action"` - CreatedAt *time.Time `json:"created_at"` - ResourceType string `json:"resource_type"` - ResourceID int `json:"resource_id"` - User struct { - ID int `json:"id"` - Name string `json:"name"` - Username string `json:"username"` - State string `json:"state"` - AvatarURL string `json:"avatar_url"` - WebURL string `json:"web_url"` - } `json:"user"` - Label struct { - ID int `json:"id"` - Name string `json:"name"` - Color string `json:"color"` - TextColor string `json:"text_color"` - Description string `json:"description"` - } `json:"label"` + ID int64 `json:"id"` + Action string `json:"action"` + CreatedAt *time.Time `json:"created_at"` + ResourceType string `json:"resource_type"` + ResourceID int64 `json:"resource_id"` + User BasicUser `json:"user"` + Label LabelEventLabel `json:"label"` +} + +// LabelEventLabel represents a resource label event label. +// +// GitLab API docs: +// https://docs.gitlab.com/api/resource_label_events/#get-single-issue-label-event +type LabelEventLabel struct { + ID int64 `json:"id"` + Name string `json:"name"` + Color string `json:"color"` + TextColor string `json:"text_color"` + Description string `json:"description"` } // ListLabelEventsOptions represents the options for all resource label events @@ -87,50 +84,23 @@ type ListLabelEventsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#list-project-issue-label-events -func (s *ResourceLabelEventsService) ListIssueLabelEvents(pid any, issue int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_label_events", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ls []*LabelEvent - resp, err := s.client.Do(req, &ls) - if err != nil { - return nil, resp, err - } - - return ls, resp, nil +func (s *ResourceLabelEventsService) ListIssueLabelEvents(pid any, issue int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { + return do[[]*LabelEvent](s.client, + withPath("projects/%s/issues/%d/resource_label_events", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueLabelEvent gets a single issue-label-event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#get-single-issue-label-event -func (s *ResourceLabelEventsService) GetIssueLabelEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_label_events/%d", PathEscape(project), issue, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - l := new(LabelEvent) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil +func (s *ResourceLabelEventsService) GetIssueLabelEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { + return do[*LabelEvent](s.client, + withPath("projects/%s/issues/%d/resource_label_events/%d", ProjectID{pid}, issue, event), + withRequestOpts(options...), + ) } // ListGroupEpicLabelEvents retrieves resource label events for the specified @@ -139,25 +109,12 @@ func (s *ResourceLabelEventsService) GetIssueLabelEvent(pid any, issue int, even // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#list-group-epic-label-events -func (s *ResourceLabelEventsService) ListGroupEpicLabelEvents(gid any, epic int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/resource_label_events", PathEscape(group), epic) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ls []*LabelEvent - resp, err := s.client.Do(req, &ls) - if err != nil { - return nil, resp, err - } - - return ls, resp, nil +func (s *ResourceLabelEventsService) ListGroupEpicLabelEvents(gid any, epic int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { + return do[[]*LabelEvent](s.client, + withPath("groups/%s/epics/%d/resource_label_events", GroupID{gid}, epic), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetGroupEpicLabelEvent gets a single group epic label event. @@ -165,25 +122,11 @@ func (s *ResourceLabelEventsService) ListGroupEpicLabelEvents(gid any, epic int, // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#get-single-epic-label-event -func (s *ResourceLabelEventsService) GetGroupEpicLabelEvent(gid any, epic int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/epics/%d/resource_label_events/%d", PathEscape(group), epic, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - l := new(LabelEvent) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil +func (s *ResourceLabelEventsService) GetGroupEpicLabelEvent(gid any, epic int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { + return do[*LabelEvent](s.client, + withPath("groups/%s/epics/%d/resource_label_events/%d", GroupID{gid}, epic, event), + withRequestOpts(options...), + ) } // ListMergeRequestsLabelEvents retrieves resource label events for the specified @@ -191,48 +134,21 @@ func (s *ResourceLabelEventsService) GetGroupEpicLabelEvent(gid any, epic int, e // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#list-project-merge-request-label-events -func (s *ResourceLabelEventsService) ListMergeRequestsLabelEvents(pid any, request int, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_label_events", PathEscape(project), request) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ls []*LabelEvent - resp, err := s.client.Do(req, &ls) - if err != nil { - return nil, resp, err - } - - return ls, resp, nil +func (s *ResourceLabelEventsService) ListMergeRequestsLabelEvents(pid any, request int64, opt *ListLabelEventsOptions, options ...RequestOptionFunc) ([]*LabelEvent, *Response, error) { + return do[[]*LabelEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_label_events", ProjectID{pid}, request), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestLabelEvent gets a single merge request label event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_label_events/#get-single-merge-request-label-event -func (s *ResourceLabelEventsService) GetMergeRequestLabelEvent(pid any, request int, event int, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_label_events/%d", PathEscape(project), request, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - l := new(LabelEvent) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil +func (s *ResourceLabelEventsService) GetMergeRequestLabelEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*LabelEvent, *Response, error) { + return do[*LabelEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_label_events/%d", ProjectID{pid}, request, event), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_milestone_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_milestone_events.go index 76cb105da..063bbdcf7 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_milestone_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_milestone_events.go @@ -17,17 +17,15 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( ResourceMilestoneEventsServiceInterface interface { - ListIssueMilestoneEvents(pid any, issue int, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) - GetIssueMilestoneEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) - ListMergeMilestoneEvents(pid any, request int, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) - GetMergeRequestMilestoneEvent(pid any, request int, event int, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) + ListIssueMilestoneEvents(pid any, issue int64, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) + GetIssueMilestoneEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) + ListMergeMilestoneEvents(pid any, request int64, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) + GetMergeRequestMilestoneEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) } // ResourceMilestoneEventsService handles communication with the event related @@ -45,11 +43,11 @@ var _ ResourceMilestoneEventsServiceInterface = (*ResourceMilestoneEventsService // // GitLab API docs: https://docs.gitlab.com/api/resource_milestone_events/ type MilestoneEvent struct { - ID int `json:"id"` + ID int64 `json:"id"` User *BasicUser `json:"user"` CreatedAt *time.Time `json:"created_at"` ResourceType string `json:"resource_type"` - ResourceID int `json:"resource_id"` + ResourceID int64 `json:"resource_id"` Milestone *Milestone `json:"milestone"` Action string `json:"action"` } @@ -68,50 +66,23 @@ type ListMilestoneEventsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/resource_milestone_events/#list-project-issue-milestone-events -func (s *ResourceMilestoneEventsService) ListIssueMilestoneEvents(pid any, issue int, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_milestone_events", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mes []*MilestoneEvent - resp, err := s.client.Do(req, &mes) - if err != nil { - return nil, resp, err - } - - return mes, resp, nil +func (s *ResourceMilestoneEventsService) ListIssueMilestoneEvents(pid any, issue int64, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) { + return do[[]*MilestoneEvent](s.client, + withPath("projects/%s/issues/%d/resource_milestone_events", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueMilestoneEvent gets a single issue milestone event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_milestone_events/#get-single-issue-milestone-event -func (s *ResourceMilestoneEventsService) GetIssueMilestoneEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_milestone_events/%d", PathEscape(project), issue, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - me := new(MilestoneEvent) - resp, err := s.client.Do(req, me) - if err != nil { - return nil, resp, err - } - - return me, resp, nil +func (s *ResourceMilestoneEventsService) GetIssueMilestoneEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) { + return do[*MilestoneEvent](s.client, + withPath("projects/%s/issues/%d/resource_milestone_events/%d", ProjectID{pid}, issue, event), + withRequestOpts(options...), + ) } // ListMergeMilestoneEvents retrieves resource milestone events for the specified @@ -119,48 +90,21 @@ func (s *ResourceMilestoneEventsService) GetIssueMilestoneEvent(pid any, issue i // // GitLab API docs: // https://docs.gitlab.com/api/resource_milestone_events/#list-project-merge-request-milestone-events -func (s *ResourceMilestoneEventsService) ListMergeMilestoneEvents(pid any, request int, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_milestone_events", PathEscape(project), request) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var mes []*MilestoneEvent - resp, err := s.client.Do(req, &mes) - if err != nil { - return nil, resp, err - } - - return mes, resp, nil +func (s *ResourceMilestoneEventsService) ListMergeMilestoneEvents(pid any, request int64, opt *ListMilestoneEventsOptions, options ...RequestOptionFunc) ([]*MilestoneEvent, *Response, error) { + return do[[]*MilestoneEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_milestone_events", ProjectID{pid}, request), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestMilestoneEvent gets a single merge request milestone event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_milestone_events/#get-single-merge-request-milestone-event -func (s *ResourceMilestoneEventsService) GetMergeRequestMilestoneEvent(pid any, request int, event int, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_milestone_events/%d", PathEscape(project), request, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - me := new(MilestoneEvent) - resp, err := s.client.Do(req, me) - if err != nil { - return nil, resp, err - } - - return me, resp, nil +func (s *ResourceMilestoneEventsService) GetMergeRequestMilestoneEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*MilestoneEvent, *Response, error) { + return do[*MilestoneEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_milestone_events/%d", ProjectID{pid}, request, event), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_state_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_state_events.go index b1acec9ce..318c5f15b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_state_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_state_events.go @@ -17,17 +17,15 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( ResourceStateEventsServiceInterface interface { - ListIssueStateEvents(pid any, issue int, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) - GetIssueStateEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*StateEvent, *Response, error) - ListMergeStateEvents(pid any, request int, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) - GetMergeRequestStateEvent(pid any, request int, event int, options ...RequestOptionFunc) (*StateEvent, *Response, error) + ListIssueStateEvents(pid any, issue int64, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) + GetIssueStateEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*StateEvent, *Response, error) + ListMergeStateEvents(pid any, request int64, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) + GetMergeRequestStateEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*StateEvent, *Response, error) } // ResourceStateEventsService handles communication with the event related @@ -45,11 +43,11 @@ var _ ResourceStateEventsServiceInterface = (*ResourceStateEventsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/resource_state_events/ type StateEvent struct { - ID int `json:"id"` + ID int64 `json:"id"` User *BasicUser `json:"user"` CreatedAt *time.Time `json:"created_at"` ResourceType string `json:"resource_type"` - ResourceID int `json:"resource_id"` + ResourceID int64 `json:"resource_id"` State EventTypeValue `json:"state"` } @@ -67,50 +65,23 @@ type ListStateEventsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/resource_state_events/#list-project-issue-state-events -func (s *ResourceStateEventsService) ListIssueStateEvents(pid any, issue int, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_state_events", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ses []*StateEvent - resp, err := s.client.Do(req, &ses) - if err != nil { - return nil, resp, err - } - - return ses, resp, nil +func (s *ResourceStateEventsService) ListIssueStateEvents(pid any, issue int64, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) { + return do[[]*StateEvent](s.client, + withPath("projects/%s/issues/%d/resource_state_events", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetIssueStateEvent gets a single issue-state-event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_state_events/#get-single-issue-state-event -func (s *ResourceStateEventsService) GetIssueStateEvent(pid any, issue int, event int, options ...RequestOptionFunc) (*StateEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_state_events/%d", PathEscape(project), issue, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - se := new(StateEvent) - resp, err := s.client.Do(req, se) - if err != nil { - return nil, resp, err - } - - return se, resp, nil +func (s *ResourceStateEventsService) GetIssueStateEvent(pid any, issue int64, event int64, options ...RequestOptionFunc) (*StateEvent, *Response, error) { + return do[*StateEvent](s.client, + withPath("projects/%s/issues/%d/resource_state_events/%d", ProjectID{pid}, issue, event), + withRequestOpts(options...), + ) } // ListMergeStateEvents retrieves resource state events for the specified @@ -118,48 +89,21 @@ func (s *ResourceStateEventsService) GetIssueStateEvent(pid any, issue int, even // // GitLab API docs: // https://docs.gitlab.com/api/resource_state_events/#list-project-merge-request-state-events -func (s *ResourceStateEventsService) ListMergeStateEvents(pid any, request int, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_state_events", PathEscape(project), request) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ses []*StateEvent - resp, err := s.client.Do(req, &ses) - if err != nil { - return nil, resp, err - } - - return ses, resp, nil +func (s *ResourceStateEventsService) ListMergeStateEvents(pid any, request int64, opt *ListStateEventsOptions, options ...RequestOptionFunc) ([]*StateEvent, *Response, error) { + return do[[]*StateEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_state_events", ProjectID{pid}, request), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetMergeRequestStateEvent gets a single merge request state event. // // GitLab API docs: // https://docs.gitlab.com/api/resource_state_events/#get-single-merge-request-state-event -func (s *ResourceStateEventsService) GetMergeRequestStateEvent(pid any, request int, event int, options ...RequestOptionFunc) (*StateEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/merge_requests/%d/resource_state_events/%d", PathEscape(project), request, event) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - se := new(StateEvent) - resp, err := s.client.Do(req, se) - if err != nil { - return nil, resp, err - } - - return se, resp, nil +func (s *ResourceStateEventsService) GetMergeRequestStateEvent(pid any, request int64, event int64, options ...RequestOptionFunc) (*StateEvent, *Response, error) { + return do[*StateEvent](s.client, + withPath("projects/%s/merge_requests/%d/resource_state_events/%d", ProjectID{pid}, request, event), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/resource_weight_events.go b/vendor/gitlab.com/gitlab-org/api/client-go/resource_weight_events.go index e515f312a..7d6d8b532 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/resource_weight_events.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/resource_weight_events.go @@ -17,14 +17,12 @@ package gitlab import ( - "fmt" - "net/http" "time" ) type ( ResourceWeightEventsServiceInterface interface { - ListIssueWeightEvents(pid any, issue int, opt *ListWeightEventsOptions, options ...RequestOptionFunc) ([]*WeightEvent, *Response, error) + ListIssueWeightEvents(pid any, issue int64, opt *ListWeightEventsOptions, options ...RequestOptionFunc) ([]*WeightEvent, *Response, error) } // ResourceWeightEventsService handles communication with the event related @@ -42,14 +40,14 @@ var _ ResourceWeightEventsServiceInterface = (*ResourceWeightEventsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/resource_weight_events/ type WeightEvent struct { - ID int `json:"id"` + ID int64 `json:"id"` User *BasicUser `json:"user"` CreatedAt *time.Time `json:"created_at"` ResourceType string `json:"resource_type"` - ResourceID int `json:"resource_id"` + ResourceID int64 `json:"resource_id"` State EventTypeValue `json:"state"` - IssueID int `json:"issue_id"` - Weight int `json:"weight"` + IssueID int64 `json:"issue_id"` + Weight int64 `json:"weight"` } // ListWeightEventsOptions represents the options for all resource weight events @@ -66,23 +64,10 @@ type ListWeightEventsOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/resource_weight_events/#list-project-issue-weight-events -func (s *ResourceWeightEventsService) ListIssueWeightEvents(pid any, issue int, opt *ListWeightEventsOptions, options ...RequestOptionFunc) ([]*WeightEvent, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/issues/%d/resource_weight_events", PathEscape(project), issue) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var wes []*WeightEvent - resp, err := s.client.Do(req, &wes) - if err != nil { - return nil, resp, err - } - - return wes, resp, nil +func (s *ResourceWeightEventsService) ListIssueWeightEvents(pid any, issue int64, opt *ListWeightEventsOptions, options ...RequestOptionFunc) ([]*WeightEvent, *Response, error) { + return do[[]*WeightEvent](s.client, + withPath("projects/%s/issues/%d/resource_weight_events", ProjectID{pid}, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_scopes.go b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_scopes.go new file mode 100644 index 000000000..6bf400e35 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_scopes.go @@ -0,0 +1,131 @@ +package gitlab + +import ( + "net/http" + "time" +) + +type ( + // RunnerControllerScopesServiceInterface handles communication with the + // runner controller scopes related methods of the GitLab API. This is an + // admin-only endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#runner-controller-scopes + RunnerControllerScopesServiceInterface interface { + // ListRunnerControllerScopes lists all scopes for a specific runner + // controller. This is an admin-only endpoint. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runner_controllers/#list-all-scopes-for-a-runner-controller + ListRunnerControllerScopes(rid int64, options ...RequestOptionFunc) (*RunnerControllerScopes, *Response, error) + // AddRunnerControllerInstanceScope adds an instance-level scope to a + // runner controller. This is an admin-only endpoint. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runner_controllers/#add-instance-level-scope + AddRunnerControllerInstanceScope(rid int64, options ...RequestOptionFunc) (*RunnerControllerInstanceLevelScoping, *Response, error) + // RemoveRunnerControllerInstanceScope removes an instance-level scope + // from a runner controller. This is an admin-only endpoint. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runner_controllers/#remove-instance-level-scope + RemoveRunnerControllerInstanceScope(rid int64, options ...RequestOptionFunc) (*Response, error) + // AddRunnerControllerRunnerScope adds a runner scope to a runner + // controller. This is an admin-only endpoint. The runner must be an + // instance-level runner. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runner_controllers/#add-runner-scope + AddRunnerControllerRunnerScope(rid, runnerID int64, options ...RequestOptionFunc) (*RunnerControllerRunnerLevelScoping, *Response, error) + // RemoveRunnerControllerRunnerScope removes a runner scope from a runner + // controller. This is an admin-only endpoint. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runner_controllers/#remove-runner-scope + RemoveRunnerControllerRunnerScope(rid, runnerID int64, options ...RequestOptionFunc) (*Response, error) + } + + // RunnerControllerScopesService handles communication with the runner + // controller scopes related methods of the GitLab API. This is an admin-only + // endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#runner-controller-scopes + RunnerControllerScopesService struct { + client *Client + } +) + +var _ RunnerControllerScopesServiceInterface = (*RunnerControllerScopesService)(nil) + +// RunnerControllerInstanceLevelScoping represents an instance-level scoping +// for a GitLab runner controller. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#runner-controller-scopes +type RunnerControllerInstanceLevelScoping struct { + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// RunnerControllerRunnerLevelScoping represents a runner-level scoping for a +// GitLab runner controller. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#runner-controller-scopes +type RunnerControllerRunnerLevelScoping struct { + RunnerID int64 `json:"runner_id"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// RunnerControllerScopes represents all scopes configured for a GitLab runner +// controller. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#runner-controller-scopes +type RunnerControllerScopes struct { + InstanceLevelScopings []*RunnerControllerInstanceLevelScoping `json:"instance_level_scopings"` + RunnerLevelScopings []*RunnerControllerRunnerLevelScoping `json:"runner_level_scopings"` +} + +func (s *RunnerControllerScopesService) ListRunnerControllerScopes(rid int64, options ...RequestOptionFunc) (*RunnerControllerScopes, *Response, error) { + return do[*RunnerControllerScopes](s.client, + withPath("runner_controllers/%d/scopes", rid), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerScopesService) AddRunnerControllerInstanceScope(rid int64, options ...RequestOptionFunc) (*RunnerControllerInstanceLevelScoping, *Response, error) { + return do[*RunnerControllerInstanceLevelScoping](s.client, + withMethod(http.MethodPost), + withPath("runner_controllers/%d/scopes/instance", rid), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerScopesService) RemoveRunnerControllerInstanceScope(rid int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runner_controllers/%d/scopes/instance", rid), + withRequestOpts(options...), + ) + return resp, err +} + +func (s *RunnerControllerScopesService) AddRunnerControllerRunnerScope(rid, runnerID int64, options ...RequestOptionFunc) (*RunnerControllerRunnerLevelScoping, *Response, error) { + return do[*RunnerControllerRunnerLevelScoping](s.client, + withMethod(http.MethodPost), + withPath("runner_controllers/%d/scopes/runners/%d", rid, runnerID), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerScopesService) RemoveRunnerControllerRunnerScope(rid, runnerID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runner_controllers/%d/scopes/runners/%d", rid, runnerID), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_tokens.go b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_tokens.go new file mode 100644 index 000000000..efbc91f2d --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controller_tokens.go @@ -0,0 +1,125 @@ +package gitlab + +import ( + "net/http" + "time" +) + +type ( + // RunnerControllerTokensServiceInterface handles communication with the runner + // controller token related methods of the GitLab API. This is an admin-only + // endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/ + RunnerControllerTokensServiceInterface interface { + // ListRunnerControllerTokens lists all runner controller tokens. This is an + // admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#list-all-runner-controller-tokens + ListRunnerControllerTokens(rid int64, opt *ListRunnerControllerTokensOptions, options ...RequestOptionFunc) ([]*RunnerControllerToken, *Response, error) + // GetRunnerControllerToken retrieves a single runner controller token. This + // is an admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#retrieve-a-single-runner-controller-token + GetRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) + // CreateRunnerControllerToken creates a new runner controller token. This is + // an admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#create-a-runner-controller-token + CreateRunnerControllerToken(rid int64, opt *CreateRunnerControllerTokenOptions, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) + // RotateRunnerControllerToken rotates an existing runner controller token. + // This is an admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#rotate-a-runner-controller-token + RotateRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) + // RevokeRunnerControllerToken revokes a runner controller token. This is an + // admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#revoke-a-runner-controller-token + RevokeRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*Response, error) + } + + // RunnerControllerTokensService handles communication with the runner + // controller token related methods of the GitLab API. This is an admin-only + // endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/ + RunnerControllerTokensService struct { + client *Client + } +) + +var _ RunnerControllerTokensServiceInterface = (*RunnerControllerTokensService)(nil) + +// RunnerControllerToken represents a GitLab runner controller token. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/ +type RunnerControllerToken struct { + ID int64 `json:"id"` + RunnerControllerID int64 `json:"runner_controller_id"` + Description string `json:"description"` + Token string `json:"token,omitempty"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// ListRunnerControllerTokensOptions represents the available +// ListRunnerControllerTokens() options. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#list-all-runner-controller-tokens +type ListRunnerControllerTokensOptions struct { + ListOptions +} + +func (s *RunnerControllerTokensService) ListRunnerControllerTokens(rid int64, opt *ListRunnerControllerTokensOptions, options ...RequestOptionFunc) ([]*RunnerControllerToken, *Response, error) { + return do[[]*RunnerControllerToken](s.client, + withPath("runner_controllers/%d/tokens", rid), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerTokensService) GetRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) { + return do[*RunnerControllerToken](s.client, + withPath("runner_controllers/%d/tokens/%d", rid, tokenID), + withRequestOpts(options...), + ) +} + +// CreateRunnerControllerTokenOptions represents the available +// CreateRunnerControllerToken() options. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controller_tokens/#create-a-runner-controller-token +type CreateRunnerControllerTokenOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` +} + +func (s *RunnerControllerTokensService) CreateRunnerControllerToken(rid int64, opt *CreateRunnerControllerTokenOptions, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) { + return do[*RunnerControllerToken](s.client, + withMethod(http.MethodPost), + withPath("runner_controllers/%d/tokens", rid), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerTokensService) RotateRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*RunnerControllerToken, *Response, error) { + return do[*RunnerControllerToken](s.client, + withMethod(http.MethodPost), + withPath("runner_controllers/%d/tokens/%d/rotate", rid, tokenID), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllerTokensService) RevokeRunnerControllerToken(rid int64, tokenID int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runner_controllers/%d/tokens/%d", rid, tokenID), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/runner_controllers.go b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controllers.go new file mode 100644 index 000000000..5732857b6 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/runner_controllers.go @@ -0,0 +1,145 @@ +package gitlab + +import ( + "net/http" + "time" +) + +type ( + // RunnerControllersServiceInterface handles communication with the runner + // controller related methods of the GitLab API. This is an admin-only endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/ + RunnerControllersServiceInterface interface { + // ListRunnerControllers gets a list of runner controllers. This is an + // admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#list-all-runner-controllers + ListRunnerControllers(opt *ListRunnerControllersOptions, options ...RequestOptionFunc) ([]*RunnerController, *Response, error) + // GetRunnerController retrieves a single runner controller. This is an + // admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#retrieve-a-single-runner-controller + GetRunnerController(rid int64, options ...RequestOptionFunc) (*RunnerController, *Response, error) + // CreateRunnerController registers a new runner controller. This is an + // admin-only endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#register-a-runner-controller + CreateRunnerController(opt *CreateRunnerControllerOptions, options ...RequestOptionFunc) (*RunnerController, *Response, error) + // UpdateRunnerController updates a runner controller. This is an admin-only + // endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#update-a-runner-controller + UpdateRunnerController(rid int64, opt *UpdateRunnerControllerOptions, options ...RequestOptionFunc) (*RunnerController, *Response, error) + // DeleteRunnerController deletes a runner controller. This is an admin-only + // endpoint. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#delete-a-runner-controller + DeleteRunnerController(rid int64, options ...RequestOptionFunc) (*Response, error) + } + + // RunnerControllersService handles communication with the runner controller + // related methods of the GitLab API. This is an admin-only endpoint. + // + // Note: This API is experimental and may change or be removed in future versions. + // + // GitLab API docs: https://docs.gitlab.com/api/runner_controllers/ + RunnerControllersService struct { + client *Client + } +) + +var _ RunnerControllersServiceInterface = (*RunnerControllersService)(nil) + +// RunnerControllerStateValue represents the state of a runner controller. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/ +type RunnerControllerStateValue string + +// These constants represent all valid runner controller states. +const ( + RunnerControllerStateDisabled RunnerControllerStateValue = "disabled" + RunnerControllerStateEnabled RunnerControllerStateValue = "enabled" + RunnerControllerStateDryRun RunnerControllerStateValue = "dry_run" +) + +// RunnerController represents a GitLab runner controller. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/ +type RunnerController struct { + ID int64 `json:"id"` + Description string `json:"description"` + State RunnerControllerStateValue `json:"state"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} + +// ListRunnerControllersOptions represents the available +// ListRunnerControllers() options. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#list-all-runner-controllers +type ListRunnerControllersOptions struct { + ListOptions +} + +func (s *RunnerControllersService) ListRunnerControllers(opt *ListRunnerControllersOptions, options ...RequestOptionFunc) ([]*RunnerController, *Response, error) { + return do[[]*RunnerController](s.client, + withPath("runner_controllers"), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllersService) GetRunnerController(rid int64, options ...RequestOptionFunc) (*RunnerController, *Response, error) { + return do[*RunnerController](s.client, + withPath("runner_controllers/%d", rid), + withRequestOpts(options...), + ) +} + +// CreateRunnerControllerOptions represents the available +// CreateRunnerController() options. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#register-a-runner-controller +type CreateRunnerControllerOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` + State *RunnerControllerStateValue `url:"state,omitempty" json:"state,omitempty"` +} + +func (s *RunnerControllersService) CreateRunnerController(opt *CreateRunnerControllerOptions, options ...RequestOptionFunc) (*RunnerController, *Response, error) { + return do[*RunnerController](s.client, + withMethod(http.MethodPost), + withPath("runner_controllers"), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// UpdateRunnerControllerOptions represents the available +// UpdateRunnerController() options. +// +// GitLab API docs: https://docs.gitlab.com/api/runner_controllers/#update-a-runner-controller +type UpdateRunnerControllerOptions struct { + Description *string `url:"description,omitempty" json:"description,omitempty"` + State *RunnerControllerStateValue `url:"state,omitempty" json:"state,omitempty"` +} + +func (s *RunnerControllersService) UpdateRunnerController(rid int64, opt *UpdateRunnerControllerOptions, options ...RequestOptionFunc) (*RunnerController, *Response, error) { + return do[*RunnerController](s.client, + withMethod(http.MethodPut), + withPath("runner_controllers/%d", rid), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +func (s *RunnerControllersService) DeleteRunnerController(rid int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runner_controllers/%d", rid), + withRequestOpts(options...), + ) + return resp, err +} diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/runners.go b/vendor/gitlab.com/gitlab-org/api/client-go/runners.go index b5285c806..0edf46f06 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/runners.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/runners.go @@ -24,21 +24,84 @@ import ( type ( RunnersServiceInterface interface { + // ListRunners gets a list of runners accessible by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#list-owned-runners ListRunners(opt *ListRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) + // ListAllRunners gets a list of all runners in the GitLab instance. Access is + // restricted to users with admin privileges. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#list-all-runners ListAllRunners(opt *ListRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) + // GetRunnerDetails returns details for given runner. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#get-runners-details GetRunnerDetails(rid any, options ...RequestOptionFunc) (*RunnerDetails, *Response, error) + // UpdateRunnerDetails updates details for a given runner. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#update-runners-details UpdateRunnerDetails(rid any, opt *UpdateRunnerDetailsOptions, options ...RequestOptionFunc) (*RunnerDetails, *Response, error) + // RemoveRunner removes a runner. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#delete-a-runner RemoveRunner(rid any, options ...RequestOptionFunc) (*Response, error) + // ListRunnerJobs gets a list of jobs that are being processed or were processed by specified Runner. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#list-jobs-processed-by-a-runner ListRunnerJobs(rid any, opt *ListRunnerJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) + // ListProjectRunners gets a list of runners accessible by the authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#list-projects-runners ListProjectRunners(pid any, opt *ListProjectRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) + // EnableProjectRunner enables an available specific runner in the project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#assign-a-runner-to-project EnableProjectRunner(pid any, opt *EnableProjectRunnerOptions, options ...RequestOptionFunc) (*Runner, *Response, error) - DisableProjectRunner(pid any, runner int, options ...RequestOptionFunc) (*Response, error) + // DisableProjectRunner disables a specific runner from project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#unassign-a-runner-from-project + DisableProjectRunner(pid any, runner int64, options ...RequestOptionFunc) (*Response, error) + // ListGroupsRunners lists all runners (specific and shared) available in the + // group as well it's ancestor groups. Shared runners are listed if at least one + // shared runner is defined. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#list-groups-runners ListGroupsRunners(gid any, opt *ListGroupsRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) + // RegisterNewRunner registers a new Runner for the instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#create-a-runner RegisterNewRunner(opt *RegisterNewRunnerOptions, options ...RequestOptionFunc) (*Runner, *Response, error) + // DeleteRegisteredRunner deletes a Runner by Token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#delete-a-runner-by-authentication-token DeleteRegisteredRunner(opt *DeleteRegisteredRunnerOptions, options ...RequestOptionFunc) (*Response, error) - DeleteRegisteredRunnerByID(rid int, options ...RequestOptionFunc) (*Response, error) + // DeleteRegisteredRunnerByID deletes a runner by ID. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#delete-a-runner-by-id + DeleteRegisteredRunnerByID(rid int64, options ...RequestOptionFunc) (*Response, error) + // VerifyRegisteredRunner registers a new runner for the instance. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#verify-authentication-for-a-registered-runner VerifyRegisteredRunner(opt *VerifyRegisteredRunnerOptions, options ...RequestOptionFunc) (*Response, error) - ResetRunnerAuthenticationToken(rid int, options ...RequestOptionFunc) (*RunnerAuthenticationToken, *Response, error) + // ResetRunnerAuthenticationToken resets a runner's authentication token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/runners/#reset-runners-authentication-token-by-using-the-runner-id + ResetRunnerAuthenticationToken(rid int64, options ...RequestOptionFunc) (*RunnerAuthenticationToken, *Response, error) // Deprecated: for removal in GitLab 20.0, see https://docs.gitlab.com/ci/runners/new_creation_workflow/ instead ResetInstanceRunnerRegistrationToken(options ...RequestOptionFunc) (*RunnerRegistrationToken, *Response, error) @@ -65,7 +128,7 @@ var _ RunnersServiceInterface = (*RunnersService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/runners/ type Runner struct { - ID int `json:"id"` + ID int64 `json:"id"` Description string `json:"description"` Paused bool `json:"paused"` IsShared bool `json:"is_shared"` @@ -87,34 +150,24 @@ type Runner struct { // // GitLab API docs: https://docs.gitlab.com/api/runners/ type RunnerDetails struct { - Paused bool `json:"paused"` - Description string `json:"description"` - ID int `json:"id"` - IsShared bool `json:"is_shared"` - RunnerType string `json:"runner_type"` - ContactedAt *time.Time `json:"contacted_at"` - MaintenanceNote string `json:"maintenance_note"` - Name string `json:"name"` - Online bool `json:"online"` - Status string `json:"status"` - Projects []struct { - ID int `json:"id"` - Name string `json:"name"` - NameWithNamespace string `json:"name_with_namespace"` - Path string `json:"path"` - PathWithNamespace string `json:"path_with_namespace"` - } `json:"projects"` - Token string `json:"token"` - TagList []string `json:"tag_list"` - RunUntagged bool `json:"run_untagged"` - Locked bool `json:"locked"` - AccessLevel string `json:"access_level"` - MaximumTimeout int `json:"maximum_timeout"` - Groups []struct { - ID int `json:"id"` - Name string `json:"name"` - WebURL string `json:"web_url"` - } `json:"groups"` + Paused bool `json:"paused"` + Description string `json:"description"` + ID int64 `json:"id"` + IsShared bool `json:"is_shared"` + RunnerType string `json:"runner_type"` + ContactedAt *time.Time `json:"contacted_at"` + MaintenanceNote string `json:"maintenance_note"` + Name string `json:"name"` + Online bool `json:"online"` + Status string `json:"status"` + Projects []RunnerDetailsProject `json:"projects"` + Token string `json:"token"` + TagList []string `json:"tag_list"` + RunUntagged bool `json:"run_untagged"` + Locked bool `json:"locked"` + AccessLevel string `json:"access_level"` + MaximumTimeout int64 `json:"maximum_timeout"` + Groups []RunnerDetailsGroup `json:"groups"` // Deprecated: for removal in v5 of the API, see GraphQL resource CiRunnerManager instead Architecture string `json:"architecture"` @@ -135,6 +188,26 @@ type RunnerDetails struct { Active bool `json:"active"` } +// RunnerDetailsProject represents the GitLab CI runner details project. +// +// GitLab API docs: https://docs.gitlab.com/api/runners/ +type RunnerDetailsProject struct { + ID int64 `json:"id"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` +} + +// RunnerDetailsGroup represents the GitLab CI runner details group. +// +// GitLab API docs: https://docs.gitlab.com/api/runners/ +type RunnerDetailsGroup struct { + ID int64 `json:"id"` + Name string `json:"name"` + WebURL string `json:"web_url"` +} + // ListRunnersOptions represents the available ListRunners() options. // // GitLab API docs: @@ -150,68 +223,43 @@ type ListRunnersOptions struct { Scope *string `url:"scope,omitempty" json:"scope,omitempty"` } -// ListRunners gets a list of runners accessible by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#list-owned-runners func (s *RunnersService) ListRunners(opt *ListRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "runners", opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Runner - resp, err := s.client.Do(req, &rs) + res, resp, err := do[[]*Runner](s.client, + withMethod(http.MethodGet), + withPath("runners"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } -// ListAllRunners gets a list of all runners in the GitLab instance. Access is -// restricted to users with admin privileges. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#list-all-runners func (s *RunnersService) ListAllRunners(opt *ListRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "runners/all", opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Runner - resp, err := s.client.Do(req, &rs) + res, resp, err := do[[]*Runner](s.client, + withMethod(http.MethodGet), + withPath("runners/all"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } -// GetRunnerDetails returns details for given runner. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#get-runners-details func (s *RunnersService) GetRunnerDetails(rid any, options ...RequestOptionFunc) (*RunnerDetails, *Response, error) { - runner, err := parseID(rid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("runners/%s", runner) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - rs := new(RunnerDetails) - resp, err := s.client.Do(req, &rs) + res, resp, err := do[*RunnerDetails](s.client, + withMethod(http.MethodGet), + withPath("runners/%s", RunnerID{rid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } // UpdateRunnerDetailsOptions represents the available UpdateRunnerDetails() options. @@ -225,55 +273,34 @@ type UpdateRunnerDetailsOptions struct { RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"` Locked *bool `url:"locked,omitempty" json:"locked,omitempty"` AccessLevel *string `url:"access_level,omitempty" json:"access_level,omitempty"` - MaximumTimeout *int `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` + MaximumTimeout *int64 `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` MaintenanceNote *string `url:"maintenance_note,omitempty" json:"maintenance_note,omitempty"` // Deprecated: for removal in v5 of the API, use Paused instead Active *bool `url:"active,omitempty" json:"active,omitempty"` } -// UpdateRunnerDetails updates details for a given runner. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#update-runners-details func (s *RunnersService) UpdateRunnerDetails(rid any, opt *UpdateRunnerDetailsOptions, options ...RequestOptionFunc) (*RunnerDetails, *Response, error) { - runner, err := parseID(rid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("runners/%s", runner) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - rs := new(RunnerDetails) - resp, err := s.client.Do(req, &rs) + res, resp, err := do[*RunnerDetails](s.client, + withMethod(http.MethodPut), + withPath("runners/%s", RunnerID{rid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } -// RemoveRunner removes a runner. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#delete-a-runner func (s *RunnersService) RemoveRunner(rid any, options ...RequestOptionFunc) (*Response, error) { - runner, err := parseID(rid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("runners/%s", runner) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runners/%s", RunnerID{rid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // ListRunnerJobsOptions represents the available ListRunnerJobs() @@ -288,29 +315,17 @@ type ListRunnerJobsOptions struct { Sort *string `url:"sort,omitempty" json:"sort,omitempty"` } -// ListRunnerJobs gets a list of jobs that are being processed or were processed by specified Runner. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#list-jobs-processed-by-a-runner func (s *RunnersService) ListRunnerJobs(rid any, opt *ListRunnerJobsOptions, options ...RequestOptionFunc) ([]*Job, *Response, error) { - runner, err := parseID(rid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("runners/%s/jobs", runner) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Job - resp, err := s.client.Do(req, &rs) + res, resp, err := do[[]*Job](s.client, + withMethod(http.MethodGet), + withPath("runners/%s/jobs", RunnerID{rid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } // ListProjectRunnersOptions represents the available ListProjectRunners() @@ -320,29 +335,17 @@ func (s *RunnersService) ListRunnerJobs(rid any, opt *ListRunnerJobsOptions, opt // https://docs.gitlab.com/api/runners/#list-projects-runners type ListProjectRunnersOptions ListRunnersOptions -// ListProjectRunners gets a list of runners accessible by the authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#list-projects-runners func (s *RunnersService) ListProjectRunners(pid any, opt *ListProjectRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/runners", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Runner - resp, err := s.client.Do(req, &rs) + res, resp, err := do[[]*Runner](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/runners", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } // EnableProjectRunnerOptions represents the available EnableProjectRunner() @@ -351,51 +354,30 @@ func (s *RunnersService) ListProjectRunners(pid any, opt *ListProjectRunnersOpti // GitLab API docs: // https://docs.gitlab.com/api/runners/#assign-a-runner-to-project type EnableProjectRunnerOptions struct { - RunnerID int `json:"runner_id"` + RunnerID int64 `json:"runner_id"` } -// EnableProjectRunner enables an available specific runner in the project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#assign-a-runner-to-project func (s *RunnersService) EnableProjectRunner(pid any, opt *EnableProjectRunnerOptions, options ...RequestOptionFunc) (*Runner, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/runners", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - r := new(Runner) - resp, err := s.client.Do(req, &r) + res, resp, err := do[*Runner](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/runners", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } -// DisableProjectRunner disables a specific runner from project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#unassign-a-runner-from-project -func (s *RunnersService) DisableProjectRunner(pid any, runner int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/runners/%d", PathEscape(project), runner) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *RunnersService) DisableProjectRunner(pid any, runner int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/runners/%d", ProjectID{pid}, runner), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // ListGroupsRunnersOptions represents the available ListGroupsRunners() options. @@ -409,31 +391,17 @@ type ListGroupsRunnersOptions struct { TagList *[]string `url:"tag_list,comma,omitempty" json:"tag_list,omitempty"` } -// ListGroupsRunners lists all runners (specific and shared) available in the -// group as well itโ€™s ancestor groups. Shared runners are listed if at least one -// shared runner is defined. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#list-groups-runners func (s *RunnersService) ListGroupsRunners(gid any, opt *ListGroupsRunnersOptions, options ...RequestOptionFunc) ([]*Runner, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/runners", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var rs []*Runner - resp, err := s.client.Do(req, &rs) + res, resp, err := do[[]*Runner](s.client, + withMethod(http.MethodGet), + withPath("groups/%s/runners", GroupID{gid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return rs, resp, nil + return res, resp, nil } // RegisterNewRunnerOptions represents the available RegisterNewRunner() @@ -450,7 +418,7 @@ type RegisterNewRunnerOptions struct { RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"` TagList *[]string `url:"tag_list[],omitempty" json:"tag_list,omitempty"` AccessLevel *string `url:"access_level,omitempty" json:"access_level,omitempty"` - MaximumTimeout *int `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` + MaximumTimeout *int64 `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` MaintenanceNote *string `url:"maintenance_note,omitempty" json:"maintenance_note,omitempty"` // Deprecated: for removal in v5 of the API, use Paused instead @@ -470,23 +438,17 @@ type RegisterNewRunnerInfoOptions struct { Architecture *string `url:"architecture,omitempty" json:"architecture,omitempty"` } -// RegisterNewRunner registers a new Runner for the instance. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#create-a-runner func (s *RunnersService) RegisterNewRunner(opt *RegisterNewRunnerOptions, options ...RequestOptionFunc) (*Runner, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "runners", opt, options) - if err != nil { - return nil, nil, err - } - - r := new(Runner) - resp, err := s.client.Do(req, &r) + res, resp, err := do[*Runner](s.client, + withMethod(http.MethodPost), + withPath("runners"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } // DeleteRegisteredRunnerOptions represents the available @@ -498,30 +460,24 @@ type DeleteRegisteredRunnerOptions struct { Token *string `url:"token" json:"token"` } -// DeleteRegisteredRunner deletes a Runner by Token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#delete-a-runner-by-authentication-token func (s *RunnersService) DeleteRegisteredRunner(opt *DeleteRegisteredRunnerOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodDelete, "runners", opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("runners"), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } -// DeleteRegisteredRunnerByID deletes a runner by ID. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#delete-a-runner-by-id -func (s *RunnersService) DeleteRegisteredRunnerByID(rid int, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodDelete, fmt.Sprintf("runners/%d", rid), nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *RunnersService) DeleteRegisteredRunnerByID(rid int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath(fmt.Sprintf("runners/%d", rid)), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // VerifyRegisteredRunnerOptions represents the available @@ -533,17 +489,14 @@ type VerifyRegisteredRunnerOptions struct { Token *string `url:"token" json:"token"` } -// VerifyRegisteredRunner registers a new runner for the instance. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#verify-authentication-for-a-registered-runner func (s *RunnersService) VerifyRegisteredRunner(opt *VerifyRegisteredRunnerOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "runners/verify", opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("runners/verify"), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } type RunnerRegistrationToken struct { @@ -558,18 +511,16 @@ type RunnerRegistrationToken struct { // GitLab API docs: // https://docs.gitlab.com/api/runners/#reset-instances-runner-registration-token func (s *RunnersService) ResetInstanceRunnerRegistrationToken(options ...RequestOptionFunc) (*RunnerRegistrationToken, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "runners/reset_registration_token", nil, options) - if err != nil { - return nil, nil, err - } - - r := new(RunnerRegistrationToken) - resp, err := s.client.Do(req, &r) + res, resp, err := do[*RunnerRegistrationToken](s.client, + withMethod(http.MethodPost), + withPath("runners/reset_registration_token"), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } // ResetGroupRunnerRegistrationToken resets a group's runner registration token. @@ -578,24 +529,16 @@ func (s *RunnersService) ResetInstanceRunnerRegistrationToken(options ...Request // GitLab API docs: // https://docs.gitlab.com/api/runners/#reset-groups-runner-registration-token func (s *RunnersService) ResetGroupRunnerRegistrationToken(gid any, options ...RequestOptionFunc) (*RunnerRegistrationToken, *Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("groups/%s/runners/reset_registration_token", PathEscape(group)) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(RunnerRegistrationToken) - resp, err := s.client.Do(req, &r) + res, resp, err := do[*RunnerRegistrationToken](s.client, + withMethod(http.MethodPost), + withPath("groups/%s/runners/reset_registration_token", GroupID{gid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } // ResetProjectRunnerRegistrationToken resets a projects's runner registration token. @@ -604,23 +547,16 @@ func (s *RunnersService) ResetGroupRunnerRegistrationToken(gid any, options ...R // GitLab API docs: // https://docs.gitlab.com/api/runners/#reset-projects-runner-registration-token func (s *RunnersService) ResetProjectRunnerRegistrationToken(pid any, options ...RequestOptionFunc) (*RunnerRegistrationToken, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/runners/reset_registration_token", PathEscape(project)) - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(RunnerRegistrationToken) - resp, err := s.client.Do(req, &r) + res, resp, err := do[*RunnerRegistrationToken](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/runners/reset_registration_token", ProjectID{pid}), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } type RunnerAuthenticationToken struct { @@ -628,22 +564,15 @@ type RunnerAuthenticationToken struct { TokenExpiresAt *time.Time `url:"token_expires_at" json:"token_expires_at"` } -// ResetRunnerAuthenticationToken resets a runner's authentication token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/runners/#reset-runners-authentication-token-by-using-the-runner-id -func (s *RunnersService) ResetRunnerAuthenticationToken(rid int, options ...RequestOptionFunc) (*RunnerAuthenticationToken, *Response, error) { - u := fmt.Sprintf("runners/%d/reset_authentication_token", rid) - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - r := new(RunnerAuthenticationToken) - resp, err := s.client.Do(req, &r) +func (s *RunnersService) ResetRunnerAuthenticationToken(rid int64, options ...RequestOptionFunc) (*RunnerAuthenticationToken, *Response, error) { + res, resp, err := do[*RunnerAuthenticationToken](s.client, + withMethod(http.MethodPost), + withPath("runners/%d/reset_authentication_token", rid), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return r, resp, nil + return res, resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/search.go b/vendor/gitlab.com/gitlab-org/api/client-go/search.go index 580e56ff1..baec55b66 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/search.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/search.go @@ -16,11 +16,6 @@ package gitlab -import ( - "fmt" - "net/http" -) - type ( SearchServiceInterface interface { Projects(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) @@ -79,9 +74,11 @@ type searchOptions struct { // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-projects func (s *SearchService) Projects(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - var ps []*Project - resp, err := s.search("projects", query, &ps, opt, options...) - return ps, resp, err + return do[[]*Project](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "projects", Search: query}), + withRequestOpts(options...), + ) } // ProjectsByGroup searches the expression within projects for @@ -89,18 +86,22 @@ func (s *SearchService) Projects(query string, opt *SearchOptions, options ...Re // // GitLab API docs: https://docs.gitlab.com/api/search/#group-search-api func (s *SearchService) ProjectsByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) { - var ps []*Project - resp, err := s.searchByGroup(gid, "projects", query, &ps, opt, options...) - return ps, resp, err + return do[[]*Project](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "projects", Search: query}), + withRequestOpts(options...), + ) } // Issues searches the expression within issues // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-issues func (s *SearchService) Issues(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - var is []*Issue - resp, err := s.search("issues", query, &is, opt, options...) - return is, resp, err + return do[[]*Issue](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "issues", Search: query}), + withRequestOpts(options...), + ) } // IssuesByGroup searches the expression within issues for @@ -108,9 +109,11 @@ func (s *SearchService) Issues(query string, opt *SearchOptions, options ...Requ // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-issues-1 func (s *SearchService) IssuesByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - var is []*Issue - resp, err := s.searchByGroup(gid, "issues", query, &is, opt, options...) - return is, resp, err + return do[[]*Issue](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "issues", Search: query}), + withRequestOpts(options...), + ) } // IssuesByProject searches the expression within issues for @@ -118,9 +121,11 @@ func (s *SearchService) IssuesByGroup(gid any, query string, opt *SearchOptions, // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-issues-2 func (s *SearchService) IssuesByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Issue, *Response, error) { - var is []*Issue - resp, err := s.searchByProject(pid, "issues", query, &is, opt, options...) - return is, resp, err + return do[[]*Issue](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "issues", Search: query}), + withRequestOpts(options...), + ) } // MergeRequests searches the expression within merge requests @@ -128,9 +133,11 @@ func (s *SearchService) IssuesByProject(pid any, query string, opt *SearchOption // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-merge_requests func (s *SearchService) MergeRequests(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) { - var ms []*MergeRequest - resp, err := s.search("merge_requests", query, &ms, opt, options...) - return ms, resp, err + return do[[]*MergeRequest](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "merge_requests", Search: query}), + withRequestOpts(options...), + ) } // MergeRequestsByGroup searches the expression within merge requests for @@ -139,9 +146,11 @@ func (s *SearchService) MergeRequests(query string, opt *SearchOptions, options // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-merge_requests-1 func (s *SearchService) MergeRequestsByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) { - var ms []*MergeRequest - resp, err := s.searchByGroup(gid, "merge_requests", query, &ms, opt, options...) - return ms, resp, err + return do[[]*MergeRequest](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "merge_requests", Search: query}), + withRequestOpts(options...), + ) } // MergeRequestsByProject searches the expression within merge requests for @@ -150,18 +159,22 @@ func (s *SearchService) MergeRequestsByGroup(gid any, query string, opt *SearchO // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-merge_requests-2 func (s *SearchService) MergeRequestsByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) { - var ms []*MergeRequest - resp, err := s.searchByProject(pid, "merge_requests", query, &ms, opt, options...) - return ms, resp, err + return do[[]*MergeRequest](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "merge_requests", Search: query}), + withRequestOpts(options...), + ) } // Milestones searches the expression within milestones // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-milestones func (s *SearchService) Milestones(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Milestone, *Response, error) { - var ms []*Milestone - resp, err := s.search("milestones", query, &ms, opt, options...) - return ms, resp, err + return do[[]*Milestone](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "milestones", Search: query}), + withRequestOpts(options...), + ) } // MilestonesByGroup searches the expression within milestones for @@ -169,9 +182,11 @@ func (s *SearchService) Milestones(query string, opt *SearchOptions, options ... // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-milestones-1 func (s *SearchService) MilestonesByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Milestone, *Response, error) { - var ms []*Milestone - resp, err := s.searchByGroup(gid, "milestones", query, &ms, opt, options...) - return ms, resp, err + return do[[]*Milestone](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "milestones", Search: query}), + withRequestOpts(options...), + ) } // MilestonesByProject searches the expression within milestones for @@ -179,9 +194,11 @@ func (s *SearchService) MilestonesByGroup(gid any, query string, opt *SearchOpti // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-milestones-2 func (s *SearchService) MilestonesByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Milestone, *Response, error) { - var ms []*Milestone - resp, err := s.searchByProject(pid, "milestones", query, &ms, opt, options...) - return ms, resp, err + return do[[]*Milestone](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "milestones", Search: query}), + withRequestOpts(options...), + ) } // SnippetTitles searches the expression within snippet titles @@ -189,9 +206,11 @@ func (s *SearchService) MilestonesByProject(pid any, query string, opt *SearchOp // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-snippet_titles func (s *SearchService) SnippetTitles(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) { - var ss []*Snippet - resp, err := s.search("snippet_titles", query, &ss, opt, options...) - return ss, resp, err + return do[[]*Snippet](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "snippet_titles", Search: query}), + withRequestOpts(options...), + ) } // NotesByProject searches the expression within notes for the specified @@ -199,9 +218,11 @@ func (s *SearchService) SnippetTitles(query string, opt *SearchOptions, options // // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-notes func (s *SearchService) NotesByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Note, *Response, error) { - var ns []*Note - resp, err := s.searchByProject(pid, "notes", query, &ns, opt, options...) - return ns, resp, err + return do[[]*Note](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "notes", Search: query}), + withRequestOpts(options...), + ) } // WikiBlobs searches the expression within all wiki blobs @@ -209,9 +230,11 @@ func (s *SearchService) NotesByProject(pid any, query string, opt *SearchOptions // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-wiki_blobs func (s *SearchService) WikiBlobs(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Wiki, *Response, error) { - var ws []*Wiki - resp, err := s.search("wiki_blobs", query, &ws, opt, options...) - return ws, resp, err + return do[[]*Wiki](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "wiki_blobs", Search: query}), + withRequestOpts(options...), + ) } // WikiBlobsByGroup searches the expression within wiki blobs for @@ -220,9 +243,11 @@ func (s *SearchService) WikiBlobs(query string, opt *SearchOptions, options ...R // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-wiki_blobs-1 func (s *SearchService) WikiBlobsByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Wiki, *Response, error) { - var ws []*Wiki - resp, err := s.searchByGroup(gid, "wiki_blobs", query, &ws, opt, options...) - return ws, resp, err + return do[[]*Wiki](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "wiki_blobs", Search: query}), + withRequestOpts(options...), + ) } // WikiBlobsByProject searches the expression within wiki blobs for @@ -231,18 +256,22 @@ func (s *SearchService) WikiBlobsByGroup(gid any, query string, opt *SearchOptio // GitLab API docs: // https://docs.gitlab.com/api/search/#scope-wiki_blobs-2 func (s *SearchService) WikiBlobsByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Wiki, *Response, error) { - var ws []*Wiki - resp, err := s.searchByProject(pid, "wiki_blobs", query, &ws, opt, options...) - return ws, resp, err + return do[[]*Wiki](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "wiki_blobs", Search: query}), + withRequestOpts(options...), + ) } // Commits searches the expression within all commits // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-commits func (s *SearchService) Commits(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { - var cs []*Commit - resp, err := s.search("commits", query, &cs, opt, options...) - return cs, resp, err + return do[[]*Commit](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "commits", Search: query}), + withRequestOpts(options...), + ) } // CommitsByGroup searches the expression within commits for the specified @@ -250,9 +279,11 @@ func (s *SearchService) Commits(query string, opt *SearchOptions, options ...Req // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-commits-1 func (s *SearchService) CommitsByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { - var cs []*Commit - resp, err := s.searchByGroup(gid, "commits", query, &cs, opt, options...) - return cs, resp, err + return do[[]*Commit](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "commits", Search: query}), + withRequestOpts(options...), + ) } // CommitsByProject searches the expression within commits for the @@ -260,9 +291,11 @@ func (s *SearchService) CommitsByGroup(gid any, query string, opt *SearchOptions // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-commits-2 func (s *SearchService) CommitsByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Commit, *Response, error) { - var cs []*Commit - resp, err := s.searchByProject(pid, "commits", query, &cs, opt, options...) - return cs, resp, err + return do[[]*Commit](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "commits", Search: query}), + withRequestOpts(options...), + ) } // Blob represents a single blob. @@ -273,17 +306,19 @@ type Blob struct { Filename string `json:"filename"` ID string `json:"id"` Ref string `json:"ref"` - Startline int `json:"startline"` - ProjectID int `json:"project_id"` + Startline int64 `json:"startline"` + ProjectID int64 `json:"project_id"` } // Blobs searches the expression within all blobs // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-blobs func (s *SearchService) Blobs(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Blob, *Response, error) { - var bs []*Blob - resp, err := s.search("blobs", query, &bs, opt, options...) - return bs, resp, err + return do[[]*Blob](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "blobs", Search: query}), + withRequestOpts(options...), + ) } // BlobsByGroup searches the expression within blobs for the specified @@ -291,9 +326,11 @@ func (s *SearchService) Blobs(query string, opt *SearchOptions, options ...Reque // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-blobs-1 func (s *SearchService) BlobsByGroup(gid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Blob, *Response, error) { - var bs []*Blob - resp, err := s.searchByGroup(gid, "blobs", query, &bs, opt, options...) - return bs, resp, err + return do[[]*Blob](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "blobs", Search: query}), + withRequestOpts(options...), + ) } // BlobsByProject searches the expression within blobs for the specified @@ -301,18 +338,22 @@ func (s *SearchService) BlobsByGroup(gid any, query string, opt *SearchOptions, // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-blobs-2 func (s *SearchService) BlobsByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Blob, *Response, error) { - var bs []*Blob - resp, err := s.searchByProject(pid, "blobs", query, &bs, opt, options...) - return bs, resp, err + return do[[]*Blob](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "blobs", Search: query}), + withRequestOpts(options...), + ) } // Users searches the expression within all users // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-users func (s *SearchService) Users(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*User, *Response, error) { - var ret []*User - resp, err := s.search("users", query, &ret, opt, options...) - return ret, resp, err + return do[[]*User](s.client, + withPath("search"), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "users", Search: query}), + withRequestOpts(options...), + ) } // UsersByGroup searches the expression within users for the specified @@ -323,9 +364,11 @@ func (s *SearchService) UsersByGroup(gid any, query string, opt *SearchOptions, if opt == nil { opt = &SearchOptions{} } - var ret []*User - resp, err := s.searchByGroup(gid, "users", query, &ret, opt, options...) - return ret, resp, err + return do[[]*User](s.client, + withPath("groups/%s/-/search", GroupID{gid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "users", Search: query}), + withRequestOpts(options...), + ) } // UsersByProject searches the expression within users for the @@ -333,52 +376,9 @@ func (s *SearchService) UsersByGroup(gid any, query string, opt *SearchOptions, // // GitLab API docs: https://docs.gitlab.com/api/search/#scope-users-2 func (s *SearchService) UsersByProject(pid any, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*User, *Response, error) { - var ret []*User - resp, err := s.searchByProject(pid, "users", query, &ret, opt, options...) - return ret, resp, err -} - -func (s *SearchService) search(scope, query string, result any, opt *SearchOptions, options ...RequestOptionFunc) (*Response, error) { - opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} - - req, err := s.client.NewRequest(http.MethodGet, "search", opts, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, result) -} - -func (s *SearchService) searchByGroup(gid any, scope, query string, result any, opt *SearchOptions, options ...RequestOptionFunc) (*Response, error) { - group, err := parseID(gid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("groups/%s/-/search", PathEscape(group)) - - opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, result) -} - -func (s *SearchService) searchByProject(pid any, scope, query string, result any, opt *SearchOptions, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/-/search", PathEscape(project)) - - opts := &searchOptions{SearchOptions: *opt, Scope: scope, Search: query} - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, result) + return do[[]*User](s.client, + withPath("projects/%s/-/search", ProjectID{pid}), + withAPIOpts(&searchOptions{SearchOptions: *opt, Scope: "users", Search: query}), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/secure_files.go b/vendor/gitlab.com/gitlab-org/api/client-go/secure_files.go index 13fc386cc..1371333c5 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/secure_files.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/secure_files.go @@ -15,7 +15,6 @@ package gitlab import ( "bytes" - "fmt" "io" "net/http" "time" @@ -24,10 +23,10 @@ import ( type ( SecureFilesServiceInterface interface { ListProjectSecureFiles(pid any, opt *ListProjectSecureFilesOptions, options ...RequestOptionFunc) ([]*SecureFile, *Response, error) - ShowSecureFileDetails(pid any, id int, options ...RequestOptionFunc) (*SecureFile, *Response, error) + ShowSecureFileDetails(pid any, id int64, options ...RequestOptionFunc) (*SecureFile, *Response, error) CreateSecureFile(pid any, content io.Reader, opt *CreateSecureFileOptions, options ...RequestOptionFunc) (*SecureFile, *Response, error) - DownloadSecureFile(pid any, id int, options ...RequestOptionFunc) (io.Reader, *Response, error) - RemoveSecureFile(pid any, id int, options ...RequestOptionFunc) (*Response, error) + DownloadSecureFile(pid any, id int64, options ...RequestOptionFunc) (io.Reader, *Response, error) + RemoveSecureFile(pid any, id int64, options ...RequestOptionFunc) (*Response, error) } // SecureFilesService handles communication with the secure files related @@ -47,7 +46,7 @@ var _ SecureFilesServiceInterface = (*SecureFilesService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/secure_files/ type SecureFile struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Checksum string `json:"checksum"` ChecksumAlgorithm string `json:"checksum_algorithm"` @@ -103,55 +102,31 @@ func (f SecureFile) String() string { // // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#list-project-secure-files -type ListProjectSecureFilesOptions ListOptions +type ListProjectSecureFilesOptions struct { + ListOptions +} // ListProjectSecureFiles gets a list of secure files in a project. // // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#list-project-secure-files func (s SecureFilesService) ListProjectSecureFiles(pid any, opt *ListProjectSecureFilesOptions, options ...RequestOptionFunc) ([]*SecureFile, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/secure_files", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var files []*SecureFile - resp, err := s.client.Do(req, &files) - if err != nil { - return nil, resp, err - } - return files, resp, nil + return do[[]*SecureFile](s.client, + withPath("projects/%s/secure_files", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ShowSecureFileDetails gets the details of a specific secure file in a project. // // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#show-secure-file-details -func (s SecureFilesService) ShowSecureFileDetails(pid any, id int, options ...RequestOptionFunc) (*SecureFile, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/secure_files/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - file := new(SecureFile) - resp, err := s.client.Do(req, file) - if err != nil { - return nil, resp, err - } - - return file, resp, nil +func (s SecureFilesService) ShowSecureFileDetails(pid any, id int64, options ...RequestOptionFunc) (*SecureFile, *Response, error) { + return do[*SecureFile](s.client, + withPath("projects/%s/secure_files/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) } // CreateSecureFileOptions represents the available @@ -168,66 +143,39 @@ type CreateSecureFileOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#create-secure-file func (s SecureFilesService) CreateSecureFile(pid any, content io.Reader, opt *CreateSecureFileOptions, options ...RequestOptionFunc) (*SecureFile, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/secure_files", PathEscape(project)) - - req, err := s.client.UploadRequest(http.MethodPost, u, content, *opt.Name, UploadFile, opt, options) - if err != nil { - return nil, nil, err - } - - file := new(SecureFile) - resp, err := s.client.Do(req, file) - if err != nil { - return nil, resp, err - } - - return file, resp, nil + return do[*SecureFile](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/secure_files", ProjectID{pid}), + withUpload(content, *opt.Name, UploadFile), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DownloadSecureFile downloads the contents of a project's secure file. // // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#download-secure-file -func (s SecureFilesService) DownloadSecureFile(pid any, id int, options ...RequestOptionFunc) (io.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/secure_files/%d/download", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var file bytes.Buffer - resp, err := s.client.Do(req, &file) +func (s SecureFilesService) DownloadSecureFile(pid any, id int64, options ...RequestOptionFunc) (io.Reader, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/secure_files/%d/download", ProjectID{pid}, id), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return &file, resp, err + return &buf, resp, nil } // RemoveSecureFile removes a project's secure file. // // GitLab API docs: // https://docs.gitlab.com/api/secure_files/#remove-secure-file -func (s SecureFilesService) RemoveSecureFile(pid any, id int, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/secure_files/%d", PathEscape(project), id) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s SecureFilesService) RemoveSecureFile(pid any, id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/secure_files/%d", ProjectID{pid}, id), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/services.go b/vendor/gitlab.com/gitlab-org/api/client-go/services.go index 98ad3ed55..c8eeb0d70 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/services.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/services.go @@ -59,6 +59,9 @@ type ( GetJiraService(pid any, options ...RequestOptionFunc) (*JiraService, *Response, error) SetJiraService(pid any, opt *SetJiraServiceOptions, options ...RequestOptionFunc) (*JiraService, *Response, error) DeleteJiraService(pid any, options ...RequestOptionFunc) (*Response, error) + GetMatrixService(pid any, options ...RequestOptionFunc) (*MatrixService, *Response, error) + SetMatrixService(pid any, opt *SetMatrixServiceOptions, options ...RequestOptionFunc) (*MatrixService, *Response, error) + DeleteMatrixService(pid any, options ...RequestOptionFunc) (*Response, error) GetMattermostService(pid any, options ...RequestOptionFunc) (*MattermostService, *Response, error) SetMattermostService(pid any, opt *SetMattermostServiceOptions, options ...RequestOptionFunc) (*MattermostService, *Response, error) DeleteMattermostService(pid any, options ...RequestOptionFunc) (*Response, error) @@ -108,24 +111,10 @@ type Service = Integration // // GitLab API docs: https://docs.gitlab.com/api/project_integrations/#list-all-active-integrations func (s *ServicesService) ListServices(pid any, options ...RequestOptionFunc) ([]*Service, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var svcs []*Service - resp, err := s.client.Do(req, &svcs) - if err != nil { - return nil, resp, err - } - - return svcs, resp, nil + return do[[]*Service](s.client, + withPath("projects/%s/services", ProjectID{pid}), + withRequestOpts(options...), + ) } // CustomIssueTrackerService represents Custom Issue Tracker service settings. @@ -152,24 +141,10 @@ type CustomIssueTrackerServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-custom-issue-tracker-settings func (s *ServicesService) GetCustomIssueTrackerService(pid any, options ...RequestOptionFunc) (*CustomIssueTrackerService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/custom-issue-tracker", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(CustomIssueTrackerService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*CustomIssueTrackerService](s.client, + withPath("projects/%s/services/custom-issue-tracker", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetCustomIssueTrackerServiceOptions represents the available SetCustomIssueTrackerService() @@ -188,24 +163,12 @@ type SetCustomIssueTrackerServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-a-custom-issue-tracker func (s *ServicesService) SetCustomIssueTrackerService(pid any, opt *SetCustomIssueTrackerServiceOptions, options ...RequestOptionFunc) (*CustomIssueTrackerService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/custom-issue-tracker", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(CustomIssueTrackerService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*CustomIssueTrackerService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/custom-issue-tracker", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteCustomIssueTrackerService deletes Custom Issue Tracker service settings for a project. @@ -213,18 +176,12 @@ func (s *ServicesService) SetCustomIssueTrackerService(pid any, opt *SetCustomIs // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-a-custom-issue-tracker func (s *ServicesService) DeleteCustomIssueTrackerService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/custom-issue-tracker", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/custom-issue-tracker", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // DataDogService represents DataDog service settings. @@ -256,24 +213,10 @@ type DataDogServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-datadog-settings func (s *ServicesService) GetDataDogService(pid any, options ...RequestOptionFunc) (*DataDogService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/datadog", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(DataDogService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*DataDogService](s.client, + withPath("projects/%s/integrations/datadog", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetDataDogServiceOptions represents the available SetDataDogService() @@ -298,24 +241,12 @@ type SetDataDogServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-datadog func (s *ServicesService) SetDataDogService(pid any, opt *SetDataDogServiceOptions, options ...RequestOptionFunc) (*DataDogService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/datadog", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(DataDogService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*DataDogService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/datadog", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteDataDogService deletes the DataDog service settings for a project. @@ -323,18 +254,12 @@ func (s *ServicesService) SetDataDogService(pid any, opt *SetDataDogServiceOptio // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-datadog func (s *ServicesService) DeleteDataDogService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/datadog", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/datadog", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // DiscordService represents Discord service settings. @@ -360,24 +285,10 @@ type DiscordServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-discord-notifications-settings func (s *ServicesService) GetDiscordService(pid any, options ...RequestOptionFunc) (*DiscordService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/discord", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(DiscordService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*DiscordService](s.client, + withPath("projects/%s/services/discord", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetDiscordServiceOptions represents the available SetDiscordService() @@ -420,24 +331,12 @@ type SetDiscordServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-discord-notifications func (s *ServicesService) SetDiscordService(pid any, opt *SetDiscordServiceOptions, options ...RequestOptionFunc) (*DiscordService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/discord", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(DiscordService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*DiscordService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/discord", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteDiscordService deletes Discord service settings for a project. @@ -445,18 +344,12 @@ func (s *ServicesService) SetDiscordService(pid any, opt *SetDiscordServiceOptio // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-discord-notifications func (s *ServicesService) DeleteDiscordService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/discord", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/discord", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // DroneCIService represents Drone CI service settings. @@ -482,24 +375,10 @@ type DroneCIServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-drone-settings func (s *ServicesService) GetDroneCIService(pid any, options ...RequestOptionFunc) (*DroneCIService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/drone-ci", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(DroneCIService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*DroneCIService](s.client, + withPath("projects/%s/services/drone-ci", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetDroneCIServiceOptions represents the available SetDroneCIService() @@ -521,24 +400,12 @@ type SetDroneCIServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-drone func (s *ServicesService) SetDroneCIService(pid any, opt *SetDroneCIServiceOptions, options ...RequestOptionFunc) (*DroneCIService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/drone-ci", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(DroneCIService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*DroneCIService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/drone-ci", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteDroneCIService deletes Drone CI service settings for a project. @@ -546,18 +413,12 @@ func (s *ServicesService) SetDroneCIService(pid any, opt *SetDroneCIServiceOptio // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-drone func (s *ServicesService) DeleteDroneCIService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/drone-ci", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/drone-ci", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // EmailsOnPushService represents Emails on Push service settings. @@ -577,9 +438,12 @@ type EmailsOnPushServiceProperties struct { Recipients string `json:"recipients"` DisableDiffs bool `json:"disable_diffs"` SendFromCommitterEmail bool `json:"send_from_committer_email"` - PushEvents bool `json:"push_events"` - TagPushEvents bool `json:"tag_push_events"` BranchesToBeNotified string `json:"branches_to_be_notified"` + + // Deprecated: to be removed in 2.0 - use EmailsOnPushService.PushEvents instead. + PushEvents bool `json:"push_events"` + // Deprecated: to be removed in 2.0 - use EmailsOnPushService.TagPushEvents instead. + TagPushEvents bool `json:"tag_push_events"` } // GetEmailsOnPushService gets Emails on Push service settings for a project. @@ -587,24 +451,10 @@ type EmailsOnPushServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-emails-on-push-settings func (s *ServicesService) GetEmailsOnPushService(pid any, options ...RequestOptionFunc) (*EmailsOnPushService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/emails-on-push", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(EmailsOnPushService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*EmailsOnPushService](s.client, + withPath("projects/%s/integrations/emails-on-push", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetEmailsOnPushServiceOptions represents the available SetEmailsOnPushService() @@ -626,24 +476,12 @@ type SetEmailsOnPushServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-emails-on-push func (s *ServicesService) SetEmailsOnPushService(pid any, opt *SetEmailsOnPushServiceOptions, options ...RequestOptionFunc) (*EmailsOnPushService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/emails-on-push", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(EmailsOnPushService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*EmailsOnPushService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/emails-on-push", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteEmailsOnPushService deletes Emails on Push service settings for a project. @@ -651,18 +489,12 @@ func (s *ServicesService) SetEmailsOnPushService(pid any, opt *SetEmailsOnPushSe // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-emails-on-push func (s *ServicesService) DeleteEmailsOnPushService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/emails-on-push", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/emails-on-push", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // ExternalWikiService represents External Wiki service settings. @@ -687,24 +519,10 @@ type ExternalWikiServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-external-wiki-settings func (s *ServicesService) GetExternalWikiService(pid any, options ...RequestOptionFunc) (*ExternalWikiService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/external-wiki", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(ExternalWikiService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*ExternalWikiService](s.client, + withPath("projects/%s/services/external-wiki", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetExternalWikiServiceOptions represents the available SetExternalWikiService() @@ -721,24 +539,12 @@ type SetExternalWikiServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-an-external-wiki func (s *ServicesService) SetExternalWikiService(pid any, opt *SetExternalWikiServiceOptions, options ...RequestOptionFunc) (*ExternalWikiService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/external-wiki", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(ExternalWikiService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*ExternalWikiService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/external-wiki", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteExternalWikiService deletes External Wiki service for project. @@ -746,18 +552,12 @@ func (s *ServicesService) SetExternalWikiService(pid any, opt *SetExternalWikiSe // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-an-external-wiki func (s *ServicesService) DeleteExternalWikiService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/external-wiki", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/external-wiki", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // GithubService represents Github service settings. @@ -783,24 +583,10 @@ type GithubServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-github-settings func (s *ServicesService) GetGithubService(pid any, options ...RequestOptionFunc) (*GithubService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/github", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(GithubService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*GithubService](s.client, + withPath("projects/%s/services/github", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetGithubServiceOptions represents the available SetGithubService() @@ -819,24 +605,12 @@ type SetGithubServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-github func (s *ServicesService) SetGithubService(pid any, opt *SetGithubServiceOptions, options ...RequestOptionFunc) (*GithubService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/github", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(GithubService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*GithubService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/github", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteGithubService deletes Github service for a project @@ -844,18 +618,12 @@ func (s *ServicesService) SetGithubService(pid any, opt *SetGithubServiceOptions // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-github func (s *ServicesService) DeleteGithubService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/github", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/github", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // HarborService represents the Harbor service settings. @@ -884,24 +652,10 @@ type HarborServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-harbor-settings func (s *ServicesService) GetHarborService(pid any, options ...RequestOptionFunc) (*HarborService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/harbor", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(HarborService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*HarborService](s.client, + withPath("projects/%s/integrations/harbor", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetHarborServiceOptions represents the available SetHarborService() @@ -916,24 +670,12 @@ type SetHarborServiceOptions = SetUpHarborOptions // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-harbor func (s *ServicesService) SetHarborService(pid any, opt *SetHarborServiceOptions, options ...RequestOptionFunc) (*HarborService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/harbor", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(HarborService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*HarborService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/harbor", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteHarborService deletes Harbor service for a project. @@ -941,18 +683,12 @@ func (s *ServicesService) SetHarborService(pid any, opt *SetHarborServiceOptions // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-harbor func (s *ServicesService) DeleteHarborService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/harbor", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/harbor", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // SlackApplication represents GitLab for slack application settings. @@ -998,24 +734,10 @@ type SlackApplicationProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-gitlab-for-slack-app-settings func (s *ServicesService) GetSlackApplication(pid any, options ...RequestOptionFunc) (*SlackApplication, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/gitlab-slack-application", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackApplication) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*SlackApplication](s.client, + withPath("projects/%s/integrations/gitlab-slack-application", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetSlackApplicationOptions represents the available SetSlackApplication() @@ -1066,24 +788,12 @@ type SetSlackApplicationOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-gitlab-for-slack-app func (s *ServicesService) SetSlackApplication(pid any, opt *SetSlackApplicationOptions, options ...RequestOptionFunc) (*SlackApplication, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/gitlab-slack-application", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackApplication) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*SlackApplication](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/gitlab-slack-application", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DisableSlackApplication disable the GitLab for Slack app integration for a project. @@ -1091,18 +801,12 @@ func (s *ServicesService) SetSlackApplication(pid any, opt *SetSlackApplicationO // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-gitlab-for-slack-app func (s *ServicesService) DisableSlackApplication(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/gitlab-slack-application", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/gitlab-slack-application", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // JenkinsCIService represents Jenkins CI service settings. @@ -1130,24 +834,10 @@ type JenkinsCIServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-jenkins-settings func (s *ServicesService) GetJenkinsCIService(pid any, options ...RequestOptionFunc) (*JenkinsCIService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/jenkins", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(JenkinsCIService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*JenkinsCIService](s.client, + withPath("projects/%s/services/jenkins", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetJenkinsCIServiceOptions represents the available SetJenkinsCIService() @@ -1171,24 +861,12 @@ type SetJenkinsCIServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-jenkins func (s *ServicesService) SetJenkinsCIService(pid any, opt *SetJenkinsCIServiceOptions, options ...RequestOptionFunc) (*JenkinsCIService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/jenkins", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(JenkinsCIService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*JenkinsCIService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/jenkins", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteJenkinsCIService deletes Jenkins CI service for project. @@ -1196,18 +874,12 @@ func (s *ServicesService) SetJenkinsCIService(pid any, opt *SetJenkinsCIServiceO // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-jenkins func (s *ServicesService) DeleteJenkinsCIService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/jenkins", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/jenkins", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // JiraService represents Jira service settings. @@ -1229,7 +901,7 @@ type JiraServiceProperties struct { Username string `json:"username" ` Password string `json:"password" ` Active bool `json:"active"` - JiraAuthType int `json:"jira_auth_type"` + JiraAuthType int64 `json:"jira_auth_type"` JiraIssuePrefix string `json:"jira_issue_prefix"` JiraIssueRegex string `json:"jira_issue_regex"` JiraIssueTransitionAutomatic bool `json:"jira_issue_transition_automatic"` @@ -1264,7 +936,7 @@ func (p *JiraServiceProperties) UnmarshalJSON(b []byte) error { case string: p.JiraIssueTransitionID = id case float64: - p.JiraIssueTransitionID = strconv.Itoa(int(id)) + p.JiraIssueTransitionID = strconv.FormatInt(int64(id), 10) default: return fmt.Errorf("failed to unmarshal JiraTransitionID of type: %T", id) } @@ -1277,24 +949,10 @@ func (p *JiraServiceProperties) UnmarshalJSON(b []byte) error { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-jira-settings func (s *ServicesService) GetJiraService(pid any, options ...RequestOptionFunc) (*JiraService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/jira", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(JiraService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*JiraService](s.client, + withPath("projects/%s/integrations/jira", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetJiraServiceOptions represents the available SetJiraService() @@ -1308,7 +966,7 @@ type SetJiraServiceOptions struct { Username *string `url:"username,omitempty" json:"username,omitempty" ` Password *string `url:"password,omitempty" json:"password,omitempty" ` Active *bool `url:"active,omitempty" json:"active,omitempty"` - JiraAuthType *int `url:"jira_auth_type,omitempty" json:"jira_auth_type,omitempty"` + JiraAuthType *int64 `url:"jira_auth_type,omitempty" json:"jira_auth_type,omitempty"` JiraIssuePrefix *string `url:"jira_issue_prefix,omitempty" json:"jira_issue_prefix,omitempty"` JiraIssueRegex *string `url:"jira_issue_regex,omitempty" json:"jira_issue_regex,omitempty"` JiraIssueTransitionAutomatic *bool `url:"jira_issue_transition_automatic,omitempty" json:"jira_issue_transition_automatic,omitempty"` @@ -1326,24 +984,12 @@ type SetJiraServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-jira-issues func (s *ServicesService) SetJiraService(pid any, opt *SetJiraServiceOptions, options ...RequestOptionFunc) (*JiraService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/jira", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(JiraService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*JiraService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/jira", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteJiraService deletes Jira service for project. @@ -1351,18 +997,95 @@ func (s *ServicesService) SetJiraService(pid any, opt *SetJiraServiceOptions, op // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-jira func (s *ServicesService) DeleteJiraService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/jira", PathEscape(project)) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/jira", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err +} - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } +// MatrixService represents Matrix service settings. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#matrix-notifications +type MatrixService struct { + Service + Properties *MatrixServiceProperties `json:"properties"` +} + +// MatrixServiceProperties represents Matrix specific properties. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#matrix-notifications +type MatrixServiceProperties struct { + Hostname string `json:"hostname"` + Token string `json:"token"` + Room string `json:"room"` + NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines"` + BranchesToBeNotified string `json:"branches_to_be_notified"` + UseInheritedSettings BoolValue `json:"use_inherited_settings"` +} + +// GetMatrixService gets Matrix service settings for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#get-matrix-notifications-settings +func (s *ServicesService) GetMatrixService(pid any, options ...RequestOptionFunc) (*MatrixService, *Response, error) { + return do[*MatrixService](s.client, + withMethod(http.MethodGet), + withPath("projects/%s/integrations/matrix", ProjectID{pid}), + withRequestOpts(options...), + ) +} + +// SetMatrixServiceOptions represents the available SetMatrixService() +// options. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#set-up-matrix-notifications +type SetMatrixServiceOptions struct { + Hostname *string `url:"hostname,omitempty" json:"hostname,omitempty"` + Token *string `url:"token,omitempty" json:"token,omitempty"` + Room *string `url:"room,omitempty" json:"room,omitempty"` + NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"` + BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"` + PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"` + IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"` + ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"` + MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"` + TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"` + NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"` + ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"` + PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"` + WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"` + UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"` +} - return s.client.Do(req, nil) +// SetMatrixService sets Matrix service for a project. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#set-up-matrix-notifications +func (s *ServicesService) SetMatrixService(pid any, opt *SetMatrixServiceOptions, options ...RequestOptionFunc) (*MatrixService, *Response, error) { + return do[*MatrixService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/matrix", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} + +// DeleteMatrixService deletes Matrix service for project. +// +// GitLab API docs: +// https://docs.gitlab.com/api/project_integrations/#disable-matrix-notifications +func (s *ServicesService) DeleteMatrixService(pid any, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/matrix", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // MattermostService represents Mattermost service settings. @@ -1401,24 +1124,10 @@ type MattermostServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-mattermost-notifications-settings func (s *ServicesService) GetMattermostService(pid any, options ...RequestOptionFunc) (*MattermostService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(MattermostService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*MattermostService](s.client, + withPath("projects/%s/services/mattermost", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetMattermostServiceOptions represents the available SetMattermostService() @@ -1457,24 +1166,12 @@ type SetMattermostServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-mattermost-notifications func (s *ServicesService) SetMattermostService(pid any, opt *SetMattermostServiceOptions, options ...RequestOptionFunc) (*MattermostService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(MattermostService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*MattermostService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/mattermost", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMattermostService deletes Mattermost service for project. @@ -1482,18 +1179,12 @@ func (s *ServicesService) SetMattermostService(pid any, opt *SetMattermostServic // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-mattermost-notifications func (s *ServicesService) DeleteMattermostService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/mattermost", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // MattermostSlashCommandsService represents Mattermost slash commands settings. @@ -1519,24 +1210,10 @@ type MattermostSlashCommandsProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-mattermost-slash-commands-settings func (s *ServicesService) GetMattermostSlashCommandsService(pid any, options ...RequestOptionFunc) (*MattermostSlashCommandsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(MattermostSlashCommandsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*MattermostSlashCommandsService](s.client, + withPath("projects/%s/services/mattermost-slash-commands", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetMattermostSlashCommandsServiceOptions represents the available SetSlackSlashCommandsService() @@ -1554,24 +1231,12 @@ type SetMattermostSlashCommandsServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-mattermost-slash-commands func (s *ServicesService) SetMattermostSlashCommandsService(pid any, opt *SetMattermostSlashCommandsServiceOptions, options ...RequestOptionFunc) (*MattermostSlashCommandsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(MattermostSlashCommandsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*MattermostSlashCommandsService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/mattermost-slash-commands", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMattermostSlashCommandsService deletes Mattermost slash commands service for project. @@ -1579,18 +1244,12 @@ func (s *ServicesService) SetMattermostSlashCommandsService(pid any, opt *SetMat // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-mattermost-slash-commands func (s *ServicesService) DeleteMattermostSlashCommandsService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/mattermost-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/mattermost-slash-commands", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // MicrosoftTeamsService represents Microsoft Teams service settings. @@ -1625,24 +1284,10 @@ type MicrosoftTeamsServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-microsoft-teams-notifications-settings func (s *ServicesService) GetMicrosoftTeamsService(pid any, options ...RequestOptionFunc) (*MicrosoftTeamsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/microsoft-teams", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(MicrosoftTeamsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*MicrosoftTeamsService](s.client, + withPath("projects/%s/services/microsoft-teams", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetMicrosoftTeamsServiceOptions represents the available SetMicrosoftTeamsService() @@ -1670,24 +1315,12 @@ type SetMicrosoftTeamsServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-microsoft-teams-notifications func (s *ServicesService) SetMicrosoftTeamsService(pid any, opt *SetMicrosoftTeamsServiceOptions, options ...RequestOptionFunc) (*MicrosoftTeamsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/microsoft-teams", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(MicrosoftTeamsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*MicrosoftTeamsService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/microsoft-teams", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteMicrosoftTeamsService deletes Microsoft Teams service for project. @@ -1695,18 +1328,12 @@ func (s *ServicesService) SetMicrosoftTeamsService(pid any, opt *SetMicrosoftTea // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-microsoft-teams-notifications func (s *ServicesService) DeleteMicrosoftTeamsService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/microsoft-teams", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/microsoft-teams", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // PipelinesEmailService represents Pipelines Email service settings. @@ -1734,24 +1361,10 @@ type PipelinesEmailProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-pipeline-status-emails-settings func (s *ServicesService) GetPipelinesEmailService(pid any, options ...RequestOptionFunc) (*PipelinesEmailService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/pipelines-email", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(PipelinesEmailService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*PipelinesEmailService](s.client, + withPath("projects/%s/services/pipelines-email", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetPipelinesEmailServiceOptions represents the available @@ -1773,24 +1386,12 @@ type SetPipelinesEmailServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-pipeline-status-emails func (s *ServicesService) SetPipelinesEmailService(pid any, opt *SetPipelinesEmailServiceOptions, options ...RequestOptionFunc) (*PipelinesEmailService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/pipelines-email", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(PipelinesEmailService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*PipelinesEmailService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/pipelines-email", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeletePipelinesEmailService deletes Pipelines Email service settings for a project. @@ -1798,18 +1399,12 @@ func (s *ServicesService) SetPipelinesEmailService(pid any, opt *SetPipelinesEma // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-pipeline-status-emails func (s *ServicesService) DeletePipelinesEmailService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/pipelines-email", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/pipelines-email", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // RedmineService represents the Redmine service settings. @@ -1837,24 +1432,10 @@ type RedmineServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-redmine-settings func (s *ServicesService) GetRedmineService(pid any, options ...RequestOptionFunc) (*RedmineService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/redmine", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(RedmineService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*RedmineService](s.client, + withPath("projects/%s/integrations/redmine", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetRedmineServiceOptions represents the available SetRedmineService(). @@ -1874,24 +1455,12 @@ type SetRedmineServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-redmine func (s *ServicesService) SetRedmineService(pid any, opt *SetRedmineServiceOptions, options ...RequestOptionFunc) (*RedmineService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/integrations/redmine", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(RedmineService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*RedmineService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/integrations/redmine", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteRedmineService deletes Redmine service for project. @@ -1899,18 +1468,12 @@ func (s *ServicesService) SetRedmineService(pid any, opt *SetRedmineServiceOptio // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-redmine func (s *ServicesService) DeleteRedmineService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/integrations/redmine", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/integrations/redmine", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // SlackService represents Slack service settings. @@ -1952,24 +1515,10 @@ type SlackServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-slack-notifications-settings func (s *ServicesService) GetSlackService(pid any, options ...RequestOptionFunc) (*SlackService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/slack", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*SlackService](s.client, + withPath("projects/%s/services/slack", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetSlackServiceOptions represents the available SetSlackService() @@ -2013,24 +1562,12 @@ type SetSlackServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-slack-notifications func (s *ServicesService) SetSlackService(pid any, opt *SetSlackServiceOptions, options ...RequestOptionFunc) (*SlackService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/slack", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*SlackService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/slack", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteSlackService deletes Slack service for project. @@ -2038,18 +1575,12 @@ func (s *ServicesService) SetSlackService(pid any, opt *SetSlackServiceOptions, // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-slack-notifications func (s *ServicesService) DeleteSlackService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/slack", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/slack", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // SlackSlashCommandsService represents Slack slash commands settings. @@ -2074,24 +1605,10 @@ type SlackSlashCommandsProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-slack-slash-commands-settings func (s *ServicesService) GetSlackSlashCommandsService(pid any, options ...RequestOptionFunc) (*SlackSlashCommandsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/slack-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackSlashCommandsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*SlackSlashCommandsService](s.client, + withPath("projects/%s/services/slack-slash-commands", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetSlackSlashCommandsServiceOptions represents the available SetSlackSlashCommandsService() @@ -2108,24 +1625,12 @@ type SetSlackSlashCommandsServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-slack-slash-commands func (s *ServicesService) SetSlackSlashCommandsService(pid any, opt *SetSlackSlashCommandsServiceOptions, options ...RequestOptionFunc) (*SlackSlashCommandsService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/slack-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(SlackSlashCommandsService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*SlackSlashCommandsService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/slack-slash-commands", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteSlackSlashCommandsService deletes Slack slash commands service for project. @@ -2133,23 +1638,17 @@ func (s *ServicesService) SetSlackSlashCommandsService(pid any, opt *SetSlackSla // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-slack-slash-commands func (s *ServicesService) DeleteSlackSlashCommandsService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/slack-slash-commands", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/slack-slash-commands", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // TelegramService represents Telegram service settings. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#telegram type TelegramService struct { Service @@ -2171,24 +1670,10 @@ type TelegramServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-telegram-settings func (s *ServicesService) GetTelegramService(pid any, options ...RequestOptionFunc) (*TelegramService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/telegram", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(TelegramService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*TelegramService](s.client, + withPath("projects/%s/services/telegram", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetTelegramServiceOptions represents the available SetTelegramService() @@ -2217,24 +1702,12 @@ type SetTelegramServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-telegram func (s *ServicesService) SetTelegramService(pid any, opt *SetTelegramServiceOptions, options ...RequestOptionFunc) (*TelegramService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/telegram", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - svc := new(TelegramService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*TelegramService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/telegram", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteTelegramService deletes Telegram service for project. @@ -2242,18 +1715,12 @@ func (s *ServicesService) SetTelegramService(pid any, opt *SetTelegramServiceOpt // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-telegram func (s *ServicesService) DeleteTelegramService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/telegram", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/telegram", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } // YouTrackService represents YouTrack service settings. @@ -2281,24 +1748,10 @@ type YouTrackServiceProperties struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#get-youtrack-settings func (s *ServicesService) GetYouTrackService(pid any, options ...RequestOptionFunc) (*YouTrackService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/youtrack", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - svc := new(YouTrackService) - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, resp, err - } - - return svc, resp, nil + return do[*YouTrackService](s.client, + withPath("projects/%s/services/youtrack", ProjectID{pid}), + withRequestOpts(options...), + ) } // SetYouTrackServiceOptions represents the available SetYouTrackService() @@ -2318,24 +1771,12 @@ type SetYouTrackServiceOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#set-up-youtrack func (s *ServicesService) SetYouTrackService(pid any, opt *SetYouTrackServiceOptions, options ...RequestOptionFunc) (*YouTrackService, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/services/youtrack", PathEscape(project)) - - svc := new(YouTrackService) - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - resp, err := s.client.Do(req, svc) - if err != nil { - return nil, nil, err - } - - return svc, resp, nil + return do[*YouTrackService](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/services/youtrack", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // DeleteYouTrackService deletes YouTrack service settings for a project. @@ -2343,16 +1784,10 @@ func (s *ServicesService) SetYouTrackService(pid any, opt *SetYouTrackServiceOpt // GitLab API docs: // https://docs.gitlab.com/api/project_integrations/#disable-youtrack func (s *ServicesService) DeleteYouTrackService(pid any, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/services/youtrack", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/services/youtrack", ProjectID{pid}), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/settings.go b/vendor/gitlab.com/gitlab-org/api/client-go/settings.go index 9e7981695..03f16d35b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/settings.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/settings.go @@ -52,7 +52,7 @@ var _ SettingsServiceInterface = (*SettingsService)(nil) // https://gitlab.com/gitlab-org/gitlab/-/blob/v14.9.3-ee/ee/lib/ee/api/helpers/settings_helpers.rb#L10 // https://gitlab.com/gitlab-org/gitlab/-/blob/v14.9.3-ee/ee/app/helpers/ee/application_settings_helper.rb#L20 type Settings struct { - ID int `json:"id"` + ID int64 `json:"id"` AbuseNotificationEmail string `json:"abuse_notification_email"` AdminMode bool `json:"admin_mode"` AfterSignOutPath string `json:"after_sign_out_path"` @@ -67,73 +67,74 @@ type Settings struct { AllowLocalRequestsFromWebHooksAndServices bool `json:"allow_local_requests_from_web_hooks_and_services"` AllowProjectCreationForGuestAndBelow bool `json:"allow_project_creation_for_guest_and_below"` AllowRunnerRegistrationToken bool `json:"allow_runner_registration_token"` + AnonymousSearchesAllowed bool `json:"anonymous_searches_allowed"` ArchiveBuildsInHumanReadable string `json:"archive_builds_in_human_readable"` - ASCIIDocMaxIncludes int `json:"asciidoc_max_includes"` + ASCIIDocMaxIncludes int64 `json:"asciidoc_max_includes"` AssetProxyAllowlist []string `json:"asset_proxy_allowlist"` AssetProxyEnabled bool `json:"asset_proxy_enabled"` AssetProxyURL string `json:"asset_proxy_url"` AssetProxySecretKey string `json:"asset_proxy_secret_key"` AuthorizedKeysEnabled bool `json:"authorized_keys_enabled"` AutoBanUserOnExcessiveProjectsDownload bool `json:"auto_ban_user_on_excessive_projects_download"` - AutocompleteUsers int `json:"autocomplete_users"` - AutocompleteUsersUnauthenticated int `json:"autocomplete_users_unauthenticated"` + AutocompleteUsers int64 `json:"autocomplete_users"` + AutocompleteUsersUnauthenticated int64 `json:"autocomplete_users_unauthenticated"` AutoDevOpsDomain string `json:"auto_devops_domain"` AutoDevOpsEnabled bool `json:"auto_devops_enabled"` AutomaticPurchasedStorageAllocation bool `json:"automatic_purchased_storage_allocation"` - BulkImportConcurrentPipelineBatchLimit int `json:"bulk_import_concurrent_pipeline_batch_limit"` + BulkImportConcurrentPipelineBatchLimit int64 `json:"bulk_import_concurrent_pipeline_batch_limit"` BulkImportEnabled bool `json:"bulk_import_enabled"` - BulkImportMaxDownloadFileSize int `json:"bulk_import_max_download_file_size"` + BulkImportMaxDownloadFileSize int64 `json:"bulk_import_max_download_file_size"` CanCreateGroup bool `json:"can_create_group"` CheckNamespacePlan bool `json:"check_namespace_plan"` CIJobLiveTraceEnabled bool `json:"ci_job_live_trace_enabled"` - CIMaxIncludes int `json:"ci_max_includes"` - CIMaxTotalYAMLSizeBytes int `json:"ci_max_total_yaml_size_bytes"` - CIPartitionsSizeLimit int `json:"ci_partitions_size_limit"` + CIMaxIncludes int64 `json:"ci_max_includes"` + CIMaxTotalYAMLSizeBytes int64 `json:"ci_max_total_yaml_size_bytes"` + CIPartitionsSizeLimit int64 `json:"ci_partitions_size_limit"` CommitEmailHostname string `json:"commit_email_hostname"` - ConcurrentBitbucketImportJobsLimit int `json:"concurrent_bitbucket_import_jobs_limit"` - ConcurrentBitbucketServerImportJobsLimit int `json:"concurrent_bitbucket_server_import_jobs_limit"` - ConcurrentGitHubImportJobsLimit int `json:"concurrent_github_import_jobs_limit"` + ConcurrentBitbucketImportJobsLimit int64 `json:"concurrent_bitbucket_import_jobs_limit"` + ConcurrentBitbucketServerImportJobsLimit int64 `json:"concurrent_bitbucket_server_import_jobs_limit"` + ConcurrentGitHubImportJobsLimit int64 `json:"concurrent_github_import_jobs_limit"` ContainerExpirationPoliciesEnableHistoricEntries bool `json:"container_expiration_policies_enable_historic_entries"` - ContainerRegistryCleanupTagsServiceMaxListSize int `json:"container_registry_cleanup_tags_service_max_list_size"` - ContainerRegistryDeleteTagsServiceTimeout int `json:"container_registry_delete_tags_service_timeout"` + ContainerRegistryCleanupTagsServiceMaxListSize int64 `json:"container_registry_cleanup_tags_service_max_list_size"` + ContainerRegistryDeleteTagsServiceTimeout int64 `json:"container_registry_delete_tags_service_timeout"` ContainerRegistryExpirationPoliciesCaching bool `json:"container_registry_expiration_policies_caching"` - ContainerRegistryExpirationPoliciesWorkerCapacity int `json:"container_registry_expiration_policies_worker_capacity"` + ContainerRegistryExpirationPoliciesWorkerCapacity int64 `json:"container_registry_expiration_policies_worker_capacity"` ContainerRegistryImportCreatedBefore *time.Time `json:"container_registry_import_created_before"` - ContainerRegistryImportMaxRetries int `json:"container_registry_import_max_retries"` - ContainerRegistryImportMaxStepDuration int `json:"container_registry_import_max_step_duration"` - ContainerRegistryImportMaxTagsCount int `json:"container_registry_import_max_tags_count"` - ContainerRegistryImportStartMaxRetries int `json:"container_registry_import_start_max_retries"` + ContainerRegistryImportMaxRetries int64 `json:"container_registry_import_max_retries"` + ContainerRegistryImportMaxStepDuration int64 `json:"container_registry_import_max_step_duration"` + ContainerRegistryImportMaxTagsCount int64 `json:"container_registry_import_max_tags_count"` + ContainerRegistryImportStartMaxRetries int64 `json:"container_registry_import_start_max_retries"` ContainerRegistryImportTargetPlan string `json:"container_registry_import_target_plan"` - ContainerRegistryTokenExpireDelay int `json:"container_registry_token_expire_delay"` + ContainerRegistryTokenExpireDelay int64 `json:"container_registry_token_expire_delay"` CreatedAt *time.Time `json:"created_at"` CustomHTTPCloneURLRoot string `json:"custom_http_clone_url_root"` DNSRebindingProtectionEnabled bool `json:"dns_rebinding_protection_enabled"` - DSAKeyRestriction int `json:"dsa_key_restriction"` + DSAKeyRestriction int64 `json:"dsa_key_restriction"` DeactivateDormantUsers bool `json:"deactivate_dormant_users"` - DeactivateDormantUsersPeriod int `json:"deactivate_dormant_users_period"` - DecompressArchiveFileTimeout int `json:"decompress_archive_file_timeout"` + DeactivateDormantUsersPeriod int64 `json:"deactivate_dormant_users_period"` + DecompressArchiveFileTimeout int64 `json:"decompress_archive_file_timeout"` DefaultArtifactsExpireIn string `json:"default_artifacts_expire_in"` DefaultBranchName string `json:"default_branch_name"` DefaultBranchProtectionDefaults *BranchProtectionDefaults `json:"default_branch_protection_defaults,omitempty"` DefaultCiConfigPath string `json:"default_ci_config_path"` DefaultGroupVisibility VisibilityValue `json:"default_group_visibility"` DefaultPreferredLanguage string `json:"default_preferred_language"` - DefaultProjectCreation int `json:"default_project_creation"` + DefaultProjectCreation int64 `json:"default_project_creation"` DefaultProjectDeletionProtection bool `json:"default_project_deletion_protection"` DefaultProjectVisibility VisibilityValue `json:"default_project_visibility"` - DefaultProjectsLimit int `json:"default_projects_limit"` + DefaultProjectsLimit int64 `json:"default_projects_limit"` DefaultSnippetVisibility VisibilityValue `json:"default_snippet_visibility"` - DefaultSyntaxHighlightingTheme int `json:"default_syntax_highlighting_theme"` + DefaultSyntaxHighlightingTheme int64 `json:"default_syntax_highlighting_theme"` DelayedGroupDeletion bool `json:"delayed_group_deletion"` DelayedProjectDeletion bool `json:"delayed_project_deletion"` DeleteInactiveProjects bool `json:"delete_inactive_projects"` DeleteUnconfirmedUsers bool `json:"delete_unconfirmed_users"` - DeletionAdjournedPeriod int `json:"deletion_adjourned_period"` + DeletionAdjournedPeriod int64 `json:"deletion_adjourned_period"` DiagramsnetEnabled bool `json:"diagramsnet_enabled"` DiagramsnetURL string `json:"diagramsnet_url"` - DiffMaxFiles int `json:"diff_max_files"` - DiffMaxLines int `json:"diff_max_lines"` - DiffMaxPatchBytes int `json:"diff_max_patch_bytes"` + DiffMaxFiles int64 `json:"diff_max_files"` + DiffMaxLines int64 `json:"diff_max_lines"` + DiffMaxPatchBytes int64 `json:"diff_max_patch_bytes"` DisableAdminOAuthScopes bool `json:"disable_admin_oauth_scopes"` DisableFeedToken bool `json:"disable_feed_token"` DisableOverridingApproversPerMergeRequest bool `json:"disable_overriding_approvers_per_merge_request"` @@ -142,16 +143,16 @@ type Settings struct { DomainAllowlist []string `json:"domain_allowlist"` DomainDenylist []string `json:"domain_denylist"` DomainDenylistEnabled bool `json:"domain_denylist_enabled"` - DownstreamPipelineTriggerLimitPerProjectUserSHA int `json:"downstream_pipeline_trigger_limit_per_project_user_sha"` + DownstreamPipelineTriggerLimitPerProjectUserSHA int64 `json:"downstream_pipeline_trigger_limit_per_project_user_sha"` DuoFeaturesEnabled bool `json:"duo_features_enabled"` - ECDSAKeyRestriction int `json:"ecdsa_key_restriction"` - ECDSASKKeyRestriction int `json:"ecdsa_sk_key_restriction"` + ECDSAKeyRestriction int64 `json:"ecdsa_key_restriction"` + ECDSASKKeyRestriction int64 `json:"ecdsa_sk_key_restriction"` EKSAccessKeyID string `json:"eks_access_key_id"` EKSAccountID string `json:"eks_account_id"` EKSIntegrationEnabled bool `json:"eks_integration_enabled"` EKSSecretAccessKey string `json:"eks_secret_access_key"` - Ed25519KeyRestriction int `json:"ed25519_key_restriction"` - Ed25519SKKeyRestriction int `json:"ed25519_sk_key_restriction"` + Ed25519KeyRestriction int64 `json:"ed25519_key_restriction"` + Ed25519SKKeyRestriction int64 `json:"ed25519_sk_key_restriction"` ElasticsearchAWS bool `json:"elasticsearch_aws"` ElasticsearchAWSAccessKey string `json:"elasticsearch_aws_access_key"` ElasticsearchAWSRegion string `json:"elasticsearch_aws_region"` @@ -160,26 +161,26 @@ type Settings struct { ElasticsearchAnalyzersKuromojiSearch bool `json:"elasticsearch_analyzers_kuromoji_search"` ElasticsearchAnalyzersSmartCNEnabled bool `json:"elasticsearch_analyzers_smartcn_enabled"` ElasticsearchAnalyzersSmartCNSearch bool `json:"elasticsearch_analyzers_smartcn_search"` - ElasticsearchClientRequestTimeout int `json:"elasticsearch_client_request_timeout"` - ElasticsearchIndexedFieldLengthLimit int `json:"elasticsearch_indexed_field_length_limit"` - ElasticsearchIndexedFileSizeLimitKB int `json:"elasticsearch_indexed_file_size_limit_kb"` + ElasticsearchClientRequestTimeout int64 `json:"elasticsearch_client_request_timeout"` + ElasticsearchIndexedFieldLengthLimit int64 `json:"elasticsearch_indexed_field_length_limit"` + ElasticsearchIndexedFileSizeLimitKB int64 `json:"elasticsearch_indexed_file_size_limit_kb"` ElasticsearchIndexing bool `json:"elasticsearch_indexing"` ElasticsearchLimitIndexing bool `json:"elasticsearch_limit_indexing"` - ElasticsearchMaxBulkConcurrency int `json:"elasticsearch_max_bulk_concurrency"` - ElasticsearchMaxBulkSizeMB int `json:"elasticsearch_max_bulk_size_mb"` - ElasticsearchMaxCodeIndexingConcurrency int `json:"elasticsearch_max_code_indexing_concurrency"` - ElasticsearchNamespaceIDs []int `json:"elasticsearch_namespace_ids"` + ElasticsearchMaxBulkConcurrency int64 `json:"elasticsearch_max_bulk_concurrency"` + ElasticsearchMaxBulkSizeMB int64 `json:"elasticsearch_max_bulk_size_mb"` + ElasticsearchMaxCodeIndexingConcurrency int64 `json:"elasticsearch_max_code_indexing_concurrency"` + ElasticsearchNamespaceIDs []int64 `json:"elasticsearch_namespace_ids"` ElasticsearchPassword string `json:"elasticsearch_password"` ElasticsearchPauseIndexing bool `json:"elasticsearch_pause_indexing"` - ElasticsearchProjectIDs []int `json:"elasticsearch_project_ids"` - ElasticsearchReplicas int `json:"elasticsearch_replicas"` + ElasticsearchProjectIDs []int64 `json:"elasticsearch_project_ids"` + ElasticsearchReplicas int64 `json:"elasticsearch_replicas"` ElasticsearchRequeueWorkers bool `json:"elasticsearch_requeue_workers"` - ElasticsearchRetryOnFailure int `json:"elasticsearch_retry_on_failure"` + ElasticsearchRetryOnFailure int64 `json:"elasticsearch_retry_on_failure"` ElasticsearchSearch bool `json:"elasticsearch_search"` - ElasticsearchShards int `json:"elasticsearch_shards"` + ElasticsearchShards int64 `json:"elasticsearch_shards"` ElasticsearchURL []string `json:"elasticsearch_url"` ElasticsearchUsername string `json:"elasticsearch_username"` - ElasticsearchWorkerNumberOfShards int `json:"elasticsearch_worker_number_of_shards"` + ElasticsearchWorkerNumberOfShards int64 `json:"elasticsearch_worker_number_of_shards"` EmailAdditionalText string `json:"email_additional_text"` EmailAuthorInBody bool `json:"email_author_in_body"` EmailConfirmationSetting string `json:"email_confirmation_setting"` @@ -199,23 +200,23 @@ type Settings struct { ExternalAuthorizationServiceEnabled bool `json:"external_authorization_service_enabled"` ExternalAuthorizationServiceTimeout float64 `json:"external_authorization_service_timeout"` ExternalAuthorizationServiceURL string `json:"external_authorization_service_url"` - ExternalPipelineValidationServiceTimeout int `json:"external_pipeline_validation_service_timeout"` + ExternalPipelineValidationServiceTimeout int64 `json:"external_pipeline_validation_service_timeout"` ExternalPipelineValidationServiceToken string `json:"external_pipeline_validation_service_token"` ExternalPipelineValidationServiceURL string `json:"external_pipeline_validation_service_url"` - FailedLoginAttemptsUnlockPeriodInMinutes int `json:"failed_login_attempts_unlock_period_in_minutes"` - FileTemplateProjectID int `json:"file_template_project_id"` - FirstDayOfWeek int `json:"first_day_of_week"` + FailedLoginAttemptsUnlockPeriodInMinutes int64 `json:"failed_login_attempts_unlock_period_in_minutes"` + FileTemplateProjectID int64 `json:"file_template_project_id"` + FirstDayOfWeek int64 `json:"first_day_of_week"` FlocEnabled bool `json:"floc_enabled"` GeoNodeAllowedIPs string `json:"geo_node_allowed_ips"` - GeoStatusTimeout int `json:"geo_status_timeout"` - GitRateLimitUsersAlertlist []int `json:"git_rate_limit_users_alertlist"` - GitTwoFactorSessionExpiry int `json:"git_two_factor_session_expiry"` - GitalyTimeoutDefault int `json:"gitaly_timeout_default"` - GitalyTimeoutFast int `json:"gitaly_timeout_fast"` - GitalyTimeoutMedium int `json:"gitaly_timeout_medium"` + GeoStatusTimeout int64 `json:"geo_status_timeout"` + GitRateLimitUsersAlertlist []int64 `json:"git_rate_limit_users_alertlist"` + GitTwoFactorSessionExpiry int64 `json:"git_two_factor_session_expiry"` + GitalyTimeoutDefault int64 `json:"gitaly_timeout_default"` + GitalyTimeoutFast int64 `json:"gitaly_timeout_fast"` + GitalyTimeoutMedium int64 `json:"gitaly_timeout_medium"` GitlabDedicatedInstance bool `json:"gitlab_dedicated_instance"` GitlabEnvironmentToolkitInstance bool `json:"gitlab_environment_toolkit_instance"` - GitlabShellOperationLimit int `json:"gitlab_shell_operation_limit"` + GitlabShellOperationLimit int64 `json:"gitlab_shell_operation_limit"` GitpodEnabled bool `json:"gitpod_enabled"` GitpodURL string `json:"gitpod_url"` GitRateLimitUsersAllowlist []string `json:"git_rate_limit_users_allowlist"` @@ -223,11 +224,11 @@ type Settings struct { GrafanaEnabled bool `json:"grafana_enabled"` GrafanaURL string `json:"grafana_url"` GravatarEnabled bool `json:"gravatar_enabled"` - GroupDownloadExportLimit int `json:"group_download_export_limit"` - GroupExportLimit int `json:"group_export_limit"` - GroupImportLimit int `json:"group_import_limit"` + GroupDownloadExportLimit int64 `json:"group_download_export_limit"` + GroupExportLimit int64 `json:"group_export_limit"` + GroupImportLimit int64 `json:"group_import_limit"` GroupOwnersCanManageDefaultBranchProtection bool `json:"group_owners_can_manage_default_branch_protection"` - GroupRunnerTokenExpirationInterval int `json:"group_runner_token_expiration_interval"` + GroupRunnerTokenExpirationInterval int64 `json:"group_runner_token_expiration_interval"` HTMLEmailsEnabled bool `json:"html_emails_enabled"` HashedStorageEnabled bool `json:"hashed_storage_enabled"` HelpPageDocumentationBaseURL string `json:"help_page_documentation_base_url"` @@ -238,15 +239,16 @@ type Settings struct { HideThirdPartyOffers bool `json:"hide_third_party_offers"` HomePageURL string `json:"home_page_url"` HousekeepingEnabled bool `json:"housekeeping_enabled"` - HousekeepingOptimizeRepositoryPeriod int `json:"housekeeping_optimize_repository_period"` + HousekeepingOptimizeRepositoryPeriod int64 `json:"housekeeping_optimize_repository_period"` ImportSources []string `json:"import_sources"` - InactiveProjectsDeleteAfterMonths int `json:"inactive_projects_delete_after_months"` - InactiveProjectsMinSizeMB int `json:"inactive_projects_min_size_mb"` - InactiveProjectsSendWarningEmailAfterMonths int `json:"inactive_projects_send_warning_email_after_months"` + InactiveProjectsDeleteAfterMonths int64 `json:"inactive_projects_delete_after_months"` + InactiveProjectsMinSizeMB int64 `json:"inactive_projects_min_size_mb"` + InactiveProjectsSendWarningEmailAfterMonths int64 `json:"inactive_projects_send_warning_email_after_months"` + InactiveResourceAccessTokensDeleteAfterDays int64 `json:"inactive_resource_access_tokens_delete_after_days"` IncludeOptionalMetricsInServicePing bool `json:"include_optional_metrics_in_service_ping"` InProductMarketingEmailsEnabled bool `json:"in_product_marketing_emails_enabled"` InvisibleCaptchaEnabled bool `json:"invisible_captcha_enabled"` - IssuesCreateLimit int `json:"issues_create_limit"` + IssuesCreateLimit int64 `json:"issues_create_limit"` JiraConnectApplicationKey string `json:"jira_connect_application_key"` JiraConnectPublicKeyStorageEnabled bool `json:"jira_connect_public_key_storage_enabled"` JiraConnectProxyURL string `json:"jira_connect_proxy_url"` @@ -254,7 +256,7 @@ type Settings struct { KrokiEnabled bool `json:"kroki_enabled"` KrokiFormats map[string]bool `json:"kroki_formats"` KrokiURL string `json:"kroki_url"` - LocalMarkdownVersion int `json:"local_markdown_version"` + LocalMarkdownVersion int64 `json:"local_markdown_version"` LockDuoFeaturesEnabled bool `json:"lock_duo_features_enabled"` LockMembershipsToLDAP bool `json:"lock_memberships_to_ldap"` LoginRecaptchaProtectionEnabled bool `json:"login_recaptcha_protection_enabled"` @@ -263,36 +265,36 @@ type Settings struct { MaintenanceMode bool `json:"maintenance_mode"` MaintenanceModeMessage string `json:"maintenance_mode_message"` MavenPackageRequestsForwarding bool `json:"maven_package_requests_forwarding"` - MaxArtifactsSize int `json:"max_artifacts_size"` - MaxAttachmentSize int `json:"max_attachment_size"` - MaxDecompressedArchiveSize int `json:"max_decompressed_archive_size"` - MaxExportSize int `json:"max_export_size"` - MaxImportRemoteFileSize int `json:"max_import_remote_file_size"` - MaxImportSize int `json:"max_import_size"` - MaxLoginAttempts int `json:"max_login_attempts"` - MaxNumberOfRepositoryDownloads int `json:"max_number_of_repository_downloads"` - MaxNumberOfRepositoryDownloadsWithinTimePeriod int `json:"max_number_of_repository_downloads_within_time_period"` - MaxPagesSize int `json:"max_pages_size"` - MaxPersonalAccessTokenLifetime int `json:"max_personal_access_token_lifetime"` - MaxSSHKeyLifetime int `json:"max_ssh_key_lifetime"` - MaxTerraformStateSizeBytes int `json:"max_terraform_state_size_bytes"` - MaxYAMLDepth int `json:"max_yaml_depth"` - MaxYAMLSizeBytes int `json:"max_yaml_size_bytes"` - MetricsMethodCallThreshold int `json:"metrics_method_call_threshold"` - MinimumPasswordLength int `json:"minimum_password_length"` + MaxArtifactsSize int64 `json:"max_artifacts_size"` + MaxAttachmentSize int64 `json:"max_attachment_size"` + MaxDecompressedArchiveSize int64 `json:"max_decompressed_archive_size"` + MaxExportSize int64 `json:"max_export_size"` + MaxImportRemoteFileSize int64 `json:"max_import_remote_file_size"` + MaxImportSize int64 `json:"max_import_size"` + MaxLoginAttempts int64 `json:"max_login_attempts"` + MaxNumberOfRepositoryDownloads int64 `json:"max_number_of_repository_downloads"` + MaxNumberOfRepositoryDownloadsWithinTimePeriod int64 `json:"max_number_of_repository_downloads_within_time_period"` + MaxPagesSize int64 `json:"max_pages_size"` + MaxPersonalAccessTokenLifetime int64 `json:"max_personal_access_token_lifetime"` + MaxSSHKeyLifetime int64 `json:"max_ssh_key_lifetime"` + MaxTerraformStateSizeBytes int64 `json:"max_terraform_state_size_bytes"` + MaxYAMLDepth int64 `json:"max_yaml_depth"` + MaxYAMLSizeBytes int64 `json:"max_yaml_size_bytes"` + MetricsMethodCallThreshold int64 `json:"metrics_method_call_threshold"` + MinimumPasswordLength int64 `json:"minimum_password_length"` MirrorAvailable bool `json:"mirror_available"` - MirrorCapacityThreshold int `json:"mirror_capacity_threshold"` - MirrorMaxCapacity int `json:"mirror_max_capacity"` - MirrorMaxDelay int `json:"mirror_max_delay"` + MirrorCapacityThreshold int64 `json:"mirror_capacity_threshold"` + MirrorMaxCapacity int64 `json:"mirror_max_capacity"` + MirrorMaxDelay int64 `json:"mirror_max_delay"` NPMPackageRequestsForwarding bool `json:"npm_package_requests_forwarding"` - NotesCreateLimit int `json:"notes_create_limit"` + NotesCreateLimit int64 `json:"notes_create_limit"` NotifyOnUnknownSignIn bool `json:"notify_on_unknown_sign_in"` NugetSkipMetadataURLValidation bool `json:"nuget_skip_metadata_url_validation"` OutboundLocalRequestsAllowlistRaw string `json:"outbound_local_requests_allowlist_raw"` OutboundLocalRequestsWhitelist []string `json:"outbound_local_requests_whitelist"` - PackageMetadataPURLTypes []int `json:"package_metadata_purl_types"` + PackageMetadataPURLTypes []int64 `json:"package_metadata_purl_types"` PackageRegistryAllowAnyoneToPullOption bool `json:"package_registry_allow_anyone_to_pull_option"` - PackageRegistryCleanupPoliciesWorkerCapacity int `json:"package_registry_cleanup_policies_worker_capacity"` + PackageRegistryCleanupPoliciesWorkerCapacity int64 `json:"package_registry_cleanup_policies_worker_capacity"` PagesDomainVerificationEnabled bool `json:"pages_domain_verification_enabled"` PasswordAuthenticationEnabledForGit bool `json:"password_authentication_enabled_for_git"` PasswordAuthenticationEnabledForWeb bool `json:"password_authentication_enabled_for_web"` @@ -302,51 +304,51 @@ type Settings struct { PasswordLowercaseRequired bool `json:"password_lowercase_required"` PerformanceBarAllowedGroupPath string `json:"performance_bar_allowed_group_path"` PersonalAccessTokenPrefix string `json:"personal_access_token_prefix"` - PipelineLimitPerProjectUserSha int `json:"pipeline_limit_per_project_user_sha"` + PipelineLimitPerProjectUserSha int64 `json:"pipeline_limit_per_project_user_sha"` PlantumlEnabled bool `json:"plantuml_enabled"` PlantumlURL string `json:"plantuml_url"` PollingIntervalMultiplier float64 `json:"polling_interval_multiplier,string"` PreventMergeRequestsAuthorApproval bool `json:"prevent_merge_request_author_approval"` PreventMergeRequestsCommittersApproval bool `json:"prevent_merge_request_committers_approval"` - ProjectDownloadExportLimit int `json:"project_download_export_limit"` + ProjectDownloadExportLimit int64 `json:"project_download_export_limit"` ProjectExportEnabled bool `json:"project_export_enabled"` - ProjectExportLimit int `json:"project_export_limit"` - ProjectImportLimit int `json:"project_import_limit"` - ProjectJobsAPIRateLimit int `json:"project_jobs_api_rate_limit"` - ProjectRunnerTokenExpirationInterval int `json:"project_runner_token_expiration_interval"` - ProjectsAPIRateLimitUnauthenticated int `json:"projects_api_rate_limit_unauthenticated"` + ProjectExportLimit int64 `json:"project_export_limit"` + ProjectImportLimit int64 `json:"project_import_limit"` + ProjectJobsAPIRateLimit int64 `json:"project_jobs_api_rate_limit"` + ProjectRunnerTokenExpirationInterval int64 `json:"project_runner_token_expiration_interval"` + ProjectsAPIRateLimitUnauthenticated int64 `json:"projects_api_rate_limit_unauthenticated"` PrometheusMetricsEnabled bool `json:"prometheus_metrics_enabled"` ProtectedCIVariables bool `json:"protected_ci_variables"` PseudonymizerEnabled bool `json:"pseudonymizer_enabled"` - PushEventActivitiesLimit int `json:"push_event_activities_limit"` - PushEventHooksLimit int `json:"push_event_hooks_limit"` + PushEventActivitiesLimit int64 `json:"push_event_activities_limit"` + PushEventHooksLimit int64 `json:"push_event_hooks_limit"` PyPIPackageRequestsForwarding bool `json:"pypi_package_requests_forwarding"` - RSAKeyRestriction int `json:"rsa_key_restriction"` + RSAKeyRestriction int64 `json:"rsa_key_restriction"` RateLimitingResponseText string `json:"rate_limiting_response_text"` - RawBlobRequestLimit int `json:"raw_blob_request_limit"` + RawBlobRequestLimit int64 `json:"raw_blob_request_limit"` RecaptchaEnabled bool `json:"recaptcha_enabled"` RecaptchaPrivateKey string `json:"recaptcha_private_key"` RecaptchaSiteKey string `json:"recaptcha_site_key"` - ReceiveMaxInputSize int `json:"receive_max_input_size"` + ReceiveMaxInputSize int64 `json:"receive_max_input_size"` ReceptiveClusterAgentsEnabled bool `json:"receptive_cluster_agents_enabled"` RememberMeEnabled bool `json:"remember_me_enabled"` RepositoryChecksEnabled bool `json:"repository_checks_enabled"` - RepositorySizeLimit int `json:"repository_size_limit"` + RepositorySizeLimit int64 `json:"repository_size_limit"` RepositoryStorages []string `json:"repository_storages"` - RepositoryStoragesWeighted map[string]int `json:"repository_storages_weighted"` + RepositoryStoragesWeighted map[string]int64 `json:"repository_storages_weighted"` RequireAdminApprovalAfterUserSignup bool `json:"require_admin_approval_after_user_signup"` RequireAdminTwoFactorAuthentication bool `json:"require_admin_two_factor_authentication"` RequirePersonalAccessTokenExpiry bool `json:"require_personal_access_token_expiry"` RequireTwoFactorAuthentication bool `json:"require_two_factor_authentication"` RestrictedVisibilityLevels []VisibilityValue `json:"restricted_visibility_levels"` - RunnerTokenExpirationInterval int `json:"runner_token_expiration_interval"` - SearchRateLimit int `json:"search_rate_limit"` - SearchRateLimitUnauthenticated int `json:"search_rate_limit_unauthenticated"` + RunnerTokenExpirationInterval int64 `json:"runner_token_expiration_interval"` + SearchRateLimit int64 `json:"search_rate_limit"` + SearchRateLimitUnauthenticated int64 `json:"search_rate_limit_unauthenticated"` SecretDetectionRevocationTokenTypesURL string `json:"secret_detection_revocation_token_types_url"` SecretDetectionTokenRevocationEnabled bool `json:"secret_detection_token_revocation_enabled"` SecretDetectionTokenRevocationToken string `json:"secret_detection_token_revocation_token"` SecretDetectionTokenRevocationURL string `json:"secret_detection_token_revocation_url"` - SecurityApprovalPoliciesLimit int `json:"security_approval_policies_limit"` + SecurityApprovalPoliciesLimit int64 `json:"security_approval_policies_limit"` SecurityPolicyGlobalGroupApproversEnabled bool `json:"security_policy_global_group_approvers_enabled"` SecurityTXTContent string `json:"security_txt_content"` SendUserConfirmationEmail bool `json:"send_user_confirmation_email"` @@ -355,12 +357,12 @@ type Settings struct { SentryEnabled bool `json:"sentry_enabled"` SentryEnvironment string `json:"sentry_environment"` ServiceAccessTokensExpirationEnforced bool `json:"service_access_tokens_expiration_enforced"` - SessionExpireDelay int `json:"session_expire_delay"` + SessionExpireDelay int64 `json:"session_expire_delay"` SharedRunnersEnabled bool `json:"shared_runners_enabled"` - SharedRunnersMinutes int `json:"shared_runners_minutes"` + SharedRunnersMinutes int64 `json:"shared_runners_minutes"` SharedRunnersText string `json:"shared_runners_text"` - SidekiqJobLimiterCompressionThresholdBytes int `json:"sidekiq_job_limiter_compression_threshold_bytes"` - SidekiqJobLimiterLimitBytes int `json:"sidekiq_job_limiter_limit_bytes"` + SidekiqJobLimiterCompressionThresholdBytes int64 `json:"sidekiq_job_limiter_compression_threshold_bytes"` + SidekiqJobLimiterLimitBytes int64 `json:"sidekiq_job_limiter_limit_bytes"` SidekiqJobLimiterMode string `json:"sidekiq_job_limiter_mode"` SignInText string `json:"sign_in_text"` SignupEnabled bool `json:"signup_enabled"` @@ -371,7 +373,7 @@ type Settings struct { SlackAppSecret string `json:"slack_app_secret"` SlackAppSigningSecret string `json:"slack_app_signing_secret"` SlackAppVerificationToken string `json:"slack_app_verification_token"` - SnippetSizeLimit int `json:"snippet_size_limit"` + SnippetSizeLimit int64 `json:"snippet_size_limit"` SnowplowAppID string `json:"snowplow_app_id"` SnowplowCollectorHostname string `json:"snowplow_collector_hostname"` SnowplowCookieDomain string `json:"snowplow_cookie_domain"` @@ -386,56 +388,56 @@ type Settings struct { StaticObjectsExternalStorageAuthToken string `json:"static_objects_external_storage_auth_token"` StaticObjectsExternalStorageURL string `json:"static_objects_external_storage_url"` SuggestPipelineEnabled bool `json:"suggest_pipeline_enabled"` - TerminalMaxSessionTime int `json:"terminal_max_session_time"` + TerminalMaxSessionTime int64 `json:"terminal_max_session_time"` Terms string `json:"terms"` ThrottleAuthenticatedAPIEnabled bool `json:"throttle_authenticated_api_enabled"` - ThrottleAuthenticatedAPIPeriodInSeconds int `json:"throttle_authenticated_api_period_in_seconds"` - ThrottleAuthenticatedAPIRequestsPerPeriod int `json:"throttle_authenticated_api_requests_per_period"` + ThrottleAuthenticatedAPIPeriodInSeconds int64 `json:"throttle_authenticated_api_period_in_seconds"` + ThrottleAuthenticatedAPIRequestsPerPeriod int64 `json:"throttle_authenticated_api_requests_per_period"` ThrottleAuthenticatedDeprecatedAPIEnabled bool `json:"throttle_authenticated_deprecated_api_enabled"` - ThrottleAuthenticatedDeprecatedAPIPeriodInSeconds int `json:"throttle_authenticated_deprecated_api_period_in_seconds"` - ThrottleAuthenticatedDeprecatedAPIRequestsPerPeriod int `json:"throttle_authenticated_deprecated_api_requests_per_period"` + ThrottleAuthenticatedDeprecatedAPIPeriodInSeconds int64 `json:"throttle_authenticated_deprecated_api_period_in_seconds"` + ThrottleAuthenticatedDeprecatedAPIRequestsPerPeriod int64 `json:"throttle_authenticated_deprecated_api_requests_per_period"` ThrottleAuthenticatedFilesAPIEnabled bool `json:"throttle_authenticated_files_api_enabled"` - ThrottleAuthenticatedFilesAPIPeriodInSeconds int `json:"throttle_authenticated_files_api_period_in_seconds"` - ThrottleAuthenticatedFilesAPIRequestsPerPeriod int `json:"throttle_authenticated_files_api_requests_per_period"` + ThrottleAuthenticatedFilesAPIPeriodInSeconds int64 `json:"throttle_authenticated_files_api_period_in_seconds"` + ThrottleAuthenticatedFilesAPIRequestsPerPeriod int64 `json:"throttle_authenticated_files_api_requests_per_period"` ThrottleAuthenticatedGitLFSEnabled bool `json:"throttle_authenticated_git_lfs_enabled"` - ThrottleAuthenticatedGitLFSPeriodInSeconds int `json:"throttle_authenticated_git_lfs_period_in_seconds"` - ThrottleAuthenticatedGitLFSRequestsPerPeriod int `json:"throttle_authenticated_git_lfs_requests_per_period"` + ThrottleAuthenticatedGitLFSPeriodInSeconds int64 `json:"throttle_authenticated_git_lfs_period_in_seconds"` + ThrottleAuthenticatedGitLFSRequestsPerPeriod int64 `json:"throttle_authenticated_git_lfs_requests_per_period"` ThrottleAuthenticatedPackagesAPIEnabled bool `json:"throttle_authenticated_packages_api_enabled"` - ThrottleAuthenticatedPackagesAPIPeriodInSeconds int `json:"throttle_authenticated_packages_api_period_in_seconds"` - ThrottleAuthenticatedPackagesAPIRequestsPerPeriod int `json:"throttle_authenticated_packages_api_requests_per_period"` + ThrottleAuthenticatedPackagesAPIPeriodInSeconds int64 `json:"throttle_authenticated_packages_api_period_in_seconds"` + ThrottleAuthenticatedPackagesAPIRequestsPerPeriod int64 `json:"throttle_authenticated_packages_api_requests_per_period"` ThrottleAuthenticatedWebEnabled bool `json:"throttle_authenticated_web_enabled"` - ThrottleAuthenticatedWebPeriodInSeconds int `json:"throttle_authenticated_web_period_in_seconds"` - ThrottleAuthenticatedWebRequestsPerPeriod int `json:"throttle_authenticated_web_requests_per_period"` + ThrottleAuthenticatedWebPeriodInSeconds int64 `json:"throttle_authenticated_web_period_in_seconds"` + ThrottleAuthenticatedWebRequestsPerPeriod int64 `json:"throttle_authenticated_web_requests_per_period"` ThrottleIncidentManagementNotificationEnabled bool `json:"throttle_incident_management_notification_enabled"` - ThrottleIncidentManagementNotificationPerPeriod int `json:"throttle_incident_management_notification_per_period"` - ThrottleIncidentManagementNotificationPeriodInSeconds int `json:"throttle_incident_management_notification_period_in_seconds"` + ThrottleIncidentManagementNotificationPerPeriod int64 `json:"throttle_incident_management_notification_per_period"` + ThrottleIncidentManagementNotificationPeriodInSeconds int64 `json:"throttle_incident_management_notification_period_in_seconds"` ThrottleProtectedPathsEnabled bool `json:"throttle_protected_paths_enabled"` - ThrottleProtectedPathsPeriodInSeconds int `json:"throttle_protected_paths_period_in_seconds"` - ThrottleProtectedPathsRequestsPerPeriod int `json:"throttle_protected_paths_requests_per_period"` + ThrottleProtectedPathsPeriodInSeconds int64 `json:"throttle_protected_paths_period_in_seconds"` + ThrottleProtectedPathsRequestsPerPeriod int64 `json:"throttle_protected_paths_requests_per_period"` ThrottleUnauthenticatedAPIEnabled bool `json:"throttle_unauthenticated_api_enabled"` - ThrottleUnauthenticatedAPIPeriodInSeconds int `json:"throttle_unauthenticated_api_period_in_seconds"` - ThrottleUnauthenticatedAPIRequestsPerPeriod int `json:"throttle_unauthenticated_api_requests_per_period"` + ThrottleUnauthenticatedAPIPeriodInSeconds int64 `json:"throttle_unauthenticated_api_period_in_seconds"` + ThrottleUnauthenticatedAPIRequestsPerPeriod int64 `json:"throttle_unauthenticated_api_requests_per_period"` ThrottleUnauthenticatedDeprecatedAPIEnabled bool `json:"throttle_unauthenticated_deprecated_api_enabled"` - ThrottleUnauthenticatedDeprecatedAPIPeriodInSeconds int `json:"throttle_unauthenticated_deprecated_api_period_in_seconds"` - ThrottleUnauthenticatedDeprecatedAPIRequestsPerPeriod int `json:"throttle_unauthenticated_deprecated_api_requests_per_period"` + ThrottleUnauthenticatedDeprecatedAPIPeriodInSeconds int64 `json:"throttle_unauthenticated_deprecated_api_period_in_seconds"` + ThrottleUnauthenticatedDeprecatedAPIRequestsPerPeriod int64 `json:"throttle_unauthenticated_deprecated_api_requests_per_period"` ThrottleUnauthenticatedFilesAPIEnabled bool `json:"throttle_unauthenticated_files_api_enabled"` - ThrottleUnauthenticatedFilesAPIPeriodInSeconds int `json:"throttle_unauthenticated_files_api_period_in_seconds"` - ThrottleUnauthenticatedFilesAPIRequestsPerPeriod int `json:"throttle_unauthenticated_files_api_requests_per_period"` + ThrottleUnauthenticatedFilesAPIPeriodInSeconds int64 `json:"throttle_unauthenticated_files_api_period_in_seconds"` + ThrottleUnauthenticatedFilesAPIRequestsPerPeriod int64 `json:"throttle_unauthenticated_files_api_requests_per_period"` ThrottleUnauthenticatedGitLFSEnabled bool `json:"throttle_unauthenticated_git_lfs_enabled"` - ThrottleUnauthenticatedGitLFSPeriodInSeconds int `json:"throttle_unauthenticated_git_lfs_period_in_seconds"` - ThrottleUnauthenticatedGitLFSRequestsPerPeriod int `json:"throttle_unauthenticated_git_lfs_requests_per_period"` + ThrottleUnauthenticatedGitLFSPeriodInSeconds int64 `json:"throttle_unauthenticated_git_lfs_period_in_seconds"` + ThrottleUnauthenticatedGitLFSRequestsPerPeriod int64 `json:"throttle_unauthenticated_git_lfs_requests_per_period"` ThrottleUnauthenticatedPackagesAPIEnabled bool `json:"throttle_unauthenticated_packages_api_enabled"` - ThrottleUnauthenticatedPackagesAPIPeriodInSeconds int `json:"throttle_unauthenticated_packages_api_period_in_seconds"` - ThrottleUnauthenticatedPackagesAPIRequestsPerPeriod int `json:"throttle_unauthenticated_packages_api_requests_per_period"` + ThrottleUnauthenticatedPackagesAPIPeriodInSeconds int64 `json:"throttle_unauthenticated_packages_api_period_in_seconds"` + ThrottleUnauthenticatedPackagesAPIRequestsPerPeriod int64 `json:"throttle_unauthenticated_packages_api_requests_per_period"` ThrottleUnauthenticatedWebEnabled bool `json:"throttle_unauthenticated_web_enabled"` - ThrottleUnauthenticatedWebPeriodInSeconds int `json:"throttle_unauthenticated_web_period_in_seconds"` - ThrottleUnauthenticatedWebRequestsPerPeriod int `json:"throttle_unauthenticated_web_requests_per_period"` + ThrottleUnauthenticatedWebPeriodInSeconds int64 `json:"throttle_unauthenticated_web_period_in_seconds"` + ThrottleUnauthenticatedWebRequestsPerPeriod int64 `json:"throttle_unauthenticated_web_requests_per_period"` TimeTrackingLimitToHours bool `json:"time_tracking_limit_to_hours"` - TwoFactorGracePeriod int `json:"two_factor_grace_period"` - UnconfirmedUsersDeleteAfterDays int `json:"unconfirmed_users_delete_after_days"` + TwoFactorGracePeriod int64 `json:"two_factor_grace_period"` + UnconfirmedUsersDeleteAfterDays int64 `json:"unconfirmed_users_delete_after_days"` UniqueIPsLimitEnabled bool `json:"unique_ips_limit_enabled"` - UniqueIPsLimitPerUser int `json:"unique_ips_limit_per_user"` - UniqueIPsLimitTimeWindow int `json:"unique_ips_limit_time_window"` + UniqueIPsLimitPerUser int64 `json:"unique_ips_limit_per_user"` + UniqueIPsLimitTimeWindow int64 `json:"unique_ips_limit_time_window"` UpdateRunnerVersionsEnabled bool `json:"update_runner_versions_enabled"` UpdatedAt *time.Time `json:"updated_at"` UpdatingNameDisabledForUsers bool `json:"updating_name_disabled_for_users"` @@ -448,26 +450,27 @@ type Settings struct { UserDefaultsToPrivateProfile bool `json:"user_defaults_to_private_profile"` UserOauthApplications bool `json:"user_oauth_applications"` UserShowAddSSHKeyMessage bool `json:"user_show_add_ssh_key_message"` - UsersGetByIDLimit int `json:"users_get_by_id_limit"` + UsersGetByIDLimit int64 `json:"users_get_by_id_limit"` UsersGetByIDLimitAllowlistRaw string `json:"users_get_by_id_limit_allowlist_raw"` ValidRunnerRegistrars []string `json:"valid_runner_registrars"` VersionCheckEnabled bool `json:"version_check_enabled"` WebIDEClientsidePreviewEnabled bool `json:"web_ide_clientside_preview_enabled"` WhatsNewVariant string `json:"whats_new_variant"` - WikiPageMaxContentBytes int `json:"wiki_page_max_content_bytes"` + WikiPageMaxContentBytes int64 `json:"wiki_page_max_content_bytes"` + LockMembershipsToSAML bool `json:"lock_memberships_to_saml"` // Deprecated: Use DefaultBranchProtectionDefaults instead. - DefaultBranchProtection int `json:"default_branch_protection"` + DefaultBranchProtection int64 `json:"default_branch_protection"` // Deprecated: Cannot be set through the API, always true HousekeepingBitmapsEnabled bool `json:"housekeeping_bitmaps_enabled"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingFullRepackPeriod int `json:"housekeeping_full_repack_period"` + HousekeepingFullRepackPeriod int64 `json:"housekeeping_full_repack_period"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingGcPeriod int `json:"housekeeping_gc_period"` + HousekeepingGcPeriod int64 `json:"housekeeping_gc_period"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingIncrementalRepackPeriod int `json:"housekeeping_incremental_repack_period"` + HousekeepingIncrementalRepackPeriod int64 `json:"housekeeping_incremental_repack_period"` // Deprecated: use PerformanceBarAllowedGroupPath instead - PerformanceBarAllowedGroupID int `json:"performance_bar_allowed_group_id"` + PerformanceBarAllowedGroupID int64 `json:"performance_bar_allowed_group_id"` // Deprecated: use PerformanceBarAllowedGroupPath: nil instead PerformanceBarEnabled bool `json:"performance_bar_enabled"` // Deprecated: Use AbuseNotificationEmail instead. @@ -479,11 +482,11 @@ type Settings struct { // Deprecated: Use ThrottleUnauthenticatedWebEnabled or ThrottleUnauthenticatedAPIEnabled instead. (Deprecated in GitLab 14.3) ThrottleUnauthenticatedEnabled bool `json:"throttle_unauthenticated_enabled"` // Deprecated: Use ThrottleUnauthenticatedWebPeriodInSeconds or ThrottleUnauthenticatedAPIPeriodInSeconds instead. (Deprecated in GitLab 14.3) - ThrottleUnauthenticatedPeriodInSeconds int `json:"throttle_unauthenticated_period_in_seconds"` + ThrottleUnauthenticatedPeriodInSeconds int64 `json:"throttle_unauthenticated_period_in_seconds"` // Deprecated: Use ThrottleUnauthenticatedWebRequestsPerPeriod or ThrottleUnauthenticatedAPIRequestsPerPeriod instead. (Deprecated in GitLab 14.3) - ThrottleUnauthenticatedRequestsPerPeriod int `json:"throttle_unauthenticated_requests_per_period"` + ThrottleUnauthenticatedRequestsPerPeriod int64 `json:"throttle_unauthenticated_requests_per_period"` // Deprecated: Replaced by SearchRateLimit in GitLab 14.9 (removed in 15.0). - UserEmailLookupLimit int `json:"user_email_lookup_limit"` + UserEmailLookupLimit int64 `json:"user_email_lookup_limit"` } // UnmarshalJSON implements the json.Unmarshaler interface. @@ -521,18 +524,10 @@ func (s Settings) String() string { // GitLab API docs: // https://docs.gitlab.com/api/settings/#get-details-on-current-application-settings func (s *SettingsService) GetSettings(options ...RequestOptionFunc) (*Settings, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "application/settings", nil, options) - if err != nil { - return nil, nil, err - } - - as := new(Settings) - resp, err := s.client.Do(req, as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[*Settings](s.client, + withPath("application/settings"), + withRequestOpts(options...), + ) } // UpdateSettingsOptions represents the available UpdateSettings() options. @@ -554,73 +549,74 @@ type UpdateSettingsOptions struct { AllowLocalRequestsFromWebHooksAndServices *bool `url:"allow_local_requests_from_web_hooks_and_services,omitempty" json:"allow_local_requests_from_web_hooks_and_services,omitempty"` AllowProjectCreationForGuestAndBelow *bool `url:"allow_project_creation_for_guest_and_below,omitempty" json:"allow_project_creation_for_guest_and_below,omitempty"` AllowRunnerRegistrationToken *bool `url:"allow_runner_registration_token,omitempty" json:"allow_runner_registration_token,omitempty"` + AnonymousSearchesAllowed *bool `url:"anonymous_searches_allowed,omitempty" json:"anonymous_searches_allowed,omitempty"` ArchiveBuildsInHumanReadable *string `url:"archive_builds_in_human_readable,omitempty" json:"archive_builds_in_human_readable,omitempty"` - ASCIIDocMaxIncludes *int `url:"asciidoc_max_includes,omitempty" json:"asciidoc_max_includes,omitempty"` + ASCIIDocMaxIncludes *int64 `url:"asciidoc_max_includes,omitempty" json:"asciidoc_max_includes,omitempty"` AssetProxyAllowlist *[]string `url:"asset_proxy_allowlist,omitempty" json:"asset_proxy_allowlist,omitempty"` AssetProxyEnabled *bool `url:"asset_proxy_enabled,omitempty" json:"asset_proxy_enabled,omitempty"` AssetProxySecretKey *string `url:"asset_proxy_secret_key,omitempty" json:"asset_proxy_secret_key,omitempty"` AssetProxyURL *string `url:"asset_proxy_url,omitempty" json:"asset_proxy_url,omitempty"` AuthorizedKeysEnabled *bool `url:"authorized_keys_enabled,omitempty" json:"authorized_keys_enabled,omitempty"` AutoBanUserOnExcessiveProjectsDownload *bool `url:"auto_ban_user_on_excessive_projects_download,omitempty" json:"auto_ban_user_on_excessive_projects_download,omitempty"` - AutocompleteUsers *int `url:"autocomplete_users,omitempty" json:"autocomplete_users,omitempty"` - AutocompleteUsersUnauthenticated *int `url:"autocomplete_users_unauthenticated,omitempty" json:"autocomplete_users_unauthenticated,omitempty"` + AutocompleteUsers *int64 `url:"autocomplete_users,omitempty" json:"autocomplete_users,omitempty"` + AutocompleteUsersUnauthenticated *int64 `url:"autocomplete_users_unauthenticated,omitempty" json:"autocomplete_users_unauthenticated,omitempty"` AutoDevOpsDomain *string `url:"auto_devops_domain,omitempty" json:"auto_devops_domain,omitempty"` AutoDevOpsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"` AutomaticPurchasedStorageAllocation *bool `url:"automatic_purchased_storage_allocation,omitempty" json:"automatic_purchased_storage_allocation,omitempty"` - BulkImportConcurrentPipelineBatchLimit *int `url:"bulk_import_concurrent_pipeline_batch_limit,omitempty" json:"bulk_import_concurrent_pipeline_batch_limit,omitempty"` + BulkImportConcurrentPipelineBatchLimit *int64 `url:"bulk_import_concurrent_pipeline_batch_limit,omitempty" json:"bulk_import_concurrent_pipeline_batch_limit,omitempty"` BulkImportEnabled *bool `url:"bulk_import_enabled,omitempty" json:"bulk_import_enabled,omitempty"` - BulkImportMaxDownloadFileSize *int `url:"bulk_import_max_download_file_size,omitempty" json:"bulk_import_max_download_file_size,omitempty"` + BulkImportMaxDownloadFileSize *int64 `url:"bulk_import_max_download_file_size,omitempty" json:"bulk_import_max_download_file_size,omitempty"` CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"` CanCreateOrganization *bool `url:"can_create_organization,omitempty" json:"can_create_organization,omitempty"` CheckNamespacePlan *bool `url:"check_namespace_plan,omitempty" json:"check_namespace_plan,omitempty"` CIJobLiveTraceEnabled *bool `url:"ci_job_live_trace_enabled,omitempty" json:"ci_job_live_trace_enabled,omitempty"` - CIMaxIncludes *int `url:"ci_max_includes,omitempty" json:"ci_max_includes,omitempty"` - CIMaxTotalYAMLSizeBytes *int `url:"ci_max_total_yaml_size_bytes,omitempty" json:"ci_max_total_yaml_size_bytes,omitempty"` - CIPartitionsSizeLimit *int `url:"ci_partitions_size_limit,omitempty" json:"ci_partitions_size_limit,omitempty"` + CIMaxIncludes *int64 `url:"ci_max_includes,omitempty" json:"ci_max_includes,omitempty"` + CIMaxTotalYAMLSizeBytes *int64 `url:"ci_max_total_yaml_size_bytes,omitempty" json:"ci_max_total_yaml_size_bytes,omitempty"` + CIPartitionsSizeLimit *int64 `url:"ci_partitions_size_limit,omitempty" json:"ci_partitions_size_limit,omitempty"` CommitEmailHostname *string `url:"commit_email_hostname,omitempty" json:"commit_email_hostname,omitempty"` - ConcurrentBitbucketImportJobsLimit *int `url:"concurrent_bitbucket_import_jobs_limit,omitempty" json:"concurrent_bitbucket_import_jobs_limit,omitempty"` - ConcurrentBitbucketServerImportJobsLimit *int `url:"concurrent_bitbucket_server_import_jobs_limit,omitempty" json:"concurrent_bitbucket_server_import_jobs_limit,omitempty"` - ConcurrentGitHubImportJobsLimit *int `url:"concurrent_github_import_jobs_limit,omitempty" json:"concurrent_github_import_jobs_limit,omitempty"` + ConcurrentBitbucketImportJobsLimit *int64 `url:"concurrent_bitbucket_import_jobs_limit,omitempty" json:"concurrent_bitbucket_import_jobs_limit,omitempty"` + ConcurrentBitbucketServerImportJobsLimit *int64 `url:"concurrent_bitbucket_server_import_jobs_limit,omitempty" json:"concurrent_bitbucket_server_import_jobs_limit,omitempty"` + ConcurrentGitHubImportJobsLimit *int64 `url:"concurrent_github_import_jobs_limit,omitempty" json:"concurrent_github_import_jobs_limit,omitempty"` ContainerExpirationPoliciesEnableHistoricEntries *bool `url:"container_expiration_policies_enable_historic_entries,omitempty" json:"container_expiration_policies_enable_historic_entries,omitempty"` - ContainerRegistryCleanupTagsServiceMaxListSize *int `url:"container_registry_cleanup_tags_service_max_list_size,omitempty" json:"container_registry_cleanup_tags_service_max_list_size,omitempty"` - ContainerRegistryDeleteTagsServiceTimeout *int `url:"container_registry_delete_tags_service_timeout,omitempty" json:"container_registry_delete_tags_service_timeout,omitempty"` + ContainerRegistryCleanupTagsServiceMaxListSize *int64 `url:"container_registry_cleanup_tags_service_max_list_size,omitempty" json:"container_registry_cleanup_tags_service_max_list_size,omitempty"` + ContainerRegistryDeleteTagsServiceTimeout *int64 `url:"container_registry_delete_tags_service_timeout,omitempty" json:"container_registry_delete_tags_service_timeout,omitempty"` ContainerRegistryExpirationPoliciesCaching *bool `url:"container_registry_expiration_policies_caching,omitempty" json:"container_registry_expiration_policies_caching,omitempty"` - ContainerRegistryExpirationPoliciesWorkerCapacity *int `url:"container_registry_expiration_policies_worker_capacity,omitempty" json:"container_registry_expiration_policies_worker_capacity,omitempty"` + ContainerRegistryExpirationPoliciesWorkerCapacity *int64 `url:"container_registry_expiration_policies_worker_capacity,omitempty" json:"container_registry_expiration_policies_worker_capacity,omitempty"` ContainerRegistryImportCreatedBefore *time.Time `url:"container_registry_import_created_before,omitempty" json:"container_registry_import_created_before,omitempty"` - ContainerRegistryImportMaxRetries *int `url:"container_registry_import_max_retries,omitempty" json:"container_registry_import_max_retries,omitempty"` - ContainerRegistryImportMaxStepDuration *int `url:"container_registry_import_max_step_duration,omitempty" json:"container_registry_import_max_step_duration,omitempty"` - ContainerRegistryImportMaxTagsCount *int `url:"container_registry_import_max_tags_count,omitempty" json:"container_registry_import_max_tags_count,omitempty"` - ContainerRegistryImportStartMaxRetries *int `url:"container_registry_import_start_max_retries,omitempty" json:"container_registry_import_start_max_retries,omitempty"` + ContainerRegistryImportMaxRetries *int64 `url:"container_registry_import_max_retries,omitempty" json:"container_registry_import_max_retries,omitempty"` + ContainerRegistryImportMaxStepDuration *int64 `url:"container_registry_import_max_step_duration,omitempty" json:"container_registry_import_max_step_duration,omitempty"` + ContainerRegistryImportMaxTagsCount *int64 `url:"container_registry_import_max_tags_count,omitempty" json:"container_registry_import_max_tags_count,omitempty"` + ContainerRegistryImportStartMaxRetries *int64 `url:"container_registry_import_start_max_retries,omitempty" json:"container_registry_import_start_max_retries,omitempty"` ContainerRegistryImportTargetPlan *string `url:"container_registry_import_target_plan,omitempty" json:"container_registry_import_target_plan,omitempty"` - ContainerRegistryTokenExpireDelay *int `url:"container_registry_token_expire_delay,omitempty" json:"container_registry_token_expire_delay,omitempty"` + ContainerRegistryTokenExpireDelay *int64 `url:"container_registry_token_expire_delay,omitempty" json:"container_registry_token_expire_delay,omitempty"` CustomHTTPCloneURLRoot *string `url:"custom_http_clone_url_root,omitempty" json:"custom_http_clone_url_root,omitempty"` DNSRebindingProtectionEnabled *bool `url:"dns_rebinding_protection_enabled,omitempty" json:"dns_rebinding_protection_enabled,omitempty"` - DSAKeyRestriction *int `url:"dsa_key_restriction,omitempty" json:"dsa_key_restriction,omitempty"` + DSAKeyRestriction *int64 `url:"dsa_key_restriction,omitempty" json:"dsa_key_restriction,omitempty"` DeactivateDormantUsers *bool `url:"deactivate_dormant_users,omitempty" json:"deactivate_dormant_users,omitempty"` - DeactivateDormantUsersPeriod *int `url:"deactivate_dormant_users_period,omitempty" json:"deactivate_dormant_users_period,omitempty"` - DecompressArchiveFileTimeout *int `url:"decompress_archive_file_timeout,omitempty" json:"decompress_archive_file_timeout,omitempty"` + DeactivateDormantUsersPeriod *int64 `url:"deactivate_dormant_users_period,omitempty" json:"deactivate_dormant_users_period,omitempty"` + DecompressArchiveFileTimeout *int64 `url:"decompress_archive_file_timeout,omitempty" json:"decompress_archive_file_timeout,omitempty"` DefaultArtifactsExpireIn *string `url:"default_artifacts_expire_in,omitempty" json:"default_artifacts_expire_in,omitempty"` DefaultBranchName *string `url:"default_branch_name,omitempty" json:"default_branch_name,omitempty"` DefaultBranchProtectionDefaults *DefaultBranchProtectionDefaultsOptions `url:"default_branch_protection_defaults,omitempty" json:"default_branch_protection_defaults,omitempty"` DefaultCiConfigPath *string `url:"default_ci_config_path,omitempty" json:"default_ci_config_path,omitempty"` DefaultGroupVisibility *VisibilityValue `url:"default_group_visibility,omitempty" json:"default_group_visibility,omitempty"` DefaultPreferredLanguage *string `url:"default_preferred_language,omitempty" json:"default_preferred_language,omitempty"` - DefaultProjectCreation *int `url:"default_project_creation,omitempty" json:"default_project_creation,omitempty"` + DefaultProjectCreation *int64 `url:"default_project_creation,omitempty" json:"default_project_creation,omitempty"` DefaultProjectDeletionProtection *bool `url:"default_project_deletion_protection,omitempty" json:"default_project_deletion_protection,omitempty"` DefaultProjectVisibility *VisibilityValue `url:"default_project_visibility,omitempty" json:"default_project_visibility,omitempty"` - DefaultProjectsLimit *int `url:"default_projects_limit,omitempty" json:"default_projects_limit,omitempty"` + DefaultProjectsLimit *int64 `url:"default_projects_limit,omitempty" json:"default_projects_limit,omitempty"` DefaultSnippetVisibility *VisibilityValue `url:"default_snippet_visibility,omitempty" json:"default_snippet_visibility,omitempty"` - DefaultSyntaxHighlightingTheme *int `url:"default_syntax_highlighting_theme,omitempty" json:"default_syntax_highlighting_theme,omitempty"` + DefaultSyntaxHighlightingTheme *int64 `url:"default_syntax_highlighting_theme,omitempty" json:"default_syntax_highlighting_theme,omitempty"` DelayedGroupDeletion *bool `url:"delayed_group_deletion,omitempty" json:"delayed_group_deletion,omitempty"` DelayedProjectDeletion *bool `url:"delayed_project_deletion,omitempty" json:"delayed_project_deletion,omitempty"` DeleteInactiveProjects *bool `url:"delete_inactive_projects,omitempty" json:"delete_inactive_projects,omitempty"` DeleteUnconfirmedUsers *bool `url:"delete_unconfirmed_users,omitempty" json:"delete_unconfirmed_users,omitempty"` - DeletionAdjournedPeriod *int `url:"deletion_adjourned_period,omitempty" json:"deletion_adjourned_period,omitempty"` + DeletionAdjournedPeriod *int64 `url:"deletion_adjourned_period,omitempty" json:"deletion_adjourned_period,omitempty"` DiagramsnetEnabled *bool `url:"diagramsnet_enabled,omitempty" json:"diagramsnet_enabled,omitempty"` DiagramsnetURL *string `url:"diagramsnet_url,omitempty" json:"diagramsnet_url,omitempty"` - DiffMaxFiles *int `url:"diff_max_files,omitempty" json:"diff_max_files,omitempty"` - DiffMaxLines *int `url:"diff_max_lines,omitempty" json:"diff_max_lines,omitempty"` - DiffMaxPatchBytes *int `url:"diff_max_patch_bytes,omitempty" json:"diff_max_patch_bytes,omitempty"` + DiffMaxFiles *int64 `url:"diff_max_files,omitempty" json:"diff_max_files,omitempty"` + DiffMaxLines *int64 `url:"diff_max_lines,omitempty" json:"diff_max_lines,omitempty"` + DiffMaxPatchBytes *int64 `url:"diff_max_patch_bytes,omitempty" json:"diff_max_patch_bytes,omitempty"` DisableFeedToken *bool `url:"disable_feed_token,omitempty" json:"disable_feed_token,omitempty"` DisableAdminOAuthScopes *bool `url:"disable_admin_oauth_scopes,omitempty" json:"disable_admin_oauth_scopes,omitempty"` DisableOverridingApproversPerMergeRequest *bool `url:"disable_overriding_approvers_per_merge_request,omitempty" json:"disable_overriding_approvers_per_merge_request,omitempty"` @@ -629,44 +625,44 @@ type UpdateSettingsOptions struct { DomainAllowlist *[]string `url:"domain_allowlist,omitempty" json:"domain_allowlist,omitempty"` DomainDenylist *[]string `url:"domain_denylist,omitempty" json:"domain_denylist,omitempty"` DomainDenylistEnabled *bool `url:"domain_denylist_enabled,omitempty" json:"domain_denylist_enabled,omitempty"` - DownstreamPipelineTriggerLimitPerProjectUserSHA *int `url:"downstream_pipeline_trigger_limit_per_project_user_sha,omitempty" json:"downstream_pipeline_trigger_limit_per_project_user_sha,omitempty"` + DownstreamPipelineTriggerLimitPerProjectUserSHA *int64 `url:"downstream_pipeline_trigger_limit_per_project_user_sha,omitempty" json:"downstream_pipeline_trigger_limit_per_project_user_sha,omitempty"` DuoFeaturesEnabled *bool `url:"duo_features_enabled,omitempty" json:"duo_features_enabled,omitempty"` - ECDSAKeyRestriction *int `url:"ecdsa_key_restriction,omitempty" json:"ecdsa_key_restriction,omitempty"` - ECDSASKKeyRestriction *int `url:"ecdsa_sk_key_restriction,omitempty" json:"ecdsa_sk_key_restriction,omitempty"` + ECDSAKeyRestriction *int64 `url:"ecdsa_key_restriction,omitempty" json:"ecdsa_key_restriction,omitempty"` + ECDSASKKeyRestriction *int64 `url:"ecdsa_sk_key_restriction,omitempty" json:"ecdsa_sk_key_restriction,omitempty"` EKSAccessKeyID *string `url:"eks_access_key_id,omitempty" json:"eks_access_key_id,omitempty"` EKSAccountID *string `url:"eks_account_id,omitempty" json:"eks_account_id,omitempty"` EKSIntegrationEnabled *bool `url:"eks_integration_enabled,omitempty" json:"eks_integration_enabled,omitempty"` EKSSecretAccessKey *string `url:"eks_secret_access_key,omitempty" json:"eks_secret_access_key,omitempty"` - Ed25519KeyRestriction *int `url:"ed25519_key_restriction,omitempty" json:"ed25519_key_restriction,omitempty"` - Ed25519SKKeyRestriction *int `url:"ed25519_sk_key_restriction,omitempty" json:"ed25519_sk_key_restriction,omitempty"` + Ed25519KeyRestriction *int64 `url:"ed25519_key_restriction,omitempty" json:"ed25519_key_restriction,omitempty"` + Ed25519SKKeyRestriction *int64 `url:"ed25519_sk_key_restriction,omitempty" json:"ed25519_sk_key_restriction,omitempty"` ElasticsearchAWS *bool `url:"elasticsearch_aws,omitempty" json:"elasticsearch_aws,omitempty"` ElasticsearchAWSAccessKey *string `url:"elasticsearch_aws_access_key,omitempty" json:"elasticsearch_aws_access_key,omitempty"` ElasticsearchAWSRegion *string `url:"elasticsearch_aws_region,omitempty" json:"elasticsearch_aws_region,omitempty"` ElasticsearchAWSSecretAccessKey *string `url:"elasticsearch_aws_secret_access_key,omitempty" json:"elasticsearch_aws_secret_access_key,omitempty"` ElasticsearchAnalyzersKuromojiEnabled *bool `url:"elasticsearch_analyzers_kuromoji_enabled,omitempty" json:"elasticsearch_analyzers_kuromoji_enabled,omitempty"` - ElasticsearchAnalyzersKuromojiSearch *int `url:"elasticsearch_analyzers_kuromoji_search,omitempty" json:"elasticsearch_analyzers_kuromoji_search,omitempty"` + ElasticsearchAnalyzersKuromojiSearch *int64 `url:"elasticsearch_analyzers_kuromoji_search,omitempty" json:"elasticsearch_analyzers_kuromoji_search,omitempty"` ElasticsearchAnalyzersSmartCNEnabled *bool `url:"elasticsearch_analyzers_smartcn_enabled,omitempty" json:"elasticsearch_analyzers_smartcn_enabled,omitempty"` - ElasticsearchAnalyzersSmartCNSearch *int `url:"elasticsearch_analyzers_smartcn_search,omitempty" json:"elasticsearch_analyzers_smartcn_search,omitempty"` - ElasticsearchClientRequestTimeout *int `url:"elasticsearch_client_request_timeout,omitempty" json:"elasticsearch_client_request_timeout,omitempty"` - ElasticsearchIndexedFieldLengthLimit *int `url:"elasticsearch_indexed_field_length_limit,omitempty" json:"elasticsearch_indexed_field_length_limit,omitempty"` - ElasticsearchIndexedFileSizeLimitKB *int `url:"elasticsearch_indexed_file_size_limit_kb,omitempty" json:"elasticsearch_indexed_file_size_limit_kb,omitempty"` + ElasticsearchAnalyzersSmartCNSearch *int64 `url:"elasticsearch_analyzers_smartcn_search,omitempty" json:"elasticsearch_analyzers_smartcn_search,omitempty"` + ElasticsearchClientRequestTimeout *int64 `url:"elasticsearch_client_request_timeout,omitempty" json:"elasticsearch_client_request_timeout,omitempty"` + ElasticsearchIndexedFieldLengthLimit *int64 `url:"elasticsearch_indexed_field_length_limit,omitempty" json:"elasticsearch_indexed_field_length_limit,omitempty"` + ElasticsearchIndexedFileSizeLimitKB *int64 `url:"elasticsearch_indexed_file_size_limit_kb,omitempty" json:"elasticsearch_indexed_file_size_limit_kb,omitempty"` ElasticsearchIndexing *bool `url:"elasticsearch_indexing,omitempty" json:"elasticsearch_indexing,omitempty"` ElasticsearchLimitIndexing *bool `url:"elasticsearch_limit_indexing,omitempty" json:"elasticsearch_limit_indexing,omitempty"` - ElasticsearchMaxBulkConcurrency *int `url:"elasticsearch_max_bulk_concurrency,omitempty" json:"elasticsearch_max_bulk_concurrency,omitempty"` - ElasticsearchMaxBulkSizeMB *int `url:"elasticsearch_max_bulk_size_mb,omitempty" json:"elasticsearch_max_bulk_size_mb,omitempty"` - ElasticsearchMaxCodeIndexingConcurrency *int `url:"elasticsearch_max_code_indexing_concurrency,omitempty" json:"elasticsearch_max_code_indexing_concurrency,omitempty"` - ElasticsearchNamespaceIDs *[]int `url:"elasticsearch_namespace_ids,omitempty" json:"elasticsearch_namespace_ids,omitempty"` + ElasticsearchMaxBulkConcurrency *int64 `url:"elasticsearch_max_bulk_concurrency,omitempty" json:"elasticsearch_max_bulk_concurrency,omitempty"` + ElasticsearchMaxBulkSizeMB *int64 `url:"elasticsearch_max_bulk_size_mb,omitempty" json:"elasticsearch_max_bulk_size_mb,omitempty"` + ElasticsearchMaxCodeIndexingConcurrency *int64 `url:"elasticsearch_max_code_indexing_concurrency,omitempty" json:"elasticsearch_max_code_indexing_concurrency,omitempty"` + ElasticsearchNamespaceIDs *[]int64 `url:"elasticsearch_namespace_ids,omitempty" json:"elasticsearch_namespace_ids,omitempty"` ElasticsearchPassword *string `url:"elasticsearch_password,omitempty" json:"elasticsearch_password,omitempty"` ElasticsearchPauseIndexing *bool `url:"elasticsearch_pause_indexing,omitempty" json:"elasticsearch_pause_indexing,omitempty"` - ElasticsearchProjectIDs *[]int `url:"elasticsearch_project_ids,omitempty" json:"elasticsearch_project_ids,omitempty"` - ElasticsearchReplicas *int `url:"elasticsearch_replicas,omitempty" json:"elasticsearch_replicas,omitempty"` + ElasticsearchProjectIDs *[]int64 `url:"elasticsearch_project_ids,omitempty" json:"elasticsearch_project_ids,omitempty"` + ElasticsearchReplicas *int64 `url:"elasticsearch_replicas,omitempty" json:"elasticsearch_replicas,omitempty"` ElasticsearchRequeueWorkers *bool `url:"elasticsearch_requeue_workers,omitempty" json:"elasticsearch_requeue_workers,omitempty"` - ElasticsearchRetryOnFailure *int `url:"elasticsearch_retry_on_failure,omitempty" json:"elasticsearch_retry_on_failure,omitempty"` + ElasticsearchRetryOnFailure *int64 `url:"elasticsearch_retry_on_failure,omitempty" json:"elasticsearch_retry_on_failure,omitempty"` ElasticsearchSearch *bool `url:"elasticsearch_search,omitempty" json:"elasticsearch_search,omitempty"` - ElasticsearchShards *int `url:"elasticsearch_shards,omitempty" json:"elasticsearch_shards,omitempty"` + ElasticsearchShards *int64 `url:"elasticsearch_shards,omitempty" json:"elasticsearch_shards,omitempty"` ElasticsearchURL *string `url:"elasticsearch_url,omitempty" json:"elasticsearch_url,omitempty"` ElasticsearchUsername *string `url:"elasticsearch_username,omitempty" json:"elasticsearch_username,omitempty"` - ElasticsearchWorkerNumberOfShards *int `url:"elasticsearch_worker_number_of_shards,omitempty" json:"elasticsearch_worker_number_of_shards,omitempty"` + ElasticsearchWorkerNumberOfShards *int64 `url:"elasticsearch_worker_number_of_shards,omitempty" json:"elasticsearch_worker_number_of_shards,omitempty"` EmailAdditionalText *string `url:"email_additional_text,omitempty" json:"email_additional_text,omitempty"` EmailAuthorInBody *bool `url:"email_author_in_body,omitempty" json:"email_author_in_body,omitempty"` EmailConfirmationSetting *string `url:"email_confirmation_setting,omitempty" json:"email_confirmation_setting,omitempty"` @@ -686,23 +682,23 @@ type UpdateSettingsOptions struct { ExternalAuthorizationServiceEnabled *bool `url:"external_authorization_service_enabled,omitempty" json:"external_authorization_service_enabled,omitempty"` ExternalAuthorizationServiceTimeout *float64 `url:"external_authorization_service_timeout,omitempty" json:"external_authorization_service_timeout,omitempty"` ExternalAuthorizationServiceURL *string `url:"external_authorization_service_url,omitempty" json:"external_authorization_service_url,omitempty"` - ExternalPipelineValidationServiceTimeout *int `url:"external_pipeline_validation_service_timeout,omitempty" json:"external_pipeline_validation_service_timeout,omitempty"` + ExternalPipelineValidationServiceTimeout *int64 `url:"external_pipeline_validation_service_timeout,omitempty" json:"external_pipeline_validation_service_timeout,omitempty"` ExternalPipelineValidationServiceToken *string `url:"external_pipeline_validation_service_token,omitempty" json:"external_pipeline_validation_service_token,omitempty"` ExternalPipelineValidationServiceURL *string `url:"external_pipeline_validation_service_url,omitempty" json:"external_pipeline_validation_service_url,omitempty"` - FailedLoginAttemptsUnlockPeriodInMinutes *int `url:"failed_login_attempts_unlock_period_in_minutes,omitempty" json:"failed_login_attempts_unlock_period_in_minutes,omitempty"` - FileTemplateProjectID *int `url:"file_template_project_id,omitempty" json:"file_template_project_id,omitempty"` - FirstDayOfWeek *int `url:"first_day_of_week,omitempty" json:"first_day_of_week,omitempty"` + FailedLoginAttemptsUnlockPeriodInMinutes *int64 `url:"failed_login_attempts_unlock_period_in_minutes,omitempty" json:"failed_login_attempts_unlock_period_in_minutes,omitempty"` + FileTemplateProjectID *int64 `url:"file_template_project_id,omitempty" json:"file_template_project_id,omitempty"` + FirstDayOfWeek *int64 `url:"first_day_of_week,omitempty" json:"first_day_of_week,omitempty"` FlocEnabled *bool `url:"floc_enabled,omitempty" json:"floc_enabled,omitempty"` GeoNodeAllowedIPs *string `url:"geo_node_allowed_ips,omitempty" json:"geo_node_allowed_ips,omitempty"` - GeoStatusTimeout *int `url:"geo_status_timeout,omitempty" json:"geo_status_timeout,omitempty"` - GitRateLimitUsersAlertlist *[]int `url:"git_rate_limit_users_alertlist,omitempty" json:"git_rate_limit_users_alertlist,omitempty"` - GitTwoFactorSessionExpiry *int `url:"git_two_factor_session_expiry,omitempty" json:"git_two_factor_session_expiry,omitempty"` - GitalyTimeoutDefault *int `url:"gitaly_timeout_default,omitempty" json:"gitaly_timeout_default,omitempty"` - GitalyTimeoutFast *int `url:"gitaly_timeout_fast,omitempty" json:"gitaly_timeout_fast,omitempty"` - GitalyTimeoutMedium *int `url:"gitaly_timeout_medium,omitempty" json:"gitaly_timeout_medium,omitempty"` + GeoStatusTimeout *int64 `url:"geo_status_timeout,omitempty" json:"geo_status_timeout,omitempty"` + GitRateLimitUsersAlertlist *[]int64 `url:"git_rate_limit_users_alertlist,omitempty" json:"git_rate_limit_users_alertlist,omitempty"` + GitTwoFactorSessionExpiry *int64 `url:"git_two_factor_session_expiry,omitempty" json:"git_two_factor_session_expiry,omitempty"` + GitalyTimeoutDefault *int64 `url:"gitaly_timeout_default,omitempty" json:"gitaly_timeout_default,omitempty"` + GitalyTimeoutFast *int64 `url:"gitaly_timeout_fast,omitempty" json:"gitaly_timeout_fast,omitempty"` + GitalyTimeoutMedium *int64 `url:"gitaly_timeout_medium,omitempty" json:"gitaly_timeout_medium,omitempty"` GitlabDedicatedInstance *bool `url:"gitlab_dedicated_instance,omitempty" json:"gitlab_dedicated_instance,omitempty"` GitlabEnvironmentToolkitInstance *bool `url:"gitlab_environment_toolkit_instance,omitempty" json:"gitlab_environment_toolkit_instance,omitempty"` - GitlabShellOperationLimit *int `url:"gitlab_shell_operation_limit,omitempty" json:"gitlab_shell_operation_limit,omitempty"` + GitlabShellOperationLimit *int64 `url:"gitlab_shell_operation_limit,omitempty" json:"gitlab_shell_operation_limit,omitempty"` GitpodEnabled *bool `url:"gitpod_enabled,omitempty" json:"gitpod_enabled,omitempty"` GitpodURL *string `url:"gitpod_url,omitempty" json:"gitpod_url,omitempty"` GitRateLimitUsersAllowlist *[]string `url:"git_rate_limit_users_allowlist,omitempty" json:"git_rate_limit_users_allowlist,omitempty"` @@ -710,11 +706,11 @@ type UpdateSettingsOptions struct { GrafanaEnabled *bool `url:"grafana_enabled,omitempty" json:"grafana_enabled,omitempty"` GrafanaURL *string `url:"grafana_url,omitempty" json:"grafana_url,omitempty"` GravatarEnabled *bool `url:"gravatar_enabled,omitempty" json:"gravatar_enabled,omitempty"` - GroupDownloadExportLimit *int `url:"group_download_export_limit,omitempty" json:"group_download_export_limit,omitempty"` - GroupExportLimit *int `url:"group_export_limit,omitempty" json:"group_export_limit,omitempty"` - GroupImportLimit *int `url:"group_import_limit,omitempty" json:"group_import_limit,omitempty"` + GroupDownloadExportLimit *int64 `url:"group_download_export_limit,omitempty" json:"group_download_export_limit,omitempty"` + GroupExportLimit *int64 `url:"group_export_limit,omitempty" json:"group_export_limit,omitempty"` + GroupImportLimit *int64 `url:"group_import_limit,omitempty" json:"group_import_limit,omitempty"` GroupOwnersCanManageDefaultBranchProtection *bool `url:"group_owners_can_manage_default_branch_protection,omitempty" json:"group_owners_can_manage_default_branch_protection,omitempty"` - GroupRunnerTokenExpirationInterval *int `url:"group_runner_token_expiration_interval,omitempty" json:"group_runner_token_expiration_interval,omitempty"` + GroupRunnerTokenExpirationInterval *int64 `url:"group_runner_token_expiration_interval,omitempty" json:"group_runner_token_expiration_interval,omitempty"` HTMLEmailsEnabled *bool `url:"html_emails_enabled,omitempty" json:"html_emails_enabled,omitempty"` HashedStorageEnabled *bool `url:"hashed_storage_enabled,omitempty" json:"hashed_storage_enabled,omitempty"` HelpPageDocumentationBaseURL *string `url:"help_page_documentation_base_url,omitempty" json:"help_page_documentation_base_url,omitempty"` @@ -725,15 +721,16 @@ type UpdateSettingsOptions struct { HideThirdPartyOffers *bool `url:"hide_third_party_offers,omitempty" json:"hide_third_party_offers,omitempty"` HomePageURL *string `url:"home_page_url,omitempty" json:"home_page_url,omitempty"` HousekeepingEnabled *bool `url:"housekeeping_enabled,omitempty" json:"housekeeping_enabled,omitempty"` - HousekeepingOptimizeRepositoryPeriod *int `url:"housekeeping_optimize_repository_period,omitempty" json:"housekeeping_optimize_repository_period,omitempty"` + HousekeepingOptimizeRepositoryPeriod *int64 `url:"housekeeping_optimize_repository_period,omitempty" json:"housekeeping_optimize_repository_period,omitempty"` ImportSources *[]string `url:"import_sources,omitempty" json:"import_sources,omitempty"` - InactiveProjectsDeleteAfterMonths *int `url:"inactive_projects_delete_after_months,omitempty" json:"inactive_projects_delete_after_months,omitempty"` - InactiveProjectsMinSizeMB *int `url:"inactive_projects_min_size_mb,omitempty" json:"inactive_projects_min_size_mb,omitempty"` - InactiveProjectsSendWarningEmailAfterMonths *int `url:"inactive_projects_send_warning_email_after_months,omitempty" json:"inactive_projects_send_warning_email_after_months,omitempty"` + InactiveProjectsDeleteAfterMonths *int64 `url:"inactive_projects_delete_after_months,omitempty" json:"inactive_projects_delete_after_months,omitempty"` + InactiveProjectsMinSizeMB *int64 `url:"inactive_projects_min_size_mb,omitempty" json:"inactive_projects_min_size_mb,omitempty"` + InactiveProjectsSendWarningEmailAfterMonths *int64 `url:"inactive_projects_send_warning_email_after_months,omitempty" json:"inactive_projects_send_warning_email_after_months,omitempty"` + InactiveResourceAccessTokensDeleteAfterDays *int64 `url:"inactive_resource_access_tokens_delete_after_days,omitempty" json:"inactive_resource_access_tokens_delete_after_days,omitempty"` IncludeOptionalMetricsInServicePing *bool `url:"include_optional_metrics_in_service_ping,omitempty" json:"include_optional_metrics_in_service_ping,omitempty"` InProductMarketingEmailsEnabled *bool `url:"in_product_marketing_emails_enabled,omitempty" json:"in_product_marketing_emails_enabled,omitempty"` InvisibleCaptchaEnabled *bool `url:"invisible_captcha_enabled,omitempty" json:"invisible_captcha_enabled,omitempty"` - IssuesCreateLimit *int `url:"issues_create_limit,omitempty" json:"issues_create_limit,omitempty"` + IssuesCreateLimit *int64 `url:"issues_create_limit,omitempty" json:"issues_create_limit,omitempty"` JiraConnectApplicationKey *string `url:"jira_connect_application_key,omitempty" json:"jira_connect_application_key,omitempty"` JiraConnectPublicKeyStorageEnabled *bool `url:"jira_connect_public_key_storage_enabled,omitempty" json:"jira_connect_public_key_storage_enabled,omitempty"` JiraConnectProxyURL *string `url:"jira_connect_proxy_url,omitempty" json:"jira_connect_proxy_url,omitempty"` @@ -741,7 +738,7 @@ type UpdateSettingsOptions struct { KrokiEnabled *bool `url:"kroki_enabled,omitempty" json:"kroki_enabled,omitempty"` KrokiFormats *map[string]bool `url:"kroki_formats,omitempty" json:"kroki_formats,omitempty"` KrokiURL *string `url:"kroki_url,omitempty" json:"kroki_url,omitempty"` - LocalMarkdownVersion *int `url:"local_markdown_version,omitempty" json:"local_markdown_version,omitempty"` + LocalMarkdownVersion *int64 `url:"local_markdown_version,omitempty" json:"local_markdown_version,omitempty"` LockDuoFeaturesEnabled *bool `url:"lock_duo_features_enabled,omitempty" json:"lock_duo_features_enabled,omitempty"` LockMembershipsToLDAP *bool `url:"lock_memberships_to_ldap,omitempty" json:"lock_memberships_to_ldap,omitempty"` LoginRecaptchaProtectionEnabled *bool `url:"login_recaptcha_protection_enabled,omitempty" json:"login_recaptcha_protection_enabled,omitempty"` @@ -750,36 +747,36 @@ type UpdateSettingsOptions struct { MaintenanceMode *bool `url:"maintenance_mode,omitempty" json:"maintenance_mode,omitempty"` MaintenanceModeMessage *string `url:"maintenance_mode_message,omitempty" json:"maintenance_mode_message,omitempty"` MavenPackageRequestsForwarding *bool `url:"maven_package_requests_forwarding,omitempty" json:"maven_package_requests_forwarding,omitempty"` - MaxArtifactsSize *int `url:"max_artifacts_size,omitempty" json:"max_artifacts_size,omitempty"` - MaxAttachmentSize *int `url:"max_attachment_size,omitempty" json:"max_attachment_size,omitempty"` - MaxDecompressedArchiveSize *int `url:"max_decompressed_archive_size,omitempty" json:"max_decompressed_archive_size,omitempty"` - MaxExportSize *int `url:"max_export_size,omitempty" json:"max_export_size,omitempty"` - MaxImportRemoteFileSize *int `url:"max_import_remote_file_size,omitempty" json:"max_import_remote_file_size,omitempty"` - MaxImportSize *int `url:"max_import_size,omitempty" json:"max_import_size,omitempty"` - MaxLoginAttempts *int `url:"max_login_attempts,omitempty" json:"max_login_attempts,omitempty"` - MaxNumberOfRepositoryDownloads *int `url:"max_number_of_repository_downloads,omitempty" json:"max_number_of_repository_downloads,omitempty"` - MaxNumberOfRepositoryDownloadsWithinTimePeriod *int `url:"max_number_of_repository_downloads_within_time_period,omitempty" json:"max_number_of_repository_downloads_within_time_period,omitempty"` - MaxPagesSize *int `url:"max_pages_size,omitempty" json:"max_pages_size,omitempty"` - MaxPersonalAccessTokenLifetime *int `url:"max_personal_access_token_lifetime,omitempty" json:"max_personal_access_token_lifetime,omitempty"` - MaxSSHKeyLifetime *int `url:"max_ssh_key_lifetime,omitempty" json:"max_ssh_key_lifetime,omitempty"` - MaxTerraformStateSizeBytes *int `url:"max_terraform_state_size_bytes,omitempty" json:"max_terraform_state_size_bytes,omitempty"` - MaxYAMLDepth *int `url:"max_yaml_depth,omitempty" json:"max_yaml_depth,omitempty"` - MaxYAMLSizeBytes *int `url:"max_yaml_size_bytes,omitempty" json:"max_yaml_size_bytes,omitempty"` - MetricsMethodCallThreshold *int `url:"metrics_method_call_threshold,omitempty" json:"metrics_method_call_threshold,omitempty"` - MinimumPasswordLength *int `url:"minimum_password_length,omitempty" json:"minimum_password_length,omitempty"` + MaxArtifactsSize *int64 `url:"max_artifacts_size,omitempty" json:"max_artifacts_size,omitempty"` + MaxAttachmentSize *int64 `url:"max_attachment_size,omitempty" json:"max_attachment_size,omitempty"` + MaxDecompressedArchiveSize *int64 `url:"max_decompressed_archive_size,omitempty" json:"max_decompressed_archive_size,omitempty"` + MaxExportSize *int64 `url:"max_export_size,omitempty" json:"max_export_size,omitempty"` + MaxImportRemoteFileSize *int64 `url:"max_import_remote_file_size,omitempty" json:"max_import_remote_file_size,omitempty"` + MaxImportSize *int64 `url:"max_import_size,omitempty" json:"max_import_size,omitempty"` + MaxLoginAttempts *int64 `url:"max_login_attempts,omitempty" json:"max_login_attempts,omitempty"` + MaxNumberOfRepositoryDownloads *int64 `url:"max_number_of_repository_downloads,omitempty" json:"max_number_of_repository_downloads,omitempty"` + MaxNumberOfRepositoryDownloadsWithinTimePeriod *int64 `url:"max_number_of_repository_downloads_within_time_period,omitempty" json:"max_number_of_repository_downloads_within_time_period,omitempty"` + MaxPagesSize *int64 `url:"max_pages_size,omitempty" json:"max_pages_size,omitempty"` + MaxPersonalAccessTokenLifetime *int64 `url:"max_personal_access_token_lifetime,omitempty" json:"max_personal_access_token_lifetime,omitempty"` + MaxSSHKeyLifetime *int64 `url:"max_ssh_key_lifetime,omitempty" json:"max_ssh_key_lifetime,omitempty"` + MaxTerraformStateSizeBytes *int64 `url:"max_terraform_state_size_bytes,omitempty" json:"max_terraform_state_size_bytes,omitempty"` + MaxYAMLDepth *int64 `url:"max_yaml_depth,omitempty" json:"max_yaml_depth,omitempty"` + MaxYAMLSizeBytes *int64 `url:"max_yaml_size_bytes,omitempty" json:"max_yaml_size_bytes,omitempty"` + MetricsMethodCallThreshold *int64 `url:"metrics_method_call_threshold,omitempty" json:"metrics_method_call_threshold,omitempty"` + MinimumPasswordLength *int64 `url:"minimum_password_length,omitempty" json:"minimum_password_length,omitempty"` MirrorAvailable *bool `url:"mirror_available,omitempty" json:"mirror_available,omitempty"` - MirrorCapacityThreshold *int `url:"mirror_capacity_threshold,omitempty" json:"mirror_capacity_threshold,omitempty"` - MirrorMaxCapacity *int `url:"mirror_max_capacity,omitempty" json:"mirror_max_capacity,omitempty"` - MirrorMaxDelay *int `url:"mirror_max_delay,omitempty" json:"mirror_max_delay,omitempty"` + MirrorCapacityThreshold *int64 `url:"mirror_capacity_threshold,omitempty" json:"mirror_capacity_threshold,omitempty"` + MirrorMaxCapacity *int64 `url:"mirror_max_capacity,omitempty" json:"mirror_max_capacity,omitempty"` + MirrorMaxDelay *int64 `url:"mirror_max_delay,omitempty" json:"mirror_max_delay,omitempty"` NPMPackageRequestsForwarding *bool `url:"npm_package_requests_forwarding,omitempty" json:"npm_package_requests_forwarding,omitempty"` - NotesCreateLimit *int `url:"notes_create_limit,omitempty" json:"notes_create_limit,omitempty"` + NotesCreateLimit *int64 `url:"notes_create_limit,omitempty" json:"notes_create_limit,omitempty"` NotifyOnUnknownSignIn *bool `url:"notify_on_unknown_sign_in,omitempty" json:"notify_on_unknown_sign_in,omitempty"` NugetSkipMetadataURLValidation *bool `url:"nuget_skip_metadata_url_validation,omitempty" json:"nuget_skip_metadata_url_validation,omitempty"` OutboundLocalRequestsAllowlistRaw *string `url:"outbound_local_requests_allowlist_raw,omitempty" json:"outbound_local_requests_allowlist_raw,omitempty"` OutboundLocalRequestsWhitelist *[]string `url:"outbound_local_requests_whitelist,omitempty" json:"outbound_local_requests_whitelist,omitempty"` - PackageMetadataPURLTypes *[]int `url:"package_metadata_purl_types,omitempty" json:"package_metadata_purl_types,omitempty"` + PackageMetadataPURLTypes *[]int64 `url:"package_metadata_purl_types,omitempty" json:"package_metadata_purl_types,omitempty"` PackageRegistryAllowAnyoneToPullOption *bool `url:"package_registry_allow_anyone_to_pull_option,omitempty" json:"package_registry_allow_anyone_to_pull_option,omitempty"` - PackageRegistryCleanupPoliciesWorkerCapacity *int `url:"package_registry_cleanup_policies_worker_capacity,omitempty" json:"package_registry_cleanup_policies_worker_capacity,omitempty"` + PackageRegistryCleanupPoliciesWorkerCapacity *int64 `url:"package_registry_cleanup_policies_worker_capacity,omitempty" json:"package_registry_cleanup_policies_worker_capacity,omitempty"` PagesDomainVerificationEnabled *bool `url:"pages_domain_verification_enabled,omitempty" json:"pages_domain_verification_enabled,omitempty"` PasswordAuthenticationEnabledForGit *bool `url:"password_authentication_enabled_for_git,omitempty" json:"password_authentication_enabled_for_git,omitempty"` PasswordAuthenticationEnabledForWeb *bool `url:"password_authentication_enabled_for_web,omitempty" json:"password_authentication_enabled_for_web,omitempty"` @@ -791,63 +788,63 @@ type UpdateSettingsOptions struct { PersonalAccessTokenPrefix *string `url:"personal_access_token_prefix,omitempty" json:"personal_access_token_prefix,omitempty"` PlantumlEnabled *bool `url:"plantuml_enabled,omitempty" json:"plantuml_enabled,omitempty"` PlantumlURL *string `url:"plantuml_url,omitempty" json:"plantuml_url,omitempty"` - PipelineLimitPerProjectUserSha *int `url:"pipeline_limit_per_project_user_sha,omitempty" json:"pipeline_limit_per_project_user_sha,omitempty"` + PipelineLimitPerProjectUserSha *int64 `url:"pipeline_limit_per_project_user_sha,omitempty" json:"pipeline_limit_per_project_user_sha,omitempty"` PollingIntervalMultiplier *float64 `url:"polling_interval_multiplier,omitempty" json:"polling_interval_multiplier,omitempty"` PreventMergeRequestsAuthorApproval *bool `url:"prevent_merge_requests_author_approval,omitempty" json:"prevent_merge_requests_author_approval,omitempty"` PreventMergeRequestsCommittersApproval *bool `url:"prevent_merge_requests_committers_approval,omitempty" json:"prevent_merge_requests_committers_approval,omitempty"` - ProjectDownloadExportLimit *int `url:"project_download_export_limit,omitempty" json:"project_download_export_limit,omitempty"` + ProjectDownloadExportLimit *int64 `url:"project_download_export_limit,omitempty" json:"project_download_export_limit,omitempty"` ProjectExportEnabled *bool `url:"project_export_enabled,omitempty" json:"project_export_enabled,omitempty"` - ProjectExportLimit *int `url:"project_export_limit,omitempty" json:"project_export_limit,omitempty"` - ProjectImportLimit *int `url:"project_import_limit,omitempty" json:"project_import_limit,omitempty"` - ProjectJobsAPIRateLimit *int `url:"project_jobs_api_rate_limit,omitempty" json:"project_jobs_api_rate_limit,omitempty"` - ProjectRunnerTokenExpirationInterval *int `url:"project_runner_token_expiration_interval,omitempty" json:"project_runner_token_expiration_interval,omitempty"` - ProjectsAPIRateLimitUnauthenticated *int `url:"projects_api_rate_limit_unauthenticated,omitempty" json:"projects_api_rate_limit_unauthenticated,omitempty"` + ProjectExportLimit *int64 `url:"project_export_limit,omitempty" json:"project_export_limit,omitempty"` + ProjectImportLimit *int64 `url:"project_import_limit,omitempty" json:"project_import_limit,omitempty"` + ProjectJobsAPIRateLimit *int64 `url:"project_jobs_api_rate_limit,omitempty" json:"project_jobs_api_rate_limit,omitempty"` + ProjectRunnerTokenExpirationInterval *int64 `url:"project_runner_token_expiration_interval,omitempty" json:"project_runner_token_expiration_interval,omitempty"` + ProjectsAPIRateLimitUnauthenticated *int64 `url:"projects_api_rate_limit_unauthenticated,omitempty" json:"projects_api_rate_limit_unauthenticated,omitempty"` PrometheusMetricsEnabled *bool `url:"prometheus_metrics_enabled,omitempty" json:"prometheus_metrics_enabled,omitempty"` ProtectedCIVariables *bool `url:"protected_ci_variables,omitempty" json:"protected_ci_variables,omitempty"` PseudonymizerEnabled *bool `url:"pseudonymizer_enabled,omitempty" json:"pseudonymizer_enabled,omitempty"` - PushEventActivitiesLimit *int `url:"push_event_activities_limit,omitempty" json:"push_event_activities_limit,omitempty"` - PushEventHooksLimit *int `url:"push_event_hooks_limit,omitempty" json:"push_event_hooks_limit,omitempty"` + PushEventActivitiesLimit *int64 `url:"push_event_activities_limit,omitempty" json:"push_event_activities_limit,omitempty"` + PushEventHooksLimit *int64 `url:"push_event_hooks_limit,omitempty" json:"push_event_hooks_limit,omitempty"` PyPIPackageRequestsForwarding *bool `url:"pypi_package_requests_forwarding,omitempty" json:"pypi_package_requests_forwarding,omitempty"` - RSAKeyRestriction *int `url:"rsa_key_restriction,omitempty" json:"rsa_key_restriction,omitempty"` + RSAKeyRestriction *int64 `url:"rsa_key_restriction,omitempty" json:"rsa_key_restriction,omitempty"` RateLimitingResponseText *string `url:"rate_limiting_response_text,omitempty" json:"rate_limiting_response_text,omitempty"` - RawBlobRequestLimit *int `url:"raw_blob_request_limit,omitempty" json:"raw_blob_request_limit,omitempty"` + RawBlobRequestLimit *int64 `url:"raw_blob_request_limit,omitempty" json:"raw_blob_request_limit,omitempty"` RecaptchaEnabled *bool `url:"recaptcha_enabled,omitempty" json:"recaptcha_enabled,omitempty"` RecaptchaPrivateKey *string `url:"recaptcha_private_key,omitempty" json:"recaptcha_private_key,omitempty"` RecaptchaSiteKey *string `url:"recaptcha_site_key,omitempty" json:"recaptcha_site_key,omitempty"` - ReceiveMaxInputSize *int `url:"receive_max_input_size,omitempty" json:"receive_max_input_size,omitempty"` + ReceiveMaxInputSize *int64 `url:"receive_max_input_size,omitempty" json:"receive_max_input_size,omitempty"` ReceptiveClusterAgentsEnabled *bool `url:"receptive_cluster_agents_enabled,omitempty" json:"receptive_cluster_agents_enabled,omitempty"` RememberMeEnabled *bool `url:"remember_me_enabled,omitempty" json:"remember_me_enabled,omitempty"` RepositoryChecksEnabled *bool `url:"repository_checks_enabled,omitempty" json:"repository_checks_enabled,omitempty"` - RepositorySizeLimit *int `url:"repository_size_limit,omitempty" json:"repository_size_limit,omitempty"` + RepositorySizeLimit *int64 `url:"repository_size_limit,omitempty" json:"repository_size_limit,omitempty"` RepositoryStorages *[]string `url:"repository_storages,omitempty" json:"repository_storages,omitempty"` - RepositoryStoragesWeighted *map[string]int `url:"repository_storages_weighted,omitempty" json:"repository_storages_weighted,omitempty"` + RepositoryStoragesWeighted *map[string]int64 `url:"repository_storages_weighted,omitempty" json:"repository_storages_weighted,omitempty"` RequireAdminApprovalAfterUserSignup *bool `url:"require_admin_approval_after_user_signup,omitempty" json:"require_admin_approval_after_user_signup,omitempty"` RequireAdminTwoFactorAuthentication *bool `url:"require_admin_two_factor_authentication,omitempty" json:"require_admin_two_factor_authentication,omitempty"` RequirePersonalAccessTokenExpiry *bool `url:"require_personal_access_token_expiry,omitempty" json:"require_personal_access_token_expiry,omitempty"` RequireTwoFactorAuthentication *bool `url:"require_two_factor_authentication,omitempty" json:"require_two_factor_authentication,omitempty"` RestrictedVisibilityLevels *[]VisibilityValue `url:"restricted_visibility_levels,omitempty" json:"restricted_visibility_levels,omitempty"` - RunnerTokenExpirationInterval *int `url:"runner_token_expiration_interval,omitempty" json:"runner_token_expiration_interval,omitempty"` - SearchRateLimit *int `url:"search_rate_limit,omitempty" json:"search_rate_limit,omitempty"` - SearchRateLimitUnauthenticated *int `url:"search_rate_limit_unauthenticated,omitempty" json:"search_rate_limit_unauthenticated,omitempty"` + RunnerTokenExpirationInterval *int64 `url:"runner_token_expiration_interval,omitempty" json:"runner_token_expiration_interval,omitempty"` + SearchRateLimit *int64 `url:"search_rate_limit,omitempty" json:"search_rate_limit,omitempty"` + SearchRateLimitUnauthenticated *int64 `url:"search_rate_limit_unauthenticated,omitempty" json:"search_rate_limit_unauthenticated,omitempty"` SecretDetectionRevocationTokenTypesURL *string `url:"secret_detection_revocation_token_types_url,omitempty" json:"secret_detection_revocation_token_types_url,omitempty"` SecretDetectionTokenRevocationEnabled *bool `url:"secret_detection_token_revocation_enabled,omitempty" json:"secret_detection_token_revocation_enabled,omitempty"` SecretDetectionTokenRevocationToken *string `url:"secret_detection_token_revocation_token,omitempty" json:"secret_detection_token_revocation_token,omitempty"` SecretDetectionTokenRevocationURL *string `url:"secret_detection_token_revocation_url,omitempty" json:"secret_detection_token_revocation_url,omitempty"` - SecurityApprovalPoliciesLimit *int `url:"security_approval_policies_limit,omitempty" json:"security_approval_policies_limit,omitempty"` + SecurityApprovalPoliciesLimit *int64 `url:"security_approval_policies_limit,omitempty" json:"security_approval_policies_limit,omitempty"` SecurityPolicyGlobalGroupApproversEnabled *bool `url:"security_policy_global_group_approvers_enabled,omitempty" json:"security_policy_global_group_approvers_enabled,omitempty"` SecurityTXTContent *string `url:"security_txt_content,omitempty" json:"security_txt_content,omitempty"` SendUserConfirmationEmail *bool `url:"send_user_confirmation_email,omitempty" json:"send_user_confirmation_email,omitempty"` SentryClientsideDSN *string `url:"sentry_clientside_dsn,omitempty" json:"sentry_clientside_dsn,omitempty"` SentryDSN *string `url:"sentry_dsn,omitempty" json:"sentry_dsn,omitempty"` - SentryEnabled *string `url:"sentry_enabled,omitempty" json:"sentry_enabled,omitempty"` + SentryEnabled *bool `url:"sentry_enabled,omitempty" json:"sentry_enabled,omitempty"` SentryEnvironment *string `url:"sentry_environment,omitempty" json:"sentry_environment,omitempty"` ServiceAccessTokensExpirationEnforced *bool `url:"service_access_tokens_expiration_enforced,omitempty" json:"service_access_tokens_expiration_enforced,omitempty"` - SessionExpireDelay *int `url:"session_expire_delay,omitempty" json:"session_expire_delay,omitempty"` + SessionExpireDelay *int64 `url:"session_expire_delay,omitempty" json:"session_expire_delay,omitempty"` SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"` - SharedRunnersMinutes *int `url:"shared_runners_minutes,omitempty" json:"shared_runners_minutes,omitempty"` + SharedRunnersMinutes *int64 `url:"shared_runners_minutes,omitempty" json:"shared_runners_minutes,omitempty"` SharedRunnersText *string `url:"shared_runners_text,omitempty" json:"shared_runners_text,omitempty"` - SidekiqJobLimiterCompressionThresholdBytes *int `url:"sidekiq_job_limiter_compression_threshold_bytes,omitempty" json:"sidekiq_job_limiter_compression_threshold_bytes,omitempty"` - SidekiqJobLimiterLimitBytes *int `url:"sidekiq_job_limiter_limit_bytes,omitempty" json:"sidekiq_job_limiter_limit_bytes,omitempty"` + SidekiqJobLimiterCompressionThresholdBytes *int64 `url:"sidekiq_job_limiter_compression_threshold_bytes,omitempty" json:"sidekiq_job_limiter_compression_threshold_bytes,omitempty"` + SidekiqJobLimiterLimitBytes *int64 `url:"sidekiq_job_limiter_limit_bytes,omitempty" json:"sidekiq_job_limiter_limit_bytes,omitempty"` SidekiqJobLimiterMode *string `url:"sidekiq_job_limiter_mode,omitempty" json:"sidekiq_job_limiter_mode,omitempty"` SignInText *string `url:"sign_in_text,omitempty" json:"sign_in_text,omitempty"` SignupEnabled *bool `url:"signup_enabled,omitempty" json:"signup_enabled,omitempty"` @@ -858,7 +855,7 @@ type UpdateSettingsOptions struct { SlackAppSecret *string `url:"slack_app_secret,omitempty" json:"slack_app_secret,omitempty"` SlackAppSigningSecret *string `url:"slack_app_signing_secret,omitempty" json:"slack_app_signing_secret,omitempty"` SlackAppVerificationToken *string `url:"slack_app_verification_token,omitempty" json:"slack_app_verification_token,omitempty"` - SnippetSizeLimit *int `url:"snippet_size_limit,omitempty" json:"snippet_size_limit,omitempty"` + SnippetSizeLimit *int64 `url:"snippet_size_limit,omitempty" json:"snippet_size_limit,omitempty"` SnowplowAppID *string `url:"snowplow_app_id,omitempty" json:"snowplow_app_id,omitempty"` SnowplowCollectorHostname *string `url:"snowplow_collector_hostname,omitempty" json:"snowplow_collector_hostname,omitempty"` SnowplowCookieDomain *string `url:"snowplow_cookie_domain,omitempty" json:"snowplow_cookie_domain,omitempty"` @@ -873,56 +870,56 @@ type UpdateSettingsOptions struct { StaticObjectsExternalStorageAuthToken *string `url:"static_objects_external_storage_auth_token,omitempty" json:"static_objects_external_storage_auth_token,omitempty"` StaticObjectsExternalStorageURL *string `url:"static_objects_external_storage_url,omitempty" json:"static_objects_external_storage_url,omitempty"` SuggestPipelineEnabled *bool `url:"suggest_pipeline_enabled,omitempty" json:"suggest_pipeline_enabled,omitempty"` - TerminalMaxSessionTime *int `url:"terminal_max_session_time,omitempty" json:"terminal_max_session_time,omitempty"` + TerminalMaxSessionTime *int64 `url:"terminal_max_session_time,omitempty" json:"terminal_max_session_time,omitempty"` Terms *string `url:"terms,omitempty" json:"terms,omitempty"` ThrottleAuthenticatedAPIEnabled *bool `url:"throttle_authenticated_api_enabled,omitempty" json:"throttle_authenticated_api_enabled,omitempty"` - ThrottleAuthenticatedAPIPeriodInSeconds *int `url:"throttle_authenticated_api_period_in_seconds,omitempty" json:"throttle_authenticated_api_period_in_seconds,omitempty"` - ThrottleAuthenticatedAPIRequestsPerPeriod *int `url:"throttle_authenticated_api_requests_per_period,omitempty" json:"throttle_authenticated_api_requests_per_period,omitempty"` + ThrottleAuthenticatedAPIPeriodInSeconds *int64 `url:"throttle_authenticated_api_period_in_seconds,omitempty" json:"throttle_authenticated_api_period_in_seconds,omitempty"` + ThrottleAuthenticatedAPIRequestsPerPeriod *int64 `url:"throttle_authenticated_api_requests_per_period,omitempty" json:"throttle_authenticated_api_requests_per_period,omitempty"` ThrottleAuthenticatedDeprecatedAPIEnabled *bool `url:"throttle_authenticated_deprecated_api_enabled,omitempty" json:"throttle_authenticated_deprecated_api_enabled,omitempty"` - ThrottleAuthenticatedDeprecatedAPIPeriodInSeconds *int `url:"throttle_authenticated_deprecated_api_period_in_seconds,omitempty" json:"throttle_authenticated_deprecated_api_period_in_seconds,omitempty"` - ThrottleAuthenticatedDeprecatedAPIRequestsPerPeriod *int `url:"throttle_authenticated_deprecated_api_requests_per_period,omitempty" json:"throttle_authenticated_deprecated_api_requests_per_period,omitempty"` + ThrottleAuthenticatedDeprecatedAPIPeriodInSeconds *int64 `url:"throttle_authenticated_deprecated_api_period_in_seconds,omitempty" json:"throttle_authenticated_deprecated_api_period_in_seconds,omitempty"` + ThrottleAuthenticatedDeprecatedAPIRequestsPerPeriod *int64 `url:"throttle_authenticated_deprecated_api_requests_per_period,omitempty" json:"throttle_authenticated_deprecated_api_requests_per_period,omitempty"` ThrottleAuthenticatedFilesAPIEnabled *bool `url:"throttle_authenticated_files_api_enabled,omitempty" json:"throttle_authenticated_files_api_enabled,omitempty"` - ThrottleAuthenticatedFilesAPIPeriodInSeconds *int `url:"throttle_authenticated_files_api_period_in_seconds,omitempty" json:"throttle_authenticated_files_api_period_in_seconds,omitempty"` - ThrottleAuthenticatedFilesAPIRequestsPerPeriod *int `url:"throttle_authenticated_files_api_requests_per_period,omitempty" json:"throttle_authenticated_files_api_requests_per_period,omitempty"` + ThrottleAuthenticatedFilesAPIPeriodInSeconds *int64 `url:"throttle_authenticated_files_api_period_in_seconds,omitempty" json:"throttle_authenticated_files_api_period_in_seconds,omitempty"` + ThrottleAuthenticatedFilesAPIRequestsPerPeriod *int64 `url:"throttle_authenticated_files_api_requests_per_period,omitempty" json:"throttle_authenticated_files_api_requests_per_period,omitempty"` ThrottleAuthenticatedGitLFSEnabled *bool `url:"throttle_authenticated_git_lfs_enabled,omitempty" json:"throttle_authenticated_git_lfs_enabled,omitempty"` - ThrottleAuthenticatedGitLFSPeriodInSeconds *int `url:"throttle_authenticated_git_lfs_period_in_seconds,omitempty" json:"throttle_authenticated_git_lfs_period_in_seconds,omitempty"` - ThrottleAuthenticatedGitLFSRequestsPerPeriod *int `url:"throttle_authenticated_git_lfs_requests_per_period,omitempty" json:"throttle_authenticated_git_lfs_requests_per_period,omitempty"` + ThrottleAuthenticatedGitLFSPeriodInSeconds *int64 `url:"throttle_authenticated_git_lfs_period_in_seconds,omitempty" json:"throttle_authenticated_git_lfs_period_in_seconds,omitempty"` + ThrottleAuthenticatedGitLFSRequestsPerPeriod *int64 `url:"throttle_authenticated_git_lfs_requests_per_period,omitempty" json:"throttle_authenticated_git_lfs_requests_per_period,omitempty"` ThrottleAuthenticatedPackagesAPIEnabled *bool `url:"throttle_authenticated_packages_api_enabled,omitempty" json:"throttle_authenticated_packages_api_enabled,omitempty"` - ThrottleAuthenticatedPackagesAPIPeriodInSeconds *int `url:"throttle_authenticated_packages_api_period_in_seconds,omitempty" json:"throttle_authenticated_packages_api_period_in_seconds,omitempty"` - ThrottleAuthenticatedPackagesAPIRequestsPerPeriod *int `url:"throttle_authenticated_packages_api_requests_per_period,omitempty" json:"throttle_authenticated_packages_api_requests_per_period,omitempty"` + ThrottleAuthenticatedPackagesAPIPeriodInSeconds *int64 `url:"throttle_authenticated_packages_api_period_in_seconds,omitempty" json:"throttle_authenticated_packages_api_period_in_seconds,omitempty"` + ThrottleAuthenticatedPackagesAPIRequestsPerPeriod *int64 `url:"throttle_authenticated_packages_api_requests_per_period,omitempty" json:"throttle_authenticated_packages_api_requests_per_period,omitempty"` ThrottleAuthenticatedWebEnabled *bool `url:"throttle_authenticated_web_enabled,omitempty" json:"throttle_authenticated_web_enabled,omitempty"` - ThrottleAuthenticatedWebPeriodInSeconds *int `url:"throttle_authenticated_web_period_in_seconds,omitempty" json:"throttle_authenticated_web_period_in_seconds,omitempty"` - ThrottleAuthenticatedWebRequestsPerPeriod *int `url:"throttle_authenticated_web_requests_per_period,omitempty" json:"throttle_authenticated_web_requests_per_period,omitempty"` + ThrottleAuthenticatedWebPeriodInSeconds *int64 `url:"throttle_authenticated_web_period_in_seconds,omitempty" json:"throttle_authenticated_web_period_in_seconds,omitempty"` + ThrottleAuthenticatedWebRequestsPerPeriod *int64 `url:"throttle_authenticated_web_requests_per_period,omitempty" json:"throttle_authenticated_web_requests_per_period,omitempty"` ThrottleIncidentManagementNotificationEnabled *bool `url:"throttle_incident_management_notification_enabled,omitempty" json:"throttle_incident_management_notification_enabled,omitempty"` - ThrottleIncidentManagementNotificationPerPeriod *int `url:"throttle_incident_management_notification_per_period,omitempty" json:"throttle_incident_management_notification_per_period,omitempty"` - ThrottleIncidentManagementNotificationPeriodInSeconds *int `url:"throttle_incident_management_notification_period_in_seconds,omitempty" json:"throttle_incident_management_notification_period_in_seconds,omitempty"` - ThrottleProtectedPathsEnabled *bool `url:"throttle_protected_paths_enabled_enabled,omitempty" json:"throttle_protected_paths_enabled,omitempty"` - ThrottleProtectedPathsPeriodInSeconds *int `url:"throttle_protected_paths_enabled_period_in_seconds,omitempty" json:"throttle_protected_paths_period_in_seconds,omitempty"` - ThrottleProtectedPathsRequestsPerPeriod *int `url:"throttle_protected_paths_enabled_requests_per_period,omitempty" json:"throttle_protected_paths_per_period,omitempty"` + ThrottleIncidentManagementNotificationPerPeriod *int64 `url:"throttle_incident_management_notification_per_period,omitempty" json:"throttle_incident_management_notification_per_period,omitempty"` + ThrottleIncidentManagementNotificationPeriodInSeconds *int64 `url:"throttle_incident_management_notification_period_in_seconds,omitempty" json:"throttle_incident_management_notification_period_in_seconds,omitempty"` + ThrottleProtectedPathsEnabled *bool `url:"throttle_protected_paths_enabled,omitempty" json:"throttle_protected_paths_enabled,omitempty"` + ThrottleProtectedPathsPeriodInSeconds *int64 `url:"throttle_protected_paths_period_in_seconds,omitempty" json:"throttle_protected_paths_period_in_seconds,omitempty"` + ThrottleProtectedPathsRequestsPerPeriod *int64 `url:"throttle_protected_paths_requests_per_period,omitempty" json:"throttle_protected_paths_requests_per_period,omitempty"` ThrottleUnauthenticatedAPIEnabled *bool `url:"throttle_unauthenticated_api_enabled,omitempty" json:"throttle_unauthenticated_api_enabled,omitempty"` - ThrottleUnauthenticatedAPIPeriodInSeconds *int `url:"throttle_unauthenticated_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_api_period_in_seconds,omitempty"` - ThrottleUnauthenticatedAPIRequestsPerPeriod *int `url:"throttle_unauthenticated_api_requests_per_period,omitempty" json:"throttle_unauthenticated_api_requests_per_period,omitempty"` + ThrottleUnauthenticatedAPIPeriodInSeconds *int64 `url:"throttle_unauthenticated_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_api_period_in_seconds,omitempty"` + ThrottleUnauthenticatedAPIRequestsPerPeriod *int64 `url:"throttle_unauthenticated_api_requests_per_period,omitempty" json:"throttle_unauthenticated_api_requests_per_period,omitempty"` ThrottleUnauthenticatedDeprecatedAPIEnabled *bool `url:"throttle_unauthenticated_deprecated_api_enabled,omitempty" json:"throttle_unauthenticated_deprecated_api_enabled,omitempty"` - ThrottleUnauthenticatedDeprecatedAPIPeriodInSeconds *int `url:"throttle_unauthenticated_deprecated_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_deprecated_api_period_in_seconds,omitempty"` - ThrottleUnauthenticatedDeprecatedAPIRequestsPerPeriod *int `url:"throttle_unauthenticated_deprecated_api_requests_per_period,omitempty" json:"throttle_unauthenticated_deprecated_api_requests_per_period,omitempty"` + ThrottleUnauthenticatedDeprecatedAPIPeriodInSeconds *int64 `url:"throttle_unauthenticated_deprecated_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_deprecated_api_period_in_seconds,omitempty"` + ThrottleUnauthenticatedDeprecatedAPIRequestsPerPeriod *int64 `url:"throttle_unauthenticated_deprecated_api_requests_per_period,omitempty" json:"throttle_unauthenticated_deprecated_api_requests_per_period,omitempty"` ThrottleUnauthenticatedFilesAPIEnabled *bool `url:"throttle_unauthenticated_files_api_enabled,omitempty" json:"throttle_unauthenticated_files_api_enabled,omitempty"` - ThrottleUnauthenticatedFilesAPIPeriodInSeconds *int `url:"throttle_unauthenticated_files_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_files_api_period_in_seconds,omitempty"` - ThrottleUnauthenticatedFilesAPIRequestsPerPeriod *int `url:"throttle_unauthenticated_files_api_requests_per_period,omitempty" json:"throttle_unauthenticated_files_api_requests_per_period,omitempty"` + ThrottleUnauthenticatedFilesAPIPeriodInSeconds *int64 `url:"throttle_unauthenticated_files_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_files_api_period_in_seconds,omitempty"` + ThrottleUnauthenticatedFilesAPIRequestsPerPeriod *int64 `url:"throttle_unauthenticated_files_api_requests_per_period,omitempty" json:"throttle_unauthenticated_files_api_requests_per_period,omitempty"` ThrottleUnauthenticatedGitLFSEnabled *bool `url:"throttle_unauthenticated_git_lfs_enabled,omitempty" json:"throttle_unauthenticated_git_lfs_enabled,omitempty"` - ThrottleUnauthenticatedGitLFSPeriodInSeconds *int `url:"throttle_unauthenticated_git_lfs_period_in_seconds,omitempty" json:"throttle_unauthenticated_git_lfs_period_in_seconds,omitempty"` - ThrottleUnauthenticatedGitLFSRequestsPerPeriod *int `url:"throttle_unauthenticated_git_lfs_requests_per_period,omitempty" json:"throttle_unauthenticated_git_lfs_requests_per_period,omitempty"` + ThrottleUnauthenticatedGitLFSPeriodInSeconds *int64 `url:"throttle_unauthenticated_git_lfs_period_in_seconds,omitempty" json:"throttle_unauthenticated_git_lfs_period_in_seconds,omitempty"` + ThrottleUnauthenticatedGitLFSRequestsPerPeriod *int64 `url:"throttle_unauthenticated_git_lfs_requests_per_period,omitempty" json:"throttle_unauthenticated_git_lfs_requests_per_period,omitempty"` ThrottleUnauthenticatedPackagesAPIEnabled *bool `url:"throttle_unauthenticated_packages_api_enabled,omitempty" json:"throttle_unauthenticated_packages_api_enabled,omitempty"` - ThrottleUnauthenticatedPackagesAPIPeriodInSeconds *int `url:"throttle_unauthenticated_packages_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_packages_api_period_in_seconds,omitempty"` - ThrottleUnauthenticatedPackagesAPIRequestsPerPeriod *int `url:"throttle_unauthenticated_packages_api_requests_per_period,omitempty" json:"throttle_unauthenticated_packages_api_requests_per_period,omitempty"` + ThrottleUnauthenticatedPackagesAPIPeriodInSeconds *int64 `url:"throttle_unauthenticated_packages_api_period_in_seconds,omitempty" json:"throttle_unauthenticated_packages_api_period_in_seconds,omitempty"` + ThrottleUnauthenticatedPackagesAPIRequestsPerPeriod *int64 `url:"throttle_unauthenticated_packages_api_requests_per_period,omitempty" json:"throttle_unauthenticated_packages_api_requests_per_period,omitempty"` ThrottleUnauthenticatedWebEnabled *bool `url:"throttle_unauthenticated_web_enabled,omitempty" json:"throttle_unauthenticated_web_enabled,omitempty"` - ThrottleUnauthenticatedWebPeriodInSeconds *int `url:"throttle_unauthenticated_web_period_in_seconds,omitempty" json:"throttle_unauthenticated_web_period_in_seconds,omitempty"` - ThrottleUnauthenticatedWebRequestsPerPeriod *int `url:"throttle_unauthenticated_web_requests_per_period,omitempty" json:"throttle_unauthenticated_web_requests_per_period,omitempty"` + ThrottleUnauthenticatedWebPeriodInSeconds *int64 `url:"throttle_unauthenticated_web_period_in_seconds,omitempty" json:"throttle_unauthenticated_web_period_in_seconds,omitempty"` + ThrottleUnauthenticatedWebRequestsPerPeriod *int64 `url:"throttle_unauthenticated_web_requests_per_period,omitempty" json:"throttle_unauthenticated_web_requests_per_period,omitempty"` TimeTrackingLimitToHours *bool `url:"time_tracking_limit_to_hours,omitempty" json:"time_tracking_limit_to_hours,omitempty"` - TwoFactorGracePeriod *int `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` - UnconfirmedUsersDeleteAfterDays *int `url:"unconfirmed_users_delete_after_days,omitempty" json:"unconfirmed_users_delete_after_days,omitempty"` + TwoFactorGracePeriod *int64 `url:"two_factor_grace_period,omitempty" json:"two_factor_grace_period,omitempty"` + UnconfirmedUsersDeleteAfterDays *int64 `url:"unconfirmed_users_delete_after_days,omitempty" json:"unconfirmed_users_delete_after_days,omitempty"` UniqueIPsLimitEnabled *bool `url:"unique_ips_limit_enabled,omitempty" json:"unique_ips_limit_enabled,omitempty"` - UniqueIPsLimitPerUser *int `url:"unique_ips_limit_per_user,omitempty" json:"unique_ips_limit_per_user,omitempty"` - UniqueIPsLimitTimeWindow *int `url:"unique_ips_limit_time_window,omitempty" json:"unique_ips_limit_time_window,omitempty"` + UniqueIPsLimitPerUser *int64 `url:"unique_ips_limit_per_user,omitempty" json:"unique_ips_limit_per_user,omitempty"` + UniqueIPsLimitTimeWindow *int64 `url:"unique_ips_limit_time_window,omitempty" json:"unique_ips_limit_time_window,omitempty"` UpdateRunnerVersionsEnabled *bool `url:"update_runner_versions_enabled,omitempty" json:"update_runner_versions_enabled,omitempty"` UpdatingNameDisabledForUsers *bool `url:"updating_name_disabled_for_users,omitempty" json:"updating_name_disabled_for_users,omitempty"` UsagePingEnabled *bool `url:"usage_ping_enabled,omitempty" json:"usage_ping_enabled,omitempty"` @@ -932,16 +929,17 @@ type UpdateSettingsOptions struct { UserDefaultExternal *bool `url:"user_default_external,omitempty" json:"user_default_external,omitempty"` UserDefaultInternalRegex *string `url:"user_default_internal_regex,omitempty" json:"user_default_internal_regex,omitempty"` UserDefaultsToPrivateProfile *bool `url:"user_defaults_to_private_profile,omitempty" json:"user_defaults_to_private_profile,omitempty"` - UserEmailLookupLimit *int `url:"user_email_lookup_limit,omitempty" json:"user_email_lookup_limit,omitempty"` + UserEmailLookupLimit *int64 `url:"user_email_lookup_limit,omitempty" json:"user_email_lookup_limit,omitempty"` UserOauthApplications *bool `url:"user_oauth_applications,omitempty" json:"user_oauth_applications,omitempty"` UserShowAddSSHKeyMessage *bool `url:"user_show_add_ssh_key_message,omitempty" json:"user_show_add_ssh_key_message,omitempty"` - UsersGetByIDLimit *int `url:"users_get_by_id_limit,omitempty" json:"users_get_by_id_limit,omitempty"` + UsersGetByIDLimit *int64 `url:"users_get_by_id_limit,omitempty" json:"users_get_by_id_limit,omitempty"` UsersGetByIDLimitAllowlistRaw *string `url:"users_get_by_id_limit_allowlist_raw,omitempty" json:"users_get_by_id_limit_allowlist_raw,omitempty"` ValidRunnerRegistrars *[]string `url:"valid_runner_registrars,omitempty" json:"valid_runner_registrars,omitempty"` VersionCheckEnabled *bool `url:"version_check_enabled,omitempty" json:"version_check_enabled,omitempty"` WebIDEClientsidePreviewEnabled *bool `url:"web_ide_clientside_preview_enabled,omitempty" json:"web_ide_clientside_preview_enabled,omitempty"` WhatsNewVariant *string `url:"whats_new_variant,omitempty" json:"whats_new_variant,omitempty"` - WikiPageMaxContentBytes *int `url:"wiki_page_max_content_bytes,omitempty" json:"wiki_page_max_content_bytes,omitempty"` + WikiPageMaxContentBytes *int64 `url:"wiki_page_max_content_bytes,omitempty" json:"wiki_page_max_content_bytes,omitempty"` + LockMembershipsToSAML *bool `url:"lock_memberships_to_saml,omitempty" json:"lock_memberships_to_saml,omitempty"` // Deprecated: Use AbuseNotificationEmail instead. AdminNotificationEmail *string `url:"admin_notification_email,omitempty" json:"admin_notification_email,omitempty"` @@ -950,25 +948,25 @@ type UpdateSettingsOptions struct { // Deprecated: Use AssetProxyAllowlist instead. AssetProxyWhitelist *[]string `url:"asset_proxy_whitelist,omitempty" json:"asset_proxy_whitelist,omitempty"` // Deprecated: Use DefaultBranchProtectionDefaults instead. - DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` + DefaultBranchProtection *int64 `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"` // Deprecated: Cannot be set through the API, always true HousekeepingBitmapsEnabled *bool `url:"housekeeping_bitmaps_enabled,omitempty" json:"housekeeping_bitmaps_enabled,omitempty"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingFullRepackPeriod *int `url:"housekeeping_full_repack_period,omitempty" json:"housekeeping_full_repack_period,omitempty"` + HousekeepingFullRepackPeriod *int64 `url:"housekeeping_full_repack_period,omitempty" json:"housekeeping_full_repack_period,omitempty"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingGcPeriod *int `url:"housekeeping_gc_period,omitempty" json:"housekeeping_gc_period,omitempty"` + HousekeepingGcPeriod *int64 `url:"housekeeping_gc_period,omitempty" json:"housekeeping_gc_period,omitempty"` // Deprecated: use HousekeepingOptimizeRepositoryPeriod instead - HousekeepingIncrementalRepackPeriod *int `url:"housekeeping_incremental_repack_period,omitempty" json:"housekeeping_incremental_repack_period,omitempty"` + HousekeepingIncrementalRepackPeriod *int64 `url:"housekeeping_incremental_repack_period,omitempty" json:"housekeeping_incremental_repack_period,omitempty"` // Deprecated: use PerformanceBarAllowedGroupPath instead - PerformanceBarAllowedGroupID *int `url:"performance_bar_allowed_group_id,omitempty" json:"performance_bar_allowed_group_id,omitempty"` + PerformanceBarAllowedGroupID *int64 `url:"performance_bar_allowed_group_id,omitempty" json:"performance_bar_allowed_group_id,omitempty"` // Deprecated: use PerformanceBarAllowedGroupPath: nil instead PerformanceBarEnabled *bool `url:"performance_bar_enabled,omitempty" json:"performance_bar_enabled,omitempty"` // Deprecated: Use ThrottleUnauthenticatedWebEnabled or ThrottleUnauthenticatedAPIEnabled instead. (Deprecated in GitLab 14.3) ThrottleUnauthenticatedEnabled *bool `url:"throttle_unauthenticated_enabled,omitempty" json:"throttle_unauthenticated_enabled,omitempty"` // Deprecated: Use ThrottleUnauthenticatedWebPeriodInSeconds or ThrottleUnauthenticatedAPIPeriodInSeconds instead. (Deprecated in GitLab 14.3) - ThrottleUnauthenticatedPeriodInSeconds *int `url:"throttle_unauthenticated_period_in_seconds,omitempty" json:"throttle_unauthenticated_period_in_seconds,omitempty"` + ThrottleUnauthenticatedPeriodInSeconds *int64 `url:"throttle_unauthenticated_period_in_seconds,omitempty" json:"throttle_unauthenticated_period_in_seconds,omitempty"` // Deprecated: Use ThrottleUnauthenticatedWebRequestsPerPeriod or ThrottleUnauthenticatedAPIRequestsPerPeriod instead. (Deprecated in GitLab 14.3) - ThrottleUnauthenticatedRequestsPerPeriod *int `url:"throttle_unauthenticated_requests_per_period,omitempty" json:"throttle_unauthenticated_requests_per_period,omitempty"` + ThrottleUnauthenticatedRequestsPerPeriod *int64 `url:"throttle_unauthenticated_requests_per_period,omitempty" json:"throttle_unauthenticated_requests_per_period,omitempty"` } // BranchProtectionDefaultsOptions represents default Git protected branch permissions options. @@ -976,10 +974,10 @@ type UpdateSettingsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/groups/#options-for-default_branch_protection_defaults type BranchProtectionDefaultsOptions struct { - AllowedToPush *[]int `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` - AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` - AllowedToMerge *[]int `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` - DeveloperCanInitialPush *bool `url:"developer_can_initial_push,omitempty" json:"developer_can_initial_push,omitempty"` + AllowedToPush *[]int64 `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"` + AllowForcePush *bool `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"` + AllowedToMerge *[]int64 `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"` + DeveloperCanInitialPush *bool `url:"developer_can_initial_push,omitempty" json:"developer_can_initial_push,omitempty"` } // UpdateSettings updates the application settings. @@ -987,16 +985,10 @@ type BranchProtectionDefaultsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/settings/#update-application-settings func (s *SettingsService) UpdateSettings(opt *UpdateSettingsOptions, options ...RequestOptionFunc) (*Settings, *Response, error) { - req, err := s.client.NewRequest(http.MethodPut, "application/settings", opt, options) - if err != nil { - return nil, nil, err - } - - as := new(Settings) - resp, err := s.client.Do(req, as) - if err != nil { - return nil, resp, err - } - - return as, resp, nil + return do[*Settings](s.client, + withMethod(http.MethodPut), + withPath("application/settings"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/sidekiq_metrics.go b/vendor/gitlab.com/gitlab-org/api/client-go/sidekiq_metrics.go index 0a985847f..0eb6a29ac 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/sidekiq_metrics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/sidekiq_metrics.go @@ -17,7 +17,6 @@ package gitlab import ( - "net/http" "time" ) @@ -44,10 +43,16 @@ var _ SidekiqServiceInterface = (*SidekiqService)(nil) // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-queue-metrics type QueueMetrics struct { - Queues map[string]struct { - Backlog int `json:"backlog"` - Latency int `json:"latency"` - } `json:"queues"` + Queues map[string]QueueMetricsQueue `json:"queues"` +} + +// QueueMetricsQueue represents the GitLab sidekiq queue metrics queue. +// +// GitLab API docs: +// https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-queue-metrics +type QueueMetricsQueue struct { + Backlog int64 `json:"backlog"` + Latency int64 `json:"latency"` } // GetQueueMetrics lists information about all the registered queues, @@ -56,18 +61,10 @@ type QueueMetrics struct { // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-queue-metrics func (s *SidekiqService) GetQueueMetrics(options ...RequestOptionFunc) (*QueueMetrics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "/sidekiq/queue_metrics", nil, options) - if err != nil { - return nil, nil, err - } - - q := new(QueueMetrics) - resp, err := s.client.Do(req, q) - if err != nil { - return nil, resp, err - } - - return q, resp, nil + return do[*QueueMetrics](s.client, + withPath("/sidekiq/queue_metrics"), + withRequestOpts(options...), + ) } // ProcessMetrics represents the GitLab sidekiq process metrics. @@ -75,16 +72,22 @@ func (s *SidekiqService) GetQueueMetrics(options ...RequestOptionFunc) (*QueueMe // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-process-metrics type ProcessMetrics struct { - Processes []struct { - Hostname string `json:"hostname"` - Pid int `json:"pid"` - Tag string `json:"tag"` - StartedAt *time.Time `json:"started_at"` - Queues []string `json:"queues"` - Labels []string `json:"labels"` - Concurrency int `json:"concurrency"` - Busy int `json:"busy"` - } `json:"processes"` + Processes []ProcessMetricsProcess `json:"processes"` +} + +// ProcessMetricsProcess represents the GitLab sidekiq process metrics process. +// +// GitLab API docs: +// https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-process-metrics +type ProcessMetricsProcess struct { + Hostname string `json:"hostname"` + Pid int64 `json:"pid"` + Tag string `json:"tag"` + StartedAt *time.Time `json:"started_at"` + Queues []string `json:"queues"` + Labels []string `json:"labels"` + Concurrency int64 `json:"concurrency"` + Busy int64 `json:"busy"` } // GetProcessMetrics lists information about all the Sidekiq workers registered @@ -93,18 +96,10 @@ type ProcessMetrics struct { // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-process-metrics func (s *SidekiqService) GetProcessMetrics(options ...RequestOptionFunc) (*ProcessMetrics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "/sidekiq/process_metrics", nil, options) - if err != nil { - return nil, nil, err - } - - p := new(ProcessMetrics) - resp, err := s.client.Do(req, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return do[*ProcessMetrics](s.client, + withPath("/sidekiq/process_metrics"), + withRequestOpts(options...), + ) } // JobStats represents the GitLab sidekiq job stats. @@ -112,11 +107,17 @@ func (s *SidekiqService) GetProcessMetrics(options ...RequestOptionFunc) (*Proce // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-job-statistics type JobStats struct { - Jobs struct { - Processed int `json:"processed"` - Failed int `json:"failed"` - Enqueued int `json:"enqueued"` - } `json:"jobs"` + Jobs JobStatsJobs `json:"jobs"` +} + +// JobStatsJobs represents the GitLab sidekiq job stats jobs. +// +// GitLab API docs: +// https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-job-statistics +type JobStatsJobs struct { + Processed int64 `json:"processed"` + Failed int64 `json:"failed"` + Enqueued int64 `json:"enqueued"` } // GetJobStats list information about the jobs that Sidekiq has performed. @@ -124,18 +125,10 @@ type JobStats struct { // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-the-current-job-statistics func (s *SidekiqService) GetJobStats(options ...RequestOptionFunc) (*JobStats, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "/sidekiq/job_stats", nil, options) - if err != nil { - return nil, nil, err - } - - j := new(JobStats) - resp, err := s.client.Do(req, j) - if err != nil { - return nil, resp, err - } - - return j, resp, nil + return do[*JobStats](s.client, + withPath("/sidekiq/job_stats"), + withRequestOpts(options...), + ) } // CompoundMetrics represents the GitLab sidekiq compounded stats. @@ -154,16 +147,8 @@ type CompoundMetrics struct { // GitLab API docs: // https://docs.gitlab.com/api/sidekiq_metrics/#get-a-compound-response-of-all-the-previously-mentioned-metrics func (s *SidekiqService) GetCompoundMetrics(options ...RequestOptionFunc) (*CompoundMetrics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "/sidekiq/compound_metrics", nil, options) - if err != nil { - return nil, nil, err - } - - c := new(CompoundMetrics) - resp, err := s.client.Do(req, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return do[*CompoundMetrics](s.client, + withPath("/sidekiq/compound_metrics"), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/snippet_repository_storage_move.go b/vendor/gitlab.com/gitlab-org/api/client-go/snippet_repository_storage_move.go index b25c3a487..ee20002a0 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/snippet_repository_storage_move.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/snippet_repository_storage_move.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" "time" ) @@ -25,10 +24,10 @@ import ( type ( SnippetRepositoryStorageMoveServiceInterface interface { RetrieveAllStorageMoves(opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) - RetrieveAllStorageMovesForSnippet(snippet int, opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) - GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) - GetStorageMoveForSnippet(snippet int, repositoryStorage int, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) - ScheduleStorageMoveForSnippet(snippet int, opts ScheduleStorageMoveForSnippetOptions, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) + RetrieveAllStorageMovesForSnippet(snippet int64, opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) + GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) + GetStorageMoveForSnippet(snippet int64, repositoryStorage int64, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) + ScheduleStorageMoveForSnippet(snippet int64, opts ScheduleStorageMoveForSnippetOptions, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) ScheduleAllStorageMoves(opts ScheduleAllSnippetStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) } @@ -49,7 +48,7 @@ var _ SnippetRepositoryStorageMoveServiceInterface = (*SnippetRepositoryStorageM // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/ type SnippetRepositoryStorageMove struct { - ID int `json:"id"` + ID int64 `json:"id"` CreatedAt *time.Time `json:"created_at"` State string `json:"state"` SourceStorageName string `json:"source_storage_name"` @@ -58,13 +57,13 @@ type SnippetRepositoryStorageMove struct { } type RepositorySnippet struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Description string `json:"description"` Visibility VisibilityValue `json:"visibility"` UpdatedAt *time.Time `json:"updated_at"` CreatedAt *time.Time `json:"created_at"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` WebURL string `json:"web_url"` RawURL string `json:"raw_url"` SSHURLToRepo string `json:"ssh_url_to_repo"` @@ -77,7 +76,9 @@ type RepositorySnippet struct { // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#retrieve-all-snippet-repository-storage-moves // https://docs.gitlab.com/api/snippet_repository_storage_moves/#retrieve-all-repository-storage-moves-for-a-snippet -type RetrieveAllSnippetStorageMovesOptions ListOptions +type RetrieveAllSnippetStorageMovesOptions struct { + ListOptions +} // RetrieveAllStorageMoves retrieves all snippet repository storage moves // accessible by the authenticated user. @@ -85,18 +86,11 @@ type RetrieveAllSnippetStorageMovesOptions ListOptions // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#retrieve-all-snippet-repository-storage-moves func (s SnippetRepositoryStorageMoveService) RetrieveAllStorageMoves(opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "snippet_repository_storage_moves", opts, options) - if err != nil { - return nil, nil, err - } - - var ssms []*SnippetRepositoryStorageMove - resp, err := s.client.Do(req, &ssms) - if err != nil { - return nil, resp, err - } - - return ssms, resp, err + return do[[]*SnippetRepositoryStorageMove](s.client, + withPath("snippet_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // RetrieveAllStorageMovesForSnippet retrieves all repository storage moves for @@ -104,63 +98,34 @@ func (s SnippetRepositoryStorageMoveService) RetrieveAllStorageMoves(opts Retrie // // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#retrieve-all-repository-storage-moves-for-a-snippet -func (s SnippetRepositoryStorageMoveService) RetrieveAllStorageMovesForSnippet(snippet int, opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("snippets/%d/repository_storage_moves", snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, opts, options) - if err != nil { - return nil, nil, err - } - - var ssms []*SnippetRepositoryStorageMove - resp, err := s.client.Do(req, &ssms) - if err != nil { - return nil, resp, err - } - - return ssms, resp, err +func (s SnippetRepositoryStorageMoveService) RetrieveAllStorageMovesForSnippet(snippet int64, opts RetrieveAllSnippetStorageMovesOptions, options ...RequestOptionFunc) ([]*SnippetRepositoryStorageMove, *Response, error) { + return do[[]*SnippetRepositoryStorageMove](s.client, + withPath("snippets/%d/repository_storage_moves", snippet), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // GetStorageMove gets a single snippet repository storage move. // // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#get-a-single-snippet-repository-storage-move -func (s SnippetRepositoryStorageMoveService) GetStorageMove(repositoryStorage int, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("snippet_repository_storage_moves/%d", repositoryStorage) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ssm := new(SnippetRepositoryStorageMove) - resp, err := s.client.Do(req, ssm) - if err != nil { - return nil, resp, err - } - - return ssm, resp, err +func (s SnippetRepositoryStorageMoveService) GetStorageMove(repositoryStorage int64, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { + return do[*SnippetRepositoryStorageMove](s.client, + withPath("snippet_repository_storage_moves/%d", repositoryStorage), + withRequestOpts(options...), + ) } // GetStorageMoveForSnippet gets a single repository storage move for a snippet. // // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#get-a-single-repository-storage-move-for-a-snippet -func (s SnippetRepositoryStorageMoveService) GetStorageMoveForSnippet(snippet int, repositoryStorage int, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("snippets/%d/repository_storage_moves/%d", snippet, repositoryStorage) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ssm := new(SnippetRepositoryStorageMove) - resp, err := s.client.Do(req, ssm) - if err != nil { - return nil, resp, err - } - - return ssm, resp, err +func (s SnippetRepositoryStorageMoveService) GetStorageMoveForSnippet(snippet int64, repositoryStorage int64, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { + return do[*SnippetRepositoryStorageMove](s.client, + withPath("snippets/%d/repository_storage_moves/%d", snippet, repositoryStorage), + withRequestOpts(options...), + ) } // ScheduleStorageMoveForSnippetOptions represents the available @@ -176,21 +141,13 @@ type ScheduleStorageMoveForSnippetOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#schedule-a-repository-storage-move-for-a-snippet -func (s SnippetRepositoryStorageMoveService) ScheduleStorageMoveForSnippet(snippet int, opts ScheduleStorageMoveForSnippetOptions, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { - u := fmt.Sprintf("snippets/%d/repository_storage_moves", snippet) - - req, err := s.client.NewRequest(http.MethodPost, u, opts, options) - if err != nil { - return nil, nil, err - } - - ssm := new(SnippetRepositoryStorageMove) - resp, err := s.client.Do(req, ssm) - if err != nil { - return nil, resp, err - } - - return ssm, resp, err +func (s SnippetRepositoryStorageMoveService) ScheduleStorageMoveForSnippet(snippet int64, opts ScheduleStorageMoveForSnippetOptions, options ...RequestOptionFunc) (*SnippetRepositoryStorageMove, *Response, error) { + return do[*SnippetRepositoryStorageMove](s.client, + withMethod(http.MethodPost), + withPath("snippets/%d/repository_storage_moves", snippet), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // ScheduleAllSnippetStorageMovesOptions represents the available @@ -208,10 +165,11 @@ type ScheduleAllSnippetStorageMovesOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/snippet_repository_storage_moves/#schedule-repository-storage-moves-for-all-snippets-on-a-storage-shard func (s SnippetRepositoryStorageMoveService) ScheduleAllStorageMoves(opts ScheduleAllSnippetStorageMovesOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "snippet_repository_storage_moves", opts, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("snippet_repository_storage_moves"), + withAPIOpts(opts), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/snippets.go b/vendor/gitlab.com/gitlab-org/api/client-go/snippets.go index d3bdad822..4c7cd150f 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/snippets.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/snippets.go @@ -18,7 +18,6 @@ package gitlab import ( "bytes" - "fmt" "net/http" "time" ) @@ -26,12 +25,12 @@ import ( type ( SnippetsServiceInterface interface { ListSnippets(opt *ListSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) - GetSnippet(snippet int, options ...RequestOptionFunc) (*Snippet, *Response, error) - SnippetContent(snippet int, options ...RequestOptionFunc) ([]byte, *Response, error) - SnippetFileContent(snippet int, ref, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) + GetSnippet(snippet int64, options ...RequestOptionFunc) (*Snippet, *Response, error) + SnippetContent(snippet int64, options ...RequestOptionFunc) ([]byte, *Response, error) + SnippetFileContent(snippet int64, ref, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) CreateSnippet(opt *CreateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) - UpdateSnippet(snippet int, opt *UpdateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) - DeleteSnippet(snippet int, options ...RequestOptionFunc) (*Response, error) + UpdateSnippet(snippet int64, opt *UpdateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) + DeleteSnippet(snippet int64, options ...RequestOptionFunc) (*Response, error) ExploreSnippets(opt *ExploreSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) ListAllSnippets(opt *ListAllSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) } @@ -51,122 +50,123 @@ var _ SnippetsServiceInterface = (*SnippetsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/snippets/ type Snippet struct { - ID int `json:"id"` - Title string `json:"title"` - FileName string `json:"file_name"` - Description string `json:"description"` - Visibility string `json:"visibility"` - Author struct { - ID int `json:"id"` - Username string `json:"username"` - Email string `json:"email"` - Name string `json:"name"` - State string `json:"state"` - CreatedAt *time.Time `json:"created_at"` - } `json:"author"` - UpdatedAt *time.Time `json:"updated_at"` - CreatedAt *time.Time `json:"created_at"` - ProjectID int `json:"project_id"` - WebURL string `json:"web_url"` - RawURL string `json:"raw_url"` - Files []struct { - Path string `json:"path"` - RawURL string `json:"raw_url"` - } `json:"files"` - RepositoryStorage string `json:"repository_storage"` + ID int64 `json:"id"` + Title string `json:"title"` + FileName string `json:"file_name"` + Description string `json:"description"` + Visibility string `json:"visibility"` + Author SnippetAuthor `json:"author"` + UpdatedAt *time.Time `json:"updated_at"` + CreatedAt *time.Time `json:"created_at"` + ProjectID int64 `json:"project_id"` + WebURL string `json:"web_url"` + RawURL string `json:"raw_url"` + Files []SnippetFile `json:"files"` + RepositoryStorage string `json:"repository_storage"` } func (s Snippet) String() string { return Stringify(s) } +// SnippetAuthor represents a GitLab snippet author. +// +// GitLab API docs: https://docs.gitlab.com/api/snippets/ +type SnippetAuthor struct { + ID int64 `json:"id"` + Username string `json:"username"` + Email string `json:"email"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"created_at"` +} + +func (a SnippetAuthor) String() string { + return Stringify(a) +} + +// SnippetFile represents a GitLab snippet file. +// +// GitLab API docs: https://docs.gitlab.com/api/snippets/ +type SnippetFile struct { + Path string `json:"path"` + RawURL string `json:"raw_url"` +} + +func (f SnippetFile) String() string { + return Stringify(f) +} + // ListSnippetsOptions represents the available ListSnippets() options. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#list-all-snippets-for-current-user -type ListSnippetsOptions ListOptions +type ListSnippetsOptions struct { + ListOptions +} // ListSnippets gets a list of snippets. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#list-all-snippets-for-current-user func (s *SnippetsService) ListSnippets(opt *ListSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "snippets", opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Snippet - resp, err := s.client.Do(req, &ps) + res, resp, err := do[[]*Snippet](s.client, + withMethod(http.MethodGet), + withPath("snippets"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } // GetSnippet gets a single snippet // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#get-a-single-snippet -func (s *SnippetsService) GetSnippet(snippet int, options ...RequestOptionFunc) (*Snippet, *Response, error) { - u := fmt.Sprintf("snippets/%d", snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) +func (s *SnippetsService) GetSnippet(snippet int64, options ...RequestOptionFunc) (*Snippet, *Response, error) { + res, resp, err := do[*Snippet](s.client, + withMethod(http.MethodGet), + withPath("snippets/%d", snippet), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } // SnippetContent gets a single snippetโ€™s raw contents. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#single-snippet-contents -func (s *SnippetsService) SnippetContent(snippet int, options ...RequestOptionFunc) ([]byte, *Response, error) { - u := fmt.Sprintf("snippets/%d/raw", snippet) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) +func (s *SnippetsService) SnippetContent(snippet int64, options ...RequestOptionFunc) ([]byte, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("snippets/%d/raw", snippet), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } // SnippetFileContent returns the raw file content as plain text. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#snippet-repository-file-content -func (s *SnippetsService) SnippetFileContent(snippet int, ref, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) { - filepath := PathEscape(filename) - u := fmt.Sprintf("snippets/%d/files/%s/%s/raw", snippet, ref, filepath) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) +func (s *SnippetsService) SnippetFileContent(snippet int64, ref, filename string, options ...RequestOptionFunc) ([]byte, *Response, error) { + buf, resp, err := do[bytes.Buffer](s.client, + withPath("snippets/%d/files/%s/%s/raw", snippet, ref, filename), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return b.Bytes(), resp, err + return buf.Bytes(), resp, nil } // CreateSnippetFileOptions represents the create snippet file options. @@ -197,18 +197,16 @@ type CreateSnippetOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/snippets/#create-new-snippet func (s *SnippetsService) CreateSnippet(opt *CreateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "snippets", opt, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) + res, resp, err := do[*Snippet](s.client, + withMethod(http.MethodPost), + withPath("snippets"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } // UpdateSnippetFileOptions represents the update snippet file options. @@ -240,21 +238,17 @@ type UpdateSnippetOptions struct { // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#update-snippet -func (s *SnippetsService) UpdateSnippet(snippet int, opt *UpdateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { - u := fmt.Sprintf("snippets/%d", snippet) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - ps := new(Snippet) - resp, err := s.client.Do(req, ps) +func (s *SnippetsService) UpdateSnippet(snippet int64, opt *UpdateSnippetOptions, options ...RequestOptionFunc) (*Snippet, *Response, error) { + res, resp, err := do[*Snippet](s.client, + withMethod(http.MethodPut), + withPath("snippets/%d", snippet), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } // DeleteSnippet deletes an existing snippet. This is an idempotent @@ -263,40 +257,39 @@ func (s *SnippetsService) UpdateSnippet(snippet int, opt *UpdateSnippetOptions, // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#delete-snippet -func (s *SnippetsService) DeleteSnippet(snippet int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("snippets/%d", snippet) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *SnippetsService) DeleteSnippet(snippet int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("snippets/%d", snippet), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } // ExploreSnippetsOptions represents the available ExploreSnippets() options. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#list-all-public-snippets -type ExploreSnippetsOptions ListOptions +type ExploreSnippetsOptions struct { + ListOptions +} // ExploreSnippets gets the list of public snippets. // // GitLab API docs: // https://docs.gitlab.com/api/snippets/#list-all-public-snippets func (s *SnippetsService) ExploreSnippets(opt *ExploreSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "snippets/public", opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Snippet - resp, err := s.client.Do(req, &ps) + res, resp, err := do[[]*Snippet](s.client, + withMethod(http.MethodGet), + withPath("snippets/public"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } // ListAllSnippetsOptions represents the available ListAllSnippets() options. @@ -315,16 +308,14 @@ type ListAllSnippetsOptions struct { // GitLab API docs: // https://docs.gitlab.com/api/snippets/#list-all-snippets func (s *SnippetsService) ListAllSnippets(opt *ListAllSnippetsOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "snippets/all", opt, options) - if err != nil { - return nil, nil, err - } - - var ps []*Snippet - resp, err := s.client.Do(req, &ps) + res, resp, err := do[[]*Snippet](s.client, + withMethod(http.MethodGet), + withPath("snippets/all"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return ps, resp, nil + return res, resp, nil } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/strings.go b/vendor/gitlab.com/gitlab-org/api/client-go/strings.go index def37b255..d8aaa7f52 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/strings.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/strings.go @@ -23,7 +23,7 @@ import ( ) // Stringify attempts to create a reasonable string representation of types in -// the Gitlab library. It does things like resolve pointers to their values +// the GitLab library. It does things like resolve pointers to their values // and omits struct fields with nil values. func Stringify(message any) string { var buf bytes.Buffer diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/system_hooks.go b/vendor/gitlab.com/gitlab-org/api/client-go/system_hooks.go index 3f778ec0f..d337ddf91 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/system_hooks.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/system_hooks.go @@ -17,18 +17,39 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( SystemHooksServiceInterface interface { + // ListHooks gets a list of system hooks. + // + // GitLab API docs: + // https://docs.gitlab.com/api/system_hooks/#list-system-hooks ListHooks(options ...RequestOptionFunc) ([]*Hook, *Response, error) - GetHook(hook int, options ...RequestOptionFunc) (*Hook, *Response, error) + // GetHook gets a single system hook. + // + // GitLab API docs: + // https://docs.gitlab.com/api/system_hooks/#get-system-hook + GetHook(hook int64, options ...RequestOptionFunc) (*Hook, *Response, error) + // AddHook adds a new system hook. + // + // GitLab API docs: + // https://docs.gitlab.com/api/system_hooks/#add-new-system-hook AddHook(opt *AddHookOptions, options ...RequestOptionFunc) (*Hook, *Response, error) - TestHook(hook int, options ...RequestOptionFunc) (*HookEvent, *Response, error) - DeleteHook(hook int, options ...RequestOptionFunc) (*Response, error) + // TestHook tests a system hook. + // + // GitLab API docs: + // https://docs.gitlab.com/api/system_hooks/#test-system-hook + TestHook(hook int64, options ...RequestOptionFunc) (*HookEvent, *Response, error) + // DeleteHook deletes a system hook. This is an idempotent API function and + // returns 200 OK even if the hook is not available. If the hook is deleted it + // is also returned as JSON. + // + // GitLab API docs: + // https://docs.gitlab.com/api/system_hooks/#delete-system-hook + DeleteHook(hook int64, options ...RequestOptionFunc) (*Response, error) } // SystemHooksService handles communication with the system hooks related @@ -46,7 +67,7 @@ var _ SystemHooksServiceInterface = (*SystemHooksService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/system_hooks/ type Hook struct { - ID int `json:"id"` + ID int64 `json:"id"` URL string `json:"url"` CreatedAt *time.Time `json:"created_at"` PushEvents bool `json:"push_events"` @@ -60,44 +81,18 @@ func (h Hook) String() string { return Stringify(h) } -// ListHooks gets a list of system hooks. -// -// GitLab API docs: -// https://docs.gitlab.com/api/system_hooks/#list-system-hooks func (s *SystemHooksService) ListHooks(options ...RequestOptionFunc) ([]*Hook, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "hooks", nil, options) - if err != nil { - return nil, nil, err - } - - var h []*Hook - resp, err := s.client.Do(req, &h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil + return do[[]*Hook](s.client, + withPath("hooks"), + withRequestOpts(options...), + ) } -// GetHook get a single system hook. -// -// GitLab API docs: -// https://docs.gitlab.com/api/system_hooks/#get-system-hook -func (s *SystemHooksService) GetHook(hook int, options ...RequestOptionFunc) (*Hook, *Response, error) { - u := fmt.Sprintf("hooks/%d", hook) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var h *Hook - resp, err := s.client.Do(req, &h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil +func (s *SystemHooksService) GetHook(hook int64, options ...RequestOptionFunc) (*Hook, *Response, error) { + return do[*Hook](s.client, + withPath("hooks/%d", hook), + withRequestOpts(options...), + ) } // AddHookOptions represents the available AddHook() options. @@ -114,23 +109,13 @@ type AddHookOptions struct { EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"` } -// AddHook adds a new system hook hook. -// -// GitLab API docs: -// https://docs.gitlab.com/api/system_hooks/#add-new-system-hook func (s *SystemHooksService) AddHook(opt *AddHookOptions, options ...RequestOptionFunc) (*Hook, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "hooks", opt, options) - if err != nil { - return nil, nil, err - } - - h := new(Hook) - resp, err := s.client.Do(req, h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil + return do[*Hook](s.client, + withMethod(http.MethodPost), + withPath("hooks"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // HookEvent represents an event trigger by a GitLab system hook. @@ -140,7 +125,7 @@ type HookEvent struct { EventName string `json:"event_name"` Name string `json:"name"` Path string `json:"path"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` OwnerName string `json:"owner_name"` OwnerEmail string `json:"owner_email"` } @@ -149,40 +134,18 @@ func (h HookEvent) String() string { return Stringify(h) } -// TestHook tests a system hook. -// -// GitLab API docs: -// https://docs.gitlab.com/api/system_hooks/#test-system-hook -func (s *SystemHooksService) TestHook(hook int, options ...RequestOptionFunc) (*HookEvent, *Response, error) { - u := fmt.Sprintf("hooks/%d", hook) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - h := new(HookEvent) - resp, err := s.client.Do(req, h) - if err != nil { - return nil, resp, err - } - - return h, resp, nil +func (s *SystemHooksService) TestHook(hook int64, options ...RequestOptionFunc) (*HookEvent, *Response, error) { + return do[*HookEvent](s.client, + withPath("hooks/%d", hook), + withRequestOpts(options...), + ) } -// DeleteHook deletes a system hook. This is an idempotent API function and -// returns 200 OK even if the hook is not available. If the hook is deleted it -// is also returned as JSON. -// -// GitLab API docs: -// https://docs.gitlab.com/api/system_hooks/#delete-system-hook -func (s *SystemHooksService) DeleteHook(hook int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("hooks/%d", hook) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *SystemHooksService) DeleteHook(hook int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("hooks/%d", hook), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/tags.go b/vendor/gitlab.com/gitlab-org/api/client-go/tags.go index aec5f3d6b..333dbfe44 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/tags.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/tags.go @@ -17,19 +17,40 @@ package gitlab import ( - "fmt" "math/big" "net/http" - "net/url" "time" ) type ( TagsServiceInterface interface { + // ListTags gets a list of tags from a project, sorted by name in reverse + // alphabetical order. + // + // GitLab API docs: + // https://docs.gitlab.com/api/tags/#list-project-repository-tags ListTags(pid any, opt *ListTagsOptions, options ...RequestOptionFunc) ([]*Tag, *Response, error) + // GetTag a specific repository tag determined by its name. It returns 200 together + // with the tag information if the tag exists. It returns 404 if the tag does not exist. + // + // GitLab API docs: + // https://docs.gitlab.com/api/tags/#get-a-single-repository-tag GetTag(pid any, tag string, options ...RequestOptionFunc) (*Tag, *Response, error) + // GetTagSignature a specific repository tag determined by its name. It returns 200 together + // with the signature if the tag exists. It returns 404 if the tag does not exist. + // + // GitLab API docs: + // https://docs.gitlab.com/api/tags/#get-x509-signature-of-a-tag GetTagSignature(pid any, tag string, options ...RequestOptionFunc) (*X509Signature, *Response, error) + // CreateTag creates a new tag in the repository that points to the supplied ref. + // + // GitLab API docs: + // https://docs.gitlab.com/api/tags/#create-a-new-tag CreateTag(pid any, opt *CreateTagOptions, options ...RequestOptionFunc) (*Tag, *Response, error) + // DeleteTag deletes a tag of a repository with given name. + // + // GitLab API docs: + // https://docs.gitlab.com/api/tags/#delete-a-tag DeleteTag(pid any, tag string, options ...RequestOptionFunc) (*Response, error) } @@ -67,7 +88,7 @@ type X509Signature struct { } type X509Certificate struct { - ID int `json:"id"` + ID int64 `json:"id"` Subject string `json:"subject"` SubjectKeyIdentifier string `json:"subject_key_identifier"` Email string `json:"email"` @@ -77,10 +98,10 @@ type X509Certificate struct { } type X509Issuer struct { - ID int `json:"id"` + ID int64 `json:"id"` Subject string `json:"subject"` SubjectKeyIdentifier string `json:"subject_key_identifier"` - CrlUrl string `json:"crl_url"` + CrlURL string `json:"crl_url"` } // ReleaseNote represents a GitLab version release. @@ -106,82 +127,26 @@ type ListTagsOptions struct { Sort *string `url:"sort,omitempty" json:"sort,omitempty"` } -// ListTags gets a list of tags from a project, sorted by name in reverse -// alphabetical order. -// -// GitLab API docs: -// https://docs.gitlab.com/api/tags/#list-project-repository-tags func (s *TagsService) ListTags(pid any, opt *ListTagsOptions, options ...RequestOptionFunc) ([]*Tag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/tags", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var t []*Tag - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[[]*Tag](s.client, + withPath("projects/%s/repository/tags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetTag a specific repository tag determined by its name. It returns 200 together -// with the tag information if the tag exists. It returns 404 if the tag does not exist. -// -// GitLab API docs: -// https://docs.gitlab.com/api/tags/#get-a-single-repository-tag func (s *TagsService) GetTag(pid any, tag string, options ...RequestOptionFunc) (*Tag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/tags/%s", PathEscape(project), url.PathEscape(tag)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var t *Tag - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*Tag](s.client, + withPath("projects/%s/repository/tags/%s", ProjectID{pid}, tag), + withRequestOpts(options...), + ) } -// GetTagSignature a specific repository tag determined by its name. It returns 200 together -// with the signature if the tag exists. It returns 404 if the tag does not exist. -// -// GitLab API docs: -// https://docs.gitlab.com/api/tags/#get-x509-signature-of-a-tag func (s *TagsService) GetTagSignature(pid any, tag string, options ...RequestOptionFunc) (*X509Signature, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/tags/%s/signature", PathEscape(project), url.PathEscape(tag)) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var sig *X509Signature - resp, err := s.client.Do(req, &sig) - if err != nil { - return nil, resp, err - } - - return sig, resp, nil + return do[*X509Signature](s.client, + withPath("projects/%s/repository/tags/%s/signature", ProjectID{pid}, tag), + withRequestOpts(options...), + ) } // CreateTagOptions represents the available CreateTag() options. @@ -194,46 +159,20 @@ type CreateTagOptions struct { Message *string `url:"message,omitempty" json:"message,omitempty"` } -// CreateTag creates a new tag in the repository that points to the supplied ref. -// -// GitLab API docs: -// https://docs.gitlab.com/api/tags/#create-a-new-tag func (s *TagsService) CreateTag(pid any, opt *CreateTagOptions, options ...RequestOptionFunc) (*Tag, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/repository/tags", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(Tag) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*Tag](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/repository/tags", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteTag deletes a tag of a repository with given name. -// -// GitLab API docs: -// https://docs.gitlab.com/api/tags/#delete-a-tag func (s *TagsService) DeleteTag(pid any, tag string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/repository/tags/%s", PathEscape(project), url.PathEscape(tag)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/repository/tags/%s", ProjectID{pid}, tag), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/terraform_states.go b/vendor/gitlab.com/gitlab-org/api/client-go/terraform_states.go index 1de1ba124..34b30d46b 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/terraform_states.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/terraform_states.go @@ -30,6 +30,8 @@ type ( var _ TerraformStatesServiceInterface = (*TerraformStatesService)(nil) +// TerraformState represents a Terraform state. +// // GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#terraformstate type TerraformState struct { Name string `json:"name"` @@ -40,6 +42,8 @@ type TerraformState struct { LockedAt time.Time `json:"lockedAt"` } +// TerraformStateVersion represents a Terraform state version. +// // GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#terraformstateversion type TerraformStateVersion struct { Serial uint64 `json:"serial"` @@ -137,115 +141,71 @@ func (s *TerraformStatesService) Get(projectFullPath string, name string, option } func (s *TerraformStatesService) DownloadLatest(pid any, name string, options ...RequestOptionFunc) (io.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s", PathEscape(project), PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodGet, uri, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/terraform/state/%s", ProjectID{pid}, name), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return &b, resp, nil + return &buf, resp, nil } func (s *TerraformStatesService) Download(pid any, name string, serial uint64, options ...RequestOptionFunc) (io.Reader, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s/versions/%d", PathEscape(project), PathEscape(name), serial) - - req, err := s.client.NewRequest(http.MethodGet, uri, nil, options) - if err != nil { - return nil, nil, err - } - - var b bytes.Buffer - resp, err := s.client.Do(req, &b) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("projects/%s/terraform/state/%s/versions/%d", ProjectID{pid}, name, serial), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return &b, resp, nil + return &buf, resp, nil } // Delete deletes a single Terraform state // // GitLab API docs: https://docs.gitlab.com/user/infrastructure/iac/terraform_state/ func (s *TerraformStatesService) Delete(pid any, name string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s", PathEscape(project), PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodDelete, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/terraform/state/%s", ProjectID{pid}, name), + withRequestOpts(options...), + ) + return resp, err } // DeleteVersion deletes a single Terraform state version // // GitLab API docs: https://docs.gitlab.com/user/infrastructure/iac/terraform_state/ func (s *TerraformStatesService) DeleteVersion(pid any, name string, serial uint64, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s/versions/%d", PathEscape(project), PathEscape(name), serial) - - req, err := s.client.NewRequest(http.MethodDelete, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/terraform/state/%s/versions/%d", ProjectID{pid}, name, serial), + withRequestOpts(options...), + ) + return resp, err } // Lock locks a single Terraform state // // GitLab API docs: https://docs.gitlab.com/user/infrastructure/iac/terraform_state/ func (s *TerraformStatesService) Lock(pid any, name string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s/lock", PathEscape(project), PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodPost, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/terraform/state/%s/lock", ProjectID{pid}, name), + withRequestOpts(options...), + ) + return resp, err } // Unlock unlocks a single Terraform state // // GitLab API docs: https://docs.gitlab.com/user/infrastructure/iac/terraform_state/ func (s *TerraformStatesService) Unlock(pid any, name string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - uri := fmt.Sprintf("projects/%s/terraform/state/%s/lock", PathEscape(project), PathEscape(name)) - - req, err := s.client.NewRequest(http.MethodDelete, uri, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/terraform/state/%s/lock", ProjectID{pid}, name), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/time_stats.go b/vendor/gitlab.com/gitlab-org/api/client-go/time_stats.go index 580acf1a6..035a88d19 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/time_stats.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/time_stats.go @@ -17,7 +17,6 @@ package gitlab import ( - "fmt" "net/http" ) @@ -35,8 +34,8 @@ type timeStatsService struct { type TimeStats struct { HumanTimeEstimate string `json:"human_time_estimate"` HumanTotalTimeSpent string `json:"human_total_time_spent"` - TimeEstimate int `json:"time_estimate"` - TotalTimeSpent int `json:"total_time_spent"` + TimeEstimate int64 `json:"time_estimate"` + TotalTimeSpent int64 `json:"total_time_spent"` } func (t TimeStats) String() string { @@ -54,49 +53,24 @@ type SetTimeEstimateOptions struct { // setTimeEstimate sets the time estimate for a single project issue. // // GitLab docs: https://docs.gitlab.com/api/issues/#set-a-time-estimate-for-an-issue -func (s *timeStatsService) setTimeEstimate(pid any, entity string, issue int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/time_estimate", PathEscape(project), entity, issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(TimeStats) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *timeStatsService) setTimeEstimate(pid any, entity string, issue int64, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { + return do[*TimeStats](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/time_estimate", ProjectID{pid}, entity, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // resetTimeEstimate resets the time estimate for a single project issue. // // GitLab docs: https://docs.gitlab.com/api/issues/#reset-the-time-estimate-for-an-issue -func (s *timeStatsService) resetTimeEstimate(pid any, entity string, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/reset_time_estimate", PathEscape(project), entity, issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(TimeStats) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *timeStatsService) resetTimeEstimate(pid any, entity string, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { + return do[*TimeStats](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/reset_time_estimate", ProjectID{pid}, entity, issue), + withRequestOpts(options...), + ) } // AddSpentTimeOptions represents the available AddSpentTime() options. @@ -110,71 +84,32 @@ type AddSpentTimeOptions struct { // addSpentTime adds spent time for a single project issue. // // GitLab docs: https://docs.gitlab.com/api/issues/#add-spent-time-for-an-issue -func (s *timeStatsService) addSpentTime(pid any, entity string, issue int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/add_spent_time", PathEscape(project), entity, issue) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(TimeStats) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *timeStatsService) addSpentTime(pid any, entity string, issue int64, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) { + return do[*TimeStats](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/add_spent_time", ProjectID{pid}, entity, issue), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // resetSpentTime resets the spent time for a single project issue. // // GitLab docs: https://docs.gitlab.com/api/issues/#reset-spent-time-for-an-issue -func (s *timeStatsService) resetSpentTime(pid any, entity string, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/reset_spent_time", PathEscape(project), entity, issue) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(TimeStats) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *timeStatsService) resetSpentTime(pid any, entity string, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { + return do[*TimeStats](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/%s/%d/reset_spent_time", ProjectID{pid}, entity, issue), + withRequestOpts(options...), + ) } // getTimeSpent gets the spent time for a single project issue. // // GitLab docs: https://docs.gitlab.com/api/issues/#get-time-tracking-stats -func (s *timeStatsService) getTimeSpent(pid any, entity string, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/%s/%d/time_stats", PathEscape(project), entity, issue) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(TimeStats) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *timeStatsService) getTimeSpent(pid any, entity string, issue int64, options ...RequestOptionFunc) (*TimeStats, *Response, error) { + return do[*TimeStats](s.client, + withPath("projects/%s/%s/%d/time_stats", ProjectID{pid}, entity, issue), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/todos.go b/vendor/gitlab.com/gitlab-org/api/client-go/todos.go index 7711e7250..ab47c78c8 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/todos.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/todos.go @@ -17,20 +17,30 @@ package gitlab import ( - "fmt" "net/http" "time" ) type ( TodosServiceInterface interface { + // ListTodos lists all todos created by authenticated user. + // When no filter is applied, it returns all pending todos for the current user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/todos/#get-a-list-of-to-do-items ListTodos(opt *ListTodosOptions, options ...RequestOptionFunc) ([]*Todo, *Response, error) - MarkTodoAsDone(id int, options ...RequestOptionFunc) (*Response, error) + // MarkTodoAsDone marks a single pending todo given by its ID for the current user as done. + // + // GitLab API docs: https://docs.gitlab.com/api/todos/#mark-a-to-do-item-as-done + MarkTodoAsDone(id int64, options ...RequestOptionFunc) (*Response, error) + // MarkAllTodosAsDone marks all pending todos for the current user as done. + // + // GitLab API docs: https://docs.gitlab.com/api/todos/#mark-all-to-do-items-as-done MarkAllTodosAsDone(options ...RequestOptionFunc) (*Response, error) } // TodosService handles communication with the todos related methods of - // the Gitlab API. + // the GitLab API. // // GitLab API docs: https://docs.gitlab.com/api/todos/ TodosService struct { @@ -44,7 +54,7 @@ var _ TodosServiceInterface = (*TodosService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/todos/ type Todo struct { - ID int `json:"id"` + ID int64 `json:"id"` Project *BasicProject `json:"project"` Author *BasicUser `json:"author"` ActionName TodoAction `json:"action_name"` @@ -67,19 +77,19 @@ type TodoTarget struct { Author *BasicUser `json:"author"` CreatedAt *time.Time `json:"created_at"` Description string `json:"description"` - Downvotes int `json:"downvotes"` + Downvotes int64 `json:"downvotes"` ID any `json:"id"` - IID int `json:"iid"` + IID int64 `json:"iid"` Labels []string `json:"labels"` Milestone *Milestone `json:"milestone"` - ProjectID int `json:"project_id"` + ProjectID int64 `json:"project_id"` State string `json:"state"` Subscribed bool `json:"subscribed"` TaskCompletionStatus *TasksCompletionStatus `json:"task_completion_status"` Title string `json:"title"` UpdatedAt *time.Time `json:"updated_at"` - Upvotes int `json:"upvotes"` - UserNotesCount int `json:"user_notes_count"` + Upvotes int64 `json:"upvotes"` + UserNotesCount int64 `json:"user_notes_count"` WebURL string `json:"web_url"` // Only available for type Issue @@ -87,13 +97,13 @@ type TodoTarget struct { DueDate string `json:"due_date"` HasTasks bool `json:"has_tasks"` Links *IssueLinks `json:"_links"` - MovedToID int `json:"moved_to_id"` + MovedToID int64 `json:"moved_to_id"` TimeStats *TimeStats `json:"time_stats"` - Weight int `json:"weight"` + Weight int64 `json:"weight"` // Only available for type MergeRequest MergedAt *time.Time `json:"merged_at"` - ApprovalsBeforeMerge int `json:"approvals_before_merge"` + ApprovalsBeforeMerge int64 `json:"approvals_before_merge"` ForceRemoveSourceBranch bool `json:"force_remove_source_branch"` MergeCommitSHA string `json:"merge_commit_sha"` MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` @@ -103,10 +113,10 @@ type TodoTarget struct { SHA string `json:"sha"` ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"` SourceBranch string `json:"source_branch"` - SourceProjectID int `json:"source_project_id"` + SourceProjectID int64 `json:"source_project_id"` Squash bool `json:"squash"` TargetBranch string `json:"target_branch"` - TargetProjectID int `json:"target_project_id"` + TargetProjectID int64 `json:"target_project_id"` WorkInProgress bool `json:"work_in_progress"` // Only available for type DesignManagement::Design @@ -120,55 +130,35 @@ type TodoTarget struct { type ListTodosOptions struct { ListOptions Action *TodoAction `url:"action,omitempty" json:"action,omitempty"` - AuthorID *int `url:"author_id,omitempty" json:"author_id,omitempty"` - ProjectID *int `url:"project_id,omitempty" json:"project_id,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` + AuthorID *int64 `url:"author_id,omitempty" json:"author_id,omitempty"` + ProjectID *int64 `url:"project_id,omitempty" json:"project_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` State *string `url:"state,omitempty" json:"state,omitempty"` Type *string `url:"type,omitempty" json:"type,omitempty"` } -// ListTodos lists all todos created by authenticated user. -// When no filter is applied, it returns all pending todos for the current user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/todos/#get-a-list-of-to-do-items func (s *TodosService) ListTodos(opt *ListTodosOptions, options ...RequestOptionFunc) ([]*Todo, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "todos", opt, options) - if err != nil { - return nil, nil, err - } - - var t []*Todo - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[[]*Todo](s.client, + withPath("todos"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// MarkTodoAsDone marks a single pending todo given by its ID for the current user as done. -// -// GitLab API docs: https://docs.gitlab.com/api/todos/#mark-a-to-do-item-as-done -func (s *TodosService) MarkTodoAsDone(id int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("todos/%d/mark_as_done", id) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *TodosService) MarkTodoAsDone(id int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("todos/%d/mark_as_done", id), + withRequestOpts(options...), + ) + return resp, err } -// MarkAllTodosAsDone marks all pending todos for the current user as done. -// -// GitLab API docs: https://docs.gitlab.com/api/todos/#mark-all-to-do-items-as-done func (s *TodosService) MarkAllTodosAsDone(options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "todos/mark_as_done", nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("todos/mark_as_done"), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/topics.go b/vendor/gitlab.com/gitlab-org/api/client-go/topics.go index abd4ff453..e2cca41ec 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/topics.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/topics.go @@ -18,20 +18,39 @@ package gitlab import ( "encoding/json" - "fmt" "io" "net/http" - - retryablehttp "github.com/hashicorp/go-retryablehttp" ) type ( TopicsServiceInterface interface { + // ListTopics returns a list of project topics in the GitLab instance ordered + // by number of associated projects. + // + // GitLab API docs: https://docs.gitlab.com/api/topics/#list-topics ListTopics(opt *ListTopicsOptions, options ...RequestOptionFunc) ([]*Topic, *Response, error) - GetTopic(topic int, options ...RequestOptionFunc) (*Topic, *Response, error) + // GetTopic gets a project topic by ID. + // + // GitLab API docs: https://docs.gitlab.com/api/topics/#get-a-topic + GetTopic(topic int64, options ...RequestOptionFunc) (*Topic, *Response, error) + // CreateTopic creates a new project topic. + // + // GitLab API docs: + // https://docs.gitlab.com/api/topics/#create-a-project-topic CreateTopic(opt *CreateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) - UpdateTopic(topic int, opt *UpdateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) - DeleteTopic(topic int, options ...RequestOptionFunc) (*Response, error) + // UpdateTopic updates a project topic. Only available to administrators. + // + // To remove a topic avatar set the TopicAvatar.Filename to an empty string + // and set TopicAvatar.Image to nil. + // + // GitLab API docs: + // https://docs.gitlab.com/api/topics/#update-a-project-topic + UpdateTopic(topic int64, opt *UpdateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) + // DeleteTopic deletes a project topic. Only available to administrators. + // + // GitLab API docs: + // https://docs.gitlab.com/api/topics/#delete-a-project-topic + DeleteTopic(topic int64, options ...RequestOptionFunc) (*Response, error) } // TopicsService handles communication with the topics related methods @@ -49,7 +68,7 @@ var _ TopicsServiceInterface = (*TopicsService)(nil) // // GitLab API docs: https://docs.gitlab.com/api/topics/ type Topic struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Title string `json:"title"` Description string `json:"description"` @@ -69,43 +88,30 @@ type ListTopicsOptions struct { Search *string `url:"search,omitempty" json:"search,omitempty"` } -// ListTopics returns a list of project topics in the GitLab instance ordered -// by number of associated projects. -// -// GitLab API docs: https://docs.gitlab.com/api/topics/#list-topics func (s *TopicsService) ListTopics(opt *ListTopicsOptions, options ...RequestOptionFunc) ([]*Topic, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "topics", opt, options) - if err != nil { - return nil, nil, err - } - - var t []*Topic - resp, err := s.client.Do(req, &t) + res, resp, err := do[[]*Topic](s.client, + withMethod(http.MethodGet), + withPath("topics"), + withAPIOpts(opt), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return t, resp, nil + return res, resp, nil } -// GetTopic gets a project topic by ID. -// -// GitLab API docs: https://docs.gitlab.com/api/topics/#get-a-topic -func (s *TopicsService) GetTopic(topic int, options ...RequestOptionFunc) (*Topic, *Response, error) { - u := fmt.Sprintf("topics/%d", topic) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(Topic) - resp, err := s.client.Do(req, t) +func (s *TopicsService) GetTopic(topic int64, options ...RequestOptionFunc) (*Topic, *Response, error) { + res, resp, err := do[*Topic](s.client, + withMethod(http.MethodGet), + withPath("topics/%d", topic), + withAPIOpts(nil), + withRequestOpts(options...), + ) if err != nil { return nil, resp, err } - - return t, resp, nil + return res, resp, nil } // CreateTopicOptions represents the available CreateTopic() options. @@ -134,38 +140,17 @@ func (a *TopicAvatar) MarshalJSON() ([]byte, error) { return json.Marshal((*alias)(a)) } -// CreateTopic creates a new project topic. -// -// GitLab API docs: -// https://docs.gitlab.com/api/topics/#create-a-project-topic func (s *TopicsService) CreateTopic(opt *CreateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) { - var err error - var req *retryablehttp.Request - - if opt.Avatar == nil { - req, err = s.client.NewRequest(http.MethodPost, "topics", opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPost, - "topics", - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) - } - if err != nil { - return nil, nil, err + reqOpts := []doOption{ + withMethod(http.MethodPost), + withPath("topics"), + withAPIOpts(opt), + withRequestOpts(options...), } - - t := new(Topic) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err + if opt.Avatar != nil { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - return t, resp, nil + return do[*Topic](s.client, reqOpts...) } // UpdateTopicOptions represents the available UpdateTopic() options. @@ -179,56 +164,25 @@ type UpdateTopicOptions struct { Avatar *TopicAvatar `url:"-" json:"avatar,omitempty"` } -// UpdateTopic updates a project topic. Only available to administrators. -// -// To remove a topic avatar set the TopicAvatar.Filename to an empty string -// and set TopicAvatar.Image to nil. -// -// GitLab API docs: -// https://docs.gitlab.com/api/topics/#update-a-project-topic -func (s *TopicsService) UpdateTopic(topic int, opt *UpdateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) { - u := fmt.Sprintf("topics/%d", topic) - - var err error - var req *retryablehttp.Request - - if opt.Avatar == nil || (opt.Avatar.Filename == "" && opt.Avatar.Image == nil) { - req, err = s.client.NewRequest(http.MethodPut, u, opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPut, - u, - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) +func (s *TopicsService) UpdateTopic(topic int64, opt *UpdateTopicOptions, options ...RequestOptionFunc) (*Topic, *Response, error) { + reqOpts := []doOption{ + withMethod(http.MethodPut), + withPath("topics/%d", topic), + withAPIOpts(opt), + withRequestOpts(options...), } - if err != nil { - return nil, nil, err + if opt.Avatar != nil && (opt.Avatar.Filename != "" || opt.Avatar.Image != nil) { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - t := new(Topic) - resp, err := s.client.Do(req, t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*Topic](s.client, reqOpts...) } -// DeleteTopic deletes a project topic. Only available to administrators. -// -// GitLab API docs: -// https://docs.gitlab.com/api/topics/#delete-a-project-topic -func (s *TopicsService) DeleteTopic(topic int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("topics/%d", topic) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *TopicsService) DeleteTopic(topic int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("topics/%d", topic), + withAPIOpts(nil), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/types.go b/vendor/gitlab.com/gitlab-org/api/client-go/types.go index 10c853006..457bfbb13 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/types.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/types.go @@ -86,6 +86,23 @@ const ( AccessTokenStateInactive AccessTokenState = "inactive" ) +// AccessTokenSort represents the available sorting options for access tokens. +// +// GitLab API docs: +// https://docs.gitlab.com/api/group_access_tokens/#list-all-group-access-tokens +type AccessTokenSort string + +const ( + CreatedAsc AccessTokenSort = "created_asc" + CreatedDesc AccessTokenSort = "created_desc" + ExpiresAsc AccessTokenSort = "expires_asc" + ExpiresDesc AccessTokenSort = "expires_desc" + LastUsedAsc AccessTokenSort = "last_used_asc" + LastUsedDesc AccessTokenSort = "last_used_desc" + NameAsc AccessTokenSort = "name_asc" + NameDesc AccessTokenSort = "name_desc" +) + // UserIDValue represents a user ID value within GitLab. type UserIDValue string @@ -103,7 +120,7 @@ type ApproverIDsValue struct { // ApproverIDs is a helper routine that creates a new ApproverIDsValue. func ApproverIDs(v any) *ApproverIDsValue { switch v.(type) { - case UserIDValue, []int: + case UserIDValue, []int64: return &ApproverIDsValue{value: v} default: panic("Unsupported value passed as approver ID") @@ -115,11 +132,11 @@ func (a *ApproverIDsValue) EncodeValues(key string, v *url.Values) error { switch value := a.value.(type) { case UserIDValue: v.Set(key, string(value)) - case []int: + case []int64: v.Del(key) v.Del(key + "[]") for _, id := range value { - v.Add(key+"[]", strconv.Itoa(id)) + v.Add(key+"[]", strconv.FormatInt(id, 10)) } } return nil @@ -143,7 +160,7 @@ type AssigneeIDValue struct { // AssigneeID is a helper routine that creates a new AssigneeIDValue. func AssigneeID(v any) *AssigneeIDValue { switch v.(type) { - case UserIDValue, int: + case UserIDValue, int, int64: return &AssigneeIDValue{value: v} default: panic("Unsupported value passed as assignee ID") @@ -157,6 +174,8 @@ func (a *AssigneeIDValue) EncodeValues(key string, v *url.Values) error { v.Set(key, string(value)) case int: v.Set(key, strconv.Itoa(value)) + case int64: + v.Set(key, strconv.FormatInt(value, 10)) } return nil } @@ -179,7 +198,7 @@ type ReviewerIDValue struct { // ReviewerID is a helper routine that creates a new ReviewerIDValue. func ReviewerID(v any) *ReviewerIDValue { switch v.(type) { - case UserIDValue, int: + case UserIDValue, int, int64: return &ReviewerIDValue{value: v} default: panic("Unsupported value passed as reviewer ID") @@ -193,6 +212,8 @@ func (a *ReviewerIDValue) EncodeValues(key string, v *url.Values) error { v.Set(key, string(value)) case int: v.Set(key, strconv.Itoa(value)) + case int64: + v.Set(key, strconv.FormatInt(value, 10)) } return nil } @@ -299,7 +320,7 @@ const ( ProtectionRuleAccessLevelAdmin ProtectionRuleAccessLevel = "admin" ) -// DeploymentApprovalStatus represents a Gitlab deployment approval status. +// DeploymentApprovalStatus represents a GitLab deployment approval status. type DeploymentApprovalStatus string // These constants represent all valid deployment approval statuses. @@ -308,7 +329,7 @@ const ( DeploymentApprovalStatusRejected DeploymentApprovalStatus = "rejected" ) -// DeploymentStatusValue represents a Gitlab deployment status. +// DeploymentStatusValue represents a GitLab deployment status. type DeploymentStatusValue string // These constants represent all valid deployment statuses. @@ -477,10 +498,18 @@ func (t *ISOTime) UnmarshalJSON(data []byte) error { return nil } - isotime, err := time.Parse(`"`+iso8601+`"`, string(data)) - *t = ISOTime(isotime) + // Try parsing as datetime first (ISO 8601 with time) + isotime, err := time.Parse(`"`+time.RFC3339+`"`, string(data)) + if err != nil { + // If that fails, try parsing as date-only + isotime, err = time.Parse(`"`+iso8601+`"`, string(data)) + if err != nil { + return err + } + } - return err + *t = ISOTime(isotime) + return nil } // EncodeValues implements the query.Encoder interface. @@ -718,9 +747,10 @@ type ResourceGroupProcessMode string // GitLab API docs: // https://docs.gitlab.com/ci/resource_groups/#process-modes const ( - Unordered ResourceGroupProcessMode = "unordered" - OldestFirst ResourceGroupProcessMode = "oldest_first" - NewestFirst ResourceGroupProcessMode = "newest_first" + Unordered ResourceGroupProcessMode = "unordered" + OldestFirst ResourceGroupProcessMode = "oldest_first" + NewestFirst ResourceGroupProcessMode = "newest_first" + NewestReadyFirst ResourceGroupProcessMode = "newest_ready_first" ) // SharedRunnersSettingValue determines whether shared runners are enabled for a @@ -774,8 +804,8 @@ const ( // TasksCompletionStatus represents tasks of the issue/merge request. type TasksCompletionStatus struct { - Count int `json:"count"` - CompletedCount int `json:"completed_count"` + Count int64 `json:"count"` + CompletedCount int64 `json:"completed_count"` } // TodoAction represents the available actions that can be performed on a todo. @@ -864,16 +894,10 @@ type BoolValue bool // https://github.com/gitlabhq/terraform-provider-gitlab/issues/348 func (t *BoolValue) UnmarshalJSON(b []byte) error { switch string(b) { - case `"1"`: + case `"1"`, `"true"`: *t = true return nil - case `"0"`: - *t = false - return nil - case `"true"`: - *t = true - return nil - case `"false"`: + case `"0"`, `"false"`: *t = false return nil default: @@ -899,3 +923,21 @@ const ( CiPipelineVariablesMaintainerRole CIPipelineVariablesMinimumOverrideRoleValue = "maintainer" CIPipelineVariablesDeveloperRole CIPipelineVariablesMinimumOverrideRoleValue = "developer" ) + +// EnabledGitAccessProtocolValue represents a git access protocol value. +type EnabledGitAccessProtocolValue string + +const ( + EnabledGitAccessProtocolSSH EnabledGitAccessProtocolValue = "ssh" + EnabledGitAccessProtocolHTTP EnabledGitAccessProtocolValue = "http" + EnabledGitAccessProtocolAll EnabledGitAccessProtocolValue = "all" +) + +// DuoAvailabilityValue represents a GitLab Duo availability value. +type DuoAvailabilityValue string + +const ( + DuoAvailabilityDefaultOn DuoAvailabilityValue = "default_on" + DuoAvailabilityDefaultOff DuoAvailabilityValue = "default_off" + DuoAvailabilityNeverOn DuoAvailabilityValue = "never_on" // Displayed as "Always Off" in the UI +) diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/usage_data.go b/vendor/gitlab.com/gitlab-org/api/client-go/usage_data.go index 788522a64..737f72c6a 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/usage_data.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/usage_data.go @@ -9,11 +9,35 @@ import ( type ( UsageDataServiceInterface interface { + // GetServicePing gets the current service ping data. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#export-service-ping-data GetServicePing(options ...RequestOptionFunc) (*ServicePingData, *Response, error) + // GetMetricDefinitionsAsYAML gets all metric definitions as a single YAML file. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#export-metric-definitions-as-a-single-yaml-file GetMetricDefinitionsAsYAML(options ...RequestOptionFunc) (io.Reader, *Response, error) + // GetQueries gets all raw SQL queries used to compute service ping. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#export-service-ping-sql-queries GetQueries(options ...RequestOptionFunc) (*ServicePingQueries, *Response, error) - GetNonSQLMetrics(options ...RequestOptionFunc) (*ServicePingNonSqlMetrics, *Response, error) + // GetNonSQLMetrics gets all non-SQL metrics data used in the service ping. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#usagedatanonsqlmetrics-api + GetNonSQLMetrics(options ...RequestOptionFunc) (*ServicePingNonSQLMetrics, *Response, error) + // TrackEvent tracks an internal GitLab event. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#events-tracking-api TrackEvent(opt *TrackEventOptions, options ...RequestOptionFunc) (*Response, error) + // TrackEvents tracks multiple internal GitLab events. + // + // GitLab API docs: + // https://docs.gitlab.com/api/usage_data/#events-tracking-api TrackEvents(opt *TrackEventsOptions, options ...RequestOptionFunc) (*Response, error) } @@ -30,46 +54,24 @@ type ( type ServicePingData struct { RecordedAt *time.Time `json:"recorded_at"` License map[string]string `json:"license"` - Counts map[string]int `json:"counts"` + Counts map[string]int64 `json:"counts"` } -// GetServicePing gets the current service ping data. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#export-service-ping-data func (s *UsageDataService) GetServicePing(options ...RequestOptionFunc) (*ServicePingData, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "usage_data/service_ping", nil, options) - if err != nil { - return nil, nil, err - } - - sp := new(ServicePingData) - resp, err := s.client.Do(req, sp) - if err != nil { - return nil, resp, err - } - - return sp, resp, nil + return do[*ServicePingData](s.client, + withPath("usage_data/service_ping"), + withRequestOpts(options...), + ) } -// GetMetricDefinitionsAsYAML gets all metric definitions as a single YAML file. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#export-metric-definitions-as-a-single-yaml-file func (s *UsageDataService) GetMetricDefinitionsAsYAML(options ...RequestOptionFunc) (io.Reader, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "usage_data/metric_definitions", nil, options) - if err != nil { - return nil, nil, err - } - - req.Header.Set("Accept", "text/yaml") - - var buf bytes.Buffer - resp, err := s.client.Do(req, &buf) + buf, resp, err := do[bytes.Buffer](s.client, + withPath("usage_data/metric_definitions"), + withRequestOpts(append([]RequestOptionFunc{WithHeader("Accept", "text/yaml")}, options...)...), + ) if err != nil { return nil, resp, err } - return &buf, resp, nil } @@ -85,13 +87,13 @@ type ServicePingQueries struct { LicenseMD5 string `json:"license_md5"` LicenseSHA256 string `json:"license_sha256"` LicenseID string `json:"license_id"` - HistoricalMaxUsers int `json:"historical_max_users"` + HistoricalMaxUsers int64 `json:"historical_max_users"` Licensee map[string]string `json:"licensee"` - LicenseUserCount int `json:"license_user_count"` + LicenseUserCount int64 `json:"license_user_count"` LicenseStartsAt string `json:"license_starts_at"` LicenseExpiresAt string `json:"license_expires_at"` LicensePlan string `json:"license_plan"` - LicenseAddOns map[string]int `json:"license_add_ons"` + LicenseAddOns map[string]int64 `json:"license_add_ons"` LicenseTrial string `json:"license_trial"` LicenseSubscriptionID string `json:"license_subscription_id"` License map[string]string `json:"license"` @@ -99,89 +101,62 @@ type ServicePingQueries struct { Counts map[string]string `json:"counts"` } -// GetQueries gets all raw SQL queries used to compute service ping. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#export-service-ping-sql-queries func (s *UsageDataService) GetQueries(options ...RequestOptionFunc) (*ServicePingQueries, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "usage_data/queries", nil, options) - if err != nil { - return nil, nil, err - } - - sq := new(ServicePingQueries) - resp, err := s.client.Do(req, sq) - if err != nil { - return nil, resp, err - } - - return sq, resp, nil + return do[*ServicePingQueries](s.client, + withPath("usage_data/queries"), + withRequestOpts(options...), + ) } -// ServicePingNonSqlMetrics represents the non-SQL metrics used in service ping. -type ServicePingNonSqlMetrics struct { +// ServicePingNonSQLMetrics represents the non-SQL metrics used in service ping. +type ServicePingNonSQLMetrics struct { RecordedAt string `json:"recorded_at"` UUID string `json:"uuid"` Hostname string `json:"hostname"` Version string `json:"version"` InstallationType string `json:"installation_type"` - ActiveUserCount int `json:"active_user_count"` + ActiveUserCount int64 `json:"active_user_count"` Edition string `json:"edition"` LicenseMD5 string `json:"license_md5"` LicenseSHA256 string `json:"license_sha256"` LicenseID string `json:"license_id"` - HistoricalMaxUsers int `json:"historical_max_users"` + HistoricalMaxUsers int64 `json:"historical_max_users"` Licensee map[string]string `json:"licensee"` - LicenseUserCount int `json:"license_user_count"` + LicenseUserCount int64 `json:"license_user_count"` LicenseStartsAt string `json:"license_starts_at"` LicenseExpiresAt string `json:"license_expires_at"` LicensePlan string `json:"license_plan"` - LicenseAddOns map[string]int `json:"license_add_ons"` + LicenseAddOns map[string]int64 `json:"license_add_ons"` LicenseTrial string `json:"license_trial"` LicenseSubscriptionID string `json:"license_subscription_id"` License map[string]string `json:"license"` Settings map[string]string `json:"settings"` } -// GetNonSQLMetrics gets all non-SQL metrics data used in the service ping. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#usagedatanonsqlmetrics-api -func (s *UsageDataService) GetNonSQLMetrics(options ...RequestOptionFunc) (*ServicePingNonSqlMetrics, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "usage_data/non_sql_metrics", nil, options) - if err != nil { - return nil, nil, err - } - - nsm := new(ServicePingNonSqlMetrics) - resp, err := s.client.Do(req, nsm) - if err != nil { - return nil, resp, err - } - - return nsm, resp, nil +func (s *UsageDataService) GetNonSQLMetrics(options ...RequestOptionFunc) (*ServicePingNonSQLMetrics, *Response, error) { + return do[*ServicePingNonSQLMetrics](s.client, + withPath("usage_data/non_sql_metrics"), + withRequestOpts(options...), + ) } // TrackEventOptions represents the available options for tracking events. type TrackEventOptions struct { Event string `json:"event" url:"event"` SendToSnowplow *bool `json:"send_to_snowplow,omitempty" url:"send_to_snowplow,omitempty"` - NamespaceID *int `json:"namespace_id,omitempty" url:"namespace_id,omitempty"` - ProjectID *int `json:"project_id,omitempty" url:"project_id,omitempty"` + NamespaceID *int64 `json:"namespace_id,omitempty" url:"namespace_id,omitempty"` + ProjectID *int64 `json:"project_id,omitempty" url:"project_id,omitempty"` AdditionalProperties map[string]string `json:"additional_properties,omitempty" url:"additional_properties,omitempty"` } -// TrackEvent tracks an internal GitLab event. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#events-tracking-api func (s *UsageDataService) TrackEvent(opt *TrackEventOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "usage_data/track_event", opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("usage_data/track_event"), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } // TrackEventsOptions represents the available options for tracking multiple events. @@ -189,15 +164,12 @@ type TrackEventsOptions struct { Events []TrackEventOptions `json:"events" url:"events"` } -// TrackEvents tracks multiple internal GitLab events. -// -// GitLab API docs: -// https://docs.gitlab.com/api/usage_data/#events-tracking-api func (s *UsageDataService) TrackEvents(opt *TrackEventsOptions, options ...RequestOptionFunc) (*Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "usage_data/track_events", opt, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("usage_data/track_events"), + withAPIOpts(opt), + withRequestOpts(options...), + ) + return resp, err } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/users.go b/vendor/gitlab.com/gitlab-org/api/client-go/users.go index 93c72216f..b97cd4eb6 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/users.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/users.go @@ -23,69 +23,284 @@ import ( "io" "net" "net/http" - "strings" + "text/template" "time" - - "github.com/hashicorp/go-retryablehttp" ) type ( UsersServiceInterface interface { + // ListUsers gets a list of users. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#list-users ListUsers(opt *ListUsersOptions, options ...RequestOptionFunc) ([]*User, *Response, error) - GetUser(user int, opt GetUsersOptions, options ...RequestOptionFunc) (*User, *Response, error) + // GetUser gets a single user. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#get-a-single-user + GetUser(user int64, opt GetUsersOptions, options ...RequestOptionFunc) (*User, *Response, error) + // CreateUser creates a new user. Note only administrators can create new users. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#create-a-user CreateUser(opt *CreateUserOptions, options ...RequestOptionFunc) (*User, *Response, error) - ModifyUser(user int, opt *ModifyUserOptions, options ...RequestOptionFunc) (*User, *Response, error) - DeleteUser(user int, options ...RequestOptionFunc) (*Response, error) + // ModifyUser modifies an existing user. Only administrators can change attributes + // of a user. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#modify-a-user + ModifyUser(user int64, opt *ModifyUserOptions, options ...RequestOptionFunc) (*User, *Response, error) + // DeleteUser deletes a user. Available only for administrators. This is an + // idempotent function, calling this function for a non-existent user id still + // returns a status code 200 OK. The JSON response differs if the user was + // actually deleted or not. In the former the user is returned and in the + // latter not. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#delete-a-user + DeleteUser(user int64, options ...RequestOptionFunc) (*Response, error) + // CurrentUser gets currently authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/users/#get-the-current-user CurrentUser(options ...RequestOptionFunc) (*User, *Response, error) + // CurrentUserStatus retrieves the user status + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#get-your-user-status CurrentUserStatus(options ...RequestOptionFunc) (*UserStatus, *Response, error) + // GetUserStatus retrieves a user's status. + // + // uid can be either a user ID (int) or a username (string); will trim one "@" character off the username, if present. + // Other types will cause an error to be returned. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#get-the-status-of-a-user GetUserStatus(uid any, options ...RequestOptionFunc) (*UserStatus, *Response, error) + // SetUserStatus sets the user's status + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#set-your-user-status SetUserStatus(opt *UserStatusOptions, options ...RequestOptionFunc) (*UserStatus, *Response, error) - GetUserAssociationsCount(user int, options ...RequestOptionFunc) (*UserAssociationsCount, *Response, error) + // GetUserAssociationsCount gets a list of a specified user's associations. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#get-a-count-of-a-users-projects-groups-issues-and-merge-requests + GetUserAssociationsCount(user int64, options ...RequestOptionFunc) (*UserAssociationsCount, *Response, error) + // ListSSHKeys gets a list of currently authenticated user's SSH keys. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys ListSSHKeys(opt *ListSSHKeysOptions, options ...RequestOptionFunc) ([]*SSHKey, *Response, error) + // ListSSHKeysForUser gets a list of a specified user's SSH keys. + // + // uid can be either a user ID (int) or a username (string). If a username + // is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys-for-a-user ListSSHKeysForUser(uid any, opt *ListSSHKeysForUserOptions, options ...RequestOptionFunc) ([]*SSHKey, *Response, error) - GetSSHKey(key int, options ...RequestOptionFunc) (*SSHKey, *Response, error) - GetSSHKeyForUser(user int, key int, options ...RequestOptionFunc) (*SSHKey, *Response, error) + // GetSSHKey gets a single key. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-an-ssh-key + GetSSHKey(key int64, options ...RequestOptionFunc) (*SSHKey, *Response, error) + // GetSSHKeyForUser gets a single key for a given user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-an-ssh-key-for-a-user + GetSSHKeyForUser(user int64, key int64, options ...RequestOptionFunc) (*SSHKey, *Response, error) + // AddSSHKey creates a new key owned by the currently authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-an-ssh-key AddSSHKey(opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) - AddSSHKeyForUser(user int, opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) - DeleteSSHKey(key int, options ...RequestOptionFunc) (*Response, error) - DeleteSSHKeyForUser(user, key int, options ...RequestOptionFunc) (*Response, error) + // AddSSHKeyForUser creates new key owned by specified user. Available only for + // admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-an-ssh-key-for-a-user + AddSSHKeyForUser(user int64, opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) + // DeleteSSHKey deletes key owned by currently authenticated user. This is an + // idempotent function and calling it on a key that is already deleted or not + // available results in 200 OK. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#delete-an-ssh-key + DeleteSSHKey(key int64, options ...RequestOptionFunc) (*Response, error) + // DeleteSSHKeyForUser deletes key owned by a specified user. Available only + // for admin. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#delete-an-ssh-key-for-a-user + DeleteSSHKeyForUser(user, key int64, options ...RequestOptionFunc) (*Response, error) + // ListGPGKeys gets a list of currently authenticated userโ€™s GPG keys. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-gpg-keys ListGPGKeys(options ...RequestOptionFunc) ([]*GPGKey, *Response, error) - GetGPGKey(key int, options ...RequestOptionFunc) (*GPGKey, *Response, error) + // GetGPGKey gets a specific GPG key of currently authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-a-gpg-key + GetGPGKey(key int64, options ...RequestOptionFunc) (*GPGKey, *Response, error) + // AddGPGKey creates a new GPG key owned by the currently authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-a-gpg-key AddGPGKey(opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) - DeleteGPGKey(key int, options ...RequestOptionFunc) (*Response, error) - ListGPGKeysForUser(user int, options ...RequestOptionFunc) ([]*GPGKey, *Response, error) - GetGPGKeyForUser(user, key int, options ...RequestOptionFunc) (*GPGKey, *Response, error) - AddGPGKeyForUser(user int, opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) - DeleteGPGKeyForUser(user, key int, options ...RequestOptionFunc) (*Response, error) + // DeleteGPGKey deletes a GPG key owned by currently authenticated user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#delete-a-gpg-key + DeleteGPGKey(key int64, options ...RequestOptionFunc) (*Response, error) + // ListGPGKeysForUser gets a list of a specified userโ€™s GPG keys. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#list-all-gpg-keys-for-a-user + ListGPGKeysForUser(user int64, options ...RequestOptionFunc) ([]*GPGKey, *Response, error) + // GetGPGKeyForUser gets a specific GPG key for a given user. + // + // GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-a-gpg-key-for-a-user + GetGPGKeyForUser(user, key int64, options ...RequestOptionFunc) (*GPGKey, *Response, error) + // AddGPGKeyForUser creates new GPG key owned by the specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#add-a-gpg-key-for-a-user + AddGPGKeyForUser(user int64, opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) + // DeleteGPGKeyForUser deletes a GPG key owned by a specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_keys/#delete-a-gpg-key-for-a-user + DeleteGPGKeyForUser(user, key int64, options ...RequestOptionFunc) (*Response, error) + // ListEmails gets a list of currently authenticated user's Emails. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses ListEmails(options ...RequestOptionFunc) ([]*Email, *Response, error) - ListEmailsForUser(user int, opt *ListEmailsForUserOptions, options ...RequestOptionFunc) ([]*Email, *Response, error) - GetEmail(email int, options ...RequestOptionFunc) (*Email, *Response, error) + // ListEmailsForUser gets a list of a specified user's Emails. Available + // only for admin + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses-for-a-user + ListEmailsForUser(user int64, opt *ListEmailsForUserOptions, options ...RequestOptionFunc) ([]*Email, *Response, error) + // GetEmail gets a single email. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#get-details-on-an-email-address + GetEmail(email int64, options ...RequestOptionFunc) (*Email, *Response, error) + // AddEmail creates a new email owned by the currently authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#add-an-email-address AddEmail(opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) - AddEmailForUser(user int, opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) - DeleteEmail(email int, options ...RequestOptionFunc) (*Response, error) - DeleteEmailForUser(user, email int, options ...RequestOptionFunc) (*Response, error) - BlockUser(user int, options ...RequestOptionFunc) error - UnblockUser(user int, options ...RequestOptionFunc) error - BanUser(user int, options ...RequestOptionFunc) error - UnbanUser(user int, options ...RequestOptionFunc) error - DeactivateUser(user int, options ...RequestOptionFunc) error - ActivateUser(user int, options ...RequestOptionFunc) error - ApproveUser(user int, options ...RequestOptionFunc) error - RejectUser(user int, options ...RequestOptionFunc) error - GetAllImpersonationTokens(user int, opt *GetAllImpersonationTokensOptions, options ...RequestOptionFunc) ([]*ImpersonationToken, *Response, error) - GetImpersonationToken(user, token int, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) - CreateImpersonationToken(user int, opt *CreateImpersonationTokenOptions, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) - RevokeImpersonationToken(user, token int, options ...RequestOptionFunc) (*Response, error) - CreatePersonalAccessToken(user int, opt *CreatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + // AddEmailForUser creates new email owned by specified user. Available only for + // admin. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#add-an-email-address-for-a-user + AddEmailForUser(user int64, opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) + // DeleteEmail deletes email owned by currently authenticated user. This is an + // idempotent function and calling it on a key that is already deleted or not + // available results in 200 OK. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#delete-an-email-address + DeleteEmail(email int64, options ...RequestOptionFunc) (*Response, error) + // DeleteEmailForUser deletes email owned by a specified user. Available only + // for admin. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_email_addresses/#delete-an-email-address-for-a-user + DeleteEmailForUser(user, email int64, options ...RequestOptionFunc) (*Response, error) + // BlockUser blocks the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#block-access-to-a-user + BlockUser(user int64, options ...RequestOptionFunc) error + // UnblockUser unblocks the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#unblock-access-to-a-user + UnblockUser(user int64, options ...RequestOptionFunc) error + // BanUser bans the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#ban-a-user + BanUser(user int64, options ...RequestOptionFunc) error + // UnbanUser unbans the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#unban-a-user + UnbanUser(user int64, options ...RequestOptionFunc) error + // DeactivateUser deactivate the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#deactivate-a-user + DeactivateUser(user int64, options ...RequestOptionFunc) error + // ActivateUser activate the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#reactivate-a-user + ActivateUser(user int64, options ...RequestOptionFunc) error + // ApproveUser approve the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#approve-access-to-a-user + ApproveUser(user int64, options ...RequestOptionFunc) error + // RejectUser reject the specified user. Available only for admin. + // + // GitLab API docs: https://docs.gitlab.com/api/user_moderation/#reject-access-to-a-user + RejectUser(user int64, options ...RequestOptionFunc) error + // GetAllImpersonationTokens retrieves all impersonation tokens of a user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#list-all-impersonation-tokens-for-a-user + GetAllImpersonationTokens(user int64, opt *GetAllImpersonationTokensOptions, options ...RequestOptionFunc) ([]*ImpersonationToken, *Response, error) + // GetImpersonationToken retrieves an impersonation token of a user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#get-an-impersonation-token-for-a-user + GetImpersonationToken(user, token int64, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) + // CreateImpersonationToken creates an impersonation token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#create-an-impersonation-token + CreateImpersonationToken(user int64, opt *CreateImpersonationTokenOptions, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) + // RevokeImpersonationToken revokes an impersonation token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#revoke-an-impersonation-token + RevokeImpersonationToken(user, token int64, options ...RequestOptionFunc) (*Response, error) + // CreatePersonalAccessToken creates a personal access token. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#create-a-personal-access-token-for-a-user + CreatePersonalAccessToken(user int64, opt *CreatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + // CreatePersonalAccessTokenForCurrentUser creates a personal access token with limited scopes for the currently authenticated user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_tokens/#create-a-personal-access-token CreatePersonalAccessTokenForCurrentUser(opt *CreatePersonalAccessTokenForCurrentUserOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) + // GetUserActivities retrieves user activities (admin only) + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#list-a-users-activity GetUserActivities(opt *GetUserActivitiesOptions, options ...RequestOptionFunc) ([]*UserActivity, *Response, error) - GetUserMemberships(user int, opt *GetUserMembershipOptions, options ...RequestOptionFunc) ([]*UserMembership, *Response, error) - DisableTwoFactor(user int, options ...RequestOptionFunc) error + // GetUserMemberships retrieves a list of the user's memberships. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#list-projects-and-groups-that-a-user-is-a-member-of + GetUserMemberships(user int64, opt *GetUserMembershipOptions, options ...RequestOptionFunc) ([]*UserMembership, *Response, error) + // DisableTwoFactor disables two factor authentication for the specified user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#disable-two-factor-authentication-for-a-user + DisableTwoFactor(user int64, options ...RequestOptionFunc) error + // CreateUserRunner creates a runner linked to the current user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#create-a-runner-linked-to-a-user CreateUserRunner(opts *CreateUserRunnerOptions, options ...RequestOptionFunc) (*UserRunner, *Response, error) + // CreateServiceAccountUser creates a new service account user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_service_accounts/#create-a-service-account-user CreateServiceAccountUser(opts *CreateServiceAccountUserOptions, options ...RequestOptionFunc) (*User, *Response, error) + // ListServiceAccounts lists all service accounts. + // + // GitLab API docs: + // https://docs.gitlab.com/api/user_service_accounts/#list-all-service-account-users ListServiceAccounts(opt *ListServiceAccountsOptions, options ...RequestOptionFunc) ([]*ServiceAccount, *Response, error) + // UploadAvatar uploads an avatar to the current user. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#upload-an-avatar-for-yourself UploadAvatar(avatar io.Reader, filename string, options ...RequestOptionFunc) (*User, *Response, error) - DeleteUserIdentity(user int, provider string, options ...RequestOptionFunc) (*Response, error) + // DeleteUserIdentity deletes a user's authentication identity using the provider + // name associated with that identity. Only available for administrators. + // + // GitLab API docs: + // https://docs.gitlab.com/api/users/#delete-authentication-identity-from-a-user + DeleteUserIdentity(user int64, provider string, options ...RequestOptionFunc) (*Response, error) // events.go ListUserContributionEvents(uid any, opt *ListContributionEventsOptions, options ...RequestOptionFunc) ([]*ContributionEvent, *Response, error) @@ -120,11 +335,24 @@ var ( // BasicUser included in other service responses (such as merge requests, pipelines, etc). type BasicUser struct { - ID int `json:"id"` - Username string `json:"username"` - Name string `json:"name"` - State string `json:"state"` - Locked bool `json:"locked"` + ID int64 `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + + // State represents the administrative status of the user account. + // Common values: "active", "blocked", "deactivated", "banned", + // "ldap_blocked", "blocked_pending_approval". + // + // This is independent from the Locked field: State tracks permanent + // administrative actions, while Locked handles temporary login failures. + State string `json:"state"` + + // Locked indicates whether the user account is temporarily locked due to + // excessive failed login attempts. This is separate from administrative + // blocking (the State field). Locks automatically expire after a configured + // time period (default: 10 minutes). + Locked bool `json:"locked"` + CreatedAt *time.Time `json:"created_at"` AvatarURL string `json:"avatar_url"` WebURL string `json:"web_url"` @@ -135,7 +363,7 @@ type BasicUser struct { // GitLab API docs: // https://docs.gitlab.com/api/user_service_accounts/ type ServiceAccount struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Name string `json:"name"` } @@ -144,7 +372,7 @@ type ServiceAccount struct { // // GitLab API docs: https://docs.gitlab.com/api/users/ type User struct { - ID int `json:"id"` + ID int64 `json:"id"` Username string `json:"username"` Email string `json:"email"` Name string `json:"name"` @@ -163,16 +391,16 @@ type User struct { JobTitle string `json:"job_title"` ExternUID string `json:"extern_uid"` Provider string `json:"provider"` - ThemeID int `json:"theme_id"` + ThemeID int64 `json:"theme_id"` LastActivityOn *ISOTime `json:"last_activity_on"` - ColorSchemeID int `json:"color_scheme_id"` + ColorSchemeID int64 `json:"color_scheme_id"` IsAdmin bool `json:"is_admin"` IsAuditor bool `json:"is_auditor"` AvatarURL string `json:"avatar_url"` CanCreateGroup bool `json:"can_create_group"` CanCreateProject bool `json:"can_create_project"` CanCreateOrganization bool `json:"can_create_organization"` - ProjectsLimit int `json:"projects_limit"` + ProjectsLimit int64 `json:"projects_limit"` CurrentSignInAt *time.Time `json:"current_sign_in_at"` CurrentSignInIP *net.IP `json:"current_sign_in_ip"` LastSignInAt *time.Time `json:"last_sign_in_at"` @@ -183,11 +411,11 @@ type User struct { Identities []*UserIdentity `json:"identities"` External bool `json:"external"` PrivateProfile bool `json:"private_profile"` - SharedRunnersMinutesLimit int `json:"shared_runners_minutes_limit"` - ExtraSharedRunnersMinutesLimit int `json:"extra_shared_runners_minutes_limit"` + SharedRunnersMinutesLimit int64 `json:"shared_runners_minutes_limit"` + ExtraSharedRunnersMinutesLimit int64 `json:"extra_shared_runners_minutes_limit"` UsingLicenseSeat bool `json:"using_license_seat"` CustomAttributes []*CustomAttribute `json:"custom_attributes"` - NamespaceID int `json:"namespace_id"` + NamespaceID int64 `json:"namespace_id"` Locked bool `json:"locked"` CreatedBy *BasicUser `json:"created_by"` } @@ -246,22 +474,12 @@ type ListUsersOptions struct { WithoutProjectBots *bool `url:"without_project_bots,omitempty" json:"without_project_bots,omitempty"` } -// ListUsers gets a list of users. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#list-users func (s *UsersService) ListUsers(opt *ListUsersOptions, options ...RequestOptionFunc) ([]*User, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "users", opt, options) - if err != nil { - return nil, nil, err - } - - var usr []*User - resp, err := s.client.Do(req, &usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil + return do[[]*User](s.client, + withPath("users"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetUsersOptions represents the available GetUser() options. @@ -271,24 +489,12 @@ type GetUsersOptions struct { WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"` } -// GetUser gets a single user. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#get-a-single-user -func (s *UsersService) GetUser(user int, opt GetUsersOptions, options ...RequestOptionFunc) (*User, *Response, error) { - u := fmt.Sprintf("users/%d", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil +func (s *UsersService) GetUser(user int64, opt GetUsersOptions, options ...RequestOptionFunc) (*User, *Response, error) { + return do[*User](s.client, + withPath("users/%d", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateUserOptions represents the available CreateUser() options. @@ -311,150 +517,91 @@ type CreateUserOptions struct { Organization *string `url:"organization,omitempty" json:"organization,omitempty"` Password *string `url:"password,omitempty" json:"password,omitempty"` PrivateProfile *bool `url:"private_profile,omitempty" json:"private_profile,omitempty"` - ProjectsLimit *int `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` + ProjectsLimit *int64 `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` Provider *string `url:"provider,omitempty" json:"provider,omitempty"` ResetPassword *bool `url:"reset_password,omitempty" json:"reset_password,omitempty"` SkipConfirmation *bool `url:"skip_confirmation,omitempty" json:"skip_confirmation,omitempty"` Skype *string `url:"skype,omitempty" json:"skype,omitempty"` - ThemeID *int `url:"theme_id,omitempty" json:"theme_id,omitempty"` + ThemeID *int64 `url:"theme_id,omitempty" json:"theme_id,omitempty"` Twitter *string `url:"twitter,omitempty" json:"twitter,omitempty"` Username *string `url:"username,omitempty" json:"username,omitempty"` WebsiteURL *string `url:"website_url,omitempty" json:"website_url,omitempty"` + ViewDiffsFileByFile *bool `url:"view_diffs_file_by_file,omitempty" json:"view_diffs_file_by_file,omitempty"` + PublicEmail *string `url:"public_email,omitempty" json:"public_email,omitempty"` } -// CreateUser creates a new user. Note only administrators can create new users. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#create-a-user func (s *UsersService) CreateUser(opt *CreateUserOptions, options ...RequestOptionFunc) (*User, *Response, error) { - var err error - var req *retryablehttp.Request - - if opt.Avatar == nil { - req, err = s.client.NewRequest(http.MethodPost, "users", opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPost, - "users", - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) + reqOpts := []doOption{ + withMethod(http.MethodPost), + withPath("users"), + withAPIOpts(opt), + withRequestOpts(options...), } - if err != nil { - return nil, nil, err + if opt.Avatar != nil { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil + return do[*User](s.client, reqOpts...) } // ModifyUserOptions represents the available ModifyUser() options. // // GitLab API docs: https://docs.gitlab.com/api/users/#modify-a-user type ModifyUserOptions struct { - Admin *bool `url:"admin,omitempty" json:"admin,omitempty"` - Avatar *UserAvatar `url:"-" json:"avatar,omitempty"` - Bio *string `url:"bio,omitempty" json:"bio,omitempty"` - CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"` - CommitEmail *string `url:"commit_email,omitempty" json:"commit_email,omitempty"` - Email *string `url:"email,omitempty" json:"email,omitempty"` - External *bool `url:"external,omitempty" json:"external,omitempty"` - ExternUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"` - JobTitle *string `url:"job_title,omitempty" json:"job_title,omitempty"` - Linkedin *string `url:"linkedin,omitempty" json:"linkedin,omitempty"` - Location *string `url:"location,omitempty" json:"location,omitempty"` - Name *string `url:"name,omitempty" json:"name,omitempty"` - Note *string `url:"note,omitempty" json:"note,omitempty"` - Organization *string `url:"organization,omitempty" json:"organization,omitempty"` - Password *string `url:"password,omitempty" json:"password,omitempty"` - PrivateProfile *bool `url:"private_profile,omitempty" json:"private_profile,omitempty"` - ProjectsLimit *int `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` - Provider *string `url:"provider,omitempty" json:"provider,omitempty"` - PublicEmail *string `url:"public_email,omitempty" json:"public_email,omitempty"` - SkipReconfirmation *bool `url:"skip_reconfirmation,omitempty" json:"skip_reconfirmation,omitempty"` - Skype *string `url:"skype,omitempty" json:"skype,omitempty"` - ThemeID *int `url:"theme_id,omitempty" json:"theme_id,omitempty"` - Twitter *string `url:"twitter,omitempty" json:"twitter,omitempty"` - Username *string `url:"username,omitempty" json:"username,omitempty"` - WebsiteURL *string `url:"website_url,omitempty" json:"website_url,omitempty"` -} - -// ModifyUser modifies an existing user. Only administrators can change attributes -// of a user. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#modify-a-user -func (s *UsersService) ModifyUser(user int, opt *ModifyUserOptions, options ...RequestOptionFunc) (*User, *Response, error) { - var err error - var req *retryablehttp.Request - u := fmt.Sprintf("users/%d", user) - - if opt.Avatar == nil || (opt.Avatar.Filename == "" && opt.Avatar.Image == nil) { - req, err = s.client.NewRequest(http.MethodPut, u, opt, options) - } else { - req, err = s.client.UploadRequest( - http.MethodPut, - u, - opt.Avatar.Image, - opt.Avatar.Filename, - UploadAvatar, - opt, - options, - ) - } - if err != nil { - return nil, nil, err - } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil + Admin *bool `url:"admin,omitempty" json:"admin,omitempty"` + Avatar *UserAvatar `url:"-" json:"avatar,omitempty"` + Bio *string `url:"bio,omitempty" json:"bio,omitempty"` + CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"` + CommitEmail *string `url:"commit_email,omitempty" json:"commit_email,omitempty"` + Email *string `url:"email,omitempty" json:"email,omitempty"` + External *bool `url:"external,omitempty" json:"external,omitempty"` + ExternUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"` + JobTitle *string `url:"job_title,omitempty" json:"job_title,omitempty"` + Linkedin *string `url:"linkedin,omitempty" json:"linkedin,omitempty"` + Location *string `url:"location,omitempty" json:"location,omitempty"` + Name *string `url:"name,omitempty" json:"name,omitempty"` + Note *string `url:"note,omitempty" json:"note,omitempty"` + Organization *string `url:"organization,omitempty" json:"organization,omitempty"` + Password *string `url:"password,omitempty" json:"password,omitempty"` + PrivateProfile *bool `url:"private_profile,omitempty" json:"private_profile,omitempty"` + ProjectsLimit *int64 `url:"projects_limit,omitempty" json:"projects_limit,omitempty"` + Provider *string `url:"provider,omitempty" json:"provider,omitempty"` + PublicEmail *string `url:"public_email,omitempty" json:"public_email,omitempty"` + SkipReconfirmation *bool `url:"skip_reconfirmation,omitempty" json:"skip_reconfirmation,omitempty"` + Skype *string `url:"skype,omitempty" json:"skype,omitempty"` + ThemeID *int64 `url:"theme_id,omitempty" json:"theme_id,omitempty"` + Twitter *string `url:"twitter,omitempty" json:"twitter,omitempty"` + Username *string `url:"username,omitempty" json:"username,omitempty"` + WebsiteURL *string `url:"website_url,omitempty" json:"website_url,omitempty"` + ViewDiffsFileByFile *bool `url:"view_diffs_file_by_file,omitempty" json:"view_diffs_file_by_file,omitempty"` } -// DeleteUser deletes a user. Available only for administrators. This is an -// idempotent function, calling this function for a non-existent user id still -// returns a status code 200 OK. The JSON response differs if the user was -// actually deleted or not. In the former the user is returned and in the -// latter not. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#delete-a-user -func (s *UsersService) DeleteUser(user int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d", user) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err +func (s *UsersService) ModifyUser(user int64, opt *ModifyUserOptions, options ...RequestOptionFunc) (*User, *Response, error) { + reqOpts := []doOption{ + withMethod(http.MethodPut), + withPath("users/%d", user), + withAPIOpts(opt), + withRequestOpts(options...), + } + if opt.Avatar != nil && (opt.Avatar.Filename != "" || opt.Avatar.Image != nil) { + reqOpts = append(reqOpts, withUpload(opt.Avatar.Image, opt.Avatar.Filename, UploadAvatar)) } + return do[*User](s.client, reqOpts...) +} - return s.client.Do(req, nil) +func (s *UsersService) DeleteUser(user int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d", user), + withRequestOpts(options...), + ) + return resp, err } -// CurrentUser gets currently authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/users/#get-the-current-user func (s *UsersService) CurrentUser(options ...RequestOptionFunc) (*User, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user", nil, options) - if err != nil { - return nil, nil, err - } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil + return do[*User](s.client, + withPath("user"), + withRequestOpts(options...), + ) } // UserStatus represents the current status of a user @@ -469,52 +616,25 @@ type UserStatus struct { ClearStatusAt *time.Time `json:"clear_status_at"` } -// CurrentUserStatus retrieves the user status -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#get-your-user-status func (s *UsersService) CurrentUserStatus(options ...RequestOptionFunc) (*UserStatus, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user/status", nil, options) - if err != nil { - return nil, nil, err - } - - status := new(UserStatus) - resp, err := s.client.Do(req, status) - if err != nil { - return nil, resp, err - } - - return status, resp, nil + return do[*UserStatus](s.client, + withPath("user/status"), + withRequestOpts(options...), + ) } // GetUserStatus retrieves a user's status. // -// uid can be either a user ID (int) or a username (string); will trim one "@" character off the username, if present. -// Other types will cause an error to be returned. +// uid can be either a user ID (int) or a username (string). If a username +// is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. // // GitLab API docs: // https://docs.gitlab.com/api/users/#get-the-status-of-a-user func (s *UsersService) GetUserStatus(uid any, options ...RequestOptionFunc) (*UserStatus, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - - u := fmt.Sprintf("users/%s/status", strings.TrimPrefix(user, "@")) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - status := new(UserStatus) - resp, err := s.client.Do(req, status) - if err != nil { - return nil, resp, err - } - - return status, resp, nil + return do[*UserStatus](s.client, + withPath("users/%s/status", UserID{uid}), + withRequestOpts(options...), + ) } // UserStatusOptions represents the options required to set the status @@ -528,62 +648,42 @@ type UserStatusOptions struct { ClearStatusAfter *ClearStatusAfterValue `url:"clear_status_after,omitempty" json:"clear_status_after,omitempty"` } -// SetUserStatus sets the user's status -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#set-your-user-status func (s *UsersService) SetUserStatus(opt *UserStatusOptions, options ...RequestOptionFunc) (*UserStatus, *Response, error) { - req, err := s.client.NewRequest(http.MethodPut, "user/status", opt, options) - if err != nil { - return nil, nil, err - } - - status := new(UserStatus) - resp, err := s.client.Do(req, status) - if err != nil { - return nil, resp, err - } - - return status, resp, nil + return do[*UserStatus](s.client, + withMethod(http.MethodPut), + withPath("user/status"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UserAssociationsCount represents the user associations count. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/users/#get-a-count-of-a-users-projects-groups-issues-and-merge-requests type UserAssociationsCount struct { - GroupsCount int `json:"groups_count"` - ProjectsCount int `json:"projects_count"` - IssuesCount int `json:"issues_count"` - MergeRequestsCount int `json:"merge_requests_count"` + GroupsCount int64 `json:"groups_count"` + ProjectsCount int64 `json:"projects_count"` + IssuesCount int64 `json:"issues_count"` + MergeRequestsCount int64 `json:"merge_requests_count"` } // GetUserAssociationsCount gets a list of a specified user associations. // -// Gitlab API docs: +// GitLab API docs: // https://docs.gitlab.com/api/users/#get-a-count-of-a-users-projects-groups-issues-and-merge-requests -func (s *UsersService) GetUserAssociationsCount(user int, options ...RequestOptionFunc) (*UserAssociationsCount, *Response, error) { - u := fmt.Sprintf("users/%d/associations_count", user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - uac := new(UserAssociationsCount) - resp, err := s.client.Do(req, uac) - if err != nil { - return nil, resp, err - } - - return uac, resp, nil +func (s *UsersService) GetUserAssociationsCount(user int64, options ...RequestOptionFunc) (*UserAssociationsCount, *Response, error) { + return do[*UserAssociationsCount](s.client, + withPath("users/%d/associations_count", user), + withRequestOpts(options...), + ) } // SSHKey represents a SSH key. // // GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys type SSHKey struct { - ID int `json:"id"` + ID int64 `json:"id"` Title string `json:"title"` Key string `json:"key"` CreatedAt *time.Time `json:"created_at"` @@ -594,95 +694,53 @@ type SSHKey struct { // ListSSHKeysOptions represents the available ListSSHKeys options. // // GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys -type ListSSHKeysOptions ListOptions +type ListSSHKeysOptions struct { + ListOptions +} -// ListSSHKeys gets a list of currently authenticated user's SSH keys. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys func (s *UsersService) ListSSHKeys(opt *ListSSHKeysOptions, options ...RequestOptionFunc) ([]*SSHKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user/keys", opt, options) - if err != nil { - return nil, nil, err - } - - var k []*SSHKey - resp, err := s.client.Do(req, &k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[[]*SSHKey](s.client, + withPath("user/keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ListSSHKeysForUserOptions represents the available ListSSHKeysForUser() options. // // GitLab API docs: // https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys-for-a-user -type ListSSHKeysForUserOptions ListOptions +type ListSSHKeysForUserOptions struct { + ListOptions +} // ListSSHKeysForUser gets a list of a specified user's SSH keys. // +// uid can be either a user ID (int) or a username (string). If a username +// is provided with a leading "@" (e.g., "@johndoe"), it will be trimmed. +// // GitLab API docs: // https://docs.gitlab.com/api/user_keys/#list-all-ssh-keys-for-a-user func (s *UsersService) ListSSHKeysForUser(uid any, opt *ListSSHKeysForUserOptions, options ...RequestOptionFunc) ([]*SSHKey, *Response, error) { - user, err := parseID(uid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("users/%s/keys", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var k []*SSHKey - resp, err := s.client.Do(req, &k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[[]*SSHKey](s.client, + withPath("users/%s/keys", UserID{uid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetSSHKey gets a single key. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-an-ssh-key -func (s *UsersService) GetSSHKey(key int, options ...RequestOptionFunc) (*SSHKey, *Response, error) { - u := fmt.Sprintf("user/keys/%d", key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(SSHKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) GetSSHKey(key int64, options ...RequestOptionFunc) (*SSHKey, *Response, error) { + return do[*SSHKey](s.client, + withPath("user/keys/%d", key), + withRequestOpts(options...), + ) } -// GetSSHKeyForUser gets a single key for a given user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-an-ssh-key-for-a-user -func (s *UsersService) GetSSHKeyForUser(user int, key int, options ...RequestOptionFunc) (*SSHKey, *Response, error) { - u := fmt.Sprintf("users/%d/keys/%d", user, key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(SSHKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) GetSSHKeyForUser(user int64, key int64, options ...RequestOptionFunc) (*SSHKey, *Response, error) { + return do[*SSHKey](s.client, + withPath("users/%d/keys/%d", user, key), + withRequestOpts(options...), + ) } // AddSSHKeyOptions represents the available AddSSHKey() options. @@ -695,123 +753,63 @@ type AddSSHKeyOptions struct { UsageType *string `url:"usage_type,omitempty" json:"usage_type,omitempty"` } -// AddSSHKey creates a new key owned by the currently authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-an-ssh-key func (s *UsersService) AddSSHKey(opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "user/keys", opt, options) - if err != nil { - return nil, nil, err - } - - k := new(SSHKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[*SSHKey](s.client, + withMethod(http.MethodPost), + withPath("user/keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// AddSSHKeyForUser creates new key owned by specified user. Available only for -// admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-an-ssh-key-for-a-user -func (s *UsersService) AddSSHKeyForUser(user int, opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) { - u := fmt.Sprintf("users/%d/keys", user) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - k := new(SSHKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) AddSSHKeyForUser(user int64, opt *AddSSHKeyOptions, options ...RequestOptionFunc) (*SSHKey, *Response, error) { + return do[*SSHKey](s.client, + withMethod(http.MethodPost), + withPath("users/%d/keys", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteSSHKey deletes key owned by currently authenticated user. This is an -// idempotent function and calling it on a key that is already deleted or not -// available results in 200 OK. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_keys/#delete-an-ssh-key -func (s *UsersService) DeleteSSHKey(key int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("user/keys/%d", key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteSSHKey(key int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("user/keys/%d", key), + withRequestOpts(options...), + ) + return resp, err } -// DeleteSSHKeyForUser deletes key owned by a specified user. Available only -// for admin. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_keys/#delete-an-ssh-key-for-a-user -func (s *UsersService) DeleteSSHKeyForUser(user, key int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d/keys/%d", user, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteSSHKeyForUser(user, key int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d/keys/%d", user, key), + withRequestOpts(options...), + ) + return resp, err } // GPGKey represents a GPG key. // // GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-gpg-keys type GPGKey struct { - ID int `json:"id"` + ID int64 `json:"id"` Key string `json:"key"` CreatedAt *time.Time `json:"created_at"` } -// ListGPGKeys gets a list of currently authenticated userโ€™s GPG keys. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#list-all-gpg-keys func (s *UsersService) ListGPGKeys(options ...RequestOptionFunc) ([]*GPGKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user/gpg_keys", nil, options) - if err != nil { - return nil, nil, err - } - - var ks []*GPGKey - resp, err := s.client.Do(req, &ks) - if err != nil { - return nil, resp, err - } - - return ks, resp, nil + return do[[]*GPGKey](s.client, + withPath("user/gpg_keys"), + withRequestOpts(options...), + ) } -// GetGPGKey gets a specific GPG key of currently authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-a-gpg-key -func (s *UsersService) GetGPGKey(key int, options ...RequestOptionFunc) (*GPGKey, *Response, error) { - u := fmt.Sprintf("user/gpg_keys/%d", key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(GPGKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) GetGPGKey(key int64, options ...RequestOptionFunc) (*GPGKey, *Response, error) { + return do[*GPGKey](s.client, + withPath("user/gpg_keys/%d", key), + withRequestOpts(options...), + ) } // AddGPGKeyOptions represents the available AddGPGKey() options. @@ -821,113 +819,54 @@ type AddGPGKeyOptions struct { Key *string `url:"key,omitempty" json:"key,omitempty"` } -// AddGPGKey creates a new GPG key owned by the currently authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#add-a-gpg-key func (s *UsersService) AddGPGKey(opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "user/gpg_keys", opt, options) - if err != nil { - return nil, nil, err - } - - k := new(GPGKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil + return do[*GPGKey](s.client, + withMethod(http.MethodPost), + withPath("user/gpg_keys"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteGPGKey deletes a GPG key owned by currently authenticated user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#delete-a-gpg-key -func (s *UsersService) DeleteGPGKey(key int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("user/gpg_keys/%d", key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteGPGKey(key int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("user/gpg_keys/%d", key), + withRequestOpts(options...), + ) + return resp, err } -// ListGPGKeysForUser gets a list of a specified userโ€™s GPG keys. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_keys/#list-all-gpg-keys-for-a-user -func (s *UsersService) ListGPGKeysForUser(user int, options ...RequestOptionFunc) ([]*GPGKey, *Response, error) { - u := fmt.Sprintf("users/%d/gpg_keys", user) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - var ks []*GPGKey - resp, err := s.client.Do(req, &ks) - if err != nil { - return nil, resp, err - } - - return ks, resp, nil +func (s *UsersService) ListGPGKeysForUser(user int64, options ...RequestOptionFunc) ([]*GPGKey, *Response, error) { + return do[[]*GPGKey](s.client, + withPath("users/%d/gpg_keys", user), + withRequestOpts(options...), + ) } -// GetGPGKeyForUser gets a specific GPG key for a given user. -// -// GitLab API docs: https://docs.gitlab.com/api/user_keys/#get-a-gpg-key-for-a-user -func (s *UsersService) GetGPGKeyForUser(user, key int, options ...RequestOptionFunc) (*GPGKey, *Response, error) { - u := fmt.Sprintf("users/%d/gpg_keys/%d", user, key) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - k := new(GPGKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) GetGPGKeyForUser(user, key int64, options ...RequestOptionFunc) (*GPGKey, *Response, error) { + return do[*GPGKey](s.client, + withPath("users/%d/gpg_keys/%d", user, key), + withRequestOpts(options...), + ) } -// AddGPGKeyForUser creates new GPG key owned by the specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_keys/#add-a-gpg-key-for-a-user -func (s *UsersService) AddGPGKeyForUser(user int, opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) { - u := fmt.Sprintf("users/%d/gpg_keys", user) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - k := new(GPGKey) - resp, err := s.client.Do(req, k) - if err != nil { - return nil, resp, err - } - - return k, resp, nil +func (s *UsersService) AddGPGKeyForUser(user int64, opt *AddGPGKeyOptions, options ...RequestOptionFunc) (*GPGKey, *Response, error) { + return do[*GPGKey](s.client, + withMethod(http.MethodPost), + withPath("users/%d/gpg_keys", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteGPGKeyForUser deletes a GPG key owned by a specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_keys/#delete-a-gpg-key-for-a-user -func (s *UsersService) DeleteGPGKeyForUser(user, key int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d/gpg_keys/%d", user, key) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteGPGKeyForUser(user, key int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d/gpg_keys/%d", user, key), + withRequestOpts(options...), + ) + return resp, err } // Email represents an Email. @@ -935,77 +874,39 @@ func (s *UsersService) DeleteGPGKeyForUser(user, key int, options ...RequestOpti // GitLab API docs: // https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses type Email struct { - ID int `json:"id"` + ID int64 `json:"id"` Email string `json:"email"` ConfirmedAt *time.Time `json:"confirmed_at"` } -// ListEmails gets a list of currently authenticated user's Emails. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses func (s *UsersService) ListEmails(options ...RequestOptionFunc) ([]*Email, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user/emails", nil, options) - if err != nil { - return nil, nil, err - } - - var e []*Email - resp, err := s.client.Do(req, &e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil + return do[[]*Email](s.client, + withPath("user/emails"), + withRequestOpts(options...), + ) } // ListEmailsForUserOptions represents the available ListEmailsForUser() options. // // GitLab API docs: // https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses-for-a-user -type ListEmailsForUserOptions ListOptions - -// ListEmailsForUser gets a list of a specified user's Emails. Available -// only for admin -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#list-all-email-addresses-for-a-user -func (s *UsersService) ListEmailsForUser(user int, opt *ListEmailsForUserOptions, options ...RequestOptionFunc) ([]*Email, *Response, error) { - u := fmt.Sprintf("users/%d/emails", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var e []*Email - resp, err := s.client.Do(req, &e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil +type ListEmailsForUserOptions struct { + ListOptions } -// GetEmail gets a single email. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#get-details-on-an-email-address -func (s *UsersService) GetEmail(email int, options ...RequestOptionFunc) (*Email, *Response, error) { - u := fmt.Sprintf("user/emails/%d", email) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - e := new(Email) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } +func (s *UsersService) ListEmailsForUser(user int64, opt *ListEmailsForUserOptions, options ...RequestOptionFunc) ([]*Email, *Response, error) { + return do[[]*Email](s.client, + withPath("users/%d/emails", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) +} - return e, resp, nil +func (s *UsersService) GetEmail(email int64, options ...RequestOptionFunc) (*Email, *Response, error) { + return do[*Email](s.client, + withPath("user/emails/%d", email), + withRequestOpts(options...), + ) } // AddEmailOptions represents the available AddEmail() options. @@ -1017,296 +918,197 @@ type AddEmailOptions struct { SkipConfirmation *bool `url:"skip_confirmation,omitempty" json:"skip_confirmation,omitempty"` } -// AddEmail creates a new email owned by the currently authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#add-an-email-address func (s *UsersService) AddEmail(opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "user/emails", opt, options) - if err != nil { - return nil, nil, err - } - - e := new(Email) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil + return do[*Email](s.client, + withMethod(http.MethodPost), + withPath("user/emails"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// AddEmailForUser creates new email owned by specified user. Available only for -// admin. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#add-an-email-address-for-a-user -func (s *UsersService) AddEmailForUser(user int, opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) { - u := fmt.Sprintf("users/%d/emails", user) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - e := new(Email) - resp, err := s.client.Do(req, e) - if err != nil { - return nil, resp, err - } - - return e, resp, nil +func (s *UsersService) AddEmailForUser(user int64, opt *AddEmailOptions, options ...RequestOptionFunc) (*Email, *Response, error) { + return do[*Email](s.client, + withMethod(http.MethodPost), + withPath("users/%d/emails", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteEmail deletes email owned by currently authenticated user. This is an -// idempotent function and calling it on a key that is already deleted or not -// available results in 200 OK. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#delete-an-email-address -func (s *UsersService) DeleteEmail(email int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("user/emails/%d", email) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteEmail(email int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("user/emails/%d", email), + withRequestOpts(options...), + ) + return resp, err } -// DeleteEmailForUser deletes email owned by a specified user. Available only -// for admin. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_email_addresses/#delete-an-email-address-for-a-user -func (s *UsersService) DeleteEmailForUser(user, email int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d/emails/%d", user, email) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) DeleteEmailForUser(user, email int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d/emails/%d", user, email), + withRequestOpts(options...), + ) + return resp, err } -// BlockUser blocks the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#block-access-to-a-user -func (s *UsersService) BlockUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/block", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) - if err != nil && resp == nil { - return err - } - - switch resp.StatusCode { - case 201: - return nil - case 403: - return ErrUserBlockPrevented - case 404: - return ErrUserNotFound - default: - return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) - } +func (s *UsersService) BlockUser(user int64, options ...RequestOptionFunc) error { + _, _, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/block", user), + withRequestOpts(options...), + ) + return err } -// UnblockUser unblocks the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#unblock-access-to-a-user -func (s *UsersService) UnblockUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/unblock", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) UnblockUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/unblock", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 403: + case http.StatusForbidden: return ErrUserUnblockPrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// BanUser bans the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#ban-a-user -func (s *UsersService) BanUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/ban", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) BanUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/ban", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// UnbanUser unbans the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#unban-a-user -func (s *UsersService) UnbanUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/unban", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) UnbanUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/unban", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// DeactivateUser deactivate the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#deactivate-a-user -func (s *UsersService) DeactivateUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/deactivate", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) DeactivateUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/deactivate", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 403: + case http.StatusForbidden: return ErrUserDeactivatePrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// ActivateUser activate the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#reactivate-a-user -func (s *UsersService) ActivateUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/activate", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) ActivateUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/activate", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 403: + case http.StatusForbidden: return ErrUserActivatePrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// ApproveUser approve the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#approve-access-to-a-user -func (s *UsersService) ApproveUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/approve", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) ApproveUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/approve", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 201: + case http.StatusCreated: return nil - case 403: + case http.StatusForbidden: return ErrUserApprovePrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) } } -// RejectUser reject the specified user. Available only for admin. -// -// GitLab API docs: https://docs.gitlab.com/api/user_moderation/#reject-access-to-a-user -func (s *UsersService) RejectUser(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/reject", user) - - req, err := s.client.NewRequest(http.MethodPost, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) RejectUser(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPost), + withPath("users/%d/reject", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 200: + case http.StatusOK: return nil - case 403: + case http.StatusForbidden: return ErrUserRejectPrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound - case 409: + case http.StatusConflict: return ErrUserConflict default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) @@ -1318,7 +1120,7 @@ func (s *UsersService) RejectUser(user int, options ...RequestOptionFunc) error // GitLab API docs: // https://docs.gitlab.com/api/user_tokens/#list-all-impersonation-tokens-for-a-user type ImpersonationToken struct { - ID int `json:"id"` + ID int64 `json:"id"` Name string `json:"name"` Active bool `json:"active"` Token string `json:"token"` @@ -1339,46 +1141,19 @@ type GetAllImpersonationTokensOptions struct { State *string `url:"state,omitempty" json:"state,omitempty"` } -// GetAllImpersonationTokens retrieves all impersonation tokens of a user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#list-all-impersonation-tokens-for-a-user -func (s *UsersService) GetAllImpersonationTokens(user int, opt *GetAllImpersonationTokensOptions, options ...RequestOptionFunc) ([]*ImpersonationToken, *Response, error) { - u := fmt.Sprintf("users/%d/impersonation_tokens", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ts []*ImpersonationToken - resp, err := s.client.Do(req, &ts) - if err != nil { - return nil, resp, err - } - - return ts, resp, nil +func (s *UsersService) GetAllImpersonationTokens(user int64, opt *GetAllImpersonationTokensOptions, options ...RequestOptionFunc) ([]*ImpersonationToken, *Response, error) { + return do[[]*ImpersonationToken](s.client, + withPath("users/%d/impersonation_tokens", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// GetImpersonationToken retrieves an impersonation token of a user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#get-an-impersonation-token-for-a-user -func (s *UsersService) GetImpersonationToken(user, token int, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) { - u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token) - - req, err := s.client.NewRequest(http.MethodGet, u, nil, options) - if err != nil { - return nil, nil, err - } - - t := new(ImpersonationToken) - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *UsersService) GetImpersonationToken(user, token int64, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) { + return do[*ImpersonationToken](s.client, + withPath("users/%d/impersonation_tokens/%d", user, token), + withRequestOpts(options...), + ) } // CreateImpersonationTokenOptions represents the available @@ -1392,40 +1167,22 @@ type CreateImpersonationTokenOptions struct { ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"` } -// CreateImpersonationToken creates an impersonation token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#create-an-impersonation-token -func (s *UsersService) CreateImpersonationToken(user int, opt *CreateImpersonationTokenOptions, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) { - u := fmt.Sprintf("users/%d/impersonation_tokens", user) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(ImpersonationToken) - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *UsersService) CreateImpersonationToken(user int64, opt *CreateImpersonationTokenOptions, options ...RequestOptionFunc) (*ImpersonationToken, *Response, error) { + return do[*ImpersonationToken](s.client, + withMethod(http.MethodPost), + withPath("users/%d/impersonation_tokens", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// RevokeImpersonationToken revokes an impersonation token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#revoke-an-impersonation-token -func (s *UsersService) RevokeImpersonationToken(user, token int, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) +func (s *UsersService) RevokeImpersonationToken(user, token int64, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d/impersonation_tokens/%d", user, token), + withRequestOpts(options...), + ) + return resp, err } // CreatePersonalAccessTokenOptions represents the available @@ -1440,25 +1197,13 @@ type CreatePersonalAccessTokenOptions struct { Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"` } -// CreatePersonalAccessToken creates a personal access token. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#create-a-personal-access-token-for-a-user -func (s *UsersService) CreatePersonalAccessToken(user int, opt *CreatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := fmt.Sprintf("users/%d/personal_access_tokens", user) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(PersonalAccessToken) - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil +func (s *UsersService) CreatePersonalAccessToken(user int64, opt *CreatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("users/%d/personal_access_tokens", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreatePersonalAccessTokenForCurrentUserOptions represents the available @@ -1473,25 +1218,13 @@ type CreatePersonalAccessTokenForCurrentUserOptions struct { ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"` } -// CreatePersonalAccessTokenForCurrentUser creates a personal access token with limited scopes for the currently authenticated user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_tokens/#create-a-personal-access-token func (s *UsersService) CreatePersonalAccessTokenForCurrentUser(opt *CreatePersonalAccessTokenForCurrentUserOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) { - u := "user/personal_access_tokens" - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - t := new(PersonalAccessToken) - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[*PersonalAccessToken](s.client, + withMethod(http.MethodPost), + withPath("user/personal_access_tokens"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UserActivity represents an entry in the user/activities response @@ -1512,23 +1245,12 @@ type GetUserActivitiesOptions struct { From *ISOTime `url:"from,omitempty" json:"from,omitempty"` } -// GetUserActivities retrieves user activities (admin only) -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#list-a-users-activity func (s *UsersService) GetUserActivities(opt *GetUserActivitiesOptions, options ...RequestOptionFunc) ([]*UserActivity, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "user/activities", opt, options) - if err != nil { - return nil, nil, err - } - - var t []*UserActivity - resp, err := s.client.Do(req, &t) - if err != nil { - return nil, resp, err - } - - return t, resp, nil + return do[[]*UserActivity](s.client, + withPath("user/activities"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // UserMembership represents a membership of the user in a namespace or project. @@ -1536,7 +1258,7 @@ func (s *UsersService) GetUserActivities(opt *GetUserActivitiesOptions, options // GitLab API docs: // https://docs.gitlab.com/api/users/#list-projects-and-groups-that-a-user-is-a-member-of type UserMembership struct { - SourceID int `json:"source_id"` + SourceID int64 `json:"source_id"` SourceName string `json:"source_name"` SourceType string `json:"source_type"` AccessLevel AccessLevelValue `json:"access_level"` @@ -1551,52 +1273,32 @@ type GetUserMembershipOptions struct { Type *string `url:"type,omitempty" json:"type,omitempty"` } -// GetUserMemberships retrieves a list of the user's memberships. -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#list-projects-and-groups-that-a-user-is-a-member-of -func (s *UsersService) GetUserMemberships(user int, opt *GetUserMembershipOptions, options ...RequestOptionFunc) ([]*UserMembership, *Response, error) { - u := fmt.Sprintf("users/%d/memberships", user) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var m []*UserMembership - resp, err := s.client.Do(req, &m) - if err != nil { - return nil, resp, err - } - - return m, resp, nil +func (s *UsersService) GetUserMemberships(user int64, opt *GetUserMembershipOptions, options ...RequestOptionFunc) ([]*UserMembership, *Response, error) { + return do[[]*UserMembership](s.client, + withPath("users/%d/memberships", user), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DisableTwoFactor disables two factor authentication for the specified user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#disable-two-factor-authentication-for-a-user -func (s *UsersService) DisableTwoFactor(user int, options ...RequestOptionFunc) error { - u := fmt.Sprintf("users/%d/disable_two_factor", user) - - req, err := s.client.NewRequest(http.MethodPatch, u, nil, options) - if err != nil { - return err - } - - resp, err := s.client.Do(req, nil) +func (s *UsersService) DisableTwoFactor(user int64, options ...RequestOptionFunc) error { + _, resp, err := do[none](s.client, + withMethod(http.MethodPatch), + withPath("users/%d/disable_two_factor", user), + withRequestOpts(options...), + ) if err != nil && resp == nil { return err } switch resp.StatusCode { - case 204: + case http.StatusNoContent: return nil - case 400: + case http.StatusBadRequest: return ErrUserTwoFactorNotEnabled - case 403: + case http.StatusForbidden: return ErrUserDisableTwoFactorPrevented - case 404: + case http.StatusNotFound: return ErrUserNotFound default: return fmt.Errorf("%w: %d", errUnexpectedResultCode, resp.StatusCode) @@ -1608,7 +1310,7 @@ func (s *UsersService) DisableTwoFactor(user int, options ...RequestOptionFunc) // GitLab API docs: // https://docs.gitlab.com/api/users/#create-a-runner-linked-to-a-user type UserRunner struct { - ID int `json:"id"` + ID int64 `json:"id"` Token string `json:"token"` TokenExpiresAt *time.Time `json:"token_expires_at"` } @@ -1619,35 +1321,25 @@ type UserRunner struct { // https://docs.gitlab.com/api/users/#create-a-runner-linked-to-a-user type CreateUserRunnerOptions struct { RunnerType *string `url:"runner_type,omitempty" json:"runner_type,omitempty"` - GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"` - ProjectID *int `url:"project_id,omitempty" json:"project_id,omitempty"` + GroupID *int64 `url:"group_id,omitempty" json:"group_id,omitempty"` + ProjectID *int64 `url:"project_id,omitempty" json:"project_id,omitempty"` Description *string `url:"description,omitempty" json:"description,omitempty"` Paused *bool `url:"paused,omitempty" json:"paused,omitempty"` Locked *bool `url:"locked,omitempty" json:"locked,omitempty"` RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"` TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"` AccessLevel *string `url:"access_level,omitempty" json:"access_level,omitempty"` - MaximumTimeout *int `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` + MaximumTimeout *int64 `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"` MaintenanceNote *string `url:"maintenance_note,omitempty" json:"maintenance_note,omitempty"` } -// CreateUserRunner creates a runner linked to the current user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#create-a-runner-linked-to-a-user func (s *UsersService) CreateUserRunner(opts *CreateUserRunnerOptions, options ...RequestOptionFunc) (*UserRunner, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "user/runners", opts, options) - if err != nil { - return nil, nil, err - } - - r := new(UserRunner) - resp, err := s.client.Do(req, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return do[*UserRunner](s.client, + withMethod(http.MethodPost), + withPath("user/runners"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } // CreateServiceAccountUserOptions represents the available CreateServiceAccountUser() options. @@ -1660,85 +1352,77 @@ type CreateServiceAccountUserOptions struct { Email *string `url:"email,omitempty" json:"email,omitempty"` } -// CreateServiceAccountUser creates a new service account user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_service_accounts/#create-a-service-account-user func (s *UsersService) CreateServiceAccountUser(opts *CreateServiceAccountUserOptions, options ...RequestOptionFunc) (*User, *Response, error) { - req, err := s.client.NewRequest(http.MethodPost, "service_accounts", opts, options) - if err != nil { - return nil, nil, err - } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil + return do[*User](s.client, + withMethod(http.MethodPost), + withPath("service_accounts"), + withAPIOpts(opts), + withRequestOpts(options...), + ) } -// ListServiceAccounts lists all service accounts. -// -// GitLab API docs: -// https://docs.gitlab.com/api/user_service_accounts/#list-all-service-account-users func (s *UsersService) ListServiceAccounts(opt *ListServiceAccountsOptions, options ...RequestOptionFunc) ([]*ServiceAccount, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "service_accounts", opt, options) - if err != nil { - return nil, nil, err - } - - var sas []*ServiceAccount - resp, err := s.client.Do(req, &sas) - if err != nil { - return nil, resp, err - } - - return sas, resp, nil + return do[[]*ServiceAccount](s.client, + withPath("service_accounts"), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// UploadAvatar uploads an avatar to the current user. -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#upload-an-avatar-for-yourself func (s *UsersService) UploadAvatar(avatar io.Reader, filename string, options ...RequestOptionFunc) (*User, *Response, error) { - u := "user/avatar" - - req, err := s.client.UploadRequest( - http.MethodPut, - u, - avatar, - filename, - UploadAvatar, - nil, - options, + return do[*User](s.client, + withMethod(http.MethodPut), + withPath("user/avatar"), + withUpload(avatar, filename, UploadAvatar), + withRequestOpts(options...), ) - if err != nil { - return nil, nil, err - } - - usr := new(User) - resp, err := s.client.Do(req, usr) - if err != nil { - return nil, resp, err - } - - return usr, resp, nil } -// DeleteUserIdentity deletes a user's authentication identity using the provider -// name associated with that identity. Only available for administrators. -// -// GitLab API docs: -// https://docs.gitlab.com/api/users/#delete-authentication-identity-from-a-user -func (s *UsersService) DeleteUserIdentity(user int, provider string, options ...RequestOptionFunc) (*Response, error) { - u := fmt.Sprintf("users/%d/identities/%s", user, provider) +func (s *UsersService) DeleteUserIdentity(user int64, provider string, options ...RequestOptionFunc) (*Response, error) { + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("users/%d/identities/%s", user, provider), + withRequestOpts(options...), + ) + return resp, err +} + +// userCoreBasicTemplate defines the common fields for a user in GraphQL queries. +var userCoreBasicTemplate = template.Must(template.New("UserCoreBasic").Parse(` + id + username + name + state + createdAt + avatarUrl + webUrl +`)) + +// userCoreBasicGQL represents the UserCore GraphQL type. It unwraps to a *BasicUser type. +type userCoreBasicGQL struct { + ID gidGQL `json:"id"` + Username string `json:"username"` + Name string `json:"name"` + State string `json:"state"` + CreatedAt *time.Time `json:"createdAt"` + AvatarURL string `json:"avatarUrl"` + WebURL string `json:"webUrl"` +} - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err +// unwrap converts the GraphQL data structure to a *BasicUser. +func (u userCoreBasicGQL) unwrap() *BasicUser { + if u.Username == "" { + return nil } - return s.client.Do(req, nil) + return &BasicUser{ + ID: u.ID.Int64, + Username: u.Username, + Name: u.Name, + State: u.State, + Locked: u.State != "active", + CreatedAt: u.CreatedAt, + AvatarURL: u.AvatarURL, + WebURL: u.WebURL, + } } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/validate.go b/vendor/gitlab.com/gitlab-org/api/client-go/validate.go index 9b05ad4ab..0aa6e5870 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/validate.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/validate.go @@ -16,14 +16,19 @@ package gitlab -import ( - "fmt" - "net/http" -) +import "net/http" type ( ValidateServiceInterface interface { + // ProjectNamespaceLint validates .gitlab-ci.yml content by project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/lint/#validate-sample-cicd-configuration ProjectNamespaceLint(pid any, opt *ProjectNamespaceLintOptions, options ...RequestOptionFunc) (*ProjectLintResult, *Response, error) + // ProjectLint validates .gitlab-ci.yml content by project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/lint/#validate-a-projects-cicd-configuration ProjectLint(pid any, opt *ProjectLintOptions, options ...RequestOptionFunc) (*ProjectLintResult, *Response, error) } @@ -86,29 +91,13 @@ type ProjectNamespaceLintOptions struct { Ref *string `url:"ref,omitempty" json:"ref,omitempty"` } -// ProjectNamespaceLint validates .gitlab-ci.yml content by project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/lint/#validate-sample-cicd-configuration func (s *ValidateService) ProjectNamespaceLint(pid any, opt *ProjectNamespaceLintOptions, options ...RequestOptionFunc) (*ProjectLintResult, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/ci/lint", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, &opt, options) - if err != nil { - return nil, nil, err - } - - l := new(ProjectLintResult) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*ProjectLintResult](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/ci/lint", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // ProjectLintOptions represents the available ProjectLint() options. @@ -123,27 +112,10 @@ type ProjectLintOptions struct { Ref *string `url:"ref,omitempty" json:"ref,omitempty"` } -// ProjectLint validates .gitlab-ci.yml content by project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/lint/#validate-a-projects-cicd-configuration func (s *ValidateService) ProjectLint(pid any, opt *ProjectLintOptions, options ...RequestOptionFunc) (*ProjectLintResult, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/ci/lint", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, &opt, options) - if err != nil { - return nil, nil, err - } - - l := new(ProjectLintResult) - resp, err := s.client.Do(req, l) - if err != nil { - return nil, resp, err - } - - return l, resp, nil + return do[*ProjectLintResult](s.client, + withPath("projects/%s/ci/lint", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/version.go b/vendor/gitlab.com/gitlab-org/api/client-go/version.go index 90bd2552a..c548f1c7d 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/version.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/version.go @@ -16,8 +16,6 @@ package gitlab -import "net/http" - type ( VersionServiceInterface interface { GetVersion(options ...RequestOptionFunc) (*Version, *Response, error) @@ -51,16 +49,8 @@ func (s Version) String() string { // // GitLab API docs: https://docs.gitlab.com/api/version/ func (s *VersionService) GetVersion(options ...RequestOptionFunc) (*Version, *Response, error) { - req, err := s.client.NewRequest(http.MethodGet, "version", nil, options) - if err != nil { - return nil, nil, err - } - - v := new(Version) - resp, err := s.client.Do(req, v) - if err != nil { - return nil, resp, err - } - - return v, resp, nil + return do[*Version](s.client, + withPath("version"), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/wikis.go b/vendor/gitlab.com/gitlab-org/api/client-go/wikis.go index e17b2041c..65b3d85d9 100644 --- a/vendor/gitlab.com/gitlab-org/api/client-go/wikis.go +++ b/vendor/gitlab.com/gitlab-org/api/client-go/wikis.go @@ -16,24 +16,49 @@ package gitlab import ( - "fmt" "io" "net/http" - "net/url" ) type ( WikisServiceInterface interface { + // ListWikis lists all pages of the wiki of the given project id. + // When with_content is set, it also returns the content of the pages. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#list-all-wiki-pages ListWikis(pid any, opt *ListWikisOptions, options ...RequestOptionFunc) ([]*Wiki, *Response, error) + // GetWikiPage gets a wiki page for a given project. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#retrieve-a-wiki-page GetWikiPage(pid any, slug string, opt *GetWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) + // CreateWikiPage creates a new wiki page for the given repository with + // the given title, slug, and content. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#create-a-wiki-page CreateWikiPage(pid any, opt *CreateWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) + // EditWikiPage Updates an existing wiki page. At least one parameter is + // required to update the wiki page. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#update-a-wiki-page EditWikiPage(pid any, slug string, opt *EditWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) + // DeleteWikiPage deletes a wiki page with a given slug. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#delete-a-wiki-page DeleteWikiPage(pid any, slug string, options ...RequestOptionFunc) (*Response, error) + // UploadWikiAttachment uploads a file to the attachment folder inside the wikiโ€™s repository. The attachment folder is the uploads folder. + // + // GitLab API docs: + // https://docs.gitlab.com/api/wikis/#upload-an-attachment-to-the-wiki-repository UploadWikiAttachment(pid any, content io.Reader, filename string, opt *UploadWikiAttachmentOptions, options ...RequestOptionFunc) (*WikiAttachment, *Response, error) } // WikisService handles communication with the wikis related methods of - // the Gitlab API. + // the GitLab API. // // GitLab API docs: // https://docs.gitlab.com/api/wikis/ @@ -92,30 +117,12 @@ type ListWikisOptions struct { WithContent *bool `url:"with_content,omitempty" json:"with_content,omitempty"` } -// ListWikis lists all pages of the wiki of the given project id. -// When with_content is set, it also returns the content of the pages. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#list-wiki-pages func (s *WikisService) ListWikis(pid any, opt *ListWikisOptions, options ...RequestOptionFunc) ([]*Wiki, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/wikis", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - var ws []*Wiki - resp, err := s.client.Do(req, &ws) - if err != nil { - return nil, resp, err - } - - return ws, resp, nil + return do[[]*Wiki](s.client, + withPath("projects/%s/wikis", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // GetWikiPageOptions represents options to GetWikiPage @@ -127,29 +134,12 @@ type GetWikiPageOptions struct { Version *string `url:"version,omitempty" json:"version,omitempty"` } -// GetWikiPage gets a wiki page for a given project. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#get-a-wiki-page func (s *WikisService) GetWikiPage(pid any, slug string, opt *GetWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/wikis/%s", PathEscape(project), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodGet, u, opt, options) - if err != nil { - return nil, nil, err - } - - w := new(Wiki) - resp, err := s.client.Do(req, w) - if err != nil { - return nil, resp, err - } - - return w, resp, nil + return do[*Wiki](s.client, + withPath("projects/%s/wikis/%s", ProjectID{pid}, slug), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // CreateWikiPageOptions represents options to CreateWikiPage. @@ -162,30 +152,13 @@ type CreateWikiPageOptions struct { Format *WikiFormatValue `url:"format,omitempty" json:"format,omitempty"` } -// CreateWikiPage creates a new wiki page for the given repository with -// the given title, slug, and content. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#create-a-new-wiki-page func (s *WikisService) CreateWikiPage(pid any, opt *CreateWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/wikis", PathEscape(project)) - - req, err := s.client.NewRequest(http.MethodPost, u, opt, options) - if err != nil { - return nil, nil, err - } - - w := new(Wiki) - resp, err := s.client.Do(req, w) - if err != nil { - return nil, resp, err - } - - return w, resp, nil + return do[*Wiki](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/wikis", ProjectID{pid}), + withAPIOpts(opt), + withRequestOpts(options...), + ) } // EditWikiPageOptions represents options to EditWikiPage. @@ -198,49 +171,22 @@ type EditWikiPageOptions struct { Format *WikiFormatValue `url:"format,omitempty" json:"format,omitempty"` } -// EditWikiPage Updates an existing wiki page. At least one parameter is -// required to update the wiki page. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#edit-an-existing-wiki-page func (s *WikisService) EditWikiPage(pid any, slug string, opt *EditWikiPageOptions, options ...RequestOptionFunc) (*Wiki, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/wikis/%s", PathEscape(project), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodPut, u, opt, options) - if err != nil { - return nil, nil, err - } - - w := new(Wiki) - resp, err := s.client.Do(req, w) - if err != nil { - return nil, resp, err - } - - return w, resp, nil + return do[*Wiki](s.client, + withMethod(http.MethodPut), + withPath("projects/%s/wikis/%s", ProjectID{pid}, slug), + withAPIOpts(opt), + withRequestOpts(options...), + ) } -// DeleteWikiPage deletes a wiki page with a given slug. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#delete-a-wiki-page func (s *WikisService) DeleteWikiPage(pid any, slug string, options ...RequestOptionFunc) (*Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, err - } - u := fmt.Sprintf("projects/%s/wikis/%s", PathEscape(project), url.PathEscape(slug)) - - req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) - if err != nil { - return nil, err - } - - return s.client.Do(req, nil) + _, resp, err := do[none](s.client, + withMethod(http.MethodDelete), + withPath("projects/%s/wikis/%s", ProjectID{pid}, slug), + withRequestOpts(options...), + ) + return resp, err } // UploadWikiAttachmentOptions represents options to UploadWikiAttachment. @@ -251,27 +197,12 @@ type UploadWikiAttachmentOptions struct { Branch *string `url:"branch,omitempty" json:"branch,omitempty"` } -// UploadWikiAttachment uploads a file to the attachment folder inside the wikiโ€™s repository. The attachment folder is the uploads folder. -// -// GitLab API docs: -// https://docs.gitlab.com/api/wikis/#upload-an-attachment-to-the-wiki-repository func (s *WikisService) UploadWikiAttachment(pid any, content io.Reader, filename string, opt *UploadWikiAttachmentOptions, options ...RequestOptionFunc) (*WikiAttachment, *Response, error) { - project, err := parseID(pid) - if err != nil { - return nil, nil, err - } - u := fmt.Sprintf("projects/%s/wikis/attachments", PathEscape(project)) - - req, err := s.client.UploadRequest(http.MethodPost, u, content, filename, UploadFile, opt, options) - if err != nil { - return nil, nil, err - } - - attachment := new(WikiAttachment) - resp, err := s.client.Do(req, attachment) - if err != nil { - return nil, resp, err - } - - return attachment, resp, nil + return do[*WikiAttachment](s.client, + withMethod(http.MethodPost), + withPath("projects/%s/wikis/attachments", ProjectID{pid}), + withUpload(content, filename, UploadFile), + withAPIOpts(opt), + withRequestOpts(options...), + ) } diff --git a/vendor/gitlab.com/gitlab-org/api/client-go/workitems.go b/vendor/gitlab.com/gitlab-org/api/client-go/workitems.go new file mode 100644 index 000000000..23c959ab3 --- /dev/null +++ b/vendor/gitlab.com/gitlab-org/api/client-go/workitems.go @@ -0,0 +1,455 @@ +package gitlab + +import ( + "errors" + "strconv" + "strings" + "text/template" + "time" +) + +type ( + WorkItemsServiceInterface interface { + GetWorkItem(fullPath string, iid int64, options ...RequestOptionFunc) (*WorkItem, *Response, error) + ListWorkItems(fullPath string, opt *ListWorkItemsOptions, options ...RequestOptionFunc) ([]*WorkItem, *Response, error) + } + + // WorkItemsService handles communication with the work item related methods + // of the GitLab API. + // + // GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#workitem + WorkItemsService struct { + client *Client + } +) + +var _ WorkItemsServiceInterface = (*WorkItemsService)(nil) + +// WorkItem represents a GitLab work item. +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#workitem +type WorkItem struct { + ID int64 + IID int64 + Type string + State string + Status string + Title string + Description string + CreatedAt *time.Time + UpdatedAt *time.Time + ClosedAt *time.Time + WebURL string + Author *BasicUser + Assignees []*BasicUser +} + +func (wi WorkItem) GID() string { + return gidGQL{ + Type: "WorkItem", + Int64: wi.ID, + }.String() +} + +// workItemTemplate defines the common fields for a work item in GraphQL queries. +// It's chained from userCoreBasicTemplate so nested templates work. +var workItemTemplate = template.Must(template.Must(userCoreBasicTemplate.Clone()).New("WorkItem").Parse(` + id + iid + workItemType { + name + } + state + title + description + author { + {{ template "UserCoreBasic" }} + } + createdAt + updatedAt + closedAt + webUrl + features { + assignees { + assignees { + nodes { + {{ template "UserCoreBasic" }} + } + } + } + status { + status { + name + } + } + } +`)) + +// getWorkItemTemplate is chained from workItemTemplate so it has access to both +// UserCoreBasic and WorkItem templates. +var getWorkItemTemplate = template.Must(template.Must(workItemTemplate.Clone()).New("GetWorkItem").Parse(` + query GetWorkItem($fullPath: ID!, $iid: String!) { + namespace(fullPath: $fullPath) { + workItem(iid: $iid) { + {{ template "WorkItem" }} + } + } + } +`)) + +// GetWorkItem gets a single work item. +// +// fullPath is the full path to either a group or project. +// iid is the internal ID of the work item. +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#namespaceworkitem +func (s *WorkItemsService) GetWorkItem(fullPath string, iid int64, options ...RequestOptionFunc) (*WorkItem, *Response, error) { + var queryBuilder strings.Builder + if err := getWorkItemTemplate.Execute(&queryBuilder, nil); err != nil { + return nil, nil, err + } + + q := GraphQLQuery{ + Query: queryBuilder.String(), + Variables: map[string]any{ + "fullPath": fullPath, + "iid": strconv.FormatInt(iid, 10), + }, + } + + var result struct { + Data struct { + Namespace struct { + WorkItem *workItemGQL `json:"workItem"` + } `json:"namespace"` + } + GenericGraphQLErrors + } + + resp, err := s.client.GraphQL.Do(q, &result, options...) + if err != nil { + return nil, resp, err + } + + if len(result.Errors) != 0 { + return nil, resp, &GraphQLResponseError{ + Err: errors.New("GraphQL query failed"), + Errors: result.GenericGraphQLErrors, + } + } + + wiQL := result.Data.Namespace.WorkItem + if wiQL == nil { + return nil, resp, ErrNotFound + } + + return wiQL.unwrap(), resp, nil +} + +// ListWorkItemsOptions represents the available ListWorkItems() options. +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#namespaceworkitems +type ListWorkItemsOptions struct { + AssigneeUsernames []string + AssigneeWildcardID *string + AuthorUsername *string + Confidential *bool + CRMContactID *string + CRMOrganizationID *string + HealthStatusFilter *string + IDs []string + IIDs []string + IncludeAncestors *bool + IncludeDescendants *bool + IterationCadenceID []string + IterationID []string + IterationWildcardID *string + LabelName []string + MilestoneTitle []string + MilestoneWildcardID *string + MyReactionEmoji *string + ParentIDs []string + ReleaseTag []string + ReleaseTagWildcardID *string + State *string + Subscribed *string + Types []string + Weight *string + WeightWildcardID *string + + // Time filters + ClosedAfter *time.Time + ClosedBefore *time.Time + CreatedAfter *time.Time + CreatedBefore *time.Time + DueAfter *time.Time + DueBefore *time.Time + UpdatedAfter *time.Time + UpdatedBefore *time.Time + + // Sorting + Sort *string + + // Search + Search *string + In []string + + // Pagination + After *string + Before *string + First *int64 + Last *int64 +} + +// listWorkItemsTemplate is chained from workItemTemplate so it has access to both +// UserCoreBasic and WorkItem templates. +var listWorkItemsTemplate = template.Must(template.Must(workItemTemplate.Clone()).New("ListWorkItems").Parse(` + query ListWorkItems( + $fullPath: ID! + $assigneeUsernames: [String!] + $assigneeWildcardId: AssigneeWildcardId + $authorUsername: String + $confidential: Boolean + $crmContactId: String + $crmOrganizationId: String + $healthStatusFilter: HealthStatusFilter + $ids: [WorkItemID!] + $iids: [String!] + $includeAncestors: Boolean + $includeDescendants: Boolean + $iterationCadenceId: [IterationsCadenceID!] + $iterationId: [ID] + $iterationWildcardId: IterationWildcardId + $labelName: [String!] + $milestoneTitle: [String!] + $milestoneWildcardId: MilestoneWildcardId + $myReactionEmoji: String + $parentIds: [WorkItemID!] + $releaseTag: [String!] + $releaseTagWildcardId: ReleaseTagWildcardId + $state: IssuableState + $subscribed: SubscriptionStatus + $types: [IssueType!] + $weight: String + $weightWildcardId: WeightWildcardId + $closedAfter: Time + $closedBefore: Time + $createdAfter: Time + $createdBefore: Time + $dueAfter: Time + $dueBefore: Time + $updatedAfter: Time + $updatedBefore: Time + $sort: WorkItemSort + $search: String + $in: [IssuableSearchableField!] + $after: String + $before: String + $first: Int + $last: Int + ) { + namespace(fullPath: $fullPath) { + workItems( + assigneeUsernames: $assigneeUsernames + assigneeWildcardId: $assigneeWildcardId + authorUsername: $authorUsername + confidential: $confidential + crmContactId: $crmContactId + crmOrganizationId: $crmOrganizationId + healthStatusFilter: $healthStatusFilter + ids: $ids + iids: $iids + includeAncestors: $includeAncestors + includeDescendants: $includeDescendants + iterationCadenceId: $iterationCadenceId + iterationId: $iterationId + iterationWildcardId: $iterationWildcardId + labelName: $labelName + milestoneTitle: $milestoneTitle + milestoneWildcardId: $milestoneWildcardId + myReactionEmoji: $myReactionEmoji + parentIds: $parentIds + releaseTag: $releaseTag + releaseTagWildcardId: $releaseTagWildcardId + state: $state + subscribed: $subscribed + types: $types + weight: $weight + weightWildcardId: $weightWildcardId + closedAfter: $closedAfter + closedBefore: $closedBefore + createdAfter: $createdAfter + createdBefore: $createdBefore + dueAfter: $dueAfter + dueBefore: $dueBefore + updatedAfter: $updatedAfter + updatedBefore: $updatedBefore + sort: $sort + search: $search + in: $in + after: $after + before: $before + first: $first + last: $last + ) { + nodes { + {{ template "WorkItem" }} + } + pageInfo { + endCursor + hasNextPage + startCursor + hasPreviousPage + } + } + } + } +`)) + +// ListWorkItems lists workitems in a given namespace (group or project). +// +// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#namespaceworkitems +func (s *WorkItemsService) ListWorkItems(fullPath string, opt *ListWorkItemsOptions, options ...RequestOptionFunc) ([]*WorkItem, *Response, error) { + var queryBuilder strings.Builder + + if err := listWorkItemsTemplate.Execute(&queryBuilder, nil); err != nil { + return nil, nil, err + } + + vars := map[string]any{ + "fullPath": fullPath, + "assigneeUsernames": opt.AssigneeUsernames, + "assigneeWildcardId": opt.AssigneeWildcardID, + "authorUsername": opt.AuthorUsername, + "confidential": opt.Confidential, + "crmContactId": opt.CRMContactID, + "crmOrganizationId": opt.CRMOrganizationID, + "healthStatusFilter": opt.HealthStatusFilter, + "ids": opt.IDs, + "iids": opt.IIDs, + "includeAncestors": opt.IncludeAncestors, + "includeDescendants": opt.IncludeDescendants, + "iterationCadenceId": opt.IterationCadenceID, + "iterationId": opt.IterationID, + "iterationWildcardId": opt.IterationWildcardID, + "labelName": opt.LabelName, + "milestoneTitle": opt.MilestoneTitle, + "milestoneWildcardId": opt.MilestoneWildcardID, + "myReactionEmoji": opt.MyReactionEmoji, + "parentIds": opt.ParentIDs, + "releaseTag": opt.ReleaseTag, + "releaseTagWildcardId": opt.ReleaseTagWildcardID, + "state": opt.State, + "subscribed": opt.Subscribed, + "types": opt.Types, + "weight": opt.Weight, + "weightWildcardId": opt.WeightWildcardID, + "closedAfter": opt.ClosedAfter, + "closedBefore": opt.ClosedBefore, + "createdAfter": opt.CreatedAfter, + "createdBefore": opt.CreatedBefore, + "dueAfter": opt.DueAfter, + "dueBefore": opt.DueBefore, + "updatedAfter": opt.UpdatedAfter, + "updatedBefore": opt.UpdatedBefore, + "sort": opt.Sort, + "search": opt.Search, + "in": opt.In, + "after": opt.After, + "before": opt.Before, + "first": opt.First, + "last": opt.Last, + } + + query := GraphQLQuery{ + Query: queryBuilder.String(), + Variables: vars, + } + + var result struct { + Data struct { + Namespace struct { + WorkItems connectionGQL[workItemGQL] `json:"workItems"` + } `json:"namespace"` + } + GenericGraphQLErrors + } + + resp, err := s.client.GraphQL.Do(query, &result, options...) + if err != nil { + return nil, resp, err + } + + if len(result.Errors) != 0 { + return nil, resp, &GraphQLResponseError{ + Err: errors.New("GraphQL query failed"), + Errors: result.GenericGraphQLErrors, + } + } + + var ret []*WorkItem + + for _, wi := range result.Data.Namespace.WorkItems.Nodes { + ret = append(ret, wi.unwrap()) + } + + resp.PageInfo = &result.Data.Namespace.WorkItems.PageInfo + + return ret, resp, nil +} + +// workItemGQL represents the JSON structure returned by the GraphQL query. +// It is used to parse the response and convert it to the more user-friendly WorkItem type. +type workItemGQL struct { + ID gidGQL `json:"id"` + IID iidGQL `json:"iid"` + WorkItemType struct { + Name string `json:"name"` + } `json:"workItemType"` + State string `json:"state"` + Title string `json:"title"` + Description string `json:"description"` + CreatedAt *time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` + ClosedAt *time.Time `json:"closedAt"` + Author userCoreBasicGQL `json:"author"` + Features workItemFeaturesGQL `json:"features"` + WebURL string `json:"webUrl"` +} + +func (w workItemGQL) unwrap() *WorkItem { + var assignees []*BasicUser + + for _, a := range w.Features.Assignees.Assignees.Nodes { + assignees = append(assignees, a.unwrap()) + } + + return &WorkItem{ + ID: w.ID.Int64, + IID: int64(w.IID), + Type: w.WorkItemType.Name, + State: w.State, + Status: w.Features.Status.Status.Name, + Title: w.Title, + Description: w.Description, + CreatedAt: w.CreatedAt, + UpdatedAt: w.UpdatedAt, + ClosedAt: w.ClosedAt, + WebURL: w.WebURL, + Author: w.Author.unwrap(), + Assignees: assignees, + } +} + +type workItemFeaturesGQL struct { + Assignees struct { + Assignees struct { + Nodes []userCoreBasicGQL `json:"nodes"` + } `json:"assignees"` + } `json:"assignees"` + Status struct { + Status struct { + Name string + } + } +} diff --git a/vendor/golang.org/x/exp/constraints/constraints.go b/vendor/golang.org/x/exp/constraints/constraints.go deleted file mode 100644 index 2c033dff4..000000000 --- a/vendor/golang.org/x/exp/constraints/constraints.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package constraints defines a set of useful constraints to be used -// with type parameters. -package constraints - -// Signed is a constraint that permits any signed integer type. -// If future releases of Go add new predeclared signed integer types, -// this constraint will be modified to include them. -type Signed interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 -} - -// Unsigned is a constraint that permits any unsigned integer type. -// If future releases of Go add new predeclared unsigned integer types, -// this constraint will be modified to include them. -type Unsigned interface { - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr -} - -// Integer is a constraint that permits any integer type. -// If future releases of Go add new predeclared integer types, -// this constraint will be modified to include them. -type Integer interface { - Signed | Unsigned -} - -// Float is a constraint that permits any floating-point type. -// If future releases of Go add new predeclared floating-point types, -// this constraint will be modified to include them. -type Float interface { - ~float32 | ~float64 -} - -// Complex is a constraint that permits any complex numeric type. -// If future releases of Go add new predeclared complex numeric types, -// this constraint will be modified to include them. -type Complex interface { - ~complex64 | ~complex128 -} - -// Ordered is a constraint that permits any ordered type: any type -// that supports the operators < <= >= >. -// If future releases of Go add new ordered types, -// this constraint will be modified to include them. -type Ordered interface { - Integer | Float | ~string -} diff --git a/vendor/golang.org/x/exp/slices/cmp.go b/vendor/golang.org/x/exp/slices/cmp.go deleted file mode 100644 index fbf1934a0..000000000 --- a/vendor/golang.org/x/exp/slices/cmp.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// min is a version of the predeclared function from the Go 1.21 release. -func min[T constraints.Ordered](a, b T) T { - if a < b || isNaN(a) { - return a - } - return b -} - -// max is a version of the predeclared function from the Go 1.21 release. -func max[T constraints.Ordered](a, b T) T { - if a > b || isNaN(a) { - return a - } - return b -} - -// cmpLess is a copy of cmp.Less from the Go 1.21 release. -func cmpLess[T constraints.Ordered](x, y T) bool { - return (isNaN(x) && !isNaN(y)) || x < y -} - -// cmpCompare is a copy of cmp.Compare from the Go 1.21 release. -func cmpCompare[T constraints.Ordered](x, y T) int { - xNaN := isNaN(x) - yNaN := isNaN(y) - if xNaN && yNaN { - return 0 - } - if xNaN || x < y { - return -1 - } - if yNaN || x > y { - return +1 - } - return 0 -} diff --git a/vendor/golang.org/x/exp/slices/slices.go b/vendor/golang.org/x/exp/slices/slices.go index 46ceac343..da0df370d 100644 --- a/vendor/golang.org/x/exp/slices/slices.go +++ b/vendor/golang.org/x/exp/slices/slices.go @@ -6,9 +6,8 @@ package slices import ( - "unsafe" - - "golang.org/x/exp/constraints" + "cmp" + "slices" ) // Equal reports whether two slices are equal: the same length and all @@ -16,16 +15,10 @@ import ( // Otherwise, the elements are compared in increasing index order, and the // comparison stops at the first unequal pair. // Floating point NaNs are not considered equal. +// +//go:fix inline func Equal[S ~[]E, E comparable](s1, s2 S) bool { - if len(s1) != len(s2) { - return false - } - for i := range s1 { - if s1[i] != s2[i] { - return false - } - } - return true + return slices.Equal(s1, s2) } // EqualFunc reports whether two slices are equal using an equality @@ -33,17 +26,10 @@ func Equal[S ~[]E, E comparable](s1, s2 S) bool { // EqualFunc returns false. Otherwise, the elements are compared in // increasing index order, and the comparison stops at the first index // for which eq returns false. +// +//go:fix inline func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool { - if len(s1) != len(s2) { - return false - } - for i, v1 := range s1 { - v2 := s2[i] - if !eq(v1, v2) { - return false - } - } - return true + return slices.EqualFunc(s1, s2, eq) } // Compare compares the elements of s1 and s2, using [cmp.Compare] on each pair @@ -53,20 +39,10 @@ func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) boo // If both slices are equal until one of them ends, the shorter slice is // considered less than the longer one. // The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. -func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmpCompare(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 +// +//go:fix inline +func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int { + return slices.Compare(s1, s2) } // CompareFunc is like [Compare] but uses a custom comparison function on each @@ -74,53 +50,41 @@ func Compare[S ~[]E, E constraints.Ordered](s1, s2 S) int { // The result is the first non-zero result of cmp; if cmp always // returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), // and +1 if len(s1) > len(s2). +// +//go:fix inline func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int { - for i, v1 := range s1 { - if i >= len(s2) { - return +1 - } - v2 := s2[i] - if c := cmp(v1, v2); c != 0 { - return c - } - } - if len(s1) < len(s2) { - return -1 - } - return 0 + return slices.CompareFunc(s1, s2, cmp) } // Index returns the index of the first occurrence of v in s, // or -1 if not present. +// +//go:fix inline func Index[S ~[]E, E comparable](s S, v E) int { - for i := range s { - if v == s[i] { - return i - } - } - return -1 + return slices.Index(s, v) } // IndexFunc returns the first index i satisfying f(s[i]), // or -1 if none do. +// +//go:fix inline func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { - for i := range s { - if f(s[i]) { - return i - } - } - return -1 + return slices.IndexFunc(s, f) } // Contains reports whether v is present in s. +// +//go:fix inline func Contains[S ~[]E, E comparable](s S, v E) bool { - return Index(s, v) >= 0 + return slices.Contains(s, v) } // ContainsFunc reports whether at least one // element e of s satisfies f(e). +// +//go:fix inline func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool { - return IndexFunc(s, f) >= 0 + return slices.ContainsFunc(s, f) } // Insert inserts the values v... into s at index i, @@ -130,93 +94,10 @@ func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool { // and r[i+len(v)] == value originally at r[i]. // Insert panics if i is out of range. // This function is O(len(s) + len(v)). +// +//go:fix inline func Insert[S ~[]E, E any](s S, i int, v ...E) S { - m := len(v) - if m == 0 { - return s - } - n := len(s) - if i == n { - return append(s, v...) - } - if n+m > cap(s) { - // Use append rather than make so that we bump the size of - // the slice up to the next storage class. - // This is what Grow does but we don't call Grow because - // that might copy the values twice. - s2 := append(s[:i], make(S, n+m-i)...) - copy(s2[i:], v) - copy(s2[i+m:], s[i:]) - return s2 - } - s = s[:n+m] - - // before: - // s: aaaaaaaabbbbccccccccdddd - // ^ ^ ^ ^ - // i i+m n n+m - // after: - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // - // a are the values that don't move in s. - // v are the values copied in from v. - // b and c are the values from s that are shifted up in index. - // d are the values that get overwritten, never to be seen again. - - if !overlaps(v, s[i+m:]) { - // Easy case - v does not overlap either the c or d regions. - // (It might be in some of a or b, or elsewhere entirely.) - // The data we copy up doesn't write to v at all, so just do it. - - copy(s[i+m:], s[i:]) - - // Now we have - // s: aaaaaaaabbbbbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // Note the b values are duplicated. - - copy(s[i:], v) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s - } - - // The hard case - v overlaps c or d. We can't just shift up - // the data because we'd move or clobber the values we're trying - // to insert. - // So instead, write v on top of d, then rotate. - copy(s[n:], v) - - // Now we have - // s: aaaaaaaabbbbccccccccvvvv - // ^ ^ ^ ^ - // i i+m n n+m - - rotateRight(s[i:], m) - - // Now we have - // s: aaaaaaaavvvvbbbbcccccccc - // ^ ^ ^ ^ - // i i+m n n+m - // That's the result we want. - return s -} - -// clearSlice sets all elements up to the length of s to the zero value of E. -// We may use the builtin clear func instead, and remove clearSlice, when upgrading -// to Go 1.21+. -func clearSlice[S ~[]E, E any](s S) { - var zero E - for i := range s { - s[i] = zero - } + return slices.Insert(s, i, v...) } // Delete removes the elements s[i:j] from s, returning the modified slice. @@ -224,136 +105,36 @@ func clearSlice[S ~[]E, E any](s S) { // Delete is O(len(s)-i), so if many items must be deleted, it is better to // make a single call deleting them all together than to delete one at a time. // Delete zeroes the elements s[len(s)-(j-i):len(s)]. +// +//go:fix inline func Delete[S ~[]E, E any](s S, i, j int) S { - _ = s[i:j:len(s)] // bounds check - - if i == j { - return s - } - - oldlen := len(s) - s = append(s[:i], s[j:]...) - clearSlice(s[len(s):oldlen]) // zero/nil out the obsolete elements, for GC - return s + return slices.Delete(s, i, j) } // DeleteFunc removes any elements from s for which del returns true, // returning the modified slice. // DeleteFunc zeroes the elements between the new length and the original length. +// +//go:fix inline func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { - i := IndexFunc(s, del) - if i == -1 { - return s - } - // Don't start copying elements until we find one to delete. - for j := i + 1; j < len(s); j++ { - if v := s[j]; !del(v) { - s[i] = v - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] + return slices.DeleteFunc(s, del) } // Replace replaces the elements s[i:j] by the given v, and returns the // modified slice. Replace panics if s[i:j] is not a valid slice of s. // When len(v) < (j-i), Replace zeroes the elements between the new length and the original length. +// +//go:fix inline func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { - _ = s[i:j] // verify that i:j is a valid subslice - - if i == j { - return Insert(s, i, v...) - } - if j == len(s) { - return append(s[:i], v...) - } - - tot := len(s[:i]) + len(v) + len(s[j:]) - if tot > cap(s) { - // Too big to fit, allocate and copy over. - s2 := append(s[:i], make(S, tot-i)...) // See Insert - copy(s2[i:], v) - copy(s2[i+len(v):], s[j:]) - return s2 - } - - r := s[:tot] - - if i+len(v) <= j { - // Easy, as v fits in the deleted portion. - copy(r[i:], v) - if i+len(v) != j { - copy(r[i+len(v):], s[j:]) - } - clearSlice(s[tot:]) // zero/nil out the obsolete elements, for GC - return r - } - - // We are expanding (v is bigger than j-i). - // The situation is something like this: - // (example has i=4,j=8,len(s)=16,len(v)=6) - // s: aaaaxxxxbbbbbbbbyy - // ^ ^ ^ ^ - // i j len(s) tot - // a: prefix of s - // x: deleted range - // b: more of s - // y: area to expand into - - if !overlaps(r[i+len(v):], v) { - // Easy, as v is not clobbered by the first copy. - copy(r[i+len(v):], s[j:]) - copy(r[i:], v) - return r - } - - // This is a situation where we don't have a single place to which - // we can copy v. Parts of it need to go to two different places. - // We want to copy the prefix of v into y and the suffix into x, then - // rotate |y| spots to the right. - // - // v[2:] v[:2] - // | | - // s: aaaavvvvbbbbbbbbvv - // ^ ^ ^ ^ - // i j len(s) tot - // - // If either of those two destinations don't alias v, then we're good. - y := len(v) - (j - i) // length of y portion - - if !overlaps(r[i:j], v) { - copy(r[i:j], v[y:]) - copy(r[len(s):], v[:y]) - rotateRight(r[i:], y) - return r - } - if !overlaps(r[len(s):], v) { - copy(r[len(s):], v[:y]) - copy(r[i:j], v[y:]) - rotateRight(r[i:], y) - return r - } - - // Now we know that v overlaps both x and y. - // That means that the entirety of b is *inside* v. - // So we don't need to preserve b at all; instead we - // can copy v first, then copy the b part of v out of - // v to the right destination. - k := startIdx(v, s[j:]) - copy(r[i:], v) - copy(r[i+len(v):], r[i+k:]) - return r + return slices.Replace(s, i, j, v...) } // Clone returns a copy of the slice. // The elements are copied using assignment, so this is a shallow clone. +// +//go:fix inline func Clone[S ~[]E, E any](s S) S { - // Preserve nil in case it matters. - if s == nil { - return nil - } - return append(S([]E{}), s...) + return slices.Clone(s) } // Compact replaces consecutive runs of equal elements with a single copy. @@ -361,155 +142,41 @@ func Clone[S ~[]E, E any](s S) S { // Compact modifies the contents of the slice s and returns the modified slice, // which may have a smaller length. // Compact zeroes the elements between the new length and the original length. +// +//go:fix inline func Compact[S ~[]E, E comparable](s S) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if s[k] != s[k-1] { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] + return slices.Compact(s) } // CompactFunc is like [Compact] but uses an equality function to compare elements. // For runs of elements that compare equal, CompactFunc keeps the first one. // CompactFunc zeroes the elements between the new length and the original length. +// +//go:fix inline func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { - if len(s) < 2 { - return s - } - i := 1 - for k := 1; k < len(s); k++ { - if !eq(s[k], s[k-1]) { - if i != k { - s[i] = s[k] - } - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] + return slices.CompactFunc(s, eq) } // Grow increases the slice's capacity, if necessary, to guarantee space for // another n elements. After Grow(n), at least n elements can be appended // to the slice without another allocation. If n is negative or too large to // allocate the memory, Grow panics. +// +//go:fix inline func Grow[S ~[]E, E any](s S, n int) S { - if n < 0 { - panic("cannot be negative") - } - if n -= cap(s) - len(s); n > 0 { - // TODO(https://go.dev/issue/53888): Make using []E instead of S - // to workaround a compiler bug where the runtime.growslice optimization - // does not take effect. Revert when the compiler is fixed. - s = append([]E(s)[:cap(s)], make([]E, n)...)[:len(s)] - } - return s + return slices.Grow(s, n) } // Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. -func Clip[S ~[]E, E any](s S) S { - return s[:len(s):len(s)] -} - -// Rotation algorithm explanation: -// -// rotate left by 2 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join first parts -// 89234567 01 -// recursively rotate first left part by 2 -// 23456789 01 -// join at the end -// 2345678901 // -// rotate left by 8 -// start with -// 0123456789 -// split up like this -// 01 234567 89 -// swap first 2 and last 2 -// 89 234567 01 -// join last parts -// 89 23456701 -// recursively rotate second part left by 6 -// 89 01234567 -// join at the end -// 8901234567 - -// TODO: There are other rotate algorithms. -// This algorithm has the desirable property that it moves each element exactly twice. -// The triple-reverse algorithm is simpler and more cache friendly, but takes more writes. -// The follow-cycles algorithm can be 1-write but it is not very cache friendly. - -// rotateLeft rotates b left by n spaces. -// s_final[i] = s_orig[i+r], wrapping around. -func rotateLeft[E any](s []E, r int) { - for r != 0 && r != len(s) { - if r*2 <= len(s) { - swap(s[:r], s[len(s)-r:]) - s = s[:len(s)-r] - } else { - swap(s[:len(s)-r], s[r:]) - s, r = s[len(s)-r:], r*2-len(s) - } - } -} -func rotateRight[E any](s []E, r int) { - rotateLeft(s, len(s)-r) -} - -// swap swaps the contents of x and y. x and y must be equal length and disjoint. -func swap[E any](x, y []E) { - for i := 0; i < len(x); i++ { - x[i], y[i] = y[i], x[i] - } -} - -// overlaps reports whether the memory ranges a[0:len(a)] and b[0:len(b)] overlap. -func overlaps[E any](a, b []E) bool { - if len(a) == 0 || len(b) == 0 { - return false - } - elemSize := unsafe.Sizeof(a[0]) - if elemSize == 0 { - return false - } - // TODO: use a runtime/unsafe facility once one becomes available. See issue 12445. - // Also see crypto/internal/alias/alias.go:AnyOverlap - return uintptr(unsafe.Pointer(&a[0])) <= uintptr(unsafe.Pointer(&b[len(b)-1]))+(elemSize-1) && - uintptr(unsafe.Pointer(&b[0])) <= uintptr(unsafe.Pointer(&a[len(a)-1]))+(elemSize-1) -} - -// startIdx returns the index in haystack where the needle starts. -// prerequisite: the needle must be aliased entirely inside the haystack. -func startIdx[E any](haystack, needle []E) int { - p := &needle[0] - for i := range haystack { - if p == &haystack[i] { - return i - } - } - // TODO: what if the overlap is by a non-integral number of Es? - panic("needle not found") +//go:fix inline +func Clip[S ~[]E, E any](s S) S { + return slices.Clip(s) } // Reverse reverses the elements of the slice in place. +// +//go:fix inline func Reverse[S ~[]E, E any](s S) { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } + slices.Reverse(s) } diff --git a/vendor/golang.org/x/exp/slices/sort.go b/vendor/golang.org/x/exp/slices/sort.go index f58bbc7ba..bd91a8d40 100644 --- a/vendor/golang.org/x/exp/slices/sort.go +++ b/vendor/golang.org/x/exp/slices/sort.go @@ -2,21 +2,19 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:generate go run $GOROOT/src/sort/gen_sort_variants.go -exp - package slices import ( - "math/bits" - - "golang.org/x/exp/constraints" + "cmp" + "slices" ) // Sort sorts a slice of any ordered type in ascending order. // When sorting floating-point numbers, NaNs are ordered before other values. -func Sort[S ~[]E, E constraints.Ordered](x S) { - n := len(x) - pdqsortOrdered(x, 0, n, bits.Len(uint(n))) +// +//go:fix inline +func Sort[S ~[]E, E cmp.Ordered](x S) { + slices.Sort(x) } // SortFunc sorts the slice x in ascending order as determined by the cmp @@ -28,119 +26,79 @@ func Sort[S ~[]E, E constraints.Ordered](x S) { // SortFunc requires that cmp is a strict weak ordering. // See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. // To indicate 'uncomparable', return 0 from the function. +// +//go:fix inline func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - n := len(x) - pdqsortCmpFunc(x, 0, n, bits.Len(uint(n)), cmp) + slices.SortFunc(x, cmp) } // SortStableFunc sorts the slice x while keeping the original order of equal // elements, using cmp to compare elements in the same way as [SortFunc]. +// +//go:fix inline func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) { - stableCmpFunc(x, len(x), cmp) + slices.SortStableFunc(x, cmp) } // IsSorted reports whether x is sorted in ascending order. -func IsSorted[S ~[]E, E constraints.Ordered](x S) bool { - for i := len(x) - 1; i > 0; i-- { - if cmpLess(x[i], x[i-1]) { - return false - } - } - return true +// +//go:fix inline +func IsSorted[S ~[]E, E cmp.Ordered](x S) bool { + return slices.IsSorted(x) } // IsSortedFunc reports whether x is sorted in ascending order, with cmp as the // comparison function as defined by [SortFunc]. +// +//go:fix inline func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool { - for i := len(x) - 1; i > 0; i-- { - if cmp(x[i], x[i-1]) < 0 { - return false - } - } - return true + return slices.IsSortedFunc(x, cmp) } // Min returns the minimal value in x. It panics if x is empty. // For floating-point numbers, Min propagates NaNs (any NaN value in x // forces the output to be NaN). -func Min[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Min: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = min(m, x[i]) - } - return m +// +//go:fix inline +func Min[S ~[]E, E cmp.Ordered](x S) E { + return slices.Min(x) } // MinFunc returns the minimal value in x, using cmp to compare elements. // It panics if x is empty. If there is more than one minimal element // according to the cmp function, MinFunc returns the first one. +// +//go:fix inline func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MinFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) < 0 { - m = x[i] - } - } - return m + return slices.MinFunc(x, cmp) } // Max returns the maximal value in x. It panics if x is empty. // For floating-point E, Max propagates NaNs (any NaN value in x // forces the output to be NaN). -func Max[S ~[]E, E constraints.Ordered](x S) E { - if len(x) < 1 { - panic("slices.Max: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - m = max(m, x[i]) - } - return m +// +//go:fix inline +func Max[S ~[]E, E cmp.Ordered](x S) E { + return slices.Max(x) } // MaxFunc returns the maximal value in x, using cmp to compare elements. // It panics if x is empty. If there is more than one maximal element // according to the cmp function, MaxFunc returns the first one. +// +//go:fix inline func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E { - if len(x) < 1 { - panic("slices.MaxFunc: empty list") - } - m := x[0] - for i := 1; i < len(x); i++ { - if cmp(x[i], m) > 0 { - m = x[i] - } - } - return m + return slices.MaxFunc(x, cmp) } // BinarySearch searches for target in a sorted slice and returns the position // where target is found, or the position where target would appear in the // sort order; it also returns a bool saying whether the target is really found // in the slice. The slice must be sorted in increasing order. -func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) { - // Inlining is faster than calling BinarySearchFunc with a lambda. - n := len(x) - // Define x[-1] < target and x[n] >= target. - // Invariant: x[i-1] < target, x[j] >= target. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i โ‰ค h < j - if cmpLess(x[h], target) { - i = h + 1 // preserves x[i-1] < target - } else { - j = h // preserves x[j] >= target - } - } - // i == j, x[i-1] < target, and x[j] (= x[i]) >= target => answer is i. - return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target))) +// +//go:fix inline +func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) { + return slices.BinarySearch(x, target) } // BinarySearchFunc works like [BinarySearch], but uses a custom comparison @@ -150,48 +108,8 @@ func BinarySearch[S ~[]E, E constraints.Ordered](x S, target E) (int, bool) { // or a positive number if the slice element follows the target. // cmp must implement the same ordering as the slice, such that if // cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice. +// +//go:fix inline func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) { - n := len(x) - // Define cmp(x[-1], target) < 0 and cmp(x[n], target) >= 0 . - // Invariant: cmp(x[i - 1], target) < 0, cmp(x[j], target) >= 0. - i, j := 0, n - for i < j { - h := int(uint(i+j) >> 1) // avoid overflow when computing h - // i โ‰ค h < j - if cmp(x[h], target) < 0 { - i = h + 1 // preserves cmp(x[i - 1], target) < 0 - } else { - j = h // preserves cmp(x[j], target) >= 0 - } - } - // i == j, cmp(x[i-1], target) < 0, and cmp(x[j], target) (= cmp(x[i], target)) >= 0 => answer is i. - return i, i < n && cmp(x[i], target) == 0 -} - -type sortedHint int // hint for pdqsort when choosing the pivot - -const ( - unknownHint sortedHint = iota - increasingHint - decreasingHint -) - -// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf -type xorshift uint64 - -func (r *xorshift) Next() uint64 { - *r ^= *r << 13 - *r ^= *r >> 17 - *r ^= *r << 5 - return uint64(*r) -} - -func nextPowerOfTwo(length int) uint { - return 1 << bits.Len(uint(length)) -} - -// isNaN reports whether x is a NaN without requiring the math package. -// This will always return false if T is not floating-point. -func isNaN[T constraints.Ordered](x T) bool { - return x != x + return slices.BinarySearchFunc(x, target, cmp) } diff --git a/vendor/golang.org/x/exp/slices/zsortanyfunc.go b/vendor/golang.org/x/exp/slices/zsortanyfunc.go deleted file mode 100644 index 06f2c7a24..000000000 --- a/vendor/golang.org/x/exp/slices/zsortanyfunc.go +++ /dev/null @@ -1,479 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -// insertionSortCmpFunc sorts data[a:b] using insertion sort. -func insertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && (cmp(data[j], data[j-1]) < 0); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownCmpFunc implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownCmpFunc[E any](data []E, lo, hi, first int, cmp func(a, b E) int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && (cmp(data[first+child], data[first+child+1]) < 0) { - child++ - } - if !(cmp(data[first+root], data[first+child]) < 0) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownCmpFunc(data, i, hi, first, cmp) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownCmpFunc(data, lo, i, first, cmp) - } -} - -// pdqsortCmpFunc sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortCmpFunc[E any](data []E, a, b, limit int, cmp func(a, b E) int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortCmpFunc(data, a, b, cmp) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortCmpFunc(data, a, b, cmp) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsCmpFunc(data, a, b, cmp) - limit-- - } - - pivot, hint := choosePivotCmpFunc(data, a, b, cmp) - if hint == decreasingHint { - reverseRangeCmpFunc(data, a, b, cmp) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortCmpFunc(data, a, b, cmp) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !(cmp(data[a-1], data[pivot]) < 0) { - mid := partitionEqualCmpFunc(data, a, b, pivot, cmp) - a = mid - continue - } - - mid, alreadyPartitioned := partitionCmpFunc(data, a, b, pivot, cmp) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortCmpFunc(data, a, mid, limit, cmp) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortCmpFunc(data, mid+1, b, limit, cmp) - b = mid - } - } -} - -// partitionCmpFunc does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && (cmp(data[i], data[a]) < 0) { - i++ - } - for i <= j && !(cmp(data[j], data[a]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualCmpFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualCmpFunc[E any](data []E, a, b, pivot int, cmp func(a, b E) int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !(cmp(data[a], data[i]) < 0) { - i++ - } - for i <= j && (cmp(data[a], data[j]) < 0) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortCmpFunc partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !(cmp(data[i], data[i-1]) < 0) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !(cmp(data[j], data[j-1]) < 0) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsCmpFunc scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotCmpFunc chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,โˆž): uses the Tukey ninther method. -func choosePivotCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentCmpFunc(data, i, &swaps, cmp) - j = medianAdjacentCmpFunc(data, j, &swaps, cmp) - k = medianAdjacentCmpFunc(data, k, &swaps, cmp) - } - // Find the median among i, j, k and stores it into j. - j = medianCmpFunc(data, i, j, k, &swaps, cmp) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2CmpFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2CmpFunc[E any](data []E, a, b int, swaps *int, cmp func(a, b E) int) (int, int) { - if cmp(data[b], data[a]) < 0 { - *swaps++ - return b, a - } - return a, b -} - -// medianCmpFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianCmpFunc[E any](data []E, a, b, c int, swaps *int, cmp func(a, b E) int) int { - a, b = order2CmpFunc(data, a, b, swaps, cmp) - b, c = order2CmpFunc(data, b, c, swaps, cmp) - a, b = order2CmpFunc(data, a, b, swaps, cmp) - return b -} - -// medianAdjacentCmpFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentCmpFunc[E any](data []E, a int, swaps *int, cmp func(a, b E) int) int { - return medianCmpFunc(data, a-1, a, a+1, swaps, cmp) -} - -func reverseRangeCmpFunc[E any](data []E, a, b int, cmp func(a, b E) int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeCmpFunc[E any](data []E, a, b, n int, cmp func(a, b E) int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableCmpFunc[E any](data []E, n int, cmp func(a, b E) int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortCmpFunc(data, a, b, cmp) - a = b - b += blockSize - } - insertionSortCmpFunc(data, a, n, cmp) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeCmpFunc(data, a, a+blockSize, b, cmp) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeCmpFunc(data, a, m, n, cmp) - } - blockSize *= 2 - } -} - -// symMergeCmpFunc merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmp(data[h], data[a]) < 0 { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !(cmp(data[m], data[h]) < 0) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !(cmp(data[p-c], data[c]) < 0) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateCmpFunc(data, start, m, end, cmp) - } - if a < start && start < mid { - symMergeCmpFunc(data, a, start, mid, cmp) - } - if mid < end && end < b { - symMergeCmpFunc(data, mid, end, b, cmp) - } -} - -// rotateCmpFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateCmpFunc[E any](data []E, a, m, b int, cmp func(a, b E) int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeCmpFunc(data, m-i, m, j, cmp) - i -= j - } else { - swapRangeCmpFunc(data, m-i, m+j-i, i, cmp) - j -= i - } - } - // i == j - swapRangeCmpFunc(data, m-i, m, i, cmp) -} diff --git a/vendor/golang.org/x/exp/slices/zsortordered.go b/vendor/golang.org/x/exp/slices/zsortordered.go deleted file mode 100644 index 99b47c398..000000000 --- a/vendor/golang.org/x/exp/slices/zsortordered.go +++ /dev/null @@ -1,481 +0,0 @@ -// Code generated by gen_sort_variants.go; DO NOT EDIT. - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package slices - -import "golang.org/x/exp/constraints" - -// insertionSortOrdered sorts data[a:b] using insertion sort. -func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && cmpLess(data[j], data[j-1]); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// siftDownOrdered implements the heap property on data[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && cmpLess(data[first+child], data[first+child+1]) { - child++ - } - if !cmpLess(data[first+root], data[first+child]) { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} - -func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDownOrdered(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDownOrdered(data, lo, i, first) - } -} - -// pdqsortOrdered sorts data[a:b]. -// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. -// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf -// C++ implementation: https://github.com/orlp/pdqsort -// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ -// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. -func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { - const maxInsertion = 12 - - var ( - wasBalanced = true // whether the last partitioning was reasonably balanced - wasPartitioned = true // whether the slice was already partitioned - ) - - for { - length := b - a - - if length <= maxInsertion { - insertionSortOrdered(data, a, b) - return - } - - // Fall back to heapsort if too many bad choices were made. - if limit == 0 { - heapSortOrdered(data, a, b) - return - } - - // If the last partitioning was imbalanced, we need to breaking patterns. - if !wasBalanced { - breakPatternsOrdered(data, a, b) - limit-- - } - - pivot, hint := choosePivotOrdered(data, a, b) - if hint == decreasingHint { - reverseRangeOrdered(data, a, b) - // The chosen pivot was pivot-a elements after the start of the array. - // After reversing it is pivot-a elements before the end of the array. - // The idea came from Rust's implementation. - pivot = (b - 1) - (pivot - a) - hint = increasingHint - } - - // The slice is likely already sorted. - if wasBalanced && wasPartitioned && hint == increasingHint { - if partialInsertionSortOrdered(data, a, b) { - return - } - } - - // Probably the slice contains many duplicate elements, partition the slice into - // elements equal to and elements greater than the pivot. - if a > 0 && !cmpLess(data[a-1], data[pivot]) { - mid := partitionEqualOrdered(data, a, b, pivot) - a = mid - continue - } - - mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) - wasPartitioned = alreadyPartitioned - - leftLen, rightLen := mid-a, b-mid - balanceThreshold := length / 8 - if leftLen < rightLen { - wasBalanced = leftLen >= balanceThreshold - pdqsortOrdered(data, a, mid, limit) - a = mid + 1 - } else { - wasBalanced = rightLen >= balanceThreshold - pdqsortOrdered(data, mid+1, b, limit) - b = mid - } - } -} - -// partitionOrdered does one quicksort partition. -// Let p = data[pivot] -// Moves elements in data[a:b] around, so that data[i]

=p for inewpivot. -// On return, data[newpivot] = p -func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - data[j], data[a] = data[a], data[j] - return j, true - } - data[i], data[j] = data[j], data[i] - i++ - j-- - - for { - for i <= j && cmpLess(data[i], data[a]) { - i++ - } - for i <= j && !cmpLess(data[j], data[a]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - data[j], data[a] = data[a], data[j] - return j, false -} - -// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. -// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. -func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { - data[a], data[pivot] = data[pivot], data[a] - i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned - - for { - for i <= j && !cmpLess(data[a], data[i]) { - i++ - } - for i <= j && cmpLess(data[a], data[j]) { - j-- - } - if i > j { - break - } - data[i], data[j] = data[j], data[i] - i++ - j-- - } - return i -} - -// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. -func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { - const ( - maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted - shortestShifting = 50 // don't shift any elements on short arrays - ) - i := a + 1 - for j := 0; j < maxSteps; j++ { - for i < b && !cmpLess(data[i], data[i-1]) { - i++ - } - - if i == b { - return true - } - - if b-a < shortestShifting { - return false - } - - data[i], data[i-1] = data[i-1], data[i] - - // Shift the smaller one to the left. - if i-a >= 2 { - for j := i - 1; j >= 1; j-- { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - // Shift the greater one to the right. - if b-i >= 2 { - for j := i + 1; j < b; j++ { - if !cmpLess(data[j], data[j-1]) { - break - } - data[j], data[j-1] = data[j-1], data[j] - } - } - } - return false -} - -// breakPatternsOrdered scatters some elements around in an attempt to break some patterns -// that might cause imbalanced partitions in quicksort. -func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { - length := b - a - if length >= 8 { - random := xorshift(length) - modulus := nextPowerOfTwo(length) - - for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { - other := int(uint(random.Next()) & (modulus - 1)) - if other >= length { - other -= length - } - data[idx], data[a+other] = data[a+other], data[idx] - } - } -} - -// choosePivotOrdered chooses a pivot in data[a:b]. -// -// [0,8): chooses a static pivot. -// [8,shortestNinther): uses the simple median-of-three method. -// [shortestNinther,โˆž): uses the Tukey ninther method. -func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { - const ( - shortestNinther = 50 - maxSwaps = 4 * 3 - ) - - l := b - a - - var ( - swaps int - i = a + l/4*1 - j = a + l/4*2 - k = a + l/4*3 - ) - - if l >= 8 { - if l >= shortestNinther { - // Tukey ninther method, the idea came from Rust's implementation. - i = medianAdjacentOrdered(data, i, &swaps) - j = medianAdjacentOrdered(data, j, &swaps) - k = medianAdjacentOrdered(data, k, &swaps) - } - // Find the median among i, j, k and stores it into j. - j = medianOrdered(data, i, j, k, &swaps) - } - - switch swaps { - case 0: - return j, increasingHint - case maxSwaps: - return j, decreasingHint - default: - return j, unknownHint - } -} - -// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. -func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { - if cmpLess(data[b], data[a]) { - *swaps++ - return b, a - } - return a, b -} - -// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. -func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { - a, b = order2Ordered(data, a, b, swaps) - b, c = order2Ordered(data, b, c, swaps) - a, b = order2Ordered(data, a, b, swaps) - return b -} - -// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. -func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { - return medianOrdered(data, a-1, a, a+1, swaps) -} - -func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { - i := a - j := b - 1 - for i < j { - data[i], data[j] = data[j], data[i] - i++ - j-- - } -} - -func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { - for i := 0; i < n; i++ { - data[a+i], data[b+i] = data[b+i], data[a+i] - } -} - -func stableOrdered[E constraints.Ordered](data []E, n int) { - blockSize := 20 // must be > 0 - a, b := 0, blockSize - for b <= n { - insertionSortOrdered(data, a, b) - a = b - b += blockSize - } - insertionSortOrdered(data, a, n) - - for blockSize < n { - a, b = 0, 2*blockSize - for b <= n { - symMergeOrdered(data, a, a+blockSize, b) - a = b - b += 2 * blockSize - } - if m := a + blockSize; m < n { - symMergeOrdered(data, a, m, n) - } - blockSize *= 2 - } -} - -// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using -// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum -// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz -// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in -// Computer Science, pages 714-723. Springer, 2004. -// -// Let M = m-a and N = b-n. Wolog M < N. -// The recursion depth is bound by ceil(log(N+M)). -// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. -// The algorithm needs O((M+N)*log(M)) calls to data.Swap. -// -// The paper gives O((M+N)*log(M)) as the number of assignments assuming a -// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation -// in the paper carries through for Swap operations, especially as the block -// swapping rotate uses only O(M+N) Swaps. -// -// symMerge assumes non-degenerate arguments: a < m && m < b. -// Having the caller check this condition eliminates many leaf recursion calls, -// which improves performance. -func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[a] into data[m:b] - // if data[a:m] only contains one element. - if m-a == 1 { - // Use binary search to find the lowest index i - // such that data[i] >= data[a] for m <= i < b. - // Exit the search loop with i == b in case no such index exists. - i := m - j := b - for i < j { - h := int(uint(i+j) >> 1) - if cmpLess(data[h], data[a]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[a] reaches the position before i. - for k := a; k < i-1; k++ { - data[k], data[k+1] = data[k+1], data[k] - } - return - } - - // Avoid unnecessary recursions of symMerge - // by direct insertion of data[m] into data[a:m] - // if data[m:b] only contains one element. - if b-m == 1 { - // Use binary search to find the lowest index i - // such that data[i] > data[m] for a <= i < m. - // Exit the search loop with i == m in case no such index exists. - i := a - j := m - for i < j { - h := int(uint(i+j) >> 1) - if !cmpLess(data[m], data[h]) { - i = h + 1 - } else { - j = h - } - } - // Swap values until data[m] reaches the position i. - for k := m; k > i; k-- { - data[k], data[k-1] = data[k-1], data[k] - } - return - } - - mid := int(uint(a+b) >> 1) - n := mid + m - var start, r int - if m > mid { - start = n - b - r = mid - } else { - start = a - r = m - } - p := n - 1 - - for start < r { - c := int(uint(start+r) >> 1) - if !cmpLess(data[p-c], data[c]) { - start = c + 1 - } else { - r = c - } - } - - end := n - start - if start < m && m < end { - rotateOrdered(data, start, m, end) - } - if a < start && start < mid { - symMergeOrdered(data, a, start, mid) - } - if mid < end && end < b { - symMergeOrdered(data, mid, end, b) - } -} - -// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: -// Data of the form 'x u v y' is changed to 'x v u y'. -// rotate performs at most b-a many calls to data.Swap, -// and it assumes non-degenerate arguments: a < m && m < b. -func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { - i := m - a - j := b - m - - for i != j { - if i > j { - swapRangeOrdered(data, m-i, m, j) - i -= j - } else { - swapRangeOrdered(data, m-i, m+j-i, i) - j -= i - } - } - // i == j - swapRangeOrdered(data, m-i, m, i) -} diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index 794b2e32b..563270c15 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -195,7 +195,7 @@ func (r *Reservation) CancelAt(t time.Time) { // update state r.lim.last = t r.lim.tokens = tokens - if r.timeToAct == r.lim.lastEvent { + if r.timeToAct.Equal(r.lim.lastEvent) { prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens))) if !prevEvent.Before(t) { r.lim.lastEvent = prevEvent diff --git a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go index 669133d04..c96e44834 100644 --- a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go +++ b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go @@ -32,7 +32,7 @@ var byteType = reflect.TypeOf(byte(0)) func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor { f := new(filedesc.Field) f.L0.ParentFile = filedesc.SurrogateProto2 - f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures + packed := false for len(tag) > 0 { i := strings.IndexByte(tag, ',') if i < 0 { @@ -108,7 +108,7 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri f.L1.StringName.InitJSON(jsonName) } case s == "packed": - f.L1.EditionFeatures.IsPacked = true + packed = true case strings.HasPrefix(s, "def="): // The default tag is special in that everything afterwards is the // default regardless of the presence of commas. @@ -121,6 +121,13 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri tag = strings.TrimPrefix(tag[i:], ",") } + // Update EditionFeatures after the loop and after we know whether this is + // a proto2 or proto3 field. + f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures + if packed { + f.L1.EditionFeatures.IsPacked = true + } + // The generator uses the group message name instead of the field name. // We obtain the real field name by lowercasing the group name. if f.L1.Kind == protoreflect.GroupKind { diff --git a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go index 099b2bf45..9aa7a9bb7 100644 --- a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go +++ b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go @@ -424,27 +424,34 @@ func (d *Decoder) parseFieldName() (tok Token, err error) { return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in)) } -// parseTypeName parses Any type URL or extension field name. The name is -// enclosed in [ and ] characters. The C++ parser does not handle many legal URL -// strings. This implementation is more liberal and allows for the pattern -// ^[-_a-zA-Z0-9]+([./][-_a-zA-Z0-9]+)*`). Whitespaces and comments are allowed -// in between [ ], '.', '/' and the sub names. +// parseTypeName parses an Any type URL or an extension field name. The name is +// enclosed in [ and ] characters. We allow almost arbitrary type URL prefixes, +// closely following the text-format spec [1,2]. We implement "ExtensionName | +// AnyName" as follows (with some exceptions for backwards compatibility): +// +// char = [-_a-zA-Z0-9] +// url_char = char | [.~!$&'()*+,;=] | "%", hex, hex +// +// Ident = char, { char } +// TypeName = Ident, { ".", Ident } ; +// UrlPrefix = url_char, { url_char | "/" } ; +// ExtensionName = "[", TypeName, "]" ; +// AnyName = "[", UrlPrefix, "/", TypeName, "]" ; +// +// Additionally, we allow arbitrary whitespace and comments between [ and ]. +// +// [1] https://protobuf.dev/reference/protobuf/textformat-spec/#characters +// [2] https://protobuf.dev/reference/protobuf/textformat-spec/#field-names func (d *Decoder) parseTypeName() (Token, error) { - startPos := len(d.orig) - len(d.in) // Use alias s to advance first in order to use d.in for error handling. - // Caller already checks for [ as first character. + // Caller already checks for [ as first character (d.in[0] == '['). s := consume(d.in[1:], 0) if len(s) == 0 { return Token{}, ErrUnexpectedEOF } + // Collect everything between [ and ] in name. var name []byte - for len(s) > 0 && isTypeNameChar(s[0]) { - name = append(name, s[0]) - s = s[1:] - } - s = consume(s, 0) - var closed bool for len(s) > 0 && !closed { switch { @@ -452,23 +459,20 @@ func (d *Decoder) parseTypeName() (Token, error) { s = s[1:] closed = true - case s[0] == '/', s[0] == '.': - if len(name) > 0 && (name[len(name)-1] == '/' || name[len(name)-1] == '.') { - return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", - d.orig[startPos:len(d.orig)-len(s)+1]) - } + case s[0] == '/' || isTypeNameChar(s[0]) || isUrlExtraChar(s[0]): name = append(name, s[0]) - s = s[1:] - s = consume(s, 0) - for len(s) > 0 && isTypeNameChar(s[0]) { - name = append(name, s[0]) - s = s[1:] + s = consume(s[1:], 0) + + // URL percent-encoded chars + case s[0] == '%': + if len(s) < 3 || !isHexChar(s[1]) || !isHexChar(s[2]) { + return Token{}, d.parseTypeNameError(s, 3) } - s = consume(s, 0) + name = append(name, s[0], s[1], s[2]) + s = consume(s[3:], 0) default: - return Token{}, d.newSyntaxError( - "invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1]) + return Token{}, d.parseTypeNameError(s, 1) } } @@ -476,15 +480,38 @@ func (d *Decoder) parseTypeName() (Token, error) { return Token{}, ErrUnexpectedEOF } - // First character cannot be '.'. Last character cannot be '.' or '/'. - size := len(name) - if size == 0 || name[0] == '.' || name[size-1] == '.' || name[size-1] == '/' { - return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", - d.orig[startPos:len(d.orig)-len(s)]) + // Split collected name on last '/' into urlPrefix and typeName (if '/' is + // present). + typeName := name + if i := bytes.LastIndexByte(name, '/'); i != -1 { + urlPrefix := name[:i] + typeName = name[i+1:] + + // urlPrefix may be empty (for backwards compatibility). + // If non-empty, it must not start with '/'. + if len(urlPrefix) > 0 && urlPrefix[0] == '/' { + return Token{}, d.parseTypeNameError(s, 0) + } } + // typeName must not be empty (note: "" splits to [""]) and all identifier + // parts must not be empty. + for _, ident := range bytes.Split(typeName, []byte{'.'}) { + if len(ident) == 0 { + return Token{}, d.parseTypeNameError(s, 0) + } + } + + // typeName must not contain any percent-encoded or special URL chars. + for _, b := range typeName { + if b == '%' || (b != '.' && isUrlExtraChar(b)) { + return Token{}, d.parseTypeNameError(s, 0) + } + } + + startPos := len(d.orig) - len(d.in) + endPos := len(d.orig) - len(s) d.in = s - endPos := len(d.orig) - len(d.in) d.consume(0) return Token{ @@ -496,16 +523,32 @@ func (d *Decoder) parseTypeName() (Token, error) { }, nil } +func (d *Decoder) parseTypeNameError(s []byte, numUnconsumedChars int) error { + return d.newSyntaxError( + "invalid type URL/extension field name: %s", + d.in[:len(d.in)-len(s)+min(numUnconsumedChars, len(s))], + ) +} + +func isHexChar(b byte) bool { + return ('0' <= b && b <= '9') || + ('a' <= b && b <= 'f') || + ('A' <= b && b <= 'F') +} + func isTypeNameChar(b byte) bool { - return (b == '-' || b == '_' || + return b == '-' || b == '_' || ('0' <= b && b <= '9') || ('a' <= b && b <= 'z') || - ('A' <= b && b <= 'Z')) + ('A' <= b && b <= 'Z') } -func isWhiteSpace(b byte) bool { +// isUrlExtraChar complements isTypeNameChar with extra characters that we allow +// in URLs but not in type names. Note that '/' is not included so that it can +// be treated specially. +func isUrlExtraChar(b byte) bool { switch b { - case ' ', '\n', '\r', '\t': + case '.', '~', '!', '$', '&', '(', ')', '*', '+', ',', ';', '=': return true default: return false diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go index dbcf90b87..c775e5832 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go @@ -32,6 +32,7 @@ const ( EditionProto3 Edition = 999 Edition2023 Edition = 1000 Edition2024 Edition = 1001 + EditionUnstable Edition = 9999 EditionUnsupported Edition = 100000 ) diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go index dd31faaeb..78f02b1b4 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go @@ -330,7 +330,6 @@ func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) { md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) extensionIdx++ case genid.DescriptorProto_Options_field_number: - md.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: @@ -356,27 +355,6 @@ func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) { md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions) } -func (md *Message) unmarshalOptions(b []byte) { - for len(b) > 0 { - num, typ, n := protowire.ConsumeTag(b) - b = b[n:] - switch typ { - case protowire.VarintType: - v, m := protowire.ConsumeVarint(b) - b = b[m:] - switch num { - case genid.MessageOptions_MapEntry_field_number: - md.L1.IsMapEntry = protowire.DecodeBool(v) - case genid.MessageOptions_MessageSetWireFormat_field_number: - md.L1.IsMessageSet = protowire.DecodeBool(v) - } - default: - m := protowire.ConsumeFieldValue(num, typ, b) - b = b[m:] - } - } -} - func unmarshalMessageReservedRange(b []byte) (r [2]protoreflect.FieldNumber) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) diff --git a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go index 950a6a325..65aaf4d21 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +++ b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go @@ -26,6 +26,7 @@ const ( Edition_EDITION_PROTO3_enum_value = 999 Edition_EDITION_2023_enum_value = 1000 Edition_EDITION_2024_enum_value = 1001 + Edition_EDITION_UNSTABLE_enum_value = 9999 Edition_EDITION_1_TEST_ONLY_enum_value = 1 Edition_EDITION_2_TEST_ONLY_enum_value = 2 Edition_EDITION_99997_TEST_ONLY_enum_value = 99997 diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go index 229c69801..4a3bf393e 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go @@ -113,6 +113,9 @@ func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalO } func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { + if opts.depth--; opts.depth < 0 { + return out, errRecursionDepth + } if wtyp != protowire.BytesType { return out, errUnknown } @@ -170,6 +173,9 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo } func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { + if opts.depth--; opts.depth < 0 { + return out, errRecursionDepth + } if wtyp != protowire.BytesType { return out, errUnknown } diff --git a/vendor/google.golang.org/protobuf/internal/impl/decode.go b/vendor/google.golang.org/protobuf/internal/impl/decode.go index e0dd21fa5..1228b5c8c 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/decode.go +++ b/vendor/google.golang.org/protobuf/internal/impl/decode.go @@ -102,8 +102,7 @@ var errUnknown = errors.New("unknown") func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) { mi.init() - opts.depth-- - if opts.depth < 0 { + if opts.depth--; opts.depth < 0 { return out, errRecursionDepth } if flags.ProtoLegacy && mi.isMessageSet { diff --git a/vendor/google.golang.org/protobuf/internal/impl/validate.go b/vendor/google.golang.org/protobuf/internal/impl/validate.go index 7b2995dde..99a1eb95f 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/validate.go +++ b/vendor/google.golang.org/protobuf/internal/impl/validate.go @@ -68,9 +68,13 @@ func Validate(mt protoreflect.MessageType, in protoiface.UnmarshalInput) (out pr if in.Resolver == nil { in.Resolver = protoregistry.GlobalTypes } + if in.Depth == 0 { + in.Depth = protowire.DefaultRecursionLimit + } o, st := mi.validate(in.Buf, 0, unmarshalOptions{ flags: in.Flags, resolver: in.Resolver, + depth: in.Depth, }) if o.initialized { out.Flags |= protoiface.UnmarshalInitialized @@ -257,6 +261,9 @@ func (mi *MessageInfo) validate(b []byte, groupTag protowire.Number, opts unmars states[0].typ = validationTypeGroup states[0].endGroup = groupTag } + if opts.depth--; opts.depth < 0 { + return out, ValidationInvalid + } initialized := true start := len(b) State: @@ -451,6 +458,13 @@ State: mi: vi.mi, tail: b, }) + if vi.typ == validationTypeMessage || + vi.typ == validationTypeGroup || + vi.typ == validationTypeMap { + if opts.depth--; opts.depth < 0 { + return out, ValidationInvalid + } + } b = v continue State case validationTypeRepeatedVarint: @@ -499,6 +513,9 @@ State: mi: vi.mi, endGroup: num, }) + if opts.depth--; opts.depth < 0 { + return out, ValidationInvalid + } continue State case flags.ProtoLegacy && vi.typ == validationTypeMessageSetItem: typeid, v, n, err := messageset.ConsumeFieldValue(b, false) @@ -521,6 +538,13 @@ State: mi: xvi.mi, tail: b[n:], }) + if xvi.typ == validationTypeMessage || + xvi.typ == validationTypeGroup || + xvi.typ == validationTypeMap { + if opts.depth--; opts.depth < 0 { + return out, ValidationInvalid + } + } b = v continue State } @@ -547,12 +571,14 @@ State: switch st.typ { case validationTypeMessage, validationTypeGroup: numRequiredFields = int(st.mi.numRequiredFields) + opts.depth++ case validationTypeMap: // If this is a map field with a message value that contains // required fields, require that the value be present. if st.mi != nil && st.mi.numRequiredFields > 0 { numRequiredFields = 1 } + opts.depth++ } // If there are more than 64 required fields, this check will // always fail and we will report that the message is potentially diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go index 77de0f238..763fd8284 100644 --- a/vendor/google.golang.org/protobuf/internal/version/version.go +++ b/vendor/google.golang.org/protobuf/internal/version/version.go @@ -52,7 +52,7 @@ import ( const ( Major = 1 Minor = 36 - Patch = 10 + Patch = 11 PreRelease = "" ) diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go index 4cbf1aeaf..889d8511d 100644 --- a/vendor/google.golang.org/protobuf/proto/decode.go +++ b/vendor/google.golang.org/protobuf/proto/decode.go @@ -121,9 +121,8 @@ func (o UnmarshalOptions) unmarshal(b []byte, m protoreflect.Message) (out proto out, err = methods.Unmarshal(in) } else { - o.RecursionLimit-- - if o.RecursionLimit < 0 { - return out, errors.New("exceeded max recursion depth") + if o.RecursionLimit--; o.RecursionLimit < 0 { + return out, errRecursionDepth } err = o.unmarshalMessageSlow(b, m) } @@ -220,6 +219,9 @@ func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp protowire.Type, m pro } func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) { + if o.RecursionLimit--; o.RecursionLimit < 0 { + return 0, errRecursionDepth + } if wtyp != protowire.BytesType { return 0, errUnknown } @@ -305,3 +307,5 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv proto var errUnknown = errors.New("BUG: internal error (unknown)") var errDecode = errors.New("cannot parse invalid wire-format data") + +var errRecursionDepth = errors.New("exceeded maximum recursion depth") diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go index 9196288e4..40f17af4e 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go @@ -108,7 +108,9 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot if f.L1.Path == "" { return nil, errors.New("file path must be populated") } - if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) { + if f.L1.Syntax == protoreflect.Editions && + (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) && + fd.GetEdition() != descriptorpb.Edition_EDITION_UNSTABLE { // Allow cmd/protoc-gen-go/testdata to use any edition for easier // testing of upcoming edition features. if !strings.HasPrefix(fd.GetName(), "cmd/protoc-gen-go/testdata/") { @@ -152,6 +154,7 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot imp := &f.L2.Imports[i] imps.importPublic(imp.Imports()) } + optionImps := importSet{f.Path(): true} if len(fd.GetOptionDependency()) > 0 { optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency())) for i, path := range fd.GetOptionDependency() { @@ -165,10 +168,12 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot } imp.FileDescriptor = f - if imps[imp.Path()] { + if imps[imp.Path()] || optionImps[imp.Path()] { return nil, errors.New("already imported %q", path) } - imps[imp.Path()] = true + // This needs to be a separate map so that we don't recognize non-options + // symbols coming from option imports. + optionImps[imp.Path()] = true } f.L2.OptionImports = func() protoreflect.FileImports { return &optionImports diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go index 697a61b29..147b8c739 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go @@ -46,6 +46,8 @@ func toEditionProto(ed filedesc.Edition) descriptorpb.Edition { return descriptorpb.Edition_EDITION_2023 case filedesc.Edition2024: return descriptorpb.Edition_EDITION_2024 + case filedesc.EditionUnstable: + return descriptorpb.Edition_EDITION_UNSTABLE default: panic(fmt.Sprintf("unknown value for edition: %v", ed)) } @@ -58,7 +60,7 @@ func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet { return def } edpb := toEditionProto(ed) - if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb { + if (defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb) && edpb != descriptorpb.Edition_EDITION_UNSTABLE { // This should never happen protodesc.(FileOptions).New would fail when // initializing the file descriptor. // This most likely means the embedded defaults were not updated. diff --git a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go index 4eacb523c..0b23faa95 100644 --- a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go +++ b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go @@ -69,6 +69,8 @@ const ( // comparison. Edition_EDITION_2023 Edition = 1000 Edition_EDITION_2024 Edition = 1001 + // A placeholder edition for developing and testing unscheduled features. + Edition_EDITION_UNSTABLE Edition = 9999 // Placeholder editions for testing feature resolution. These should not be // used or relied on outside of tests. Edition_EDITION_1_TEST_ONLY Edition = 1 @@ -91,6 +93,7 @@ var ( 999: "EDITION_PROTO3", 1000: "EDITION_2023", 1001: "EDITION_2024", + 9999: "EDITION_UNSTABLE", 1: "EDITION_1_TEST_ONLY", 2: "EDITION_2_TEST_ONLY", 99997: "EDITION_99997_TEST_ONLY", @@ -105,6 +108,7 @@ var ( "EDITION_PROTO3": 999, "EDITION_2023": 1000, "EDITION_2024": 1001, + "EDITION_UNSTABLE": 9999, "EDITION_1_TEST_ONLY": 1, "EDITION_2_TEST_ONLY": 2, "EDITION_99997_TEST_ONLY": 99997, @@ -4793,11 +4797,11 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" + "\x18EnumValueDescriptorProto\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" + "\x06number\x18\x02 \x01(\x05R\x06number\x12;\n" + - "\aoptions\x18\x03 \x01(\v2!.google.protobuf.EnumValueOptionsR\aoptions\"\xa7\x01\n" + + "\aoptions\x18\x03 \x01(\v2!.google.protobuf.EnumValueOptionsR\aoptions\"\xb5\x01\n" + "\x16ServiceDescriptorProto\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12>\n" + "\x06method\x18\x02 \x03(\v2&.google.protobuf.MethodDescriptorProtoR\x06method\x129\n" + - "\aoptions\x18\x03 \x01(\v2\x1f.google.protobuf.ServiceOptionsR\aoptions\"\x89\x02\n" + + "\aoptions\x18\x03 \x01(\v2\x1f.google.protobuf.ServiceOptionsR\aoptionsJ\x04\b\x04\x10\x05R\x06stream\"\x89\x02\n" + "\x15MethodDescriptorProto\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1d\n" + "\n" + @@ -5033,14 +5037,15 @@ const file_google_protobuf_descriptor_proto_rawDesc = "" + "\bSemantic\x12\b\n" + "\x04NONE\x10\x00\x12\a\n" + "\x03SET\x10\x01\x12\t\n" + - "\x05ALIAS\x10\x02*\xa7\x02\n" + + "\x05ALIAS\x10\x02*\xbe\x02\n" + "\aEdition\x12\x13\n" + "\x0fEDITION_UNKNOWN\x10\x00\x12\x13\n" + "\x0eEDITION_LEGACY\x10\x84\a\x12\x13\n" + "\x0eEDITION_PROTO2\x10\xe6\a\x12\x13\n" + "\x0eEDITION_PROTO3\x10\xe7\a\x12\x11\n" + "\fEDITION_2023\x10\xe8\a\x12\x11\n" + - "\fEDITION_2024\x10\xe9\a\x12\x17\n" + + "\fEDITION_2024\x10\xe9\a\x12\x15\n" + + "\x10EDITION_UNSTABLE\x10\x8fN\x12\x17\n" + "\x13EDITION_1_TEST_ONLY\x10\x01\x12\x17\n" + "\x13EDITION_2_TEST_ONLY\x10\x02\x12\x1d\n" + "\x17EDITION_99997_TEST_ONLY\x10\x9d\x8d\x06\x12\x1d\n" + diff --git a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go index 06d584c14..484c21fd5 100644 --- a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go +++ b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go @@ -172,13 +172,14 @@ import ( // ) to obtain a formatter capable of generating timestamps in this format. type Timestamp struct { state protoimpl.MessageState `protogen:"open.v1"` - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. + // Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must + // be between -315576000000 and 315576000000 inclusive (which corresponds to + // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z). Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 + // Non-negative fractions of a second at nanosecond resolution. This field is + // the nanosecond portion of the duration, not an alternative to seconds. + // Negative second values with fractions must still have non-negative nanos + // values that count forward in time. Must be between 0 and 999,999,999 // inclusive. Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` unknownFields protoimpl.UnknownFields diff --git a/vendor/modules.txt b/vendor/modules.txt index a6f42553e..e6f3b975e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -240,7 +240,7 @@ github.com/golang/mock/gomock # github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree -# github.com/google/cel-go v0.26.1 => github.com/google/cel-go v0.22.0 +# github.com/google/cel-go v0.27.0 => github.com/google/cel-go v0.22.0 ## explicit; go 1.21.1 github.com/google/cel-go/cel github.com/google/cel-go/checker @@ -278,8 +278,8 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/go-querystring v1.1.0 -## explicit; go 1.10 +# github.com/google/go-querystring v1.2.0 +## explicit; go 1.13 github.com/google/go-querystring/query # github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 ## explicit; go 1.24.0 @@ -542,8 +542,8 @@ github.com/yuin/gopher-lua github.com/yuin/gopher-lua/ast github.com/yuin/gopher-lua/parse github.com/yuin/gopher-lua/pm -# gitlab.com/gitlab-org/api/client-go v0.145.0 -## explicit; go 1.23.0 +# gitlab.com/gitlab-org/api/client-go v1.46.0 +## explicit; go 1.24.0 gitlab.com/gitlab-org/api/client-go # go.opentelemetry.io/auto/sdk v1.2.1 ## explicit; go 1.24.0 @@ -642,9 +642,8 @@ golang.org/x/crypto/internal/alias golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/md4 golang.org/x/crypto/sha3 -# golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 -## explicit; go 1.20 -golang.org/x/exp/constraints +# golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 +## explicit; go 1.24.0 golang.org/x/exp/slices # golang.org/x/mod v0.32.0 ## explicit; go 1.24.0 @@ -716,8 +715,8 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.12.0 -## explicit; go 1.23.0 +# golang.org/x/time v0.14.0 +## explicit; go 1.24.0 golang.org/x/time/rate # golang.org/x/tools v0.41.0 ## explicit; go 1.24.0 @@ -817,7 +816,7 @@ google.golang.org/grpc/serviceconfig google.golang.org/grpc/stats google.golang.org/grpc/status google.golang.org/grpc/tap -# google.golang.org/protobuf v1.36.10 +# google.golang.org/protobuf v1.36.11 ## explicit; go 1.23 google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson