//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// AccessRequest represents a access request for a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html
type AccessRequest struct {
ID int `json:"id"`
Username string `json:"username"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
RequestedAt *time.Time `json:"requested_at"`
AccessLevel AccessLevelValue `json:"access_level"`
}
// AccessRequestsService handles communication with the project/group
// access requests related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/access_requests.html
type AccessRequestsService struct {
client *Client
}
// ListAccessRequestsOptions represents the available
// ListProjectAccessRequests() or ListGroupAccessRequests() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#list-access-requests-for-a-group-or-project
type ListAccessRequestsOptions ListOptions
// ListProjectAccessRequests gets a list of access requests
// viewable by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#list-access-requests-for-a-group-or-project
func (s *AccessRequestsService) ListProjectAccessRequests(pid interface{}, 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
}
// ListGroupAccessRequests gets a list of access requests
// viewable by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#list-access-requests-for-a-group-or-project
func (s *AccessRequestsService) ListGroupAccessRequests(gid interface{}, 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
}
// RequestProjectAccess requests access for the authenticated user
// to a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#request-access-to-a-group-or-project
func (s *AccessRequestsService) RequestProjectAccess(pid interface{}, 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
}
// RequestGroupAccess requests access for the authenticated user
// to a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#request-access-to-a-group-or-project
func (s *AccessRequestsService) RequestGroupAccess(gid interface{}, 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
}
// ApproveAccessRequestOptions represents the available
// ApproveProjectAccessRequest() and ApproveGroupAccessRequest() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#approve-an-access-request
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/ee/api/access_requests.html#approve-an-access-request
func (s *AccessRequestsService) ApproveProjectAccessRequest(pid interface{}, 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
}
// ApproveGroupAccessRequest approves an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#approve-an-access-request
func (s *AccessRequestsService) ApproveGroupAccessRequest(gid interface{}, 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
}
// DenyProjectAccessRequest denies an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#deny-an-access-request
func (s *AccessRequestsService) DenyProjectAccessRequest(pid interface{}, 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)
}
// DenyGroupAccessRequest denies an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/access_requests.html#deny-an-access-request
func (s *AccessRequestsService) DenyGroupAccessRequest(gid interface{}, 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)
}
//
// Copyright 2023, 徐晓伟 <xuxiaowei@xuxiaowei.com.cn>
//
// 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"
// AppearanceService handles communication with appearance of the Gitlab API.
//
// Gitlab API docs : https://docs.gitlab.com/ee/api/appearance.html
type AppearanceService struct {
client *Client
}
// Appearance represents a GitLab appearance.
//
// Gitlab API docs : https://docs.gitlab.com/ee/api/appearance.html
type Appearance struct {
Title string `json:"title"`
Description string `json:"description"`
PWAName string `json:"pwa_name"`
PWAShortName string `json:"pwa_short_name"`
PWADescription string `json:"pwa_description"`
PWAIcon string `json:"pwa_icon"`
Logo string `json:"logo"`
HeaderLogo string `json:"header_logo"`
Favicon string `json:"favicon"`
NewProjectGuidelines string `json:"new_project_guidelines"`
ProfileImageGuidelines string `json:"profile_image_guidelines"`
HeaderMessage string `json:"header_message"`
FooterMessage string `json:"footer_message"`
MessageBackgroundColor string `json:"message_background_color"`
MessageFontColor string `json:"message_font_color"`
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/ee/api/appearance.html#get-current-appearance-configuration
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
}
// ChangeAppearanceOptions represents the available ChangeAppearance() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/appearance.html#change-appearance-configuration
type ChangeAppearanceOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
PWAName *string `url:"pwa_name,omitempty" json:"pwa_name,omitempty"`
PWAShortName *string `url:"pwa_short_name,omitempty" json:"pwa_short_name,omitempty"`
PWADescription *string `url:"pwa_description,omitempty" json:"pwa_description,omitempty"`
PWAIcon *string `url:"pwa_icon,omitempty" json:"pwa_icon,omitempty"`
Logo *string `url:"logo,omitempty" json:"logo,omitempty"`
HeaderLogo *string `url:"header_logo,omitempty" json:"header_logo,omitempty"`
Favicon *string `url:"favicon,omitempty" json:"favicon,omitempty"`
NewProjectGuidelines *string `url:"new_project_guidelines,omitempty" json:"new_project_guidelines,omitempty"`
ProfileImageGuidelines *string `url:"profile_image_guidelines,omitempty" json:"profile_image_guidelines,omitempty"`
HeaderMessage *string `url:"header_message,omitempty" json:"header_message,omitempty"`
FooterMessage *string `url:"footer_message,omitempty" json:"footer_message,omitempty"`
MessageBackgroundColor *string `url:"message_background_color,omitempty" json:"message_background_color,omitempty"`
MessageFontColor *string `url:"message_font_color,omitempty" json:"message_font_color,omitempty"`
EmailHeaderAndFooterEnabled *bool `url:"email_header_and_footer_enabled,omitempty" json:"email_header_and_footer_enabled,omitempty"`
URL *string `url:"url,omitempty" json:"url,omitempty"`
}
// ChangeAppearance changes the appearance configuration.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/appearance.html#change-appearance-configuration
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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ApplicationsService handles communication with administrables applications
// of the Gitlab API.
//
// Gitlab API docs : https://docs.gitlab.com/ee/api/applications.html
type ApplicationsService struct {
client *Client
}
// Application represents a GitLab application
type Application struct {
ID int `json:"id"`
ApplicationID string `json:"application_id"`
ApplicationName string `json:"application_name"`
Secret string `json:"secret"`
CallbackURL string `json:"callback_url"`
Confidential bool `json:"confidential"`
}
// CreateApplicationOptions represents the available CreateApplication() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/applications.html#create-an-application
type CreateApplicationOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
RedirectURI *string `url:"redirect_uri,omitempty" json:"redirect_uri,omitempty"`
Scopes *string `url:"scopes,omitempty" json:"scopes,omitempty"`
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/ee/api/applications.html#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
}
// ListApplicationsOptions represents the available
// ListApplications() options.
type ListApplicationsOptions ListOptions
// ListApplications get a list of administrables applications by the authenticated user
//
// Gitlab API docs : https://docs.gitlab.com/ee/api/applications.html#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
}
// DeleteApplication removes a specific application.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/applications.html#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)
}
package gitlab
import (
"fmt"
"net/http"
"time"
)
// AuditEvent represents an audit event for a group, a project or the instance.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html
type AuditEvent struct {
ID int `json:"id"`
AuthorID int `json:"author_id"`
EntityID int `json:"entity_id"`
EntityType string `json:"entity_type"`
Details AuditEventDetails `json:"details"`
CreatedAt *time.Time `json:"created_at"`
EventType string `json:"event_type"`
}
// AuditEventDetails represents the details portion of an audit event for
// a group, a project or the instance. The exact fields that are returned
// for an audit event depend on the action being recorded.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html
type AuditEventDetails struct {
With string `json:"with"`
Add string `json:"add"`
As string `json:"as"`
Change string `json:"change"`
From string `json:"from"`
To string `json:"to"`
Remove string `json:"remove"`
CustomMessage string `json:"custom_message"`
AuthorName string `json:"author_name"`
AuthorEmail string `json:"author_email"`
AuthorClass string `json:"author_class"`
TargetID interface{} `json:"target_id"`
TargetType string `json:"target_type"`
TargetDetails string `json:"target_details"`
IPAddress string `json:"ip_address"`
EntityPath string `json:"entity_path"`
FailedLogin string `json:"failed_login"`
}
// AuditEventsService handles communication with the project/group/instance
// audit event related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html
type AuditEventsService struct {
client *Client
}
// ListAuditEventsOptions represents the available ListProjectAuditEvents(),
// ListGroupAuditEvents() or ListInstanceAuditEvents() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html
type ListAuditEventsOptions struct {
ListOptions
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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/ee/api/audit_events.html#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
}
// GetInstanceAuditEvent gets a specific instance audit event.
// Authentication as Administrator is required.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html#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
}
// ListGroupAuditEvents gets a list of audit events for the specified group
// viewable by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html#retrieve-all-group-audit-events
func (s *AuditEventsService) ListGroupAuditEvents(gid interface{}, 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
}
// GetGroupAuditEvent gets a specific group audit event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html#retrieve-a-specific-group-audit-event
func (s *AuditEventsService) GetGroupAuditEvent(gid interface{}, 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
}
// ListProjectAuditEvents gets a list of audit events for the specified project
// viewable by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/audit_events.html#retrieve-all-project-audit-events
func (s *AuditEventsService) ListProjectAuditEvents(pid interface{}, 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
}
// GetProjectAuditEvent gets a specific project audit event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/audit_events.html#retrieve-a-specific-project-audit-event
func (s *AuditEventsService) GetProjectAuditEvent(pid interface{}, 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
}
//
// Copyright 2021, Pavel Kostohrys
//
// 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"
)
// AvatarRequestsService handles communication with the avatar related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/avatar.html
type AvatarRequestsService struct {
client *Client
}
// Avatar represents a GitLab avatar.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/avatar.html
type Avatar struct {
AvatarURL string `json:"avatar_url"`
}
// GetAvatarOptions represents the available GetAvatar() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/avatar.html#get-a-single-avatar-url
type GetAvatarOptions struct {
Email *string `url:"email,omitempty" json:"email,omitempty"`
Size *int `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/ee/api/avatar.html#get-a-single-avatar-url
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
}
//
// Copyright 2021, Arkbriar
//
// 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 (
"fmt"
"net/http"
"time"
)
// AwardEmojiService handles communication with the emoji awards related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/award_emoji.html
type AwardEmojiService struct {
client *Client
}
// AwardEmoji represents a GitLab Award Emoji.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/award_emoji.html
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"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
AwardableID int `json:"awardable_id"`
AwardableType string `json:"awardable_type"`
}
const (
awardMergeRequest = "merge_requests"
awardIssue = "issues"
awardSnippets = "snippets"
)
// ListAwardEmojiOptions represents the available options for listing emoji
// for each resources
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html
type ListAwardEmojiOptions ListOptions
// ListMergeRequestAwardEmoji gets a list of all award emoji on the merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#list-an-awardables-award-emojis
func (s *AwardEmojiService) ListMergeRequestAwardEmoji(pid interface{}, mergeRequestIID int, 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/ee/api/award_emoji.html#list-an-awardables-award-emojis
func (s *AwardEmojiService) ListIssueAwardEmoji(pid interface{}, issueIID int, 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/ee/api/award_emoji.html#list-an-awardables-award-emojis
func (s *AwardEmojiService) ListSnippetAwardEmoji(pid interface{}, snippetID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) {
return s.listAwardEmoji(pid, awardSnippets, snippetID, opt, options...)
}
func (s *AwardEmojiService) listAwardEmoji(pid interface{}, 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,
)
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/ee/api/award_emoji.html#get-single-award-emoji
func (s *AwardEmojiService) GetMergeRequestAwardEmoji(pid interface{}, mergeRequestIID, awardID int, 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/ee/api/award_emoji.html#get-single-award-emoji
func (s *AwardEmojiService) GetIssueAwardEmoji(pid interface{}, issueIID, awardID int, 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/ee/api/award_emoji.html#get-single-award-emoji
func (s *AwardEmojiService) GetSnippetAwardEmoji(pid interface{}, snippetID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) {
return s.getAwardEmoji(pid, awardSnippets, snippetID, awardID, options...)
}
func (s *AwardEmojiService) getAwardEmoji(pid interface{}, 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,
)
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
// for a resource
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#award-a-new-emoji
type CreateAwardEmojiOptions struct {
Name string `json:"name"`
}
// CreateMergeRequestAwardEmoji get an award emoji from merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#award-a-new-emoji
func (s *AwardEmojiService) CreateMergeRequestAwardEmoji(pid interface{}, mergeRequestIID int, 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/ee/api/award_emoji.html#award-a-new-emoji
func (s *AwardEmojiService) CreateIssueAwardEmoji(pid interface{}, issueIID int, 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/ee/api/award_emoji.html#award-a-new-emoji
func (s *AwardEmojiService) CreateSnippetAwardEmoji(pid interface{}, snippetID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) {
return s.createAwardEmoji(pid, awardSnippets, snippetID, opt, options...)
}
func (s *AwardEmojiService) createAwardEmoji(pid interface{}, 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,
)
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/ee/api/award_emoji.html#delete-an-award-emoji
func (s *AwardEmojiService) DeleteIssueAwardEmoji(pid interface{}, issueIID, awardID int, 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/ee/api/award_emoji.html#delete-an-award-emoji
func (s *AwardEmojiService) DeleteMergeRequestAwardEmoji(pid interface{}, mergeRequestIID, awardID int, 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/ee/api/award_emoji.html#delete-an-award-emoji
func (s *AwardEmojiService) DeleteSnippetAwardEmoji(pid interface{}, snippetID, awardID int, options ...RequestOptionFunc) (*Response, error) {
return s.deleteAwardEmoji(pid, awardSnippets, snippetID, awardID, options...)
}
// DeleteAwardEmoji Delete an award emoji on the specified resource.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#delete-an-award-emoji
func (s *AwardEmojiService) deleteAwardEmoji(pid interface{}, 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)
}
// ListIssuesAwardEmojiOnNote gets a list of all award emoji on a note from the
// issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#list-a-comments-award-emojis
func (s *AwardEmojiService) ListIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID int, 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/ee/api/award_emoji.html#list-a-comments-award-emojis
func (s *AwardEmojiService) ListMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID int, 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/ee/api/award_emoji.html#list-a-comments-award-emojis
func (s *AwardEmojiService) ListSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID int, opt *ListAwardEmojiOptions, options ...RequestOptionFunc) ([]*AwardEmoji, *Response, error) {
return s.listAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, opt, options...)
}
func (s *AwardEmojiService) listAwardEmojiOnNote(pid interface{}, resources string, ressourceID, 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,
ressourceID, 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
}
// GetIssuesAwardEmojiOnNote gets an award emoji on a note from an issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#get-an-award-emoji-for-a-comment
func (s *AwardEmojiService) GetIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID, awardID int, 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/ee/api/award_emoji.html#get-an-award-emoji-for-a-comment
func (s *AwardEmojiService) GetMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID, awardID int, 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/ee/api/award_emoji.html#get-an-award-emoji-for-a-comment
func (s *AwardEmojiService) GetSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) {
return s.getSingleNoteAwardEmoji(pid, awardSnippets, snippetIID, noteID, awardID, options...)
}
func (s *AwardEmojiService) getSingleNoteAwardEmoji(pid interface{}, ressource 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),
ressource,
resourceID,
noteID,
awardID,
)
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/ee/api/award_emoji.html#award-a-new-emoji-on-a-comment
func (s *AwardEmojiService) CreateIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID int, 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/ee/api/award_emoji.html#award-a-new-emoji-on-a-comment
func (s *AwardEmojiService) CreateMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID int, 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/ee/api/award_emoji.html#award-a-new-emoji-on-a-comment
func (s *AwardEmojiService) CreateSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID int, opt *CreateAwardEmojiOptions, options ...RequestOptionFunc) (*AwardEmoji, *Response, error) {
return s.createAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, opt, options...)
}
// CreateAwardEmojiOnNote award emoji on a note.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/award_emoji.html#award-a-new-emoji-on-a-comment
func (s *AwardEmojiService) createAwardEmojiOnNote(pid interface{}, 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,
)
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/ee/api/award_emoji.html#delete-an-award-emoji-from-a-comment
func (s *AwardEmojiService) DeleteIssuesAwardEmojiOnNote(pid interface{}, issueID, noteID, awardID int, 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/ee/api/award_emoji.html#delete-an-award-emoji-from-a-comment
func (s *AwardEmojiService) DeleteMergeRequestAwardEmojiOnNote(pid interface{}, mergeRequestIID, noteID, awardID int, 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/ee/api/award_emoji.html#delete-an-award-emoji-from-a-comment
func (s *AwardEmojiService) DeleteSnippetAwardEmojiOnNote(pid interface{}, snippetIID, noteID, awardID int, options ...RequestOptionFunc) (*Response, error) {
return s.deleteAwardEmojiOnNote(pid, awardSnippets, snippetIID, noteID, awardID, options...)
}
func (s *AwardEmojiService) deleteAwardEmojiOnNote(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// IssueBoardsService handles communication with the issue board related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html
type IssueBoardsService struct {
client *Client
}
// IssueBoard represents a GitLab issue board.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html
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"`
}
func (b IssueBoard) String() string {
return Stringify(b)
}
// BoardList represents a GitLab board list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html
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"`
}
func (b BoardList) String() string {
return Stringify(b)
}
// CreateIssueBoardOptions represents the available CreateIssueBoard() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#create-an-issue-board
type CreateIssueBoardOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// CreateIssueBoard creates a new issue board.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#create-an-issue-board
func (s *IssueBoardsService) CreateIssueBoard(pid interface{}, 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
}
// UpdateIssueBoardOptions represents the available UpdateIssueBoard() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#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"`
}
// UpdateIssueBoard update an issue board.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#update-an-issue-board
func (s *IssueBoardsService) UpdateIssueBoard(pid interface{}, 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
}
// DeleteIssueBoard deletes an issue board.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#delete-an-issue-board
func (s *IssueBoardsService) DeleteIssueBoard(pid interface{}, 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)
}
// ListIssueBoardsOptions represents the available ListIssueBoards() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#list-project-issue-boards
type ListIssueBoardsOptions ListOptions
// ListIssueBoards gets a list of all issue boards in a project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#list-project-issue-boards
func (s *IssueBoardsService) ListIssueBoards(pid interface{}, 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
}
// GetIssueBoard gets a single issue board of a project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#show-a-single-issue-board
func (s *IssueBoardsService) GetIssueBoard(pid interface{}, 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
}
// GetIssueBoardListsOptions represents the available GetIssueBoardLists() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#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/ee/api/boards.html#list-board-lists-in-a-project-issue-board
func (s *IssueBoardsService) GetIssueBoardLists(pid interface{}, 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
}
// GetIssueBoardList gets a single issue board list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#show-a-single-board-list
func (s *IssueBoardsService) GetIssueBoardList(pid interface{}, 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,
)
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
}
// CreateIssueBoardListOptions represents the available CreateIssueBoardList()
// options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#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"`
}
// CreateIssueBoardList creates a new issue board list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#create-a-board-list
func (s *IssueBoardsService) CreateIssueBoardList(pid interface{}, 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
}
// UpdateIssueBoardListOptions represents the available UpdateIssueBoardList()
// options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#reorder-a-list-in-a-board
type UpdateIssueBoardListOptions struct {
Position *int `url:"position" json:"position"`
}
// UpdateIssueBoardList updates the position of an existing issue board list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/boards.html#reorder-a-list-in-a-board
func (s *IssueBoardsService) UpdateIssueBoardList(pid interface{}, 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,
)
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/ee/api/boards.html#delete-a-board-list-from-a-board
func (s *IssueBoardsService) DeleteIssueBoardList(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// BranchesService handles communication with the branch related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/branches.html
type BranchesService struct {
client *Client
}
// Branch represents a GitLab branch.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/branches.html
type Branch struct {
Commit *Commit `json:"commit"`
Name string `json:"name"`
Protected bool `json:"protected"`
Merged bool `json:"merged"`
Default bool `json:"default"`
CanPush bool `json:"can_push"`
DevelopersCanPush bool `json:"developers_can_push"`
DevelopersCanMerge bool `json:"developers_can_merge"`
WebURL string `json:"web_url"`
}
func (b Branch) String() string {
return Stringify(b)
}
// ListBranchesOptions represents the available ListBranches() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#list-repository-branches
type ListBranchesOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
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/ee/api/branches.html#list-repository-branches
func (s *BranchesService) ListBranches(pid interface{}, 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
}
// GetBranch gets a single project repository branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#get-single-repository-branch
func (s *BranchesService) GetBranch(pid interface{}, 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
}
// ProtectBranchOptions represents the available ProtectBranch() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#protect-repository-branch
type ProtectBranchOptions struct {
DevelopersCanPush *bool `url:"developers_can_push,omitempty" json:"developers_can_push,omitempty"`
DevelopersCanMerge *bool `url:"developers_can_merge,omitempty" json:"developers_can_merge,omitempty"`
}
// ProtectBranch protects a single project repository branch. This is an
// idempotent function, protecting an already protected repository branch
// still returns a 200 OK status code.
//
// Deprecated: This endpoint has been replaced by
// ProtectedBranchesService.ProtectRepositoryBranches()
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#protect-repository-branch
func (s *BranchesService) ProtectBranch(pid interface{}, branch string, opts *ProtectBranchOptions, options ...RequestOptionFunc) (*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches/%s/protect", PathEscape(project), url.PathEscape(branch))
req, err := s.client.NewRequest(http.MethodPut, u, opts, 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
}
// UnprotectBranch unprotects a single project repository branch. This is an
// idempotent function, unprotecting an already unprotected repository branch
// still returns a 200 OK status code.
//
// Deprecated: This endpoint has been replaced by
// ProtectedBranchesService.UnprotectRepositoryBranches()
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#unprotect-repository-branch
func (s *BranchesService) UnprotectBranch(pid interface{}, 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/unprotect", PathEscape(project), url.PathEscape(branch))
req, err := s.client.NewRequest(http.MethodPut, 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
}
// CreateBranchOptions represents the available CreateBranch() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#create-repository-branch
type CreateBranchOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// CreateBranch creates branch from commit SHA or existing branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#create-repository-branch
func (s *BranchesService) CreateBranch(pid interface{}, 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
}
// DeleteBranch deletes an existing branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#delete-repository-branch
func (s *BranchesService) DeleteBranch(pid interface{}, 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)
}
// DeleteMergedBranches deletes all branches that are merged into the project's default branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/branches.html#delete-merged-branches
func (s *BranchesService) DeleteMergedBranches(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// BroadcastMessagesService handles communication with the broadcast
// messages methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/broadcast_messages.html
type BroadcastMessagesService struct {
client *Client
}
// BroadcastMessage represents a GitLab issue board.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#get-all-broadcast-messages
type BroadcastMessage struct {
Message string `json:"message"`
StartsAt *time.Time `json:"starts_at"`
EndsAt *time.Time `json:"ends_at"`
Font string `json:"font"`
ID int `json:"id"`
Active bool `json:"active"`
TargetAccessLevels []AccessLevelValue `json:"target_access_levels"`
TargetPath string `json:"target_path"`
BroadcastType string `json:"broadcast_type"`
Dismissable bool `json:"dismissable"`
// Deprecated: This parameter was removed in GitLab 15.6.
Color string `json:"color"`
}
// ListBroadcastMessagesOptions represents the available ListBroadcastMessages()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#get-all-broadcast-messages
type ListBroadcastMessagesOptions ListOptions
// ListBroadcastMessages gets a list of all broadcasted messages.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#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
}
// GetBroadcastMessage gets a single broadcast message.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#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
}
// CreateBroadcastMessageOptions represents the available CreateBroadcastMessage()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#create-a-broadcast-message
type CreateBroadcastMessageOptions struct {
Message *string `url:"message" json:"message"`
StartsAt *time.Time `url:"starts_at,omitempty" json:"starts_at,omitempty"`
EndsAt *time.Time `url:"ends_at,omitempty" json:"ends_at,omitempty"`
Font *string `url:"font,omitempty" json:"font,omitempty"`
TargetAccessLevels []AccessLevelValue `url:"target_access_levels,omitempty" json:"target_access_levels,omitempty"`
TargetPath *string `url:"target_path,omitempty" json:"target_path,omitempty"`
BroadcastType *string `url:"broadcast_type,omitempty" json:"broadcast_type,omitempty"`
Dismissable *bool `url:"dismissable,omitempty" json:"dismissable,omitempty"`
// Deprecated: This parameter was removed in GitLab 15.6.
Color *string `url:"color,omitempty" json:"color,omitempty"`
}
// CreateBroadcastMessage creates a message to broadcast.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#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
}
// UpdateBroadcastMessageOptions represents the available CreateBroadcastMessage()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#update-a-broadcast-message
type UpdateBroadcastMessageOptions struct {
Message *string `url:"message,omitempty" json:"message,omitempty"`
StartsAt *time.Time `url:"starts_at,omitempty" json:"starts_at,omitempty"`
EndsAt *time.Time `url:"ends_at,omitempty" json:"ends_at,omitempty"`
Font *string `url:"font,omitempty" json:"font,omitempty"`
TargetAccessLevels []AccessLevelValue `url:"target_access_levels,omitempty" json:"target_access_levels,omitempty"`
TargetPath *string `url:"target_path,omitempty" json:"target_path,omitempty"`
BroadcastType *string `url:"broadcast_type,omitempty" json:"broadcast_type,omitempty"`
Dismissable *bool `url:"dismissable,omitempty" json:"dismissable,omitempty"`
// Deprecated: This parameter was removed in GitLab 15.6.
Color *string `url:"color,omitempty" json:"color,omitempty"`
}
// UpdateBroadcastMessage update a broadcasted message.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#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
}
// DeleteBroadcastMessage deletes a broadcasted message.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/broadcast_messages.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// CIYMLTemplatesService handles communication with the gitlab
// CI YML templates related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html
type CIYMLTemplatesService struct {
client *Client
}
// CIYMLTemplate represents a GitLab CI YML template.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html
type CIYMLTemplate struct {
Name string `json:"name"`
Content string `json:"content"`
}
// CIYMLTemplateListItem represents a GitLab CI YML template from the list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html
type CIYMLTemplateListItem struct {
Key string `json:"key"`
Name string `json:"name"`
}
// ListCIYMLTemplatesOptions represents the available ListAllTemplates() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html#list-gitlab-ci-yaml-templates
type ListCIYMLTemplatesOptions ListOptions
// ListAllTemplates get all GitLab CI YML templates.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html#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
}
// GetTemplate get a single GitLab CI YML template.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitlab_ci_ymls.html#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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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"
"time"
retryablehttp "github.com/hashicorp/go-retryablehttp"
)
// ClientOptionFunc can be used to customize a new GitLab API client.
type ClientOptionFunc func(*Client) error
// WithBaseURL sets the base URL for API requests to a custom endpoint.
func WithBaseURL(urlStr string) ClientOptionFunc {
return func(c *Client) error {
return c.setBaseURL(urlStr)
}
}
// WithCustomBackoff can be used to configure a custom backoff policy.
func WithCustomBackoff(backoff retryablehttp.Backoff) ClientOptionFunc {
return func(c *Client) error {
c.client.Backoff = backoff
return nil
}
}
// WithCustomLeveledLogger can be used to configure a custom retryablehttp
// leveled logger.
func WithCustomLeveledLogger(leveledLogger retryablehttp.LeveledLogger) ClientOptionFunc {
return func(c *Client) error {
c.client.Logger = leveledLogger
return nil
}
}
// WithCustomLimiter injects a custom rate limiter to the client.
func WithCustomLimiter(limiter RateLimiter) ClientOptionFunc {
return func(c *Client) error {
c.configureLimiterOnce.Do(func() {})
c.limiter = limiter
return nil
}
}
// WithCustomLogger can be used to configure a custom retryablehttp logger.
func WithCustomLogger(logger retryablehttp.Logger) ClientOptionFunc {
return func(c *Client) error {
c.client.Logger = logger
return nil
}
}
// WithCustomRetry can be used to configure a custom retry policy.
func WithCustomRetry(checkRetry retryablehttp.CheckRetry) ClientOptionFunc {
return func(c *Client) error {
c.client.CheckRetry = checkRetry
return nil
}
}
// WithCustomRetryMax can be used to configure a custom maximum number of retries.
func WithCustomRetryMax(retryMax int) ClientOptionFunc {
return func(c *Client) error {
c.client.RetryMax = retryMax
return nil
}
}
// WithCustomRetryWaitMinMax can be used to configure a custom minimum and
// maximum time to wait between retries.
func WithCustomRetryWaitMinMax(waitMin, waitMax time.Duration) ClientOptionFunc {
return func(c *Client) error {
c.client.RetryWaitMin = waitMin
c.client.RetryWaitMax = waitMax
return nil
}
}
// WithErrorHandler can be used to configure a custom error handler.
func WithErrorHandler(handler retryablehttp.ErrorHandler) ClientOptionFunc {
return func(c *Client) error {
c.client.ErrorHandler = handler
return nil
}
}
// WithHTTPClient can be used to configure a custom HTTP client.
func WithHTTPClient(httpClient *http.Client) ClientOptionFunc {
return func(c *Client) error {
c.client.HTTPClient = httpClient
return nil
}
}
// WithRequestLogHook can be used to configure a custom request log hook.
func WithRequestLogHook(hook retryablehttp.RequestLogHook) ClientOptionFunc {
return func(c *Client) error {
c.client.RequestLogHook = hook
return nil
}
}
// WithResponseLogHook can be used to configure a custom response log hook.
func WithResponseLogHook(hook retryablehttp.ResponseLogHook) ClientOptionFunc {
return func(c *Client) error {
c.client.ResponseLogHook = hook
return nil
}
}
// WithoutRetries disables the default retry logic.
func WithoutRetries() ClientOptionFunc {
return func(c *Client) error {
c.disableRetries = true
return nil
}
}
// WithRequestOptions can be used to configure default request options applied to every request.
func WithRequestOptions(options ...RequestOptionFunc) ClientOptionFunc {
return func(c *Client) error {
c.defaultRequestOptions = append(c.defaultRequestOptions, options...)
return nil
}
}
//
// Copyright 2022, Timo Furrer <tuxtimo@gmail.com>
//
// 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 (
"fmt"
"net/http"
"time"
)
// ClusterAgentsService handles communication with the cluster agents related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/cluster_agents.html
type ClusterAgentsService struct {
client *Client
}
// Agent represents a GitLab agent for Kubernetes.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/cluster_agents.html
type Agent struct {
ID int `json:"id"`
Name string `json:"name"`
CreatedAt *time.Time `json:"created_at"`
CreatedByUserID int `json:"created_by_user_id"`
ConfigProject ConfigProject `json:"config_project"`
}
type ConfigProject 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"`
}
func (a Agent) String() string {
return Stringify(a)
}
// AgentToken represents a GitLab agent token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#list-tokens-for-an-agent
type AgentToken struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
AgentID int `json:"agent_id"`
Status string `json:"status"`
CreatedAt *time.Time `json:"created_at"`
CreatedByUserID int `json:"created_by_user_id"`
LastUsedAt *time.Time `json:"last_used_at"`
Token string `json:"token"`
}
func (a AgentToken) String() string {
return Stringify(a)
}
// ListAgentsOptions represents the available ListAgents() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#list-the-agents-for-a-project
type ListAgentsOptions ListOptions
// ListAgents returns a list of agents registered for the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#list-the-agents-for-a-project
func (s *ClusterAgentsService) ListAgents(pid interface{}, 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
}
// GetAgent gets a single agent details.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#get-details-about-an-agent
func (s *ClusterAgentsService) GetAgent(pid interface{}, 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
}
// RegisterAgentOptions represents the available RegisterAgent()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#register-an-agent-with-a-project
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/ee/api/cluster_agents.html#register-an-agent-with-a-project
func (s *ClusterAgentsService) RegisterAgent(pid interface{}, 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
}
// DeleteAgent deletes an existing agent registration.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#delete-a-registered-agent
func (s *ClusterAgentsService) DeleteAgent(pid interface{}, 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)
}
// ListAgentTokensOptions represents the available ListAgentTokens() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#list-tokens-for-an-agent
type ListAgentTokensOptions ListOptions
// ListAgentTokens returns a list of tokens for an agent.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#list-tokens-for-an-agent
func (s *ClusterAgentsService) ListAgentTokens(pid interface{}, 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
}
// GetAgentToken gets a single agent token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#get-a-single-agent-token
func (s *ClusterAgentsService) GetAgentToken(pid interface{}, 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
}
return at, resp, nil
}
// CreateAgentTokenOptions represents the available CreateAgentToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#create-an-agent-token
type CreateAgentTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
}
// CreateAgentToken creates a new token for an agent.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#create-an-agent-token
func (s *ClusterAgentsService) CreateAgentToken(pid interface{}, 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
}
// RevokeAgentToken revokes an agent token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/cluster_agents.html#revoke-an-agent-token
func (s *ClusterAgentsService) RevokeAgentToken(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"net/url"
"time"
)
// CommitsService handles communication with the commit related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html
type CommitsService struct {
client *Client
}
// Commit represents a GitLab commit.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html
type Commit struct {
ID string `json:"id"`
ShortID string `json:"short_id"`
Title string `json:"title"`
AuthorName string `json:"author_name"`
AuthorEmail string `json:"author_email"`
AuthoredDate *time.Time `json:"authored_date"`
CommitterName string `json:"committer_name"`
CommitterEmail string `json:"committer_email"`
CommittedDate *time.Time `json:"committed_date"`
CreatedAt *time.Time `json:"created_at"`
Message string `json:"message"`
ParentIDs []string `json:"parent_ids"`
Stats *CommitStats `json:"stats"`
Status *BuildStateValue `json:"status"`
LastPipeline *PipelineInfo `json:"last_pipeline"`
ProjectID int `json:"project_id"`
Trailers map[string]string `json:"trailers"`
ExtendedTrailers map[string]string `json:"extended_trailers"`
WebURL string `json:"web_url"`
}
// CommitStats represents the number of added and deleted files in a commit.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html
type CommitStats struct {
Additions int `json:"additions"`
Deletions int `json:"deletions"`
Total int `json:"total"`
}
func (c Commit) String() string {
return Stringify(c)
}
// ListCommitsOptions represents the available ListCommits() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#list-repository-commits
type ListCommitsOptions struct {
ListOptions
RefName *string `url:"ref_name,omitempty" json:"ref_name,omitempty"`
Since *time.Time `url:"since,omitempty" json:"since,omitempty"`
Until *time.Time `url:"until,omitempty" json:"until,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
Author *string `url:"author,omitempty" json:"author,omitempty"`
All *bool `url:"all,omitempty" json:"all,omitempty"`
WithStats *bool `url:"with_stats,omitempty" json:"with_stats,omitempty"`
FirstParent *bool `url:"first_parent,omitempty" json:"first_parent,omitempty"`
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/ee/api/commits.html#list-repository-commits
func (s *CommitsService) ListCommits(pid interface{}, 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
}
// CommitRef represents the reference of branches/tags in a commit.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-references-a-commit-is-pushed-to
type CommitRef struct {
Type string `json:"type"`
Name string `json:"name"`
}
// GetCommitRefsOptions represents the available GetCommitRefs() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-references-a-commit-is-pushed-to
type GetCommitRefsOptions struct {
ListOptions
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/ee/api/commits.html#get-references-a-commit-is-pushed-to
func (s *CommitsService) GetCommitRefs(pid interface{}, 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
}
// GetCommitOptions represents the available GetCommit() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-a-single-commit
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/ee/api/commits.html#get-a-single-commit
func (s *CommitsService) GetCommit(pid interface{}, 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")
}
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
}
// CreateCommitOptions represents the available options for a new commit.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions
type CreateCommitOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"`
StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"`
StartSHA *string `url:"start_sha,omitempty" json:"start_sha,omitempty"`
StartProject *string `url:"start_project,omitempty" json:"start_project,omitempty"`
Actions []*CommitActionOptions `url:"actions" json:"actions"`
AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"`
AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"`
Stats *bool `url:"stats,omitempty" json:"stats,omitempty"`
Force *bool `url:"force,omitempty" json:"force,omitempty"`
}
// CommitActionOptions represents the available options for a new single
// file action.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions
type CommitActionOptions struct {
Action *FileActionValue `url:"action,omitempty" json:"action,omitempty"`
FilePath *string `url:"file_path,omitempty" json:"file_path,omitempty"`
PreviousPath *string `url:"previous_path,omitempty" json:"previous_path,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
Encoding *string `url:"encoding,omitempty" json:"encoding,omitempty"`
LastCommitID *string `url:"last_commit_id,omitempty" json:"last_commit_id,omitempty"`
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/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions
func (s *CommitsService) CreateCommit(pid interface{}, 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
}
// Diff represents a GitLab diff.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html
type Diff struct {
Diff string `json:"diff"`
NewPath string `json:"new_path"`
OldPath string `json:"old_path"`
AMode string `json:"a_mode"`
BMode string `json:"b_mode"`
NewFile bool `json:"new_file"`
RenamedFile bool `json:"renamed_file"`
DeletedFile bool `json:"deleted_file"`
}
func (d Diff) String() string {
return Stringify(d)
}
// GetCommitDiffOptions represents the available GetCommitDiff() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-the-diff-of-a-commit
type GetCommitDiffOptions struct {
ListOptions
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/ee/api/commits.html#get-the-diff-of-a-commit
func (s *CommitsService) GetCommitDiff(pid interface{}, 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
}
// CommitComment represents a GitLab commit comment.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html
type CommitComment struct {
Note string `json:"note"`
Path string `json:"path"`
Line int `json:"line"`
LineType string `json:"line_type"`
Author Author `json:"author"`
}
// Author represents a GitLab commit author
type Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
Blocked bool `json:"blocked"`
CreatedAt *time.Time `json:"created_at"`
}
func (c CommitComment) String() string {
return Stringify(c)
}
// GetCommitCommentsOptions represents the available GetCommitComments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-the-comments-of-a-commit
type GetCommitCommentsOptions ListOptions
// GetCommitComments gets the comments of a commit in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-the-comments-of-a-commit
func (s *CommitsService) GetCommitComments(pid interface{}, 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
}
// PostCommitCommentOptions represents the available PostCommitComment()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#post-comment-to-commit
type PostCommitCommentOptions struct {
Note *string `url:"note,omitempty" json:"note,omitempty"`
Path *string `url:"path" json:"path"`
Line *int `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/ee/api/commits.html#post-comment-to-commit
func (s *CommitsService) PostCommitComment(pid interface{}, 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
}
// GetCommitStatusesOptions represents the available GetCommitStatuses() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#list-the-statuses-of-a-commit
type GetCommitStatusesOptions struct {
ListOptions
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
Stage *string `url:"stage,omitempty" json:"stage,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
All *bool `url:"all,omitempty" json:"all,omitempty"`
}
// CommitStatus represents a GitLab commit status.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#commit-status
type CommitStatus struct {
ID int `json:"id"`
SHA string `json:"sha"`
Ref string `json:"ref"`
Status string `json:"status"`
CreatedAt *time.Time `json:"created_at"`
StartedAt *time.Time `json:"started_at"`
FinishedAt *time.Time `json:"finished_at"`
Name string `json:"name"`
AllowFailure bool `json:"allow_failure"`
Coverage float64 `json:"coverage"`
PipelineId int `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/ee/api/commits.html#list-the-statuses-of-a-commit
func (s *CommitsService) GetCommitStatuses(pid interface{}, 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
}
// SetCommitStatusOptions represents the available SetCommitStatus() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#set-the-pipeline-status-of-a-commit
type SetCommitStatusOptions struct {
State BuildStateValue `url:"state" json:"state"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
Context *string `url:"context,omitempty" json:"context,omitempty"`
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"`
}
// SetCommitStatus sets the status of a commit in a project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#set-the-pipeline-status-of-a-commit
func (s *CommitsService) SetCommitStatus(pid interface{}, 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
}
// ListMergeRequestsByCommit gets merge request associated with a commit.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#list-merge-requests-associated-with-a-commit
func (s *CommitsService) ListMergeRequestsByCommit(pid interface{}, sha string, options ...RequestOptionFunc) ([]*MergeRequest, *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 []*MergeRequest
resp, err := s.client.Do(req, &mrs)
if err != nil {
return nil, resp, err
}
return mrs, resp, nil
}
// CherryPickCommitOptions represents the available CherryPickCommit() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#cherry-pick-a-commit
type CherryPickCommitOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
DryRun *bool `url:"dry_run,omitempty" json:"dry_run,omitempty"`
Message *string `url:"message,omitempty" json:"message,omitempty"`
}
// CherryPickCommit cherry picks a commit to a given branch.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#cherry-pick-a-commit
func (s *CommitsService) CherryPickCommit(pid interface{}, 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/ee/api/commits.html#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/ee/api/commits.html#revert-a-commit
func (s *CommitsService) RevertCommit(pid interface{}, 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
}
return c, resp, nil
}
// GPGSignature represents a Gitlab commit's GPG Signature.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#get-gpg-signature-of-a-commit
type GPGSignature struct {
KeyID int `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"`
}
// GetGPGSignature gets a GPG signature of a commit.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/commits.html#get-gpg-signature-of-a-commit
func (s *CommitsService) GetGPGSignature(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ContainerRegistryService handles communication with the container registry
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html
type ContainerRegistryService struct {
client *Client
}
// RegistryRepository represents a GitLab content registry repository.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html
type RegistryRepository struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
ProjectID int `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"`
Tags []*RegistryRepositoryTag `json:"tags"`
}
func (s RegistryRepository) String() string {
return Stringify(s)
}
// RegistryRepositoryTag represents a GitLab registry image tag.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/container_registry.html
type RegistryRepositoryTag struct {
Name string `json:"name"`
Path string `json:"path"`
Location string `json:"location"`
Revision string `json:"revision"`
ShortRevision string `json:"short_revision"`
Digest string `json:"digest"`
CreatedAt *time.Time `json:"created_at"`
TotalSize int `json:"total_size"`
}
func (s RegistryRepositoryTag) String() string {
return Stringify(s)
}
// ListRegistryRepositoriesOptions represents the available
// ListRegistryRepositories() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repositories
type ListRegistryRepositoriesOptions 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/ee/api/container_registry.html#within-a-project
func (s *ContainerRegistryService) ListProjectRegistryRepositories(pid interface{}, 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.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#within-a-group
func (s *ContainerRegistryService) ListGroupRegistryRepositories(gid interface{}, 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
}
var repos []*RegistryRepository
resp, err := s.client.Do(req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// GetSingleRegistryRepositoryOptions represents the available
// GetSingleRegistryRepository() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#get-details-of-a-single-repository
type GetSingleRegistryRepositoryOptions struct {
Tags *bool `url:"tags,omitempty" json:"tags,omitempty"`
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/ee/api/container_registry.html#get-details-of-a-single-repository
func (s *ContainerRegistryService) GetSingleRegistryRepository(pid interface{}, 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
}
// DeleteRegistryRepository deletes a repository in a registry.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository
func (s *ContainerRegistryService) DeleteRegistryRepository(pid interface{}, 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)
}
// ListRegistryRepositoryTagsOptions represents the available
// ListRegistryRepositoryTags() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repository-tags
type ListRegistryRepositoryTagsOptions ListOptions
// ListRegistryRepositoryTags gets a list of tags for given registry repository.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repository-tags
func (s *ContainerRegistryService) ListRegistryRepositoryTags(pid interface{}, 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,
)
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/ee/api/container_registry.html#get-details-of-a-registry-repository-tag
func (s *ContainerRegistryService) GetRegistryRepositoryTagDetail(pid interface{}, 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,
)
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/ee/api/container_registry.html#delete-a-registry-repository-tag
func (s *ContainerRegistryService) DeleteRegistryRepositoryTag(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteRegistryRepositoryTagsOptions represents the available
// DeleteRegistryRepositoryTags() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#delete-registry-repository-tags-in-bulk
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"`
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/ee/api/container_registry.html#delete-registry-repository-tags-in-bulk
func (s *ContainerRegistryService) DeleteRegistryRepositoryTags(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// CustomAttributesService handles communication with the group, project and
// user custom attributes related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/custom_attributes.html
type CustomAttributesService struct {
client *Client
}
// CustomAttribute struct is used to unmarshal response to api calls.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/custom_attributes.html
type CustomAttribute struct {
Key string `json:"key"`
Value string `json:"value"`
}
// ListCustomUserAttributes lists the custom attributes of the specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#list-custom-attributes
func (s *CustomAttributesService) ListCustomUserAttributes(user int, 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/ee/api/custom_attributes.html#list-custom-attributes
func (s *CustomAttributesService) ListCustomGroupAttributes(group int, 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/ee/api/custom_attributes.html#list-custom-attributes
func (s *CustomAttributesService) ListCustomProjectAttributes(project int, 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)
if err != nil {
return nil, resp, err
}
return cas, resp, nil
}
// GetCustomUserAttribute returns the user attribute with a speciifc key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#single-custom-attribute
func (s *CustomAttributesService) GetCustomUserAttribute(user int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) {
return s.getCustomAttribute("users", user, key, options...)
}
// GetCustomGroupAttribute returns the group attribute with a speciifc key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#single-custom-attribute
func (s *CustomAttributesService) GetCustomGroupAttribute(group int, key string, options ...RequestOptionFunc) (*CustomAttribute, *Response, error) {
return s.getCustomAttribute("groups", group, key, options...)
}
// GetCustomProjectAttribute returns the project attribute with a speciifc key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#single-custom-attribute
func (s *CustomAttributesService) GetCustomProjectAttribute(project int, 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)
if err != nil {
return nil, resp, err
}
return ca, resp, nil
}
// SetCustomUserAttribute sets the custom attributes of the specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#set-custom-attribute
func (s *CustomAttributesService) SetCustomUserAttribute(user int, 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/ee/api/custom_attributes.html#set-custom-attribute
func (s *CustomAttributesService) SetCustomGroupAttribute(group int, 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/ee/api/custom_attributes.html#set-custom-attribute
func (s *CustomAttributesService) SetCustomProjectAttribute(project int, 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)
if err != nil {
return nil, resp, err
}
return ca, resp, nil
}
// DeleteCustomUserAttribute removes the custom attribute of the specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/custom_attributes.html#delete-custom-attribute
func (s *CustomAttributesService) DeleteCustomUserAttribute(user int, 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/ee/api/custom_attributes.html#delete-custom-attribute
func (s *CustomAttributesService) DeleteCustomGroupAttribute(group int, 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/ee/api/custom_attributes.html#delete-custom-attribute
func (s *CustomAttributesService) DeleteCustomProjectAttribute(project int, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// DeployKeysService handles communication with the keys related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/deploy_keys.html
type DeployKeysService struct {
client *Client
}
// InstanceDeployKey represents a GitLab deploy key with the associated
// projects it has write access to.
type InstanceDeployKey struct {
ID int `json:"id"`
Title string `json:"title"`
CreatedAt *time.Time `json:"created_at"`
Key string `json:"key"`
Fingerprint string `json:"fingerprint"`
ProjectsWithWriteAccess []*DeployKeyProject `json:"projects_with_write_access"`
}
func (k InstanceDeployKey) String() string {
return Stringify(k)
}
// DeployKeyProject refers to a project an InstanceDeployKey has write access to.
type DeployKeyProject 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"`
}
func (k DeployKeyProject) String() string {
return Stringify(k)
}
// ProjectDeployKey represents a GitLab project deploy key.
type ProjectDeployKey struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt *time.Time `json:"created_at"`
CanPush bool `json:"can_push"`
}
func (k ProjectDeployKey) String() string {
return Stringify(k)
}
// ListProjectDeployKeysOptions represents the available ListAllDeployKeys()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#list-all-deploy-keys
type ListInstanceDeployKeysOptions struct {
ListOptions
Public *bool `url:"public,omitempty" json:"public,omitempty"`
}
// ListAllDeployKeys gets a list of all deploy keys
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#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
}
// ListProjectDeployKeysOptions represents the available ListProjectDeployKeys()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#list-deploy-keys-for-project
type ListProjectDeployKeysOptions ListOptions
// ListProjectDeployKeys gets a list of a project's deploy keys
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#list-deploy-keys-for-project
func (s *DeployKeysService) ListProjectDeployKeys(pid interface{}, 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
}
// GetDeployKey gets a single deploy key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#get-a-single-deploy-key
func (s *DeployKeysService) GetDeployKey(pid interface{}, 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
}
// AddDeployKeyOptions represents the available ADDDeployKey() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key
type AddDeployKeyOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Key *string `url:"key,omitempty" json:"key,omitempty"`
CanPush *bool `url:"can_push,omitempty" json:"can_push,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 was is accessible by same user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key
func (s *DeployKeysService) AddDeployKey(pid interface{}, 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
}
// DeleteDeployKey deletes a deploy key from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#delete-deploy-key
func (s *DeployKeysService) DeleteDeployKey(pid interface{}, 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)
}
// EnableDeployKey enables a deploy key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#enable-a-deploy-key
func (s *DeployKeysService) EnableDeployKey(pid interface{}, 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
}
// UpdateDeployKeyOptions represents the available UpdateDeployKey() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_keys.html#update-deploy-key
type UpdateDeployKeyOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
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/ee/api/deploy_keys.html#update-deploy-key
func (s *DeployKeysService) UpdateDeployKey(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// DeployTokensService handles communication with the deploy tokens related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/deploy_tokens.html
type DeployTokensService struct {
client *Client
}
// DeployToken represents a GitLab deploy token.
type DeployToken struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
ExpiresAt *time.Time `json:"expires_at"`
Revoked bool `json:"revoked"`
Expired bool `json:"expired"`
Token string `json:"token,omitempty"`
Scopes []string `json:"scopes"`
}
func (k DeployToken) String() string {
return Stringify(k)
}
// ListAllDeployTokens gets a list of all deploy tokens.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#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
}
// ListProjectDeployTokensOptions represents the available ListProjectDeployTokens()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#list-project-deploy-tokens
type ListProjectDeployTokensOptions ListOptions
// ListProjectDeployTokens gets a list of a project's deploy tokens.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#list-project-deploy-tokens
func (s *DeployTokensService) ListProjectDeployTokens(pid interface{}, 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
}
// GetProjectDeployToken gets a single deploy token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#get-a-project-deploy-token
func (s *DeployTokensService) GetProjectDeployToken(pid interface{}, 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
}
// CreateProjectDeployTokenOptions represents the available CreateProjectDeployToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#create-a-project-deploy-token
type CreateProjectDeployTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
}
// CreateProjectDeployToken creates a new deploy token for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#create-a-project-deploy-token
func (s *DeployTokensService) CreateProjectDeployToken(pid interface{}, 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
}
// DeleteProjectDeployToken removes a deploy token from the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#delete-a-project-deploy-token
func (s *DeployTokensService) DeleteProjectDeployToken(pid interface{}, 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)
}
// ListGroupDeployTokensOptions represents the available ListGroupDeployTokens()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#list-group-deploy-tokens
type ListGroupDeployTokensOptions ListOptions
// ListGroupDeployTokens gets a list of a group’s deploy tokens.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#list-group-deploy-tokens
func (s *DeployTokensService) ListGroupDeployTokens(gid interface{}, 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
}
// GetGroupDeployToken gets a single deploy token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#get-a-group-deploy-token
func (s *DeployTokensService) GetGroupDeployToken(gid interface{}, 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
}
// CreateGroupDeployTokenOptions represents the available CreateGroupDeployToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#create-a-group-deploy-token
type CreateGroupDeployTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
}
// CreateGroupDeployToken creates a new deploy token for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#create-a-group-deploy-token
func (s *DeployTokensService) CreateGroupDeployToken(gid interface{}, 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
}
// DeleteGroupDeployToken removes a deploy token from the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deploy_tokens.html#delete-a-group-deploy-token
func (s *DeployTokensService) DeleteGroupDeployToken(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// DeploymentsService handles communication with the deployment related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/deployments.html
type DeploymentsService struct {
client *Client
}
// 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"`
}
// ListProjectDeploymentsOptions represents the available ListProjectDeployments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#list-project-deployments
type ListProjectDeploymentsOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Environment *string `url:"environment,omitempty" json:"environment,omitempty"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
// 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
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/ee/api/deployments.html#list-project-deployments
func (s *DeploymentsService) ListProjectDeployments(pid interface{}, 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
}
// GetProjectDeployment get a deployment for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#get-a-specific-deployment
func (s *DeploymentsService) GetProjectDeployment(pid interface{}, 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
}
// CreateProjectDeploymentOptions represents the available
// CreateProjectDeployment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#create-a-deployment
type CreateProjectDeploymentOptions struct {
Environment *string `url:"environment,omitempty" json:"environment,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
Tag *bool `url:"tag,omitempty" json:"tag,omitempty"`
Status *DeploymentStatusValue `url:"status,omitempty" json:"status,omitempty"`
}
// CreateProjectDeployment creates a project deployment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#create-a-deployment
func (s *DeploymentsService) CreateProjectDeployment(pid interface{}, 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
}
// UpdateProjectDeploymentOptions represents the available
// UpdateProjectDeployment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#update-a-deployment
type UpdateProjectDeploymentOptions struct {
Status *DeploymentStatusValue `url:"status,omitempty" json:"status,omitempty"`
}
// UpdateProjectDeployment updates a project deployment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#update-a-deployment
func (s *DeploymentsService) UpdateProjectDeployment(pid interface{}, 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
}
// ApproveOrRejectProjectDeploymentOptions represents the available
// ApproveOrRejectProjectDeployment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#approve-or-reject-a-blocked-deployment
type ApproveOrRejectProjectDeploymentOptions struct {
Status *DeploymentApprovalStatus `url:"status,omitempty" json:"status,omitempty"`
Comment *string `url:"comment,omitempty" json:"comment,omitempty"`
RepresentedAs *string `url:"represented_as,omitempty" json:"represented_as,omitempty"`
}
// ApproveOrRejectProjectDeployment approve or reject a blocked deployment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#approve-or-reject-a-blocked-deployment
func (s *DeploymentsService) ApproveOrRejectProjectDeployment(pid interface{}, 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)
}
// DeleteProjectDeployment delete a project deployment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#delete-a-specific-deployment
func (s *DeploymentsService) DeleteProjectDeployment(pid interface{}, 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)
}
// Copyright 2022, Daniela Filipe Bento
//
// 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 (
"fmt"
"net/http"
)
// DeploymentMergeRequestsService handles communication with the deployment's
// merge requests related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#list-of-merge-requests-associated-with-a-deployment
type DeploymentMergeRequestsService struct {
client *Client
}
// ListDeploymentMergeRequests get the merge requests associated with deployment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/deployments.html#list-of-merge-requests-associated-with-a-deployment
func (s *DeploymentMergeRequestsService) ListDeploymentMergeRequests(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// DiscussionsService handles communication with the discussions related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/discussions.html
type DiscussionsService struct {
client *Client
}
// Discussion represents a GitLab discussion.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/discussions.html
type Discussion struct {
ID string `json:"id"`
IndividualNote bool `json:"individual_note"`
Notes []*Note `json:"notes"`
}
func (d Discussion) String() string {
return Stringify(d)
}
// ListIssueDiscussionsOptions represents the available ListIssueDiscussions()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#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/ee/api/discussions.html#list-project-issue-discussion-items
func (s *DiscussionsService) ListIssueDiscussions(pid interface{}, 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
}
// GetIssueDiscussion returns a single discussion for a specific project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#get-single-issue-discussion-item
func (s *DiscussionsService) GetIssueDiscussion(pid interface{}, 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,
)
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
}
// CreateIssueDiscussionOptions represents the available CreateIssueDiscussion()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-issue-thread
type CreateIssueDiscussionOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#create-new-issue-thread
func (s *DiscussionsService) CreateIssueDiscussion(pid interface{}, 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
}
// AddIssueDiscussionNoteOptions represents the available AddIssueDiscussionNote()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#add-note-to-existing-issue-thread
type AddIssueDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#add-note-to-existing-issue-thread
func (s *DiscussionsService) AddIssueDiscussionNote(pid interface{}, 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,
)
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
// UpdateIssueDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-existing-issue-thread-note
type UpdateIssueDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#modify-existing-issue-thread-note
func (s *DiscussionsService) UpdateIssueDiscussionNote(pid interface{}, 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,
)
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/ee/api/discussions.html#delete-an-issue-thread-note
func (s *DiscussionsService) DeleteIssueDiscussionNote(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ListSnippetDiscussionsOptions represents the available ListSnippetDiscussions()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#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/ee/api/discussions.html#list-project-snippet-discussion-items
func (s *DiscussionsService) ListSnippetDiscussions(pid interface{}, 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
}
// GetSnippetDiscussion returns a single discussion for a given snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#get-single-snippet-discussion-item
func (s *DiscussionsService) GetSnippetDiscussion(pid interface{}, 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,
)
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
}
// CreateSnippetDiscussionOptions represents the available
// CreateSnippetDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-snippet-thread
type CreateSnippetDiscussionOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#create-new-snippet-thread
func (s *DiscussionsService) CreateSnippetDiscussion(pid interface{}, 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
}
// AddSnippetDiscussionNoteOptions represents the available
// AddSnippetDiscussionNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#add-note-to-existing-snippet-thread
type AddSnippetDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#add-note-to-existing-snippet-thread
func (s *DiscussionsService) AddSnippetDiscussionNote(pid interface{}, 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,
)
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
// UpdateSnippetDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-existing-snippet-thread-note
type UpdateSnippetDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#modify-existing-snippet-thread-note
func (s *DiscussionsService) UpdateSnippetDiscussionNote(pid interface{}, 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,
)
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/ee/api/discussions.html#delete-a-snippet-thread-note
func (s *DiscussionsService) DeleteSnippetDiscussionNote(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ListGroupEpicDiscussionsOptions represents the available
// ListEpicDiscussions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#list-group-epic-discussion-items
type ListGroupEpicDiscussionsOptions 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/ee/api/discussions.html#list-group-epic-discussion-items
func (s *DiscussionsService) ListGroupEpicDiscussions(gid interface{}, 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,
)
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/ee/api/discussions.html#get-single-epic-discussion-item
func (s *DiscussionsService) GetEpicDiscussion(gid interface{}, 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,
)
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()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-epic-thread
type CreateEpicDiscussionOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#create-new-epic-thread
func (s *DiscussionsService) CreateEpicDiscussion(gid interface{}, 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,
)
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
// AddEpicDiscussionNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#add-note-to-existing-epic-thread
type AddEpicDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#add-note-to-existing-epic-thread
func (s *DiscussionsService) AddEpicDiscussionNote(gid interface{}, 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,
)
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()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-existing-epic-thread-note
type UpdateEpicDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
}
// UpdateEpicDiscussionNote modifies existing discussion of a epic.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-existing-epic-thread-note
func (s *DiscussionsService) UpdateEpicDiscussionNote(gid interface{}, 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,
)
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/ee/api/discussions.html#delete-an-epic-thread-note
func (s *DiscussionsService) DeleteEpicDiscussionNote(gid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ListMergeRequestDiscussionsOptions represents the available
// ListMergeRequestDiscussions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#list-project-merge-request-discussion-items
type ListMergeRequestDiscussionsOptions ListOptions
// ListMergeRequestDiscussions gets a list of all discussions for a single
// merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#list-project-merge-request-discussion-items
func (s *DiscussionsService) ListMergeRequestDiscussions(pid interface{}, 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,
)
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/ee/api/discussions.html#get-single-merge-request-discussion-item
func (s *DiscussionsService) GetMergeRequestDiscussion(pid interface{}, 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,
)
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
// CreateMergeRequestDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-merge-request-thread
type CreateMergeRequestDiscussionOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CommitID *string `url:"commit_id,omitempty" json:"commit_id,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
Position *PositionOptions `url:"position,omitempty" json:"position,omitempty"`
}
// PositionOptions represents the position option of a discussion.
type PositionOptions struct {
BaseSHA *string `url:"base_sha,omitempty" json:"base_sha,omitempty"`
HeadSHA *string `url:"head_sha,omitempty" json:"head_sha,omitempty"`
StartSHA *string `url:"start_sha,omitempty" json:"start_sha,omitempty"`
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"`
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"`
X *float64 `url:"x,omitempty" json:"x,omitempty"`
Y *float64 `url:"y,omitempty" json:"y,omitempty"`
}
// LineRangeOptions represents the line range option of a discussion.
type LineRangeOptions struct {
Start *LinePositionOptions `url:"start,omitempty" json:"start,omitempty"`
End *LinePositionOptions `url:"end,omitempty" json:"end,omitempty"`
}
// LinePositionOptions represents the line position option of a discussion.
type LinePositionOptions struct {
LineCode *string `url:"line_code,omitempty" json:"line_code,omitempty"`
Type *string `url:"type,omitempty" json:"type,omitempty"`
}
// CreateMergeRequestDiscussion creates a new discussion for a single merge
// request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-merge-request-thread
func (s *DiscussionsService) CreateMergeRequestDiscussion(pid interface{}, 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,
)
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
// ResolveMergeRequestDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#resolve-a-merge-request-thread
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/ee/api/discussions.html#resolve-a-merge-request-thread
func (s *DiscussionsService) ResolveMergeRequestDiscussion(pid interface{}, 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,
)
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
// AddMergeRequestDiscussionNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#add-note-to-existing-merge-request-thread
type AddMergeRequestDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#add-note-to-existing-merge-request-thread
func (s *DiscussionsService) AddMergeRequestDiscussionNote(pid interface{}, 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,
)
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
// UpdateMergeRequestDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-an-existing-merge-request-thread-note
type UpdateMergeRequestDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
Resolved *bool `url:"resolved,omitempty" json:"resolved,omitempty"`
}
// UpdateMergeRequestDiscussionNote modifies existing discussion of a merge
// request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-an-existing-merge-request-thread-note
func (s *DiscussionsService) UpdateMergeRequestDiscussionNote(pid interface{}, 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,
)
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/ee/api/discussions.html#delete-a-merge-request-thread-note
func (s *DiscussionsService) DeleteMergeRequestDiscussionNote(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ListCommitDiscussionsOptions represents the available
// ListCommitDiscussions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#list-project-commit-discussion-items
type ListCommitDiscussionsOptions ListOptions
// ListCommitDiscussions gets a list of all discussions for a single
// commit.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#list-project-commit-discussion-items
func (s *DiscussionsService) ListCommitDiscussions(pid interface{}, 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,
)
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/ee/api/discussions.html#get-single-commit-discussion-item
func (s *DiscussionsService) GetCommitDiscussion(pid interface{}, 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,
)
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
// CreateCommitDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#create-new-commit-thread
type CreateCommitDiscussionOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
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/ee/api/discussions.html#create-new-commit-thread
func (s *DiscussionsService) CreateCommitDiscussion(pid interface{}, 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,
)
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
// AddCommitDiscussionNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#add-note-to-existing-commit-thread
type AddCommitDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
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/ee/api/discussions.html#add-note-to-existing-commit-thread
func (s *DiscussionsService) AddCommitDiscussionNote(pid interface{}, 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,
)
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
// UpdateCommitDiscussion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-an-existing-commit-thread-note
type UpdateCommitDiscussionNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
}
// UpdateCommitDiscussionNote modifies existing discussion of an commit.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/discussions.html#modify-an-existing-commit-thread-note
func (s *DiscussionsService) UpdateCommitDiscussionNote(pid interface{}, 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,
)
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/ee/api/discussions.html#delete-a-commit-thread-note
func (s *DiscussionsService) DeleteCommitDiscussionNote(pid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2022, FantasyTeddy
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// DockerfileTemplatesService handles communication with the Dockerfile
// templates related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/dockerfiles.html
type DockerfileTemplatesService struct {
client *Client
}
// DockerfileTemplate represents a GitLab Dockerfile template.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/dockerfiles.html
type DockerfileTemplate struct {
Name string `json:"name"`
Content string `json:"content"`
}
// DockerfileTemplateListItem represents a GitLab Dockerfile template from the list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/dockerfiles.html
type DockerfileTemplateListItem struct {
Key string `json:"key"`
Name string `json:"name"`
}
// ListDockerfileTemplatesOptions represents the available ListAllTemplates() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/dockerfiles.html#list-dockerfile-templates
type ListDockerfileTemplatesOptions ListOptions
// ListTemplates get a list of available Dockerfile templates.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/dockerfiles.html#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
}
// GetTemplate get a single Dockerfile template.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/dockerfiles.html#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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// DORAMetricsService handles communication with the DORA metrics related methods
// of the GitLab API.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
type DORAMetricsService struct {
client *Client
}
// DORAMetric represents a single DORA metric data point.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
type DORAMetric struct {
Date string `json:"date"`
Value float64 `json:"value"`
}
// Gets a string representation of a DORAMetric data point
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
func (m DORAMetric) String() string {
return Stringify(m)
}
// GetDORAMetricsOptions represent the request body options for getting
// DORA metrics
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
type GetDORAMetricsOptions struct {
Metric *DORAMetricType `url:"metric,omitempty" json:"metric,omitempty"`
EndDate *ISOTime `url:"end_date,omitempty" json:"end_date,omitempty"`
EnvironmentTiers *[]string `url:"environment_tiers,comma,omitempty" json:"environment_tiers,omitempty"`
Interval *DORAMetricInterval `url:"interval,omitempty" json:"interval,omitempty"`
StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
// Deprecated, use environment tiers instead
EnvironmentTier *string `url:"environment_tier,omitempty" json:"environment_tier,omitempty"`
}
// GetProjectDORAMetrics gets the DORA metrics for a project.
//
// GitLab API Docs:
// https://docs.gitlab.com/ee/api/dora/metrics.html#get-project-level-dora-metrics
func (s *DORAMetricsService) GetProjectDORAMetrics(pid interface{}, 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
}
// GetGroupDORAMetrics gets the DORA metrics for a group.
//
// GitLab API Docs:
// https://docs.gitlab.com/ee/api/dora/metrics.html#get-group-level-dora-metrics
func (s *DORAMetricsService) GetGroupDORAMetrics(gid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
type DraftNote struct {
ID int `json:"id"`
AuthorID int `json:"author_id"`
MergeRequestID int `json:"merge_request_id"`
ResolveDiscussion bool `json:"resolve_discussion"`
DiscussionID string `json:"discussion_id"`
Note string `json:"note"`
CommitID string `json:"commit_id"`
LineCode string `json:"line_code"`
Position *NotePosition `json:"position"`
}
// DraftNotesService handles communication with the draft notes related methods
// of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#list-all-merge-request-draft-notes
type DraftNotesService struct {
client *Client
}
// ListDraftNotesOptions represents the available ListDraftNotes()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#list-all-merge-request-draft-notes
type ListDraftNotesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
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/ee/api/draft_notes.html#list-all-merge-request-draft-notes
func (s *DraftNotesService) ListDraftNotes(pid interface{}, 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
}
// GetDraftNote gets a single draft note for a merge request.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#get-a-single-draft-note
func (s *DraftNotesService) GetDraftNote(pid interface{}, 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
}
// CreateDraftNoteOptions represents the available CreateDraftNote()
// options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
type CreateDraftNoteOptions struct {
Note *string `url:"note" json:"note"`
CommitID *string `url:"commit_id,omitempty" json:"commit_id,omitempty"`
InReplyToDiscussionID *string `url:"in_reply_to_discussion_id,omitempty" json:"in_reply_to_discussion_id,omitempty"`
ResolveDiscussion *bool `url:"resolve_discussion,omitempty" json:"resolve_discussion,omitempty"`
Position *PositionOptions `url:"position,omitempty" json:"position,omitempty"`
}
// CreateDraftNote creates a draft note for a merge request.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
func (s *DraftNotesService) CreateDraftNote(pid interface{}, 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
}
// UpdateDraftNoteOptions represents the available UpdateDraftNote()
// options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#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/ee/api/draft_notes.html#create-a-draft-note
func (s *DraftNotesService) UpdateDraftNote(pid interface{}, 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
}
// DeleteDraftNote deletes a single draft note for a merge request.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#delete-a-draft-note
func (s *DraftNotesService) DeleteDraftNote(pid interface{}, 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)
}
// PublishDraftNote publishes a single draft note for a merge request.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#publish-a-draft-note
func (s *DraftNotesService) PublishDraftNote(pid interface{}, 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)
}
// PublishAllDraftNotes publishes all draft notes for a merge request that belong to the user.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/draft_notes.html#publish-a-draft-note
func (s *DraftNotesService) PublishAllDraftNotes(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// EnvironmentsService handles communication with the environment related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/environments.html
type EnvironmentsService struct {
client *Client
}
// Environment represents a GitLab environment.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/environments.html
type Environment struct {
ID int `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
State string `json:"state"`
Tier string `json:"tier"`
ExternalURL string `json:"external_url"`
Project *Project `json:"project"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
LastDeployment *Deployment `json:"last_deployment"`
}
func (env Environment) String() string {
return Stringify(env)
}
// ListEnvironmentsOptions represents the available ListEnvironments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#list-environments
type ListEnvironmentsOptions struct {
ListOptions
Name *string `url:"name,omitempty" json:"name,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
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/ee/api/environments.html#list-environments
func (s *EnvironmentsService) ListEnvironments(pid interface{}, 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
}
// GetEnvironment gets a specific environment from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#get-a-specific-environment
func (s *EnvironmentsService) GetEnvironment(pid interface{}, 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
}
// CreateEnvironmentOptions represents the available CreateEnvironment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#create-a-new-environment
type CreateEnvironmentOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"`
Tier *string `url:"tier,omitempty" json:"tier,omitempty"`
}
// CreateEnvironment adds an environment to a project. This is an idempotent
// method and can be called multiple times with the same parameters. Createing
// an environment that is already a environment does not affect the
// existing environmentship.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#create-a-new-environment
func (s *EnvironmentsService) CreateEnvironment(pid interface{}, 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
}
// EditEnvironmentOptions represents the available EditEnvironment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#update-an-existing-environment
type EditEnvironmentOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExternalURL *string `url:"external_url,omitempty" json:"external_url,omitempty"`
Tier *string `url:"tier,omitempty" json:"tier,omitempty"`
}
// EditEnvironment updates a project team environment to a specified access level..
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#update-an-existing-environment
func (s *EnvironmentsService) EditEnvironment(pid interface{}, 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
}
// DeleteEnvironment removes an environment from a project team.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#delete-an-environment
func (s *EnvironmentsService) DeleteEnvironment(pid interface{}, 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)
}
// StopEnvironmentOptions represents the available StopEnvironment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/environments.html#stop-an-environment
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/ee/api/environments.html#stop-an-environment
func (s *EnvironmentsService) StopEnvironment(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// EpicIssuesService handles communication with the epic issue related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epic_issues.html
type EpicIssuesService struct {
client *Client
}
// EpicIssueAssignment contains both the epic and issue objects returned from
// Gitlab with the assignment ID.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epic_issues.html
type EpicIssueAssignment struct {
ID int `json:"id"`
Epic *Epic `json:"epic"`
Issue *Issue `json:"issue"`
}
// ListEpicIssues get a list of epic issues.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#list-issues-for-an-epic
func (s *EpicIssuesService) ListEpicIssues(gid interface{}, 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
}
// AssignEpicIssue assigns an existing issue to an epic.
//
// Gitlab API Docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#assign-an-issue-to-the-epic
func (s *EpicIssuesService) AssignEpicIssue(gid interface{}, 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
}
// RemoveEpicIssue removes an issue from an epic.
//
// Gitlab API Docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#remove-an-issue-from-the-epic
func (s *EpicIssuesService) RemoveEpicIssue(gid interface{}, 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
}
// UpdateEpicIsssueAssignmentOptions describes the UpdateEpicIssueAssignment()
// options.
//
// Gitlab API Docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#update-epic---issue-association
type UpdateEpicIsssueAssignmentOptions 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"`
}
// UpdateEpicIssueAssignment moves an issue before or after another issue in an
// epic issue list.
//
// Gitlab API Docs:
// https://docs.gitlab.com/ee/api/epic_issues.html#update-epic---issue-association
func (s *EpicIssuesService) UpdateEpicIssueAssignment(gid interface{}, epic, epicIssue int, opt *UpdateEpicIsssueAssignmentOptions, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// EpicsService handles communication with the epic related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html
type EpicsService struct {
client *Client
}
// EpicAuthor represents a author of the epic.
type EpicAuthor struct {
ID int `json:"id"`
State string `json:"state"`
WebURL string `json:"web_url"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
Username string `json:"username"`
}
// Epic represents a GitLab epic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html
type Epic struct {
ID int `json:"id"`
IID int `json:"iid"`
GroupID int `json:"group_id"`
ParentID int `json:"parent_id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
Confidential bool `json:"confidential"`
WebURL string `json:"web_url"`
Author *EpicAuthor `json:"author"`
StartDate *ISOTime `json:"start_date"`
StartDateIsFixed bool `json:"start_date_is_fixed"`
StartDateFixed *ISOTime `json:"start_date_fixed"`
StartDateFromMilestones *ISOTime `json:"start_date_from_milestones"`
DueDate *ISOTime `json:"due_date"`
DueDateIsFixed bool `json:"due_date_is_fixed"`
DueDateFixed *ISOTime `json:"due_date_fixed"`
DueDateFromMilestones *ISOTime `json:"due_date_from_milestones"`
CreatedAt *time.Time `json:"created_at"`
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"`
URL string `json:"url"`
}
func (e Epic) String() string {
return Stringify(e)
}
// ListGroupEpicsOptions represents the available ListGroupEpics() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#list-epics-for-a-group
type ListGroupEpicsOptions struct {
ListOptions
AuthorID *int `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"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
State *string `url:"state,omitempty" json:"state,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
IncludeAncestorGroups *bool `url:"include_ancestor_groups,omitempty" json:"include_ancestor_groups,omitempty"`
IncludeDescendantGroups *bool `url:"include_descendant_groups,omitempty" json:"include_descendant_groups,omitempty"`
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.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#list-epics-for-a-group
func (s *EpicsService) ListGroupEpics(gid interface{}, 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
}
// GetEpic gets a single group epic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#single-epic
func (s *EpicsService) GetEpic(gid interface{}, 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
}
// GetEpicLinks gets all child epics of an epic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epic_links.html
func (s *EpicsService) GetEpicLinks(gid interface{}, 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
}
// CreateEpicOptions represents the available CreateEpic() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#new-epic
type CreateEpicOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Labels *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Color *string `url:"color,omitempty" json:"color,omitempty"`
Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
StartDateIsFixed *bool `url:"start_date_is_fixed,omitempty" json:"start_date_is_fixed,omitempty"`
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"`
}
// CreateEpic creates a new group epic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#new-epic
func (s *EpicsService) CreateEpic(gid interface{}, 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
}
// UpdateEpicOptions represents the available UpdateEpic() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#update-epic
type UpdateEpicOptions struct {
AddLabels *LabelOptions `url:"add_labels,omitempty" json:"add_labels,omitempty"`
Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
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"`
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"`
StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
UpdatedAt *time.Time `url:"updated_at,omitempty" json:"updated_at,omitempty"`
Color *string `url:"color,omitempty" json:"color,omitempty"`
}
// UpdateEpic updates an existing group epic. This function is also used
// to mark an epic as closed.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#update-epic
func (s *EpicsService) UpdateEpic(gid interface{}, 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
}
// DeleteEpic deletes a single group epic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/epics.html#delete-epic
func (s *EpicsService) DeleteEpic(gid interface{}, 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)
}
//
// Copyright 2022, Ryan Glab <ryan.j.glab@gmail.com>
//
// 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 (
"fmt"
"net/http"
)
// ErrorTrackingService handles communication with the error tracking
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html
type ErrorTrackingService struct {
client *Client
}
// ErrorTrackingClientKey represents an error tracking client key.
//
// GitLab docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#error-tracking-client-keys
type ErrorTrackingClientKey struct {
ID int `json:"id"`
Active bool `json:"active"`
PublicKey string `json:"public_key"`
SentryDsn string `json:"sentry_dsn"`
}
func (p ErrorTrackingClientKey) String() string {
return Stringify(p)
}
// ErrorTrackingSettings represents error tracking settings for a GitLab project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#error-tracking-project-settings
type ErrorTrackingSettings struct {
Active bool `json:"active"`
ProjectName string `json:"project_name"`
SentryExternalURL string `json:"sentry_external_url"`
APIURL string `json:"api_url"`
Integrated bool `json:"integrated"`
}
func (p ErrorTrackingSettings) String() string {
return Stringify(p)
}
// GetErrorTrackingSettings gets error tracking settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#get-error-tracking-settings
func (s *ErrorTrackingService) GetErrorTrackingSettings(pid interface{}, 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
}
// EnableDisableErrorTrackingOptions represents the available
// EnableDisableErrorTracking() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#enable-or-disable-the-error-tracking-project-settings
type EnableDisableErrorTrackingOptions struct {
Active *bool `url:"active,omitempty" json:"active,omitempty"`
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/ee/api/error_tracking.html#enable-or-disable-the-error-tracking-project-settings
func (s *ErrorTrackingService) EnableDisableErrorTracking(pid interface{}, 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
}
// ListClientKeysOptions represents the available ListClientKeys() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#list-project-client-keys
type ListClientKeysOptions ListOptions
// ListClientKeys lists error tracking project client keys.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#list-project-client-keys
func (s *ErrorTrackingService) ListClientKeys(pid interface{}, 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
}
// CreateClientKey creates a new client key for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#create-a-client-key
func (s *ErrorTrackingService) CreateClientKey(pid interface{}, 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
}
// DeleteClientKey removes a client key from the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/error_tracking.html#delete-a-client-key
func (s *ErrorTrackingService) DeleteClientKey(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"net/http"
)
// EventType represents a Gitlab event type.
type EventType string
// List of available event types.
const (
EventConfidentialIssue EventType = "Confidential Issue Hook"
EventConfidentialNote EventType = "Confidential Note Hook"
EventTypeBuild EventType = "Build Hook"
EventTypeDeployment EventType = "Deployment Hook"
EventTypeFeatureFlag EventType = "Feature Flag Hook"
EventTypeIssue EventType = "Issue Hook"
EventTypeJob EventType = "Job Hook"
EventTypeMember EventType = "Member Hook"
EventTypeMergeRequest EventType = "Merge Request Hook"
EventTypeNote EventType = "Note Hook"
EventTypePipeline EventType = "Pipeline Hook"
EventTypePush EventType = "Push Hook"
EventTypeRelease EventType = "Release Hook"
EventTypeResourceAccessToken EventType = "Resource Access Token Hook"
EventTypeServiceHook EventType = "Service Hook"
EventTypeSubGroup EventType = "Subgroup Hook"
EventTypeSystemHook EventType = "System Hook"
EventTypeTagPush EventType = "Tag Push Hook"
EventTypeWikiPage EventType = "Wiki Page Hook"
)
const (
eventObjectKindPush = "push"
eventObjectKindTagPush = "tag_push"
eventObjectKindMergeRequest = "merge_request"
)
const (
noteableTypeCommit = "Commit"
noteableTypeIssue = "Issue"
noteableTypeMergeRequest = "MergeRequest"
noteableTypeSnippet = "Snippet"
)
type noteEvent struct {
ObjectKind string `json:"object_kind"`
ObjectAttributes struct {
NoteableType string `json:"noteable_type"`
} `json:"object_attributes"`
}
type serviceEvent struct {
ObjectKind string `json:"object_kind"`
}
const eventTokenHeader = "X-Gitlab-Token"
// HookEventToken returns the token for the given request.
func HookEventToken(r *http.Request) string {
return r.Header.Get(eventTokenHeader)
}
const eventTypeHeader = "X-Gitlab-Event"
// HookEventType returns the event type for the given request.
func HookEventType(r *http.Request) EventType {
return EventType(r.Header.Get(eventTypeHeader))
}
// ParseHook tries to parse both web- and system hooks.
//
// Example usage:
//
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// payload, err := ioutil.ReadAll(r.Body)
// if err != nil { ... }
// event, err := gitlab.ParseHook(gitlab.HookEventType(r), payload)
// if err != nil { ... }
// switch event := event.(type) {
// case *gitlab.PushEvent:
// processPushEvent(event)
// case *gitlab.MergeEvent:
// processMergeEvent(event)
// ...
// }
// }
func ParseHook(eventType EventType, payload []byte) (event interface{}, err error) {
switch eventType {
case EventTypeSystemHook:
return ParseSystemhook(payload)
default:
return ParseWebhook(eventType, payload)
}
}
// ParseSystemhook parses the event payload. For recognized event types, a
// value of the corresponding struct type will be returned. An error will be
// returned for unrecognized event types.
//
// Example usage:
//
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// payload, err := ioutil.ReadAll(r.Body)
// if err != nil { ... }
// event, err := gitlab.ParseSystemhook(payload)
// if err != nil { ... }
// switch event := event.(type) {
// case *gitlab.PushSystemEvent:
// processPushSystemEvent(event)
// case *gitlab.MergeSystemEvent:
// processMergeSystemEvent(event)
// ...
// }
// }
func ParseSystemhook(payload []byte) (event interface{}, err error) {
e := &systemHookEvent{}
err = json.Unmarshal(payload, e)
if err != nil {
return nil, err
}
switch e.EventName {
case eventObjectKindPush:
event = &PushSystemEvent{}
case eventObjectKindTagPush:
event = &TagPushSystemEvent{}
case "repository_update":
event = &RepositoryUpdateSystemEvent{}
case
"project_create",
"project_update",
"project_destroy",
"project_transfer",
"project_rename":
event = &ProjectSystemEvent{}
case
"group_create",
"group_destroy",
"group_rename":
event = &GroupSystemEvent{}
case "key_create", "key_destroy":
event = &KeySystemEvent{}
case
"user_create",
"user_destroy",
"user_rename",
"user_failed_login":
event = &UserSystemEvent{}
case
"user_add_to_group",
"user_remove_from_group",
"user_update_for_group":
event = &UserGroupSystemEvent{}
case
"user_add_to_team",
"user_remove_from_team",
"user_update_for_team":
event = &UserTeamSystemEvent{}
default:
switch e.ObjectKind {
case string(MergeRequestEventTargetType):
event = &MergeEvent{}
default:
return nil, fmt.Errorf("unexpected system hook type %s", e.EventName)
}
}
if err := json.Unmarshal(payload, event); err != nil {
return nil, err
}
return event, nil
}
// WebhookEventType returns the event type for the given request.
func WebhookEventType(r *http.Request) EventType {
return EventType(r.Header.Get(eventTypeHeader))
}
// ParseWebhook parses the event payload. For recognized event types, a
// value of the corresponding struct type will be returned. An error will
// be returned for unrecognized event types.
//
// Example usage:
//
// func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// payload, err := ioutil.ReadAll(r.Body)
// if err != nil { ... }
// event, err := gitlab.ParseWebhook(gitlab.HookEventType(r), payload)
// if err != nil { ... }
// switch event := event.(type) {
// case *gitlab.PushEvent:
// processPushEvent(event)
// case *gitlab.MergeEvent:
// processMergeEvent(event)
// ...
// }
// }
func ParseWebhook(eventType EventType, payload []byte) (event interface{}, err error) {
switch eventType {
case EventTypeBuild:
event = &BuildEvent{}
case EventTypeDeployment:
event = &DeploymentEvent{}
case EventTypeFeatureFlag:
event = &FeatureFlagEvent{}
case EventTypeIssue, EventConfidentialIssue:
event = &IssueEvent{}
case EventTypeJob:
event = &JobEvent{}
case EventTypeMember:
event = &MemberEvent{}
case EventTypeMergeRequest:
event = &MergeEvent{}
case EventTypeNote, EventConfidentialNote:
note := ¬eEvent{}
err := json.Unmarshal(payload, note)
if err != nil {
return nil, err
}
if note.ObjectKind != string(NoteEventTargetType) {
return nil, fmt.Errorf("unexpected object kind %s", note.ObjectKind)
}
switch note.ObjectAttributes.NoteableType {
case noteableTypeCommit:
event = &CommitCommentEvent{}
case noteableTypeMergeRequest:
event = &MergeCommentEvent{}
case noteableTypeIssue:
event = &IssueCommentEvent{}
case noteableTypeSnippet:
event = &SnippetCommentEvent{}
default:
return nil, fmt.Errorf("unexpected noteable type %s", note.ObjectAttributes.NoteableType)
}
case EventTypePipeline:
event = &PipelineEvent{}
case EventTypePush:
event = &PushEvent{}
case EventTypeRelease:
event = &ReleaseEvent{}
case EventTypeResourceAccessToken:
data := map[string]interface{}{}
err := json.Unmarshal(payload, &data)
if err != nil {
return nil, err
}
_, groupEvent := data["group"]
_, projectEvent := data["project"]
switch {
case groupEvent:
event = &GroupResourceAccessTokenEvent{}
case projectEvent:
event = &ProjectResourceAccessTokenEvent{}
default:
return nil, fmt.Errorf("unexpected resource access token payload")
}
case EventTypeServiceHook:
service := &serviceEvent{}
err := json.Unmarshal(payload, service)
if err != nil {
return nil, err
}
switch service.ObjectKind {
case eventObjectKindPush:
event = &PushEvent{}
case eventObjectKindTagPush:
event = &TagEvent{}
case eventObjectKindMergeRequest:
event = &MergeEvent{}
default:
return nil, fmt.Errorf("unexpected service type %s", service.ObjectKind)
}
case EventTypeSubGroup:
event = &SubGroupEvent{}
case EventTypeTagPush:
event = &TagEvent{}
case EventTypeWikiPage:
event = &WikiPageEvent{}
default:
return nil, fmt.Errorf("unexpected event type: %s", eventType)
}
if err := json.Unmarshal(payload, event); err != nil {
return nil, err
}
return event, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"strconv"
"time"
)
// StateID identifies the state of an issue or merge request.
//
// 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
const (
StateIDNone StateID = 0
StateIDOpen StateID = 1
StateIDClosed StateID = 2
StateIDMerged StateID = 3
StateIDLocked StateID = 4
)
// BuildEvent represents a build event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// CommitCommentEvent represents a comment on a commit event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// DeploymentEvent represents a deployment event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// FeatureFlagEvent represents a feature flag event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// GroupResourceAccessTokenEvent represents a resource access token event for a
// group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// IssueCommentEvent represents a comment on an issue event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// IssueEvent represents a issue event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-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"`
}
// JobEvent represents a job event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// MemberEvent represents a member event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#group-member-events
type MemberEvent struct {
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
GroupName string `json:"group_name"`
GroupPath string `json:"group_path"`
GroupID int `json:"group_id"`
UserUsername string `json:"user_username"`
UserName string `json:"user_name"`
UserEmail string `json:"user_email"`
UserID int `json:"user_id"`
GroupAccess string `json:"group_access"`
GroupPlan string `json:"group_plan"`
ExpiresAt *time.Time `json:"expires_at"`
EventName string `json:"event_name"`
}
// MergeCommentEvent represents a comment on a merge event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
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"`
} `json:"merge_request"`
}
// MergeEvent represents a merge event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
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
// initiator or a merge assignee.
type EventUser struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
Email string `json:"email"`
}
// MergeParams represents the merge params.
type MergeParams struct {
ForceRemoveSourceBranch bool `json:"force_remove_source_branch"`
}
// UnmarshalJSON decodes the merge parameters
//
// This allows support of ForceRemoveSourceBranch for both type
// bool (>11.9) and string (<11.9)
func (p *MergeParams) UnmarshalJSON(b []byte) error {
type Alias MergeParams
raw := struct {
*Alias
ForceRemoveSourceBranch interface{} `json:"force_remove_source_branch"`
}{
Alias: (*Alias)(p),
}
err := json.Unmarshal(b, &raw)
if err != nil {
return err
}
switch v := raw.ForceRemoveSourceBranch.(type) {
case nil:
// No action needed.
case bool:
p.ForceRemoveSourceBranch = v
case string:
p.ForceRemoveSourceBranch, err = strconv.ParseBool(v)
if err != nil {
return err
}
default:
return fmt.Errorf("failed to unmarshal ForceRemoveSourceBranch of type: %T", v)
}
return nil
}
// PipelineEvent represents a pipeline event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
SourcePipline 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"`
}
// ProjectResourceAccessTokenEvent represents a resource access token event for
// a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// PushEvent represents a push event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
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"`
}
// ReleaseEvent represents a release event
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
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"`
}
// SnippetCommentEvent represents a comment on a snippet event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// SubGroupEvent represents a subgroup event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#subgroup-events
type SubGroupEvent struct {
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
EventName string `json:"event_name"`
Name string `json:"name"`
Path string `json:"path"`
FullPath string `json:"full_path"`
GroupID int `json:"group_id"`
ParentGroupID int `json:"parent_group_id"`
ParentName string `json:"parent_name"`
ParentPath string `json:"parent_path"`
ParentFullPath string `json:"parent_full_path"`
}
// TagEvent represents a tag event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// WikiPageEvent represents a wiki page event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#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"`
}
// EventLabel represents a label inside a webhook event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events
type EventLabel struct {
ID int `json:"id"`
Title string `json:"title"`
Color string `json:"color"`
ProjectID int `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"`
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// EventsService handles communication with the event related methods of
// the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/events.html
type EventsService struct {
client *Client
}
// ContributionEvent represents a user's contribution
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/events.html#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"`
}
// ListContributionEventsOptions represents the options for GetUserContributionEvents
//
// GitLap API docs:
// https://docs.gitlab.com/ee/api/events.html#get-user-contribution-events
type ListContributionEventsOptions struct {
ListOptions
Action *EventTypeValue `url:"action,omitempty" json:"action,omitempty"`
TargetType *EventTargetTypeValue `url:"target_type,omitempty" json:"target_type,omitempty"`
Before *ISOTime `url:"before,omitempty" json:"before,omitempty"`
After *ISOTime `url:"after,omitempty" json:"after,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListUserContributionEvents retrieves user contribution events
// for the specified user, sorted from newest to oldest.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/events.html#get-user-contribution-events
func (s *UsersService) ListUserContributionEvents(uid interface{}, 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
}
// ListCurrentUserContributionEvents gets a list currently authenticated user's events
//
// GitLab API docs: https://docs.gitlab.com/ee/api/events.html#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
}
// ProjectEvent represents a GitLab project event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/events.html#list-a-projects-visible-events
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"`
}
func (s ProjectEvent) String() string {
return Stringify(s)
}
// ListProjectVisibleEventsOptions represents the available
// ListProjectVisibleEvents() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/events.html#list-a-projects-visible-events
type ListProjectVisibleEventsOptions struct {
ListOptions
Action *EventTypeValue `url:"action,omitempty" json:"action,omitempty"`
TargetType *EventTargetTypeValue `url:"target_type,omitempty" json:"target_type,omitempty"`
Before *ISOTime `url:"before,omitempty" json:"before,omitempty"`
After *ISOTime `url:"after,omitempty" json:"after,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListProjectVisibleEvents gets the events for the specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/events.html#list-a-projects-visible-events
func (s *EventsService) ListProjectVisibleEvents(pid interface{}, 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
}
package gitlab
import (
"fmt"
"net/http"
"time"
)
// ExternalStatusChecksService handles communication with the external
// status check related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/status_checks.html
type ExternalStatusChecksService struct {
client *Client
}
type MergeStatusCheck struct {
ID int `json:"id"`
Name string `json:"name"`
ExternalURL string `json:"external_url"`
Status string `json:"status"`
}
type ProjectStatusCheck struct {
ID int `json:"id"`
Name string `json:"name"`
ProjectID int `json:"project_id"`
ExternalURL string `json:"external_url"`
ProtectedBranches []StatusCheckProtectedBranch `json:"protected_branches"`
}
type StatusCheckProtectedBranch struct {
ID int `json:"id"`
ProjectID int `json:"project_id"`
Name string `json:"name"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
CodeOwnerApprovalRequired bool `json:"code_owner_approval_required"`
}
// ListMergeStatusChecks lists the external status checks that apply to it
// and their status for a single merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#list-status-checks-for-a-merge-request
func (s *ExternalStatusChecksService) ListMergeStatusChecks(pid interface{}, 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
}
// SetExternalStatusCheckStatusOptions represents the available
// SetExternalStatusCheckStatus() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#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"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
}
// SetExternalStatusCheckStatus sets the status of an external status check.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#set-status-of-an-external-status-check
func (s *ExternalStatusChecksService) SetExternalStatusCheckStatus(pid interface{}, 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)
}
// ListProjectStatusChecks lists the project external status checks.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#get-project-external-status-checks
func (s *ExternalStatusChecksService) ListProjectStatusChecks(pid interface{}, 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
}
// CreateExternalStatusCheckOptions represents the available
// CreateExternalStatusCheck() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#create-external-status-check
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"`
}
// CreateExternalStatusCheck creates an external status check.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#create-external-status-check
func (s *ExternalStatusChecksService) CreateExternalStatusCheck(pid interface{}, 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)
}
// DeleteExternalStatusCheck deletes an external status check.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#delete-external-status-check
func (s *ExternalStatusChecksService) DeleteExternalStatusCheck(pid interface{}, 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)
}
// UpdateExternalStatusCheckOptions represents the available
// UpdateExternalStatusCheck() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#update-external-status-check
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"`
}
// UpdateExternalStatusCheck updates an external status check.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#update-external-status-check
func (s *ExternalStatusChecksService) UpdateExternalStatusCheck(pid interface{}, 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)
}
// UpdateExternalStatusCheck updates an external status check.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/status_checks.html#retry-failed-status-check-for-a-merge-request
func (s *ExternalStatusChecksService) RetryFailedStatusCheckForAMergeRequest(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// FeaturesService handles the communication with the application FeaturesService
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/features.html
type FeaturesService struct {
client *Client
}
// Feature represents a GitLab feature flag.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/features.html
type Feature struct {
Name string `json:"name"`
State string `json:"state"`
Gates []Gate
}
// Gate represents a gate of a GitLab feature flag.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/features.html
type Gate struct {
Key string `json:"key"`
Value interface{} `json:"value"`
}
func (f Feature) String() string {
return Stringify(f)
}
// ListFeatures gets a list of feature flags
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/features.html#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
}
// SetFeatureFlag sets or creates a feature flag gate
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/features.html#set-or-create-a-feature
func (s *FeaturesService) SetFeatureFlag(name string, value interface{}, options ...RequestOptionFunc) (*Feature, *Response, error) {
u := fmt.Sprintf("features/%s", url.PathEscape(name))
opt := struct {
Value interface{} `url:"value" json:"value"`
}{
value,
}
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
}
//
// Copyright 2021 Paul Cioanca
//
// 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 (
"fmt"
"net/http"
"time"
)
// FreezePeriodsService handles the communication with the freeze periods
// related methods of the GitLab API.
//
// https://docs.gitlab.com/ee/api/freeze_periods.html
type FreezePeriodsService struct {
client *Client
}
// FreezePeriod represents a freeze period object.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#list-freeze-periods
type FreezePeriod struct {
ID int `json:"id"`
FreezeStart string `json:"freeze_start"`
FreezeEnd string `json:"freeze_end"`
CronTimezone string `json:"cron_timezone"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}
// ListFreezePeriodsOptions represents the available ListFreezePeriodsOptions()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#list-freeze-periods
type ListFreezePeriodsOptions ListOptions
// ListFreezePeriods gets a list of project project freeze periods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#list-freeze-periods
func (s *FreezePeriodsService) ListFreezePeriods(pid interface{}, 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
}
// GetFreezePeriod gets a specific freeze period for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#get-a-freeze-period-by-a-freeze_period_id
func (s *FreezePeriodsService) GetFreezePeriod(pid interface{}, 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
}
// CreateFreezePeriodOptions represents the available CreateFreezePeriodOptions()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#create-a-freeze-period
type CreateFreezePeriodOptions struct {
FreezeStart *string `url:"freeze_start,omitempty" json:"freeze_start,omitempty"`
FreezeEnd *string `url:"freeze_end,omitempty" json:"freeze_end,omitempty"`
CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
}
// CreateFreezePeriodOptions adds a freeze period to a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#create-a-freeze-period
func (s *FreezePeriodsService) CreateFreezePeriodOptions(pid interface{}, 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
}
// UpdateFreezePeriodOptions represents the available UpdateFreezePeriodOptions()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#update-a-freeze-period
type UpdateFreezePeriodOptions struct {
FreezeStart *string `url:"freeze_start,omitempty" json:"freeze_start,omitempty"`
FreezeEnd *string `url:"freeze_end,omitempty" json:"freeze_end,omitempty"`
CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
}
// UpdateFreezePeriodOptions edits a freeze period for a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/freeze_periods.html#update-a-freeze-period
func (s *FreezePeriodsService) UpdateFreezePeriodOptions(pid interface{}, 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
}
// DeleteFreezePeriod removes a freeze period 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/ee/api/freeze_periods.html#delete-a-freeze-period
func (s *FreezePeriodsService) DeleteFreezePeriod(pid interface{}, 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)
}
//
// Copyright 2021, Sune Keller
//
// 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 (
"bytes"
"fmt"
"io"
"net/http"
"time"
)
// GenericPackagesService handles communication with the packages related
// methods of the GitLab API.
//
// GitLab docs:
// https://docs.gitlab.com/ee/user/packages/generic_packages/index.html
type GenericPackagesService struct {
client *Client
}
// GenericPackagesFile represents a GitLab generic package file.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/packages/generic_packages/index.html#publish-a-package-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"`
}
// FormatPackageURL returns the GitLab Package Registry URL for the given artifact metadata, without the BaseURL.
// This does not make a GitLab API request, but rather computes it based on their documentation.
func (s *GenericPackagesService) FormatPackageURL(pid interface{}, packageName, packageVersion, fileName string) (string, error) {
project, err := parseID(pid)
if err != nil {
return "", err
}
u := fmt.Sprintf(
"projects/%s/packages/generic/%s/%s/%s",
PathEscape(project),
PathEscape(packageName),
PathEscape(packageVersion),
PathEscape(fileName),
)
return u, nil
}
// PublishPackageFileOptions represents the available PublishPackageFile()
// options.
//
// GitLab docs:
// https://docs.gitlab.com/ee/user/packages/generic_packages/index.html#publish-a-package-file
type PublishPackageFileOptions struct {
Status *GenericPackageStatusValue `url:"status,omitempty" json:"status,omitempty"`
Select *GenericPackageSelectValue `url:"select,omitempty" json:"select,omitempty"`
}
// PublishPackageFile uploads a file to a project's package registry.
//
// GitLab docs:
// https://docs.gitlab.com/ee/user/packages/generic_packages/index.html#publish-a-package-file
func (s *GenericPackagesService) PublishPackageFile(pid interface{}, packageName, packageVersion, fileName string, content io.Reader, opt *PublishPackageFileOptions, options ...RequestOptionFunc) (*GenericPackagesFile, *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),
)
// We need to create the request as a GET request to make sure the options
// are set correctly. After the request is created we will overwrite both
// the method and the body.
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
// Overwrite the method and body.
req.Method = http.MethodPut
req.SetBody(content)
f := new(GenericPackagesFile)
resp, err := s.client.Do(req, f)
if err != nil {
return nil, resp, err
}
return f, resp, nil
}
// DownloadPackageFile allows you to download the package file.
//
// GitLab docs:
// https://docs.gitlab.com/ee/user/packages/generic_packages/index.html#download-package-file
func (s *GenericPackagesService) DownloadPackageFile(pid interface{}, 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),
)
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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// GeoNode represents a GitLab Geo Node.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/geo_nodes.html
type GeoNode struct {
ID int `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"`
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"`
SyncObjectStorage bool `json:"sync_object_storage"`
CloneProtocol string `json:"clone_protocol"`
WebEditURL string `json:"web_edit_url"`
WebGeoProjectsURL string `json:"web_geo_projects_url"`
Links GeoNodeLinks `json:"_links"`
}
// GeoNodeLinks represents links for GitLab GeoNode.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/geo_nodes.html
type GeoNodeLinks struct {
Self string `json:"self"`
Status string `json:"status"`
Repair string `json:"repair"`
}
// GeoNodesService handles communication with Geo Nodes related methods
// of GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/geo_nodes.html
type GeoNodesService struct {
client *Client
}
// CreateGeoNodesOptions represents the available CreateGeoNode() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#create-a-new-geo-node
type CreateGeoNodesOptions 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"`
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"`
}
// CreateGeoNode creates a new Geo Node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// ListGeoNodesOptions represents the available ListGeoNodes() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#retrieve-configuration-about-all-geo-nodes
type ListGeoNodesOptions ListOptions
// ListGeoNodes gets a list of geo nodes.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// GetGeoNode gets a specific geo node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// UpdateGeoNodesOptions represents the available EditGeoNode() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#edit-a-geo-node
type UpdateGeoNodesOptions struct {
ID *int `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"`
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"`
}
// EditGeoNode updates settings of an existing Geo node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// DeleteGeoNode removes the Geo node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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)
}
// RepairGeoNode to repair the OAuth authentication of a Geo node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// GeoNodeStatus represents the status of Geo Node.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#retrieve-status-about-all-geo-nodes
type GeoNodeStatus struct {
GeoNodeID int `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"`
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"`
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"`
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"`
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"`
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"`
RepositoriesSyncedInPercentage string `json:"repositories_synced_in_percentage"`
WikisCount int `json:"wikis_count"`
WikisFailedCount int `json:"wikis_failed_count"`
WikisSyncedCount int `json:"wikis_synced_count"`
WikisSyncedInPercentage string `json:"wikis_synced_in_percentage"`
ReplicationSlotsCount int `json:"replication_slots_count"`
ReplicationSlotsUsedCount int `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"`
RepositoriesCheckedInPercentage string `json:"repositories_checked_in_percentage"`
RepositoriesChecksummedCount int `json:"repositories_checksummed_count"`
RepositoriesChecksumFailedCount int `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"`
WikisChecksummedInPercentage string `json:"wikis_checksummed_in_percentage"`
RepositoriesVerifiedCount int `json:"repositories_verified_count"`
RepositoriesVerificationFailedCount int `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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
UploadsSyncedInPercentage string `json:"uploads_synced_in_percentage"`
}
// RetrieveStatusOfAllGeoNodes get the list of status of all Geo Nodes.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
// RetrieveStatusOfGeoNode get the of status of a specific Geo Nodes.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/geo_nodes.html#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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// GitIgnoreTemplatesService handles communication with the gitignore
// templates related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/gitignores.html
type GitIgnoreTemplatesService struct {
client *Client
}
// GitIgnoreTemplate represents a GitLab gitignore template.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/gitignores.html
type GitIgnoreTemplate struct {
Name string `json:"name"`
Content string `json:"content"`
}
// GitIgnoreTemplateListItem represents a GitLab gitignore template from the list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/gitignores.html
type GitIgnoreTemplateListItem struct {
Key string `json:"key"`
Name string `json:"name"`
}
// ListTemplatesOptions represents the available ListAllTemplates() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitignores.html#get-all-gitignore-templates
type ListTemplatesOptions ListOptions
// ListTemplates get a list of available git ignore templates
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitignores.html#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
}
// GetTemplate get a git ignore template
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/gitignores.html#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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 implements a GitLab API client.
package gitlab
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"math/rand"
"mime/multipart"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/hashicorp/go-cleanhttp"
"github.com/google/go-querystring/query"
retryablehttp "github.com/hashicorp/go-retryablehttp"
"golang.org/x/oauth2"
"golang.org/x/time/rate"
)
const (
defaultBaseURL = "https://gitlab.com/"
apiVersionPath = "api/v4/"
userAgent = "go-gitlab"
headerRateLimit = "RateLimit-Limit"
headerRateReset = "RateLimit-Reset"
)
// AuthType represents an authentication type within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
type AuthType int
// List of available authentication types.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
const (
BasicAuth AuthType = iota
JobToken
OAuthToken
PrivateToken
)
var ErrNotFound = errors.New("404 Not Found")
// A Client manages communication with the GitLab API.
type Client struct {
// HTTP client used to communicate with the API.
client *retryablehttp.Client
// Base URL for API requests. Defaults to the public GitLab API, but can be
// set to a domain endpoint to use with a self hosted GitLab server. baseURL
// should always be specified with a trailing slash.
baseURL *url.URL
// disableRetries is used to disable the default retry logic.
disableRetries bool
// configureLimiterOnce is used to make sure the limiter is configured exactly
// once and block all other calls until the initial (one) call is done.
configureLimiterOnce sync.Once
// Limiter is used to limit API calls and prevent 429 responses.
limiter RateLimiter
// Token type used to make authenticated API calls.
authType AuthType
// Username and password used for basic authentication.
username, password string
// Token used to make authenticated API calls.
token string
// Protects the token field from concurrent read/write accesses.
tokenLock sync.RWMutex
// Default request options applied to every request.
defaultRequestOptions []RequestOptionFunc
// User agent used when communicating with the GitLab API.
UserAgent string
// Services used for talking to different parts of the GitLab API.
AccessRequests *AccessRequestsService
Appearance *AppearanceService
Applications *ApplicationsService
AuditEvents *AuditEventsService
Avatar *AvatarRequestsService
AwardEmoji *AwardEmojiService
Boards *IssueBoardsService
Branches *BranchesService
BroadcastMessage *BroadcastMessagesService
CIYMLTemplate *CIYMLTemplatesService
ClusterAgents *ClusterAgentsService
Commits *CommitsService
ContainerRegistry *ContainerRegistryService
CustomAttribute *CustomAttributesService
DeployKeys *DeployKeysService
DeployTokens *DeployTokensService
DeploymentMergeRequests *DeploymentMergeRequestsService
Deployments *DeploymentsService
Discussions *DiscussionsService
DockerfileTemplate *DockerfileTemplatesService
DORAMetrics *DORAMetricsService
DraftNotes *DraftNotesService
Environments *EnvironmentsService
EpicIssues *EpicIssuesService
Epics *EpicsService
ErrorTracking *ErrorTrackingService
Events *EventsService
ExternalStatusChecks *ExternalStatusChecksService
Features *FeaturesService
FreezePeriods *FreezePeriodsService
GenericPackages *GenericPackagesService
GeoNodes *GeoNodesService
GitIgnoreTemplates *GitIgnoreTemplatesService
GroupAccessTokens *GroupAccessTokensService
GroupBadges *GroupBadgesService
GroupCluster *GroupClustersService
GroupEpicBoards *GroupEpicBoardsService
GroupImportExport *GroupImportExportService
GroupIssueBoards *GroupIssueBoardsService
GroupIterations *GroupIterationsService
GroupLabels *GroupLabelsService
GroupMembers *GroupMembersService
GroupMilestones *GroupMilestonesService
GroupProtectedEnvironments *GroupProtectedEnvironmentsService
GroupRepositoryStorageMove *GroupRepositoryStorageMoveService
GroupSSHCertificates *GroupSSHCertificatesService
GroupVariables *GroupVariablesService
GroupWikis *GroupWikisService
Groups *GroupsService
Import *ImportService
InstanceCluster *InstanceClustersService
InstanceVariables *InstanceVariablesService
Invites *InvitesService
IssueLinks *IssueLinksService
Issues *IssuesService
IssuesStatistics *IssuesStatisticsService
Jobs *JobsService
JobTokenScope *JobTokenScopeService
Keys *KeysService
Labels *LabelsService
License *LicenseService
LicenseTemplates *LicenseTemplatesService
ManagedLicenses *ManagedLicensesService
Markdown *MarkdownService
MemberRolesService *MemberRolesService
MergeRequestApprovals *MergeRequestApprovalsService
MergeRequests *MergeRequestsService
MergeTrains *MergeTrainsService
Metadata *MetadataService
Milestones *MilestonesService
Namespaces *NamespacesService
Notes *NotesService
NotificationSettings *NotificationSettingsService
Packages *PackagesService
Pages *PagesService
PagesDomains *PagesDomainsService
PersonalAccessTokens *PersonalAccessTokensService
PipelineSchedules *PipelineSchedulesService
PipelineTriggers *PipelineTriggersService
Pipelines *PipelinesService
PlanLimits *PlanLimitsService
ProjectAccessTokens *ProjectAccessTokensService
ProjectBadges *ProjectBadgesService
ProjectCluster *ProjectClustersService
ProjectFeatureFlags *ProjectFeatureFlagService
ProjectImportExport *ProjectImportExportService
ProjectIterations *ProjectIterationsService
ProjectMembers *ProjectMembersService
ProjectMirrors *ProjectMirrorService
ProjectRepositoryStorageMove *ProjectRepositoryStorageMoveService
ProjectSnippets *ProjectSnippetsService
ProjectTemplates *ProjectTemplatesService
ProjectVariables *ProjectVariablesService
ProjectVulnerabilities *ProjectVulnerabilitiesService
Projects *ProjectsService
ProtectedBranches *ProtectedBranchesService
ProtectedEnvironments *ProtectedEnvironmentsService
ProtectedTags *ProtectedTagsService
ReleaseLinks *ReleaseLinksService
Releases *ReleasesService
Repositories *RepositoriesService
RepositoryFiles *RepositoryFilesService
RepositorySubmodules *RepositorySubmodulesService
ResourceGroup *ResourceGroupService
ResourceIterationEvents *ResourceIterationEventsService
ResourceLabelEvents *ResourceLabelEventsService
ResourceMilestoneEvents *ResourceMilestoneEventsService
ResourceStateEvents *ResourceStateEventsService
ResourceWeightEvents *ResourceWeightEventsService
Runners *RunnersService
Search *SearchService
Services *ServicesService
Settings *SettingsService
Sidekiq *SidekiqService
SnippetRepositoryStorageMove *SnippetRepositoryStorageMoveService
Snippets *SnippetsService
SystemHooks *SystemHooksService
Tags *TagsService
Todos *TodosService
Topics *TopicsService
Users *UsersService
Validate *ValidateService
Version *VersionService
Wikis *WikisService
}
// ListOptions specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
// For offset-based paginated result sets, page of results to retrieve.
Page int `url:"page,omitempty" json:"page,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"`
// For keyset-based paginated result sets, name of the column by which to order
OrderBy string `url:"order_by,omitempty" json:"order_by,omitempty"`
// For keyset-based paginated result sets, the value must be `"keyset"`
Pagination string `url:"pagination,omitempty" json:"pagination,omitempty"`
// For keyset-based paginated result sets, sort order (`"asc"`` or `"desc"`)
Sort string `url:"sort,omitempty" json:"sort,omitempty"`
}
// RateLimiter describes the interface that all (custom) rate limiters must implement.
type RateLimiter interface {
Wait(context.Context) error
}
// NewClient returns a new GitLab API client. To use API methods which require
// authentication, provide a valid private or personal token.
func NewClient(token string, options ...ClientOptionFunc) (*Client, error) {
client, err := newClient(options...)
if err != nil {
return nil, err
}
client.authType = PrivateToken
client.token = token
return client, nil
}
// NewBasicAuthClient returns a new GitLab API client. To use API methods which
// require authentication, provide a valid username and password.
func NewBasicAuthClient(username, password string, options ...ClientOptionFunc) (*Client, error) {
client, err := newClient(options...)
if err != nil {
return nil, err
}
client.authType = BasicAuth
client.username = username
client.password = password
return client, nil
}
// NewJobClient returns a new GitLab API client. To use API methods which require
// authentication, provide a valid job token.
func NewJobClient(token string, options ...ClientOptionFunc) (*Client, error) {
client, err := newClient(options...)
if err != nil {
return nil, err
}
client.authType = JobToken
client.token = token
return client, nil
}
// NewOAuthClient returns a new GitLab API client. To use API methods which
// require authentication, provide a valid oauth token.
func NewOAuthClient(token string, options ...ClientOptionFunc) (*Client, error) {
client, err := newClient(options...)
if err != nil {
return nil, err
}
client.authType = OAuthToken
client.token = token
return client, nil
}
func newClient(options ...ClientOptionFunc) (*Client, error) {
c := &Client{UserAgent: userAgent}
// Configure the HTTP client.
c.client = &retryablehttp.Client{
Backoff: c.retryHTTPBackoff,
CheckRetry: c.retryHTTPCheck,
ErrorHandler: retryablehttp.PassthroughErrorHandler,
HTTPClient: cleanhttp.DefaultPooledClient(),
RetryWaitMin: 100 * time.Millisecond,
RetryWaitMax: 400 * time.Millisecond,
RetryMax: 5,
}
// Set the default base URL.
c.setBaseURL(defaultBaseURL)
// Apply any given client options.
for _, fn := range options {
if fn == nil {
continue
}
if err := fn(c); err != nil {
return nil, err
}
}
// If no custom limiter was set using a client option, configure
// the default rate limiter with values that implicitly disable
// rate limiting until an initial HTTP call is done and we can
// use the headers to try and properly configure the limiter.
if c.limiter == nil {
c.limiter = rate.NewLimiter(rate.Inf, 0)
}
// Create the internal timeStats service.
timeStats := &timeStatsService{client: c}
// Create all the public services.
c.AccessRequests = &AccessRequestsService{client: c}
c.Appearance = &AppearanceService{client: c}
c.Applications = &ApplicationsService{client: c}
c.AuditEvents = &AuditEventsService{client: c}
c.Avatar = &AvatarRequestsService{client: c}
c.AwardEmoji = &AwardEmojiService{client: c}
c.Boards = &IssueBoardsService{client: c}
c.Branches = &BranchesService{client: c}
c.BroadcastMessage = &BroadcastMessagesService{client: c}
c.CIYMLTemplate = &CIYMLTemplatesService{client: c}
c.ClusterAgents = &ClusterAgentsService{client: c}
c.Commits = &CommitsService{client: c}
c.ContainerRegistry = &ContainerRegistryService{client: c}
c.CustomAttribute = &CustomAttributesService{client: c}
c.DeployKeys = &DeployKeysService{client: c}
c.DeployTokens = &DeployTokensService{client: c}
c.DeploymentMergeRequests = &DeploymentMergeRequestsService{client: c}
c.Deployments = &DeploymentsService{client: c}
c.Discussions = &DiscussionsService{client: c}
c.DockerfileTemplate = &DockerfileTemplatesService{client: c}
c.DORAMetrics = &DORAMetricsService{client: c}
c.DraftNotes = &DraftNotesService{client: c}
c.Environments = &EnvironmentsService{client: c}
c.EpicIssues = &EpicIssuesService{client: c}
c.Epics = &EpicsService{client: c}
c.ErrorTracking = &ErrorTrackingService{client: c}
c.Events = &EventsService{client: c}
c.ExternalStatusChecks = &ExternalStatusChecksService{client: c}
c.Features = &FeaturesService{client: c}
c.FreezePeriods = &FreezePeriodsService{client: c}
c.GenericPackages = &GenericPackagesService{client: c}
c.GeoNodes = &GeoNodesService{client: c}
c.GitIgnoreTemplates = &GitIgnoreTemplatesService{client: c}
c.GroupAccessTokens = &GroupAccessTokensService{client: c}
c.GroupBadges = &GroupBadgesService{client: c}
c.GroupCluster = &GroupClustersService{client: c}
c.GroupEpicBoards = &GroupEpicBoardsService{client: c}
c.GroupImportExport = &GroupImportExportService{client: c}
c.GroupIssueBoards = &GroupIssueBoardsService{client: c}
c.GroupIterations = &GroupIterationsService{client: c}
c.GroupLabels = &GroupLabelsService{client: c}
c.GroupMembers = &GroupMembersService{client: c}
c.GroupMilestones = &GroupMilestonesService{client: c}
c.GroupProtectedEnvironments = &GroupProtectedEnvironmentsService{client: c}
c.GroupRepositoryStorageMove = &GroupRepositoryStorageMoveService{client: c}
c.GroupSSHCertificates = &GroupSSHCertificatesService{client: c}
c.GroupVariables = &GroupVariablesService{client: c}
c.GroupWikis = &GroupWikisService{client: c}
c.Groups = &GroupsService{client: c}
c.Import = &ImportService{client: c}
c.InstanceCluster = &InstanceClustersService{client: c}
c.InstanceVariables = &InstanceVariablesService{client: c}
c.Invites = &InvitesService{client: c}
c.IssueLinks = &IssueLinksService{client: c}
c.Issues = &IssuesService{client: c, timeStats: timeStats}
c.IssuesStatistics = &IssuesStatisticsService{client: c}
c.Jobs = &JobsService{client: c}
c.JobTokenScope = &JobTokenScopeService{client: c}
c.Keys = &KeysService{client: c}
c.Labels = &LabelsService{client: c}
c.License = &LicenseService{client: c}
c.LicenseTemplates = &LicenseTemplatesService{client: c}
c.ManagedLicenses = &ManagedLicensesService{client: c}
c.Markdown = &MarkdownService{client: c}
c.MemberRolesService = &MemberRolesService{client: c}
c.MergeRequestApprovals = &MergeRequestApprovalsService{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.Namespaces = &NamespacesService{client: c}
c.Notes = &NotesService{client: c}
c.NotificationSettings = &NotificationSettingsService{client: c}
c.Packages = &PackagesService{client: c}
c.Pages = &PagesService{client: c}
c.PagesDomains = &PagesDomainsService{client: c}
c.PersonalAccessTokens = &PersonalAccessTokensService{client: c}
c.PipelineSchedules = &PipelineSchedulesService{client: c}
c.PipelineTriggers = &PipelineTriggersService{client: c}
c.Pipelines = &PipelinesService{client: c}
c.PlanLimits = &PlanLimitsService{client: c}
c.ProjectAccessTokens = &ProjectAccessTokensService{client: c}
c.ProjectBadges = &ProjectBadgesService{client: c}
c.ProjectCluster = &ProjectClustersService{client: c}
c.ProjectFeatureFlags = &ProjectFeatureFlagService{client: c}
c.ProjectImportExport = &ProjectImportExportService{client: c}
c.ProjectIterations = &ProjectIterationsService{client: c}
c.ProjectMembers = &ProjectMembersService{client: c}
c.ProjectMirrors = &ProjectMirrorService{client: c}
c.ProjectRepositoryStorageMove = &ProjectRepositoryStorageMoveService{client: c}
c.ProjectSnippets = &ProjectSnippetsService{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.ProtectedTags = &ProtectedTagsService{client: c}
c.ReleaseLinks = &ReleaseLinksService{client: c}
c.Releases = &ReleasesService{client: c}
c.Repositories = &RepositoriesService{client: c}
c.RepositoryFiles = &RepositoryFilesService{client: c}
c.RepositorySubmodules = &RepositorySubmodulesService{client: c}
c.ResourceGroup = &ResourceGroupService{client: c}
c.ResourceIterationEvents = &ResourceIterationEventsService{client: c}
c.ResourceLabelEvents = &ResourceLabelEventsService{client: c}
c.ResourceMilestoneEvents = &ResourceMilestoneEventsService{client: c}
c.ResourceStateEvents = &ResourceStateEventsService{client: c}
c.ResourceWeightEvents = &ResourceWeightEventsService{client: c}
c.Runners = &RunnersService{client: c}
c.Search = &SearchService{client: c}
c.Services = &ServicesService{client: c}
c.Settings = &SettingsService{client: c}
c.Sidekiq = &SidekiqService{client: c}
c.Snippets = &SnippetsService{client: c}
c.SnippetRepositoryStorageMove = &SnippetRepositoryStorageMoveService{client: c}
c.SystemHooks = &SystemHooksService{client: c}
c.Tags = &TagsService{client: c}
c.Todos = &TodosService{client: c}
c.Topics = &TopicsService{client: c}
c.Users = &UsersService{client: c}
c.Validate = &ValidateService{client: c}
c.Version = &VersionService{client: c}
c.Wikis = &WikisService{client: c}
return c, nil
}
// retryHTTPCheck provides a callback for Client.CheckRetry which
// will retry both rate limit (429) and server (>= 500) errors.
func (c *Client) retryHTTPCheck(ctx context.Context, resp *http.Response, err error) (bool, error) {
if ctx.Err() != nil {
return false, ctx.Err()
}
if err != nil {
return false, err
}
if !c.disableRetries && (resp.StatusCode == 429 || resp.StatusCode >= 500) {
return true, nil
}
return false, nil
}
// retryHTTPBackoff provides a generic callback for Client.Backoff which
// will pass through all calls based on the status code of the response.
func (c *Client) retryHTTPBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
// Use the rate limit backoff function when we are rate limited.
if resp != nil && resp.StatusCode == 429 {
return rateLimitBackoff(min, max, attemptNum, resp)
}
// Set custom duration's when we experience a service interruption.
min = 700 * time.Millisecond
max = 900 * time.Millisecond
return retryablehttp.LinearJitterBackoff(min, max, attemptNum, 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
// 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, _ 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))
if resp != nil {
if v := resp.Header.Get(headerRateReset); v != "" {
if reset, _ := strconv.ParseInt(v, 10, 64); reset > 0 {
// Only update min if the given time to wait is longer.
if wait := time.Until(time.Unix(reset, 0)); wait > min {
min = wait
}
}
}
}
return min + jitter
}
// configureLimiter configures the rate limiter.
func (c *Client) configureLimiter(ctx context.Context, headers http.Header) {
if v := headers.Get(headerRateLimit); v != "" {
if rateLimit, _ := strconv.ParseFloat(v, 64); rateLimit > 0 {
// The rate limit is based on requests per minute, so for our limiter to
// work correctly we divide the limit by 60 to get the limit per second.
rateLimit /= 60
// Configure the limit and burst using a split of 2/3 for the limit and
// 1/3 for the burst. This enables clients to burst 1/3 of the allowed
// calls before the limiter kicks in. The remaining calls will then be
// spread out evenly using intervals of time.Second / limit which should
// prevent hitting the rate limit.
limit := rate.Limit(rateLimit * 0.66)
burst := int(rateLimit * 0.33)
// Need at least one allowed to burst or x/time will throw an error
if burst == 0 {
burst = 1
}
// Create a new limiter using the calculated values.
c.limiter = rate.NewLimiter(limit, burst)
// Call the limiter once as we have already made a request
// to get the headers and the limiter is not aware of this.
c.limiter.Wait(ctx)
}
}
}
// BaseURL return a copy of the baseURL.
func (c *Client) BaseURL() *url.URL {
u := *c.baseURL
return &u
}
// 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
if !strings.HasSuffix(urlStr, "/") {
urlStr += "/"
}
baseURL, err := url.Parse(urlStr)
if err != nil {
return err
}
if !strings.HasSuffix(baseURL.Path, apiVersionPath) {
baseURL.Path += apiVersionPath
}
// Update the base URL of the client.
c.baseURL = baseURL
return nil
}
// NewRequest creates a new API request. The method expects a relative URL
// path that will be resolved relative to the base URL of the Client.
// Relative URL paths should always be specified without a preceding slash.
// If specified, the value pointed to by body is JSON encoded and included
// as the request body.
func (c *Client) NewRequest(method, path string, opt interface{}, options []RequestOptionFunc) (*retryablehttp.Request, error) {
u := *c.baseURL
unescaped, err := url.PathUnescape(path)
if err != nil {
return nil, err
}
// Set the encoded path data
u.RawPath = c.baseURL.Path + path
u.Path = c.baseURL.Path + unescaped
// Create a request specific headers map.
reqHeaders := make(http.Header)
reqHeaders.Set("Accept", "application/json")
if c.UserAgent != "" {
reqHeaders.Set("User-Agent", c.UserAgent)
}
var body interface{}
switch {
case method == http.MethodPatch || method == http.MethodPost || method == http.MethodPut:
reqHeaders.Set("Content-Type", "application/json")
if opt != nil {
body, err = json.Marshal(opt)
if err != nil {
return nil, err
}
}
case opt != nil:
q, err := query.Values(opt)
if err != nil {
return nil, err
}
u.RawQuery = q.Encode()
}
req, err := retryablehttp.NewRequest(method, u.String(), body)
if err != nil {
return nil, err
}
for _, fn := range append(c.defaultRequestOptions, options...) {
if fn == nil {
continue
}
if err := fn(req); err != nil {
return nil, err
}
}
// Set the request specific headers.
for k, v := range reqHeaders {
req.Header[k] = v
}
return req, nil
}
// UploadRequest creates an API request for uploading a file. The method
// expects a relative URL path that will be resolved relative to the base
// URL of the Client. Relative URL paths should always be specified without
// a preceding slash. If specified, the value pointed to by body is JSON
// encoded and included as the request body.
func (c *Client) UploadRequest(method, path string, content io.Reader, filename string, uploadType UploadType, opt interface{}, options []RequestOptionFunc) (*retryablehttp.Request, error) {
u := *c.baseURL
unescaped, err := url.PathUnescape(path)
if err != nil {
return nil, err
}
// Set the encoded path data
u.RawPath = c.baseURL.Path + path
u.Path = c.baseURL.Path + unescaped
// Create a request specific headers map.
reqHeaders := make(http.Header)
reqHeaders.Set("Accept", "application/json")
if c.UserAgent != "" {
reqHeaders.Set("User-Agent", c.UserAgent)
}
b := new(bytes.Buffer)
w := multipart.NewWriter(b)
fw, err := w.CreateFormFile(string(uploadType), filename)
if err != nil {
return nil, err
}
if _, err := io.Copy(fw, content); err != nil {
return nil, err
}
if opt != nil {
fields, err := query.Values(opt)
if err != nil {
return nil, err
}
for name := range fields {
if err = w.WriteField(name, fmt.Sprintf("%v", fields.Get(name))); err != nil {
return nil, err
}
}
}
if err = w.Close(); err != nil {
return nil, err
}
reqHeaders.Set("Content-Type", w.FormDataContentType())
req, err := retryablehttp.NewRequest(method, u.String(), b)
if err != nil {
return nil, err
}
for _, fn := range append(c.defaultRequestOptions, options...) {
if fn == nil {
continue
}
if err := fn(req); err != nil {
return nil, err
}
}
// Set the request specific headers.
for k, v := range reqHeaders {
req.Header[k] = v
}
return req, nil
}
// Response is a GitLab API response. This wraps the standard http.Response
// returned from GitLab and provides convenient access to things like
// pagination links.
type Response struct {
*http.Response
// Fields used for offset-based pagination.
TotalItems int
TotalPages int
ItemsPerPage int
CurrentPage int
NextPage int
PreviousPage int
// Fields used for keyset-based pagination.
PreviousLink string
NextLink string
FirstLink string
LastLink string
}
// newResponse creates a new Response for the provided http.Response.
func newResponse(r *http.Response) *Response {
response := &Response{Response: r}
response.populatePageValues()
response.populateLinkValues()
return response
}
const (
// Headers used for offset-based pagination.
xTotal = "X-Total"
xTotalPages = "X-Total-Pages"
xPerPage = "X-Per-Page"
xPage = "X-Page"
xNextPage = "X-Next-Page"
xPrevPage = "X-Prev-Page"
// Headers used for keyset-based pagination.
linkPrev = "prev"
linkNext = "next"
linkFirst = "first"
linkLast = "last"
)
// populatePageValues parses the HTTP Link response headers and populates the
// various pagination link values in the Response.
func (r *Response) populatePageValues() {
if totalItems := r.Header.Get(xTotal); totalItems != "" {
r.TotalItems, _ = strconv.Atoi(totalItems)
}
if totalPages := r.Header.Get(xTotalPages); totalPages != "" {
r.TotalPages, _ = strconv.Atoi(totalPages)
}
if itemsPerPage := r.Header.Get(xPerPage); itemsPerPage != "" {
r.ItemsPerPage, _ = strconv.Atoi(itemsPerPage)
}
if currentPage := r.Header.Get(xPage); currentPage != "" {
r.CurrentPage, _ = strconv.Atoi(currentPage)
}
if nextPage := r.Header.Get(xNextPage); nextPage != "" {
r.NextPage, _ = strconv.Atoi(nextPage)
}
if previousPage := r.Header.Get(xPrevPage); previousPage != "" {
r.PreviousPage, _ = strconv.Atoi(previousPage)
}
}
func (r *Response) populateLinkValues() {
if link := r.Header.Get("Link"); link != "" {
for _, link := range strings.Split(link, ",") {
parts := strings.Split(link, ";")
if len(parts) < 2 {
continue
}
linkType := strings.Trim(strings.Split(parts[1], "=")[1], "\"")
linkValue := strings.Trim(parts[0], "< >")
switch linkType {
case linkPrev:
r.PreviousLink = linkValue
case linkNext:
r.NextLink = linkValue
case linkFirst:
r.FirstLink = linkValue
case linkLast:
r.LastLink = linkValue
}
}
}
}
// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting to
// first decode it.
func (c *Client) Do(req *retryablehttp.Request, v interface{}) (*Response, error) {
// Wait will block until the limiter can obtain a new token.
err := c.limiter.Wait(req.Context())
if err != nil {
return nil, err
}
// Set the correct authentication header. If using basic auth, then check
// if we already have a token and if not first authenticate and get one.
var basicAuthToken string
switch c.authType {
case BasicAuth:
c.tokenLock.RLock()
basicAuthToken = c.token
c.tokenLock.RUnlock()
if basicAuthToken == "" {
// If we don't have a token yet, we first need to request one.
basicAuthToken, err = c.requestOAuthToken(req.Context(), basicAuthToken)
if err != nil {
return nil, err
}
}
req.Header.Set("Authorization", "Bearer "+basicAuthToken)
case JobToken:
if values := req.Header.Values("JOB-TOKEN"); len(values) == 0 {
req.Header.Set("JOB-TOKEN", c.token)
}
case OAuthToken:
if values := req.Header.Values("Authorization"); len(values) == 0 {
req.Header.Set("Authorization", "Bearer "+c.token)
}
case PrivateToken:
if values := req.Header.Values("PRIVATE-TOKEN"); len(values) == 0 {
req.Header.Set("PRIVATE-TOKEN", c.token)
}
}
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusUnauthorized && c.authType == BasicAuth {
resp.Body.Close()
// The token most likely expired, so we need to request a new one and try again.
if _, err := c.requestOAuthToken(req.Context(), basicAuthToken); err != nil {
return nil, err
}
return c.Do(req, v)
}
defer resp.Body.Close()
defer io.Copy(io.Discard, resp.Body)
// If not yet configured, try to configure the rate limiter
// using the response headers we just received. Fail silently
// so the limiter will remain disabled in case of an error.
c.configureLimiterOnce.Do(func() { c.configureLimiter(req.Context(), resp.Header) })
response := newResponse(resp)
err = CheckResponse(resp)
if err != nil {
// Even though there was an error, we still return the response
// in case the caller wants to inspect it further.
return response, err
}
if v != nil {
if w, ok := v.(io.Writer); ok {
_, err = io.Copy(w, resp.Body)
} else {
err = json.NewDecoder(resp.Body).Decode(v)
}
}
return response, err
}
func (c *Client) requestOAuthToken(ctx context.Context, token string) (string, error) {
c.tokenLock.Lock()
defer c.tokenLock.Unlock()
// Return early if the token was updated while waiting for the lock.
if c.token != token {
return c.token, nil
}
config := &oauth2.Config{
Endpoint: oauth2.Endpoint{
AuthURL: strings.TrimSuffix(c.baseURL.String(), apiVersionPath) + "oauth/authorize",
TokenURL: strings.TrimSuffix(c.baseURL.String(), apiVersionPath) + "oauth/token",
},
}
ctx = context.WithValue(ctx, oauth2.HTTPClient, c.client.HTTPClient)
t, err := config.PasswordCredentialsToken(ctx, c.username, c.password)
if err != nil {
return "", err
}
c.token = t.AccessToken
return c.token, nil
}
// Helper function to accept and format both the project ID or name as project
// identifier for all API calls.
func parseID(id interface{}) (string, error) {
switch v := id.(type) {
case int:
return strconv.Itoa(v), nil
case string:
return v, nil
default:
return "", fmt.Errorf("invalid ID type %#v, the ID must be an int or a string", id)
}
}
// Helper function to escape a project identifier.
func PathEscape(s string) string {
return strings.ReplaceAll(url.PathEscape(s), ".", "%2E")
}
// An ErrorResponse reports one or more errors caused by an API request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/index.html#data-validation-and-error-reporting
type ErrorResponse struct {
Body []byte
Response *http.Response
Message string
}
func (e *ErrorResponse) Error() string {
path, _ := url.QueryUnescape(e.Response.Request.URL.Path)
url := fmt.Sprintf("%s://%s%s", e.Response.Request.URL.Scheme, e.Response.Request.URL.Host, path)
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)
}
}
// CheckResponse checks the API response for errors, and returns them if present.
func CheckResponse(r *http.Response) error {
switch r.StatusCode {
case 200, 201, 202, 204, 304:
return nil
case 404:
return ErrNotFound
}
errorResponse := &ErrorResponse{Response: r}
data, err := io.ReadAll(r.Body)
if err == nil && strings.TrimSpace(string(data)) != "" {
errorResponse.Body = data
var raw interface{}
if err := json.Unmarshal(data, &raw); err != nil {
errorResponse.Message = fmt.Sprintf("failed to parse unknown error format: %s", data)
} else {
errorResponse.Message = parseError(raw)
}
}
return errorResponse
}
// Format:
//
// {
// "message": {
// "<property-name>": [
// "<error-message>",
// "<error-message>",
// ...
// ],
// "<embed-entity>": {
// "<property-name>": [
// "<error-message>",
// "<error-message>",
// ...
// ],
// }
// },
// "error": "<error-message>"
// }
func parseError(raw interface{}) string {
switch raw := raw.(type) {
case string:
return raw
case []interface{}:
var errs []string
for _, v := range raw {
errs = append(errs, parseError(v))
}
return fmt.Sprintf("[%s]", strings.Join(errs, ", "))
case map[string]interface{}:
var errs []string
for k, v := range raw {
errs = append(errs, fmt.Sprintf("{%s: %s}", k, parseError(v)))
}
sort.Strings(errs)
return strings.Join(errs, ", ")
default:
return fmt.Sprintf("failed to parse unexpected error type: %T", raw)
}
}
//
// Copyright 2022, Masahiro Yoshida
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupAccessTokensService handles communication with the
// groups access tokens related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_access_tokens.html
type GroupAccessTokensService struct {
client *Client
}
// GroupAccessToken represents a GitLab group access token.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_access_tokens.html
type GroupAccessToken struct {
ID int `json:"id"`
UserID int `json:"user_id"`
Name string `json:"name"`
Scopes []string `json:"scopes"`
CreatedAt *time.Time `json:"created_at"`
ExpiresAt *ISOTime `json:"expires_at"`
LastUsedAt *time.Time `json:"last_used_at"`
Active bool `json:"active"`
Revoked bool `json:"revoked"`
Token string `json:"token"`
AccessLevel AccessLevelValue `json:"access_level"`
}
func (v GroupAccessToken) String() string {
return Stringify(v)
}
// ListGroupAccessTokensOptions represents the available options for
// listing variables in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#list-group-access-tokens
type ListGroupAccessTokensOptions ListOptions
// ListGroupAccessTokens gets a list of all group access tokens in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#list-group-access-tokens
func (s *GroupAccessTokensService) ListGroupAccessTokens(gid interface{}, 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
}
// GetGroupAccessToken gets a single group access tokens in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#get-a-group-access-token
func (s *GroupAccessTokensService) GetGroupAccessToken(gid interface{}, 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
}
// CreateGroupAccessTokenOptions represents the available CreateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#create-a-group-access-token
type CreateGroupAccessTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// CreateGroupAccessToken creates a new group access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#create-a-group-access-token
func (s *GroupAccessTokensService) CreateGroupAccessToken(gid interface{}, 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
}
// RotateGroupAccessTokenOptions represents the available RotateGroupAccessToken()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#rotate-a-group-access-token
type RotateGroupAccessTokenOptions struct {
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// RotateGroupAccessToken revokes a group access token and returns a new group
// access token that expires in one week per default.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#rotate-a-group-access-token
func (s *GroupAccessTokensService) RotateGroupAccessToken(gid interface{}, 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
}
// RevokeGroupAccessToken revokes a group access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_access_tokens.html#revoke-a-group-access-token
func (s *GroupAccessTokensService) RevokeGroupAccessToken(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// GroupBadgesService handles communication with the group badges
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html
type GroupBadgesService struct {
client *Client
}
// BadgeKind represents a GitLab Badge Kind
type BadgeKind string
// all possible values Badge Kind
const (
ProjectBadgeKind BadgeKind = "project"
GroupBadgeKind BadgeKind = "group"
)
// GroupBadge represents a group badge.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html
type GroupBadge struct {
ID int `json:"id"`
Name string `json:"name"`
LinkURL string `json:"link_url"`
ImageURL string `json:"image_url"`
RenderedLinkURL string `json:"rendered_link_url"`
RenderedImageURL string `json:"rendered_image_url"`
Kind BadgeKind `json:"kind"`
}
// ListGroupBadgesOptions represents the available ListGroupBadges() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#list-all-badges-of-a-group
type ListGroupBadgesOptions struct {
ListOptions
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// ListGroupBadges gets a list of a group badges.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#list-all-badges-of-a-group
func (s *GroupBadgesService) ListGroupBadges(gid interface{}, 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
}
// GetGroupBadge gets a group badge.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#get-a-badge-of-a-group
func (s *GroupBadgesService) GetGroupBadge(gid interface{}, 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
}
// AddGroupBadgeOptions represents the available AddGroupBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#add-a-badge-to-a-group
type AddGroupBadgeOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// AddGroupBadge adds a badge to a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#add-a-badge-to-a-group
func (s *GroupBadgesService) AddGroupBadge(gid interface{}, 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
}
// EditGroupBadgeOptions represents the available EditGroupBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#edit-a-badge-of-a-group
type EditGroupBadgeOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// EditGroupBadge updates a badge of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#edit-a-badge-of-a-group
func (s *GroupBadgesService) EditGroupBadge(gid interface{}, 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
}
// DeleteGroupBadge removes a badge from a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#remove-a-badge-from-a-group
func (s *GroupBadgesService) DeleteGroupBadge(gid interface{}, 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)
}
// GroupBadgePreviewOptions represents the available PreviewGroupBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#preview-a-badge-from-a-group
type GroupBadgePreviewOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// PreviewGroupBadge returns how the link_url and image_url final URLs would be after
// resolving the placeholder interpolation.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_badges.html#preview-a-badge-from-a-group
func (s *GroupBadgesService) PreviewGroupBadge(gid interface{}, 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
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
)
// GroupIssueBoardsService handles communication with the group issue board
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html
type GroupIssueBoardsService struct {
client *Client
}
// GroupIssueBoard represents a GitLab group issue board.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html
type GroupIssueBoard struct {
ID int `json:"id"`
Name string `json:"name"`
Group *Group `json:"group"`
Milestone *Milestone `json:"milestone"`
Labels []*GroupLabel `json:"labels"`
Lists []*BoardList `json:"lists"`
}
func (b GroupIssueBoard) String() string {
return Stringify(b)
}
// ListGroupIssueBoardsOptions represents the available
// ListGroupIssueBoards() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#list-all-group-issue-boards-in-a-group
type ListGroupIssueBoardsOptions ListOptions
// ListGroupIssueBoards gets a list of all issue boards in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#list-all-group-issue-boards-in-a-group
func (s *GroupIssueBoardsService) ListGroupIssueBoards(gid interface{}, 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
}
// CreateGroupIssueBoardOptions represents the available
// CreateGroupIssueBoard() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#create-a-group-issue-board
type CreateGroupIssueBoardOptions struct {
Name *string `url:"name" json:"name"`
}
// CreateGroupIssueBoard creates a new issue board.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#create-a-group-issue-board
func (s *GroupIssueBoardsService) CreateGroupIssueBoard(gid interface{}, 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
}
// GetGroupIssueBoard gets a single issue board of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#single-group-issue-board
func (s *GroupIssueBoardsService) GetGroupIssueBoard(gid interface{}, 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
}
// UpdateGroupIssueBoardOptions represents a group issue board.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#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"`
Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"`
Weight *int `url:"weight,omitempty" json:"weight,omitempty"`
}
// UpdateIssueBoard updates a single issue board of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#update-a-group-issue-board
func (s *GroupIssueBoardsService) UpdateIssueBoard(gid interface{}, 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
}
// DeleteIssueBoard delete a single issue board of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#delete-a-group-issue-board
func (s *GroupIssueBoardsService) DeleteIssueBoard(gid interface{}, 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)
}
// ListGroupIssueBoardListsOptions represents the available
// ListGroupIssueBoardLists() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#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/ee/api/group_boards.html#list-group-issue-board-lists
func (s *GroupIssueBoardsService) ListGroupIssueBoardLists(gid interface{}, 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
}
// GetGroupIssueBoardList gets a single issue board list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#single-group-issue-board-list
func (s *GroupIssueBoardsService) GetGroupIssueBoardList(gid interface{}, 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,
)
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
}
// CreateGroupIssueBoardListOptions represents the available
// CreateGroupIssueBoardList() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#new-group-issue-board-list
type CreateGroupIssueBoardListOptions struct {
LabelID *int `url:"label_id" json:"label_id"`
}
// CreateGroupIssueBoardList creates a new issue board list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#new-group-issue-board-list
func (s *GroupIssueBoardsService) CreateGroupIssueBoardList(gid interface{}, 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
}
// UpdateGroupIssueBoardListOptions represents the available
// UpdateGroupIssueBoardList() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#edit-group-issue-board-list
type UpdateGroupIssueBoardListOptions struct {
Position *int `url:"position" json:"position"`
}
// UpdateIssueBoardList updates the position of an existing
// group issue board list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_boards.html#edit-group-issue-board-list
func (s *GroupIssueBoardsService) UpdateIssueBoardList(gid interface{}, 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,
)
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/ee/api/group_boards.html#delete-a-group-issue-board-list
func (s *GroupIssueBoardsService) DeleteGroupIssueBoardList(gid interface{}, 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,
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Paul Shoemaker
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupClustersService handles communication with the
// group clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html
type GroupClustersService struct {
client *Client
}
// GroupCluster represents a GitLab Group Cluster.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_clusters.html
type GroupCluster struct {
ID int `json:"id"`
Name string `json:"name"`
Domain string `json:"domain"`
CreatedAt *time.Time `json:"created_at"`
Managed bool `json:"managed"`
Enabled bool `json:"enabled"`
ProviderType string `json:"provider_type"`
PlatformType string `json:"platform_type"`
EnvironmentScope string `json:"environment_scope"`
ClusterType string `json:"cluster_type"`
User *User `json:"user"`
PlatformKubernetes *PlatformKubernetes `json:"platform_kubernetes"`
ManagementProject *ManagementProject `json:"management_project"`
Group *Group `json:"group"`
}
func (v GroupCluster) String() string {
return Stringify(v)
}
// ListClusters gets a list of all clusters in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#list-group-clusters
func (s *GroupClustersService) ListClusters(pid interface{}, 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
}
// GetCluster gets a cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#get-a-single-group-cluster
func (s *GroupClustersService) GetCluster(pid interface{}, 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
}
// AddGroupClusterOptions represents the available AddCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
type AddGroupClusterOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Domain *string `url:"domain,omitempty" json:"domain,omitempty"`
ManagementProjectID *string `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
Managed *bool `url:"managed,omitempty" json:"managed,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
PlatformKubernetes *AddGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
}
// AddGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for adding.
type AddGroupPlatformKubernetesOptions struct {
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"`
AuthorizationType *string `url:"authorization_type,omitempty" json:"authorization_type,omitempty"`
}
// AddCluster adds an existing cluster to the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#add-existing-cluster-to-group
func (s *GroupClustersService) AddCluster(pid interface{}, 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
}
// EditGroupClusterOptions represents the available EditCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
type EditGroupClusterOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Domain *string `url:"domain,omitempty" json:"domain,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
PlatformKubernetes *EditGroupPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
ManagementProjectID *string `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
}
// EditGroupPlatformKubernetesOptions represents the available PlatformKubernetes options for editing.
type EditGroupPlatformKubernetesOptions struct {
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
}
// EditCluster updates an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#edit-group-cluster
func (s *GroupClustersService) EditCluster(pid interface{}, 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
}
// DeleteCluster deletes an existing group cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_clusters.html#delete-group-cluster
func (s *GroupClustersService) DeleteCluster(pid interface{}, 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)
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
)
// GroupEpicBoardsService handles communication with the group epic board
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_epic_boards.html
type GroupEpicBoardsService struct {
client *Client
}
// GroupEpicBoard represents a GitLab group epic board.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_epic_boards.html
type GroupEpicBoard struct {
ID int `json:"id"`
Name string `json:"name"`
Group *Group `json:"group"`
Labels []*LabelDetails `json:"labels"`
Lists []*BoardList `json:"lists"`
}
func (b GroupEpicBoard) String() string {
return Stringify(b)
}
// ListGroupEpicBoardsOptions represents the available
// ListGroupEpicBoards() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_epic_boards.html#list-all-epic-boards-in-a-group
type ListGroupEpicBoardsOptions ListOptions
// ListGroupEpicBoards gets a list of all epic boards in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_epic_boards.html#list-all-epic-boards-in-a-group
func (s *GroupEpicBoardsService) ListGroupEpicBoards(gid interface{}, 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
}
// GetGroupEpicBoard gets a single epic board of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_epic_boards.html#single-group-epic-board
func (s *GroupEpicBoardsService) GetGroupEpicBoard(gid interface{}, 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
}
//
// Copyright 2021, Eric Stevens
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupHook represents a GitLab group hook.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#list-group-hooks
type GroupHook struct {
ID int `json:"id"`
URL string `json:"url"`
GroupID int `json:"group_id"`
PushEvents bool `json:"push_events"`
PushEventsBranchFilter string `json:"push_events_branch_filter"`
IssuesEvents bool `json:"issues_events"`
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
ConfidentialNoteEvents bool `json:"confidential_note_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
TagPushEvents bool `json:"tag_push_events"`
NoteEvents bool `json:"note_events"`
JobEvents bool `json:"job_events"`
PipelineEvents bool `json:"pipeline_events"`
WikiPageEvents bool `json:"wiki_page_events"`
DeploymentEvents bool `json:"deployment_events"`
ReleasesEvents bool `json:"releases_events"`
SubGroupEvents bool `json:"subgroup_events"`
MemberEvents bool `json:"member_events"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
AlertStatus string `json:"alert_status"`
CreatedAt *time.Time `json:"created_at"`
CustomWebhookTemplate string `json:"custom_webhook_template"`
ResourceAccessTokenEvents bool `json:"resource_access_token_events"`
CustomHeaders []*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"`
}
// ListGroupHooksOptions represents the available ListGroupHooks() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#list-group-hooks
type ListGroupHooksOptions ListOptions
// ListGroupHooks gets a list of group hooks.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#list-group-hooks
func (s *GroupsService) ListGroupHooks(gid interface{}, 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
}
// GetGroupHook gets a specific hook for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#get-group-hook
func (s *GroupsService) GetGroupHook(pid interface{}, hook int, options ...RequestOptionFunc) (*GroupHook, *Response, error) {
group, err := parseID(pid)
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
}
// AddGroupHookOptions represents the available AddGroupHook() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#add-group-hook
type AddGroupHookOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_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"`
JobEvents *bool `url:"job_events,omitempty" json:"job_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"`
ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"`
SubGroupEvents *bool `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
MemberEvents *bool `url:"member_events,omitempty" json:"member_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"`
CustomWebhookTemplate *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
CustomHeaders *[]*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"`
}
// AddGroupHook create a new group scoped webhook.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#add-group-hook
func (s *GroupsService) AddGroupHook(gid interface{}, 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
}
// EditGroupHookOptions represents the available EditGroupHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#edit-group-hook
type EditGroupHookOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_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"`
JobEvents *bool `url:"job_events,omitempty" json:"job_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"`
ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"`
SubGroupEvents *bool `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
MemberEvents *bool `url:"member_events,omitempty" json:"member_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"`
CustomWebhookTemplate *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
CustomHeaders *[]*HookCustomHeader `url:"custom_headers,omitempty" json:"custom_headers,omitempty"`
}
// EditGroupHook edits a hook for a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/groups.html#edit-group-hook
func (s *GroupsService) EditGroupHook(pid interface{}, hook int, opt *EditGroupHookOptions, options ...RequestOptionFunc) (*GroupHook, *Response, error) {
group, err := parseID(pid)
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
}
// DeleteGroupHook removes a hook from a group. This is an idempotent
// method and can be called multiple times.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-group-hook
func (s *GroupsService) DeleteGroupHook(pid interface{}, hook int, options ...RequestOptionFunc) (*Response, error) {
group, err := parseID(pid)
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)
}
// SetGroupCustomHeader creates or updates a group custom webhook header.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#set-a-custom-header
func (s *GroupsService) SetGroupCustomHeader(gid interface{}, 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)
}
// DeleteGroupCustomHeader deletes a group custom webhook header.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-a-custom-header
func (s *GroupsService) DeleteGroupCustomHeader(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strconv"
)
// GroupImportExportService handles communication with the group import export
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_import_export.html
type GroupImportExportService struct {
client *Client
}
// ScheduleExport starts a new group export.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_import_export.html#schedule-new-export
func (s *GroupImportExportService) ScheduleExport(gid interface{}, 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)
}
// ExportDownload downloads the finished export.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_import_export.html#export-download
func (s *GroupImportExportService) ExportDownload(gid interface{}, 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)
if err != nil {
return nil, resp, err
}
return bytes.NewReader(exportDownload.Bytes()), resp, err
}
// GroupImportFileOptions represents the available ImportFile() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_import_export.html#import-a-file
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"`
}
// ImportFile imports a file.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_import_export.html#import-a-file
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")
}
if opt.Path == nil || *opt.Path == "" {
return nil, fmt.Errorf("Missing required option: Path")
}
if opt.File == nil || *opt.File == "" {
return nil, fmt.Errorf("Missing required option: File")
}
f, err := os.Open(*opt.File)
if err != nil {
return nil, err
}
defer f.Close()
b := &bytes.Buffer{}
w := multipart.NewWriter(b)
_, filename := filepath.Split(*opt.File)
fw, err := w.CreateFormFile("file", filename)
if err != nil {
return nil, err
}
_, err = io.Copy(fw, f)
if err != nil {
return nil, err
}
// Populate the additional fields.
fw, err = w.CreateFormField("name")
if err != nil {
return nil, err
}
_, err = fw.Write([]byte(*opt.Name))
if err != nil {
return nil, err
}
fw, err = w.CreateFormField("path")
if err != nil {
return nil, err
}
_, err = fw.Write([]byte(*opt.Path))
if err != nil {
return nil, err
}
if opt.ParentID != nil {
fw, err = w.CreateFormField("parent_id")
if err != nil {
return nil, err
}
_, err = fw.Write([]byte(strconv.Itoa(*opt.ParentID)))
if err != nil {
return nil, err
}
}
if err = w.Close(); err != nil {
return nil, err
}
req, err := s.client.NewRequest(http.MethodPost, "groups/import", nil, options)
if err != nil {
return nil, err
}
// Set the buffer as the request body.
if err = req.SetBody(b); err != nil {
return nil, err
}
// Overwrite the default content type.
req.Header.Set("Content-Type", w.FormDataContentType())
return s.client.Do(req, nil)
}
//
// Copyright 2022, Daniel Steinke
//
// 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 (
"fmt"
"net/http"
"time"
)
// IterationsAPI handles communication with the iterations related methods
// of the GitLab API
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_iterations.html
type GroupIterationsService struct {
client *Client
}
// GroupInteration represents a GitLab iteration.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_iterations.html
type GroupIteration struct {
ID int `json:"id"`
IID int `json:"iid"`
Sequence int `json:"sequence"`
GroupID int `json:"group_id"`
Title string `json:"title"`
Description string `json:"description"`
State int `json:"state"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
DueDate *ISOTime `json:"due_date"`
StartDate *ISOTime `json:"start_date"`
WebURL string `json:"web_url"`
}
func (i GroupIteration) String() string {
return Stringify(i)
}
// ListGroupIterationsOptions contains the available ListGroupIterations()
// options
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_iterations.html#list-group-iterations
type ListGroupIterationsOptions struct {
ListOptions
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"`
}
// ListGroupIterations returns a list of group iterations.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_iterations.html#list-group-iterations
func (s *GroupIterationsService) ListGroupIterations(gid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// GroupLabelsService handles communication with the label related methods of the
// GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_labels.html
type GroupLabelsService struct {
client *Client
}
// GroupLabel represents a GitLab group label.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_labels.html
type GroupLabel Label
func (l GroupLabel) String() string {
return Stringify(l)
}
// ListGroupLabelsOptions represents the available ListGroupLabels() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_labels.html#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"`
}
// ListGroupLabels gets all labels for given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#list-group-labels
func (s *GroupLabelsService) ListGroupLabels(gid interface{}, 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
}
// GetGroupLabel get a single label for a given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#get-a-single-group-label
func (s *GroupLabelsService) GetGroupLabel(gid interface{}, labelID interface{}, options ...RequestOptionFunc) (*GroupLabel, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
label, err := parseID(labelID)
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
}
// CreateGroupLabelOptions represents the available CreateGroupLabel() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#create-a-new-group-label
type CreateGroupLabelOptions CreateLabelOptions
// CreateGroupLabel creates a new label for given group with given name and
// color.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#create-a-new-group-label
func (s *GroupLabelsService) CreateGroupLabel(gid interface{}, 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
}
// DeleteGroupLabelOptions represents the available DeleteGroupLabel() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#delete-a-group-label
type DeleteGroupLabelOptions DeleteLabelOptions
// DeleteGroupLabel deletes a group label given by its name or ID.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#delete-a-group-label
func (s *GroupLabelsService) DeleteGroupLabel(gid interface{}, lid interface{}, opt *DeleteGroupLabelOptions, options ...RequestOptionFunc) (*Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("groups/%s/labels", PathEscape(group))
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
}
return s.client.Do(req, nil)
}
// UpdateGroupLabelOptions represents the available UpdateGroupLabel() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#update-a-group-label
type UpdateGroupLabelOptions UpdateLabelOptions
// UpdateGroupLabel updates an existing label with new name or now color. At least
// one parameter is required, to update the label.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#update-a-group-label
func (s *GroupLabelsService) UpdateGroupLabel(gid interface{}, 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))
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
}
return l, resp, nil
}
// SubscribeToGroupLabel subscribes the authenticated user to a label to receive
// notifications. If the user is already subscribed to the label, the status
// code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#subscribe-to-a-group-label
func (s *GroupLabelsService) SubscribeToGroupLabel(gid interface{}, labelID interface{}, options ...RequestOptionFunc) (*GroupLabel, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
label, err := parseID(labelID)
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
}
// UnsubscribeFromGroupLabel unsubscribes the authenticated user from a label to not
// receive notifications from it. If the user is not subscribed to the label, the
// status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_labels.html#unsubscribe-from-a-group-label
func (s *GroupLabelsService) UnsubscribeFromGroupLabel(gid interface{}, labelID interface{}, options ...RequestOptionFunc) (*Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, err
}
label, err := parseID(labelID)
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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupMembersService handles communication with the group members
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html
type GroupMembersService struct {
client *Client
}
// GroupMemberSAMLIdentity represents the SAML Identity link for the group member.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project
// Gitlab MR for API change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20357
// Gitlab MR for API Doc change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25652
type GroupMemberSAMLIdentity struct {
ExternUID string `json:"extern_uid"`
Provider string `json:"provider"`
SAMLProviderID int `json:"saml_provider_id"`
}
// GroupMember represents a GitLab group member.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html
type GroupMember 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"`
CreatedAt *time.Time `json:"created_at"`
ExpiresAt *ISOTime `json:"expires_at"`
AccessLevel AccessLevelValue `json:"access_level"`
Email string `json:"email,omitempty"`
GroupSAMLIdentity *GroupMemberSAMLIdentity `json:"group_saml_identity"`
MemberRole *MemberRole `json:"member_role"`
}
// ListGroupMembersOptions represents the available ListGroupMembers() and
// ListAllGroupMembers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#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"`
}
// ListGroupMembers get a list of group members viewable by the authenticated
// user. Inherited members through ancestor groups are not included.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project
func (s *GroupsService) ListGroupMembers(gid interface{}, 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
}
// ListAllGroupMembers get a list of group members viewable by the authenticated
// user. Returns a list including inherited members through ancestor groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project-including-inherited-and-invited-members
func (s *GroupsService) ListAllGroupMembers(gid interface{}, 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
}
// AddGroupMemberOptions represents the available AddGroupMember() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#add-a-member-to-a-group-or-project
type AddGroupMemberOptions struct {
UserID *int `url:"user_id,omitempty" json:"user_id,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"`
}
// GetGroupMember gets a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#get-a-member-of-a-group-or-project
func (s *GroupMembersService) GetGroupMember(gid interface{}, 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
}
// GetInheritedGroupMember get a member of a group or project, including
// inherited and invited members
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#get-a-member-of-a-group-or-project-including-inherited-and-invited-members
func (s *GroupMembersService) GetInheritedGroupMember(gid interface{}, 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
}
// BillableGroupMember represents a GitLab billable group member.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html#list-all-billable-members-of-a-group
type BillableGroupMember 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"`
Email string `json:"email"`
LastActivityOn *ISOTime `json:"last_activity_on"`
MembershipType string `json:"membership_type"`
Removable bool `json:"removable"`
CreatedAt *time.Time `json:"created_at"`
IsLastOwner bool `json:"is_last_owner"`
LastLoginAt *time.Time `json:"last_login_at"`
}
// ListBillableGroupMembersOptions represents the available ListBillableGroupMembers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-billable-members-of-a-group
type ListBillableGroupMembersOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListBillableGroupMembers Gets a list of group members that count as billable.
// The list includes members in the subgroup or subproject.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-billable-members-of-a-group
func (s *GroupsService) ListBillableGroupMembers(gid interface{}, 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
}
// RemoveBillableGroupMember removes a given group members that count as billable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#remove-a-billable-member-from-a-group
func (s *GroupsService) RemoveBillableGroupMember(gid interface{}, 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)
}
// AddGroupMember adds a user to the list of group members.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#add-a-member-to-a-group-or-project
func (s *GroupMembersService) AddGroupMember(gid interface{}, 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
}
// ShareWithGroup shares a group with the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#share-groups-with-groups
func (s *GroupMembersService) ShareWithGroup(gid interface{}, 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
}
// DeleteShareWithGroup allows to unshare a group from a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-link-sharing-group-with-another-group
func (s *GroupMembersService) DeleteShareWithGroup(gid interface{}, 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)
}
// EditGroupMemberOptions represents the available EditGroupMember()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#edit-a-member-of-a-group-or-project
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"`
}
// EditGroupMember updates a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#edit-a-member-of-a-group-or-project
func (s *GroupMembersService) EditGroupMember(gid interface{}, 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
}
// RemoveGroupMemberOptions represents the available options to remove a group member.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html#remove-a-member-from-a-group-or-project
type RemoveGroupMemberOptions struct {
SkipSubresources *bool `url:"skip_subresources,omitempty" json:"skip_subresources,omitempty"`
UnassignIssuables *bool `url:"unassign_issuables,omitempty" json:"unassign_issuables,omitempty"`
}
// RemoveGroupMember removes user from user team.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#remove-a-member-from-a-group-or-project
func (s *GroupMembersService) RemoveGroupMember(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupMilestonesService handles communication with the milestone related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_milestones.html
type GroupMilestonesService struct {
client *Client
}
// GroupMilestone represents a GitLab milestone.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_milestones.html
type GroupMilestone struct {
ID int `json:"id"`
IID int `json:"iid"`
GroupID int `json:"group_id"`
Title string `json:"title"`
Description string `json:"description"`
StartDate *ISOTime `json:"start_date"`
DueDate *ISOTime `json:"due_date"`
State string `json:"state"`
UpdatedAt *time.Time `json:"updated_at"`
CreatedAt *time.Time `json:"created_at"`
Expired *bool `json:"expired"`
}
func (m GroupMilestone) String() string {
return Stringify(m)
}
// ListGroupMilestonesOptions represents the available
// ListGroupMilestones() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#list-group-milestones
type ListGroupMilestonesOptions struct {
ListOptions
IIDs *[]int `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"`
IncludeParentMilestones *bool `url:"include_parent_milestones,omitempty" json:"include_parent_milestones,omitempty"`
}
// ListGroupMilestones returns a list of group milestones.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#list-group-milestones
func (s *GroupMilestonesService) ListGroupMilestones(gid interface{}, 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
}
// GetGroupMilestone gets a single group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-single-milestone
func (s *GroupMilestonesService) GetGroupMilestone(gid interface{}, 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
}
// CreateGroupMilestoneOptions represents the available CreateGroupMilestone() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#create-new-milestone
type CreateGroupMilestoneOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
}
// CreateGroupMilestone creates a new group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#create-new-milestone
func (s *GroupMilestonesService) CreateGroupMilestone(gid interface{}, 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
}
// UpdateGroupMilestoneOptions represents the available UpdateGroupMilestone() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#edit-milestone
type UpdateGroupMilestoneOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"`
}
// UpdateGroupMilestone updates an existing group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#edit-milestone
func (s *GroupMilestonesService) UpdateGroupMilestone(gid interface{}, 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
}
// DeleteGroupMilestone deletes a specified group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#delete-group-milestone
func (s *GroupMilestonesService) DeleteGroupMilestone(pid interface{}, 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)
}
// GetGroupMilestoneIssuesOptions represents the available GetGroupMilestoneIssues() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-issues-assigned-to-a-single-milestone
type GetGroupMilestoneIssuesOptions ListOptions
// GetGroupMilestoneIssues gets all issues assigned to a single group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-issues-assigned-to-a-single-milestone
func (s *GroupMilestonesService) GetGroupMilestoneIssues(gid interface{}, 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
}
// GetGroupMilestoneMergeRequestsOptions represents the available
// GetGroupMilestoneMergeRequests() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-merge-requests-assigned-to-a-single-milestone
type GetGroupMilestoneMergeRequestsOptions ListOptions
// GetGroupMilestoneMergeRequests gets all merge requests assigned to a
// single group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-merge-requests-assigned-to-a-single-milestone
func (s *GroupMilestonesService) GetGroupMilestoneMergeRequests(gid interface{}, milestone int, opt *GetGroupMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *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 []*MergeRequest
resp, err := s.client.Do(req, &mr)
if err != nil {
return nil, resp, err
}
return mr, resp, nil
}
// BurndownChartEvent reprensents a burnout chart event
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-burndown-chart-events-for-a-single-milestone
type BurndownChartEvent struct {
CreatedAt *time.Time `json:"created_at"`
Weight *int `json:"weight"`
Action *string `json:"action"`
}
// GetGroupMilestoneBurndownChartEventsOptions represents the available
// GetGroupMilestoneBurndownChartEventsOptions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-burndown-chart-events-for-a-single-milestone
type GetGroupMilestoneBurndownChartEventsOptions ListOptions
// GetGroupMilestoneBurndownChartEvents gets all merge requests assigned to a
// single group milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_milestones.html#get-all-burndown-chart-events-for-a-single-milestone
func (s *GroupMilestonesService) GetGroupMilestoneBurndownChartEvents(gid interface{}, 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
}
//
// Copyright 2023, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// GroupProtectedEnvironmentsService handles communication with the group-level
// protected environment methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html
type GroupProtectedEnvironmentsService struct {
client *Client
}
// GroupProtectedEnvironment represents a group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html
type GroupProtectedEnvironment struct {
Name string `json:"name"`
DeployAccessLevels []*GroupEnvironmentAccessDescription `json:"deploy_access_levels"`
RequiredApprovalCount int `json:"required_approval_count"`
ApprovalRules []*GroupEnvironmentApprovalRule `json:"approval_rules"`
}
// GroupEnvironmentAccessDescription represents the access decription for a
// group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html
type GroupEnvironmentAccessDescription struct {
ID int `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"`
}
// GroupEnvironmentApprovalRule represents the approval rules for a group-level
// protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#protect-a-single-environment
type GroupEnvironmentApprovalRule struct {
ID int `json:"id"`
UserID int `json:"user_id"`
GroupID int `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"`
}
// ListGroupProtectedEnvironmentsOptions represents the available
// ListGroupProtectedEnvironments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#list-group-level-protected-environments
type ListGroupProtectedEnvironmentsOptions ListOptions
// ListGroupProtectedEnvironments returns a list of protected environments from
// a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#list-group-level-protected-environments
func (s *GroupProtectedEnvironmentsService) ListGroupProtectedEnvironments(gid interface{}, 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
}
// GetGroupProtectedEnvironment returns a single group-level protected
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#get-a-single-protected-environment
func (s *GroupProtectedEnvironmentsService) GetGroupProtectedEnvironment(gid interface{}, 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
}
// ProtectGroupEnvironmentOptions represents the available
// ProtectGroupEnvironment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#protect-a-single-environment
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"`
ApprovalRules *[]*GroupEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"`
}
// GroupEnvironmentAccessOptions represents the options for an access decription
// for a group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#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"`
}
// GroupEnvironmentApprovalRuleOptions represents the approval rules for a
// group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#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"`
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"`
}
// ProtectGroupEnvironment protects a single group-level environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#protect-a-single-environment
func (s *GroupProtectedEnvironmentsService) ProtectGroupEnvironment(gid interface{}, 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
}
// UpdateGroupProtectedEnvironmentOptions represents the available
// UpdateGroupProtectedEnvironment() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#update-a-protected-environment
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"`
ApprovalRules *[]*UpdateGroupEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"`
}
// UpdateGroupEnvironmentAccessOptions represents the options for updates to the
// access decription for a group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#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"`
Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"`
}
// UpdateGroupEnvironmentApprovalRuleOptions represents the updates to the
// approval rules for a group-level protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#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"`
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"`
Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"`
}
// UpdateGroupProtectedEnvironment updates a single group-level protected
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#update-a-protected-environment
func (s *GroupProtectedEnvironmentsService) UpdateGroupProtectedEnvironment(gid interface{}, 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
}
// UnprotectGroupEnvironment unprotects the given protected group-level
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_protected_environments.html#unprotect-a-single-environment
func (s *GroupProtectedEnvironmentsService) UnprotectGroupEnvironment(gid interface{}, 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)
}
//
// Copyright 2023, Nick Westbury
//
// 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 (
"fmt"
"net/http"
"time"
)
// GroupRepositoryStorageMoveService handles communication with the
// group repositories related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html
type GroupRepositoryStorageMoveService struct {
client *Client
}
// GroupRepositoryStorageMove represents the status of a repository move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html
type GroupRepositoryStorageMove struct {
ID int `json:"id"`
CreatedAt *time.Time `json:"created_at"`
State string `json:"state"`
SourceStorageName string `json:"source_storage_name"`
DestinationStorageName string `json:"destination_storage_name"`
Group *RepositoryGroup `json:"group"`
}
type RepositoryGroup struct {
ID int `json:"id"`
Name string `json:"name"`
WebURL string `json:"web_url"`
}
// RetrieveAllGroupStorageMovesOptions represents the available
// RetrieveAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#retrieve-all-group-repository-storage-moves
type RetrieveAllGroupStorageMovesOptions ListOptions
// RetrieveAllStorageMoves retrieves all group repository storage moves
// accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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
}
// RetrieveAllStorageMovesForGroup retrieves all repository storage moves for
// a single group accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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
}
// GetStorageMove gets a single group repository storage move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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
}
// GetStorageMoveForGroup gets a single repository storage move for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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
}
// ScheduleStorageMoveForGroupOptions represents the available
// ScheduleStorageMoveForGroup() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#schedule-a-repository-storage-move-for-a-group
type ScheduleStorageMoveForGroupOptions struct {
DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"`
}
// ScheduleStorageMoveForGroup schedule a repository to be moved for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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
}
// ScheduleAllGroupStorageMovesOptions represents the available
// ScheduleAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#schedule-repository-storage-moves-for-all-groups-on-a-storage-shard
type ScheduleAllGroupStorageMovesOptions struct {
SourceStorageName *string `url:"source_storage_name,omitempty" json:"source_storage_name,omitempty"`
DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"`
}
// ScheduleAllStorageMoves schedules all group repositories to be moved.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_repository_storage_moves.html#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)
}
//
// Copyright 2023, James Hong
//
// 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 (
"fmt"
"net/http"
)
// GroupServiceAccount represents a GitLab service account user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#create-service-account-user
type GroupServiceAccount struct {
ID int `json:"id"`
Name string `json:"name"`
UserName string `json:"username"`
}
// CreateServiceAccount create a new service account user for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#create-service-account-user
func (s *GroupsService) CreateServiceAccount(gid interface{}, 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, nil, 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
}
// CreateServiceAccountPersonalAccessTokenOptions represents the available
// CreateServiceAccountPersonalAccessToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#create-personal-access-token-for-service-account-user
type CreateServiceAccountPersonalAccessTokenOptions struct {
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// CreateServiceAccountPersonalAccessToken add a new Personal Access Token for a
// service account user for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#create-personal-access-token-for-service-account-user
func (s *GroupsService) CreateServiceAccountPersonalAccessToken(gid interface{}, 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
}
// RotateServiceAccountPersonalAccessToken rotates a Personal Access Token for a
// service account user for a group.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#create-personal-access-token-for-service-account-user
func (s *GroupsService) RotateServiceAccountPersonalAccessToken(gid interface{}, serviceAccount, token int, 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, 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
}
package gitlab
import (
"fmt"
"net/http"
"time"
)
// GroupSSHCertificatesService handles communication with the group
// SSH certificate related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_ssh_certificates.html
type GroupSSHCertificatesService struct {
client *Client
}
// GroupSSHCertificate represents a GitLab Group SSH certificate.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/member_roles.html
type GroupSSHCertificate struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt *time.Time `json:"created_at"`
}
// ListGroupSSHCertificates gets a list of SSH certificates for a specified
// group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/group_ssh_certificates.html#get-all-ssh-certificates-for-a-particular-group
func (s *GroupSSHCertificatesService) ListGroupSSHCertificates(gid interface{}, 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
}
// CreateGroupSSHCertificateOptions represents the available
// CreateGroupSSHCertificate() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_ssh_certificates.html#create-ssh-certificate
type CreateGroupSSHCertificateOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
}
// CreateMemberRole creates a new member role for a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/group_ssh_certificates.html#create-ssh-certificate
func (s *GroupSSHCertificatesService) CreateGroupSSHCertificate(gid interface{}, 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
}
// DeleteGroupSSHCertificate deletes a SSH certificate from a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/group_ssh_certificates.html#delete-group-ssh-certificate
func (s *GroupSSHCertificatesService) DeleteGroupSSHCertificate(gid interface{}, 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)
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// GroupVariablesService handles communication with the
// group variables related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html
type GroupVariablesService struct {
client *Client
}
// GroupVariable represents a GitLab group Variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html
type GroupVariable struct {
Key string `json:"key"`
Value string `json:"value"`
VariableType VariableTypeValue `json:"variable_type"`
Protected bool `json:"protected"`
Masked bool `json:"masked"`
Raw bool `json:"raw"`
EnvironmentScope string `json:"environment_scope"`
Description string `json:"description"`
}
func (v GroupVariable) String() string {
return Stringify(v)
}
// ListGroupVariablesOptions represents the available options for listing variables
// for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#list-group-variables
type ListGroupVariablesOptions ListOptions
// ListVariables gets a list of all variables for a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#list-group-variables
func (s *GroupVariablesService) ListVariables(gid interface{}, 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
}
// GetVariable gets a variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#show-variable-details
func (s *GroupVariablesService) GetVariable(gid interface{}, key string, 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, nil, 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
}
// CreateGroupVariableOptions represents the available CreateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#create-variable
type CreateGroupVariableOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// CreateVariable creates a new group variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#create-variable
func (s *GroupVariablesService) CreateVariable(gid interface{}, 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
}
// UpdateGroupVariableOptions represents the available UpdateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#update-variable
type UpdateGroupVariableOptions struct {
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
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/ee/api/group_level_variables.html#update-variable
func (s *GroupVariablesService) UpdateVariable(gid interface{}, 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
}
// RemoveVariable removes a group's variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_level_variables.html#remove-variable
func (s *GroupVariablesService) RemoveVariable(gid interface{}, key string, 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, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Markus Lackner
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// GroupWikisService handles communication with the group wikis related methods of
// the Gitlab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_wikis.html
type GroupWikisService struct {
client *Client
}
// GroupWiki represents a GitLab groups wiki.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/group_wikis.html
type GroupWiki struct {
Content string `json:"content"`
Encoding string `json:"encoding"`
Format WikiFormatValue `json:"format"`
Slug string `json:"slug"`
Title string `json:"title"`
}
func (w GroupWiki) String() string {
return Stringify(w)
}
// ListGroupWikisOptions represents the available ListGroupWikis options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#list-wiki-pages
type ListGroupWikisOptions struct {
WithContent *bool `url:"with_content,omitempty" json:"with_content,omitempty"`
}
// ListGroupWikis lists all pages of the wiki of the given group id.
// When with_content is set, it also returns the content of the pages.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#list-wiki-pages
func (s *GroupWikisService) ListGroupWikis(gid interface{}, 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
}
// GetGroupWikiPageOptions represents options to GetGroupWikiPage
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#get-a-wiki-page
type GetGroupWikiPageOptions struct {
RenderHTML *bool `url:"render_html,omitempty" json:"render_html,omitempty"`
Version *string `url:"version,omitempty" json:"version,omitempty"`
}
// GetGroupWikiPage gets a wiki page for a given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#get-a-wiki-page
func (s *GroupWikisService) GetGroupWikiPage(gid interface{}, 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
}
// CreateGroupWikiPageOptions represents options to CreateGroupWikiPage.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#create-a-new-wiki-page
type CreateGroupWikiPageOptions struct {
Content *string `url:"content,omitempty" json:"content,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
Format *WikiFormatValue `url:"format,omitempty" json:"format,omitempty"`
}
// CreateGroupWikiPage creates a new wiki page for the given group with
// the given title, slug, and content.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#create-a-new-wiki-page
func (s *GroupWikisService) CreateGroupWikiPage(gid interface{}, 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
}
// EditGroupWikiPageOptions represents options to EditGroupWikiPage.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#edit-an-existing-wiki-page
type EditGroupWikiPageOptions struct {
Content *string `url:"content,omitempty" json:"content,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
Format *WikiFormatValue `url:"format,omitempty" json:"format,omitempty"`
}
// EditGroupWikiPage Updates an existing wiki page. At least one parameter is
// required to update the wiki page.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#edit-an-existing-wiki-page
func (s *GroupWikisService) EditGroupWikiPage(gid interface{}, 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
}
// DeleteGroupWikiPage deletes a wiki page with a given slug.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/group_wikis.html#delete-a-wiki-page
func (s *GroupWikisService) DeleteGroupWikiPage(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
retryablehttp "github.com/hashicorp/go-retryablehttp"
)
// GroupsService handles communication with the group related methods of
// the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html
type GroupsService struct {
client *Client
}
// Group represents a GitLab group.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html
type Group struct {
ID int `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"`
DefaultBranchProtectionDefaults struct {
AllowedToPush []*GroupAccessLevel `json:"allowed_to_push"`
AllowForcePush bool `json:"allow_force_push"`
AllowedToMerge []*GroupAccessLevel `json:"allowed_to_merge"`
DeveloperCanInitialPush bool `json:"developer_can_initial_push"`
} `json:"default_branch_protection_defaults"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
RequestAccessEnabled bool `json:"request_access_enabled"`
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"`
Projects []*Project `json:"projects"`
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"`
ProjectCreationLevel ProjectCreationLevelValue `json:"project_creation_level"`
AutoDevopsEnabled bool `json:"auto_devops_enabled"`
SubGroupCreationLevel SubGroupCreationLevelValue `json:"subgroup_creation_level"`
EmailsEnabled bool `json:"emails_enabled"`
MentionsDisabled bool `json:"mentions_disabled"`
RunnersToken string `json:"runners_token"`
SharedProjects []*Project `json:"shared_projects"`
SharedRunnersSetting SharedRunnersSettingValue `json:"shared_runners_setting"`
SharedWithGroups []struct {
GroupID int `json:"group_id"`
GroupName string `json:"group_name"`
GroupFullPath string `json:"group_full_path"`
GroupAccessLevel int `json:"group_access_level"`
ExpiresAt *ISOTime `json:"expires_at"`
} `json:"shared_with_groups"`
LDAPCN string `json:"ldap_cn"`
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"`
PreventForkingOutsideGroup bool `json:"prevent_forking_outside_group"`
MarkedForDeletionOn *ISOTime `json:"marked_for_deletion_on"`
CreatedAt *time.Time `json:"created_at"`
IPRestrictionRanges string `json:"ip_restriction_ranges"`
WikiAccessLevel AccessControlValue `json:"wiki_access_level"`
// Deprecated: Use EmailsEnabled instead
EmailsDisabled bool `json:"emails_disabled"`
// Deprecated: Use DefaultBranchProtectionDefaults instead
DefaultBranchProtection int `json:"default_branch_protection"`
}
// GroupAccessLevel represents default branch protection defaults access levels.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#options-for-default_branch_protection_defaults
type GroupAccessLevel struct {
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
}
// GroupAvatar represents a GitLab group avatar.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html
type GroupAvatar struct {
Filename string
Image io.Reader
}
// MarshalJSON implements the json.Marshaler interface.
func (a *GroupAvatar) MarshalJSON() ([]byte, error) {
if a.Filename == "" && a.Image == nil {
return []byte(`""`), nil
}
type alias GroupAvatar
return json.Marshal((*alias)(a))
}
// LDAPGroupLink represents a GitLab LDAP group link.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#ldap-group-links
type LDAPGroupLink struct {
CN string `json:"cn"`
Filter string `json:"filter"`
GroupAccess AccessLevelValue `json:"group_access"`
Provider string `json:"provider"`
}
// SAMLGroupLink represents a GitLab SAML group link.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#saml-group-links
type SAMLGroupLink struct {
Name string `json:"name"`
AccessLevel AccessLevelValue `json:"access_level"`
MemberRoleID int `json:"member_role_id,omitempty"`
}
// ListGroupsOptions represents the available ListGroups() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#list-groups
type ListGroupsOptions struct {
ListOptions
SkipGroups *[]int `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"`
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"`
}
// ListGroups gets a list of groups (as user: my groups, as admin: all groups).
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#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
}
// ListSubGroupsOptions represents the available ListSubGroups() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-subgroups
type ListSubGroupsOptions ListGroupsOptions
// ListSubGroups gets a list of subgroups for a given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-subgroups
func (s *GroupsService) ListSubGroups(gid interface{}, 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
}
// ListDescendantGroupsOptions represents the available ListDescendantGroups()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-descendant-groups
type ListDescendantGroupsOptions ListGroupsOptions
// ListDescendantGroups gets a list of subgroups for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-descendant-groups
func (s *GroupsService) ListDescendantGroups(gid interface{}, 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
}
// ListGroupProjectsOptions represents the available ListGroup() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-projects
type ListGroupProjectsOptions struct {
ListOptions
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"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Owned *bool `url:"owned,omitempty" json:"owned,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
Simple *bool `url:"simple,omitempty" json:"simple,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Starred *bool `url:"starred,omitempty" json:"starred,omitempty"`
Topic *string `url:"topic,omitempty" json:"topic,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
WithIssuesEnabled *bool `url:"with_issues_enabled,omitempty" json:"with_issues_enabled,omitempty"`
WithMergeRequestsEnabled *bool `url:"with_merge_requests_enabled,omitempty" json:"with_merge_requests_enabled,omitempty"`
WithSecurityReports *bool `url:"with_security_reports,omitempty" json:"with_security_reports,omitempty"`
WithShared *bool `url:"with_shared,omitempty" json:"with_shared,omitempty"`
}
// ListGroupProjects get a list of group projects
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-projects
func (s *GroupsService) ListGroupProjects(gid interface{}, 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
}
// GetGroupOptions represents the available GetGroup() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#details-of-a-group
type GetGroupOptions struct {
ListOptions
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
WithProjects *bool `url:"with_projects,omitempty" json:"with_projects,omitempty"`
}
// GetGroup gets all details of a group.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#details-of-a-group
func (s *GroupsService) GetGroup(gid interface{}, 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
}
// DownloadAvatar downloads a group avatar.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#download-a-group-avatar
func (s *GroupsService) DownloadAvatar(gid interface{}, 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)
if err != nil {
return nil, resp, err
}
return bytes.NewReader(avatar.Bytes()), resp, err
}
// CreateGroupOptions represents the available CreateGroup() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#new-group
type CreateGroupOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
Avatar *GroupAvatar `url:"-" json:"-"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
MembershipLock *bool `url:"membership_lock,omitempty" json:"membership_lock,omitempty"`
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"`
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"`
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"`
IPRestrictionRanges *string `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,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"`
}
// DefaultBranchProtectionDefaultsOptions represents the available options for
// using default_branch_protection_defaults in CreateGroup() or UpdateGroup()
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#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"`
}
// CreateGroup creates a new project group. Available only for users who can
// create groups.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#new-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 {
req, err = s.client.UploadRequest(
http.MethodPost,
"groups",
opt.Avatar.Image,
opt.Avatar.Filename,
UploadAvatar,
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
}
// TransferGroup transfers a project to the Group namespace. Available only
// for admin.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#transfer-project-to-group
func (s *GroupsService) TransferGroup(gid interface{}, pid interface{}, 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
}
// TransferSubGroupOptions represents the available TransferSubGroup() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#transfer-a-group-to-a-new-parent-group--turn-a-subgroup-to-a-top-level-group
type TransferSubGroupOptions struct {
GroupID *int `url:"group_id,omitempty" json:"group_id,omitempty"`
}
// TransferSubGroup transfers a group to a new parent group or turn a subgroup
// to a top-level group. Available to administrators and users.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#transfer-a-group-to-a-new-parent-group--turn-a-subgroup-to-a-top-level-group
func (s *GroupsService) TransferSubGroup(gid interface{}, 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
}
// UpdateGroupOptions represents the available UpdateGroup() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#update-group
type UpdateGroupOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
Avatar *GroupAvatar `url:"-" json:"avatar,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
MembershipLock *bool `url:"membership_lock,omitempty" json:"membership_lock,omitempty"`
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"`
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"`
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"`
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"`
IPRestrictionRanges *string `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,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: Use DefaultBranchProtectionDefaults instead
DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,omitempty"`
}
// UpdateGroup updates an existing group; only available to group owners and
// administrators.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#update-group
func (s *GroupsService) UpdateGroup(gid interface{}, opt *UpdateGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
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 {
req, err = s.client.UploadRequest(
http.MethodPut,
u,
opt.Avatar.Image,
opt.Avatar.Filename,
UploadAvatar,
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
}
// UploadAvatar uploads a group avatar.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#upload-a-group-avatar
func (s *GroupsService) UploadAvatar(gid interface{}, 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,
)
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.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#update-group
type DeleteGroupOptions struct {
PermanentlyRemove *bool `url:"permanently_remove,omitempty" json:"permanently_remove,omitempty"`
FullPath *string `url:"full_path,omitempty" json:"full_path,omitempty"`
}
// DeleteGroup removes group with all projects inside.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#remove-group
func (s *GroupsService) DeleteGroup(gid interface{}, 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)
}
// RestoreGroup restores a previously deleted group
//
// GitLap API docs:
// https://docs.gitlab.com/ee/api/groups.html#restore-group-marked-for-deletion
func (s *GroupsService) RestoreGroup(gid interface{}, 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
}
// SearchGroup get all groups that match your string in their name or path.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#search-for-group
func (s *GroupsService) SearchGroup(query string, options ...RequestOptionFunc) ([]*Group, *Response, error) {
var q struct {
Search string `url:"search,omitempty" json:"search,omitempty"`
}
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
}
// ListProvisionedUsersOptions represents the available ListProvisionedUsers()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-provisioned-users
type ListProvisionedUsersOptions struct {
ListOptions
Username *string `url:"username,omitempty" json:"username,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
Active *bool `url:"active,omitempty" json:"active,omitempty"`
Blocked *bool `url:"blocked,omitempty" json:"blocked,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
}
// ListProvisionedUsers gets a list of users provisioned by the given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-provisioned-users
func (s *GroupsService) ListProvisionedUsers(gid interface{}, 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
}
// ListGroupLDAPLinks lists the group's LDAP links. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-ldap-group-links
func (s *GroupsService) ListGroupLDAPLinks(gid interface{}, 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
}
// AddGroupLDAPLinkOptions represents the available AddGroupLDAPLink() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-ldap-group-link-with-cn-or-filter
type AddGroupLDAPLinkOptions struct {
CN *string `url:"cn,omitempty" json:"cn,omitempty"`
Filter *string `url:"filter,omitempty" json:"filter,omitempty"`
GroupAccess *AccessLevelValue `url:"group_access,omitempty" json:"group_access,omitempty"`
Provider *string `url:"provider,omitempty" json:"provider,omitempty"`
}
// DeleteGroupLDAPLinkWithCNOrFilterOptions represents the available DeleteGroupLDAPLinkWithCNOrFilter() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-ldap-group-link-with-cn-or-filter
type DeleteGroupLDAPLinkWithCNOrFilterOptions struct {
CN *string `url:"cn,omitempty" json:"cn,omitempty"`
Filter *string `url:"filter,omitempty" json:"filter,omitempty"`
Provider *string `url:"provider,omitempty" json:"provider,omitempty"`
}
// AddGroupLDAPLink creates a new group LDAP link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-ldap-group-link-with-cn-or-filter
func (s *GroupsService) AddGroupLDAPLink(gid interface{}, 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
}
// DeleteGroupLDAPLink deletes a group LDAP link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-ldap-group-link
func (s *GroupsService) DeleteGroupLDAPLink(gid interface{}, 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)
}
// DeleteGroupLDAPLinkWithCNOrFilter deletes a group LDAP link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-ldap-group-link-with-cn-or-filter
func (s *GroupsService) DeleteGroupLDAPLinkWithCNOrFilter(gid interface{}, 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)
}
// DeleteGroupLDAPLinkForProvider deletes a group LDAP link from a specific
// provider. Available only for users who can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-ldap-group-link
func (s *GroupsService) DeleteGroupLDAPLinkForProvider(gid interface{}, 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),
)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ListGroupSAMLLinks lists the group's SAML links. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#list-saml-group-links
func (s *GroupsService) ListGroupSAMLLinks(gid interface{}, 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
}
// GetGroupSAMLLink get a specific group SAML link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#get-saml-group-link
func (s *GroupsService) GetGroupSAMLLink(gid interface{}, 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
}
// AddGroupSAMLLinkOptions represents the available AddGroupSAMLLink() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-saml-group-link
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"`
}
// AddGroupSAMLLink creates a new group SAML link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-saml-group-link
func (s *GroupsService) AddGroupSAMLLink(gid interface{}, 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
}
// DeleteGroupSAMLLink deletes a group SAML link. Available only for users who
// can edit groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-saml-group-link
func (s *GroupsService) DeleteGroupSAMLLink(gid interface{}, 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)
}
// ShareGroupWithGroupOptions represents the available ShareGroupWithGroup() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#share-groups-with-groups
type ShareGroupWithGroupOptions struct {
GroupID *int `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"`
}
// ShareGroupWithGroup shares a group with another group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#create-a-link-to-share-a-group-with-another-group
func (s *GroupsService) ShareGroupWithGroup(gid interface{}, 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
}
// UnshareGroupFromGroup unshares a group from another group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-link-sharing-group-with-another-group
func (s *GroupsService) UnshareGroupFromGroup(gid interface{}, 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)
}
// GroupPushRules represents a group push rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#get-group-push-rules
type GroupPushRules struct {
ID int `json:"id"`
CreatedAt *time.Time `json:"created_at"`
CommitMessageRegex string `json:"commit_message_regex"`
CommitMessageNegativeRegex string `json:"commit_message_negative_regex"`
BranchNameRegex string `json:"branch_name_regex"`
DenyDeleteTag bool `json:"deny_delete_tag"`
MemberCheck bool `json:"member_check"`
PreventSecrets bool `json:"prevent_secrets"`
AuthorEmailRegex string `json:"author_email_regex"`
FileNameRegex string `json:"file_name_regex"`
MaxFileSize int `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"`
}
// GetGroupPushRules gets the push rules of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#get-group-push-rules
func (s *GroupsService) GetGroupPushRules(gid interface{}, 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
}
// AddGroupPushRuleOptions represents the available AddGroupPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-group-push-rule
type AddGroupPushRuleOptions struct {
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
CommitCommitterNameCheck *bool `url:"commit_committer_name_check,omitempty" json:"commit_committer_name_check,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
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"`
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"`
}
// AddGroupPushRule adds push rules to the specified group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#add-group-push-rule
func (s *GroupsService) AddGroupPushRule(gid interface{}, 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
}
// EditGroupPushRuleOptions represents the available EditGroupPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#edit-group-push-rule
type EditGroupPushRuleOptions struct {
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
CommitCommitterNameCheck *bool `url:"commit_committer_name_check,omitempty" json:"commit_committer_name_check,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
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"`
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"`
}
// EditGroupPushRule edits a push rule for a specified group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#edit-group-push-rule
func (s *GroupsService) EditGroupPushRule(gid interface{}, 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
}
// DeleteGroupPushRule deletes the push rules of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#delete-group-push-rule
func (s *GroupsService) DeleteGroupPushRule(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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"
)
// ImportService handles communication with the import
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html
type ImportService struct {
client *Client
}
// GitHubImport represents the response from an import from GitHub.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-repository-from-github
type GitHubImport struct {
ID int `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
FullName string `json:"full_name"`
RefsUrl string `json:"refs_url"`
ImportSource string `json:"import_source"`
ImportStatus string `json:"import_status"`
HumanImportStatusName string `json:"human_import_status_name"`
ProviderLink string `json:"provider_link"`
RelationType string `json:"relation_type"`
ImportWarning string `json:"import_warning"`
}
func (s GitHubImport) String() string {
return Stringify(s)
}
// ImportRepositoryFromGitHubOptions represents the available
// ImportRepositoryFromGitHub() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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"`
}
// Import a repository from GitHub.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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
}
// CancelledGitHubImport represents the response when canceling
// an import from GitHub.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#cancel-github-project-import
type CancelledGitHubImport struct {
ID int `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
FullName string `json:"full_name"`
ImportSource string `json:"import_source"`
ImportStatus string `json:"import_status"`
HumanImportStatusName string `json:"human_import_status_name"`
ProviderLink string `json:"provider_link"`
}
func (s CancelledGitHubImport) String() string {
return Stringify(s)
}
// CancelGitHubProjectImportOptions represents the available
// CancelGitHubProjectImport() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#cancel-github-project-import
type CancelGitHubProjectImportOptions struct {
ProjectID *int `url:"project_id,omitempty" json:"project_id,omitempty"`
}
// Cancel an import of a repository from GitHub.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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
}
// ImportGitHubGistsIntoGitLabSnippetsOptions represents the available
// ImportGitHubGistsIntoGitLabSnippets() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-github-gists-into-gitlab-snippets
type ImportGitHubGistsIntoGitLabSnippetsOptions struct {
PersonalAccessToken *string `url:"personal_access_token,omitempty" json:"personal_access_token,omitempty"`
}
// Import personal GitHub Gists into personal GitLab Snippets.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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)
}
// BitbucketServerImport represents the response from an import from Bitbucket
// Server.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-repository-from-bitbucket-server
type BitbucketServerImport struct {
ID int `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
FullName string `json:"full_name"`
RefsUrl string `json:"refs_url"`
}
func (s BitbucketServerImport) String() string {
return Stringify(s)
}
// ImportRepositoryFromBitbucketServerOptions represents the available ImportRepositoryFromBitbucketServer() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-repository-from-bitbucket-server
type ImportRepositoryFromBitbucketServerOptions struct {
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"`
BitbucketServerRepo *string `url:"bitbucket_server_repo,omitempty" json:"bitbucket_server_repo,omitempty"`
NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"`
NewNamespace *string `url:"new_namespace,omitempty" json:"new_namespace,omitempty"`
TimeoutStrategy *string `url:"timeout_strategy,omitempty" json:"timeout_strategy,omitempty"`
}
// Import a repository from Bitbucket Server.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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
}
// BitbucketCloudImport represents the response from an import from Bitbucket
// Cloud.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-repository-from-bitbucket-cloud
type BitbucketCloudImport struct {
ID int `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
FullName string `json:"full_name"`
RefsUrl string `json:"refs_url"`
ImportSource string `json:"import_source"`
ImportStatus string `json:"import_status"`
HumanImportStatusName string `json:"human_import_status_name"`
ProviderLink string `json:"provider_link"`
RelationType string `json:"relation_type"`
ImportWarning string `json:"import_warning"`
}
func (s BitbucketCloudImport) String() string {
return Stringify(s)
}
// ImportRepositoryFromBitbucketCloudOptions represents the available
// ImportRepositoryFromBitbucketCloud() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#import-repository-from-bitbucket-cloud
type ImportRepositoryFromBitbucketCloudOptions struct {
BitbucketUsername *string `url:"bitbucket_username,omitempty" json:"bitbucket_username,omitempty"`
BitbucketAppPassword *string `url:"bitbucket_app_password,omitempty" json:"bitbucket_app_password,omitempty"`
RepoPath *string `url:"repo_path,omitempty" json:"repo_path,omitempty"`
TargetNamespace *string `url:"target_namespace,omitempty" json:"target_namespace,omitempty"`
NewName *string `url:"new_name,omitempty" json:"new_name,omitempty"`
}
// Import a repository from Bitbucket Cloud.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/import.html#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
}
//
// Copyright 2021, Serena Fang
//
// 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 (
"fmt"
"net/http"
"time"
)
// InstanceClustersService handles communication with the
// instance clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html
type InstanceClustersService struct {
client *Client
}
// InstanceCluster represents a GitLab Instance Cluster.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/instance_clusters.html
type InstanceCluster struct {
ID int `json:"id"`
Name string `json:"name"`
Domain string `json:"domain"`
Managed bool `json:"managed"`
CreatedAt *time.Time `json:"created_at"`
ProviderType string `json:"provider_type"`
PlatformType string `json:"platform_type"`
EnvironmentScope string `json:"environment_scope"`
ClusterType string `json:"cluster_type"`
User *User `json:"user"`
PlatformKubernetes *PlatformKubernetes `json:"platform_kubernetes"`
ManagementProject *ManagementProject `json:"management_project"`
}
func (v InstanceCluster) String() string {
return Stringify(v)
}
// ListClusters gets a list of all instance clusters.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html#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
}
// GetCluster gets an instance cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html#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
}
// AddCluster adds an existing cluster to the instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html#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
}
// EditCluster updates an existing instance cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html#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
}
// DeleteCluster deletes an existing instance cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_clusters.html#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)
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// InstanceVariablesService handles communication with the
// instance level CI variables related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html
type InstanceVariablesService struct {
client *Client
}
// InstanceVariable represents a GitLab instance level CI Variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html
type InstanceVariable struct {
Key string `json:"key"`
Value string `json:"value"`
VariableType VariableTypeValue `json:"variable_type"`
Protected bool `json:"protected"`
Masked bool `json:"masked"`
Raw bool `json:"raw"`
Description string `json:"description"`
}
func (v InstanceVariable) String() string {
return Stringify(v)
}
// ListInstanceVariablesOptions represents the available options for listing variables
// for an instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#list-all-instance-variables
type ListInstanceVariablesOptions ListOptions
// ListVariables gets a list of all variables for an instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#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
}
// GetVariable gets a variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#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
}
// CreateInstanceVariableOptions represents the available CreateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#create-instance-variable
type CreateInstanceVariableOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
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/ee/api/instance_level_ci_variables.html#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
}
// UpdateInstanceVariableOptions represents the available UpdateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#update-instance-variable
type UpdateInstanceVariableOptions struct {
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
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/ee/api/instance_level_ci_variables.html#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
}
// RemoveVariable removes an instance level CI variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/instance_level_ci_variables.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// InvitesService handles communication with the invitation related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/invitations.html
type InvitesService struct {
client *Client
}
// PendingInvite represents a pending invite.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/invitations.html
type PendingInvite struct {
ID int `json:"id"`
InviteEmail string `json:"invite_email"`
CreatedAt *time.Time `json:"created_at"`
AccessLevel AccessLevelValue `json:"access_level"`
ExpiresAt *time.Time `json:"expires_at"`
UserName string `json:"user_name"`
CreatedByName string `json:"created_by_name"`
}
// ListPendingInvitationsOptions represents the available
// ListPendingInvitations() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#list-all-invitations-pending-for-a-group-or-project
type ListPendingInvitationsOptions struct {
ListOptions
Query *string `url:"query,omitempty" json:"query,omitempty"`
}
// ListPendingGroupInvitations gets a list of invited group members.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#list-all-invitations-pending-for-a-group-or-project
func (s *InvitesService) ListPendingGroupInvitations(gid interface{}, 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
}
// ListPendingProjectInvitations gets a list of invited project members.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#list-all-invitations-pending-for-a-group-or-project
func (s *InvitesService) ListPendingProjectInvitations(pid interface{}, 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
}
// InvitesOptions represents the available GroupInvites() and ProjectInvites()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#add-a-member-to-a-group-or-project
type InvitesOptions struct {
ID interface{} `url:"id,omitempty" json:"id,omitempty"`
Email *string `url:"email,omitempty" json:"email,omitempty"`
UserID interface{} `url:"user_id,omitempty" json:"user_id,omitempty"`
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// InvitesResult represents an invitations result.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#add-a-member-to-a-group-or-project
type InvitesResult struct {
Status string `json:"status"`
Message map[string]string `json:"message,omitempty"`
}
// GroupInvites invites new users by email to join a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#add-a-member-to-a-group-or-project
func (s *InvitesService) GroupInvites(gid interface{}, 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
}
// ProjectInvites invites new users by email to join a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/invitations.html#add-a-member-to-a-group-or-project
func (s *InvitesService) ProjectInvites(pid interface{}, 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
}
//
// Copyright 2021, Arkbriar
//
// 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 (
"fmt"
"net/http"
"time"
)
// IssueLinksService handles communication with the issue relations related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html
type IssueLinksService struct {
client *Client
}
// IssueLink represents a two-way relation between two issues.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html
type IssueLink struct {
SourceIssue *Issue `json:"source_issue"`
TargetIssue *Issue `json:"target_issue"`
LinkType string `json:"link_type"`
}
// IssueRelation gets a relation between two issues.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issue_links.html#list-issue-relations
type IssueRelation struct {
ID int `json:"id"`
IID int `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"`
Assignees []*IssueAssignee `json:"assignees"`
Assignee *IssueAssignee `json:"assignee"`
UpdatedAt *time.Time `json:"updated_at"`
Title string `json:"title"`
CreatedAt *time.Time `json:"created_at"`
Labels Labels `json:"labels"`
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"`
LinkType string `json:"link_type"`
LinkCreatedAt *time.Time `json:"link_created_at"`
LinkUpdatedAt *time.Time `json:"link_updated_at"`
}
// ListIssueRelations gets a list of related issues of a given issue,
// sorted by the relationship creation datetime (ascending).
//
// Issues will be filtered according to the user authorizations.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issue_links.html#list-issue-relations
func (s *IssueLinksService) ListIssueRelations(pid interface{}, 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
}
// GetIssueLink gets a specific issue link.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issue_links.html#get-an-issue-link
func (s *IssueLinksService) GetIssueLink(pid interface{}, 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
}
// CreateIssueLinkOptions represents the available CreateIssueLink() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html#create-an-issue-link
type CreateIssueLinkOptions struct {
TargetProjectID *string `json:"target_project_id"`
TargetIssueIID *string `json:"target_issue_iid"`
LinkType *string `json:"link_type"`
}
// CreateIssueLink creates a two-way relation between two issues.
// User must be allowed to update both issues in order to succeed.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issue_links.html#create-an-issue-link
func (s *IssueLinksService) CreateIssueLink(pid interface{}, 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
}
// DeleteIssueLink deletes an issue link, thus removes the two-way relationship.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issue_links.html#delete-an-issue-link
func (s *IssueLinksService) DeleteIssueLink(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"net/http"
"reflect"
"time"
)
// IssuesService handles communication with the issue related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html
type IssuesService struct {
client *Client
timeStats *timeStatsService
}
// IssueAuthor represents a author of the issue.
type IssueAuthor struct {
ID int `json:"id"`
State string `json:"state"`
WebURL string `json:"web_url"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
Username string `json:"username"`
}
// IssueAssignee represents a assignee of the issue.
type IssueAssignee struct {
ID int `json:"id"`
State string `json:"state"`
WebURL string `json:"web_url"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
Username string `json:"username"`
}
// IssueReferences represents references of the issue.
type IssueReferences struct {
Short string `json:"short"`
Relative string `json:"relative"`
Full string `json:"full"`
}
// IssueCloser represents a closer of the issue.
type IssueCloser struct {
ID int `json:"id"`
State string `json:"state"`
WebURL string `json:"web_url"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
Username string `json:"username"`
}
// IssueLinks represents links of the issue.
type IssueLinks struct {
Self string `json:"self"`
Notes string `json:"notes"`
AwardEmoji string `json:"award_emoji"`
Project string `json:"project"`
}
// Issue represents a GitLab issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html
type Issue struct {
ID int `json:"id"`
IID int `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"`
Assignees []*IssueAssignee `json:"assignees"`
Assignee *IssueAssignee `json:"assignee"`
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"`
Labels Labels `json:"labels"`
LabelDetails []*LabelDetails `json:"label_details"`
Upvotes int `json:"upvotes"`
Downvotes int `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"`
DiscussionLocked bool `json:"discussion_locked"`
IssueType *string `json:"issue_type,omitempty"`
Subscribed bool `json:"subscribed"`
UserNotesCount int `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"`
Epic *Epic `json:"epic"`
Iteration *GroupIteration `json:"iteration"`
TaskCompletionStatus *TasksCompletionStatus `json:"task_completion_status"`
}
func (i Issue) String() string {
return Stringify(i)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (i *Issue) UnmarshalJSON(data []byte) error {
type alias Issue
raw := make(map[string]interface{})
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
if reflect.TypeOf(raw["id"]).Kind() == reflect.String {
raw["external_id"] = raw["id"]
delete(raw, "id")
}
labelDetails, ok := raw["labels"].([]interface{})
if ok && len(labelDetails) > 0 {
// We only want to change anything if we got label details.
if _, ok := labelDetails[0].(map[string]interface{}); ok {
labels := make([]interface{}, len(labelDetails))
for i, details := range labelDetails {
labels[i] = details.(map[string]interface{})["name"]
}
// Set the correct values
raw["labels"] = labels
raw["label_details"] = labelDetails
}
}
data, err = json.Marshal(raw)
if err != nil {
return err
}
return json.Unmarshal(data, (*alias)(i))
}
// LabelDetails represents detailed label information.
type LabelDetails struct {
ID int `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Description string `json:"description"`
DescriptionHTML string `json:"description_html"`
TextColor string `json:"text_color"`
}
// ListIssuesOptions represents the available ListIssues() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#list-issues
type ListIssuesOptions struct {
ListOptions
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 *AssigneeIDValue `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"`
IIDs *[]int `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"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
NotSearch *string `url:"not[search],omitempty" json:"not[search],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"`
}
// ListIssues gets all issues created by authenticated user. This function
// takes pagination parameters page and per_page to restrict the list of issues.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#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
}
// ListGroupIssuesOptions represents the available ListGroupIssues() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#list-group-issues
type ListGroupIssuesOptions struct {
ListOptions
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"`
IIDs *[]int `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"`
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"`
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"`
NotSearch *string `url:"not[search],omitempty" json:"not[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"`
IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"`
IterationID *int `url:"iteration_id,omitempty" json:"iteration_id,omitempty"`
}
// ListGroupIssues gets a list of group issues. This function accepts
// pagination parameters page and per_page to return the list of group issues.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#list-group-issues
func (s *IssuesService) ListGroupIssues(pid interface{}, 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
}
// ListProjectIssuesOptions represents the available ListProjectIssues() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#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 *AssigneeIDValue `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"`
}
// ListProjectIssues gets a list of project issues. This function accepts
// pagination parameters page and per_page to return the list of project issues.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#list-project-issues
func (s *IssuesService) ListProjectIssues(pid interface{}, 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
}
// GetIssueByID gets a single issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#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
}
// GetIssue gets a single project issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#single-project-issue
func (s *IssuesService) GetIssue(pid interface{}, 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
}
// CreateIssueOptions represents the available CreateIssue() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#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"`
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"`
DiscussionToResolve *string `url:"discussion_to_resolve,omitempty" json:"discussion_to_resolve,omitempty"`
Weight *int `url:"weight,omitempty" json:"weight,omitempty"`
IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"`
}
// CreateIssue creates a new project issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#new-issue
func (s *IssuesService) CreateIssue(pid interface{}, 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
}
// UpdateIssueOptions represents the available UpdateIssue() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#edit-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"`
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"`
DiscussionLocked *bool `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"`
IssueType *string `url:"issue_type,omitempty" json:"issue_type,omitempty"`
}
// UpdateIssue updates an existing project issue. This function is also used
// to mark an issue as closed.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#edit-issues
func (s *IssuesService) UpdateIssue(pid interface{}, 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
}
// DeleteIssue deletes a single project issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#delete-an-issue
func (s *IssuesService) DeleteIssue(pid interface{}, 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)
}
// ReorderIssueOptions represents the available ReorderIssue() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#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"`
}
// ReorderIssue reorders an issue.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#reorder-an-issue
func (s *IssuesService) ReorderIssue(pid interface{}, 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
}
// MoveIssueOptions represents the available MoveIssue() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues.html#move-an-issue
type MoveIssueOptions struct {
ToProjectID *int `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/ee/api/issues.html#move-an-issue
func (s *IssuesService) MoveIssue(pid interface{}, 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
}
// SubscribeToIssue subscribes the authenticated user to the given issue to
// receive notifications. If the user is already subscribed to the issue, the
// status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#subscribe-to-an-issue
func (s *IssuesService) SubscribeToIssue(pid interface{}, 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
}
// UnsubscribeFromIssue unsubscribes the authenticated user from the given
// issue to not receive notifications from that merge request. If the user
// is not subscribed to the issue, status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#unsubscribe-from-an-issue
func (s *IssuesService) UnsubscribeFromIssue(pid interface{}, 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
}
// CreateTodo creates a todo for the current user for an issue.
// If there already exists a todo for the user on that issue, status code
// 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#create-a-to-do-item
func (s *IssuesService) CreateTodo(pid interface{}, 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
}
// ListMergeRequestsClosingIssueOptions represents the available
// ListMergeRequestsClosingIssue() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#list-merge-requests-that-close-a-particular-issue-on-merge
type ListMergeRequestsClosingIssueOptions ListOptions
// ListMergeRequestsClosingIssue gets all the merge requests that will close
// issue when merged.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#list-merge-requests-that-close-a-particular-issue-on-merge
func (s *IssuesService) ListMergeRequestsClosingIssue(pid interface{}, issue int, opt *ListMergeRequestsClosingIssueOptions, options ...RequestOptionFunc) ([]*MergeRequest, *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 []*MergeRequest
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListMergeRequestsRelatedToIssueOptions represents the available
// ListMergeRequestsRelatedToIssue() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#list-merge-requests-related-to-issue
type ListMergeRequestsRelatedToIssueOptions ListOptions
// ListMergeRequestsRelatedToIssue gets all the merge requests that are
// related to the issue
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#list-merge-requests-related-to-issue
func (s *IssuesService) ListMergeRequestsRelatedToIssue(pid interface{}, issue int, opt *ListMergeRequestsRelatedToIssueOptions, options ...RequestOptionFunc) ([]*MergeRequest, *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,
)
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var m []*MergeRequest
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/ee/api/issues.html#set-a-time-estimate-for-an-issue
func (s *IssuesService) SetTimeEstimate(pid interface{}, issue int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.setTimeEstimate(pid, "issues", issue, opt, options...)
}
// ResetTimeEstimate resets the time estimate for a single project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#reset-the-time-estimate-for-an-issue
func (s *IssuesService) ResetTimeEstimate(pid interface{}, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.resetTimeEstimate(pid, "issues", issue, options...)
}
// AddSpentTime adds spent time for a single project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#add-spent-time-for-an-issue
func (s *IssuesService) AddSpentTime(pid interface{}, issue int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.addSpentTime(pid, "issues", issue, opt, options...)
}
// ResetSpentTime resets the spent time for a single project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#reset-spent-time-for-an-issue
func (s *IssuesService) ResetSpentTime(pid interface{}, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.resetSpentTime(pid, "issues", issue, options...)
}
// GetTimeSpent gets the spent time for a single project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#get-time-tracking-stats
func (s *IssuesService) GetTimeSpent(pid interface{}, issue int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.getTimeSpent(pid, "issues", issue, options...)
}
// GetParticipants gets a list of issue participants.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues.html#participants-on-issues
func (s *IssuesService) GetParticipants(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// IssuesStatisticsService handles communication with the issues statistics
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues_statistics.html
type IssuesStatisticsService struct {
client *Client
}
// IssuesStatistics represents a GitLab issues statistic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/issues_statistics.html
type IssuesStatistics struct {
Statistics struct {
Counts struct {
All int `json:"all"`
Closed int `json:"closed"`
Opened int `json:"opened"`
} `json:"counts"`
} `json:"statistics"`
}
func (n IssuesStatistics) String() string {
return Stringify(n)
}
// GetIssuesStatisticsOptions represents the available GetIssuesStatistics() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
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"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `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"`
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"`
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"`
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/ee/api/issues_statistics.html#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
}
// GetGroupIssuesStatisticsOptions represents the available GetGroupIssuesStatistics()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues_statistics.html#get-group-issues-statistics
type GetGroupIssuesStatisticsOptions struct {
Labels *LabelOptions `url:"labels,omitempty" json:"labels,omitempty"`
IIDs *[]int `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"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `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"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"`
}
// GetGroupIssuesStatistics gets issues count statistics for given group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues_statistics.html#get-group-issues-statistics
func (s *IssuesStatisticsService) GetGroupIssuesStatistics(gid interface{}, 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
}
// GetProjectIssuesStatisticsOptions represents the available
// GetProjectIssuesStatistics() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues_statistics.html#get-project-issues-statistics
type GetProjectIssuesStatisticsOptions struct {
IIDs *[]int `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"`
AuthorUsername *string `url:"author_username,omitempty" json:"author_username,omitempty"`
AssigneeID *int `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"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
Confidential *bool `url:"confidential,omitempty" json:"confidential,omitempty"`
}
// GetProjectIssuesStatistics gets issues count statistics for given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/issues_statistics.html#get-project-issues-statistics
func (s *IssuesStatisticsService) GetProjectIssuesStatistics(pid interface{}, 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
}
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// JobTokenScopeService handles communication with project CI settings
// such as token permissions.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html
type JobTokenScopeService struct {
client *Client
}
// JobTokenAccessSettings represents job token access attributes for this project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html
type JobTokenAccessSettings struct {
InboundEnabled bool `json:"inbound_enabled"`
OutboundEnabled bool `json:"outbound_enabled"`
}
// GetProjectJobTokenAccessSettings fetch the CI/CD job token access settings (job token scope) of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-access-settings
func (j *JobTokenScopeService) GetProjectJobTokenAccessSettings(pid interface{}, 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
}
// PatchProjectJobTokenAccessSettingsOptions represents the available
// PatchProjectJobTokenAccessSettings() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#patch-a-projects-cicd-job-token-access-settings
type PatchProjectJobTokenAccessSettingsOptions struct {
Enabled bool `json:"enabled"`
}
// PatchProjectJobTokenAccessSettings patch the Limit access to this project setting (job token scope) of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#patch-a-projects-cicd-job-token-access-settings
func (j *JobTokenScopeService) PatchProjectJobTokenAccessSettings(pid interface{}, 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)
}
// JobTokenInboundAllowItem represents a single job token inbound allowlist item.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html
type JobTokenInboundAllowItem struct {
SourceProjectID int `json:"source_project_id"`
TargetProjectID int `json:"target_project_id"`
}
// GetJobTokenInboundAllowListOptions represents the available
// GetJobTokenInboundAllowList() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist
type GetJobTokenInboundAllowListOptions struct {
ListOptions
}
// GetProjectJobTokenInboundAllowList fetches the CI/CD job token inbound
// allowlist (job token scope) of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist
func (j *JobTokenScopeService) GetProjectJobTokenInboundAllowList(pid interface{}, 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
}
// AddProjectToJobScopeAllowListOptions represents the available
// AddProjectToJobScopeAllowList() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#create-a-new-project-to-a-projects-cicd-job-token-inbound-allowlist
type JobTokenInboundAllowOptions struct {
TargetProjectID *int `url:"target_project_id,omitempty" json:"target_project_id,omitempty"`
}
// AddProjectToJobScopeAllowList adds a new project to a project's job token
// inbound allow list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#create-a-new-project-to-a-projects-cicd-job-token-inbound-allowlist
func (j *JobTokenScopeService) AddProjectToJobScopeAllowList(pid interface{}, 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
}
// RemoveProjectFromJobScopeAllowList removes a project from a project's job
// token inbound allow list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#remove-a-project-from-a-projects-cicd-job-token-inbound-allowlist
func (j *JobTokenScopeService) RemoveProjectFromJobScopeAllowList(pid interface{}, 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)
}
// JobTokenAllowlistItem represents a single job token allowlist item.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_job_token_scopes.html
type JobTokenAllowlistItem struct {
SourceProjectID int `json:"source_project_id"`
TargetGroupID int `json:"target_group_id"`
}
// GetJobTokenAllowlistGroupsOptions represents the available
// GetJobTokenAllowlistGroups() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups
type GetJobTokenAllowlistGroupsOptions struct {
ListOptions
}
// GetJobTokenAllowListGroups fetches the CI/CD job token allowlist groups
// (job token scopes) of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups
func (j *JobTokenScopeService) GetJobTokenAllowlistGroups(pid interface{}, 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
}
// AddGroupToJobTokenAllowlistOptions represents the available
// AddGroupToJobTokenAllowlist() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist
type AddGroupToJobTokenAllowlistOptions struct {
TargetGroupID *int `url:"target_group_id,omitempty" json:"target_group_id,omitempty"`
}
// AddProjectToJobScopeGroupsAllowList adds a new group to a project's job token
// inbound groups allow list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#add-a-group-to-a-cicd-job-token-allowlist
func (j *JobTokenScopeService) AddGroupToJobTokenAllowlist(pid interface{}, 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
}
// RemoveGroupFromJopTokenAllowlist removes a group from a project's job
// token inbound groups allow list.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_job_token_scopes.html#remove-a-group-from-a-cicd-job-token-allowlist
func (j *JobTokenScopeService) RemoveGroupFromJobTokenAllowlist(pid interface{}, 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)
}
//
// Copyright 2021, Arkbriar
//
// 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 (
"bytes"
"fmt"
"net/http"
"time"
)
// JobsService handles communication with the ci builds related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/jobs.html
type JobsService struct {
client *Client
}
// Job represents a ci build.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/jobs.html
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"`
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"`
}
// Bridge represents a pipeline bridge.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-bridges
type Bridge 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"`
ID int `json:"id"`
Name string `json:"name"`
Pipeline PipelineInfo `json:"pipeline"`
Ref string `json:"ref"`
Stage string `json:"stage"`
Status string `json:"status"`
FailureReason string `json:"failure_reason"`
Tag bool `json:"tag"`
WebURL string `json:"web_url"`
User *User `json:"user"`
DownstreamPipeline *PipelineInfo `json:"downstream_pipeline"`
}
// ListJobsOptions represents the available ListProjectJobs() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#list-project-jobs
type ListJobsOptions struct {
ListOptions
Scope *[]BuildStateValue `url:"scope[],omitempty" json:"scope,omitempty"`
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/ee/api/jobs.html#list-project-jobs
func (s *JobsService) ListProjectJobs(pid interface{}, 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
}
// 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/ee/api/jobs.html#list-pipeline-jobs
func (s *JobsService) ListPipelineJobs(pid interface{}, 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
}
// ListPipelineBridges gets a list of bridges for specific pipeline in a
// project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-jobs
func (s *JobsService) ListPipelineBridges(pid interface{}, 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
}
// GetJobTokensJobOptions represents the available GetJobTokensJob() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/jobs.html#get-job-tokens-job
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/ee/api/jobs.html#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
}
// GetJob gets a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#get-a-single-job
func (s *JobsService) GetJob(pid interface{}, 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
}
// GetJobArtifacts get jobs artifacts of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#get-job-artifacts
func (s *JobsService) GetJobArtifacts(pid interface{}, 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
}
return bytes.NewReader(artifactsBuf.Bytes()), resp, err
}
// DownloadArtifactsFileOptions represents the available DownloadArtifactsFile()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#download-the-artifacts-archive
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/ee/api/job_artifacts.html#download-the-artifacts-archive
func (s *JobsService) DownloadArtifactsFile(pid interface{}, 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
}
return bytes.NewReader(artifactsBuf.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/ee/api/job_artifacts.html#download-a-single-artifact-file-by-job-id
func (s *JobsService) DownloadSingleArtifactsFile(pid interface{}, 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,
)
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
}
// DownloadSingleArtifactsFile download a single artifact file for a specific
// job of the latest successful pipeline for the given reference name from
// inside the job’s artifacts archive. The file is extracted from the archive
// and streamed to the client.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#download-a-single-artifact-file-from-specific-tag-or-branch
func (s *JobsService) DownloadSingleArtifactsFileByTagOrBranch(pid interface{}, 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,
)
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
}
// GetTraceFile gets a trace of a specific job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#get-a-log-file
func (s *JobsService) GetTraceFile(pid interface{}, 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
}
return bytes.NewReader(traceBuf.Bytes()), resp, err
}
// CancelJob cancels a single job of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#cancel-a-job
func (s *JobsService) CancelJob(pid interface{}, 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
}
// RetryJob retries a single job of a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#retry-a-job
func (s *JobsService) RetryJob(pid interface{}, 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
}
// EraseJob erases a single job of a project, removes a job
// artifacts and a job trace.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#erase-a-job
func (s *JobsService) EraseJob(pid interface{}, 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
}
// KeepArtifacts prevents artifacts from being deleted when
// expiration is set.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#keep-artifacts
func (s *JobsService) KeepArtifacts(pid interface{}, 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
}
// PlayJobOptions represents the available PlayJob() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#run-a-job
type PlayJobOptions struct {
JobVariablesAttributes *[]*JobVariableOptions `url:"job_variables_attributes,omitempty" json:"job_variables_attributes,omitempty"`
}
// JobVariableOptions represents a single job variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/jobs.html#run-a-job
type JobVariableOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Value *string `url:"value,omitempty" json:"value,omitempty"`
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/ee/api/jobs.html#run-a-job
func (s *JobsService) PlayJob(pid interface{}, 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
}
// DeleteArtifacts delete artifacts of a job
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#delete-job-artifacts
func (s *JobsService) DeleteArtifacts(pid interface{}, 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)
}
// DeleteProjectArtifacts delete artifacts eligible for deletion in a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/job_artifacts.html#delete-project-artifacts
func (s *JobsService) DeleteProjectArtifacts(pid interface{}, 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)
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"time"
)
// KeysService handles communication with the
// keys related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/keys.html
type KeysService struct {
client *Client
}
// Key represents a GitLab user's SSH key.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/keys.html
type Key struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt *time.Time `json:"created_at"`
User User `json:"user"`
}
// GetKeyWithUser gets a single key by id along with the associated
// user information.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/keys.html#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
}
// GetKeyByFingerprintOptions represents the available GetKeyByFingerprint()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/keys.html#get-user-by-fingerprint-of-ssh-key
// https://docs.gitlab.com/ee/api/keys.html#get-user-by-deploy-key-fingerprint
type GetKeyByFingerprintOptions struct {
Fingerprint string `url:"fingerprint" json:"fingerprint"`
}
// GetKeyByFingerprint gets a specific SSH key or deploy key by fingerprint
// along with the associated user information.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/keys.html#get-user-by-fingerprint-of-ssh-key
// https://docs.gitlab.com/ee/api/keys.html#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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"net/http"
)
// LabelsService handles communication with the label related methods of the
// GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html
type LabelsService struct {
client *Client
}
// Label represents a GitLab label.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html
type Label struct {
ID int `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"`
Subscribed bool `json:"subscribed"`
Priority int `json:"priority"`
IsProjectLabel bool `json:"is_project_label"`
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (l *Label) UnmarshalJSON(data []byte) error {
type alias Label
if err := json.Unmarshal(data, (*alias)(l)); err != nil {
return err
}
if l.Name == "" {
var raw map[string]interface{}
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
if title, ok := raw["title"].(string); ok {
l.Name = title
}
}
return nil
}
func (l Label) String() string {
return Stringify(l)
}
// ListLabelsOptions represents the available ListLabels() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#list-labels
type ListLabelsOptions struct {
ListOptions
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"`
}
// ListLabels gets all labels for given project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#list-labels
func (s *LabelsService) ListLabels(pid interface{}, 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
}
// GetLabel get a single label for a given project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#get-a-single-project-label
func (s *LabelsService) GetLabel(pid interface{}, labelID interface{}, options ...RequestOptionFunc) (*Label, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
label, err := parseID(labelID)
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
}
// CreateLabelOptions represents the available CreateLabel() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#create-a-new-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"`
}
// CreateLabel creates a new label for given repository with given name and
// color.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#create-a-new-label
func (s *LabelsService) CreateLabel(pid interface{}, 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
}
// DeleteLabelOptions represents the available DeleteLabel() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#delete-a-label
type DeleteLabelOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// DeleteLabel deletes a label given by its name or ID.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#delete-a-label
func (s *LabelsService) DeleteLabel(pid interface{}, lid interface{}, opt *DeleteLabelOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/labels", PathEscape(project))
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
}
return s.client.Do(req, nil)
}
// UpdateLabelOptions represents the available UpdateLabel() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#edit-an-existing-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"`
}
// UpdateLabel updates an existing label with new name or now color. At least
// one parameter is required, to update the label.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/labels.html#edit-an-existing-label
func (s *LabelsService) UpdateLabel(pid interface{}, 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))
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
}
return l, resp, nil
}
// SubscribeToLabel subscribes the authenticated user to a label to receive
// notifications. If the user is already subscribed to the label, the status
// code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/labels.html#subscribe-to-a-label
func (s *LabelsService) SubscribeToLabel(pid interface{}, labelID interface{}, options ...RequestOptionFunc) (*Label, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
label, err := parseID(labelID)
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
}
// UnsubscribeFromLabel unsubscribes the authenticated user from a label to not
// receive notifications from it. If the user is not subscribed to the label, the
// status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/labels.html#unsubscribe-from-a-label
func (s *LabelsService) UnsubscribeFromLabel(pid interface{}, labelID interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
label, err := parseID(labelID)
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)
}
// PromoteLabel Promotes a project label to a group label.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/labels.html#promote-a-project-label-to-a-group-label
func (s *LabelsService) PromoteLabel(pid interface{}, labelID interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
label, err := parseID(labelID)
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)
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"time"
)
// LicenseService handles communication with the license
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/license.html
type LicenseService struct {
client *Client
}
// License represents a GitLab license.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/license.html
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"`
// 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"`
}
func (l License) String() string {
return Stringify(l)
}
// GetLicense retrieves information about the current license.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/license.html#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
}
// AddLicenseOptions represents the available AddLicense() options.
//
// https://docs.gitlab.com/ee/api/license.html#add-a-new-license
type AddLicenseOptions struct {
License *string `url:"license" json:"license"`
}
// AddLicense adds a new license.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/license.html#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
}
// DeleteLicense deletes an existing license.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/license.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// LicenseTemplate represents a license template.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/licenses.html
type LicenseTemplate struct {
Key string `json:"key"`
Name string `json:"name"`
Nickname string `json:"nickname"`
Featured bool `json:"featured"`
HTMLURL string `json:"html_url"`
SourceURL string `json:"source_url"`
Description string `json:"description"`
Conditions []string `json:"conditions"`
Permissions []string `json:"permissions"`
Limitations []string `json:"limitations"`
Content string `json:"content"`
}
// LicenseTemplatesService handles communication with the license templates
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/templates/licenses.html
type LicenseTemplatesService struct {
client *Client
}
// ListLicenseTemplatesOptions represents the available
// ListLicenseTemplates() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/licenses.html#list-license-templates
type ListLicenseTemplatesOptions struct {
ListOptions
Popular *bool `url:"popular,omitempty" json:"popular,omitempty"`
}
// ListLicenseTemplates get all license templates.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/licenses.html#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
}
// GetLicenseTemplateOptions represents the available
// GetLicenseTemplate() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/licenses.html#single-license-template
type GetLicenseTemplateOptions struct {
Project *string `url:"project,omitempty" json:"project,omitempty"`
Fullname *string `url:"fullname,omitempty" json:"fullname,omitempty"`
}
// GetLicenseTemplate get a single license template. You can pass parameters
// to replace the license placeholder.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/templates/licenses.html#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
}
package gitlab
import "net/http"
// MarkdownService handles communication with the markdown related methods of
// the GitLab API.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/markdown.html
type MarkdownService struct {
client *Client
}
// Markdown represents a markdown document.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/markdown.html
type Markdown struct {
HTML string `json:"html"`
}
// RenderOptions represents the available Render() options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/markdown.html#render-an-arbitrary-markdown-document
type RenderOptions struct {
Text *string `url:"text,omitempty" json:"text,omitempty"`
GitlabFlavouredMarkdown *bool `url:"gfm,omitempty" json:"gfm,omitempty"`
Project *string `url:"project,omitempty" json:"project,omitempty"`
}
// Render an arbitrary markdown document.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/markdown.html#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
}
package gitlab
import (
"fmt"
"net/http"
)
// MemberRolesService handles communication with the member roles related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/member_roles.html
type MemberRolesService struct {
client *Client
}
// MemberRole represents a GitLab member role.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/member_roles.html
type MemberRole struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
GroupId int `json:"group_id"`
BaseAccessLevel AccessLevelValue `json:"base_access_level"`
AdminCICDVariables bool `json:"admin_cicd_variables,omitempty"`
AdminMergeRequests bool `json:"admin_merge_request,omitempty"`
AdminTerraformState bool `json:"admin_terraform_state,omitempty"`
AdminVulnerability bool `json:"admin_vulnerability,omitempty"`
ReadCode bool `json:"read_code,omitempty"`
ReadDependency bool `json:"read_dependency,omitempty"`
ReadVulnerability bool `json:"read_vulnerability,omitempty"`
AdminGroupMembers bool `json:"admin_group_member,omitempty"`
ManageProjectAccessToken bool `json:"manage_project_access_tokens,omitempty"`
ArchiveProject bool `json:"archive_project,omitempty"`
RemoveProject bool `json:"remove_project,omitempty"`
ManageGroupAccesToken bool `json:"manage_group_access_tokens,omitempty"`
}
// ListMemberRoles gets a list of member roles for a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/member_roles.html#list-all-member-roles-of-a-group
func (s *MemberRolesService) ListMemberRoles(gid interface{}, 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
}
// CreateMemberRoleOptions represents the available CreateMemberRole() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/member_roles.html#add-a-member-role-to-a-group
type CreateMemberRoleOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
BaseAccessLevel *AccessLevelValue `url:"base_access_level,omitempty" json:"base_access_level,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
AdminMergeRequest *bool `url:"admin_merge_request,omitempty" json:"admin_merge_request,omitempty"`
AdminVulnerability *bool `url:"admin_vulnerability,omitempty" json:"admin_vulnerability,omitempty"`
ReadCode *bool `url:"read_code,omitempty" json:"read_code,omitempty"`
ReadDependency *bool `url:"read_dependency,omitempty" json:"read_dependency,omitempty"`
ReadVulnerability *bool `url:"read_vulnerability,omitempty" json:"read_vulnerability,omitempty"`
}
// CreateMemberRole creates a new member role for a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/member_roles.html#add-a-member-role-to-a-group
func (s *MemberRolesService) CreateMemberRole(gid interface{}, 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
}
// DeleteMemberRole deletes a member role from a specified group.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/member_roles.html#remove-member-role-of-a-group
func (s *MemberRolesService) DeleteMemberRole(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// MergeRequestApprovalsService handles communication with the merge request
// approvals related methods of the GitLab API. This includes reading/updating
// approval settings and approve/unapproving merge requests
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_request_approvals.html
type MergeRequestApprovalsService struct {
client *Client
}
// MergeRequestApprovals represents GitLab merge request approvals.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals
type MergeRequestApprovals struct {
ID int `json:"id"`
IID int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
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"`
RequirePasswordToApprove bool `json:"require_password_to_approve"`
ApprovedBy []*MergeRequestApproverUser `json:"approved_by"`
SuggestedApprovers []*BasicUser `json:"suggested_approvers"`
Approvers []*MergeRequestApproverUser `json:"approvers"`
ApproverGroups []*MergeRequestApproverGroup `json:"approver_groups"`
UserHasApproved bool `json:"user_has_approved"`
UserCanApprove bool `json:"user_can_approve"`
ApprovalRulesLeft []*MergeRequestApprovalRule `json:"approval_rules_left"`
HasApprovalRules bool `json:"has_approval_rules"`
MergeRequestApproversAvailable bool `json:"merge_request_approvers_available"`
MultipleApprovalRulesAvailable bool `json:"multiple_approval_rules_available"`
}
func (m MergeRequestApprovals) String() string {
return Stringify(m)
}
// MergeRequestApproverGroup represents GitLab project level merge request approver group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
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"`
}
}
// MergeRequestApprovalRule represents a GitLab merge request approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-merge-request-level-rules
type MergeRequestApprovalRule struct {
ID int `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"`
SourceRule *ProjectApprovalRule `json:"source_rule"`
Users []*BasicUser `json:"users"`
Groups []*Group `json:"groups"`
ContainsHiddenGroups bool `json:"contains_hidden_groups"`
Section string `json:"section"`
ApprovedBy []*BasicUser `json:"approved_by"`
Approved bool `json:"approved"`
}
// MergeRequestApprovalState represents a GitLab merge request approval state.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
type MergeRequestApprovalState struct {
ApprovalRulesOverwritten bool `json:"approval_rules_overwritten"`
Rules []*MergeRequestApprovalRule `json:"rules"`
}
// String is a stringify for MergeRequestApprovalRule
func (s MergeRequestApprovalRule) String() string {
return Stringify(s)
}
// MergeRequestApproverUser represents GitLab project level merge request approver user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type MergeRequestApproverUser struct {
User *BasicUser
}
// ApproveMergeRequestOptions represents the available ApproveMergeRequest() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request
type ApproveMergeRequestOptions struct {
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
}
// ApproveMergeRequest approves a merge request on GitLab. If a non-empty sha
// is provided then it must match the sha at the HEAD of the MR.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#approve-merge-request
func (s *MergeRequestApprovalsService) ApproveMergeRequest(pid interface{}, 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
}
// UnapproveMergeRequest unapproves a previously approved merge request on GitLab.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#unapprove-merge-request
func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid interface{}, 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)
}
// ResetApprovalsOfMergeRequest clear all approvals of merge request on GitLab.
// Available only for bot users based on project or group tokens.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#reset-approvals-of-a-merge-request
func (s *MergeRequestApprovalsService) ResetApprovalsOfMergeRequest(pid interface{}, 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)
}
// ChangeMergeRequestApprovalConfigurationOptions represents the available
// ChangeMergeRequestApprovalConfiguration() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-approval-configuration-deprecated
type ChangeMergeRequestApprovalConfigurationOptions struct {
ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
}
// GetConfiguration shows information about single merge request approvals
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-configuration-1
func (s *MergeRequestApprovalsService) GetConfiguration(pid interface{}, 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
}
// ChangeApprovalConfiguration updates the approval configuration of a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-approval-configuration-deprecated
func (s *MergeRequestApprovalsService) ChangeApprovalConfiguration(pid interface{}, 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
}
// ChangeMergeRequestAllowedApproversOptions represents the available
// ChangeMergeRequestAllowedApprovers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers-for-merge-request
type ChangeMergeRequestAllowedApproversOptions struct {
ApproverIDs []int `url:"approver_ids" json:"approver_ids"`
ApproverGroupIDs []int `url:"approver_group_ids" json:"approver_group_ids"`
}
// ChangeAllowedApprovers updates the approvers for a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers-for-merge-request
func (s *MergeRequestApprovalsService) ChangeAllowedApprovers(pid interface{}, mergeRequest int, opt *ChangeMergeRequestAllowedApproversOptions, options ...RequestOptionFunc) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests/%d/approvers", 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
}
// GetApprovalRules requests information about a merge request’s approval rules
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-merge-request-level-rules
func (s *MergeRequestApprovalsService) GetApprovalRules(pid interface{}, 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
}
// GetApprovalState requests information about a merge request’s approval state
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-the-approval-state-of-merge-requests
func (s *MergeRequestApprovalsService) GetApprovalState(pid interface{}, 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
}
// CreateMergeRequestApprovalRuleOptions represents the available CreateApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-merge-request-level-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"`
}
// CreateApprovalRule creates a new MR level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-merge-request-level-rule
func (s *MergeRequestApprovalsService) CreateApprovalRule(pid interface{}, 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
}
// UpdateMergeRequestApprovalRuleOptions represents the available UpdateApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-merge-request-level-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"`
}
// UpdateApprovalRule updates an existing approval rule with new options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-merge-request-level-rule
func (s *MergeRequestApprovalsService) UpdateApprovalRule(pid interface{}, 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
}
// DeleteApprovalRule deletes a mr level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#delete-merge-request-level-rule
func (s *MergeRequestApprovalsService) DeleteApprovalRule(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"net/http"
"time"
)
// MergeRequestsService handles communication with the merge requests related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_requests.html
type MergeRequestsService struct {
client *Client
timeStats *timeStatsService
}
// MergeRequest represents a GitLab merge request.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_requests.html
type MergeRequest struct {
ID int `json:"id"`
IID int `json:"iid"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
ProjectID int `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"`
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"`
Labels Labels `json:"labels"`
LabelDetails []*LabelDetails `json:"label_details"`
Description string `json:"description"`
Draft bool `json:"draft"`
WorkInProgress bool `json:"work_in_progress"`
Milestone *Milestone `json:"milestone"`
MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
DetailedMergeStatus string `json:"detailed_merge_status"`
MergeError string `json:"merge_error"`
MergedBy *BasicUser `json:"merged_by"`
MergedAt *time.Time `json:"merged_at"`
ClosedBy *BasicUser `json:"closed_by"`
ClosedAt *time.Time `json:"closed_at"`
Subscribed bool `json:"subscribed"`
SHA string `json:"sha"`
MergeCommitSHA string `json:"merge_commit_sha"`
SquashCommitSHA string `json:"squash_commit_sha"`
UserNotesCount int `json:"user_notes_count"`
ChangesCount string `json:"changes_count"`
ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"`
ForceRemoveSourceBranch bool `json:"force_remove_source_branch"`
AllowCollaboration bool `json:"allow_collaboration"`
WebURL string `json:"web_url"`
References *IssueReferences `json:"references"`
DiscussionLocked bool `json:"discussion_locked"`
Changes []*MergeRequestDiff `json:"changes"`
User struct {
CanMerge bool `json:"can_merge"`
} `json:"user"`
TimeStats *TimeStats `json:"time_stats"`
Squash bool `json:"squash"`
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"`
DivergedCommitsCount int `json:"diverged_commits_count"`
RebaseInProgress bool `json:"rebase_in_progress"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
Reference string `json:"reference"`
FirstContribution bool `json:"first_contribution"`
TaskCompletionStatus *TasksCompletionStatus `json:"task_completion_status"`
HasConflicts bool `json:"has_conflicts"`
BlockingDiscussionsResolved bool `json:"blocking_discussions_resolved"`
Overflow bool `json:"overflow"`
// Deprecated: This parameter is replaced by DetailedMergeStatus in GitLab 15.6.
MergeStatus string `json:"merge_status"`
}
func (m MergeRequest) String() string {
return Stringify(m)
}
func (m *MergeRequest) UnmarshalJSON(data []byte) error {
type alias MergeRequest
raw := make(map[string]interface{})
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
labelDetails, ok := raw["labels"].([]interface{})
if ok && len(labelDetails) > 0 {
// We only want to change anything if we got label details.
if _, ok := labelDetails[0].(map[string]interface{}); !ok {
return json.Unmarshal(data, (*alias)(m))
}
labels := make([]interface{}, len(labelDetails))
for i, details := range labelDetails {
labels[i] = details.(map[string]interface{})["name"]
}
// Set the correct values
raw["labels"] = labels
raw["label_details"] = labelDetails
data, err = json.Marshal(raw)
if err != nil {
return err
}
}
return json.Unmarshal(data, (*alias)(m))
}
// MergeRequestDiff represents Gitlab merge request diff.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
type MergeRequestDiff struct {
OldPath string `json:"old_path"`
NewPath string `json:"new_path"`
AMode string `json:"a_mode"`
BMode string `json:"b_mode"`
Diff string `json:"diff"`
NewFile bool `json:"new_file"`
RenamedFile bool `json:"renamed_file"`
DeletedFile bool `json:"deleted_file"`
}
// MergeRequestDiffVersion represents Gitlab merge request version.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
type MergeRequestDiffVersion struct {
ID int `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"`
State string `json:"state,omitempty"`
RealSize string `json:"real_size,omitempty"`
Commits []*Commit `json:"commits,omitempty"`
Diffs []*Diff `json:"diffs,omitempty"`
}
func (m MergeRequestDiffVersion) String() string {
return Stringify(m)
}
// ListMergeRequestsOptions represents the available ListMergeRequests()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
type ListMergeRequestsOptions struct {
ListOptions
Approved *string `url:"approved,omitempty" json:"approved,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"`
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"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
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"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ApproverIDs *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
ApprovedByIDs *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
ReviewerID *ReviewerIDValue `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
In *string `url:"in,omitempty" json:"in,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
}
// ListMergeRequests gets all merge requests. The state parameter can be used
// to get only merge requests with a given state (opened, closed, or merged)
// or all of them (all). The pagination parameters page and per_page can be
// used to restrict the list of merge requests.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
func (s *MergeRequestsService) ListMergeRequests(opt *ListMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *Response, error) {
req, err := s.client.NewRequest(http.MethodGet, "merge_requests", opt, options)
if err != nil {
return nil, nil, err
}
var m []*MergeRequest
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListProjectMergeRequestsOptions represents the available ListMergeRequests()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests
type ListProjectMergeRequestsOptions struct {
ListOptions
IIDs *[]int `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"`
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"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
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"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ApproverIDs *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
ApprovedByIDs *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
ReviewerID *ReviewerIDValue `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
}
// ListProjectMergeRequests gets all merge requests for this project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests
func (s *MergeRequestsService) ListProjectMergeRequests(pid interface{}, opt *ListProjectMergeRequestsOptions, 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.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var m []*MergeRequest
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListGroupMergeRequestsOptions represents the available ListGroupMergeRequests()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-group-merge-requests
type ListGroupMergeRequestsOptions struct {
ListOptions
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"`
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"`
WithMergeStatusRecheck *bool `url:"with_merge_status_recheck,omitempty" json:"with_merge_status_recheck,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
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"`
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"`
AssigneeID *AssigneeIDValue `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
ApproverIDs *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
ApprovedByIDs *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
ReviewerID *ReviewerIDValue `url:"reviewer_id,omitempty" json:"reviewer_id,omitempty"`
ReviewerUsername *string `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
MyReactionEmoji *string `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
SourceBranch *string `url:"source_branch,omitempty" json:"source_branch,omitempty"`
TargetBranch *string `url:"target_branch,omitempty" json:"target_branch,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
In *string `url:"in,omitempty" json:"in,omitempty"`
Draft *bool `url:"draft,omitempty" json:"draft,omitempty"`
WIP *string `url:"wip,omitempty" json:"wip,omitempty"`
}
// ListGroupMergeRequests gets all merge requests for this group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-group-merge-requests
func (s *MergeRequestsService) ListGroupMergeRequests(gid interface{}, opt *ListGroupMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *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 []*MergeRequest
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// GetMergeRequestsOptions represents the available GetMergeRequests()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
type GetMergeRequestsOptions struct {
RenderHTML *bool `url:"render_html,omitempty" json:"render_html,omitempty"`
IncludeDivergedCommitsCount *bool `url:"include_diverged_commits_count,omitempty" json:"include_diverged_commits_count,omitempty"`
IncludeRebaseInProgress *bool `url:"include_rebase_in_progress,omitempty" json:"include_rebase_in_progress,omitempty"`
}
// GetMergeRequest shows information about a single merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr
func (s *MergeRequestsService) GetMergeRequest(pid interface{}, 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
}
// GetMergeRequestApprovals gets information about a merge requests approvals
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#merge-request-level-mr-approvals
func (s *MergeRequestsService) GetMergeRequestApprovals(pid interface{}, 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
}
// GetMergeRequestCommitsOptions represents the available GetMergeRequestCommits()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-commits
type GetMergeRequestCommitsOptions ListOptions
// GetMergeRequestCommits gets a list of merge request commits.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-commits
func (s *MergeRequestsService) GetMergeRequestCommits(pid interface{}, 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
}
// GetMergeRequestChangesOptions represents the available GetMergeRequestChanges()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-changes
type GetMergeRequestChangesOptions struct {
AccessRawDiffs *bool `url:"access_raw_diffs,omitempty" json:"access_raw_diffs,omitempty"`
Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
}
// GetMergeRequestChanges shows information about the merge request including
// its files and changes.
//
// Deprecated: This endpoint has been replaced by
// MergeRequestsService.ListMergeRequestDiffs()
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-changes
func (s *MergeRequestsService) GetMergeRequestChanges(pid interface{}, 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
}
// ListMergeRequestDiffsOptions represents the available ListMergeRequestDiffs()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
type ListMergeRequestDiffsOptions struct {
ListOptions
Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
}
// ListMergeRequestDiffs List diffs of the files changed in a merge request
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs
func (s *MergeRequestsService) ListMergeRequestDiffs(pid interface{}, 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
}
// GetMergeRequestParticipants gets a list of merge request participants.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-participants
func (s *MergeRequestsService) GetMergeRequestParticipants(pid interface{}, 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/ee/api/merge_requests.html#get-single-merge-request-reviewers
type MergeRequestReviewer struct {
User *BasicUser `json:"user"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
}
// GetMergeRequestReviewers gets a list of merge request reviewers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-single-merge-request-reviewers
func (s *MergeRequestsService) GetMergeRequestReviewers(pid interface{}, 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
}
// ListMergeRequestPipelines gets all pipelines for the provided merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-pipelines
func (s *MergeRequestsService) ListMergeRequestPipelines(pid interface{}, 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
}
// CreateMergeRequestPipeline creates a new pipeline for a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#create-merge-request-pipeline
func (s *MergeRequestsService) CreateMergeRequestPipeline(pid interface{}, 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
}
// GetIssuesClosedOnMergeOptions represents the available GetIssuesClosedOnMerge()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-issues-that-close-on-merge
type GetIssuesClosedOnMergeOptions ListOptions
// GetIssuesClosedOnMerge gets all the issues that would be closed by merging the
// provided merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#list-issues-that-close-on-merge
func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid interface{}, 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
}
// CreateMergeRequestOptions represents the available CreateMergeRequest()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
type CreateMergeRequestOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
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"`
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"`
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
}
// CreateMergeRequest creates a new merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
func (s *MergeRequestsService) CreateMergeRequest(pid interface{}, 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
}
// UpdateMergeRequestOptions represents the available UpdateMergeRequest()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#update-mr
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"`
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"`
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"`
DiscussionLocked *bool `url:"discussion_locked,omitempty" json:"discussion_locked,omitempty"`
AllowCollaboration *bool `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
}
// UpdateMergeRequest updates an existing project milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#update-mr
func (s *MergeRequestsService) UpdateMergeRequest(pid interface{}, 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
}
// DeleteMergeRequest deletes a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#delete-a-merge-request
func (s *MergeRequestsService) DeleteMergeRequest(pid interface{}, 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)
}
// AcceptMergeRequestOptions represents the available AcceptMergeRequest()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#merge-a-merge-request
type AcceptMergeRequestOptions struct {
MergeCommitMessage *string `url:"merge_commit_message,omitempty" json:"merge_commit_message,omitempty"`
SquashCommitMessage *string `url:"squash_commit_message,omitempty" json:"squash_commit_message,omitempty"`
Squash *bool `url:"squash,omitempty" json:"squash,omitempty"`
ShouldRemoveSourceBranch *bool `url:"should_remove_source_branch,omitempty" json:"should_remove_source_branch,omitempty"`
MergeWhenPipelineSucceeds *bool `url:"merge_when_pipeline_succeeds,omitempty" json:"merge_when_pipeline_succeeds,omitempty"`
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
}
// AcceptMergeRequest merges changes submitted with MR using this API. If merge
// success you get 200 OK. If it has some conflicts and can not be merged - you
// get 405 and error message 'Branch cannot be merged'. If merge request is
// already merged or closed - you get 405 and error message 'Method Not Allowed'
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#merge-a-merge-request
func (s *MergeRequestsService) AcceptMergeRequest(pid interface{}, 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
}
// CancelMergeWhenPipelineSucceeds cancels a merge when pipeline succeeds. If
// you don't have permissions to accept this merge request - you'll get a 401.
// If the merge request is already merged or closed - you get 405 and error
// message 'Method Not Allowed'. In case the merge request is not set to be
// merged when the pipeline succeeds, you'll also get a 406 error.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#cancel-merge-when-pipeline-succeeds
func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid interface{}, 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
}
// RebaseMergeRequestOptions represents the available RebaseMergeRequest()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
type RebaseMergeRequestOptions struct {
SkipCI *bool `url:"skip_ci,omitempty" json:"skip_ci,omitempty"`
}
// RebaseMergeRequest automatically rebases the source_branch of the merge
// request against its target_branch. If you don’t have permissions to push
// to the merge request’s source branch, you’ll get a 403 Forbidden response.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
func (s *MergeRequestsService) RebaseMergeRequest(pid interface{}, 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)
}
// GetMergeRequestDiffVersionsOptions represents the available
// GetMergeRequestDiffVersions() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
type GetMergeRequestDiffVersionsOptions ListOptions
// GetMergeRequestDiffVersions get a list of merge request diff versions.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-merge-request-diff-versions
func (s *MergeRequestsService) GetMergeRequestDiffVersions(pid interface{}, 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
}
// GetSingleMergeRequestDiffVersionOptions represents the available
// GetSingleMergeRequestDiffVersion() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-a-single-merge-request-diff-version
type GetSingleMergeRequestDiffVersionOptions struct {
Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
}
// GetSingleMergeRequestDiffVersion get a single MR diff version
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-a-single-merge-request-diff-version
func (s *MergeRequestsService) GetSingleMergeRequestDiffVersion(pid interface{}, 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
}
// SubscribeToMergeRequest subscribes the authenticated user to the given merge
// request to receive notifications. If the user is already subscribed to the
// merge request, the status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#subscribe-to-a-merge-request
func (s *MergeRequestsService) SubscribeToMergeRequest(pid interface{}, 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
}
// UnsubscribeFromMergeRequest unsubscribes the authenticated user from the
// given merge request to not receive notifications from that merge request.
// If the user is not subscribed to the merge request, status code 304 is
// returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#unsubscribe-from-a-merge-request
func (s *MergeRequestsService) UnsubscribeFromMergeRequest(pid interface{}, 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
}
// CreateTodo manually creates a todo for the current user on a merge request.
// If there already exists a todo for the user on that merge request,
// status code 304 is returned.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#create-a-to-do-item
func (s *MergeRequestsService) CreateTodo(pid interface{}, 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
}
// SetTimeEstimate sets the time estimate for a single project merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#set-a-time-estimate-for-a-merge-request
func (s *MergeRequestsService) SetTimeEstimate(pid interface{}, mergeRequest int, opt *SetTimeEstimateOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.setTimeEstimate(pid, "merge_requests", mergeRequest, opt, options...)
}
// ResetTimeEstimate resets the time estimate for a single project merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#reset-the-time-estimate-for-a-merge-request
func (s *MergeRequestsService) ResetTimeEstimate(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.resetTimeEstimate(pid, "merge_requests", mergeRequest, options...)
}
// AddSpentTime adds spent time for a single project merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#add-spent-time-for-a-merge-request
func (s *MergeRequestsService) AddSpentTime(pid interface{}, mergeRequest int, opt *AddSpentTimeOptions, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.addSpentTime(pid, "merge_requests", mergeRequest, opt, options...)
}
// ResetSpentTime resets the spent time for a single project merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#reset-spent-time-for-a-merge-request
func (s *MergeRequestsService) ResetSpentTime(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.resetSpentTime(pid, "merge_requests", mergeRequest, options...)
}
// GetTimeSpent gets the spent time for a single project merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_requests.html#get-time-tracking-stats
func (s *MergeRequestsService) GetTimeSpent(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*TimeStats, *Response, error) {
return s.timeStats.getTimeSpent(pid, "merge_requests", mergeRequest, options...)
}
package gitlab
import (
"fmt"
"net/http"
"time"
)
// MergeTrainsService handles communication with the merge trains related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_trains.html
type MergeTrainsService struct {
client *Client
}
// MergeTrain represents a Gitlab merge train.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_trains.html
type MergeTrain struct {
ID int `json:"id"`
MergeRequest *MergeTrainMergeRequest `json:"merge_request"`
User *BasicUser `json:"user"`
Pipeline *Pipeline `json:"pipeline"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
TargetBranch string `json:"target_branch"`
Status string `json:"status"`
MergedAt *time.Time `json:"merged_at"`
Duration int `json:"duration"`
}
// MergeTrainMergeRequest represents a Gitlab merge request inside merge train.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_trains.html
type MergeTrainMergeRequest struct {
ID int `json:"id"`
IID int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
WebURL string `json:"web_url"`
}
// ListMergeTrainsOptions represents the available ListMergeTrain() options.
//
// Gitab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#list-merge-trains-for-a-project
type ListMergeTrainsOptions struct {
ListOptions
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListProjectMergeTrains get a list of merge trains in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#list-merge-trains-for-a-project
func (s *MergeTrainsService) ListProjectMergeTrains(pid interface{}, 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
}
// ListMergeRequestInMergeTrain gets a list of merge requests added to a merge
// train for the requested target branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#list-merge-requests-in-a-merge-train
func (s *MergeTrainsService) ListMergeRequestInMergeTrain(pid interface{}, 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
}
// GetMergeRequestOnAMergeTrain Get merge train information for the requested
// merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#get-the-status-of-a-merge-request-on-a-merge-train
func (s *MergeTrainsService) GetMergeRequestOnAMergeTrain(pid interface{}, 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
}
// AddMergeRequestToMergeTrainOptions represents the available
// AddMergeRequestToMergeTrain() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#add-a-merge-request-to-a-merge-train
type AddMergeRequestToMergeTrainOptions struct {
WhenPipelineSucceeds *bool `url:"when_pipeline_succeeds,omitempty" json:"when_pipeline_succeeds,omitempty"`
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
Squash *bool `url:"squash,omitempty" json:"squash,omitempty"`
}
// AddMergeRequestToMergeTrain Add a merge request to the merge train targeting
// the merge request’s target branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_trains.html#add-a-merge-request-to-a-merge-train
func (s *MergeTrainsService) AddMergeRequestToMergeTrain(pid interface{}, 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
}
//
// Copyright 2022, Timo Furrer <tuxtimo@gmail.com>
//
// 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"
// MetadataService handles communication with the GitLab server instance to
// retrieve its metadata information via the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/metadata.html
type MetadataService struct {
client *Client
}
// Metadata represents a GitLab instance version.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/metadata.html
type Metadata struct {
Version string `json:"version"`
Revision string `json:"revision"`
KAS struct {
Enabled bool `json:"enabled"`
ExternalURL string `json:"externalUrl"`
Version string `json:"version"`
} `json:"kas"`
Enterprise bool `json:"enterprise"`
}
func (s Metadata) String() string {
return Stringify(s)
}
// GetMetadata gets a GitLab server instance meteadata.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/metadata.html
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
}
v := new(Metadata)
resp, err := s.client.Do(req, v)
if err != nil {
return nil, resp, err
}
return v, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// MilestonesService handles communication with the milestone related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/milestones.html
type MilestonesService struct {
client *Client
}
// Milestone represents a GitLab milestone.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/milestones.html
type Milestone struct {
ID int `json:"id"`
IID int `json:"iid"`
GroupID int `json:"group_id"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
StartDate *ISOTime `json:"start_date"`
DueDate *ISOTime `json:"due_date"`
State string `json:"state"`
WebURL string `json:"web_url"`
UpdatedAt *time.Time `json:"updated_at"`
CreatedAt *time.Time `json:"created_at"`
Expired *bool `json:"expired"`
}
func (m Milestone) String() string {
return Stringify(m)
}
// ListMilestonesOptions represents the available ListMilestones() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#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"`
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/ee/api/milestones.html#list-project-milestones
func (s *MilestonesService) ListMilestones(pid interface{}, 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
}
// GetMilestone gets a single project milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#get-single-milestone
func (s *MilestonesService) GetMilestone(pid interface{}, 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
}
// CreateMilestoneOptions represents the available CreateMilestone() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#create-new-milestone
type CreateMilestoneOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
}
// CreateMilestone creates a new project milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#create-new-milestone
func (s *MilestonesService) CreateMilestone(pid interface{}, 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
}
// UpdateMilestoneOptions represents the available UpdateMilestone() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#edit-milestone
type UpdateMilestoneOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
StartDate *ISOTime `url:"start_date,omitempty" json:"start_date,omitempty"`
DueDate *ISOTime `url:"due_date,omitempty" json:"due_date,omitempty"`
StateEvent *string `url:"state_event,omitempty" json:"state_event,omitempty"`
}
// UpdateMilestone updates an existing project milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#edit-milestone
func (s *MilestonesService) UpdateMilestone(pid interface{}, 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
}
// DeleteMilestone deletes a specified project milestone.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#delete-project-milestone
func (s *MilestonesService) DeleteMilestone(pid interface{}, 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)
}
// GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#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/ee/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
func (s *MilestonesService) GetMilestoneIssues(pid interface{}, 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
}
return i, resp, nil
}
// GetMilestoneMergeRequestsOptions represents the available
// GetMilestoneMergeRequests() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/milestones.html#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/ee/api/milestones.html#get-all-merge-requests-assigned-to-a-single-milestone
func (s *MilestonesService) GetMilestoneMergeRequests(pid interface{}, milestone int, opt *GetMilestoneMergeRequestsOptions, options ...RequestOptionFunc) ([]*MergeRequest, *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 []*MergeRequest
resp, err := s.client.Do(req, &mr)
if err != nil {
return nil, resp, err
}
return mr, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// NamespacesService handles communication with the namespace related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/namespaces.html
type NamespacesService struct {
client *Client
}
// Namespace represents a GitLab namespace.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/namespaces.html
type Namespace struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Kind string `json:"kind"`
FullPath string `json:"full_path"`
ParentID int `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"`
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"`
}
func (n Namespace) String() string {
return Stringify(n)
}
// ListNamespacesOptions represents the available ListNamespaces() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/namespaces.html#list-namespaces
type ListNamespacesOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
OwnedOnly *bool `url:"owned_only,omitempty" json:"owned_only,omitempty"`
}
// ListNamespaces gets a list of projects accessible by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/namespaces.html#list-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
}
// SearchNamespace gets all namespaces that match your string in their name
// or path.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/namespaces.html#list-namespaces
func (s *NamespacesService) SearchNamespace(query string, options ...RequestOptionFunc) ([]*Namespace, *Response, error) {
var q struct {
Search string `url:"search,omitempty" json:"search,omitempty"`
}
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
}
// GetNamespace gets a namespace by id.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/namespaces.html#get-namespace-by-id
func (s *NamespacesService) GetNamespace(id interface{}, options ...RequestOptionFunc) (*Namespace, *Response, error) {
namespace, err := parseID(id)
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
}
// NamespaceExistance represents a namespace exists result.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/namespaces.html#get-existence-of-a-namespace
type NamespaceExistance struct {
Exists bool `json:"exists"`
Suggests []string `json:"suggests"`
}
// NamespaceExistsOptions represents the available NamespaceExists() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/namespaces.html#get-existence-of-a-namespace
type NamespaceExistsOptions struct {
ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"`
}
// NamespaceExists checks the existence of a namespace.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/namespaces.html#get-existence-of-a-namespace
func (s *NamespacesService) NamespaceExists(id interface{}, opt *NamespaceExistsOptions, options ...RequestOptionFunc) (*NamespaceExistance, *Response, error) {
namespace, err := parseID(id)
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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// NotesService handles communication with the notes related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/notes.html
type NotesService struct {
client *Client
}
// Note represents a GitLab note.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/notes.html
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 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"`
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"`
Confidential bool `json:"confidential"`
Internal bool `json:"internal"`
}
// NotePosition represents the position attributes of a note.
type NotePosition struct {
BaseSHA string `json:"base_sha"`
StartSHA string `json:"start_sha"`
HeadSHA string `json:"head_sha"`
PositionType string `json:"position_type"`
NewPath string `json:"new_path,omitempty"`
NewLine int `json:"new_line,omitempty"`
OldPath string `json:"old_path,omitempty"`
OldLine int `json:"old_line,omitempty"`
LineRange *LineRange `json:"line_range,omitempty"`
}
// LineRange represents the range of a note.
type LineRange struct {
StartRange *LinePosition `json:"start"`
EndRange *LinePosition `json:"end"`
}
// LinePosition represents a position in a line range.
type LinePosition struct {
LineCode string `json:"line_code"`
Type string `json:"type"`
OldLine int `json:"old_line"`
NewLine int `json:"new_line"`
}
func (n Note) String() string {
return Stringify(n)
}
// ListIssueNotesOptions represents the available ListIssueNotes() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-project-issue-notes
type ListIssueNotesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListIssueNotes gets a list of all notes for a single issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-project-issue-notes
func (s *NotesService) ListIssueNotes(pid interface{}, 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
}
// GetIssueNote returns a single note for a specific project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#get-single-issue-note
func (s *NotesService) GetIssueNote(pid interface{}, 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
}
// CreateIssueNoteOptions represents the available CreateIssueNote()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-issue-note
type CreateIssueNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
CreatedAt *time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
}
// CreateIssueNote creates a new note to a single project issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-issue-note
func (s *NotesService) CreateIssueNote(pid interface{}, 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
}
// UpdateIssueNoteOptions represents the available UpdateIssueNote()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-issue-note
type UpdateIssueNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// UpdateIssueNote modifies existing note of an issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-issue-note
func (s *NotesService) UpdateIssueNote(pid interface{}, 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
}
// DeleteIssueNote deletes an existing note of an issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#delete-an-issue-note
func (s *NotesService) DeleteIssueNote(pid interface{}, 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)
}
// ListSnippetNotesOptions represents the available ListSnippetNotes() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-snippet-notes
type ListSnippetNotesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListSnippetNotes gets a list of all notes for a single snippet. Snippet
// notes are comments users can post to a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-snippet-notes
func (s *NotesService) ListSnippetNotes(pid interface{}, 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
}
// GetSnippetNote returns a single note for a given snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#get-single-snippet-note
func (s *NotesService) GetSnippetNote(pid interface{}, 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
}
// CreateSnippetNoteOptions represents the available CreateSnippetNote()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-snippet-note
type CreateSnippetNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// CreateSnippetNote creates a new note for a single snippet. Snippet notes are
// comments users can post to a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-snippet-note
func (s *NotesService) CreateSnippetNote(pid interface{}, 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
}
// UpdateSnippetNoteOptions represents the available UpdateSnippetNote()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-snippet-note
type UpdateSnippetNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// UpdateSnippetNote modifies existing note of a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-snippet-note
func (s *NotesService) UpdateSnippetNote(pid interface{}, 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
}
// DeleteSnippetNote deletes an existing note of a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#delete-a-snippet-note
func (s *NotesService) DeleteSnippetNote(pid interface{}, 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)
}
// ListMergeRequestNotesOptions represents the available ListMergeRequestNotes()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-merge-request-notes
type ListMergeRequestNotesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListMergeRequestNotes gets a list of all notes for a single merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-merge-request-notes
func (s *NotesService) ListMergeRequestNotes(pid interface{}, 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
}
// GetMergeRequestNote returns a single note for a given merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#get-single-merge-request-note
func (s *NotesService) GetMergeRequestNote(pid interface{}, 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
}
// CreateMergeRequestNoteOptions represents the available
// CreateMergeRequestNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-merge-request-note
type CreateMergeRequestNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// CreateMergeRequestNote creates a new note for a single merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-merge-request-note
func (s *NotesService) CreateMergeRequestNote(pid interface{}, 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
}
// UpdateMergeRequestNoteOptions represents the available
// UpdateMergeRequestNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-merge-request-note
type UpdateMergeRequestNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// UpdateMergeRequestNote modifies existing note of a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-merge-request-note
func (s *NotesService) UpdateMergeRequestNote(pid interface{}, 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
}
// DeleteMergeRequestNote deletes an existing note of a merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#delete-a-merge-request-note
func (s *NotesService) DeleteMergeRequestNote(pid interface{}, 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)
}
// ListEpicNotesOptions represents the available ListEpicNotes() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
type ListEpicNotesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListEpicNotes gets a list of all notes for a single epic.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes
func (s *NotesService) ListEpicNotes(gid interface{}, 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
}
// GetEpicNote returns a single note for an epic.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#get-single-epic-note
func (s *NotesService) GetEpicNote(gid interface{}, 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
}
// CreateEpicNoteOptions represents the available CreateEpicNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
type CreateEpicNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// CreateEpicNote creates a new note for a single merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#create-new-epic-note
func (s *NotesService) CreateEpicNote(gid interface{}, 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
}
// UpdateEpicNoteOptions represents the available UpdateEpicNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
type UpdateEpicNoteOptions struct {
Body *string `url:"body,omitempty" json:"body,omitempty"`
}
// UpdateEpicNote modifies existing note of an epic.
//
// https://docs.gitlab.com/ee/api/notes.html#modify-existing-epic-note
func (s *NotesService) UpdateEpicNote(gid interface{}, 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
}
// DeleteEpicNote deletes an existing note of a merge request.
//
// https://docs.gitlab.com/ee/api/notes.html#delete-an-epic-note
func (s *NotesService) DeleteEpicNote(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"errors"
"fmt"
"net/http"
)
// NotificationSettingsService handles communication with the notification settings
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/notification_settings.html
type NotificationSettingsService struct {
client *Client
}
// NotificationSettings represents the Gitlab notification setting.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#valid-notification-levels
type NotificationSettings struct {
Level NotificationLevelValue `json:"level"`
NotificationEmail string `json:"notification_email"`
Events *NotificationEvents `json:"events"`
}
// NotificationEvents represents the available notification setting events.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#valid-notification-levels
type NotificationEvents struct {
CloseIssue bool `json:"close_issue"`
CloseMergeRequest bool `json:"close_merge_request"`
FailedPipeline bool `json:"failed_pipeline"`
FixedPipeline bool `json:"fixed_pipeline"`
IssueDue bool `json:"issue_due"`
MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
MergeMergeRequest bool `json:"merge_merge_request"`
MovedProject bool `json:"moved_project"`
NewIssue bool `json:"new_issue"`
NewMergeRequest bool `json:"new_merge_request"`
NewEpic bool `json:"new_epic"`
NewNote bool `json:"new_note"`
PushToMergeRequest bool `json:"push_to_merge_request"`
ReassignIssue bool `json:"reassign_issue"`
ReassignMergeRequest bool `json:"reassign_merge_request"`
ReopenIssue bool `json:"reopen_issue"`
ReopenMergeRequest bool `json:"reopen_merge_request"`
SuccessPipeline bool `json:"success_pipeline"`
}
func (ns NotificationSettings) String() string {
return Stringify(ns)
}
// GetGlobalSettings returns current notification settings and email address.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#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
}
// NotificationSettingsOptions represents the available options that can be passed
// to the API when updating the notification settings.
type NotificationSettingsOptions struct {
Level *NotificationLevelValue `url:"level,omitempty" json:"level,omitempty"`
NotificationEmail *string `url:"notification_email,omitempty" json:"notification_email,omitempty"`
CloseIssue *bool `url:"close_issue,omitempty" json:"close_issue,omitempty"`
CloseMergeRequest *bool `url:"close_merge_request,omitempty" json:"close_merge_request,omitempty"`
FailedPipeline *bool `url:"failed_pipeline,omitempty" json:"failed_pipeline,omitempty"`
FixedPipeline *bool `url:"fixed_pipeline,omitempty" json:"fixed_pipeline,omitempty"`
IssueDue *bool `url:"issue_due,omitempty" json:"issue_due,omitempty"`
MergeMergeRequest *bool `url:"merge_merge_request,omitempty" json:"merge_merge_request,omitempty"`
MergeWhenPipelineSucceeds *bool `url:"merge_when_pipeline_succeeds,omitempty" json:"merge_when_pipeline_succeeds,omitempty"`
MovedProject *bool `url:"moved_project,omitempty" json:"moved_project,omitempty"`
NewEpic *bool `url:"new_epic,omitempty" json:"new_epic,omitempty"`
NewIssue *bool `url:"new_issue,omitempty" json:"new_issue,omitempty"`
NewMergeRequest *bool `url:"new_merge_request,omitempty" json:"new_merge_request,omitempty"`
NewNote *bool `url:"new_note,omitempty" json:"new_note,omitempty"`
PushToMergeRequest *bool `url:"push_to_merge_request,omitempty" json:"push_to_merge_request,omitempty"`
ReassignIssue *bool `url:"reassign_issue,omitempty" json:"reassign_issue,omitempty"`
ReassignMergeRequest *bool `url:"reassign_merge_request,omitempty" json:"reassign_merge_request,omitempty"`
ReopenIssue *bool `url:"reopen_issue,omitempty" json:"reopen_issue,omitempty"`
ReopenMergeRequest *bool `url:"reopen_merge_request,omitempty" json:"reopen_merge_request,omitempty"`
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/ee/api/notification_settings.html#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
}
// GetSettingsForGroup returns current group notification settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#group--project-level-notification-settings
func (s *NotificationSettingsService) GetSettingsForGroup(gid interface{}, 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
}
// GetSettingsForProject returns current project notification settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#group--project-level-notification-settings
func (s *NotificationSettingsService) GetSettingsForProject(pid interface{}, 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
}
// UpdateSettingsForGroup updates current group notification settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#update-groupproject-level-notification-settings
func (s *NotificationSettingsService) UpdateSettingsForGroup(gid interface{}, 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
}
// UpdateSettingsForProject updates current project notification settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/notification_settings.html#update-groupproject-level-notification-settings
func (s *NotificationSettingsService) UpdateSettingsForProject(pid interface{}, 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
}
//
// Copyright 2021, Kordian Bruck
//
// 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 (
"fmt"
"net/http"
"time"
)
// PackagesService handles communication with the packages related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
type PackagesService struct {
client *Client
}
// Package represents a GitLab package.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
type Package struct {
ID int `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
PackageType string `json:"package_type"`
Status string `json:"status"`
Links *PackageLinks `json:"_links"`
CreatedAt *time.Time `json:"created_at"`
LastDownloadedAt *time.Time `json:"last_downloaded_at"`
Tags []PackageTag `json:"tags"`
}
func (s Package) String() string {
return Stringify(s)
}
// GroupPackage represents a GitLab group package.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
type GroupPackage struct {
Package
ProjectID int `json:"project_id"`
ProjectPath string `json:"project_path"`
}
func (s GroupPackage) String() string {
return Stringify(s)
}
// PackageLinks holds links for itself and deleting.
type PackageLinks struct {
WebPath string `json:"web_path"`
DeleteAPIPath string `json:"delete_api_path"`
}
func (s PackageLinks) String() string {
return Stringify(s)
}
// PackageTag holds label information about the package
type PackageTag struct {
ID int `json:"id"`
PackageID int `json:"package_id"`
Name string `json:"name"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}
func (s PackageTag) String() string {
return Stringify(s)
}
// PackageFile represents one file contained within a package.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
type PackageFile struct {
ID int `json:"id"`
PackageID int `json:"package_id"`
CreatedAt *time.Time `json:"created_at"`
FileName string `json:"file_name"`
Size int `json:"size"`
FileMD5 string `json:"file_md5"`
FileSHA1 string `json:"file_sha1"`
FileSHA256 string `json:"file_sha256"`
Pipeline *[]Pipeline `json:"pipelines"`
}
func (s PackageFile) String() string {
return Stringify(s)
}
// ListProjectPackagesOptions represents the available ListProjectPackages()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#within-a-project
type ListProjectPackagesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
PackageType *string `url:"package_type,omitempty" json:"package_type,omitempty"`
PackageName *string `url:"package_name,omitempty" json:"package_name,omitempty"`
PackageVersion *string `url:"package_version,omitempty" json:"package_version,omitempty"`
IncludeVersionless *bool `url:"include_versionless,omitempty" json:"include_versionless,omitempty"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
}
// ListProjectPackages gets a list of packages in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#within-a-project
func (s *PackagesService) ListProjectPackages(pid interface{}, 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
}
// ListGroupPackagesOptions represents the available ListGroupPackages()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#within-a-group
type ListGroupPackagesOptions struct {
ListOptions
ExcludeSubGroups *bool `url:"exclude_subgroups,omitempty" json:"exclude_subgroups,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
PackageType *string `url:"package_type,omitempty" json:"package_type,omitempty"`
PackageName *string `url:"package_name,omitempty" json:"package_name,omitempty"`
IncludeVersionless *bool `url:"include_versionless,omitempty" json:"include_versionless,omitempty"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
}
// ListGroupPackages gets a list of packages in a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#within-a-group
func (s *PackagesService) ListGroupPackages(gid interface{}, 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
}
// ListPackageFilesOptions represents the available ListPackageFiles()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#list-package-files
type ListPackageFilesOptions ListOptions
// ListPackageFiles gets a list of files that are within a package
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#list-package-files
func (s *PackagesService) ListPackageFiles(pid interface{}, 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,
)
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/ee/api/packages.html#delete-a-project-package
func (s *PackagesService) DeleteProjectPackage(pid interface{}, 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)
}
// DeletePackageFile deletes a file in project package
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/packages.html#delete-a-package-file
func (s *PackagesService) DeletePackageFile(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
type PagesService struct {
client *Client
}
// UnpublishPages unpublished pages. The user must have admin privileges.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages.html#unpublish-pages
func (s *PagesService) UnpublishPages(gid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// PagesDomainsService handles communication with the pages domains
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pages_domains.html
type PagesDomainsService struct {
client *Client
}
// PagesDomain represents a pages domain.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pages_domains.html
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"`
}
// ListPagesDomainsOptions represents the available ListPagesDomains() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#list-pages-domains
type ListPagesDomainsOptions ListOptions
// ListPagesDomains gets a list of project pages domains.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#list-pages-domains
func (s *PagesDomainsService) ListPagesDomains(pid interface{}, 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
}
// ListAllPagesDomains gets a list of all pages domains.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#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
}
// GetPagesDomain get a specific pages domain for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#single-pages-domain
func (s *PagesDomainsService) GetPagesDomain(pid interface{}, 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
}
// CreatePagesDomainOptions represents the available CreatePagesDomain() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#create-new-pages-domain
type CreatePagesDomainOptions struct {
Domain *string `url:"domain,omitempty" json:"domain,omitempty"`
AutoSslEnabled *bool `url:"auto_ssl_enabled,omitempty" json:"auto_ssl_enabled,omitempty"`
Certificate *string `url:"certificate,omitempty" json:"certificate,omitempty"`
Key *string `url:"key,omitempty" json:"key,omitempty"`
}
// CreatePagesDomain creates a new project pages domain.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#create-new-pages-domain
func (s *PagesDomainsService) CreatePagesDomain(pid interface{}, 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
}
// UpdatePagesDomainOptions represents the available UpdatePagesDomain() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#update-pages-domain
type UpdatePagesDomainOptions struct {
AutoSslEnabled *bool `url:"auto_ssl_enabled,omitempty" json:"auto_ssl_enabled,omitempty"`
Certificate *string `url:"certificate,omitempty" json:"certificate,omitempty"`
Key *string `url:"key,omitempty" json:"key,omitempty"`
}
// UpdatePagesDomain updates an existing project pages domain.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#update-pages-domain
func (s *PagesDomainsService) UpdatePagesDomain(pid interface{}, 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
}
// DeletePagesDomain deletes an existing prject pages domain.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pages_domains.html#delete-pages-domain
func (s *PagesDomainsService) DeletePagesDomain(pid interface{}, 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)
}
//
// Copyright 2022, Ryan Glab <ryan.j.glab@gmail.com>
//
// 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 (
"fmt"
"net/http"
"time"
)
// PersonalAccessTokensService handles communication with the personal access
// tokens related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/personal_access_tokens.html
type PersonalAccessTokensService struct {
client *Client
}
// PersonalAccessToken represents a personal access token.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/personal_access_tokens.html
type PersonalAccessToken struct {
ID int `json:"id"`
Name string `json:"name"`
Revoked bool `json:"revoked"`
CreatedAt *time.Time `json:"created_at"`
Scopes []string `json:"scopes"`
UserID int `json:"user_id"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
Active bool `json:"active"`
ExpiresAt *ISOTime `json:"expires_at"`
Token string `json:"token,omitempty"`
}
func (p PersonalAccessToken) String() string {
return Stringify(p)
}
// ListPersonalAccessTokensOptions represents the available
// ListPersonalAccessTokens() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#list-personal-access-tokens
type ListPersonalAccessTokensOptions 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"`
UserID *int `url:"user_id,omitempty" json:"user_id,omitempty"`
}
// ListPersonalAccessTokens gets a list of all personal access tokens.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#list-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
}
// GetSinglePersonalAccessTokenByID get a single personal access token by its ID.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#using-a-personal-access-token-id
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
}
// GetSinglePersonalAccessToken get a single personal access token by using
// passing the token in a header.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#using-a-request-header
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
}
// RotatePersonalAccessTokenOptions represents the available RotatePersonalAccessToken()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#rotate-a-personal-access-token
type RotatePersonalAccessTokenOptions struct {
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// RotatePersonalAccessToken is a backwards-compat shim for RotatePersonalAccessTokenByID.
func (s *PersonalAccessTokensService) RotatePersonalAccessToken(token int, opt *RotatePersonalAccessTokenOptions, options ...RequestOptionFunc) (*PersonalAccessToken, *Response, error) {
return s.RotatePersonalAccessTokenByID(token, opt, options...)
}
// RotatePersonalAccessTokenByID revokes a token and returns a new token that
// expires in one week per default.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#use-a-personal-access-token-id
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
}
// RotatePersonalAccessTokenSelf revokes the currently authenticated token
// and returns a new token that expires in one week per default.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#use-a-request-header
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
}
// RevokePersonalAccessToken is a backwards-compat shim for RevokePersonalAccessTokenByID.
func (s *PersonalAccessTokensService) RevokePersonalAccessToken(token int, options ...RequestOptionFunc) (*Response, error) {
return s.RevokePersonalAccessTokenByID(token, options...)
}
// RevokePersonalAccessTokenByID revokes a personal access token by its ID.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#using-a-personal-access-token-id-1
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)
}
// RevokePersonalAccessTokenSelf revokes the currently authenticated
// personal access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/personal_access_tokens.html#using-a-request-header-1
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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// PipelineSchedulesService handles communication with the pipeline
// schedules related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipeline_schedules.html
type PipelineSchedulesService struct {
client *Client
}
// PipelineSchedule represents a pipeline schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html
type PipelineSchedule struct {
ID int `json:"id"`
Description string `json:"description"`
Ref string `json:"ref"`
Cron string `json:"cron"`
CronTimezone string `json:"cron_timezone"`
NextRunAt *time.Time `json:"next_run_at"`
Active bool `json:"active"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
Owner *User `json:"owner"`
LastPipeline *LastPipeline `json:"last_pipeline"`
Variables []*PipelineVariable `json:"variables"`
}
// 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"`
SHA string `json:"sha"`
Ref string `json:"ref"`
Status string `json:"status"`
WebURL string `json:"web_url"`
}
// ListPipelineSchedulesOptions represents the available ListPipelineTriggers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#get-all-pipeline-schedules
type ListPipelineSchedulesOptions ListOptions
// ListPipelineSchedules gets a list of project triggers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#get-all-pipeline-schedules
func (s *PipelineSchedulesService) ListPipelineSchedules(pid interface{}, 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
}
// GetPipelineSchedule gets a pipeline schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#get-a-single-pipeline-schedule
func (s *PipelineSchedulesService) GetPipelineSchedule(pid interface{}, 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
}
// ListPipelinesTriggeredByScheduleOptions represents the available
// ListPipelinesTriggeredBySchedule() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#get-all-pipelines-triggered-by-a-pipeline-schedule
type ListPipelinesTriggeredByScheduleOptions ListOptions
// ListPipelinesTriggeredBySchedule gets all pipelines triggered by a pipeline
// schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#get-all-pipelines-triggered-by-a-pipeline-schedule
func (s *PipelineSchedulesService) ListPipelinesTriggeredBySchedule(pid interface{}, 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
}
// CreatePipelineScheduleOptions represents the available
// CreatePipelineSchedule() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#create-a-new-pipeline-schedule
type CreatePipelineScheduleOptions struct {
Description *string `url:"description" json:"description"`
Ref *string `url:"ref" json:"ref"`
Cron *string `url:"cron" json:"cron"`
CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
Active *bool `url:"active,omitempty" json:"active,omitempty"`
}
// CreatePipelineSchedule creates a pipeline schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#create-a-new-pipeline-schedule
func (s *PipelineSchedulesService) CreatePipelineSchedule(pid interface{}, 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
}
// EditPipelineScheduleOptions represents the available
// EditPipelineSchedule() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#edit-a-pipeline-schedule
type EditPipelineScheduleOptions struct {
Description *string `url:"description,omitempty" json:"description,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
Cron *string `url:"cron,omitempty" json:"cron,omitempty"`
CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
Active *bool `url:"active,omitempty" json:"active,omitempty"`
}
// EditPipelineSchedule edits a pipeline schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#edit-a-pipeline-schedule
func (s *PipelineSchedulesService) EditPipelineSchedule(pid interface{}, 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
}
// TakeOwnershipOfPipelineSchedule sets the owner of the specified
// pipeline schedule to the user issuing the request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#take-ownership-of-a-pipeline-schedule
func (s *PipelineSchedulesService) TakeOwnershipOfPipelineSchedule(pid interface{}, 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
}
// DeletePipelineSchedule deletes a pipeline schedule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#delete-a-pipeline-schedule
func (s *PipelineSchedulesService) DeletePipelineSchedule(pid interface{}, 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)
}
// RunPipelineSchedule triggers a new scheduled pipeline to run immediately.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#run-a-scheduled-pipeline-immediately
func (s *PipelineSchedulesService) RunPipelineSchedule(pid interface{}, 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)
}
// CreatePipelineScheduleVariableOptions represents the available
// CreatePipelineScheduleVariable() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#create-a-new-pipeline-schedule
type CreatePipelineScheduleVariableOptions struct {
Key *string `url:"key" json:"key"`
Value *string `url:"value" json:"value"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// CreatePipelineScheduleVariable creates a pipeline schedule variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#create-a-new-pipeline-schedule
func (s *PipelineSchedulesService) CreatePipelineScheduleVariable(pid interface{}, 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
}
// EditPipelineScheduleVariableOptions represents the available
// EditPipelineScheduleVariable() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable
type EditPipelineScheduleVariableOptions struct {
Value *string `url:"value" json:"value"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// EditPipelineScheduleVariable creates a pipeline schedule variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable
func (s *PipelineSchedulesService) EditPipelineScheduleVariable(pid interface{}, 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
}
// DeletePipelineScheduleVariable creates a pipeline schedule variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_schedules.html#delete-a-pipeline-schedule-variable
func (s *PipelineSchedulesService) DeletePipelineScheduleVariable(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// PipelineTriggersService handles Project pipeline triggers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html
type PipelineTriggersService struct {
client *Client
}
// PipelineTrigger represents a project pipeline trigger.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html
type PipelineTrigger struct {
ID int `json:"id"`
Description string `json:"description"`
CreatedAt *time.Time `json:"created_at"`
DeletedAt *time.Time `json:"deleted_at"`
LastUsed *time.Time `json:"last_used"`
Token string `json:"token"`
UpdatedAt *time.Time `json:"updated_at"`
Owner *User `json:"owner"`
}
// ListPipelineTriggersOptions represents the available ListPipelineTriggers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#list-project-trigger-tokens
type ListPipelineTriggersOptions ListOptions
// ListPipelineTriggers gets a list of project triggers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#list-project-trigger-tokens
func (s *PipelineTriggersService) ListPipelineTriggers(pid interface{}, 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
}
// GetPipelineTrigger gets a specific pipeline trigger for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#get-trigger-token-details
func (s *PipelineTriggersService) GetPipelineTrigger(pid interface{}, 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
}
// AddPipelineTriggerOptions represents the available AddPipelineTrigger() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#create-a-trigger-token
type AddPipelineTriggerOptions struct {
Description *string `url:"description,omitempty" json:"description,omitempty"`
}
// AddPipelineTrigger adds a pipeline trigger to a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#create-a-trigger-token
func (s *PipelineTriggersService) AddPipelineTrigger(pid interface{}, 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
}
// EditPipelineTriggerOptions represents the available EditPipelineTrigger() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#update-a-project-trigger-token
type EditPipelineTriggerOptions struct {
Description *string `url:"description,omitempty" json:"description,omitempty"`
}
// EditPipelineTrigger edits a trigger for a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#update-a-project-trigger-token
func (s *PipelineTriggersService) EditPipelineTrigger(pid interface{}, 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
}
// TakeOwnershipOfPipelineTrigger sets the owner of the specified
// pipeline trigger to the user issuing the request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#take-ownership-of-a-project-trigger
func (s *PipelineTriggersService) TakeOwnershipOfPipelineTrigger(pid interface{}, 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/take_ownership", PathEscape(project), trigger)
req, err := s.client.NewRequest(http.MethodPost, 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
}
// DeletePipelineTrigger removes a trigger from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#remove-a-project-trigger-token
func (s *PipelineTriggersService) DeletePipelineTrigger(pid interface{}, 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)
}
// RunPipelineTriggerOptions represents the available RunPipelineTrigger() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#trigger-a-pipeline-with-a-token
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"`
}
// RunPipelineTrigger starts a trigger from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipeline_triggers.html#trigger-a-pipeline-with-a-token
func (s *PipelineTriggersService) RunPipelineTrigger(pid interface{}, 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
}
//
// Copyright 2021, Igor Varavko
//
// 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 (
"fmt"
"net/http"
"time"
)
// PipelinesService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html
type PipelinesService struct {
client *Client
}
// PipelineVariable represents a pipeline variable.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html
type PipelineVariable struct {
Key string `json:"key"`
Value string `json:"value"`
VariableType VariableTypeValue `json:"variable_type"`
}
// Pipeline represents a GitLab pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html
type Pipeline struct {
ID int `json:"id"`
IID int `json:"iid"`
ProjectID int `json:"project_id"`
Status string `json:"status"`
Source string `json:"source"`
Ref string `json:"ref"`
Name string `json:"name"`
SHA string `json:"sha"`
BeforeSHA string `json:"before_sha"`
Tag bool `json:"tag"`
YamlErrors string `json:"yaml_errors"`
User *BasicUser `json:"user"`
UpdatedAt *time.Time `json:"updated_at"`
CreatedAt *time.Time `json:"created_at"`
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"`
Coverage string `json:"coverage"`
WebURL string `json:"web_url"`
DetailedStatus *DetailedStatus `json:"detailed_status"`
}
// 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"`
}
func (p Pipeline) String() string {
return Stringify(p)
}
// 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"`
TestSuites []*PipelineTestSuites `json:"test_suites"`
}
// PipelineTestSuites contains test suites results.
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"`
TestCases []*PipelineTestCases `json:"test_cases"`
}
// PipelineTestCases contains test cases details.
type PipelineTestCases struct {
Status string `json:"status"`
Name string `json:"name"`
Classname string `json:"classname"`
File string `json:"file"`
ExecutionTime float64 `json:"execution_time"`
SystemOutput interface{} `json:"system_output"`
StackTrace string `json:"stack_trace"`
AttachmentURL string `json:"attachment_url"`
RecentFailures *RecentFailures `json:"recent_failures"`
}
// RecentFailures contains failures count for the project's default branch.
type RecentFailures struct {
Count int `json:"count"`
BaseBranch string `json:"base_branch"`
}
func (p PipelineTestReport) String() string {
return Stringify(p)
}
// 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"`
Status string `json:"status"`
Source string `json:"source"`
Ref string `json:"ref"`
SHA string `json:"sha"`
WebURL string `json:"web_url"`
UpdatedAt *time.Time `json:"updated_at"`
CreatedAt *time.Time `json:"created_at"`
}
func (p PipelineInfo) String() string {
return Stringify(p)
}
// ListProjectPipelinesOptions represents the available ListProjectPipelines() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#list-project-pipelines
type ListProjectPipelinesOptions struct {
ListOptions
Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
Status *BuildStateValue `url:"status,omitempty" json:"status,omitempty"`
Source *string `url:"source,omitempty" json:"source,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
YamlErrors *bool `url:"yaml_errors,omitempty" json:"yaml_errors,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
UpdatedAfter *time.Time `url:"updated_after,omitempty" json:"updated_after,omitempty"`
UpdatedBefore *time.Time `url:"updated_before,omitempty" json:"updated_before,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// ListProjectPipelines gets a list of project piplines.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#list-project-pipelines
func (s *PipelinesService) ListProjectPipelines(pid interface{}, 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
}
// GetPipeline gets a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-a-single-pipeline
func (s *PipelinesService) GetPipeline(pid interface{}, 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
}
// GetPipelineVariables gets the variables of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-variables-of-a-pipeline
func (s *PipelinesService) GetPipelineVariables(pid interface{}, 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
}
// GetPipelineTestReport gets the test report of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-a-pipelines-test-report
func (s *PipelinesService) GetPipelineTestReport(pid interface{}, 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
}
return p, resp, nil
}
// GetLatestPipelineOptions represents the available GetLatestPipeline() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-the-latest-pipeline
type GetLatestPipelineOptions struct {
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// GetLatestPipeline gets the latest pipeline for a specific ref in a project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-the-latest-pipeline
func (s *PipelinesService) GetLatestPipeline(pid interface{}, 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
}
// CreatePipelineOptions represents the available CreatePipeline() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#create-a-new-pipeline
type CreatePipelineOptions struct {
Ref *string `url:"ref" json:"ref"`
Variables *[]*PipelineVariableOptions `url:"variables,omitempty" json:"variables,omitempty"`
}
// PipelineVariable represents a pipeline variable.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#create-a-new-pipeline
type PipelineVariableOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Value *string `url:"value,omitempty" json:"value,omitempty"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// CreatePipeline creates a new project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#create-a-new-pipeline
func (s *PipelinesService) CreatePipeline(pid interface{}, 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))
req, err := s.client.NewRequest(http.MethodPost, 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
}
// RetryPipelineBuild retries failed builds in a pipeline
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipelines.html#retry-jobs-in-a-pipeline
func (s *PipelinesService) RetryPipelineBuild(pid interface{}, 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
}
// CancelPipelineBuild cancels a pipeline builds
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipelines.html#cancel-a-pipelines-jobs
func (s *PipelinesService) CancelPipelineBuild(pid interface{}, 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
}
// DeletePipeline deletes an existing pipeline.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/pipelines.html#delete-a-pipeline
func (s *PipelinesService) DeletePipeline(pid interface{}, 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)
}
//
// Copyright 2021, Igor Varavko
//
// 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"
// PlanLimitsService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/plan_limits.html
type PlanLimitsService struct {
client *Client
}
// PlanLimit represents a GitLab pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/plan_limits.html
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"`
}
// GetCurrentPlanLimitsOptions represents the available GetCurrentPlanLimits()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/plan_limits.html#get-current-plan-limits
type GetCurrentPlanLimitsOptions struct {
PlanName *string `url:"plan_name,omitempty" json:"plan_name,omitempty"`
}
// List the current limits of a plan on the GitLab instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/plan_limits.html#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
}
// ChangePlanLimitOptions represents the available ChangePlanLimits() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/plan_limits.html#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"`
}
// ChangePlanLimits modifies the limits of a plan on the GitLab instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/plan_limits.html#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
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"time"
)
// ProjectAccessTokensService handles communication with the
// project access tokens related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_access_tokens.html
type ProjectAccessTokensService struct {
client *Client
}
// ProjectAccessToken represents a GitLab project access token.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_access_tokens.html
type ProjectAccessToken struct {
ID int `json:"id"`
UserID int `json:"user_id"`
Name string `json:"name"`
Scopes []string `json:"scopes"`
CreatedAt *time.Time `json:"created_at"`
LastUsedAt *time.Time `json:"last_used_at"`
ExpiresAt *ISOTime `json:"expires_at"`
Active bool `json:"active"`
Revoked bool `json:"revoked"`
Token string `json:"token"`
AccessLevel AccessLevelValue `json:"access_level"`
}
func (v ProjectAccessToken) String() string {
return Stringify(v)
}
// ListProjectAccessTokensOptions represents the available
// ListProjectAccessTokens() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#list-project-access-tokens
type ListProjectAccessTokensOptions ListOptions
// ListProjectAccessTokens gets a list of all project access tokens in a
// project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#list-project-access-tokens
func (s *ProjectAccessTokensService) ListProjectAccessTokens(pid interface{}, 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
}
// GetProjectAccessToken gets a single project access tokens in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#get-a-project-access-token
func (s *ProjectAccessTokensService) GetProjectAccessToken(pid interface{}, 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
}
// CreateProjectAccessTokenOptions represents the available CreateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#create-a-project-access-token
type CreateProjectAccessTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// CreateProjectAccessToken creates a new project access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#create-a-project-access-token
func (s *ProjectAccessTokensService) CreateProjectAccessToken(pid interface{}, 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
}
// RotateProjectAccessTokenOptions represents the available RotateProjectAccessToken()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#rotate-a-project-access-token
type RotateProjectAccessTokenOptions struct {
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// RotateProjectAccessToken revokes a project access token and returns a new
// project access token that expires in one week per default.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#rotate-a-project-access-token
func (s *ProjectAccessTokensService) RotateProjectAccessToken(pid interface{}, 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
}
// RevokeProjectAccessToken revokes a project access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_access_tokens.html#revoke-a-project-access-token
func (s *ProjectAccessTokensService) RevokeProjectAccessToken(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ProjectBadge represents a project badge.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#list-all-badges-of-a-project
type ProjectBadge struct {
ID int `json:"id"`
Name string `json:"name"`
LinkURL string `json:"link_url"`
ImageURL string `json:"image_url"`
RenderedLinkURL string `json:"rendered_link_url"`
RenderedImageURL string `json:"rendered_image_url"`
// Kind represents a project badge kind. Can be empty, when used PreviewProjectBadge().
Kind string `json:"kind"`
}
// ProjectBadgesService handles communication with the project badges
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_badges.html
type ProjectBadgesService struct {
client *Client
}
// ListProjectBadgesOptions represents the available ListProjectBadges()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#list-all-badges-of-a-project
type ListProjectBadgesOptions struct {
ListOptions
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// ListProjectBadges gets a list of a project's badges and its group badges.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#list-all-badges-of-a-project
func (s *ProjectBadgesService) ListProjectBadges(pid interface{}, 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
}
// GetProjectBadge gets a project badge.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#get-a-badge-of-a-project
func (s *ProjectBadgesService) GetProjectBadge(pid interface{}, 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
}
// AddProjectBadgeOptions represents the available AddProjectBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#add-a-badge-to-a-project
type AddProjectBadgeOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// AddProjectBadge adds a badge to a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#add-a-badge-to-a-project
func (s *ProjectBadgesService) AddProjectBadge(pid interface{}, 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
}
// EditProjectBadgeOptions represents the available EditProjectBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#edit-a-badge-of-a-project
type EditProjectBadgeOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
}
// EditProjectBadge updates a badge of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#edit-a-badge-of-a-project
func (s *ProjectBadgesService) EditProjectBadge(pid interface{}, 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
}
// DeleteProjectBadge removes a badge from a project. Only project's
// badges will be removed by using this endpoint.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#remove-a-badge-from-a-project
func (s *ProjectBadgesService) DeleteProjectBadge(pid interface{}, 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)
}
// ProjectBadgePreviewOptions represents the available PreviewProjectBadge() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#preview-a-badge-from-a-project
type ProjectBadgePreviewOptions struct {
LinkURL *string `url:"link_url,omitempty" json:"link_url,omitempty"`
ImageURL *string `url:"image_url,omitempty" json:"image_url,omitempty"`
}
// PreviewProjectBadge returns how the link_url and image_url final URLs would be after
// resolving the placeholder interpolation.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_badges.html#preview-a-badge-from-a-project
func (s *ProjectBadgesService) PreviewProjectBadge(pid interface{}, 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
}
//
// Copyright 2021, Matej Velikonja
//
// 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 (
"fmt"
"net/http"
"time"
)
// ProjectClustersService handles communication with the
// project clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html
type ProjectClustersService struct {
client *Client
}
// ProjectCluster represents a GitLab Project Cluster.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_clusters.html
type ProjectCluster struct {
ID int `json:"id"`
Name string `json:"name"`
Domain string `json:"domain"`
CreatedAt *time.Time `json:"created_at"`
ProviderType string `json:"provider_type"`
PlatformType string `json:"platform_type"`
EnvironmentScope string `json:"environment_scope"`
ClusterType string `json:"cluster_type"`
User *User `json:"user"`
PlatformKubernetes *PlatformKubernetes `json:"platform_kubernetes"`
ManagementProject *ManagementProject `json:"management_project"`
Project *Project `json:"project"`
}
func (v ProjectCluster) String() string {
return Stringify(v)
}
// PlatformKubernetes represents a GitLab Project Cluster PlatformKubernetes.
type PlatformKubernetes struct {
APIURL string `json:"api_url"`
Token string `json:"token"`
CaCert string `json:"ca_cert"`
Namespace string `json:"namespace"`
AuthorizationType string `json:"authorization_type"`
}
// ManagementProject represents a GitLab Project Cluster management_project.
type ManagementProject 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"`
}
// ListClusters gets a list of all clusters in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#list-project-clusters
func (s *ProjectClustersService) ListClusters(pid interface{}, 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
}
// GetCluster gets a cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#get-a-single-project-cluster
func (s *ProjectClustersService) GetCluster(pid interface{}, 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
}
// AddClusterOptions represents the available AddCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#add-existing-cluster-to-project
type AddClusterOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Domain *string `url:"domain,omitempty" json:"domain,omitempty"`
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
Managed *bool `url:"managed,omitempty" json:"managed,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
PlatformKubernetes *AddPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
ManagementProjectID *string `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
}
// AddPlatformKubernetesOptions represents the available PlatformKubernetes options for adding.
type AddPlatformKubernetesOptions struct {
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"`
AuthorizationType *string `url:"authorization_type,omitempty" json:"authorization_type,omitempty"`
}
// AddCluster adds an existing cluster to the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#add-existing-cluster-to-project
func (s *ProjectClustersService) AddCluster(pid interface{}, 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
}
// EditClusterOptions represents the available EditCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#edit-project-cluster
type EditClusterOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Domain *string `url:"domain,omitempty" json:"domain,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
ManagementProjectID *string `url:"management_project_id,omitempty" json:"management_project_id,omitempty"`
PlatformKubernetes *EditPlatformKubernetesOptions `url:"platform_kubernetes_attributes,omitempty" json:"platform_kubernetes_attributes,omitempty"`
}
// EditPlatformKubernetesOptions represents the available PlatformKubernetes options for editing.
type EditPlatformKubernetesOptions struct {
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
CaCert *string `url:"ca_cert,omitempty" json:"ca_cert,omitempty"`
Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"`
}
// EditCluster updates an existing project cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#edit-project-cluster
func (s *ProjectClustersService) EditCluster(pid interface{}, 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
}
// DeleteCluster deletes an existing project cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#delete-project-cluster
func (s *ProjectClustersService) DeleteCluster(pid interface{}, 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)
}
package gitlab
import (
"fmt"
"net/http"
"time"
)
// ProjectFeatureFlagService handles operations on gitlab project feature
// flags using the following api:
//
// GitLab API docs: https://docs.gitlab.com/ee/api/feature_flags.html
type ProjectFeatureFlagService struct {
client *Client
}
// ProjectFeatureFlag represents a GitLab project iteration.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/feature_flags.html
type ProjectFeatureFlag struct {
Name string `json:"name"`
Description string `json:"description"`
Active bool `json:"active"`
Version string `json:"version"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
Scopes []*ProjectFeatureFlagScope `json:"scopes"`
Strategies []*ProjectFeatureFlagStrategy `json:"strategies"`
}
// ProjectFeatureFlagScope defines the scopes of a feature flag
//
// GitLab API docs: https://docs.gitlab.com/ee/api/feature_flags.html
type ProjectFeatureFlagScope struct {
ID int `json:"id"`
EnvironmentScope string `json:"environment_scope"`
}
// ProjectFeatureFlagStrategy defines the strategy used for a feature flag
//
// GitLab API docs: https://docs.gitlab.com/ee/api/feature_flags.html
type ProjectFeatureFlagStrategy struct {
ID int `json:"id"`
Name string `json:"name"`
Parameters *ProjectFeatureFlagStrategyParameter `json:"parameters"`
Scopes []*ProjectFeatureFlagScope `json:"scopes"`
}
// ProjectFeatureFlagStrategyParameter is used in updating and creating feature flags
//
// GitLab API docs: https://docs.gitlab.com/ee/api/feature_flags.html
type ProjectFeatureFlagStrategyParameter struct {
GroupID string `json:"groupId,omitempty"`
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.
// Docs: https://docs.getunleash.io/reference/activation-strategies#gradual-rollout
Rollout string `json:"rollout,omitempty"`
Stickiness string `json:"stickiness,omitempty"`
}
func (i ProjectFeatureFlag) String() string {
return Stringify(i)
}
// ListProjectFeatureFlagOptions contains the options for ListProjectFeatureFlags
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#list-feature-flags-for-a-project
type ListProjectFeatureFlagOptions struct {
ListOptions
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/ee/api/feature_flags.html#list-feature-flags-for-a-project
func (s *ProjectFeatureFlagService) ListProjectFeatureFlags(pid interface{}, 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
}
// GetProjectFeatureFlag gets a single feature flag for the specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#get-a-single-feature-flag
func (s *ProjectFeatureFlagService) GetProjectFeatureFlag(pid interface{}, 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
}
// CreateProjectFeatureFlagOptions represents the available
// CreateProjectFeatureFlag() options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#create-a-feature-flag
type CreateProjectFeatureFlagOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Version *string `url:"version,omitempty" json:"version,omitempty"`
Active *bool `url:"active,omitempty" json:"active,omitempty"`
Strategies *[]*FeatureFlagStrategyOptions `url:"strategies,omitempty" json:"strategies,omitempty"`
}
// FeatureFlagStrategyOptions represents the available feature flag strategy
// options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#create-a-feature-flag
type FeatureFlagStrategyOptions struct {
ID *int `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"`
}
// ProjectFeatureFlagScopeOptions represents the available feature flag scope
// options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#create-a-feature-flag
type ProjectFeatureFlagScopeOptions struct {
ID *int `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/ee/api/feature_flags.html#create-a-feature-flag
func (s *ProjectFeatureFlagService) CreateProjectFeatureFlag(pid interface{}, 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),
)
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:
// https://docs.gitlab.com/ee/api/feature_flags.html#update-a-feature-flag
type UpdateProjectFeatureFlagOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Active *bool `url:"active,omitempty" json:"active,omitempty"`
Strategies *[]*FeatureFlagStrategyOptions `url:"strategies,omitempty" json:"strategies,omitempty"`
}
// UpdateProjectFeatureFlag updates a feature flag
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/feature_flags.html#update-a-feature-flag
func (s *ProjectFeatureFlagService) UpdateProjectFeatureFlag(pid interface{}, 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,
)
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/ee/api/feature_flags.html#delete-a-feature-flag
func (s *ProjectFeatureFlagService) DeleteProjectFeatureFlag(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"io"
"net/http"
"time"
)
// ProjectImportExportService handles communication with the project
// import/export related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html
type ProjectImportExportService struct {
client *Client
}
// ImportStatus represents a project import status.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#import-status
type ImportStatus 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"`
CreateAt *time.Time `json:"create_at"`
ImportStatus string `json:"import_status"`
ImportType string `json:"import_type"`
CorrelationID string `json:"correlation_id"`
ImportError string `json:"import_error"`
}
func (s ImportStatus) String() string {
return Stringify(s)
}
// ExportStatus represents a project export status.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#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"`
}
func (s ExportStatus) String() string {
return Stringify(s)
}
// ScheduleExportOptions represents the available ScheduleExport() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#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"`
}
// ScheduleExport schedules a project export.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#schedule-an-export
func (s *ProjectImportExportService) ScheduleExport(pid interface{}, opt *ScheduleExportOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/export", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ExportStatus get the status of export.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#export-status
func (s *ProjectImportExportService) ExportStatus(pid interface{}, 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
}
// ExportDownload download the finished export.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#export-download
func (s *ProjectImportExportService) ExportDownload(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// ImportFileOptions represents the available ImportFile() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#import-a-file
type ImportFileOptions struct {
Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
Overwrite *bool `url:"overwrite,omitempty" json:"overwrite,omitempty"`
OverrideParams *CreateProjectOptions `url:"override_params,omitempty" json:"override_params,omitempty"`
}
// Import a project from an archive file.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_import_export.html#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,
)
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/ee/api/project_import_export.html#import-status
func (s *ProjectImportExportService) ImportStatus(pid interface{}, 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
}
//
// Copyright 2022, Daniel Steinke
//
// 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 (
"fmt"
"net/http"
"time"
)
// IterationsAPI handles communication with the project iterations related
// methods of the GitLab API
//
// GitLab API docs: https://docs.gitlab.com/ee/api/iterations.html
type ProjectIterationsService struct {
client *Client
}
// ProjectIteration represents a GitLab project iteration.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/iterations.html
type ProjectIteration struct {
ID int `json:"id"`
IID int `json:"iid"`
Sequence int `json:"sequence"`
GroupID int `json:"group_id"`
Title string `json:"title"`
Description string `json:"description"`
State int `json:"state"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
DueDate *ISOTime `json:"due_date"`
StartDate *ISOTime `json:"start_date"`
WebURL string `json:"web_url"`
}
func (i ProjectIteration) String() string {
return Stringify(i)
}
// ListProjectIterationsOptions contains the available ListProjectIterations()
// options
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations
type ListProjectIterationsOptions struct {
ListOptions
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"`
}
// ListProjectIterations returns a list of projects iterations.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations
func (i *ProjectIterationsService) ListProjectIterations(pid interface{}, 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
}
//
// Copyright 2021, Andrea Perizzato
//
// 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 (
"fmt"
"net/http"
)
// ManagedLicensesService handles communication with the managed licenses
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/managed_licenses.html
type ManagedLicensesService struct {
client *Client
}
// ManagedLicense represents a managed license.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/managed_licenses.html
type ManagedLicense struct {
ID int `json:"id"`
Name string `json:"name"`
ApprovalStatus LicenseApprovalStatusValue `json:"approval_status"`
}
// ListManagedLicenses returns a list of managed licenses from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#list-managed-licenses
func (s *ManagedLicensesService) ListManagedLicenses(pid interface{}, options ...RequestOptionFunc) ([]*ManagedLicense, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/managed_licenses", PathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
var mls []*ManagedLicense
resp, err := s.client.Do(req, &mls)
if err != nil {
return nil, resp, err
}
return mls, resp, nil
}
// GetManagedLicense returns an existing managed license.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#show-an-existing-managed-license
func (s *ManagedLicensesService) GetManagedLicense(pid, mlid interface{}, options ...RequestOptionFunc) (*ManagedLicense, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
license, err := parseID(mlid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/managed_licenses/%s", PathEscape(project), PathEscape(license))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
ml := new(ManagedLicense)
resp, err := s.client.Do(req, ml)
if err != nil {
return nil, resp, err
}
return ml, resp, nil
}
// AddManagedLicenseOptions represents the available AddManagedLicense() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#create-a-new-managed-license
type AddManagedLicenseOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ApprovalStatus *LicenseApprovalStatusValue `url:"approval_status,omitempty" json:"approval_status,omitempty"`
}
// AddManagedLicense adds a managed license to a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#create-a-new-managed-license
func (s *ManagedLicensesService) AddManagedLicense(pid interface{}, opt *AddManagedLicenseOptions, options ...RequestOptionFunc) (*ManagedLicense, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/managed_licenses", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
ml := new(ManagedLicense)
resp, err := s.client.Do(req, ml)
if err != nil {
return nil, resp, err
}
return ml, resp, nil
}
// DeleteManagedLicense deletes a managed license with a given ID.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#delete-a-managed-license
func (s *ManagedLicensesService) DeleteManagedLicense(pid, mlid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
license, err := parseID(mlid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/managed_licenses/%s", PathEscape(project), PathEscape(license))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// EditManagedLicenceOptions represents the available EditManagedLicense() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#edit-an-existing-managed-license
type EditManagedLicenceOptions struct {
ApprovalStatus *LicenseApprovalStatusValue `url:"approval_status,omitempty" json:"approval_status,omitempty"`
}
// EditManagedLicense updates an existing managed license with a new approval
// status.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/managed_licenses.html#edit-an-existing-managed-license
func (s *ManagedLicensesService) EditManagedLicense(pid, mlid interface{}, opt *EditManagedLicenceOptions, options ...RequestOptionFunc) (*ManagedLicense, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
license, err := parseID(mlid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/managed_licenses/%s", PathEscape(project), PathEscape(license))
req, err := s.client.NewRequest(http.MethodPatch, u, opt, options)
if err != nil {
return nil, nil, err
}
ml := new(ManagedLicense)
resp, err := s.client.Do(req, ml)
if err != nil {
return nil, resp, err
}
return ml, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ProjectMembersService handles communication with the project members
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/members.html
type ProjectMembersService struct {
client *Client
}
// ListProjectMembersOptions represents the available ListProjectMembers() and
// ListAllProjectMembers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#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"`
}
// ListProjectMembers gets a list of a project's team members viewable by the
// authenticated user. Returns only direct members and not inherited members
// through ancestors groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project
func (s *ProjectMembersService) ListProjectMembers(pid interface{}, 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
}
// ListAllProjectMembers gets a list of a project's team members viewable by the
// authenticated user. Returns a list including inherited members through
// ancestor groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project-including-inherited-and-invited-members
func (s *ProjectMembersService) ListAllProjectMembers(pid interface{}, 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
}
// GetProjectMember gets a project team member.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#get-a-member-of-a-group-or-project
func (s *ProjectMembersService) GetProjectMember(pid interface{}, 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
}
// GetInheritedProjectMember gets a project team member, including inherited
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#get-a-member-of-a-group-or-project-including-inherited-and-invited-members
func (s *ProjectMembersService) GetInheritedProjectMember(pid interface{}, 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
}
// AddProjectMemberOptions represents the available AddProjectMember() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#add-a-member-to-a-group-or-project
type AddProjectMemberOptions struct {
UserID interface{} `url:"user_id,omitempty" json:"user_id,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"`
}
// AddProjectMember adds a user to a project team. This is an idempotent
// method and can be called multiple times with the same parameters. Adding
// team membership to a user that is already a member does not affect the
// existing membership.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#add-a-member-to-a-group-or-project
func (s *ProjectMembersService) AddProjectMember(pid interface{}, 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
}
// EditProjectMemberOptions represents the available EditProjectMember() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#edit-a-member-of-a-group-or-project
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"`
}
// EditProjectMember updates a project team member to a specified access level..
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#edit-a-member-of-a-group-or-project
func (s *ProjectMembersService) EditProjectMember(pid interface{}, 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
}
// DeleteProjectMember removes a user from a project team.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#remove-a-member-from-a-group-or-project
func (s *ProjectMembersService) DeleteProjectMember(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ProjectMirrorService handles communication with the project mirror
// related methods of the GitLab API.
//
// GitLAb API docs: https://docs.gitlab.com/ee/api/remote_mirrors.html
type ProjectMirrorService struct {
client *Client
}
// ProjectMirror represents a project mirror configuration.
//
// GitLAb API docs: https://docs.gitlab.com/ee/api/remote_mirrors.html
type ProjectMirror struct {
Enabled bool `json:"enabled"`
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"`
MirrorBranchRegex string `json:"mirror_branch_regex"`
OnlyProtectedBranches bool `json:"only_protected_branches"`
KeepDivergentRefs bool `json:"keep_divergent_refs"`
UpdateStatus string `json:"update_status"`
URL string `json:"url"`
}
// ListProjectMirrorOptions represents the available ListProjectMirror() options.
type ListProjectMirrorOptions ListOptions
// ListProjectMirror gets a list of mirrors configured on the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#list-a-projects-remote-mirrors
func (s *ProjectMirrorService) ListProjectMirror(pid interface{}, 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
}
// GetProjectMirror gets a single mirror configured on the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#get-a-single-projects-remote-mirror
func (s *ProjectMirrorService) GetProjectMirror(pid interface{}, 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
}
// AddProjectMirrorOptions contains the properties requires to create
// a new project mirror.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#create-a-push-mirror
type AddProjectMirrorOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
KeepDivergentRefs *bool `url:"keep_divergent_refs,omitempty" json:"keep_divergent_refs,omitempty"`
OnlyProtectedBranches *bool `url:"only_protected_branches,omitempty" json:"only_protected_branches,omitempty"`
MirrorBranchRegex *string `url:"mirror_branch_regex,omitempty" json:"mirror_branch_regex,omitempty"`
}
// AddProjectMirror creates a new mirror on the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#create-a-push-mirror
func (s *ProjectMirrorService) AddProjectMirror(pid interface{}, 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
}
// EditProjectMirrorOptions contains the properties requires to edit
// an existing project mirror.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#update-a-remote-mirrors-attributes
type EditProjectMirrorOptions struct {
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
KeepDivergentRefs *bool `url:"keep_divergent_refs,omitempty" json:"keep_divergent_refs,omitempty"`
OnlyProtectedBranches *bool `url:"only_protected_branches,omitempty" json:"only_protected_branches,omitempty"`
MirrorBranchRegex *string `url:"mirror_branch_regex,omitempty" json:"mirror_branch_regex,omitempty"`
}
// EditProjectMirror updates a project team member to a specified access level..
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#update-a-remote-mirrors-attributes
func (s *ProjectMirrorService) EditProjectMirror(pid interface{}, 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
}
// DeleteProjectMirror deletes a project mirror.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/remote_mirrors.html#delete-a-remote-mirror
func (s *ProjectMirrorService) DeleteProjectMirror(pid interface{}, 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
}
return s.client.Do(req, nil)
}
//
// Copyright 2023, Nick Westbury
//
// 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 (
"fmt"
"net/http"
"time"
)
// ProjectRepositoryStorageMoveService handles communication with the
// repositories related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html
type ProjectRepositoryStorageMoveService struct {
client *Client
}
// ProjectRepositoryStorageMove represents the status of a repository move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html
type ProjectRepositoryStorageMove struct {
ID int `json:"id"`
CreatedAt *time.Time `json:"created_at"`
State string `json:"state"`
SourceStorageName string `json:"source_storage_name"`
DestinationStorageName string `json:"destination_storage_name"`
Project *RepositoryProject `json:"project"`
}
type RepositoryProject 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"`
}
// RetrieveAllProjectStorageMovesOptions represents the available
// RetrieveAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#retrieve-all-project-repository-storage-moves
type RetrieveAllProjectStorageMovesOptions ListOptions
// RetrieveAllStorageMoves retrieves all project repository storage moves
// accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#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
}
// RetrieveAllStorageMovesForProject retrieves all repository storage moves for
// a single project accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#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
}
// GetStorageMove gets a single project repository storage move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#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
}
// GetStorageMoveForProject gets a single repository storage move for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#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
}
// ScheduleStorageMoveForProjectOptions represents the available
// ScheduleStorageMoveForProject() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#schedule-a-repository-storage-move-for-a-project
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/ee/api/project_repository_storage_moves.html#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
}
// ScheduleAllProjectStorageMovesOptions represents the available
// ScheduleAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_repository_storage_moves.html#schedule-repository-storage-moves-for-all-projects-on-a-storage-shard
type ScheduleAllProjectStorageMovesOptions struct {
SourceStorageName *string `url:"source_storage_name,omitempty" json:"source_storage_name,omitempty"`
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/ee/api/project_repository_storage_moves.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"net/http"
)
// ProjectSnippetsService handles communication with the project snippets
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_snippets.html
type ProjectSnippetsService struct {
client *Client
}
// ListProjectSnippetsOptions represents the available ListSnippets() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_snippets.html#list-snippets
type ListProjectSnippetsOptions ListOptions
// ListSnippets gets a list of project snippets.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_snippets.html#list-snippets
func (s *ProjectSnippetsService) ListSnippets(pid interface{}, 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
}
// GetSnippet gets a single project snippet
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#single-snippet
func (s *ProjectSnippetsService) GetSnippet(pid interface{}, 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
}
// CreateProjectSnippetOptions represents the available CreateSnippet() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#create-new-snippet
type CreateProjectSnippetOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
Files *[]*CreateSnippetFileOptions `url:"files,omitempty" json:"files,omitempty"`
}
// CreateSnippet creates a new project snippet. The user must have permission
// to create new snippets.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#create-new-snippet
func (s *ProjectSnippetsService) CreateSnippet(pid interface{}, 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
}
// UpdateProjectSnippetOptions represents the available UpdateSnippet() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#update-snippet
type UpdateProjectSnippetOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
Files *[]*UpdateSnippetFileOptions `url:"files,omitempty" json:"files,omitempty"`
}
// UpdateSnippet updates an existing project snippet. The user must have
// permission to change an existing snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#update-snippet
func (s *ProjectSnippetsService) UpdateSnippet(pid interface{}, 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
}
// DeleteSnippet deletes an existing project snippet. This is an idempotent
// function and deleting a non-existent snippet still returns a 200 OK status
// code.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#delete-snippet
func (s *ProjectSnippetsService) DeleteSnippet(pid interface{}, 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)
}
// SnippetContent returns the raw project snippet as plain text.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_snippets.html#snippet-content
func (s *ProjectSnippetsService) SnippetContent(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ProjectTemplatesService handles communication with the project templates
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_templates.html
type ProjectTemplatesService struct {
client *Client
}
// ProjectTemplate represents a GitLab ProjectTemplate.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_templates.html
type ProjectTemplate struct {
Key string `json:"key"`
Name string `json:"name"`
Nickname string `json:"nickname"`
Popular bool `json:"popular"`
HTMLURL string `json:"html_url"`
SourceURL string `json:"source_url"`
Description string `json:"description"`
Conditions []string `json:"conditions"`
Permissions []string `json:"permissions"`
Limitations []string `json:"limitations"`
Content string `json:"content"`
}
func (s ProjectTemplate) String() string {
return Stringify(s)
}
// ListProjectTemplatesOptions represents the available ListSnippets() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_templates.html#get-all-templates-of-a-particular-type
type ListProjectTemplatesOptions struct {
ListOptions
ID *int `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/ee/api/project_templates.html#get-all-templates-of-a-particular-type
func (s *ProjectTemplatesService) ListTemplates(pid interface{}, 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
}
// GetProjectTemplate gets a single project template.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_templates.html#get-one-template-of-a-particular-type
func (s *ProjectTemplatesService) GetProjectTemplate(pid interface{}, 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
}
//
// Copyright 2021, Patrick Webster
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// ProjectVariablesService handles communication with the
// project variables related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html
type ProjectVariablesService struct {
client *Client
}
// ProjectVariable represents a GitLab Project Variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html
type ProjectVariable struct {
Key string `json:"key"`
Value string `json:"value"`
VariableType VariableTypeValue `json:"variable_type"`
Protected bool `json:"protected"`
Masked bool `json:"masked"`
Raw bool `json:"raw"`
EnvironmentScope string `json:"environment_scope"`
Description string `json:"description"`
}
func (v ProjectVariable) String() string {
return Stringify(v)
}
// VariableFilter filters available for project variable related functions
type VariableFilter struct {
EnvironmentScope string `url:"environment_scope, omitempty" json:"environment_scope,omitempty"`
}
// ListProjectVariablesOptions represents the available options for listing variables
// in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#list-project-variables
type ListProjectVariablesOptions ListOptions
// ListVariables gets a list of all variables in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#list-project-variables
func (s *ProjectVariablesService) ListVariables(pid interface{}, 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
}
// GetProjectVariableOptions represents the available GetVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#get-a-single-variable
type GetProjectVariableOptions struct {
Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"`
}
// GetVariable gets a variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#get-a-single-variable
func (s *ProjectVariablesService) GetVariable(pid interface{}, 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
}
// CreateProjectVariableOptions represents the available CreateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable
type CreateProjectVariableOptions struct {
Key *string `url:"key,omitempty" json:"key,omitempty"`
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// CreateVariable creates a new project variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable
func (s *ProjectVariablesService) CreateVariable(pid interface{}, 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
}
// UpdateProjectVariableOptions represents the available UpdateVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#update-a-variable
type UpdateProjectVariableOptions struct {
Value *string `url:"value,omitempty" json:"value,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EnvironmentScope *string `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"`
Masked *bool `url:"masked,omitempty" json:"masked,omitempty"`
Protected *bool `url:"protected,omitempty" json:"protected,omitempty"`
Raw *bool `url:"raw,omitempty" json:"raw,omitempty"`
VariableType *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}
// UpdateVariable updates a project's variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#update-a-variable
func (s *ProjectVariablesService) UpdateVariable(pid interface{}, 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
}
// RemoveProjectVariableOptions represents the available RemoveVariable()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#delete-a-variable
type RemoveProjectVariableOptions struct {
Filter *VariableFilter `url:"filter,omitempty" json:"filter,omitempty"`
}
// RemoveVariable removes a project's variable.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_level_variables.html#delete-a-variable
func (s *ProjectVariablesService) RemoveVariable(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ProjectVulnerabilitiesService handles communication with the projects
// vulnerabilities related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_vulnerabilities.html
type ProjectVulnerabilitiesService struct {
client *Client
}
// Project represents a GitLab project vulnerability.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_vulnerabilities.html
type ProjectVulnerability struct {
AuthorID int `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"`
DueDate *time.Time `json:"due_date"`
Finding *Finding `json:"finding"`
ID int `json:"id"`
LastEditedAt *time.Time `json:"last_edited_at"`
LastEditedByID int `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"`
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"`
}
// Project represents a GitLab project vulnerability finding.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/project_vulnerabilities.html
type Finding struct {
Confidence string `json:"confidence"`
CreatedAt *time.Time `json:"created_at"`
ID int `json:"id"`
LocationFingerprint string `json:"location_fingerprint"`
MetadataVersion string `json:"metadata_version"`
Name string `json:"name"`
PrimaryIdentifierID int `json:"primary_identifier_id"`
ProjectFingerprint string `json:"project_fingerprint"`
ProjectID int `json:"project_id"`
RawMetadata string `json:"raw_metadata"`
ReportType string `json:"report_type"`
ScannerID int `json:"scanner_id"`
Severity string `json:"severity"`
UpdatedAt *time.Time `json:"updated_at"`
UUID string `json:"uuid"`
VulnerabilityID int `json:"vulnerability_id"`
}
// ListProjectVulnerabilitiesOptions represents the available
// ListProjectVulnerabilities() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_vulnerabilities.html#list-project-vulnerabilities
type ListProjectVulnerabilitiesOptions struct {
ListOptions
}
// ListProjectVulnerabilities gets a list of all project vulnerabilities.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_vulnerabilities.html#list-project-vulnerabilities
func (s *ProjectVulnerabilitiesService) ListProjectVulnerabilities(pid interface{}, 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
}
// CreateVulnerabilityOptions represents the available CreateVulnerability()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_vulnerabilities.html#new-vulnerability
type CreateVulnerabilityOptions struct {
FindingID *int `url:"finding_id,omitempty" json:"finding_id,omitempty"`
}
// CreateVulnerability creates a new vulnerability on the selected project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_vulnerabilities.html#new-vulnerability
func (s *ProjectVulnerabilitiesService) CreateVulnerability(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/hashicorp/go-retryablehttp"
)
// ProjectsService handles communication with the repositories related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html
type ProjectsService struct {
client *Client
}
// Project represents a GitLab project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html
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"`
TagList []string `json:"tag_list"`
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"`
IssuesEnabled bool `json:"issues_enabled"`
OpenIssuesCount int `json:"open_issues_count"`
MergeRequestsEnabled bool `json:"merge_requests_enabled"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
JobsEnabled bool `json:"jobs_enabled"`
WikiEnabled bool `json:"wiki_enabled"`
SnippetsEnabled bool `json:"snippets_enabled"`
ResolveOutdatedDiffDiscussions bool `json:"resolve_outdated_diff_discussions"`
ContainerExpirationPolicy *ContainerExpirationPolicy `json:"container_expiration_policy,omitempty"`
ContainerRegistryEnabled bool `json:"container_registry_enabled"`
ContainerRegistryAccessLevel AccessControlValue `json:"container_registry_access_level"`
ContainerRegistryImagePrefix string `json:"container_registry_image_prefix,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
CreatorID int `json:"creator_id"`
Namespace *ProjectNamespace `json:"namespace"`
Permissions *Permissions `json:"permissions"`
MarkedForDeletionAt *ISOTime `json:"marked_for_deletion_at"`
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"`
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"`
CIForwardDeploymentEnabled bool `json:"ci_forward_deployment_enabled"`
CIForwardDeploymentRollbackAllowed bool `json:"ci_forward_deployment_rollback_allowed"`
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"`
RestrictUserDefinedVariables bool `json:"restrict_user_defined_variables"`
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"`
// Deprecated: Use EmailsEnabled instead
EmailsDisabled bool `json:"emails_disabled"`
// Deprecated: This parameter has been renamed to PublicJobs in GitLab 9.0.
PublicBuilds bool `json:"public_builds"`
}
// BasicProject included in other service responses (such as todos).
type BasicProject 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"`
}
// ContainerExpirationPolicy represents the container expiration policy.
type ContainerExpirationPolicy struct {
Cadence string `json:"cadence"`
KeepN int `json:"keep_n"`
OlderThan string `json:"older_than"`
NameRegex string `json:"name_regex"`
NameRegexDelete string `json:"name_regex_delete"`
NameRegexKeep string `json:"name_regex_keep"`
Enabled bool `json:"enabled"`
NextRunAt *time.Time `json:"next_run_at"`
}
// ForkParent represents the parent project when this is a fork.
type ForkParent 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"`
HTTPURLToRepo string `json:"http_url_to_repo"`
WebURL string `json:"web_url"`
RepositoryStorage string `json:"repository_storage"`
}
// GroupAccess represents group access.
type GroupAccess struct {
AccessLevel AccessLevelValue `json:"access_level"`
NotificationLevel NotificationLevelValue `json:"notification_level"`
}
// Links represents a project web links for self, issues, merge_requests,
// repo_branches, labels, events, members.
type Links struct {
Self string `json:"self"`
Issues string `json:"issues"`
MergeRequests string `json:"merge_requests"`
RepoBranches string `json:"repo_branches"`
Labels string `json:"labels"`
Events string `json:"events"`
Members string `json:"members"`
ClusterAgents string `json:"cluster_agents"`
}
// Permissions represents permissions.
type Permissions struct {
ProjectAccess *ProjectAccess `json:"project_access"`
GroupAccess *GroupAccess `json:"group_access"`
}
// ProjectAccess represents project access.
type ProjectAccess struct {
AccessLevel AccessLevelValue `json:"access_level"`
NotificationLevel NotificationLevelValue `json:"notification_level"`
}
// ProjectLicense represent the license for a project.
type ProjectLicense struct {
Key string `json:"key"`
Name string `json:"name"`
Nickname string `json:"nickname"`
HTMLURL string `json:"html_url"`
SourceURL string `json:"source_url"`
}
// ProjectNamespace represents a project namespace.
type ProjectNamespace struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Kind string `json:"kind"`
FullPath string `json:"full_path"`
ParentID int `json:"parent_id"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}
// Repository represents a repository.
type Repository struct {
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"`
Visibility VisibilityValue `json:"visibility"`
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"`
}
// Statistics represents a statistics record for a group or project.
type Statistics struct {
CommitCount int64 `json:"commit_count"`
StorageSize int64 `json:"storage_size"`
RepositorySize int64 `json:"repository_size"`
WikiSize int64 `json:"wiki_size"`
LFSObjectsSize int64 `json:"lfs_objects_size"`
JobArtifactsSize int64 `json:"job_artifacts_size"`
PipelineArtifactsSize int64 `json:"pipeline_artifacts_size"`
PackagesSize int64 `json:"packages_size"`
SnippetsSize int64 `json:"snippets_size"`
UploadsSize int64 `json:"uploads_size"`
ContainerRegistrySize int64 `json:"container_registry_size"`
}
func (s Project) String() string {
return Stringify(s)
}
// ProjectApprovalRule represents a GitLab project approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-project-level-rules
type ProjectApprovalRule struct {
ID int `json:"id"`
Name string `json:"name"`
RuleType string `json:"rule_type"`
EligibleApprovers []*BasicUser `json:"eligible_approvers"`
ApprovalsRequired int `json:"approvals_required"`
Users []*BasicUser `json:"users"`
Groups []*Group `json:"groups"`
ContainsHiddenGroups bool `json:"contains_hidden_groups"`
ProtectedBranches []*ProtectedBranch `json:"protected_branches"`
AppliesToAllProtectedBranches bool `json:"applies_to_all_protected_branches"`
}
func (s ProjectApprovalRule) String() string {
return Stringify(s)
}
// ListProjectsOptions represents the available ListProjects() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#list-all-projects
type ListProjectsOptions struct {
ListOptions
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"`
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"`
LastActivityAfter *time.Time `url:"last_activity_after,omitempty" json:"last_activity_after,omitempty"`
LastActivityBefore *time.Time `url:"last_activity_before,omitempty" json:"last_activity_before,omitempty"`
Membership *bool `url:"membership,omitempty" json:"membership,omitempty"`
MinAccessLevel *AccessLevelValue `url:"min_access_level,omitempty" json:"min_access_level,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Owned *bool `url:"owned,omitempty" json:"owned,omitempty"`
RepositoryChecksumFailed *bool `url:"repository_checksum_failed,omitempty" json:"repository_checksum_failed,omitempty"`
RepositoryStorage *string `url:"repository_storage,omitempty" json:"repository_storage,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
SearchNamespaces *bool `url:"search_namespaces,omitempty" json:"search_namespaces,omitempty"`
Simple *bool `url:"simple,omitempty" json:"simple,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Starred *bool `url:"starred,omitempty" json:"starred,omitempty"`
Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"`
Topic *string `url:"topic,omitempty" json:"topic,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
WikiChecksumFailed *bool `url:"wiki_checksum_failed,omitempty" json:"wiki_checksum_failed,omitempty"`
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
WithIssuesEnabled *bool `url:"with_issues_enabled,omitempty" json:"with_issues_enabled,omitempty"`
WithMergeRequestsEnabled *bool `url:"with_merge_requests_enabled,omitempty" json:"with_merge_requests_enabled,omitempty"`
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/ee/api/projects.html#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
}
// ListUserProjects gets a list of projects for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-user-projects
func (s *ProjectsService) ListUserProjects(uid interface{}, 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
}
// ListUserContributedProjects gets a list of visible projects a given user has contributed to.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-projects-a-user-has-contributed-to
func (s *ProjectsService) ListUserContributedProjects(uid interface{}, 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
}
// ListUserStarredProjects gets a list of projects starred by the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-projects-starred-by-a-user
func (s *ProjectsService) ListUserStarredProjects(uid interface{}, 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
}
// ProjectUser represents a GitLab project user.
type ProjectUser 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"`
}
// ListProjectUserOptions represents the available ListProjectsUsers() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#get-project-users
type ListProjectUserOptions struct {
ListOptions
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/ee/api/projects.html#get-project-users
func (s *ProjectsService) ListProjectsUsers(pid interface{}, 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
}
// ProjectGroup represents a GitLab project group.
type ProjectGroup struct {
ID int `json:"id"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
FullName string `json:"full_name"`
FullPath string `json:"full_path"`
}
// ListProjectGroupOptions represents the available ListProjectsGroups() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#list-a-projects-groups
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"`
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/ee/api/projects.html#list-a-projects-groups
func (s *ProjectsService) ListProjectsGroups(pid interface{}, 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
}
// ProjectLanguages is a map of strings because the response is arbitrary
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/projects.html#languages
type ProjectLanguages map[string]float32
// GetProjectLanguages gets a list of languages used by the project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#languages
func (s *ProjectsService) GetProjectLanguages(pid interface{}, 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
}
// GetProjectOptions represents the available GetProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#get-single-project
type GetProjectOptions struct {
License *bool `url:"license,omitempty" json:"license,omitempty"`
Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"`
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/ee/api/projects.html#get-single-project
func (s *ProjectsService) GetProject(pid interface{}, 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
}
// CreateProjectOptions represents the available CreateProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type CreateProjectOptions struct {
AllowMergeOnSkippedPipeline *bool `url:"allow_merge_on_skipped_pipeline,omitempty" json:"allow_merge_on_skipped_pipeline,omitempty"`
OnlyAllowMergeIfAllStatusChecksPassed *bool `url:"only_allow_merge_if_all_status_checks_passed,omitempty" json:"only_allow_merge_if_all_status_checks_passed,omitempty"`
AnalyticsAccessLevel *AccessControlValue `url:"analytics_access_level,omitempty" json:"analytics_access_level,omitempty"`
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
AutoCancelPendingPipelines *string `url:"auto_cancel_pending_pipelines,omitempty" json:"auto_cancel_pending_pipelines,omitempty"`
AutoDevopsDeployStrategy *string `url:"auto_devops_deploy_strategy,omitempty" json:"auto_devops_deploy_strategy,omitempty"`
AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
AutocloseReferencedIssues *bool `url:"autoclose_referenced_issues,omitempty" json:"autoclose_referenced_issues,omitempty"`
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"`
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"`
ContainerRegistryAccessLevel *AccessControlValue `url:"container_registry_access_level,omitempty" json:"container_registry_access_level,omitempty"`
DefaultBranch *string `url:"default_branch,omitempty" json:"default_branch,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EmailsEnabled *bool `url:"emails_enabled,omitempty" json:"emails_enabled,omitempty"`
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"`
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"`
IssueBranchTemplate *string `url:"issue_branch_template,omitempty" json:"issue_branch_template,omitempty"`
LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
MergeCommitTemplate *string `url:"merge_commit_template,omitempty" json:"merge_commit_template,omitempty"`
MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"`
MergePipelinesEnabled *bool `url:"merge_pipelines_enabled,omitempty" json:"merge_pipelines_enabled,omitempty"`
MergeRequestsAccessLevel *AccessControlValue `url:"merge_requests_access_level,omitempty" json:"merge_requests_access_level,omitempty"`
MergeTrainsEnabled *bool `url:"merge_trains_enabled,omitempty" json:"merge_trains_enabled,omitempty"`
Mirror *bool `url:"mirror,omitempty" json:"mirror,omitempty"`
MirrorTriggerBuilds *bool `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,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"`
NamespaceID *int `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"`
PackagesEnabled *bool `url:"packages_enabled,omitempty" json:"packages_enabled,omitempty"`
PagesAccessLevel *AccessControlValue `url:"pages_access_level,omitempty" json:"pages_access_level,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"`
ReleasesAccessLevel *AccessControlValue `url:"releases_access_level,omitempty" json:"releases_access_level,omitempty"`
EnvironmentsAccessLevel *AccessControlValue `url:"environments_access_level,omitempty" json:"environments_access_level,omitempty"`
FeatureFlagsAccessLevel *AccessControlValue `url:"feature_flags_access_level,omitempty" json:"feature_flags_access_level,omitempty"`
InfrastructureAccessLevel *AccessControlValue `url:"infrastructure_access_level,omitempty" json:"infrastructure_access_level,omitempty"`
MonitorAccessLevel *AccessControlValue `url:"monitor_access_level,omitempty" json:"monitor_access_level,omitempty"`
RemoveSourceBranchAfterMerge *bool `url:"remove_source_branch_after_merge,omitempty" json:"remove_source_branch_after_merge,omitempty"`
PrintingMergeRequestLinkEnabled *bool `url:"printing_merge_request_link_enabled,omitempty" json:"printing_merge_request_link_enabled,omitempty"`
RepositoryAccessLevel *AccessControlValue `url:"repository_access_level,omitempty" json:"repository_access_level,omitempty"`
RepositoryStorage *string `url:"repository_storage,omitempty" json:"repository_storage,omitempty"`
RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
RequirementsAccessLevel *AccessControlValue `url:"requirements_access_level,omitempty" json:"requirements_access_level,omitempty"`
ResolveOutdatedDiffDiscussions *bool `url:"resolve_outdated_diff_discussions,omitempty" json:"resolve_outdated_diff_discussions,omitempty"`
SecurityAndComplianceAccessLevel *AccessControlValue `url:"security_and_compliance_access_level,omitempty" json:"security_and_compliance_access_level,omitempty"`
PreReceiveSecretDetectionEnabled *bool `url:"pre_receive_secret_detection_enabled,omitempty" json:"pre_receive_secret_detection_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"`
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"`
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: No longer supported in recent versions.
CIForwardDeploymentEnabled *bool `url:"ci_forward_deployment_enabled,omitempty" json:"ci_forward_deployment_enabled,omitempty"`
// Deprecated: Use ContainerRegistryAccessLevel instead.
ContainerRegistryEnabled *bool `url:"container_registry_enabled,omitempty" json:"container_registry_enabled,omitempty"`
// Deprecated: Use EmailsEnabled instead
EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
// Deprecated: Use IssuesAccessLevel instead.
IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"`
// Deprecated: No longer supported in recent versions.
IssuesTemplate *string `url:"issues_template,omitempty" json:"issues_template,omitempty"`
// Deprecated: Use BuildsAccessLevel instead.
JobsEnabled *bool `url:"jobs_enabled,omitempty" json:"jobs_enabled,omitempty"`
// Deprecated: Use MergeRequestsAccessLevel instead.
MergeRequestsEnabled *bool `url:"merge_requests_enabled,omitempty" json:"merge_requests_enabled,omitempty"`
// Deprecated: No longer supported in recent versions.
MergeRequestsTemplate *string `url:"merge_requests_template,omitempty" json:"merge_requests_template,omitempty"`
// Deprecated: No longer supported in recent versions.
ServiceDeskEnabled *bool `url:"service_desk_enabled,omitempty" json:"service_desk_enabled,omitempty"`
// Deprecated: Use SnippetsAccessLevel instead.
SnippetsEnabled *bool `url:"snippets_enabled,omitempty" json:"snippets_enabled,omitempty"`
// Deprecated: Use Topics instead. (Deprecated in GitLab 14.0)
TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"`
// Deprecated: Use WikiAccessLevel instead.
WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"`
}
// ContainerExpirationPolicyAttributes represents the available container
// expiration policy attributes.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type ContainerExpirationPolicyAttributes struct {
Cadence *string `url:"cadence,omitempty" json:"cadence,omitempty"`
KeepN *int `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"`
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
// Deprecated: Is replaced by NameRegexDelete and is internally hardwired to its value.
NameRegex *string `url:"name_regex,omitempty" json:"name_regex,omitempty"`
}
// ProjectAvatar represents a GitLab project avatar.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type ProjectAvatar struct {
Filename string
Image io.Reader
}
// MarshalJSON implements the json.Marshaler interface.
func (a *ProjectAvatar) MarshalJSON() ([]byte, error) {
if a.Filename == "" && a.Image == nil {
return []byte(`""`), nil
}
type alias ProjectAvatar
return json.Marshal((*alias)(a))
}
// CreateProject creates a new project owned by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-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
// when NameRegex is removed (it's now deprecated).
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
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
// CreateProjectForUserOptions represents the available CreateProjectForUser()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#create-project-for-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/ee/api/projects.html#create-project-for-user
func (s *ProjectsService) CreateProjectForUser(user int, 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
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
// EditProjectOptions represents the available EditProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#edit-project
type EditProjectOptions struct {
AllowMergeOnSkippedPipeline *bool `url:"allow_merge_on_skipped_pipeline,omitempty" json:"allow_merge_on_skipped_pipeline,omitempty"`
AllowPipelineTriggerApproveDeployment *bool `url:"allow_pipeline_trigger_approve_deployment,omitempty" json:"allow_pipeline_trigger_approve_deployment,omitempty"`
OnlyAllowMergeIfAllStatusChecksPassed *bool `url:"only_allow_merge_if_all_status_checks_passed,omitempty" json:"only_allow_merge_if_all_status_checks_passed,omitempty"`
AnalyticsAccessLevel *AccessControlValue `url:"analytics_access_level,omitempty" json:"analytics_access_level,omitempty"`
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
AutoCancelPendingPipelines *string `url:"auto_cancel_pending_pipelines,omitempty" json:"auto_cancel_pending_pipelines,omitempty"`
AutoDevopsDeployStrategy *string `url:"auto_devops_deploy_strategy,omitempty" json:"auto_devops_deploy_strategy,omitempty"`
AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
AutocloseReferencedIssues *bool `url:"autoclose_referenced_issues,omitempty" json:"autoclose_referenced_issues,omitempty"`
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"`
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"`
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"`
CISeperateCache *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"`
ContainerExpirationPolicyAttributes *ContainerExpirationPolicyAttributes `url:"container_expiration_policy_attributes,omitempty" json:"container_expiration_policy_attributes,omitempty"`
ContainerRegistryAccessLevel *AccessControlValue `url:"container_registry_access_level,omitempty" json:"container_registry_access_level,omitempty"`
DefaultBranch *string `url:"default_branch,omitempty" json:"default_branch,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
EmailsEnabled *bool `url:"emails_enabled,omitempty" json:"emails_enabled,omitempty"`
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"`
ImportURL *string `url:"import_url,omitempty" json:"import_url,omitempty"`
IssuesAccessLevel *AccessControlValue `url:"issues_access_level,omitempty" json:"issues_access_level,omitempty"`
IssueBranchTemplate *string `url:"issue_branch_template,omitempty" json:"issue_branch_template,omitempty"`
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"`
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"`
MergePipelinesEnabled *bool `url:"merge_pipelines_enabled,omitempty" json:"merge_pipelines_enabled,omitempty"`
MergeRequestsAccessLevel *AccessControlValue `url:"merge_requests_access_level,omitempty" json:"merge_requests_access_level,omitempty"`
MergeRequestsTemplate *string `url:"merge_requests_template,omitempty" json:"merge_requests_template,omitempty"`
MergeTrainsEnabled *bool `url:"merge_trains_enabled,omitempty" json:"merge_trains_enabled,omitempty"`
Mirror *bool `url:"mirror,omitempty" json:"mirror,omitempty"`
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"`
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"`
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"`
OnlyMirrorProtectedBranches *bool `url:"only_mirror_protected_branches,omitempty" json:"only_mirror_protected_branches,omitempty"`
OperationsAccessLevel *AccessControlValue `url:"operations_access_level,omitempty" json:"operations_access_level,omitempty"`
PackagesEnabled *bool `url:"packages_enabled,omitempty" json:"packages_enabled,omitempty"`
PagesAccessLevel *AccessControlValue `url:"pages_access_level,omitempty" json:"pages_access_level,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"`
ReleasesAccessLevel *AccessControlValue `url:"releases_access_level,omitempty" json:"releases_access_level,omitempty"`
EnvironmentsAccessLevel *AccessControlValue `url:"environments_access_level,omitempty" json:"environments_access_level,omitempty"`
FeatureFlagsAccessLevel *AccessControlValue `url:"feature_flags_access_level,omitempty" json:"feature_flags_access_level,omitempty"`
InfrastructureAccessLevel *AccessControlValue `url:"infrastructure_access_level,omitempty" json:"infrastructure_access_level,omitempty"`
MonitorAccessLevel *AccessControlValue `url:"monitor_access_level,omitempty" json:"monitor_access_level,omitempty"`
RemoveSourceBranchAfterMerge *bool `url:"remove_source_branch_after_merge,omitempty" json:"remove_source_branch_after_merge,omitempty"`
PreventMergeWithoutJiraIssue *bool `url:"prevent_merge_without_jira_issue,omitempty" json:"prevent_merge_without_jira_issue,omitempty"`
PrintingMergeRequestLinkEnabled *bool `url:"printing_merge_request_link_enabled,omitempty" json:"printing_merge_request_link_enabled,omitempty"`
RepositoryAccessLevel *AccessControlValue `url:"repository_access_level,omitempty" json:"repository_access_level,omitempty"`
RepositoryStorage *string `url:"repository_storage,omitempty" json:"repository_storage,omitempty"`
RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
RequirementsAccessLevel *AccessControlValue `url:"requirements_access_level,omitempty" json:"requirements_access_level,omitempty"`
ResolveOutdatedDiffDiscussions *bool `url:"resolve_outdated_diff_discussions,omitempty" json:"resolve_outdated_diff_discussions,omitempty"`
RestrictUserDefinedVariables *bool `url:"restrict_user_defined_variables,omitempty" json:"restrict_user_defined_variables,omitempty"`
SecurityAndComplianceAccessLevel *AccessControlValue `url:"security_and_compliance_access_level,omitempty" json:"security_and_compliance_access_level,omitempty"`
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"`
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"`
Topics *[]string `url:"topics,omitempty" json:"topics,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"`
// Deprecated: Use ContainerRegistryAccessLevel instead.
ContainerRegistryEnabled *bool `url:"container_registry_enabled,omitempty" json:"container_registry_enabled,omitempty"`
// Deprecated: Use EmailsEnabled instead
EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
// Deprecated: Use IssuesAccessLevel instead.
IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"`
// Deprecated: Use BuildsAccessLevel instead.
JobsEnabled *bool `url:"jobs_enabled,omitempty" json:"jobs_enabled,omitempty"`
// Deprecated: Use MergeRequestsAccessLevel instead.
MergeRequestsEnabled *bool `url:"merge_requests_enabled,omitempty" json:"merge_requests_enabled,omitempty"`
// Deprecated: Use SnippetsAccessLevel instead.
SnippetsEnabled *bool `url:"snippets_enabled,omitempty" json:"snippets_enabled,omitempty"`
// Deprecated: Use Topics instead. (Deprecated in GitLab 14.0)
TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"`
// Deprecated: Use WikiAccessLevel instead.
WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"`
}
// EditProject updates an existing project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#edit-project
func (s *ProjectsService) EditProject(pid interface{}, opt *EditProjectOptions, 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
}
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,
)
}
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
}
// ForkProjectOptions represents the available ForkProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#fork-project
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"`
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"`
// Deprecated: This parameter has been split into NamespaceID and NamespacePath.
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/ee/api/projects.html#fork-project
func (s *ProjectsService) ForkProject(pid interface{}, 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
}
// StarProject stars a given the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#star-a-project
func (s *ProjectsService) StarProject(pid interface{}, 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
}
// UnstarProject unstars a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#unstar-a-project
func (s *ProjectsService) UnstarProject(pid interface{}, 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
}
// ArchiveProject archives the project if the user is either admin or the
// project owner of this project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#archive-a-project
func (s *ProjectsService) ArchiveProject(pid interface{}, 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
}
// UnarchiveProject unarchives the project if the user is either admin or
// the project owner of this project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#unarchive-a-project
func (s *ProjectsService) UnarchiveProject(pid interface{}, 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
}
// DeleteProject removes a project including all associated resources
// (issues, merge requests etc.)
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#delete-project
func (s *ProjectsService) DeleteProject(pid interface{}, 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, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ShareWithGroupOptions represents options to share project with groups
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#share-project-with-group
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"`
}
// ShareProjectWithGroup allows to share a project with a group.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#share-project-with-group
func (s *ProjectsService) ShareProjectWithGroup(pid interface{}, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/share", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteSharedProjectFromGroup allows to unshare a project from a group.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#delete-a-shared-project-link-within-a-group
func (s *ProjectsService) DeleteSharedProjectFromGroup(pid interface{}, 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)
}
// ProjectMember represents a project member.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/members.html#list-all-members-of-a-group-or-project
type ProjectMember 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"`
ExpiresAt *ISOTime `json:"expires_at"`
AccessLevel AccessLevelValue `json:"access_level"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
}
// 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"`
}
// ProjectHook represents a project hook.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-project-hooks
type ProjectHook struct {
ID int `json:"id"`
URL string `json:"url"`
ConfidentialNoteEvents bool `json:"confidential_note_events"`
ProjectID int `json:"project_id"`
PushEvents bool `json:"push_events"`
PushEventsBranchFilter string `json:"push_events_branch_filter"`
IssuesEvents bool `json:"issues_events"`
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
TagPushEvents bool `json:"tag_push_events"`
NoteEvents bool `json:"note_events"`
JobEvents bool `json:"job_events"`
PipelineEvents bool `json:"pipeline_events"`
WikiPageEvents bool `json:"wiki_page_events"`
DeploymentEvents bool `json:"deployment_events"`
ReleasesEvents bool `json:"releases_events"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
CreatedAt *time.Time `json:"created_at"`
ResourceAccessTokenEvents bool `json:"resource_access_token_events"`
CustomWebhookTemplate string `json:"custom_webhook_template"`
CustomHeaders []*HookCustomHeader `json:"custom_headers"`
}
// ListProjectHooksOptions represents the available ListProjectHooks() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#list-project-hooks
type ListProjectHooksOptions ListOptions
// ListProjectHooks gets a list of project hooks.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-project-hooks
func (s *ProjectsService) ListProjectHooks(pid interface{}, 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
}
// GetProjectHook gets a specific hook for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#get-project-hook
func (s *ProjectsService) GetProjectHook(pid interface{}, 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
}
// AddProjectHookOptions represents the available AddProjectHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#add-project-hook
type AddProjectHookOptions struct {
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
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"`
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"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
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"`
}
// AddProjectHook adds a hook to a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#add-project-hook
func (s *ProjectsService) AddProjectHook(pid interface{}, 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
}
// EditProjectHookOptions represents the available EditProjectHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#edit-project-hook
type EditProjectHookOptions struct {
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
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"`
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"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
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"`
}
// EditProjectHook edits a hook for a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#edit-project-hook
func (s *ProjectsService) EditProjectHook(pid interface{}, 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
}
// 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/ee/api/projects.html#delete-project-hook
func (s *ProjectsService) DeleteProjectHook(pid interface{}, 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)
}
// 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/ee/api/projects.html#trigger-a-test-project-hook
func (s *ProjectsService) TriggerTestProjectHook(pid interface{}, 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)
}
// SetHookCustomHeaderOptions represents a project or group hook custom header.
// If the header isn't present, it will be created.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#set-a-custom-header
type SetHookCustomHeaderOptions struct {
Value *string `json:"value,omitempty"`
}
// SetProjectCustomHeader creates or updates a project custom webhook header.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#set-a-custom-header
func (s *ProjectsService) SetProjectCustomHeader(pid interface{}, 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)
}
// DeleteProjectCustomHeader deletes a project custom webhook header.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#delete-a-custom-header
func (s *ProjectsService) DeleteProjectCustomHeader(pid interface{}, 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)
}
// ProjectForkRelation represents a project fork relationship.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#admin-fork-relation
type ProjectForkRelation struct {
ID int `json:"id"`
ForkedToProjectID int `json:"forked_to_project_id"`
ForkedFromProjectID int `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/ee/api/projects.html#create-a-forked-fromto-relation-between-existing-projects.
func (s *ProjectsService) CreateProjectForkRelation(pid interface{}, 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
}
// DeleteProjectForkRelation deletes an existing forked from relationship.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#delete-an-existing-forked-from-relationship
func (s *ProjectsService) DeleteProjectForkRelation(pid interface{}, 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)
}
// ProjectFile represents an uploaded project file.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#upload-a-file
type ProjectFile struct {
Alt string `json:"alt"`
URL string `json:"url"`
FullPath string `json:"full_path"`
Markdown string `json:"markdown"`
}
// UploadFile uploads a file.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#upload-a-file
func (s *ProjectsService) UploadFile(pid interface{}, content io.Reader, filename string, options ...RequestOptionFunc) (*ProjectFile, *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,
)
if err != nil {
return nil, nil, err
}
pf := new(ProjectFile)
resp, err := s.client.Do(req, pf)
if err != nil {
return nil, resp, err
}
return pf, resp, nil
}
// UploadAvatar uploads an avatar.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#upload-a-project-avatar
func (s *ProjectsService) UploadAvatar(pid interface{}, 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,
)
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
}
// ListProjectForks gets a list of project forks.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#list-forks-of-a-project
func (s *ProjectsService) ListProjectForks(pid interface{}, 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
}
// ProjectPushRules represents a project push rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#push-rules
type ProjectPushRules struct {
ID int `json:"id"`
ProjectID int `json:"project_id"`
CommitMessageRegex string `json:"commit_message_regex"`
CommitMessageNegativeRegex string `json:"commit_message_negative_regex"`
BranchNameRegex string `json:"branch_name_regex"`
DenyDeleteTag bool `json:"deny_delete_tag"`
CreatedAt *time.Time `json:"created_at"`
MemberCheck bool `json:"member_check"`
PreventSecrets bool `json:"prevent_secrets"`
AuthorEmailRegex string `json:"author_email_regex"`
FileNameRegex string `json:"file_name_regex"`
MaxFileSize int `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/ee/api/projects.html#get-project-push-rules
func (s *ProjectsService) GetProjectPushRules(pid interface{}, 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
}
// AddProjectPushRuleOptions represents the available AddProjectPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#add-project-push-rule
type AddProjectPushRuleOptions struct {
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
CommitCommitterNameCheck *bool `url:"commit_committer_name_check,omitempty" json:"commit_committer_name_check,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
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"`
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/ee/api/projects.html#add-project-push-rule
func (s *ProjectsService) AddProjectPushRule(pid interface{}, 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
}
// EditProjectPushRuleOptions represents the available EditProjectPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#edit-project-push-rule
type EditProjectPushRuleOptions struct {
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
CommitCommitterNameCheck *bool `url:"commit_committer_name_check,omitempty" json:"commit_committer_name_check,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
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"`
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/ee/api/projects.html#edit-project-push-rule
func (s *ProjectsService) EditProjectPushRule(pid interface{}, 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
}
// 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/ee/api/projects.html#delete-project-push-rule
func (s *ProjectsService) DeleteProjectPushRule(pid interface{}, 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)
}
// ProjectApprovals represents GitLab project level merge request approvals.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type ProjectApprovals struct {
Approvers []*MergeRequestApproverUser `json:"approvers"`
ApproverGroups []*MergeRequestApproverGroup `json:"approver_groups"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
ResetApprovalsOnPush bool `json:"reset_approvals_on_push"`
DisableOverridingApproversPerMergeRequest bool `json:"disable_overriding_approvers_per_merge_request"`
MergeRequestsAuthorApproval bool `json:"merge_requests_author_approval"`
MergeRequestsDisableCommittersApproval bool `json:"merge_requests_disable_committers_approval"`
RequirePasswordToApprove bool `json:"require_password_to_approve"`
SelectiveCodeOwnerRemovals bool `json:"selective_code_owner_removals,omitempty"`
}
// GetApprovalConfiguration get the approval configuration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-configuration
func (s *ProjectsService) GetApprovalConfiguration(pid interface{}, 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
}
// ChangeApprovalConfigurationOptions represents the available
// ApprovalConfiguration() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
type ChangeApprovalConfigurationOptions struct {
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
DisableOverridingApproversPerMergeRequest *bool `url:"disable_overriding_approvers_per_merge_request,omitempty" json:"disable_overriding_approvers_per_merge_request,omitempty"`
MergeRequestsAuthorApproval *bool `url:"merge_requests_author_approval,omitempty" json:"merge_requests_author_approval,omitempty"`
MergeRequestsDisableCommittersApproval *bool `url:"merge_requests_disable_committers_approval,omitempty" json:"merge_requests_disable_committers_approval,omitempty"`
RequirePasswordToApprove *bool `url:"require_password_to_approve,omitempty" json:"require_password_to_approve,omitempty"`
ResetApprovalsOnPush *bool `url:"reset_approvals_on_push,omitempty" json:"reset_approvals_on_push,omitempty"`
SelectiveCodeOwnerRemovals *bool `url:"selective_code_owner_removals,omitempty" json:"selective_code_owner_removals,omitempty"`
}
// ChangeApprovalConfiguration updates the approval configuration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
func (s *ProjectsService) ChangeApprovalConfiguration(pid interface{}, 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
}
// GetProjectApprovalRulesListsOptions represents the available GetProjectApprovalRules() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-project-level-rules
type GetProjectApprovalRulesListsOptions ListOptions
// GetProjectApprovalRules looks up the list of project level approver rules.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-project-level-rules
func (s *ProjectsService) GetProjectApprovalRules(pid interface{}, 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
}
// GetProjectApprovalRule gets the project level approvers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-a-single-project-level-rule
func (s *ProjectsService) GetProjectApprovalRule(pid interface{}, 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
}
// CreateProjectLevelRuleOptions represents the available CreateProjectApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-project-level-rule
type CreateProjectLevelRuleOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ApprovalsRequired *int `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"`
AppliesToAllProtectedBranches *bool `url:"applies_to_all_protected_branches,omitempty" json:"applies_to_all_protected_branches,omitempty"`
}
// CreateProjectApprovalRule creates a new project-level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-project-level-rule
func (s *ProjectsService) CreateProjectApprovalRule(pid interface{}, 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
}
// UpdateProjectLevelRuleOptions represents the available UpdateProjectApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-project-level-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"`
AppliesToAllProtectedBranches *bool `url:"applies_to_all_protected_branches,omitempty" json:"applies_to_all_protected_branches,omitempty"`
}
// UpdateProjectApprovalRule updates an existing approval rule with new options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-project-level-rule
func (s *ProjectsService) UpdateProjectApprovalRule(pid interface{}, 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
}
// DeleteProjectApprovalRule deletes a project-level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#delete-project-level-rule
func (s *ProjectsService) DeleteProjectApprovalRule(pid interface{}, 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)
}
// ChangeAllowedApproversOptions represents the available ChangeAllowedApprovers()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
type ChangeAllowedApproversOptions struct {
ApproverGroupIDs *[]int `url:"approver_group_ids,omitempty" json:"approver_group_ids,omitempty"`
ApproverIDs *[]int `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
}
// ChangeAllowedApprovers updates the list of approvers and approver groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
func (s *ProjectsService) ChangeAllowedApprovers(pid interface{}, opt *ChangeAllowedApproversOptions, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvers", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, 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
}
// ProjectPullMirrorDetails represent the details of the configuration pull
// mirror and its update status.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#get-a-projects-pull-mirror-details
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"`
}
// GetProjectPullMirrorDetails returns the pull mirror details.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#get-a-projects-pull-mirror-details
func (s *ProjectsService) GetProjectPullMirrorDetails(pid interface{}, 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
}
// StartMirroringProject start the pull mirroring process for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project
func (s *ProjectsService) StartMirroringProject(pid interface{}, 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
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// TransferProjectOptions represents the available TransferProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#transfer-a-project-to-a-new-namespace
type TransferProjectOptions struct {
Namespace interface{} `url:"namespace,omitempty" json:"namespace,omitempty"`
}
// TransferProject transfer a project into the specified namespace
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#transfer-a-project-to-a-new-namespace
func (s *ProjectsService) TransferProject(pid interface{}, 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
}
// StartHousekeepingProject start the Housekeeping task for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#start-the-housekeeping-task-for-a-project
func (s *ProjectsService) StartHousekeepingProject(pid interface{}, 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)
}
// GetRepositoryStorage Get the path to repository storage.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#get-the-path-to-repository-storage
type ProjectReposityStorage struct {
ProjectID int `json:"project_id"`
DiskPath string `json:"disk_path"`
CreatedAt *time.Time `json:"created_at"`
RepositoryStorage string `json:"repository_storage"`
}
func (s *ProjectsService) GetRepositoryStorage(pid interface{}, 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
}
prs := new(ProjectReposityStorage)
resp, err := s.client.Do(req, prs)
if err != nil {
return nil, resp, err
}
return prs, resp, nil
}
//
// Copyright 2021, Sander van Harmelen, Michael Lihs
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// ProtectedBranchesService handles communication with the protected branch
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html
type ProtectedBranchesService struct {
client *Client
}
// ProtectedBranch represents a protected branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#list-protected-branches
type ProtectedBranch struct {
ID int `json:"id"`
Name string `json:"name"`
PushAccessLevels []*BranchAccessDescription `json:"push_access_levels"`
MergeAccessLevels []*BranchAccessDescription `json:"merge_access_levels"`
UnprotectAccessLevels []*BranchAccessDescription `json:"unprotect_access_levels"`
AllowForcePush bool `json:"allow_force_push"`
CodeOwnerApprovalRequired bool `json:"code_owner_approval_required"`
}
// BranchAccessDescription represents the access description for a protected
// branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#list-protected-branches
type BranchAccessDescription struct {
ID int `json:"id"`
AccessLevel AccessLevelValue `json:"access_level"`
AccessLevelDescription string `json:"access_level_description"`
UserID int `json:"user_id"`
GroupID int `json:"group_id"`
}
// ListProtectedBranchesOptions represents the available ListProtectedBranches()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#list-protected-branches
type ListProtectedBranchesOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
}
// ListProtectedBranches gets a list of protected branches from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#list-protected-branches
func (s *ProtectedBranchesService) ListProtectedBranches(pid interface{}, 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
}
// GetProtectedBranch gets a single protected branch or wildcard protected branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#get-a-single-protected-branch-or-wildcard-protected-branch
func (s *ProtectedBranchesService) GetProtectedBranch(pid interface{}, 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
}
// ProtectRepositoryBranchesOptions represents the available
// ProtectRepositoryBranches() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#protect-repository-branches
type ProtectRepositoryBranchesOptions 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 *[]*BranchPermissionOptions `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"`
AllowedToMerge *[]*BranchPermissionOptions `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"`
AllowedToUnprotect *[]*BranchPermissionOptions `url:"allowed_to_unprotect,omitempty" json:"allowed_to_unprotect,omitempty"`
CodeOwnerApprovalRequired *bool `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"`
}
// BranchPermissionOptions represents a branch permission option.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#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"`
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"`
}
// ProtectRepositoryBranches protects a single repository branch or several
// project repository branches using a wildcard protected branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#protect-repository-branches
func (s *ProtectedBranchesService) ProtectRepositoryBranches(pid interface{}, 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
}
// UnprotectRepositoryBranches unprotects the given protected branch or wildcard
// protected branch.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#unprotect-repository-branches
func (s *ProtectedBranchesService) UnprotectRepositoryBranches(pid interface{}, 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)
}
// UpdateProtectedBranchOptions represents the available
// UpdateProtectedBranch() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#update-a-protected-branch
type UpdateProtectedBranchOptions 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 *[]*BranchPermissionOptions `url:"allowed_to_push,omitempty" json:"allowed_to_push,omitempty"`
AllowedToMerge *[]*BranchPermissionOptions `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"`
AllowedToUnprotect *[]*BranchPermissionOptions `url:"allowed_to_unprotect,omitempty" json:"allowed_to_unprotect,omitempty"`
}
// UpdateProtectedBranch updates a protected branch.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#update-a-protected-branch
func (s *ProtectedBranchesService) UpdateProtectedBranch(pid interface{}, 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
}
// RequireCodeOwnerApprovalsOptions represents the available
// RequireCodeOwnerApprovals() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#update-a-protected-branch
type RequireCodeOwnerApprovalsOptions struct {
CodeOwnerApprovalRequired *bool `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"`
}
// RequireCodeOwnerApprovals updates the code owner approval option.
//
// Deprecated: Use UpdateProtectedBranch() instead.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/protected_branches.html#update-a-protected-branch
func (s *ProtectedBranchesService) RequireCodeOwnerApprovals(pid interface{}, branch string, opt *RequireCodeOwnerApprovalsOptions, options ...RequestOptionFunc) (*Response, error) {
updateOptions := &UpdateProtectedBranchOptions{
CodeOwnerApprovalRequired: opt.CodeOwnerApprovalRequired,
}
_, req, err := s.UpdateProtectedBranch(pid, branch, updateOptions, options...)
return req, err
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ProtectedEnvironmentsService handles communication with the protected
// environment methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html
type ProtectedEnvironmentsService struct {
client *Client
}
// ProtectedEnvironment represents a protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html
type ProtectedEnvironment struct {
Name string `json:"name"`
DeployAccessLevels []*EnvironmentAccessDescription `json:"deploy_access_levels"`
RequiredApprovalCount int `json:"required_approval_count"`
ApprovalRules []*EnvironmentApprovalRule `json:"approval_rules"`
}
// EnvironmentAccessDescription represents the access decription for a protected
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html
type EnvironmentAccessDescription struct {
ID int `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"`
}
// EnvironmentApprovalRule represents the approval rules for a protected
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
type EnvironmentApprovalRule struct {
ID int `json:"id"`
UserID int `json:"user_id"`
GroupID int `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"`
}
// ListProtectedEnvironmentsOptions represents the available
// ListProtectedEnvironments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#list-protected-environments
type ListProtectedEnvironmentsOptions ListOptions
// ListProtectedEnvironments returns a list of protected environments from a
// project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#list-protected-environments
func (s *ProtectedEnvironmentsService) ListProtectedEnvironments(pid interface{}, 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
}
// GetProtectedEnvironment returns a single protected environment or wildcard
// protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#get-a-single-protected-environment
func (s *ProtectedEnvironmentsService) GetProtectedEnvironment(pid interface{}, 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
}
// ProtectRepositoryEnvironmentsOptions represents the available
// ProtectRepositoryEnvironments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
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"`
ApprovalRules *[]*EnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"`
}
// EnvironmentAccessOptions represents the options for an access decription for
// a protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#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"`
}
// EnvironmentApprovalRuleOptions represents the approval rules for a protected
// environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#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"`
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"`
}
// ProtectRepositoryEnvironments protects a single repository environment or
// several project repository environments using wildcard protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
func (s *ProtectedEnvironmentsService) ProtectRepositoryEnvironments(pid interface{}, 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
}
// UpdateProtectedEnvironmentsOptions represents the available
// UpdateProtectedEnvironments() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#update-a-protected-environment
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"`
ApprovalRules *[]*UpdateEnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"`
}
// UpdateEnvironmentAccessOptions represents the options for updates to an
// access decription for a protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#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"`
Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"`
}
// UpdateEnvironmentApprovalRuleOptions represents the updates to the approval
// rules for a protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#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"`
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"`
Destroy *bool `url:"_destroy,omitempty" json:"_destroy,omitempty"`
}
// UpdateProtectedEnvironments updates a single repository environment or
// several project repository environments using wildcard protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#update-a-protected-environment
func (s *ProtectedEnvironmentsService) UpdateProtectedEnvironments(pid interface{}, 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
}
// UnprotectEnvironment unprotects the given protected environment or wildcard
// protected environment.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_environments.html#unprotect-a-single-environment
func (s *ProtectedEnvironmentsService) UnprotectEnvironment(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ProtectedTagsService handles communication with the protected tag methods
// of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html
type ProtectedTagsService struct {
client *Client
}
// ProtectedTag represents a protected tag.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html
type ProtectedTag struct {
Name string `json:"name"`
CreateAccessLevels []*TagAccessDescription `json:"create_access_levels"`
}
// TagAccessDescription reperesents the access decription for a protected tag.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html
type TagAccessDescription struct {
ID int `json:"id"`
UserID int `json:"user_id"`
GroupID int `json:"group_id"`
AccessLevel AccessLevelValue `json:"access_level"`
AccessLevelDescription string `json:"access_level_description"`
}
// ListProtectedTagsOptions represents the available ListProtectedTags()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#list-protected-tags
type ListProtectedTagsOptions ListOptions
// ListProtectedTags returns a list of protected tags from a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#list-protected-tags
func (s *ProtectedTagsService) ListProtectedTags(pid interface{}, 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
}
// GetProtectedTag returns a single protected tag or wildcard protected tag.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#get-a-single-protected-tag-or-wildcard-protected-tag
func (s *ProtectedTagsService) GetProtectedTag(pid interface{}, 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
}
// ProtectRepositoryTagsOptions represents the available ProtectRepositoryTags()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#protect-repository-tags
type ProtectRepositoryTagsOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
CreateAccessLevel *AccessLevelValue `url:"create_access_level,omitempty" json:"create_access_level,omitempty"`
AllowedToCreate *[]*TagsPermissionOptions `url:"allowed_to_create,omitempty" json:"allowed_to_create,omitempty"`
}
// TagsPermissionOptions represents a protected tag permission option.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#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"`
AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
}
// ProtectRepositoryTags protects a single repository tag or several project
// repository tags using a wildcard protected tag.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#protect-repository-tags
func (s *ProtectedTagsService) ProtectRepositoryTags(pid interface{}, 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
}
// UnprotectRepositoryTags unprotects the given protected tag or wildcard
// protected tag.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/protected_tags.html#unprotect-repository-tags
func (s *ProtectedTagsService) UnprotectRepositoryTags(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ReleaseLinksService handles communication with the release link methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html
type ReleaseLinksService struct {
client *Client
}
// ReleaseLink represents a release link.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html
type ReleaseLink struct {
ID int `json:"id"`
Name string `json:"name"`
URL string `json:"url"`
DirectAssetURL string `json:"direct_asset_url"`
External bool `json:"external"`
LinkType LinkTypeValue `json:"link_type"`
}
// ListReleaseLinksOptions represents ListReleaseLinks() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#list-links-of-a-release
type ListReleaseLinksOptions ListOptions
// ListReleaseLinks gets assets as links from a Release.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#list-links-of-a-release
func (s *ReleaseLinksService) ListReleaseLinks(pid interface{}, 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
}
// GetReleaseLink returns a link from release assets.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#get-a-release-link
func (s *ReleaseLinksService) GetReleaseLink(pid interface{}, 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
}
// CreateReleaseLinkOptions represents CreateReleaseLink() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#create-a-release-link
type CreateReleaseLinkOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
URL *string `url:"url,omitempty" json:"url,omitempty"`
FilePath *string `url:"filepath,omitempty" json:"filepath,omitempty"`
DirectAssetPath *string `url:"direct_asset_path,omitempty" json:"direct_asset_path,omitempty"`
LinkType *LinkTypeValue `url:"link_type,omitempty" json:"link_type,omitempty"`
}
// CreateReleaseLink creates a link.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#create-a-release-link
func (s *ReleaseLinksService) CreateReleaseLink(pid interface{}, 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
}
// UpdateReleaseLinkOptions represents UpdateReleaseLink() options.
//
// You have to specify at least one of Name of URL.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#update-a-release-link
type UpdateReleaseLinkOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
URL *string `url:"url,omitempty" json:"url,omitempty"`
FilePath *string `url:"filepath,omitempty" json:"filepath,omitempty"`
DirectAssetPath *string `url:"direct_asset_path,omitempty" json:"direct_asset_path,omitempty"`
LinkType *LinkTypeValue `url:"link_type,omitempty" json:"link_type,omitempty"`
}
// UpdateReleaseLink updates an asset link.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#update-a-release-link
func (s *ReleaseLinksService) UpdateReleaseLink(pid interface{}, 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
}
// DeleteReleaseLink deletes a link from release.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/links.html#delete-a-release-link
func (s *ReleaseLinksService) DeleteReleaseLink(pid interface{}, 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.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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ReleasesService handles communication with the releases methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/releases/index.html
type ReleasesService struct {
client *Client
}
// Release represents a project release.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#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"`
Commit Commit `json:"commit"`
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"`
} `json:"assets"`
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"`
}
// ListReleasesOptions represents ListReleases() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#list-releases
type ListReleasesOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
IncludeHTMLDescription *bool `url:"include_html_description,omitempty" json:"include_html_description,omitempty"`
}
// ListReleases gets a pagenated of releases accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#list-releases
func (s *ReleasesService) ListReleases(pid interface{}, 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
}
// GetRelease returns a single release, identified by a tag name.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#get-a-release-by-a-tag-name
func (s *ReleasesService) GetRelease(pid interface{}, 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
}
// GetLatestRelease returns the latest release for the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/#get-the-latest-release
func (s *ReleasesService) GetLatestRelease(pid interface{}, 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
}
// CreateReleaseOptions represents CreateRelease() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#create-a-release
type CreateReleaseOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
TagName *string `url:"tag_name,omitempty" json:"tag_name,omitempty"`
TagMessage *string `url:"tag_message,omitempty" json:"tag_message,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
Milestones *[]string `url:"milestones,omitempty" json:"milestones,omitempty"`
Assets *ReleaseAssetsOptions `url:"assets,omitempty" json:"assets,omitempty"`
ReleasedAt *time.Time `url:"released_at,omitempty" json:"released_at,omitempty"`
}
// ReleaseAssetsOptions represents release assets in CreateRelease() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#create-a-release
type ReleaseAssetsOptions struct {
Links []*ReleaseAssetLinkOptions `url:"links,omitempty" json:"links,omitempty"`
}
// ReleaseAssetLinkOptions represents release asset link in CreateRelease()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#create-a-release
type ReleaseAssetLinkOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
URL *string `url:"url,omitempty" json:"url,omitempty"`
FilePath *string `url:"filepath,omitempty" json:"filepath,omitempty"`
DirectAssetPath *string `url:"direct_asset_path,omitempty" json:"direct_asset_path,omitempty"`
LinkType *LinkTypeValue `url:"link_type,omitempty" json:"link_type,omitempty"`
}
// CreateRelease creates a release.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#create-a-release
func (s *ReleasesService) CreateRelease(pid interface{}, 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
}
// UpdateReleaseOptions represents UpdateRelease() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#update-a-release
type UpdateReleaseOptions struct {
Name *string `url:"name" json:"name"`
Description *string `url:"description" json:"description"`
Milestones *[]string `url:"milestones,omitempty" json:"milestones,omitempty"`
ReleasedAt *time.Time `url:"released_at,omitempty" json:"released_at,omitempty"`
}
// UpdateRelease updates a release.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#update-a-release
func (s *ReleasesService) UpdateRelease(pid interface{}, 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
}
// DeleteRelease deletes a release.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/index.html#delete-a-release
func (s *ReleasesService) DeleteRelease(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"io"
"net/http"
"net/url"
)
// RepositoriesService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repositories.html
type RepositoriesService struct {
client *Client
}
// TreeNode represents a GitLab repository file or directory.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repositories.html
type TreeNode struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Path string `json:"path"`
Mode string `json:"mode"`
}
func (t TreeNode) String() string {
return Stringify(t)
}
// ListTreeOptions represents the available ListTree() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#list-repository-tree
type ListTreeOptions struct {
ListOptions
Path *string `url:"path,omitempty" json:"path,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
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/ee/api/repositories.html#list-repository-tree
func (s *RepositoriesService) ListTree(pid interface{}, 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
}
// 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/ee/api/repositories.html#get-a-blob-from-repository
func (s *RepositoriesService) Blob(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// RawBlobContent gets the raw file contents for a blob by blob SHA.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#raw-blob-content
func (s *RepositoriesService) RawBlobContent(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// ArchiveOptions represents the available Archive() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#get-file-archive
type ArchiveOptions struct {
Format *string `url:"-" json:"-"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
SHA *string `url:"sha,omitempty" json:"sha,omitempty"`
}
// Archive gets an archive of the repository.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#get-file-archive
func (s *RepositoriesService) Archive(pid interface{}, 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.
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
}
var b bytes.Buffer
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// StreamArchive streams an archive of the repository to the provided
// io.Writer.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#get-file-archive
func (s *RepositoriesService) StreamArchive(pid interface{}, w io.Writer, opt *ArchiveOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/repository/archive", PathEscape(project))
// Set an optional format for the archive.
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, err
}
return s.client.Do(req, w)
}
// Compare represents the result of a comparison of branches, tags or commits.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#compare-branches-tags-or-commits
type Compare struct {
Commit *Commit `json:"commit"`
Commits []*Commit `json:"commits"`
Diffs []*Diff `json:"diffs"`
CompareTimeout bool `json:"compare_timeout"`
CompareSameRef bool `json:"compare_same_ref"`
}
func (c Compare) String() string {
return Stringify(c)
}
// CompareOptions represents the available Compare() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#compare-branches-tags-or-commits
type CompareOptions struct {
From *string `url:"from,omitempty" json:"from,omitempty"`
To *string `url:"to,omitempty" json:"to,omitempty"`
Straight *bool `url:"straight,omitempty" json:"straight,omitempty"`
Unidiff *bool `url:"unidiff,omitempty" json:"unidiff,omitempty"`
}
// Compare compares branches, tags or commits.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#compare-branches-tags-or-commits
func (s *RepositoriesService) Compare(pid interface{}, 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
}
// Contributor represents a GitLap contributor.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repositories.html#contributors
type Contributor struct {
Name string `json:"name"`
Email string `json:"email"`
Commits int `json:"commits"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
}
func (c Contributor) String() string {
return Stringify(c)
}
// ListContributorsOptions represents the available ListContributors() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repositories.html#contributors
type ListContributorsOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
}
// Contributors gets the repository contributors list.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repositories.html#contributors
func (s *RepositoriesService) Contributors(pid interface{}, 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
}
// MergeBaseOptions represents the available MergeBase() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#merge-base
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/ee/api/repositories.html#merge-base
func (s *RepositoriesService) MergeBase(pid interface{}, 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
}
// AddChangelogOptions represents the available AddChangelog() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#add-changelog-data-to-a-changelog-file
type AddChangelogOptions struct {
Version *string `url:"version,omitempty" json:"version,omitempty"`
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
ConfigFile *string `url:"config_file,omitempty" json:"config_file,omitempty"`
Date *ISOTime `url:"date,omitempty" json:"date,omitempty"`
File *string `url:"file,omitempty" json:"file,omitempty"`
From *string `url:"from,omitempty" json:"from,omitempty"`
Message *string `url:"message,omitempty" json:"message,omitempty"`
To *string `url:"to,omitempty" json:"to,omitempty"`
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/ee/api/repositories.html#add-changelog-data-to-a-changelog-file
func (s *RepositoriesService) AddChangelog(pid interface{}, 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)
}
// ChangelogData represents the generated changelog data.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data
type ChangelogData struct {
Notes string `json:"notes"`
}
func (c ChangelogData) String() string {
return Stringify(c)
}
// GenerateChangelogDataOptions represents the available GenerateChangelogData()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data
type GenerateChangelogDataOptions struct {
Version *string `url:"version,omitempty" json:"version,omitempty"`
ConfigFile *string `url:"config_file,omitempty" json:"config_file,omitempty"`
Date *ISOTime `url:"date,omitempty" json:"date,omitempty"`
From *string `url:"from,omitempty" json:"from,omitempty"`
To *string `url:"to,omitempty" json:"to,omitempty"`
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/ee/api/repositories.html#generate-changelog-data
func (s *RepositoriesService) GenerateChangelogData(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"net/http"
"strconv"
"time"
)
// RepositoryFilesService handles communication with the repository files
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_files.html
type RepositoryFilesService struct {
client *Client
}
// File represents a GitLab repository file.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_files.html
type File struct {
FileName string `json:"file_name"`
FilePath string `json:"file_path"`
Size int `json:"size"`
Encoding string `json:"encoding"`
Content string `json:"content"`
ExecuteFilemode bool `json:"execute_filemode"`
Ref string `json:"ref"`
BlobID string `json:"blob_id"`
CommitID string `json:"commit_id"`
SHA256 string `json:"content_sha256"`
LastCommitID string `json:"last_commit_id"`
}
func (r File) String() string {
return Stringify(r)
}
// GetFileOptions represents the available GetFile() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository
type GetFileOptions struct {
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// GetFile allows you to receive information about a file in repository like
// name, size, content. Note that file content is Base64 encoded.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository
func (s *RepositoryFilesService) GetFile(pid interface{}, 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),
)
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.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository
type GetFileMetaDataOptions struct {
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// GetFileMetaData allows you to receive meta information about a file in
// repository like name, size.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository
func (s *RepositoryFilesService) GetFileMetaData(pid interface{}, 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),
)
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
}
f := &File{
BlobID: resp.Header.Get("X-Gitlab-Blob-Id"),
CommitID: resp.Header.Get("X-Gitlab-Commit-Id"),
Encoding: resp.Header.Get("X-Gitlab-Encoding"),
FileName: resp.Header.Get("X-Gitlab-File-Name"),
FilePath: resp.Header.Get("X-Gitlab-File-Path"),
ExecuteFilemode: resp.Header.Get("X-Gitlab-Execute-Filemode") == "true",
Ref: resp.Header.Get("X-Gitlab-Ref"),
SHA256: resp.Header.Get("X-Gitlab-Content-Sha256"),
LastCommitID: resp.Header.Get("X-Gitlab-Last-Commit-Id"),
}
if sizeString := resp.Header.Get("X-Gitlab-Size"); sizeString != "" {
f.Size, err = strconv.Atoi(sizeString)
if err != nil {
return nil, resp, err
}
}
return f, resp, nil
}
// FileBlameRange represents one item of blame information.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_files.html
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"`
}
func (b FileBlameRange) String() string {
return Stringify(b)
}
// GetFileBlameOptions represents the available GetFileBlame() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#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"`
}
// GetFileBlame allows you to receive blame information. Each blame range
// contains lines and corresponding commit info.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-file-blame-from-repository
func (s *RepositoryFilesService) GetFileBlame(pid interface{}, 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),
)
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.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-raw-file-from-repository
type GetRawFileOptions struct {
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
LFS *bool `url:"lfs,omitempty" json:"lfs,omitempty"`
}
// GetRawFile allows you to receive the raw file in repository.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#get-raw-file-from-repository
func (s *RepositoryFilesService) GetRawFile(pid interface{}, 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),
)
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
}
// FileInfo represents file details of a GitLab repository file.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_files.html
type FileInfo struct {
FilePath string `json:"file_path"`
Branch string `json:"branch"`
}
func (r FileInfo) String() string {
return Stringify(r)
}
// CreateFileOptions represents the available CreateFile() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#create-new-file-in-repository
type CreateFileOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"`
Encoding *string `url:"encoding,omitempty" json:"encoding,omitempty"`
AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"`
AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"`
ExecuteFilemode *bool `url:"execute_filemode,omitempty" json:"execute_filemode,omitempty"`
}
// CreateFile creates a new file in a repository.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#create-new-file-in-repository
func (s *RepositoryFilesService) CreateFile(pid interface{}, 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),
)
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.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#update-existing-file-in-repository
type UpdateFileOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"`
Encoding *string `url:"encoding,omitempty" json:"encoding,omitempty"`
AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"`
AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"`
LastCommitID *string `url:"last_commit_id,omitempty" json:"last_commit_id,omitempty"`
ExecuteFilemode *bool `url:"execute_filemode,omitempty" json:"execute_filemode,omitempty"`
}
// UpdateFile updates an existing file in a repository
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#update-existing-file-in-repository
func (s *RepositoryFilesService) UpdateFile(pid interface{}, 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),
)
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.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#delete-existing-file-in-repository
type DeleteFileOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
StartBranch *string `url:"start_branch,omitempty" json:"start_branch,omitempty"`
AuthorEmail *string `url:"author_email,omitempty" json:"author_email,omitempty"`
AuthorName *string `url:"author_name,omitempty" json:"author_name,omitempty"`
CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"`
LastCommitID *string `url:"last_commit_id,omitempty" json:"last_commit_id,omitempty"`
}
// DeleteFile deletes an existing file in a repository
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_files.html#delete-existing-file-in-repository
func (s *RepositoryFilesService) DeleteFile(pid interface{}, 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),
)
req, err := s.client.NewRequest(http.MethodDelete, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// RepositorySubmodulesService handles communication with the repository
// submodules related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_submodules.html
type RepositorySubmodulesService struct {
client *Client
}
// SubmoduleCommit represents a GitLab submodule commit.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/repository_submodules.html
type SubmoduleCommit struct {
ID string `json:"id"`
ShortID string `json:"short_id"`
Title string `json:"title"`
AuthorName string `json:"author_name"`
AuthorEmail string `json:"author_email"`
CommitterName string `json:"committer_name"`
CommitterEmail string `json:"committer_email"`
CreatedAt *time.Time `json:"created_at"`
Message string `json:"message"`
ParentIDs []string `json:"parent_ids"`
CommittedDate *time.Time `json:"committed_date"`
AuthoredDate *time.Time `json:"authored_date"`
Status *BuildStateValue `json:"status"`
}
func (r SubmoduleCommit) String() string {
return Stringify(r)
}
// UpdateSubmoduleOptions represents the available UpdateSubmodule() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_submodules.html#update-existing-submodule-reference-in-repository
type UpdateSubmoduleOptions struct {
Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
CommitSHA *string `url:"commit_sha,omitempty" json:"commit_sha,omitempty"`
CommitMessage *string `url:"commit_message,omitempty" json:"commit_message,omitempty"`
}
// UpdateSubmodule updates an existing submodule reference.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/repository_submodules.html#update-existing-submodule-reference-in-repository
func (s *RepositorySubmodulesService) UpdateSubmodule(pid interface{}, 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),
)
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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"context"
"net/url"
retryablehttp "github.com/hashicorp/go-retryablehttp"
)
// RequestOptionFunc can be passed to all API requests to customize the API request.
type RequestOptionFunc func(*retryablehttp.Request) error
// WithContext runs the request with the provided context
func WithContext(ctx context.Context) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
*req = *req.WithContext(ctx)
return nil
}
}
// WithHeader takes a header name and value and appends it to the request headers.
func WithHeader(name, value string) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
req.Header.Set(name, value)
return nil
}
}
// WithHeaders takes a map of header name/value pairs and appends them to the
// request headers.
func WithHeaders(headers map[string]string) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
for k, v := range headers {
req.Header.Set(k, v)
}
return nil
}
}
// WithKeysetPaginationParameters takes a "next" link from the Link header of a
// response to a keyset-based paginated request and modifies the values of each
// query parameter in the request with its corresponding response parameter.
func WithKeysetPaginationParameters(nextLink string) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
nextUrl, err := url.Parse(nextLink)
if err != nil {
return err
}
q := req.URL.Query()
for k, values := range nextUrl.Query() {
q.Del(k)
for _, v := range values {
q.Add(k, v)
}
}
req.URL.RawQuery = q.Encode()
return nil
}
}
// WithSudo takes either a username or user ID and sets the SUDO request header.
func WithSudo(uid interface{}) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
user, err := parseID(uid)
if err != nil {
return err
}
req.Header.Set("SUDO", user)
return nil
}
}
// WithToken takes a token which is then used when making this one request.
func WithToken(authType AuthType, token string) RequestOptionFunc {
return func(req *retryablehttp.Request) error {
switch authType {
case JobToken:
req.Header.Set("JOB-TOKEN", token)
case OAuthToken:
req.Header.Set("Authorization", "Bearer "+token)
case PrivateToken:
req.Header.Set("PRIVATE-TOKEN", token)
}
return nil
}
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceGroupService handles communication with the resource
// group related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html
type ResourceGroupService struct {
client *Client
}
// ResourceGrouop represents a GitLab Project Resource Group.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html
type ResourceGroup struct {
ID int `json:"id"`
Key string `json:"key"`
ProcessMode string `json:"process_mode"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}
// Gets a string representation of a ResourceGroup
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html
func (rg ResourceGroup) String() string {
return Stringify(rg)
}
// GetAllResourceGroupsForAProject allows you to get all resource
// groups associated with a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html#get-all-resource-groups-for-a-project
func (s *ResourceGroupService) GetAllResourceGroupsForAProject(pid interface{}, 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
}
// GetASpecificResourceGroup allows you to get a specific
// resource group for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html#get-a-specific-resource-group
func (s *ResourceGroupService) GetASpecificResourceGroup(pid interface{}, 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
}
// ListUpcomingJobsForASpecificResourceGroup allows you to get all
// upcoming jobs for a specific resource group for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html#list-upcoming-jobs-for-a-specific-resource-group
func (s *ResourceGroupService) ListUpcomingJobsForASpecificResourceGroup(pid interface{}, 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
}
// EditAnExistingResourceGroupOptions represents the available
// EditAnExistingResourceGroup options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html#edit-an-existing-resource-group
type EditAnExistingResourceGroupOptions struct {
ProcessMode *ResourceGroupProcessMode `url:"process_mode,omitempty" json:"process_mode,omitempty"`
}
// EditAnExistingResourceGroup allows you to edit a specific
// resource group for a given project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_groups.html#edit-an-existing-resource-group
func (s *ResourceGroupService) EditAnExistingResourceGroup(pid interface{}, 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
}
//
// Copyright 2023, Hakki Ceylan, Yavuz Turk
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceIterationEventsService handles communication with the event related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
type ResourceIterationEventsService struct {
client *Client
}
// IterationEvent represents a resource iteration event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
type IterationEvent struct {
ID int `json:"id"`
User *BasicUser `json:"user"`
CreatedAt *time.Time `json:"created_at"`
ResourceType string `json:"resource_type"`
ResourceID int `json:"resource_id"`
Iteration *Iteration `json:"iteration"`
Action string `json:"action"`
}
// Iteration represents a project issue iteration.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
type Iteration struct {
ID int `json:"id"`
IID int `json:"iid"`
Sequence int `json:"sequence"`
GroupId int `json:"group_id"`
Title string `json:"title"`
Description string `json:"description"`
State int `json:"state"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
DueDate *ISOTime `json:"due_date"`
StartDate *ISOTime `json:"start_date"`
WebURL string `json:"web_url"`
}
// ListIterationEventsOptions represents the options for all resource state
// events list methods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_iteration_events.html#list-project-issue-iteration-events
type ListIterationEventsOptions struct {
ListOptions
}
// ListIssueIterationEvents retrieves resource iteration events for the
// specified project and issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_iteration_events.html#list-project-issue-iteration-events
func (s *ResourceIterationEventsService) ListIssueIterationEvents(pid interface{}, 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
}
// GetIssueIterationEvent gets a single issue iteration event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_iteration_events.html#get-single-issue-iteration-event
func (s *ResourceIterationEventsService) GetIssueIterationEvent(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceLabelEventsService handles communication with the event related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_label_events.html
type ResourceLabelEventsService struct {
client *Client
}
// LabelEvent represents a resource label event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#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"`
}
// ListLabelEventsOptions represents the options for all resource label events
// list methods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#list-project-issue-label-events
type ListLabelEventsOptions struct {
ListOptions
}
// ListIssueLabelEvents retrieves resource label events for the
// specified project and issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#list-project-issue-label-events
func (s *ResourceLabelEventsService) ListIssueLabelEvents(pid interface{}, 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
}
// GetIssueLabelEvent gets a single issue-label-event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#get-single-issue-label-event
func (s *ResourceLabelEventsService) GetIssueLabelEvent(pid interface{}, 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
}
// ListGroupEpicLabelEvents retrieves resource label events for the specified
// group and epic.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#list-group-epic-label-events
func (s *ResourceLabelEventsService) ListGroupEpicLabelEvents(gid interface{}, 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
}
// GetGroupEpicLabelEvent gets a single group epic label event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#get-single-epic-label-event
func (s *ResourceLabelEventsService) GetGroupEpicLabelEvent(gid interface{}, 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
}
// ListMergeRequestsLabelEvents retrieves resource label events for the specified
// project and merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#list-project-merge-request-label-events
func (s *ResourceLabelEventsService) ListMergeRequestsLabelEvents(pid interface{}, 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
}
// GetMergeRequestLabelEvent gets a single merge request label event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_label_events.html#get-single-merge-request-label-event
func (s *ResourceLabelEventsService) GetMergeRequestLabelEvent(pid interface{}, 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
}
//
// Copyright 2022, Mai Lapyst
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceMilestoneEventsService handles communication with the event related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_milestone_events.html
type ResourceMilestoneEventsService struct {
client *Client
}
// MilestoneEvent represents a resource milestone event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_milestone_events.html
type MilestoneEvent struct {
ID int `json:"id"`
User *BasicUser `json:"user"`
CreatedAt *time.Time `json:"created_at"`
ResourceType string `json:"resource_type"`
ResourceID int `json:"resource_id"`
Milestone *Milestone `json:"milestone"`
Action string `json:"action"`
}
// ListMilestoneEventsOptions represents the options for all resource state events
// list methods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_milestone_events.html#list-project-issue-milestone-events
type ListMilestoneEventsOptions struct {
ListOptions
}
// ListIssueMilestoneEvents retrieves resource milestone events for the specified
// project and issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_milestone_events.html#list-project-issue-milestone-events
func (s *ResourceMilestoneEventsService) ListIssueMilestoneEvents(pid interface{}, 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
}
// GetIssueMilestoneEvent gets a single issue milestone event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_milestone_events.html#get-single-issue-milestone-event
func (s *ResourceMilestoneEventsService) GetIssueMilestoneEvent(pid interface{}, 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
}
// ListMergeMilestoneEvents retrieves resource milestone events for the specified
// project and merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_milestone_events.html#list-project-merge-request-milestone-events
func (s *ResourceMilestoneEventsService) ListMergeMilestoneEvents(pid interface{}, 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
}
// GetMergeRequestMilestoneEvent gets a single merge request milestone event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_milestone_events.html#get-single-merge-request-milestone-event
func (s *ResourceMilestoneEventsService) GetMergeRequestMilestoneEvent(pid interface{}, 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
}
//
// Copyright 2021, Matthias Simon
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceStateEventsService handles communication with the event related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_state_events.html
type ResourceStateEventsService struct {
client *Client
}
// StateEvent represents a resource state event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_state_events.html
type StateEvent struct {
ID int `json:"id"`
User *BasicUser `json:"user"`
CreatedAt *time.Time `json:"created_at"`
ResourceType string `json:"resource_type"`
ResourceID int `json:"resource_id"`
State EventTypeValue `json:"state"`
}
// ListStateEventsOptions represents the options for all resource state events
// list methods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_state_events.html#list-project-issue-state-events
type ListStateEventsOptions struct {
ListOptions
}
// ListIssueStateEvents retrieves resource state events for the specified
// project and issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_state_events.html#list-project-issue-state-events
func (s *ResourceStateEventsService) ListIssueStateEvents(pid interface{}, 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
}
// GetIssueStateEvent gets a single issue-state-event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_state_events.html#get-single-issue-state-event
func (s *ResourceStateEventsService) GetIssueStateEvent(pid interface{}, 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
}
// ListMergeStateEvents retrieves resource state events for the specified
// project and merge request.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_state_events.html#list-project-merge-request-state-events
func (s *ResourceStateEventsService) ListMergeStateEvents(pid interface{}, 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
}
// GetMergeRequestStateEvent gets a single merge request state event.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_state_events.html#get-single-merge-request-state-event
func (s *ResourceStateEventsService) GetMergeRequestStateEvent(pid interface{}, 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
}
//
// Copyright 2021, Matthias Simon
//
// 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 (
"fmt"
"net/http"
"time"
)
// ResourceWeightEventsService handles communication with the event related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_weight_events.html
type ResourceWeightEventsService struct {
client *Client
}
// WeightEvent represents a resource weight event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/resource_weight_events.html
type WeightEvent struct {
ID int `json:"id"`
User *BasicUser `json:"user"`
CreatedAt *time.Time `json:"created_at"`
ResourceType string `json:"resource_type"`
ResourceID int `json:"resource_id"`
State EventTypeValue `json:"state"`
IssueID int `json:"issue_id"`
Weight int `json:"weight"`
}
// ListWeightEventsOptions represents the options for all resource weight events
// list methods.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_weight_events.html#list-project-issue-weight-events
type ListWeightEventsOptions struct {
ListOptions
}
// ListIssueWeightEvents retrieves resource weight events for the specified
// project and issue.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/resource_weight_events.html#list-project-issue-weight-events
func (s *ResourceWeightEventsService) ListIssueWeightEvents(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// RunnersService handles communication with the runner related methods of the
// GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/runners.html
type RunnersService struct {
client *Client
}
// Runner represents a GitLab CI Runner.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/runners.html
type Runner struct {
ID int `json:"id"`
Description string `json:"description"`
Active bool `json:"active"`
Paused bool `json:"paused"`
IsShared bool `json:"is_shared"`
IPAddress string `json:"ip_address"`
RunnerType string `json:"runner_type"`
Name string `json:"name"`
Online bool `json:"online"`
Status string `json:"status"`
Token string `json:"token"`
TokenExpiresAt *time.Time `json:"token_expires_at"`
}
// RunnerDetails represents the GitLab CI runner details.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/runners.html
type RunnerDetails struct {
Paused bool `json:"paused"`
Architecture string `json:"architecture"`
Description string `json:"description"`
ID int `json:"id"`
IPAddress string `json:"ip_address"`
IsShared bool `json:"is_shared"`
RunnerType string `json:"runner_type"`
ContactedAt *time.Time `json:"contacted_at"`
Name string `json:"name"`
Online bool `json:"online"`
Status string `json:"status"`
Platform string `json:"platform"`
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"`
Revision string `json:"revision"`
TagList []string `json:"tag_list"`
RunUntagged bool `json:"run_untagged"`
Version string `json:"version"`
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"`
// Deprecated: Use Paused instead. (Deprecated in GitLab 14.8)
Active bool `json:"active"`
}
// ListRunnersOptions represents the available ListRunners() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#list-owned-runners
type ListRunnersOptions struct {
ListOptions
Type *string `url:"type,omitempty" json:"type,omitempty"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
Paused *bool `url:"paused,omitempty" json:"paused,omitempty"`
TagList *[]string `url:"tag_list,comma,omitempty" json:"tag_list,omitempty"`
// Deprecated: Use Type or Status instead.
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/ee/api/runners.html#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)
if err != nil {
return nil, resp, err
}
return rs, 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/ee/api/runners.html#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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// GetRunnerDetails returns details for given runner.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#get-runners-details
func (s *RunnersService) GetRunnerDetails(rid interface{}, 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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// UpdateRunnerDetailsOptions represents the available UpdateRunnerDetails() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#update-runners-details
type UpdateRunnerDetailsOptions struct {
Description *string `url:"description,omitempty" json:"description,omitempty"`
Paused *bool `url:"paused,omitempty" json:"paused,omitempty"`
TagList *[]string `url:"tag_list[],omitempty" json:"tag_list,omitempty"`
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"`
// Deprecated: Use Paused instead. (Deprecated in GitLab 14.8)
Active *bool `url:"active,omitempty" json:"active,omitempty"`
}
// UpdateRunnerDetails updates details for a given runner.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#update-runners-details
func (s *RunnersService) UpdateRunnerDetails(rid interface{}, 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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// RemoveRunner removes a runner.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#delete-a-runner
func (s *RunnersService) RemoveRunner(rid interface{}, 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)
}
// ListRunnerJobsOptions represents the available ListRunnerJobs()
// options. Status can be one of: running, success, failed, canceled.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#list-runners-jobs
type ListRunnerJobsOptions struct {
ListOptions
Status *string `url:"status,omitempty" json:"status,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
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/ee/api/runners.html#list-runners-jobs
func (s *RunnersService) ListRunnerJobs(rid interface{}, 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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// ListProjectRunnersOptions represents the available ListProjectRunners()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#list-projects-runners
type ListProjectRunnersOptions ListRunnersOptions
// ListProjectRunners gets a list of runners accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#list-projects-runners
func (s *RunnersService) ListProjectRunners(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// EnableProjectRunnerOptions represents the available EnableProjectRunner()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#enable-a-runner-in-project
type EnableProjectRunnerOptions struct {
RunnerID int `json:"runner_id"`
}
// EnableProjectRunner enables an available specific runner in the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#enable-a-runner-in-project
func (s *RunnersService) EnableProjectRunner(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// DisableProjectRunner disables a specific runner from project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#disable-a-runner-from-project
func (s *RunnersService) DisableProjectRunner(pid interface{}, 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)
}
// ListGroupsRunnersOptions represents the available ListGroupsRunners() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#list-groups-runners
type ListGroupsRunnersOptions struct {
ListOptions
Type *string `url:"type,omitempty" json:"type,omitempty"`
Status *string `url:"status,omitempty" json:"status,omitempty"`
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/ee/api/runners.html#list-groups-runners
func (s *RunnersService) ListGroupsRunners(gid interface{}, 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)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// RegisterNewRunnerOptions represents the available RegisterNewRunner()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner
type RegisterNewRunnerOptions struct {
Token *string `url:"token" json:"token"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Info *RegisterNewRunnerInfoOptions `url:"info,omitempty" json:"info,omitempty"`
Active *bool `url:"active,omitempty" json:"active,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"`
MaintenanceNote *string `url:"maintenance_note,omitempty" json:"maintenance_note,omitempty"`
}
// RegisterNewRunnerInfoOptions represents the info hashmap parameter in
// RegisterNewRunnerOptions.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner
type RegisterNewRunnerInfoOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Version *string `url:"version,omitempty" json:"version,omitempty"`
Revision *string `url:"revision,omitempty" json:"revision,omitempty"`
Platform *string `url:"platform,omitempty" json:"platform,omitempty"`
Architecture *string `url:"architecture,omitempty" json:"architecture,omitempty"`
}
// RegisterNewRunner registers a new Runner for the instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#register-a-new-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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// DeleteRegisteredRunnerOptions represents the available
// DeleteRegisteredRunner() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#delete-a-runner-by-authentication-token
type DeleteRegisteredRunnerOptions struct {
Token *string `url:"token" json:"token"`
}
// DeleteRegisteredRunner deletes a Runner by Token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#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)
}
// DeleteRegisteredRunnerByID deletes a runner by ID.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#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)
}
// VerifyRegisteredRunnerOptions represents the available
// VerifyRegisteredRunner() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#verify-authentication-for-a-registered-runner
type VerifyRegisteredRunnerOptions struct {
Token *string `url:"token" json:"token"`
}
// VerifyRegisteredRunner registers a new runner for the instance.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#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)
}
type RunnerRegistrationToken struct {
Token *string `url:"token" json:"token"`
TokenExpiresAt *time.Time `url:"token_expires_at" json:"token_expires_at"`
}
// ResetInstanceRunnerRegistrationToken resets the instance runner registration
// token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// ResetGroupRunnerRegistrationToken resets a group's runner registration token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#reset-groups-runner-registration-token
func (s *RunnersService) ResetGroupRunnerRegistrationToken(gid interface{}, 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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// ResetGroupRunnerRegistrationToken resets a projects's runner registration token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/runners.html#reset-projects-runner-registration-token
func (s *RunnersService) ResetProjectRunnerRegistrationToken(pid interface{}, 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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
type RunnerAuthenticationToken struct {
Token *string `url:"token" json:"token"`
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/ee/api/runners.html#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)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// SearchService handles communication with the search related methods of the
// GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html
type SearchService struct {
client *Client
}
// SearchOptions represents the available options for all search methods.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html
type SearchOptions struct {
ListOptions
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
type searchOptions struct {
SearchOptions
Scope string `url:"scope" json:"scope"`
Search string `url:"search" json:"search"`
}
// Projects searches the expression within projects
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// ProjectsByGroup searches the expression within projects for
// the specified group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#group-search-api
func (s *SearchService) ProjectsByGroup(gid interface{}, 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
}
// Issues searches the expression within issues
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// IssuesByGroup searches the expression within issues for
// the specified group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-issues-1
func (s *SearchService) IssuesByGroup(gid interface{}, 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
}
// IssuesByProject searches the expression within issues for
// the specified project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-issues-2
func (s *SearchService) IssuesByProject(pid interface{}, 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
}
// MergeRequests searches the expression within merge requests
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#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
}
// MergeRequestsByGroup searches the expression within merge requests for
// the specified group
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#scope-merge_requests-1
func (s *SearchService) MergeRequestsByGroup(gid interface{}, 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
}
// MergeRequestsByProject searches the expression within merge requests for
// the specified project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#scope-merge_requests-2
func (s *SearchService) MergeRequestsByProject(pid interface{}, 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
}
// Milestones searches the expression within milestones
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// MilestonesByGroup searches the expression within milestones for
// the specified group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-milestones-1
func (s *SearchService) MilestonesByGroup(gid interface{}, 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
}
// MilestonesByProject searches the expression within milestones for
// the specified project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-milestones-2
func (s *SearchService) MilestonesByProject(pid interface{}, 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
}
// SnippetTitles searches the expression within snippet titles
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#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
}
// SnippetBlobs searches the expression within snippet blobs
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#scope-snippet_blobs
func (s *SearchService) SnippetBlobs(query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*Snippet, *Response, error) {
var ss []*Snippet
resp, err := s.search("snippet_blobs", query, &ss, opt, options...)
return ss, resp, err
}
// NotesByProject searches the expression within notes for the specified
// project
//
// GitLab API docs: // https://docs.gitlab.com/ee/api/search.html#scope-notes
func (s *SearchService) NotesByProject(pid interface{}, 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
}
// WikiBlobs searches the expression within all wiki blobs
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#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
}
// WikiBlobsByGroup searches the expression within wiki blobs for
// specified group
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#scope-wiki_blobs-premium-1
func (s *SearchService) WikiBlobsByGroup(gid interface{}, 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
}
// WikiBlobsByProject searches the expression within wiki blobs for
// the specified project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/search.html#scope-wiki_blobs-premium-2
func (s *SearchService) WikiBlobsByProject(pid interface{}, 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
}
// Commits searches the expression within all commits
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// CommitsByGroup searches the expression within commits for the specified
// group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-commits-premium-1
func (s *SearchService) CommitsByGroup(gid interface{}, 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
}
// CommitsByProject searches the expression within commits for the
// specified project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-commits-premium-2
func (s *SearchService) CommitsByProject(pid interface{}, 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
}
// Blob represents a single blob.
type Blob struct {
Basename string `json:"basename"`
Data string `json:"data"`
Path string `json:"path"`
Filename string `json:"filename"`
ID string `json:"id"`
Ref string `json:"ref"`
Startline int `json:"startline"`
ProjectID int `json:"project_id"`
}
// Blobs searches the expression within all blobs
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// BlobsByGroup searches the expression within blobs for the specified
// group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-blobs-premium-1
func (s *SearchService) BlobsByGroup(gid interface{}, 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
}
// BlobsByProject searches the expression within blobs for the specified
// project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-blobs-premium-2
func (s *SearchService) BlobsByProject(pid interface{}, 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
}
// Users searches the expression within all users
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#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
}
// UsersByGroup searches the expression within users for the specified
// group
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-users-1
func (s *SearchService) UsersByGroup(gid interface{}, query string, opt *SearchOptions, options ...RequestOptionFunc) ([]*User, *Response, error) {
var ret []*User
resp, err := s.searchByGroup(gid, "users", query, &ret, opt, options...)
return ret, resp, err
}
// UsersByProject searches the expression within users for the
// specified project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/search.html#scope-users-2
func (s *SearchService) UsersByProject(pid interface{}, 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 interface{}, 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 interface{}, scope, query string, result interface{}, 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 interface{}, scope, query string, result interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
)
// ServicesService handles communication with the services related methods of
// the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/integrations.html
type ServicesService struct {
client *Client
}
// Service represents a GitLab service.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/integrations.html
type Service 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"`
Active bool `json:"active"`
PushEvents bool `json:"push_events"`
IssuesEvents bool `json:"issues_events"`
AlertEvents bool `json:"alert_events"`
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
CommitEvents bool `json:"commit_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
CommentOnEventEnabled bool `json:"comment_on_event_enabled"`
TagPushEvents bool `json:"tag_push_events"`
NoteEvents bool `json:"note_events"`
ConfidentialNoteEvents bool `json:"confidential_note_events"`
PipelineEvents bool `json:"pipeline_events"`
JobEvents bool `json:"job_events"`
WikiPageEvents bool `json:"wiki_page_events"`
VulnerabilityEvents bool `json:"vulnerability_events"`
DeploymentEvents bool `json:"deployment_events"`
}
// ListServices gets a list of all active services.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/integrations.html#list-all-active-integrations
func (s *ServicesService) ListServices(pid interface{}, 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
}
// CustomIssueTrackerService represents Custom Issue Tracker service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#custom-issue-tracker
type CustomIssueTrackerService struct {
Service
Properties *CustomIssueTrackerServiceProperties `json:"properties"`
}
// CustomIssueTrackerServiceProperties represents Custom Issue Tracker specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#custom-issue-tracker
type CustomIssueTrackerServiceProperties struct {
ProjectURL string `json:"project_url,omitempty"`
IssuesURL string `json:"issues_url,omitempty"`
NewIssueURL string `json:"new_issue_url,omitempty"`
}
// GetCustomIssueTrackerService gets Custom Issue Tracker service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-custom-issue-tracker-settings
func (s *ServicesService) GetCustomIssueTrackerService(pid interface{}, 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
}
// SetCustomIssueTrackerServiceOptions represents the available SetCustomIssueTrackerService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-a-custom-issue-tracker
type SetCustomIssueTrackerServiceOptions struct {
NewIssueURL *string `url:"new_issue_url,omitempty" json:"new_issue_url,omitempty"`
IssuesURL *string `url:"issues_url,omitempty" json:"issues_url,omitempty"`
ProjectURL *string `url:"project_url,omitempty" json:"project_url,omitempty"`
}
// SetCustomIssueTrackerService sets Custom Issue Tracker service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-a-custom-issue-tracker
func (s *ServicesService) SetCustomIssueTrackerService(pid interface{}, opt *SetCustomIssueTrackerServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteCustomIssueTrackerService deletes Custom Issue Tracker service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-a-custom-issue-tracker
func (s *ServicesService) DeleteCustomIssueTrackerService(pid interface{}, 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)
}
// DataDogService represents DataDog service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#datadog
type DataDogService struct {
Service
Properties *DataDogServiceProperties `json:"properties"`
}
// DataDogServiceProperties represents DataDog specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#datadog
type DataDogServiceProperties struct {
APIURL string `url:"api_url,omitempty" json:"api_url,omitempty"`
DataDogEnv string `url:"datadog_env,omitempty" json:"datadog_env,omitempty"`
DataDogService string `url:"datadog_service,omitempty" json:"datadog_service,omitempty"`
DataDogSite string `url:"datadog_site,omitempty" json:"datadog_site,omitempty"`
DataDogTags string `url:"datadog_tags,omitempty" json:"datadog_tags,omitempty"`
ArchiveTraceEvents bool `url:"archive_trace_events,omitempty" json:"archive_trace_events,omitempty"`
}
// GetDataDogService gets DataDog service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-datadog-settings
func (s *ServicesService) GetDataDogService(pid interface{}, options ...RequestOptionFunc) (*DataDogService, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/services/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
}
// SetDataDogServiceOptions represents the available SetDataDogService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-datadog
type SetDataDogServiceOptions struct {
APIKey *string `url:"api_key,omitempty" json:"api_key,omitempty"`
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
DataDogEnv *string `url:"datadog_env,omitempty" json:"datadog_env,omitempty"`
DataDogService *string `url:"datadog_service,omitempty" json:"datadog_service,omitempty"`
DataDogSite *string `url:"datadog_site,omitempty" json:"datadog_site,omitempty"`
DataDogTags *string `url:"datadog_tags,omitempty" json:"datadog_tags,omitempty"`
ArchiveTraceEvents *bool `url:"archive_trace_events,omitempty" json:"archive_trace_events,omitempty"`
}
// SetDataDogService sets DataDog service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-datadog
func (s *ServicesService) SetDataDogService(pid interface{}, opt *SetDataDogServiceOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/datadog", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteDataDogService deletes the DataDog service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-datadog
func (s *ServicesService) DeleteDataDogService(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/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)
}
// DiscordService represents Discord service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#discord-notifications
type DiscordService struct {
Service
Properties *DiscordServiceProperties `json:"properties"`
}
// DiscordServiceProperties represents Discord specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#discord-notifications
type DiscordServiceProperties struct {
BranchesToBeNotified string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"`
NotifyOnlyBrokenPipelines bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"`
}
// GetDiscordService gets Discord service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-discord-notifications-settings
func (s *ServicesService) GetDiscordService(pid interface{}, 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
}
// SetDiscordServiceOptions represents the available SetDiscordService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-discord-notifications
type SetDiscordServiceOptions struct {
WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty"`
BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"`
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
ConfidentialIssuesChannel *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
ConfidentialNoteChannel *string `url:"confidential_note_channel,omitempty" json:"confidential_note_channel,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
DeploymentChannel *string `url:"deployment_channel,omitempty" json:"deployment_channel,omitempty"`
GroupConfidentialMentionsEvents *bool `url:"group_confidential_mentions_events,omitempty" json:"group_confidential_mentions_events,omitempty"`
GroupConfidentialMentionsChannel *string `url:"group_confidential_mentions_channel,omitempty" json:"group_confidential_mentions_channel,omitempty"`
GroupMentionsEvents *bool `url:"group_mentions_events,omitempty" json:"group_mentions_events,omitempty"`
GroupMentionsChannel *string `url:"group_mentions_channel,omitempty" json:"group_mentions_channel,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
IssueChannel *string `url:"issue_channel,omitempty" json:"issue_channel,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
MergeRequestChannel *string `url:"merge_request_channel,omitempty" json:"merge_request_channel,omitempty"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
NoteChannel *string `url:"note_channel,omitempty" json:"note_channel,omitempty"`
NotifyOnlyBrokenPipelines *bool `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
PipelineChannel *string `url:"pipeline_channel,omitempty" json:"pipeline_channel,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
PushChannel *string `url:"push_channel,omitempty" json:"push_channel,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
TagPushChannel *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
WikiPageChannel *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"`
}
// SetDiscordService sets Discord service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-discord-notifications
func (s *ServicesService) SetDiscordService(pid interface{}, opt *SetDiscordServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteDiscordService deletes Discord service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-discord-notifications
func (s *ServicesService) DeleteDiscordService(pid interface{}, 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)
}
// DroneCIService represents Drone CI service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#drone
type DroneCIService struct {
Service
Properties *DroneCIServiceProperties `json:"properties"`
}
// DroneCIServiceProperties represents Drone CI specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#drone
type DroneCIServiceProperties struct {
DroneURL string `json:"drone_url"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
}
// GetDroneCIService gets Drone CI service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-drone-settings
func (s *ServicesService) GetDroneCIService(pid interface{}, 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
}
// SetDroneCIServiceOptions represents the available SetDroneCIService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-drone
type SetDroneCIServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty"`
DroneURL *string `url:"drone_url,omitempty" json:"drone_url,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_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"`
}
// SetDroneCIService sets Drone CI service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-drone
func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteDroneCIService deletes Drone CI service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-drone
func (s *ServicesService) DeleteDroneCIService(pid interface{}, 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)
}
// EmailsOnPushService represents Emails on Push service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#emails-on-push
type EmailsOnPushService struct {
Service
Properties *EmailsOnPushServiceProperties `json:"properties"`
}
// EmailsOnPushServiceProperties represents Emails on Push specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#emails-on-push
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"`
}
// GetEmailsOnPushService gets Emails on Push service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-emails-on-push-integration-settings
func (s *ServicesService) GetEmailsOnPushService(pid interface{}, 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
}
// SetEmailsOnPushServiceOptions represents the available SetEmailsOnPushService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-emails-on-push
type SetEmailsOnPushServiceOptions struct {
Recipients *string `url:"recipients,omitempty" json:"recipients,omitempty"`
DisableDiffs *bool `url:"disable_diffs,omitempty" json:"disable_diffs,omitempty"`
SendFromCommitterEmail *bool `url:"send_from_committer_email,omitempty" json:"send_from_committer_email,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"`
}
// SetEmailsOnPushService sets Emails on Push service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-emails-on-push
func (s *ServicesService) SetEmailsOnPushService(pid interface{}, opt *SetEmailsOnPushServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteEmailsOnPushService deletes Emails on Push service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-emails-on-push
func (s *ServicesService) DeleteEmailsOnPushService(pid interface{}, 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)
}
// ExternalWikiService represents External Wiki service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#external-wiki
type ExternalWikiService struct {
Service
Properties *ExternalWikiServiceProperties `json:"properties"`
}
// ExternalWikiServiceProperties represents External Wiki specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#external-wiki
type ExternalWikiServiceProperties struct {
ExternalWikiURL string `json:"external_wiki_url"`
}
// GetExternalWikiService gets External Wiki service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-external-wiki-settings
func (s *ServicesService) GetExternalWikiService(pid interface{}, 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
}
// SetExternalWikiServiceOptions represents the available SetExternalWikiService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-an-external-wiki
type SetExternalWikiServiceOptions struct {
ExternalWikiURL *string `url:"external_wiki_url,omitempty" json:"external_wiki_url,omitempty"`
}
// SetExternalWikiService sets External Wiki service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-an-external-wiki
func (s *ServicesService) SetExternalWikiService(pid interface{}, opt *SetExternalWikiServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteExternalWikiService deletes External Wiki service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-an-external-wiki
func (s *ServicesService) DeleteExternalWikiService(pid interface{}, 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)
}
// GithubService represents Github service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#github
type GithubService struct {
Service
Properties *GithubServiceProperties `json:"properties"`
}
// GithubServiceProperties represents Github specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#github
type GithubServiceProperties struct {
RepositoryURL string `json:"repository_url"`
StaticContext bool `json:"static_context"`
}
// GetGithubService gets Github service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-github-settings
func (s *ServicesService) GetGithubService(pid interface{}, 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
}
// SetGithubServiceOptions represents the available SetGithubService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-github
type SetGithubServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty"`
RepositoryURL *string `url:"repository_url,omitempty" json:"repository_url,omitempty"`
StaticContext *bool `url:"static_context,omitempty" json:"static_context,omitempty"`
}
// SetGithubService sets Github service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-github
func (s *ServicesService) SetGithubService(pid interface{}, opt *SetGithubServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteGithubService deletes Github service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-github
func (s *ServicesService) DeleteGithubService(pid interface{}, 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)
}
// SlackApplication represents GitLab for slack application settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#gitlab-for-slack-app
type SlackApplication struct {
Service
Properties *SlackApplicationProperties `json:"properties"`
}
// SlackApplicationProperties represents GitLab for slack application specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#gitlab-for-slack-app
type SlackApplicationProperties struct {
Channel string `json:"channel"`
NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
AlertEvents bool `json:"alert_events"`
IssuesEvents bool `json:"issues_events"`
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
NoteEvents bool `json:"note_events"`
ConfidentialNoteEvents bool `json:"confidential_note_events"`
DeploymentEvents bool `json:"deployment_events"`
IncidentsEvents bool `json:"incidents_events"`
PipelineEvents bool `json:"pipeline_events"`
PushEvents bool `json:"push_events"`
TagPushEvents bool `json:"tag_push_events"`
VulnerabilityEvents bool `json:"vulnerability_events"`
WikiPageEvents bool `json:"wiki_page_events"`
// Deprecated: This parameter has been replaced with BranchesToBeNotified.
NotifyOnlyDefaultBranch bool `json:"notify_only_default_branch"`
}
// GetSlackApplication gets the GitLab for Slack app integration settings for a
// project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-gitlab-for-slack-app-settings
func (s *ServicesService) GetSlackApplication(pid interface{}, 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
}
// SetSlackApplicationOptions represents the available SetSlackApplication()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-gitlab-for-slack-app
type SetSlackApplicationOptions struct {
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"`
AlertEvents *bool `url:"alert_events,omitempty" json:"alert_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"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
IncidentsEvents *bool `url:"incidents_events,omitempty" json:"incidents_events,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
VulnerabilityEvents *bool `url:"vulnerability_events,omitempty" json:"vulnerability_events,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
// Deprecated: This parameter has been replaced with BranchesToBeNotified.
NotifyOnlyDefaultBranch *bool `url:"notify_only_default_branch,omitempty" json:"notify_only_default_branch,omitempty"`
}
// SetSlackApplication update the GitLab for Slack app integration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-gitlab-for-slack-app
func (s *ServicesService) SetSlackApplication(pid interface{}, opt *SetSlackApplicationOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DisableSlackApplication disable the GitLab for Slack app integration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-gitlab-for-slack-app
func (s *ServicesService) DisableSlackApplication(pid interface{}, 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)
}
// SetGitLabCIServiceOptions represents the available SetGitLabCIService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-gitlab-ci-service
type SetGitLabCIServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty"`
ProjectURL *string `url:"project_url,omitempty" json:"project_url,omitempty"`
}
// SetGitLabCIService sets GitLab CI service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-gitlab-ci-service
func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCIServiceOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/gitlab-ci", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteGitLabCIService deletes GitLab CI service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-gitlab-ci-service
func (s *ServicesService) DeleteGitLabCIService(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/gitlab-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)
}
// SetHipChatServiceOptions represents the available SetHipChatService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-hipchat-service
type SetHipChatServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty" `
Room *string `url:"room,omitempty" json:"room,omitempty"`
}
// SetHipChatService sets HipChat service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-hipchat-service
func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServiceOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/hipchat", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteHipChatService deletes HipChat service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-hipchat-service
func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/hipchat", PathEscape(project))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// JenkinsCIService represents Jenkins CI service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#jenkins
type JenkinsCIService struct {
Service
Properties *JenkinsCIServiceProperties `json:"properties"`
}
// JenkinsCIServiceProperties represents Jenkins CI specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#jenkins
type JenkinsCIServiceProperties struct {
URL string `json:"jenkins_url"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
ProjectName string `json:"project_name"`
Username string `json:"username"`
}
// GetJenkinsCIService gets Jenkins CI service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-jenkins-settings
func (s *ServicesService) GetJenkinsCIService(pid interface{}, 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
}
// SetJenkinsCIServiceOptions represents the available SetJenkinsCIService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#jenkins
type SetJenkinsCIServiceOptions struct {
URL *string `url:"jenkins_url,omitempty" json:"jenkins_url,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
ProjectName *string `url:"project_name,omitempty" json:"project_name,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
Password *string `url:"password,omitempty" json:"password,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_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"`
}
// SetJenkinsCIService sets Jenkins service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-jenkins
func (s *ServicesService) SetJenkinsCIService(pid interface{}, opt *SetJenkinsCIServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteJenkinsCIService deletes Jenkins CI service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-jenkins
func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, 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)
}
// JiraService represents Jira service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#jira
type JiraService struct {
Service
Properties *JiraServiceProperties `json:"properties"`
}
// JiraServiceProperties represents Jira specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#jira
type JiraServiceProperties struct {
URL string `json:"url"`
APIURL string `json:"api_url"`
ProjectKeys []string `json:"project_keys" `
Username string `json:"username" `
Password string `json:"password" `
JiraIssueTransitionID string `json:"jira_issue_transition_id"`
// Deprecated: This parameter was removed in GitLab 17.0
ProjectKey string `json:"project_key" `
}
// UnmarshalJSON decodes the Jira Service Properties.
//
// This allows support of JiraIssueTransitionID for both type string (>11.9) and float64 (<11.9)
func (p *JiraServiceProperties) UnmarshalJSON(b []byte) error {
type Alias JiraServiceProperties
raw := struct {
*Alias
JiraIssueTransitionID interface{} `json:"jira_issue_transition_id"`
}{
Alias: (*Alias)(p),
}
if err := json.Unmarshal(b, &raw); err != nil {
return err
}
switch id := raw.JiraIssueTransitionID.(type) {
case nil:
// No action needed.
case string:
p.JiraIssueTransitionID = id
case float64:
p.JiraIssueTransitionID = strconv.Itoa(int(id))
default:
return fmt.Errorf("failed to unmarshal JiraTransitionID of type: %T", id)
}
return nil
}
// GetJiraService gets Jira service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-jira-service-settings
func (s *ServicesService) GetJiraService(pid interface{}, options ...RequestOptionFunc) (*JiraService, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/services/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
}
// SetJiraServiceOptions represents the available SetJiraService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-jira-service
type SetJiraServiceOptions 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 *int `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,comma,omitempty" json:"project_keys,omitempty" `
UseInheritedSettings *bool `url:"use_inherited_settings,omitempty" json:"use_inherited_settings,omitempty"`
// Deprecated: This parameter was removed in GitLab 17.0
ProjectKey *string `url:"project_key,omitempty" json:"project_key,omitempty" `
}
// SetJiraService sets Jira service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-jira-service
func (s *ServicesService) SetJiraService(pid interface{}, opt *SetJiraServiceOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/jira", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteJiraService deletes Jira service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-jira-service
func (s *ServicesService) DeleteJiraService(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/jira", PathEscape(project))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// MattermostService represents Mattermost service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#mattermost-notifications
type MattermostService struct {
Service
Properties *MattermostServiceProperties `json:"properties"`
}
// MattermostServiceProperties represents Mattermost specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#mattermost-notifications
type MattermostServiceProperties struct {
WebHook string `json:"webhook"`
Username string `json:"username"`
Channel string `json:"channel"`
NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
ConfidentialIssueChannel string `json:"confidential_issue_channel"`
ConfidentialNoteChannel string `json:"confidential_note_channel"`
IssueChannel string `json:"issue_channel"`
MergeRequestChannel string `json:"merge_request_channel"`
NoteChannel string `json:"note_channel"`
TagPushChannel string `json:"tag_push_channel"`
PipelineChannel string `json:"pipeline_channel"`
PushChannel string `json:"push_channel"`
VulnerabilityChannel string `json:"vulnerability_channel"`
WikiPageChannel string `json:"wiki_page_channel"`
}
// GetMattermostService gets Mattermost service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-slack-service-settings
func (s *ServicesService) GetMattermostService(pid interface{}, 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
}
// SetMattermostServiceOptions represents the available SetMattermostService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-mattermost-notifications-service
type SetMattermostServiceOptions 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"`
ConfidentialNoteChannel *string `url:"confidential_note_channel,omitempty" json:"confidential_note_channel,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_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"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,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"`
}
// MattermostSlashCommandsService represents Mattermost slash commands settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#mattermost-slash-commands
type MattermostSlashCommandsService struct {
Service
Properties *MattermostSlashCommandsProperties `json:"properties"`
}
// MattermostSlashCommandsProperties represents Mattermost slash commands specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#mattermost-slash-commands
type MattermostSlashCommandsProperties struct {
Token string `json:"token"`
Username string `json:"username,omitempty"`
}
// GetMattermostSlashCommandsService gets Slack Mattermost commands service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-mattermost-slash-command-integration-settings
func (s *ServicesService) GetMattermostSlashCommandsService(pid interface{}, 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
}
// SetMattermostSlashCommandsServiceOptions represents the available SetSlackSlashCommandsService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-mattermost-slash-command-integration-settings
type SetMattermostSlashCommandsServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
}
// SetMattermostSlashCommandsService sets Mattermost slash commands service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-mattermost-slash-command-integration
func (s *ServicesService) SetMattermostSlashCommandsService(pid interface{}, opt *SetMattermostSlashCommandsServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteMattermostSlashCommandsService deletes Mattermost slash commands service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-mattermost-slash-command-integration
func (s *ServicesService) DeleteMattermostSlashCommandsService(pid interface{}, 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)
}
// SetMattermostService sets Mattermost service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-mattermost-notifications-service
func (s *ServicesService) SetMattermostService(pid interface{}, opt *SetMattermostServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteMattermostService deletes Mattermost service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-mattermost-notifications-service
func (s *ServicesService) DeleteMattermostService(pid interface{}, 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)
}
// MicrosoftTeamsService represents Microsoft Teams service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#microsoft-teams
type MicrosoftTeamsService struct {
Service
Properties *MicrosoftTeamsServiceProperties `json:"properties"`
}
// MicrosoftTeamsServiceProperties represents Microsoft Teams specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#microsoft-teams
type MicrosoftTeamsServiceProperties struct {
WebHook string `json:"webhook"`
NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
IssuesEvents BoolValue `json:"issues_events"`
ConfidentialIssuesEvents BoolValue `json:"confidential_issues_events"`
MergeRequestsEvents BoolValue `json:"merge_requests_events"`
TagPushEvents BoolValue `json:"tag_push_events"`
NoteEvents BoolValue `json:"note_events"`
ConfidentialNoteEvents BoolValue `json:"confidential_note_events"`
PipelineEvents BoolValue `json:"pipeline_events"`
WikiPageEvents BoolValue `json:"wiki_page_events"`
}
// GetMicrosoftTeamsService gets MicrosoftTeams service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-microsoft-teams-service-settings
func (s *ServicesService) GetMicrosoftTeamsService(pid interface{}, 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
}
// SetMicrosoftTeamsServiceOptions represents the available SetMicrosoftTeamsService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#create-edit-microsoft-teams-service
type SetMicrosoftTeamsServiceOptions struct {
WebHook *string `url:"webhook,omitempty" json:"webhook,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"`
}
// SetMicrosoftTeamsService sets Microsoft Teams service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#create-edit-microsoft-teams-service
func (s *ServicesService) SetMicrosoftTeamsService(pid interface{}, opt *SetMicrosoftTeamsServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteMicrosoftTeamsService deletes Microsoft Teams service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-microsoft-teams-service
func (s *ServicesService) DeleteMicrosoftTeamsService(pid interface{}, 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)
}
// PipelinesEmailService represents Pipelines Email service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#pipeline-emails
type PipelinesEmailService struct {
Service
Properties *PipelinesEmailProperties `json:"properties"`
}
// PipelinesEmailProperties represents PipelinesEmail specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#pipeline-emails
type PipelinesEmailProperties struct {
Recipients string `json:"recipients"`
NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines"`
NotifyOnlyDefaultBranch BoolValue `json:"notify_only_default_branch"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
}
// GetPipelinesEmailService gets Pipelines Email service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-pipeline-emails-service-settings
func (s *ServicesService) GetPipelinesEmailService(pid interface{}, 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
}
// SetPipelinesEmailServiceOptions represents the available
// SetPipelinesEmailService() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#pipeline-emails
type SetPipelinesEmailServiceOptions struct {
Recipients *string `url:"recipients,omitempty" json:"recipients,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"`
AddPusher *bool `url:"add_pusher,omitempty" json:"add_pusher,omitempty"`
BranchesToBeNotified *string `url:"branches_to_be_notified,omitempty" json:"branches_to_be_notified,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
}
// SetPipelinesEmailService sets Pipelines Email service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#pipeline-emails
func (s *ServicesService) SetPipelinesEmailService(pid interface{}, opt *SetPipelinesEmailServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeletePipelinesEmailService deletes Pipelines Email service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-pipeline-emails-service
func (s *ServicesService) DeletePipelinesEmailService(pid interface{}, 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)
}
// PrometheusService represents Prometheus service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#prometheus
type PrometheusService struct {
Service
Properties *PrometheusServiceProperties `json:"properties"`
}
// PrometheusServiceProperties represents Prometheus specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#prometheus
type PrometheusServiceProperties struct {
APIURL string `json:"api_url"`
GoogleIAPAudienceClientID string `json:"google_iap_audience_client_id"`
GoogleIAPServiceAccountJSON string `json:"google_iap_service_account_json"`
}
// GetPrometheusService gets Prometheus service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-prometheus-service-settings
func (s *ServicesService) GetPrometheusService(pid interface{}, options ...RequestOptionFunc) (*PrometheusService, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/services/prometheus", PathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
svc := new(PrometheusService)
resp, err := s.client.Do(req, svc)
if err != nil {
return nil, resp, err
}
return svc, resp, nil
}
// SetPrometheusServiceOptions represents the available SetPrometheusService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-prometheus-service
type SetPrometheusServiceOptions struct {
APIURL *string `url:"api_url,omitempty" json:"api_url,omitempty"`
GoogleIAPAudienceClientID *string `url:"google_iap_audience_client_id,omitempty" json:"google_iap_audience_client_id,omitempty"`
GoogleIAPServiceAccountJSON *string `url:"google_iap_service_account_json,omitempty" json:"google_iap_service_account_json,omitempty"`
}
// SetPrometheusService sets Prometheus service for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-prometheus-service
func (s *ServicesService) SetPrometheusService(pid interface{}, opt *SetPrometheusServiceOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/prometheus", PathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeletePrometheusService deletes Prometheus service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-prometheus-service
func (s *ServicesService) DeletePrometheusService(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/prometheus", PathEscape(project))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// SlackService represents Slack service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#slack
type SlackService struct {
Service
Properties *SlackServiceProperties `json:"properties"`
}
// SlackServiceProperties represents Slack specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#slack
type SlackServiceProperties struct {
WebHook string `json:"webhook"`
Username string `json:"username"`
Channel string `json:"channel"`
NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines"`
NotifyOnlyDefaultBranch BoolValue `json:"notify_only_default_branch"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
AlertChannel string `json:"alert_channel"`
ConfidentialIssueChannel string `json:"confidential_issue_channel"`
ConfidentialNoteChannel string `json:"confidential_note_channel"`
DeploymentChannel string `json:"deployment_channel"`
IssueChannel string `json:"issue_channel"`
MergeRequestChannel string `json:"merge_request_channel"`
NoteChannel string `json:"note_channel"`
TagPushChannel string `json:"tag_push_channel"`
PipelineChannel string `json:"pipeline_channel"`
PushChannel string `json:"push_channel"`
VulnerabilityChannel string `json:"vulnerability_channel"`
WikiPageChannel string `json:"wiki_page_channel"`
}
// GetSlackService gets Slack service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-slack-service-settings
func (s *ServicesService) GetSlackService(pid interface{}, 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
}
// SetSlackServiceOptions represents the available SetSlackService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-slack-service
type SetSlackServiceOptions 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"`
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"`
AlertChannel *string `url:"alert_channel,omitempty" json:"alert_channel,omitempty"`
AlertEvents *bool `url:"alert_events,omitempty" json:"alert_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"`
ConfidentialNoteChannel *string `url:"confidential_note_channel,omitempty" json:"confidential_note_channel,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
DeploymentChannel *string `url:"deployment_channel,omitempty" json:"deployment_channel,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
IssueChannel *string `url:"issue_channel,omitempty" json:"issue_channel,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"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"`
PipelineChannel *string `url:"pipeline_channel,omitempty" json:"pipeline_channel,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
PushChannel *string `url:"push_channel,omitempty" json:"push_channel,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_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"`
WikiPageChannel *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
}
// SetSlackService sets Slack service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#edit-slack-service
func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteSlackService deletes Slack service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-slack-service
func (s *ServicesService) DeleteSlackService(pid interface{}, 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)
}
// SlackSlashCommandsService represents Slack slash commands settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#slack-slash-commands
type SlackSlashCommandsService struct {
Service
Properties *SlackSlashCommandsProperties `json:"properties"`
}
// SlackSlashCommandsProperties represents Slack slash commands specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#slack-slash-commands
type SlackSlashCommandsProperties struct {
Token string `json:"token"`
}
// GetSlackSlashCommandsService gets Slack slash commands service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-slack-slash-command-integration-settings
func (s *ServicesService) GetSlackSlashCommandsService(pid interface{}, 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
}
// SetSlackSlashCommandsServiceOptions represents the available SetSlackSlashCommandsService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-slack-slash-command-service
type SetSlackSlashCommandsServiceOptions struct {
Token *string `url:"token,omitempty" json:"token,omitempty"`
}
// SetSlackSlashCommandsService sets Slack slash commands service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/13.12/ee/api/integrations.html#createedit-slack-slash-command-service
func (s *ServicesService) SetSlackSlashCommandsService(pid interface{}, opt *SetSlackSlashCommandsServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteSlackSlashCommandsService deletes Slack slash commands service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/13.12/ee/api/integrations.html#delete-slack-slash-command-service
func (s *ServicesService) DeleteSlackSlashCommandsService(pid interface{}, 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)
}
// TelegramService represents Telegram service settings.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#telegram
type TelegramService struct {
Service
Properties *TelegramServiceProperties `json:"properties"`
}
// TelegramServiceProperties represents Telegram specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-telegram
type TelegramServiceProperties struct {
Room string `json:"room"`
NotifyOnlyBrokenPipelines bool `json:"notify_only_broken_pipelines"`
BranchesToBeNotified string `json:"branches_to_be_notified"`
}
// GetTelegramService gets MicrosoftTeams service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-telegram-settings
func (s *ServicesService) GetTelegramService(pid interface{}, 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
}
// SetTelegramServiceOptions represents the available SetTelegramService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-telegram
type SetTelegramServiceOptions struct {
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"`
}
// SetTelegramService sets Telegram service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#set-up-telegram
func (s *ServicesService) SetTelegramService(pid interface{}, opt *SetTelegramServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteTelegramService deletes Telegram service for project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#disable-telegram
func (s *ServicesService) DeleteTelegramService(pid interface{}, 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)
}
// YouTrackService represents YouTrack service settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#youtrack
type YouTrackService struct {
Service
Properties *YouTrackServiceProperties `json:"properties"`
}
// YouTrackServiceProperties represents YouTrack specific properties.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#youtrack
type YouTrackServiceProperties struct {
IssuesURL string `json:"issues_url"`
ProjectURL string `json:"project_url"`
Description string `json:"description"`
PushEvents bool `json:"push_events"`
}
// GetYouTrackService gets YouTrack service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#get-youtrack-service-settings
func (s *ServicesService) GetYouTrackService(pid interface{}, 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
}
// SetYouTrackServiceOptions represents the available SetYouTrackService()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-youtrack-service
type SetYouTrackServiceOptions struct {
IssuesURL *string `url:"issues_url,omitempty" json:"issues_url,omitempty"`
ProjectURL *string `url:"project_url,omitempty" json:"project_url,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
}
// SetYouTrackService sets YouTrack service for a project
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#createedit-youtrack-service
func (s *ServicesService) SetYouTrackService(pid interface{}, opt *SetYouTrackServiceOptions, 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.MethodPut, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteYouTrackService deletes YouTrack service settings for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/integrations.html#delete-youtrack-service
func (s *ServicesService) DeleteYouTrackService(pid interface{}, 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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"net/http"
"time"
)
// SettingsService handles communication with the application SettingsService
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/settings.html
type SettingsService struct {
client *Client
}
// Settings represents the GitLab application settings.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/settings.html
//
// The available parameters have been modeled directly after the code, as the
// documentation seems to be inaccurate.
//
// https://gitlab.com/gitlab-org/gitlab/-/blob/v14.9.3-ee/lib/api/settings.rb
// https://gitlab.com/gitlab-org/gitlab/-/blob/v14.9.3-ee/lib/api/entities/application_setting.rb#L5
// https://gitlab.com/gitlab-org/gitlab/-/blob/v14.9.3-ee/app/helpers/application_settings_helper.rb#L192
// 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"`
AbuseNotificationEmail string `json:"abuse_notification_email"`
AdminMode bool `json:"admin_mode"`
AfterSignOutPath string `json:"after_sign_out_path"`
AfterSignUpText string `json:"after_sign_up_text"`
AkismetAPIKey string `json:"akismet_api_key"`
AkismetEnabled bool `json:"akismet_enabled"`
AllowAccountDeletion bool `json:"allow_account_deletion"`
AllowGroupOwnersToManageLDAP bool `json:"allow_group_owners_to_manage_ldap"`
AllowLocalRequestsFromSystemHooks bool `json:"allow_local_requests_from_system_hooks"`
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"`
ArchiveBuildsInHumanReadable string `json:"archive_builds_in_human_readable"`
ASCIIDocMaxIncludes int `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"`
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"`
BulkImportEnabled bool `json:"bulk_import_enabled"`
BulkImportMaxDownloadFileSize int `json:"bulk_import_max_download_file_size"`
CanCreateGroup bool `json:"can_create_group"`
CheckNamespacePlan bool `json:"check_namespace_plan"`
CIMaxIncludes int `json:"ci_max_includes"`
CIMaxTotalYAMLSizeBytes int `json:"ci_max_total_yaml_size_bytes"`
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"`
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"`
ContainerRegistryExpirationPoliciesCaching bool `json:"container_registry_expiration_policies_caching"`
ContainerRegistryExpirationPoliciesWorkerCapacity int `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"`
ContainerRegistryImportTargetPlan string `json:"container_registry_import_target_plan"`
ContainerRegistryTokenExpireDelay int `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"`
DeactivateDormantUsers bool `json:"deactivate_dormant_users"`
DeactivateDormantUsersPeriod int `json:"deactivate_dormant_users_period"`
DecompressArchiveFileTimeout int `json:"decompress_archive_file_timeout"`
DefaultArtifactsExpireIn string `json:"default_artifacts_expire_in"`
DefaultBranchName string `json:"default_branch_name"`
DefaultBranchProtection int `json:"default_branch_protection"`
DefaultCiConfigPath string `json:"default_ci_config_path"`
DefaultGroupVisibility VisibilityValue `json:"default_group_visibility"`
DefaultProjectCreation int `json:"default_project_creation"`
DefaultProjectDeletionProtection bool `json:"default_project_deletion_protection"`
DefaultProjectVisibility VisibilityValue `json:"default_project_visibility"`
DefaultProjectsLimit int `json:"default_projects_limit"`
DefaultSnippetVisibility VisibilityValue `json:"default_snippet_visibility"`
DelayedGroupDeletion bool `json:"delayed_group_deletion"`
DelayedProjectDeletion bool `json:"delayed_project_deletion"`
DeleteInactiveProjects bool `json:"delete_inactive_projects"`
DeletionAdjournedPeriod int `json:"deletion_adjourned_period"`
DiffMaxFiles int `json:"diff_max_files"`
DiffMaxLines int `json:"diff_max_lines"`
DiffMaxPatchBytes int `json:"diff_max_patch_bytes"`
DisableFeedToken bool `json:"disable_feed_token"`
DisableOverridingApproversPerMergeRequest bool `json:"disable_overriding_approvers_per_merge_request"`
DisabledOauthSignInSources []string `json:"disabled_oauth_sign_in_sources"`
DomainAllowlist []string `json:"domain_allowlist"`
DomainDenylist []string `json:"domain_denylist"`
DomainDenylistEnabled bool `json:"domain_denylist_enabled"`
ECDSAKeyRestriction int `json:"ecdsa_key_restriction"`
ECDSASKKeyRestriction int `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"`
ElasticsearchAWS bool `json:"elasticsearch_aws"`
ElasticsearchAWSAccessKey string `json:"elasticsearch_aws_access_key"`
ElasticsearchAWSRegion string `json:"elasticsearch_aws_region"`
ElasticsearchAWSSecretAccessKey string `json:"elasticsearch_aws_secret_access_key"`
ElasticsearchAnalyzersKuromojiEnabled bool `json:"elasticsearch_analyzers_kuromoji_enabled"`
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"`
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"`
ElasticsearchNamespaceIDs []int `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"`
ElasticsearchSearch bool `json:"elasticsearch_search"`
ElasticsearchShards int `json:"elasticsearch_shards"`
ElasticsearchURL []string `json:"elasticsearch_url"`
ElasticsearchUsername string `json:"elasticsearch_username"`
EmailAdditionalText string `json:"email_additional_text"`
EmailAuthorInBody bool `json:"email_author_in_body"`
EmailRestrictions string `json:"email_restrictions"`
EmailRestrictionsEnabled bool `json:"email_restrictions_enabled"`
EnabledGitAccessProtocol string `json:"enabled_git_access_protocol"`
EnforceNamespaceStorageLimit bool `json:"enforce_namespace_storage_limit"`
EnforcePATExpiration bool `json:"enforce_pat_expiration"`
EnforceSSHKeyExpiration bool `json:"enforce_ssh_key_expiration"`
EnforceTerms bool `json:"enforce_terms"`
ExternalAuthClientCert string `json:"external_auth_client_cert"`
ExternalAuthClientKey string `json:"external_auth_client_key"`
ExternalAuthClientKeyPass string `json:"external_auth_client_key_pass"`
ExternalAuthorizationServiceDefaultLabel string `json:"external_authorization_service_default_label"`
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"`
ExternalPipelineValidationServiceToken string `json:"external_pipeline_validation_service_token"`
ExternalPipelineValidationServiceURL string `json:"external_pipeline_validation_service_url"`
FileTemplateProjectID int `json:"file_template_project_id"`
FirstDayOfWeek int `json:"first_day_of_week"`
FlocEnabled bool `json:"floc_enabled"`
GeoNodeAllowedIPs string `json:"geo_node_allowed_ips"`
GeoStatusTimeout int `json:"geo_status_timeout"`
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"`
GitpodEnabled bool `json:"gitpod_enabled"`
GitpodURL string `json:"gitpod_url"`
GitRateLimitUsersAllowlist []string `json:"git_rate_limit_users_allowlist"`
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"`
GroupOwnersCanManageDefaultBranchProtection bool `json:"group_owners_can_manage_default_branch_protection"`
GroupRunnerTokenExpirationInterval int `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"`
HelpPageHideCommercialContent bool `json:"help_page_hide_commercial_content"`
HelpPageSupportURL string `json:"help_page_support_url"`
HelpPageText string `json:"help_page_text"`
HelpText string `json:"help_text"`
HideThirdPartyOffers bool `json:"hide_third_party_offers"`
HomePageURL string `json:"home_page_url"`
HousekeepingBitmapsEnabled bool `json:"housekeeping_bitmaps_enabled"`
HousekeepingEnabled bool `json:"housekeeping_enabled"`
HousekeepingFullRepackPeriod int `json:"housekeeping_full_repack_period"`
HousekeepingGcPeriod int `json:"housekeeping_gc_period"`
HousekeepingIncrementalRepackPeriod int `json:"housekeeping_incremental_repack_period"`
HousekeepingOptimizeRepositoryPeriod int `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"`
InProductMarketingEmailsEnabled bool `json:"in_product_marketing_emails_enabled"`
InvisibleCaptchaEnabled bool `json:"invisible_captcha_enabled"`
IssuesCreateLimit int `json:"issues_create_limit"`
KeepLatestArtifact bool `json:"keep_latest_artifact"`
KrokiEnabled bool `json:"kroki_enabled"`
KrokiFormats map[string]bool `json:"kroki_formats"`
KrokiURL string `json:"kroki_url"`
LocalMarkdownVersion int `json:"local_markdown_version"`
LockMembershipsToLDAP bool `json:"lock_memberships_to_ldap"`
LoginRecaptchaProtectionEnabled bool `json:"login_recaptcha_protection_enabled"`
MailgunEventsEnabled bool `json:"mailgun_events_enabled"`
MailgunSigningKey string `json:"mailgun_signing_key"`
MaintenanceMode bool `json:"maintenance_mode"`
MaintenanceModeMessage string `json:"maintenance_mode_message"`
MaxArtifactsSize int `json:"max_artifacts_size"`
MaxAttachmentSize int `json:"max_attachment_size"`
MaxExportSize int `json:"max_export_size"`
MaxImportSize int `json:"max_import_size"`
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"`
MirrorAvailable bool `json:"mirror_available"`
MirrorCapacityThreshold int `json:"mirror_capacity_threshold"`
MirrorMaxCapacity int `json:"mirror_max_capacity"`
MirrorMaxDelay int `json:"mirror_max_delay"`
NPMPackageRequestsForwarding bool `json:"npm_package_requests_forwarding"`
NotesCreateLimit int `json:"notes_create_limit"`
NotifyOnUnknownSignIn bool `json:"notify_on_unknown_sign_in"`
OutboundLocalRequestsAllowlistRaw string `json:"outbound_local_requests_allowlist_raw"`
OutboundLocalRequestsWhitelist []string `json:"outbound_local_requests_whitelist"`
PackageRegistryCleanupPoliciesWorkerCapacity int `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"`
PasswordNumberRequired bool `json:"password_number_required"`
PasswordSymbolRequired bool `json:"password_symbol_required"`
PasswordUppercaseRequired bool `json:"password_uppercase_required"`
PasswordLowercaseRequired bool `json:"password_lowercase_required"`
PerformanceBarAllowedGroupID int `json:"performance_bar_allowed_group_id"`
PerformanceBarAllowedGroupPath string `json:"performance_bar_allowed_group_path"`
PerformanceBarEnabled bool `json:"performance_bar_enabled"`
PersonalAccessTokenPrefix string `json:"personal_access_token_prefix"`
PipelineLimitPerProjectUserSha int `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"`
ProjectExportEnabled bool `json:"project_export_enabled"`
ProjectExportLimit int `json:"project_export_limit"`
ProjectImportLimit int `json:"project_import_limit"`
ProjectRunnerTokenExpirationInterval int `json:"project_runner_token_expiration_interval"`
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"`
PyPIPackageRequestsForwarding bool `json:"pypi_package_requests_forwarding"`
RSAKeyRestriction int `json:"rsa_key_restriction"`
RateLimitingResponseText string `json:"rate_limiting_response_text"`
RawBlobRequestLimit int `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"`
RepositoryChecksEnabled bool `json:"repository_checks_enabled"`
RepositorySizeLimit int `json:"repository_size_limit"`
RepositoryStorages []string `json:"repository_storages"`
RepositoryStoragesWeighted map[string]int `json:"repository_storages_weighted"`
RequireAdminApprovalAfterUserSignup bool `json:"require_admin_approval_after_user_signup"`
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"`
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"`
SendUserConfirmationEmail bool `json:"send_user_confirmation_email"`
SentryClientsideDSN string `json:"sentry_clientside_dsn"`
SentryDSN string `json:"sentry_dsn"`
SentryEnabled bool `json:"sentry_enabled"`
SentryEnvironment string `json:"sentry_environment"`
SessionExpireDelay int `json:"session_expire_delay"`
SharedRunnersEnabled bool `json:"shared_runners_enabled"`
SharedRunnersMinutes int `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"`
SidekiqJobLimiterMode string `json:"sidekiq_job_limiter_mode"`
SignInText string `json:"sign_in_text"`
SignupEnabled bool `json:"signup_enabled"`
SlackAppEnabled bool `json:"slack_app_enabled"`
SlackAppID string `json:"slack_app_id"`
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"`
SnowplowAppID string `json:"snowplow_app_id"`
SnowplowCollectorHostname string `json:"snowplow_collector_hostname"`
SnowplowCookieDomain string `json:"snowplow_cookie_domain"`
SnowplowEnabled bool `json:"snowplow_enabled"`
SourcegraphEnabled bool `json:"sourcegraph_enabled"`
SourcegraphPublicOnly bool `json:"sourcegraph_public_only"`
SourcegraphURL string `json:"sourcegraph_url"`
SpamCheckAPIKey string `json:"spam_check_api_key"`
SpamCheckEndpointEnabled bool `json:"spam_check_endpoint_enabled"`
SpamCheckEndpointURL string `json:"spam_check_endpoint_url"`
SuggestPipelineEnabled bool `json:"suggest_pipeline_enabled"`
TerminalMaxSessionTime int `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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
TimeTrackingLimitToHours bool `json:"time_tracking_limit_to_hours"`
TwoFactorGracePeriod int `json:"two_factor_grace_period"`
UniqueIPsLimitEnabled bool `json:"unique_ips_limit_enabled"`
UniqueIPsLimitPerUser int `json:"unique_ips_limit_per_user"`
UniqueIPsLimitTimeWindow int `json:"unique_ips_limit_time_window"`
UpdatedAt *time.Time `json:"updated_at"`
UpdatingNameDisabledForUsers bool `json:"updating_name_disabled_for_users"`
UsagePingEnabled bool `json:"usage_ping_enabled"`
UsagePingFeaturesEnabled bool `json:"usage_ping_features_enabled"`
UserDeactivationEmailsEnabled bool `json:"user_deactivation_emails_enabled"`
UserDefaultExternal bool `json:"user_default_external"`
UserDefaultInternalRegex string `json:"user_default_internal_regex"`
UserOauthApplications bool `json:"user_oauth_applications"`
UserShowAddSSHKeyMessage bool `json:"user_show_add_ssh_key_message"`
UsersGetByIDLimit int `json:"users_get_by_id_limit"`
UsersGetByIDLimitAllowlistRaw string `json:"users_get_by_id_limit_allowlist_raw"`
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"`
// Deprecated: Use AbuseNotificationEmail instead.
AdminNotificationEmail string `json:"admin_notification_email"`
// Deprecated: Use AllowLocalRequestsFromWebHooksAndServices instead.
AllowLocalRequestsFromHooksAndServices bool `json:"allow_local_requests_from_hooks_and_services"`
// Deprecated: Use AssetProxyAllowlist instead.
AssetProxyWhitelist []string `json:"asset_proxy_whitelist"`
// 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"`
// Deprecated: Use ThrottleUnauthenticatedWebRequestsPerPeriod or ThrottleUnauthenticatedAPIRequestsPerPeriod instead. (Deprecated in GitLab 14.3)
ThrottleUnauthenticatedRequestsPerPeriod int `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"`
}
// Settings requires a custom unmarshaller in order to properly unmarshal
// `container_registry_import_created_before` which is either a time.Time or
// an empty string if no value is set.
func (s *Settings) UnmarshalJSON(data []byte) error {
type Alias Settings
raw := make(map[string]interface{})
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
// If empty string, remove the value to leave it nil in the response.
if v, ok := raw["container_registry_import_created_before"]; ok && v == "" {
delete(raw, "container_registry_import_created_before")
data, err = json.Marshal(raw)
if err != nil {
return err
}
}
return json.Unmarshal(data, (*Alias)(s))
}
func (s Settings) String() string {
return Stringify(s)
}
// GetSettings gets the current application settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/settings.html#get-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
}
// UpdateSettingsOptions represents the available UpdateSettings() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/settings.html#change-application-settings
type UpdateSettingsOptions struct {
AbuseNotificationEmail *string `url:"abuse_notification_email,omitempty" json:"abuse_notification_email,omitempty"`
AdminMode *bool `url:"admin_mode,omitempty" json:"admin_mode,omitempty"`
AdminNotificationEmail *string `url:"admin_notification_email,omitempty" json:"admin_notification_email,omitempty"`
AfterSignOutPath *string `url:"after_sign_out_path,omitempty" json:"after_sign_out_path,omitempty"`
AfterSignUpText *string `url:"after_sign_up_text,omitempty" json:"after_sign_up_text,omitempty"`
AkismetAPIKey *string `url:"akismet_api_key,omitempty" json:"akismet_api_key,omitempty"`
AkismetEnabled *bool `url:"akismet_enabled,omitempty" json:"akismet_enabled,omitempty"`
AllowAccountDeletion *bool `url:"allow_account_deletion,omitempty" json:"allow_account_deletion,omitempty"`
AllowGroupOwnersToManageLDAP *bool `url:"allow_group_owners_to_manage_ldap,omitempty" json:"allow_group_owners_to_manage_ldap,omitempty"`
AllowLocalRequestsFromHooksAndServices *bool `url:"allow_local_requests_from_hooks_and_services,omitempty" json:"allow_local_requests_from_hooks_and_services,omitempty"`
AllowLocalRequestsFromSystemHooks *bool `url:"allow_local_requests_from_system_hooks,omitempty" json:"allow_local_requests_from_system_hooks,omitempty"`
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"`
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"`
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"`
AssetProxyWhitelist *[]string `url:"asset_proxy_whitelist,omitempty" json:"asset_proxy_whitelist,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"`
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"`
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"`
CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,omitempty"`
CheckNamespacePlan *bool `url:"check_namespace_plan,omitempty" json:"check_namespace_plan,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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
DefaultBranchProtection *int `url:"default_branch_protection,omitempty" json:"default_branch_protection,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"`
DefaultProjectCreation *int `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"`
DefaultSnippetVisibility *VisibilityValue `url:"default_snippet_visibility,omitempty" json:"default_snippet_visibility,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"`
DeletionAdjournedPeriod *int `url:"deletion_adjourned_period,omitempty" json:"deletion_adjourned_period,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"`
DisableFeedToken *bool `url:"disable_feed_token,omitempty" json:"disable_feed_token,omitempty"`
DisableOverridingApproversPerMergeRequest *bool `url:"disable_overriding_approvers_per_merge_request,omitempty" json:"disable_overriding_approvers_per_merge_request,omitempty"`
DisabledOauthSignInSources *[]string `url:"disabled_oauth_sign_in_sources,omitempty" json:"disabled_oauth_sign_in_sources,omitempty"`
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"`
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"`
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"`
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"`
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"`
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"`
ElasticsearchNamespaceIDs *[]int `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"`
ElasticsearchSearch *bool `url:"elasticsearch_search,omitempty" json:"elasticsearch_search,omitempty"`
ElasticsearchShards *int `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"`
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"`
EmailRestrictions *string `url:"email_restrictions,omitempty" json:"email_restrictions,omitempty"`
EmailRestrictionsEnabled *bool `url:"email_restrictions_enabled,omitempty" json:"email_restrictions_enabled,omitempty"`
EnabledGitAccessProtocol *string `url:"enabled_git_access_protocol,omitempty" json:"enabled_git_access_protocol,omitempty"`
EnforceNamespaceStorageLimit *bool `url:"enforce_namespace_storage_limit,omitempty" json:"enforce_namespace_storage_limit,omitempty"`
EnforcePATExpiration *bool `url:"enforce_pat_expiration,omitempty" json:"enforce_pat_expiration,omitempty"`
EnforceSSHKeyExpiration *bool `url:"enforce_ssh_key_expiration,omitempty" json:"enforce_ssh_key_expiration,omitempty"`
EnforceTerms *bool `url:"enforce_terms,omitempty" json:"enforce_terms,omitempty"`
ExternalAuthClientCert *string `url:"external_auth_client_cert,omitempty" json:"external_auth_client_cert,omitempty"`
ExternalAuthClientKey *string `url:"external_auth_client_key,omitempty" json:"external_auth_client_key,omitempty"`
ExternalAuthClientKeyPass *string `url:"external_auth_client_key_pass,omitempty" json:"external_auth_client_key_pass,omitempty"`
ExternalAuthorizationServiceDefaultLabel *string `url:"external_authorization_service_default_label,omitempty" json:"external_authorization_service_default_label,omitempty"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
HelpPageHideCommercialContent *bool `url:"help_page_hide_commercial_content,omitempty" json:"help_page_hide_commercial_content,omitempty"`
HelpPageSupportURL *string `url:"help_page_support_url,omitempty" json:"help_page_support_url,omitempty"`
HelpPageText *string `url:"help_page_text,omitempty" json:"help_page_text,omitempty"`
HelpText *string `url:"help_text,omitempty" json:"help_text,omitempty"`
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"`
HousekeepingBitmapsEnabled *bool `url:"housekeeping_bitmaps_enabled,omitempty" json:"housekeeping_bitmaps_enabled,omitempty"`
HousekeepingEnabled *bool `url:"housekeeping_enabled,omitempty" json:"housekeeping_enabled,omitempty"`
HousekeepingFullRepackPeriod *int `url:"housekeeping_full_repack_period,omitempty" json:"housekeeping_full_repack_period,omitempty"`
HousekeepingGcPeriod *int `url:"housekeeping_gc_period,omitempty" json:"housekeeping_gc_period,omitempty"`
HousekeepingIncrementalRepackPeriod *int `url:"housekeeping_incremental_repack_period,omitempty" json:"housekeeping_incremental_repack_period,omitempty"`
HousekeepingOptimizeRepositoryPeriod *int `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"`
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"`
KeepLatestArtifact *bool `url:"keep_latest_artifact,omitempty" json:"keep_latest_artifact,omitempty"`
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"`
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"`
MailgunEventsEnabled *bool `url:"mailgun_events_enabled,omitempty" json:"mailgun_events_enabled,omitempty"`
MailgunSigningKey *string `url:"mailgun_signing_key,omitempty" json:"mailgun_signing_key,omitempty"`
MaintenanceMode *bool `url:"maintenance_mode,omitempty" json:"maintenance_mode,omitempty"`
MaintenanceModeMessage *string `url:"maintenance_mode_message,omitempty" json:"maintenance_mode_message,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"`
MaxExportSize *int `url:"max_export_size,omitempty" json:"max_export_size,omitempty"`
MaxImportSize *int `url:"max_import_size,omitempty" json:"max_import_size,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"`
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"`
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"`
NotifyOnUnknownSignIn *bool `url:"notify_on_unknown_sign_in,omitempty" json:"notify_on_unknown_sign_in,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"`
PackageRegistryCleanupPoliciesWorkerCapacity *int `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"`
PasswordNumberRequired *bool `url:"password_number_required,omitempty" json:"password_number_required,omitempty"`
PasswordSymbolRequired *bool `url:"password_symbol_required,omitempty" json:"password_symbol_required,omitempty"`
PasswordUppercaseRequired *bool `url:"password_uppercase_required,omitempty" json:"password_uppercase_required,omitempty"`
PasswordLowercaseRequired *bool `url:"password_lowercase_required,omitempty" json:"password_lowercase_required,omitempty"`
PerformanceBarAllowedGroupID *int `url:"performance_bar_allowed_group_id,omitempty" json:"performance_bar_allowed_group_id,omitempty"`
PerformanceBarAllowedGroupPath *string `url:"performance_bar_allowed_group_path,omitempty" json:"performance_bar_allowed_group_path,omitempty"`
PerformanceBarEnabled *bool `url:"performance_bar_enabled,omitempty" json:"performance_bar_enabled,omitempty"`
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"`
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"`
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"`
ProjectRunnerTokenExpirationInterval *int `url:"project_runner_token_expiration_interval,omitempty" json:"project_runner_token_expiration_interval,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"`
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"`
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"`
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"`
RepositoryChecksEnabled *bool `url:"repository_checks_enabled,omitempty" json:"repository_checks_enabled,omitempty"`
RepositorySizeLimit *int `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"`
RequireAdminApprovalAfterUserSignup *bool `url:"require_admin_approval_after_user_signup,omitempty" json:"require_admin_approval_after_user_signup,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"`
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"`
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"`
SentryEnvironment *string `url:"sentry_environment,omitempty" json:"sentry_environment,omitempty"`
SessionExpireDelay *int `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"`
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"`
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"`
SlackAppEnabled *bool `url:"slack_app_enabled,omitempty" json:"slack_app_enabled,omitempty"`
SlackAppID *string `url:"slack_app_id,omitempty" json:"slack_app_id,omitempty"`
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"`
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"`
SnowplowEnabled *bool `url:"snowplow_enabled,omitempty" json:"snowplow_enabled,omitempty"`
SourcegraphEnabled *bool `url:"sourcegraph_enabled,omitempty" json:"sourcegraph_enabled,omitempty"`
SourcegraphPublicOnly *bool `url:"sourcegraph_public_only,omitempty" json:"sourcegraph_public_only,omitempty"`
SourcegraphURL *string `url:"sourcegraph_url,omitempty" json:"sourcegraph_url,omitempty"`
SpamCheckAPIKey *string `url:"spam_check_api_key,omitempty" json:"spam_check_api_key,omitempty"`
SpamCheckEndpointEnabled *bool `url:"spam_check_endpoint_enabled,omitempty" json:"spam_check_endpoint_enabled,omitempty"`
SpamCheckEndpointURL *string `url:"spam_check_endpoint_url,omitempty" json:"spam_check_endpoint_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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
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"`
ThrottleUnauthenticatedEnabled *bool `url:"throttle_unauthenticated_enabled,omitempty" json:"throttle_unauthenticated_enabled,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"`
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"`
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"`
ThrottleUnauthenticatedPeriodInSeconds *int `url:"throttle_unauthenticated_period_in_seconds,omitempty" json:"throttle_unauthenticated_period_in_seconds,omitempty"`
ThrottleUnauthenticatedRequestsPerPeriod *int `url:"throttle_unauthenticated_requests_per_period,omitempty" json:"throttle_unauthenticated_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"`
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"`
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"`
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"`
UsagePingFeaturesEnabled *bool `url:"usage_ping_features_enabled,omitempty" json:"usage_ping_features_enabled,omitempty"`
UserDeactivationEmailsEnabled *bool `url:"user_deactivation_emails_enabled,omitempty" json:"user_deactivation_emails_enabled,omitempty"`
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"`
UserEmailLookupLimit *int `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"`
UsersGetByIDLimitAllowlistRaw *string `url:"users_get_by_id_limit_allowlist_raw,omitempty" json:"users_get_by_id_limit_allowlist_raw,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"`
}
// UpdateSettings updates the application settings.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/settings.html#change-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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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"
"time"
)
// SidekiqService handles communication with the sidekiq service
//
// GitLab API docs: https://docs.gitlab.com/ee/api/sidekiq_metrics.html
type SidekiqService struct {
client *Client
}
// QueueMetrics represents the GitLab sidekiq queue metrics.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#get-the-current-queue-metrics
type QueueMetrics struct {
Queues map[string]struct {
Backlog int `json:"backlog"`
Latency int `json:"latency"`
} `json:"queues"`
}
// GetQueueMetrics lists information about all the registered queues,
// their backlog and their latency.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#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
}
// ProcessMetrics represents the GitLab sidekiq process metrics.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#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"`
}
// GetProcessMetrics lists information about all the Sidekiq workers registered
// to process your queues.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#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
}
// JobStats represents the GitLab sidekiq job stats.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#get-the-current-job-statistics
type JobStats struct {
Jobs struct {
Processed int `json:"processed"`
Failed int `json:"failed"`
Enqueued int `json:"enqueued"`
} `json:"jobs"`
}
// GetJobStats list information about the jobs that Sidekiq has performed.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#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
}
// CompoundMetrics represents the GitLab sidekiq compounded stats.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/sidekiq_metrics.html#get-a-compound-response-of-all-the-previously-mentioned-metrics
type CompoundMetrics struct {
QueueMetrics
ProcessMetrics
JobStats
}
// GetCompoundMetrics lists all the currently available information about Sidekiq.
// Get a compound response of all the previously mentioned metrics
//
// GitLab API docs: https://docs.gitlab.com/ee/api/sidekiq_metrics.html#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
}
//
// Copyright 2023, Nick Westbury
//
// 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 (
"fmt"
"net/http"
"time"
)
// SnippetRepositoryStorageMoveService handles communication with the
// snippets related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html
type SnippetRepositoryStorageMoveService struct {
client *Client
}
// SnippetRepositoryStorageMove represents the status of a repository move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html
type SnippetRepositoryStorageMove struct {
ID int `json:"id"`
CreatedAt *time.Time `json:"created_at"`
State string `json:"state"`
SourceStorageName string `json:"source_storage_name"`
DestinationStorageName string `json:"destination_storage_name"`
Snippet *RepositorySnippet `json:"snippet"`
}
type RepositorySnippet struct {
ID int `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"`
WebURL string `json:"web_url"`
RawURL string `json:"raw_url"`
SSHURLToRepo string `json:"ssh_url_to_repo"`
HTTPURLToRepo string `json:"http_url_to_repo"`
}
// RetrieveAllSnippetStorageMovesOptions represents the available
// RetrieveAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#retrieve-all-repository-storage-moves-for-a-snippet
type RetrieveAllSnippetStorageMovesOptions ListOptions
// RetrieveAllStorageMoves retrieves all snippet repository storage moves
// accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#retrieve-all-repository-storage-moves-for-a-snippet
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
}
// RetrieveAllStorageMovesForSnippet retrieves all repository storage moves for
// a single snippet accessible by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#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
}
// GetStorageMove gets a single snippet repository storage move.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#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
}
// GetStorageMoveForSnippet gets a single repository storage move for a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#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
}
// ScheduleStorageMoveForSnippetOptions represents the available
// ScheduleStorageMoveForSnippet() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#schedule-a-repository-storage-move-for-a-snippet
type ScheduleStorageMoveForSnippetOptions struct {
DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"`
}
// ScheduleStorageMoveForSnippet schedule a repository to be moved for a snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#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
}
// ScheduleAllSnippetStorageMovesOptions represents the available
// ScheduleAllStorageMoves() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#schedule-repository-storage-moves-for-all-snippets-on-a-storage-shard
type ScheduleAllSnippetStorageMovesOptions struct {
SourceStorageName *string `url:"source_storage_name,omitempty" json:"source_storage_name,omitempty"`
DestinationStorageName *string `url:"destination_storage_name,omitempty" json:"destination_storage_name,omitempty"`
}
// ScheduleAllStorageMoves schedules all snippet repositories to be moved.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippet_repository_storage_moves.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"net/http"
"time"
)
// SnippetsService handles communication with the snippets
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/snippets.html
type SnippetsService struct {
client *Client
}
// Snippet represents a GitLab snippet.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/snippets.html
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"`
}
func (s Snippet) String() string {
return Stringify(s)
}
// ListSnippetsOptions represents the available ListSnippets() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#list-all-snippets-for-a-user
type ListSnippetsOptions ListOptions
// ListSnippets gets a list of snippets.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#list-all-snippets-for-a-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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
// GetSnippet gets a single snippet
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
// SnippetContent gets a single snippet’s raw contents.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// SnippetFileContent returns the raw file content as plain text.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// CreateSnippetFileOptions represents the create snippet file options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#create-new-snippet
type CreateSnippetFileOptions struct {
FilePath *string `url:"file_path,omitempty" json:"file_path,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
}
// CreateSnippetOptions represents the available CreateSnippet() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#create-new-snippet
type CreateSnippetOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
Files *[]*CreateSnippetFileOptions `url:"files,omitempty" json:"files,omitempty"`
}
// CreateSnippet creates a new snippet. The user must have permission
// to create new snippets.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
// UpdateSnippetFileOptions represents the update snippet file options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#update-snippet
type UpdateSnippetFileOptions struct {
Action *string `url:"action,omitempty" json:"action,omitempty"`
FilePath *string `url:"file_path,omitempty" json:"file_path,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
PreviousPath *string `url:"previous_path,omitempty" json:"previous_path,omitempty"`
}
// UpdateSnippetOptions represents the available UpdateSnippet() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#update-snippet
type UpdateSnippetOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
FileName *string `url:"file_name,omitempty" json:"file_name,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Content *string `url:"content,omitempty" json:"content,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
Files *[]*UpdateSnippetFileOptions `url:"files,omitempty" json:"files,omitempty"`
}
// UpdateSnippet updates an existing snippet. The user must have
// permission to change an existing snippet.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
// DeleteSnippet deletes an existing snippet. This is an idempotent
// function and deleting a non-existent snippet still returns a 200 OK status
// code.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
}
// ExploreSnippetsOptions represents the available ExploreSnippets() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#list-all-public-snippets
type ExploreSnippetsOptions ListOptions
// ExploreSnippets gets the list of public snippets.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
// ListAllSnippetsOptions represents the available ListAllSnippets() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#list-all-snippets
type ListAllSnippetsOptions struct {
ListOptions
CreatedAfter *ISOTime `url:"created_after,omitempty" json:"created_after,omitempty"`
CreatedBefore *ISOTime `url:"created_before,omitempty" json:"created_before,omitempty"`
RepositoryStorage *string `url:"repository_storage,omitempty" json:"repository_storage,omitempty"`
}
// ListAllSnippets gets all snippets the current user has access to.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/snippets.html#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)
if err != nil {
return nil, resp, err
}
return ps, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"fmt"
"reflect"
)
// Stringify attempts to create a reasonable string representation of types in
// the Gitlab library. It does things like resolve pointers to their values
// and omits struct fields with nil values.
func Stringify(message interface{}) string {
var buf bytes.Buffer
v := reflect.ValueOf(message)
stringifyValue(&buf, v)
return buf.String()
}
// stringifyValue was heavily inspired by the goprotobuf library.
func stringifyValue(buf *bytes.Buffer, val reflect.Value) {
if val.Kind() == reflect.Ptr && val.IsNil() {
buf.WriteString("<nil>")
return
}
v := reflect.Indirect(val)
switch v.Kind() {
case reflect.String:
fmt.Fprintf(buf, `"%s"`, v)
case reflect.Slice:
buf.WriteByte('[')
for i := 0; i < v.Len(); i++ {
if i > 0 {
buf.WriteByte(' ')
}
stringifyValue(buf, v.Index(i))
}
buf.WriteByte(']')
return
case reflect.Struct:
if v.Type().Name() != "" {
buf.WriteString(v.Type().String())
}
buf.WriteByte('{')
var sep bool
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
if fv.Kind() == reflect.Ptr && fv.IsNil() {
continue
}
if fv.Kind() == reflect.Slice && fv.IsNil() {
continue
}
if sep {
buf.WriteString(", ")
} else {
sep = true
}
buf.WriteString(v.Type().Field(i).Name)
buf.WriteByte(':')
stringifyValue(buf, fv)
}
buf.WriteByte('}')
default:
if v.CanInterface() {
fmt.Fprint(buf, v.Interface())
}
}
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// SystemHooksService handles communication with the system hooks related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/system_hooks.html
type SystemHooksService struct {
client *Client
}
// Hook represents a GitLap system hook.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/system_hooks.html
type Hook struct {
ID int `json:"id"`
URL string `json:"url"`
CreatedAt *time.Time `json:"created_at"`
PushEvents bool `json:"push_events"`
TagPushEvents bool `json:"tag_push_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
RepositoryUpdateEvents bool `json:"repository_update_events"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
}
func (h Hook) String() string {
return Stringify(h)
}
// ListHooks gets a list of system hooks.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/system_hooks.html#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
}
// GetHook get a single system hook.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/system_hooks.html#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
}
// AddHookOptions represents the available AddHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/system_hooks.html#add-new-system-hook
type AddHookOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
RepositoryUpdateEvents *bool `url:"repository_update_events,omitempty" json:"repository_update_events,omitempty"`
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/ee/api/system_hooks.html#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
}
// HookEvent represents an event trigger by a GitLab system hook.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/system_hooks.html
type HookEvent struct {
EventName string `json:"event_name"`
Name string `json:"name"`
Path string `json:"path"`
ProjectID int `json:"project_id"`
OwnerName string `json:"owner_name"`
OwnerEmail string `json:"owner_email"`
}
func (h HookEvent) String() string {
return Stringify(h)
}
// TestHook tests a system hook.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/system_hooks.html#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
}
// 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/ee/api/system_hooks.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// TagsService handles communication with the tags related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/tags.html
type TagsService struct {
client *Client
}
// Tag represents a GitLab tag.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/tags.html
type Tag struct {
Commit *Commit `json:"commit"`
Release *ReleaseNote `json:"release"`
Name string `json:"name"`
Message string `json:"message"`
Protected bool `json:"protected"`
Target string `json:"target"`
}
// ReleaseNote represents a GitLab version release.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/tags.html
type ReleaseNote struct {
TagName string `json:"tag_name"`
Description string `json:"description"`
}
func (t Tag) String() string {
return Stringify(t)
}
// ListTagsOptions represents the available ListTags() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#list-project-repository-tags
type ListTagsOptions struct {
ListOptions
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
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/ee/api/tags.html#list-project-repository-tags
func (s *TagsService) ListTags(pid interface{}, 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
}
// 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/ee/api/tags.html#get-a-single-repository-tag
func (s *TagsService) GetTag(pid interface{}, 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
}
// CreateTagOptions represents the available CreateTag() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag
type CreateTagOptions struct {
TagName *string `url:"tag_name,omitempty" json:"tag_name,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
Message *string `url:"message,omitempty" json:"message,omitempty"`
// Deprecated: Use the Releases API instead. (Deprecated in GitLab 11.7)
ReleaseDescription *string `url:"release_description:omitempty" json:"release_description,omitempty"`
}
// CreateTag creates a new tag in the repository that points to the supplied ref.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag
func (s *TagsService) CreateTag(pid interface{}, 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
}
// DeleteTag deletes a tag of a repository with given name.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#delete-a-tag
func (s *TagsService) DeleteTag(pid interface{}, 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)
}
// CreateReleaseNoteOptions represents the available CreateReleaseNote() options.
//
// Deprecated: This feature was deprecated in GitLab 11.7.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#create-a-new-release
type CreateReleaseNoteOptions struct {
Description *string `url:"description:omitempty" json:"description,omitempty"`
}
// CreateReleaseNote Add release notes to the existing git tag.
// If there already exists a release for the given tag, status code 409 is returned.
//
// Deprecated: This feature was deprecated in GitLab 11.7.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#create-a-new-release
func (s *TagsService) CreateReleaseNote(pid interface{}, tag string, opt *CreateReleaseNoteOptions, options ...RequestOptionFunc) (*ReleaseNote, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/tags/%s/release", PathEscape(project), url.PathEscape(tag))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
r := new(ReleaseNote)
resp, err := s.client.Do(req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// UpdateReleaseNoteOptions represents the available UpdateReleaseNote() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#update-a-release
type UpdateReleaseNoteOptions struct {
Description *string `url:"description:omitempty" json:"description,omitempty"`
}
// UpdateReleaseNote Updates the release notes of a given release.
//
// Deprecated: This feature was deprecated in GitLab 11.7.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/tags.html#update-a-release
func (s *TagsService) UpdateReleaseNote(pid interface{}, tag string, opt *UpdateReleaseNoteOptions, options ...RequestOptionFunc) (*ReleaseNote, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/tags/%s/release", PathEscape(project), url.PathEscape(tag))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
r := new(ReleaseNote)
resp, err := s.client.Do(req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// timeStatsService handles communication with the time tracking related
// methods of the GitLab API.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
type timeStatsService struct {
client *Client
}
// TimeStats represents the time estimates and time spent for an issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
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"`
}
func (t TimeStats) String() string {
return Stringify(t)
}
// SetTimeEstimateOptions represents the available SetTimeEstimate()
// options.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
type SetTimeEstimateOptions struct {
Duration *string `url:"duration,omitempty" json:"duration,omitempty"`
}
// setTimeEstimate sets the time estimate for a single project issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
func (s *timeStatsService) setTimeEstimate(pid interface{}, 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
}
// resetTimeEstimate resets the time estimate for a single project issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
func (s *timeStatsService) resetTimeEstimate(pid interface{}, 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
}
// AddSpentTimeOptions represents the available AddSpentTime() options.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
type AddSpentTimeOptions struct {
Duration *string `url:"duration,omitempty" json:"duration,omitempty"`
Summary *string `url:"summary,omitempty" json:"summary,omitempty"`
}
// addSpentTime adds spent time for a single project issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
func (s *timeStatsService) addSpentTime(pid interface{}, 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
}
// resetSpentTime resets the spent time for a single project issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
func (s *timeStatsService) resetSpentTime(pid interface{}, 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
}
// getTimeSpent gets the spent time for a single project issue.
//
// GitLab docs: https://docs.gitlab.com/ee/workflow/time_tracking.html
func (s *timeStatsService) getTimeSpent(pid interface{}, 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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
"time"
)
// TodosService handles communication with the todos related methods of
// the Gitlab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html
type TodosService struct {
client *Client
}
// Todo represents a GitLab todo.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html
type Todo struct {
ID int `json:"id"`
Project *BasicProject `json:"project"`
Author *BasicUser `json:"author"`
ActionName TodoAction `json:"action_name"`
TargetType TodoTargetType `json:"target_type"`
Target *TodoTarget `json:"target"`
TargetURL string `json:"target_url"`
Body string `json:"body"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
}
func (t Todo) String() string {
return Stringify(t)
}
// TodoTarget represents a todo target of type Issue or MergeRequest
type TodoTarget struct {
Assignees []*BasicUser `json:"assignees"`
Assignee *BasicUser `json:"assignee"`
Author *BasicUser `json:"author"`
CreatedAt *time.Time `json:"created_at"`
Description string `json:"description"`
Downvotes int `json:"downvotes"`
ID interface{} `json:"id"`
IID int `json:"iid"`
Labels []string `json:"labels"`
Milestone *Milestone `json:"milestone"`
ProjectID int `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"`
WebURL string `json:"web_url"`
// Only available for type Issue
Confidential bool `json:"confidential"`
DueDate string `json:"due_date"`
HasTasks bool `json:"has_tasks"`
Links *IssueLinks `json:"_links"`
MovedToID int `json:"moved_to_id"`
TimeStats *TimeStats `json:"time_stats"`
Weight int `json:"weight"`
// Only available for type MergeRequest
MergedAt *time.Time `json:"merged_at"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
ForceRemoveSourceBranch bool `json:"force_remove_source_branch"`
MergeCommitSHA string `json:"merge_commit_sha"`
MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
MergeStatus string `json:"merge_status"`
Reference string `json:"reference"`
Reviewers []*BasicUser `json:"reviewers"`
SHA string `json:"sha"`
ShouldRemoveSourceBranch bool `json:"should_remove_source_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID int `json:"source_project_id"`
Squash bool `json:"squash"`
TargetBranch string `json:"target_branch"`
TargetProjectID int `json:"target_project_id"`
WorkInProgress bool `json:"work_in_progress"`
// Only available for type DesignManagement::Design
FileName string `json:"filename"`
ImageURL string `json:"image_url"`
}
// ListTodosOptions represents the available ListTodos() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html#get-a-list-of-to-do-items
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"`
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/ee/api/todos.html#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
}
// MarkTodoAsDone marks a single pending todo given by its ID for the current user as done.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html#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)
}
// MarkAllTodosAsDone marks all pending todos for the current user as done.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"fmt"
"io"
"net/http"
retryablehttp "github.com/hashicorp/go-retryablehttp"
)
// TopicsService handles communication with the topics related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/topics.html
type TopicsService struct {
client *Client
}
// Topic represents a GitLab project topic.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/topics.html
type Topic struct {
ID int `json:"id"`
Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description"`
TotalProjectsCount uint64 `json:"total_projects_count"`
AvatarURL string `json:"avatar_url"`
}
func (t Topic) String() string {
return Stringify(t)
}
// ListTopicsOptions represents the available ListTopics() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/topics.html#list-topics
type ListTopicsOptions struct {
ListOptions
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/ee/api/topics.html#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)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// GetTopic gets a project topic by ID.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/topics.html#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)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// CreateTopicOptions represents the available CreateTopic() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/topics.html#create-a-project-topic
type CreateTopicOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
Avatar *TopicAvatar `url:"-" json:"-"`
}
// TopicAvatar represents a GitLab topic avatar.
type TopicAvatar struct {
Filename string
Image io.Reader
}
// MarshalJSON implements the json.Marshaler interface.
func (a *TopicAvatar) MarshalJSON() ([]byte, error) {
if a.Filename == "" && a.Image == nil {
return []byte(`""`), nil
}
type alias TopicAvatar
return json.Marshal((*alias)(a))
}
// CreateTopic creates a new project topic.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/topics.html#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
}
t := new(Topic)
resp, err := s.client.Do(req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// UpdateTopicOptions represents the available UpdateTopic() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/topics.html#update-a-project-topic
type UpdateTopicOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
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/ee/api/topics.html#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,
)
}
if err != nil {
return nil, nil, err
}
t := new(Topic)
resp, err := s.client.Do(req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// DeleteTopic deletes a project topic. Only available to administrators.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/topics.html#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)
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/url"
"reflect"
"strconv"
"strings"
"time"
)
// Ptr is a helper that returns a pointer to v.
func Ptr[T any](v T) *T {
return &v
}
// AccessControlValue represents an access control value within GitLab,
// used for managing access to certain project features.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html
type AccessControlValue string
// List of available access control values.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html
const (
DisabledAccessControl AccessControlValue = "disabled"
EnabledAccessControl AccessControlValue = "enabled"
PrivateAccessControl AccessControlValue = "private"
PublicAccessControl AccessControlValue = "public"
)
// AccessControl is a helper routine that allocates a new AccessControlValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func AccessControl(v AccessControlValue) *AccessControlValue {
return Ptr(v)
}
// AccessLevelValue represents a permission level within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/user/permissions.html
type AccessLevelValue int
// List of available access levels.
//
// GitLab API docs: https://docs.gitlab.com/ee/user/permissions.html
const (
NoPermissions AccessLevelValue = 0
MinimalAccessPermissions AccessLevelValue = 5
GuestPermissions AccessLevelValue = 10
ReporterPermissions AccessLevelValue = 20
DeveloperPermissions AccessLevelValue = 30
MaintainerPermissions AccessLevelValue = 40
OwnerPermissions AccessLevelValue = 50
AdminPermissions AccessLevelValue = 60
// Deprecated: Renamed to MaintainerPermissions in GitLab 11.0.
MasterPermissions AccessLevelValue = 40
// Deprecated: Renamed to OwnerPermissions.
OwnerPermission AccessLevelValue = 50
)
// AccessLevel is a helper routine that allocates a new AccessLevelValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func AccessLevel(v AccessLevelValue) *AccessLevelValue {
return Ptr(v)
}
// UserIDValue represents a user ID value within GitLab.
type UserIDValue string
// List of available user ID values.
const (
UserIDAny UserIDValue = "Any"
UserIDNone UserIDValue = "None"
)
// ApproverIDsValue represents an approver ID value within GitLab.
type ApproverIDsValue struct {
value interface{}
}
// ApproverIDs is a helper routine that creates a new ApproverIDsValue.
func ApproverIDs(v interface{}) *ApproverIDsValue {
switch v.(type) {
case UserIDValue, []int:
return &ApproverIDsValue{value: v}
default:
panic("Unsupported value passed as approver ID")
}
}
// EncodeValues implements the query.Encoder interface.
func (a *ApproverIDsValue) EncodeValues(key string, v *url.Values) error {
switch value := a.value.(type) {
case UserIDValue:
v.Set(key, string(value))
case []int:
v.Del(key)
v.Del(key + "[]")
for _, id := range value {
v.Add(key+"[]", strconv.Itoa(id))
}
}
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (a ApproverIDsValue) MarshalJSON() ([]byte, error) {
return json.Marshal(a.value)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *ApproverIDsValue) UnmarshalJSON(bytes []byte) error {
return json.Unmarshal(bytes, a.value)
}
// AssigneeIDValue represents an assignee ID value within GitLab.
type AssigneeIDValue struct {
value interface{}
}
// AssigneeID is a helper routine that creates a new AssigneeIDValue.
func AssigneeID(v interface{}) *AssigneeIDValue {
switch v.(type) {
case UserIDValue, int:
return &AssigneeIDValue{value: v}
default:
panic("Unsupported value passed as assignee ID")
}
}
// EncodeValues implements the query.Encoder interface.
func (a *AssigneeIDValue) EncodeValues(key string, v *url.Values) error {
switch value := a.value.(type) {
case UserIDValue:
v.Set(key, string(value))
case int:
v.Set(key, strconv.Itoa(value))
}
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (a AssigneeIDValue) MarshalJSON() ([]byte, error) {
return json.Marshal(a.value)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *AssigneeIDValue) UnmarshalJSON(bytes []byte) error {
return json.Unmarshal(bytes, a.value)
}
// ReviewerIDValue represents a reviewer ID value within GitLab.
type ReviewerIDValue struct {
value interface{}
}
// ReviewerID is a helper routine that creates a new ReviewerIDValue.
func ReviewerID(v interface{}) *ReviewerIDValue {
switch v.(type) {
case UserIDValue, int:
return &ReviewerIDValue{value: v}
default:
panic("Unsupported value passed as reviewer ID")
}
}
// EncodeValues implements the query.Encoder interface.
func (a *ReviewerIDValue) EncodeValues(key string, v *url.Values) error {
switch value := a.value.(type) {
case UserIDValue:
v.Set(key, string(value))
case int:
v.Set(key, strconv.Itoa(value))
}
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (a ReviewerIDValue) MarshalJSON() ([]byte, error) {
return json.Marshal(a.value)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *ReviewerIDValue) UnmarshalJSON(bytes []byte) error {
return json.Unmarshal(bytes, a.value)
}
// AvailabilityValue represents an availability value within GitLab.
type AvailabilityValue string
// List of available availability values.
//
// Undocummented, see code at:
// https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/app/models/user_status.rb#L22
const (
NotSet AvailabilityValue = "not_set"
Busy AvailabilityValue = "busy"
)
// Availability is a helper routine that allocates a new AvailabilityValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func Availability(v AvailabilityValue) *AvailabilityValue {
return Ptr(v)
}
// BuildStateValue represents a GitLab build state.
type BuildStateValue string
// These constants represent all valid build states.
const (
Created BuildStateValue = "created"
WaitingForResource BuildStateValue = "waiting_for_resource"
Preparing BuildStateValue = "preparing"
Pending BuildStateValue = "pending"
Running BuildStateValue = "running"
Success BuildStateValue = "success"
Failed BuildStateValue = "failed"
Canceled BuildStateValue = "canceled"
Skipped BuildStateValue = "skipped"
Manual BuildStateValue = "manual"
Scheduled BuildStateValue = "scheduled"
)
// BuildState is a helper routine that allocates a new BuildStateValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func BuildState(v BuildStateValue) *BuildStateValue {
return Ptr(v)
}
// CommentEventAction identifies if a comment has been newly created or updated.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events
type CommentEventAction string
const (
CommentEventActionCreate CommentEventAction = "create"
CommentEventActionUpdate CommentEventAction = "update"
)
// ContainerRegistryStatus represents the status of a Container Registry.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/container_registry.html#list-registry-repositories
type ContainerRegistryStatus string
// ContainerRegistryStatus represents all valid statuses of a Container Registry.
//
// Undocumented, see code at:
// https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/container_repository.rb?ref_type=heads#L35
const (
ContainerRegistryStatusDeleteScheduled ContainerRegistryStatus = "delete_scheduled"
ContainerRegistryStatusDeleteFailed ContainerRegistryStatus = "delete_failed"
ContainerRegistryStatusDeleteOngoing ContainerRegistryStatus = "delete_ongoing"
)
// DeploymentApprovalStatus represents a Gitlab deployment approval status.
type DeploymentApprovalStatus string
// These constants represent all valid deployment approval statuses.
const (
DeploymentApprovalStatusApproved DeploymentApprovalStatus = "approved"
DeploymentApprovalStatusRejected DeploymentApprovalStatus = "rejected"
)
// DeploymentStatusValue represents a Gitlab deployment status.
type DeploymentStatusValue string
// These constants represent all valid deployment statuses.
const (
DeploymentStatusCreated DeploymentStatusValue = "created"
DeploymentStatusRunning DeploymentStatusValue = "running"
DeploymentStatusSuccess DeploymentStatusValue = "success"
DeploymentStatusFailed DeploymentStatusValue = "failed"
DeploymentStatusCanceled DeploymentStatusValue = "canceled"
)
// DeploymentStatus is a helper routine that allocates a new
// DeploymentStatusValue to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func DeploymentStatus(v DeploymentStatusValue) *DeploymentStatusValue {
return Ptr(v)
}
// DORAMetricType represents all valid DORA metrics types.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
type DORAMetricType string
// List of available DORA metric type names.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
const (
DORAMetricDeploymentFrequency DORAMetricType = "deployment_frequency"
DORAMetricLeadTimeForChanges DORAMetricType = "lead_time_for_changes"
DORAMetricTimeToRestoreService DORAMetricType = "time_to_restore_service"
DORAMetricChangeFailureRate DORAMetricType = "change_failure_rate"
)
// DORAMetricInterval represents the time period over which the
// metrics are aggregated.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
type DORAMetricInterval string
// List of available DORA metric interval types.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/dora/metrics.html
const (
DORAMetricIntervalDaily DORAMetricInterval = "daily"
DORAMetricIntervalMonthly DORAMetricInterval = "monthly"
DORAMetricIntervalAll DORAMetricInterval = "all"
)
// EventTypeValue represents actions type for contribution events.
type EventTypeValue string
// List of available action type.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/user/profile/contributions_calendar.html#user-contribution-events
const (
CreatedEventType EventTypeValue = "created"
UpdatedEventType EventTypeValue = "updated"
ClosedEventType EventTypeValue = "closed"
ReopenedEventType EventTypeValue = "reopened"
PushedEventType EventTypeValue = "pushed"
CommentedEventType EventTypeValue = "commented"
MergedEventType EventTypeValue = "merged"
JoinedEventType EventTypeValue = "joined"
LeftEventType EventTypeValue = "left"
DestroyedEventType EventTypeValue = "destroyed"
ExpiredEventType EventTypeValue = "expired"
)
// EventTargetTypeValue represents actions type value for contribution events.
type EventTargetTypeValue string
// List of available action type.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/events.html#target-types
const (
IssueEventTargetType EventTargetTypeValue = "issue"
MilestoneEventTargetType EventTargetTypeValue = "milestone"
MergeRequestEventTargetType EventTargetTypeValue = "merge_request"
NoteEventTargetType EventTargetTypeValue = "note"
ProjectEventTargetType EventTargetTypeValue = "project"
SnippetEventTargetType EventTargetTypeValue = "snippet"
UserEventTargetType EventTargetTypeValue = "user"
)
// FileActionValue represents the available actions that can be performed on a file.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions
type FileActionValue string
// The available file actions.
const (
FileCreate FileActionValue = "create"
FileDelete FileActionValue = "delete"
FileMove FileActionValue = "move"
FileUpdate FileActionValue = "update"
FileChmod FileActionValue = "chmod"
)
// FileAction is a helper routine that allocates a new FileActionValue value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func FileAction(v FileActionValue) *FileActionValue {
return Ptr(v)
}
// GenericPackageSelectValue represents a generic package select value.
type GenericPackageSelectValue string
// The available generic package select values.
const (
SelectPackageFile GenericPackageSelectValue = "package_file"
)
// GenericPackageSelect is a helper routine that allocates a new
// GenericPackageSelectValue value to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func GenericPackageSelect(v GenericPackageSelectValue) *GenericPackageSelectValue {
return Ptr(v)
}
// GenericPackageStatusValue represents a generic package status.
type GenericPackageStatusValue string
// The available generic package statuses.
const (
PackageDefault GenericPackageStatusValue = "default"
PackageHidden GenericPackageStatusValue = "hidden"
)
// GenericPackageStatus is a helper routine that allocates a new
// GenericPackageStatusValue value to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func GenericPackageStatus(v GenericPackageStatusValue) *GenericPackageStatusValue {
return Ptr(v)
}
// ISOTime represents an ISO 8601 formatted date.
type ISOTime time.Time
// ISO 8601 date format.
const iso8601 = "2006-01-02"
// ParseISOTime parses an ISO 8601 formatted date.
func ParseISOTime(s string) (ISOTime, error) {
t, err := time.Parse(iso8601, s)
return ISOTime(t), err
}
// MarshalJSON implements the json.Marshaler interface.
func (t ISOTime) MarshalJSON() ([]byte, error) {
if reflect.ValueOf(t).IsZero() {
return []byte(`null`), nil
}
if y := time.Time(t).Year(); y < 0 || y >= 10000 {
// ISO 8901 uses 4 digits for the years.
return nil, errors.New("json: ISOTime year outside of range [0,9999]")
}
b := make([]byte, 0, len(iso8601)+2)
b = append(b, '"')
b = time.Time(t).AppendFormat(b, iso8601)
b = append(b, '"')
return b, nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (t *ISOTime) UnmarshalJSON(data []byte) error {
// Ignore null, like in the main JSON package.
if string(data) == "null" {
return nil
}
isotime, err := time.Parse(`"`+iso8601+`"`, string(data))
*t = ISOTime(isotime)
return err
}
// EncodeValues implements the query.Encoder interface.
func (t *ISOTime) EncodeValues(key string, v *url.Values) error {
if t == nil || (time.Time(*t)).IsZero() {
return nil
}
v.Add(key, t.String())
return nil
}
// String implements the Stringer interface.
func (t ISOTime) String() string {
return time.Time(t).Format(iso8601)
}
// Labels represents a list of labels.
type Labels []string
// LabelOptions is a custom type with specific marshaling characteristics.
type LabelOptions []string
// MarshalJSON implements the json.Marshaler interface.
func (l *LabelOptions) MarshalJSON() ([]byte, error) {
if *l == nil {
return []byte(`null`), nil
}
return json.Marshal(strings.Join(*l, ","))
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (l *LabelOptions) UnmarshalJSON(data []byte) error {
type alias LabelOptions
if !bytes.HasPrefix(data, []byte("[")) {
data = []byte(fmt.Sprintf("[%s]", string(data)))
}
return json.Unmarshal(data, (*alias)(l))
}
// EncodeValues implements the query.EncodeValues interface.
func (l *LabelOptions) EncodeValues(key string, v *url.Values) error {
v.Set(key, strings.Join(*l, ","))
return nil
}
// LinkTypeValue represents a release link type.
type LinkTypeValue string
// List of available release link types.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/releases/links.html#create-a-release-link
const (
ImageLinkType LinkTypeValue = "image"
OtherLinkType LinkTypeValue = "other"
PackageLinkType LinkTypeValue = "package"
RunbookLinkType LinkTypeValue = "runbook"
)
// LinkType is a helper routine that allocates a new LinkType value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func LinkType(v LinkTypeValue) *LinkTypeValue {
return Ptr(v)
}
// LicenseApprovalStatusValue describe the approval statuses of a license.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/managed_licenses.html
type LicenseApprovalStatusValue string
// List of available license approval statuses.
const (
LicenseApproved LicenseApprovalStatusValue = "approved"
LicenseBlacklisted LicenseApprovalStatusValue = "blacklisted"
LicenseAllowed LicenseApprovalStatusValue = "allowed"
LicenseDenied LicenseApprovalStatusValue = "denied"
)
// LicenseApprovalStatus is a helper routine that allocates a new license
// approval status value to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func LicenseApprovalStatus(v LicenseApprovalStatusValue) *LicenseApprovalStatusValue {
return Ptr(v)
}
// MergeMethodValue represents a project merge type within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#project-merge-method
type MergeMethodValue string
// List of available merge type
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#project-merge-method
const (
NoFastForwardMerge MergeMethodValue = "merge"
FastForwardMerge MergeMethodValue = "ff"
RebaseMerge MergeMethodValue = "rebase_merge"
)
// MergeMethod is a helper routine that allocates a new MergeMethod
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func MergeMethod(v MergeMethodValue) *MergeMethodValue {
return Ptr(v)
}
// NoteTypeValue represents the type of a Note.
type NoteTypeValue string
// List of available note types.
const (
DiffNote NoteTypeValue = "DiffNote"
DiscussionNote NoteTypeValue = "DiscussionNote"
GenericNote NoteTypeValue = "Note"
LegacyDiffNote NoteTypeValue = "LegacyDiffNote"
)
// NoteType is a helper routine that allocates a new NoteTypeValue to
// store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func NoteType(v NoteTypeValue) *NoteTypeValue {
return Ptr(v)
}
// NotificationLevelValue represents a notification level.
type NotificationLevelValue int
// String implements the fmt.Stringer interface.
func (l NotificationLevelValue) String() string {
return notificationLevelNames[l]
}
// MarshalJSON implements the json.Marshaler interface.
func (l NotificationLevelValue) MarshalJSON() ([]byte, error) {
return json.Marshal(l.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (l *NotificationLevelValue) UnmarshalJSON(data []byte) error {
var raw interface{}
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
switch raw := raw.(type) {
case float64:
*l = NotificationLevelValue(raw)
case string:
*l = notificationLevelTypes[raw]
case nil:
// No action needed.
default:
return fmt.Errorf("json: cannot unmarshal %T into Go value of type %T", raw, *l)
}
return nil
}
// List of valid notification levels.
const (
DisabledNotificationLevel NotificationLevelValue = iota
ParticipatingNotificationLevel
WatchNotificationLevel
GlobalNotificationLevel
MentionNotificationLevel
CustomNotificationLevel
)
var notificationLevelNames = [...]string{
"disabled",
"participating",
"watch",
"global",
"mention",
"custom",
}
var notificationLevelTypes = map[string]NotificationLevelValue{
"disabled": DisabledNotificationLevel,
"participating": ParticipatingNotificationLevel,
"watch": WatchNotificationLevel,
"global": GlobalNotificationLevel,
"mention": MentionNotificationLevel,
"custom": CustomNotificationLevel,
}
// NotificationLevel is a helper routine that allocates a new NotificationLevelValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func NotificationLevel(v NotificationLevelValue) *NotificationLevelValue {
return Ptr(v)
}
// ProjectCreationLevelValue represents a project creation level within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
type ProjectCreationLevelValue string
// List of available project creation levels.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
const (
NoOneProjectCreation ProjectCreationLevelValue = "noone"
MaintainerProjectCreation ProjectCreationLevelValue = "maintainer"
DeveloperProjectCreation ProjectCreationLevelValue = "developer"
)
// ProjectCreationLevel is a helper routine that allocates a new ProjectCreationLevelValue
// to store v and returns a pointer to it.
// Please use Ptr instead.
func ProjectCreationLevel(v ProjectCreationLevelValue) *ProjectCreationLevelValue {
return Ptr(v)
}
// ProjectHookEvent represents a project hook event.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#hook-events
type ProjectHookEvent string
// List of available project hook events.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#hook-events
const (
ProjectHookEventPush ProjectHookEvent = "push_events"
ProjectHookEventTagPush ProjectHookEvent = "tag_push_events"
ProjectHookEventIssues ProjectHookEvent = "issues_events"
ProjectHookEventConfidentialIssues ProjectHookEvent = "confidential_issues_events"
ProjectHookEventNote ProjectHookEvent = "note_events"
ProjectHookEventMergeRequests ProjectHookEvent = "merge_requests_events"
ProjectHookEventJob ProjectHookEvent = "job_events"
ProjectHookEventPipeline ProjectHookEvent = "pipeline_events"
ProjectHookEventWiki ProjectHookEvent = "wiki_page_events"
ProjectHookEventReleases ProjectHookEvent = "releases_events"
ProjectHookEventEmoji ProjectHookEvent = "emoji_events"
ProjectHookEventResourceAccessToken ProjectHookEvent = "resource_access_token_events"
)
// ResourceGroupProcessMode represents a process mode for a resource group
// within a GitLab project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/ci/resource_groups/index.html#process-modes
type ResourceGroupProcessMode string
// List of available resource group process modes.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/ci/resource_groups/index.html#process-modes
const (
Unordered ResourceGroupProcessMode = "unordered"
OldestFirst ResourceGroupProcessMode = "oldest_first"
NewestFirst ResourceGroupProcessMode = "newest_first"
)
// SharedRunnersSettingValue determines whether shared runners are enabled for a
// group’s subgroups and projects.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#options-for-shared_runners_setting
type SharedRunnersSettingValue string
// List of available shared runner setting levels.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/groups.html#options-for-shared_runners_setting
const (
EnabledSharedRunnersSettingValue SharedRunnersSettingValue = "enabled"
DisabledAndOverridableSharedRunnersSettingValue SharedRunnersSettingValue = "disabled_and_overridable"
DisabledAndUnoverridableSharedRunnersSettingValue SharedRunnersSettingValue = "disabled_and_unoverridable"
// Deprecated: DisabledWithOverrideSharedRunnersSettingValue is deprecated
// in favor of DisabledAndOverridableSharedRunnersSettingValue.
DisabledWithOverrideSharedRunnersSettingValue SharedRunnersSettingValue = "disabled_with_override"
)
// SharedRunnersSetting is a helper routine that allocates a new SharedRunnersSettingValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func SharedRunnersSetting(v SharedRunnersSettingValue) *SharedRunnersSettingValue {
return Ptr(v)
}
// SubGroupCreationLevelValue represents a sub group creation level within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
type SubGroupCreationLevelValue string
// List of available sub group creation levels.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
const (
OwnerSubGroupCreationLevelValue SubGroupCreationLevelValue = "owner"
MaintainerSubGroupCreationLevelValue SubGroupCreationLevelValue = "maintainer"
)
// SubGroupCreationLevel is a helper routine that allocates a new SubGroupCreationLevelValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func SubGroupCreationLevel(v SubGroupCreationLevelValue) *SubGroupCreationLevelValue {
return Ptr(v)
}
// SquashOptionValue represents a squash optional level within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type SquashOptionValue string
// List of available squash options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
const (
SquashOptionNever SquashOptionValue = "never"
SquashOptionAlways SquashOptionValue = "always"
SquashOptionDefaultOff SquashOptionValue = "default_off"
SquashOptionDefaultOn SquashOptionValue = "default_on"
)
// SquashOption is a helper routine that allocates a new SquashOptionValue
// to store s and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func SquashOption(s SquashOptionValue) *SquashOptionValue {
return Ptr(s)
}
// TasksCompletionStatus represents tasks of the issue/merge request.
type TasksCompletionStatus struct {
Count int `json:"count"`
CompletedCount int `json:"completed_count"`
}
// TodoAction represents the available actions that can be performed on a todo.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html
type TodoAction string
// The available todo actions.
const (
TodoAssigned TodoAction = "assigned"
TodoMentioned TodoAction = "mentioned"
TodoBuildFailed TodoAction = "build_failed"
TodoMarked TodoAction = "marked"
TodoApprovalRequired TodoAction = "approval_required"
TodoDirectlyAddressed TodoAction = "directly_addressed"
)
// TodoTargetType represents the available target that can be linked to a todo.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/todos.html
type TodoTargetType string
const (
TodoTargetAlertManagement TodoTargetType = "AlertManagement::Alert"
TodoTargetDesignManagement TodoTargetType = "DesignManagement::Design"
TodoTargetIssue TodoTargetType = "Issue"
TodoTargetMergeRequest TodoTargetType = "MergeRequest"
)
// UploadType represents the available upload types.
type UploadType string
// The available upload types.
const (
UploadAvatar UploadType = "avatar"
UploadFile UploadType = "file"
)
// VariableTypeValue represents a variable type within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
type VariableTypeValue string
// List of available variable types.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
const (
EnvVariableType VariableTypeValue = "env_var"
FileVariableType VariableTypeValue = "file"
)
// VariableType is a helper routine that allocates a new VariableTypeValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func VariableType(v VariableTypeValue) *VariableTypeValue {
return Ptr(v)
}
// VisibilityValue represents a visibility level within GitLab.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
type VisibilityValue string
// List of available visibility levels.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/
const (
PrivateVisibility VisibilityValue = "private"
InternalVisibility VisibilityValue = "internal"
PublicVisibility VisibilityValue = "public"
)
// Visibility is a helper routine that allocates a new VisibilityValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func Visibility(v VisibilityValue) *VisibilityValue {
return Ptr(v)
}
// WikiFormatValue represents the available wiki formats.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/wikis.html
type WikiFormatValue string
// The available wiki formats.
const (
WikiFormatMarkdown WikiFormatValue = "markdown"
WikiFormatRDoc WikiFormatValue = "rdoc"
WikiFormatASCIIDoc WikiFormatValue = "asciidoc"
WikiFormatOrg WikiFormatValue = "org"
)
// WikiFormat is a helper routine that allocates a new WikiFormatValue
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func WikiFormat(v WikiFormatValue) *WikiFormatValue {
return Ptr(v)
}
// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func Bool(v bool) *bool {
return Ptr(v)
}
// Int is a helper routine that allocates a new int value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func Int(v int) *int {
return Ptr(v)
}
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func String(v string) *string {
return Ptr(v)
}
// Time is a helper routine that allocates a new time.Time value
// to store v and returns a pointer to it.
//
// Deprecated: Please use Ptr instead.
func Time(v time.Time) *time.Time {
return Ptr(v)
}
// BoolValue is a boolean value with advanced json unmarshaling features.
type BoolValue bool
// UnmarshalJSON allows 1, 0, "true", and "false" to be considered as boolean values
// Needed for:
// https://gitlab.com/gitlab-org/gitlab-ce/issues/50122
// https://gitlab.com/gitlab-org/gitlab/-/issues/233941
// https://github.com/gitlabhq/terraform-provider-gitlab/issues/348
func (t *BoolValue) UnmarshalJSON(b []byte) error {
switch string(b) {
case `"1"`:
*t = true
return nil
case `"0"`:
*t = false
return nil
case `"true"`:
*t = true
return nil
case `"false"`:
*t = false
return nil
default:
var v bool
err := json.Unmarshal(b, &v)
*t = BoolValue(v)
return err
}
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"time"
"github.com/hashicorp/go-retryablehttp"
)
// List a couple of standard errors.
var (
ErrUserActivatePrevented = errors.New("Cannot activate a user that is blocked by admin or by LDAP synchronization")
ErrUserApprovePrevented = errors.New("Cannot approve a user that is blocked by admin or by LDAP synchronization")
ErrUserBlockPrevented = errors.New("Cannot block a user that is already blocked by LDAP synchronization")
ErrUserConflict = errors.New("User does not have a pending request")
ErrUserDeactivatePrevented = errors.New("Cannot deactivate a user that is blocked by admin or by LDAP synchronization")
ErrUserDisableTwoFactorPrevented = errors.New("Cannot disable two factor authentication if not authenticated as administrator")
ErrUserNotFound = errors.New("User does not exist")
ErrUserRejectPrevented = errors.New("Cannot reject a user if not authenticated as administrator")
ErrUserTwoFactorNotEnabled = errors.New("Cannot disable two factor authentication if not enabled")
ErrUserUnblockPrevented = errors.New("Cannot unblock a user that is blocked by LDAP synchronization")
)
// UsersService handles communication with the user related methods of
// the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html
type UsersService struct {
client *Client
}
// 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"`
CreatedAt *time.Time `json:"created_at"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}
// User represents a GitLab user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
WebURL string `json:"web_url"`
CreatedAt *time.Time `json:"created_at"`
Bio string `json:"bio"`
Bot bool `json:"bot"`
Location string `json:"location"`
PublicEmail string `json:"public_email"`
Skype string `json:"skype"`
Linkedin string `json:"linkedin"`
Twitter string `json:"twitter"`
WebsiteURL string `json:"website_url"`
Organization string `json:"organization"`
JobTitle string `json:"job_title"`
ExternUID string `json:"extern_uid"`
Provider string `json:"provider"`
ThemeID int `json:"theme_id"`
LastActivityOn *ISOTime `json:"last_activity_on"`
ColorSchemeID int `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"`
ProjectsLimit int `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"`
LastSignInIP *net.IP `json:"last_sign_in_ip"`
ConfirmedAt *time.Time `json:"confirmed_at"`
TwoFactorEnabled bool `json:"two_factor_enabled"`
Note string `json:"note"`
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"`
UsingLicenseSeat bool `json:"using_license_seat"`
CustomAttributes []*CustomAttribute `json:"custom_attributes"`
NamespaceID int `json:"namespace_id"`
Locked bool `json:"locked"`
}
// UserIdentity represents a user identity.
type UserIdentity struct {
Provider string `json:"provider"`
ExternUID string `json:"extern_uid"`
}
// UserAvatar represents a GitLab user avatar.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html
type UserAvatar struct {
Filename string
Image io.Reader
}
// MarshalJSON implements the json.Marshaler interface.
func (a *UserAvatar) MarshalJSON() ([]byte, error) {
if a.Filename == "" && a.Image == nil {
return []byte(`""`), nil
}
type alias UserAvatar
return json.Marshal((*alias)(a))
}
// ListUsersOptions represents the available ListUsers() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-users
type ListUsersOptions struct {
ListOptions
Active *bool `url:"active,omitempty" json:"active,omitempty"`
Blocked *bool `url:"blocked,omitempty" json:"blocked,omitempty"`
ExcludeInternal *bool `url:"exclude_internal,omitempty" json:"exclude_internal,omitempty"`
ExcludeExternal *bool `url:"exclude_external,omitempty" json:"exclude_external,omitempty"`
// The options below are only available for admins.
Search *string `url:"search,omitempty" json:"search,omitempty"`
Username *string `url:"username,omitempty" json:"username,omitempty"`
ExternalUID *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"`
Provider *string `url:"provider,omitempty" json:"provider,omitempty"`
CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
TwoFactor *string `url:"two_factor,omitempty" json:"two_factor,omitempty"`
Admins *bool `url:"admins,omitempty" json:"admins,omitempty"`
External *bool `url:"external,omitempty" json:"external,omitempty"`
WithoutProjects *bool `url:"without_projects,omitempty" json:"without_projects,omitempty"`
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
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/ee/api/users.html#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
}
// GetUsersOptions represents the available GetUser() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#single-user
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/ee/api/users.html#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
}
// CreateUserOptions represents the available CreateUser() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#user-creation
type CreateUserOptions struct {
Admin *bool `url:"admin,omitempty" json:"admin,omitempty"`
Avatar *UserAvatar `url:"-" json:"-"`
Bio *string `url:"bio,omitempty" json:"bio,omitempty"`
CanCreateGroup *bool `url:"can_create_group,omitempty" json:"can_create_group,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"`
ForceRandomPassword *bool `url:"force_random_password,omitempty" json:"force_random_password,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"`
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"`
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"`
}
// CreateUser creates a new user. Note only administrators can create new users.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#user-creation
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,
)
}
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
}
// ModifyUserOptions represents the available ModifyUser() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#user-modification
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/ee/api/users.html#user-modification
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
}
// 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/ee/api/users.html#user-deletion
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
}
return s.client.Do(req, nil)
}
// CurrentUser gets currently authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-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
}
// UserStatus represents the current status of a user
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#user-status
type UserStatus struct {
Emoji string `json:"emoji"`
Availability AvailabilityValue `json:"availability"`
Message string `json:"message"`
MessageHTML string `json:"message_html"`
}
// CurrentUserStatus retrieves the user status
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#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
}
// GetUserStatus retrieves a user's status
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-the-status-of-a-user
func (s *UsersService) GetUserStatus(user int, options ...RequestOptionFunc) (*UserStatus, *Response, error) {
u := fmt.Sprintf("users/%d/status", 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
}
// UserStatusOptions represents the options required to set the status
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#set-user-status
type UserStatusOptions struct {
Emoji *string `url:"emoji,omitempty" json:"emoji,omitempty"`
Availability *AvailabilityValue `url:"availability,omitempty" json:"availability,omitempty"`
Message *string `url:"message,omitempty" json:"message,omitempty"`
}
// SetUserStatus sets the user's status
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#set-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
}
// UserAssociationsCount represents the user associations count.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/users.html#list-associations-count-for-user
type UserAssociationsCount struct {
GroupsCount int `json:"groups_count"`
ProjectsCount int `json:"projects_count"`
IssuesCount int `json:"issues_count"`
MergeRequestsCount int `json:"merge_requests_count"`
}
// GetUserAssociationsCount gets a list of a specified user associations.
//
// Gitlab API docs: https://docs.gitlab.com/ee/api/users.html#list-associations-count-for-user
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
}
// SSHKey represents a SSH key.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-ssh-keys
type SSHKey struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt *time.Time `json:"created_at"`
ExpiresAt *time.Time `json:"expires_at"`
}
// ListSSHKeysOptions represents the available ListSSHKeys options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-ssh-keys
type ListSSHKeysOptions ListOptions
// ListSSHKeys gets a list of currently authenticated user's SSH keys.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-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
}
// ListSSHKeysForUserOptions represents the available ListSSHKeysForUser() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#list-ssh-keys-for-user
type ListSSHKeysForUserOptions ListOptions
// ListSSHKeysForUser gets a list of a specified user's SSH keys.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#list-ssh-keys-for-user
func (s *UsersService) ListSSHKeysForUser(uid interface{}, 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
}
// GetSSHKey gets a single key.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#single-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
}
// GetSSHKeyForUser gets a single key for a given user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#single-ssh-key-for-given-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
}
// AddSSHKeyOptions represents the available AddSSHKey() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-ssh-key
type AddSSHKeyOptions struct {
Title *string `url:"title,omitempty" json:"title,omitempty"`
Key *string `url:"key,omitempty" json:"key,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// AddSSHKey creates a new key owned by the currently authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-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
}
// AddSSHKeyForUser creates new key owned by specified user. Available only for
// admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-ssh-key-for-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
}
// 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/ee/api/users.html#delete-ssh-key-for-current-user
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)
}
// DeleteSSHKeyForUser deletes key owned by a specified user. Available only
// for admin.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#delete-ssh-key-for-given-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)
}
// GPGKey represents a GPG key.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-all-gpg-keys
type GPGKey struct {
ID int `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/ee/api/users.html#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
}
// GetGPGKey gets a specific GPG key of currently authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#get-a-specific-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
}
// AddGPGKeyOptions represents the available AddGPGKey() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-a-gpg-key
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/ee/api/users.html#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
}
// DeleteGPGKey deletes a GPG key owned by currently authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#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)
}
// ListGPGKeysForUser gets a list of a specified user’s GPG keys.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#list-all-gpg-keys-for-given-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
}
// GetGPGKeyForUser gets a specific GPG key for a given user.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#get-a-specific-gpg-key-for-a-given-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
}
// AddGPGKeyForUser creates new GPG key owned by the specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#add-a-gpg-key-for-a-given-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
}
// DeleteGPGKeyForUser deletes a GPG key owned by a specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#delete-a-gpg-key-for-a-given-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)
}
// Email represents an Email.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#list-emails
type Email struct {
ID int `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/ee/api/users.html#list-emails
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
}
// ListEmailsForUserOptions represents the available ListEmailsForUser() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#list-emails-for-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/ee/api/users.html#list-emails-for-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
}
// GetEmail gets a single email.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#single-email
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
}
return e, resp, nil
}
// AddEmailOptions represents the available AddEmail() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-email
type AddEmailOptions struct {
Email *string `url:"email,omitempty" json:"email,omitempty"`
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/ee/api/users.html#add-email
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
}
// AddEmailForUser creates new email owned by specified user. Available only for
// admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#add-email-for-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
}
// 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/ee/api/users.html#delete-email-for-current-user
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)
}
// DeleteEmailForUser deletes email owned by a specified user. Available only
// for admin.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#delete-email-for-given-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)
}
// BlockUser blocks the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#block-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("Received unexpected result code: %d", resp.StatusCode)
}
}
// UnblockUser unblocks the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#unblock-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 403:
return ErrUserUnblockPrevented
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// BanUser bans the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#ban-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// UnbanUser unbans the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#unban-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// DeactivateUser deactivate the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#deactivate-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 403:
return ErrUserDeactivatePrevented
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// ActivateUser activate the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#activate-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 403:
return ErrUserActivatePrevented
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// ApproveUser approve the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#approve-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 201:
return nil
case 403:
return ErrUserApprovePrevented
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// RejectUser reject the specified user. Available only for admin.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#reject-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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 200:
return nil
case 403:
return ErrUserRejectPrevented
case 404:
return ErrUserNotFound
case 409:
return ErrUserConflict
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// ImpersonationToken represents an impersonation token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-all-impersonation-tokens-of-a-user
type ImpersonationToken struct {
ID int `json:"id"`
Name string `json:"name"`
Active bool `json:"active"`
Token string `json:"token"`
Scopes []string `json:"scopes"`
Revoked bool `json:"revoked"`
CreatedAt *time.Time `json:"created_at"`
ExpiresAt *ISOTime `json:"expires_at"`
LastUsedAt *time.Time `json:"last_used_at"`
}
// GetAllImpersonationTokensOptions represents the available
// GetAllImpersonationTokens() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-all-impersonation-tokens-of-a-user
type GetAllImpersonationTokensOptions struct {
ListOptions
State *string `url:"state,omitempty" json:"state,omitempty"`
}
// GetAllImpersonationTokens retrieves all impersonation tokens of a user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-all-impersonation-tokens-of-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
}
// GetImpersonationToken retrieves an impersonation token of a user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-an-impersonation-token-of-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
}
// CreateImpersonationTokenOptions represents the available
// CreateImpersonationToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-an-impersonation-token
type CreateImpersonationTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"`
}
// CreateImpersonationToken creates an impersonation token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#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
}
// RevokeImpersonationToken revokes an impersonation token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#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)
}
// CreatePersonalAccessTokenOptions represents the available
// CreatePersonalAccessToken() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token
type CreatePersonalAccessTokenOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ExpiresAt *ISOTime `url:"expires_at,omitempty" json:"expires_at,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
}
// CreatePersonalAccessToken creates a personal access token.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token
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
}
// CreatePersonalAccessTokenForCurrentUserOptions represents the available
// CreatePersonalAccessTokenForCurrentUser() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token-with-limited-scopes-for-the-currently-authenticated-user
type CreatePersonalAccessTokenForCurrentUserOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
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/ee/api/users.html#create-a-personal-access-token-with-limited-scopes-for-the-currently-authenticated-user
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
}
// UserActivity represents an entry in the user/activities response
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-user-activities
type UserActivity struct {
Username string `json:"username"`
LastActivityOn *ISOTime `json:"last_activity_on"`
}
// GetUserActivitiesOptions represents the options for GetUserActivities
//
// GitLap API docs:
// https://docs.gitlab.com/ee/api/users.html#get-user-activities
type GetUserActivitiesOptions struct {
ListOptions
From *ISOTime `url:"from,omitempty" json:"from,omitempty"`
}
// GetUserActivities retrieves user activities (admin only)
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#get-user-activities
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
}
// UserMembership represents a membership of the user in a namespace or project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#user-memberships
type UserMembership struct {
SourceID int `json:"source_id"`
SourceName string `json:"source_name"`
SourceType string `json:"source_type"`
AccessLevel AccessLevelValue `json:"access_level"`
}
// GetUserMembershipOptions represents the options available to query user memberships.
//
// GitLab API docs:
// ohttps://docs.gitlab.com/ee/api/users.html#user-memberships
type GetUserMembershipOptions struct {
ListOptions
Type *string `url:"type,omitempty" json:"type,omitempty"`
}
// GetUserMemberships retrieves a list of the user's memberships.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#user-memberships
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
}
// DisableTwoFactor disables two factor authentication for the specified user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#disable-two-factor-authentication
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)
if err != nil && resp == nil {
return err
}
switch resp.StatusCode {
case 204:
return nil
case 400:
return ErrUserTwoFactorNotEnabled
case 403:
return ErrUserDisableTwoFactorPrevented
case 404:
return ErrUserNotFound
default:
return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
}
}
// UserRunner represents a GitLab runner linked to the current user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-a-runner
type UserRunner struct {
ID int `json:"id"`
Token string `json:"token"`
TokenExpiresAt *time.Time `json:"token_expires_at"`
}
// CreateUserRunnerOptions represents the available CreateUserRunner() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#create-a-runner
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"`
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"`
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/ee/api/users.html#create-a-runner
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
}
// CreateServiceAccountUser creates a new service account user. Note only administrators can create new service account users.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/users.html#create-service-account-user
func (s *UsersService) CreateServiceAccountUser(options ...RequestOptionFunc) (*User, *Response, error) {
req, err := s.client.NewRequest(http.MethodPost, "service_accounts", 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
}
// UploadAvatar uploads an avatar to the current user.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/users.html#upload-a-current-user-avatar
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,
)
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
}
//
// Copyright 2021, Sander van Harmelen
//
// 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 (
"fmt"
"net/http"
)
// ValidateService handles communication with the validation related methods of
// the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/lint.html
type ValidateService struct {
client *Client
}
// LintResult represents the linting results.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/lint.html
type LintResult struct {
Status string `json:"status"`
Errors []string `json:"errors"`
Warnings []string `json:"warnings"`
MergedYaml string `json:"merged_yaml"`
}
// ProjectLintResult represents the linting results by project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-a-projects-ci-configuration
type ProjectLintResult struct {
Valid bool `json:"valid"`
Errors []string `json:"errors"`
Warnings []string `json:"warnings"`
MergedYaml string `json:"merged_yaml"`
}
// LintOptions represents the available Lint() options.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-the-ci-yaml-configuration
type LintOptions struct {
Content string `url:"content,omitempty" json:"content,omitempty"`
IncludeMergedYAML bool `url:"include_merged_yaml,omitempty" json:"include_merged_yaml,omitempty"`
IncludeJobs bool `url:"include_jobs,omitempty" json:"include_jobs,omitempty"`
}
// Lint validates .gitlab-ci.yml content.
// Deprecated: This endpoint was removed in GitLab 16.0.
//
// Gitlab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-the-ci-yaml-configuration-deprecated
func (s *ValidateService) Lint(opts *LintOptions, options ...RequestOptionFunc) (*LintResult, *Response, error) {
req, err := s.client.NewRequest(http.MethodPost, "ci/lint", &opts, options)
if err != nil {
return nil, nil, err
}
l := new(LintResult)
resp, err := s.client.Do(req, l)
if err != nil {
return nil, resp, err
}
return l, resp, nil
}
// ProjectNamespaceLintOptions represents the available ProjectNamespaceLint() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace
type ProjectNamespaceLintOptions struct {
Content *string `url:"content,omitempty" json:"content,omitempty"`
DryRun *bool `url:"dry_run,omitempty" json:"dry_run,omitempty"`
IncludeJobs *bool `url:"include_jobs,omitempty" json:"include_jobs,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// ProjectNamespaceLint validates .gitlab-ci.yml content by project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-a-ci-yaml-configuration-with-a-namespace
func (s *ValidateService) ProjectNamespaceLint(pid interface{}, 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
}
// ProjectLintOptions represents the available ProjectLint() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-a-projects-ci-configuration
type ProjectLintOptions struct {
ContentRef *string `url:"content_ref,omitempty" json:"content_ref,omitempty"`
DryRunRef *string `url:"dry_run_ref,omitempty" json:"dry_run_ref,omitempty"`
DryRun *bool `url:"dry_run,omitempty" json:"dry_run,omitempty"`
IncludeJobs *bool `url:"include_jobs,omitempty" json:"include_jobs,omitempty"`
Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
}
// ProjectLint validates .gitlab-ci.yml content by project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/lint.html#validate-a-projects-ci-configuration
func (s *ValidateService) ProjectLint(pid interface{}, 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
}
//
// Copyright 2021, Andrea Funto'
//
// 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"
// VersionService handles communication with the GitLab server instance to
// retrieve its version information via the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/version.html
type VersionService struct {
client *Client
}
// Version represents a GitLab instance version.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/version.html
type Version struct {
Version string `json:"version"`
Revision string `json:"revision"`
}
func (s Version) String() string {
return Stringify(s)
}
// GetVersion gets a GitLab server instance version; it is only available to
// authenticated users.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/version.html
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
}
//
// Copyright 2021, Stany MARCEL
//
// 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 (
"fmt"
"net/http"
"net/url"
)
// WikisService handles communication with the wikis related methods of
// the Gitlab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/wikis.html
type WikisService struct {
client *Client
}
// Wiki represents a GitLab wiki.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/wikis.html
type Wiki struct {
Content string `json:"content"`
Encoding string `json:"encoding"`
Format WikiFormatValue `json:"format"`
Slug string `json:"slug"`
Title string `json:"title"`
}
func (w Wiki) String() string {
return Stringify(w)
}
// ListWikisOptions represents the available ListWikis options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#list-wiki-pages
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/ee/api/wikis.html#list-wiki-pages
func (s *WikisService) ListWikis(pid interface{}, 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
}
// GetWikiPageOptions represents options to GetWikiPage
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#get-a-wiki-page
type GetWikiPageOptions struct {
RenderHTML *bool `url:"render_html,omitempty" json:"render_html,omitempty"`
Version *string `url:"version,omitempty" json:"version,omitempty"`
}
// GetWikiPage gets a wiki page for a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#get-a-wiki-page
func (s *WikisService) GetWikiPage(pid interface{}, 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
}
// CreateWikiPageOptions represents options to CreateWikiPage.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#create-a-new-wiki-page
type CreateWikiPageOptions struct {
Content *string `url:"content,omitempty" json:"content,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
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/ee/api/wikis.html#create-a-new-wiki-page
func (s *WikisService) CreateWikiPage(pid interface{}, 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
}
// EditWikiPageOptions represents options to EditWikiPage.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#edit-an-existing-wiki-page
type EditWikiPageOptions struct {
Content *string `url:"content,omitempty" json:"content,omitempty"`
Title *string `url:"title,omitempty" json:"title,omitempty"`
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/ee/api/wikis.html#edit-an-existing-wiki-page
func (s *WikisService) EditWikiPage(pid interface{}, 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
}
// DeleteWikiPage deletes a wiki page with a given slug.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/wikis.html#delete-a-wiki-page
func (s *WikisService) DeleteWikiPage(pid interface{}, 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)
}