services.go

  1//
  2// Copyright 2017, Sander van Harmelen
  3//
  4// Licensed under the Apache License, Version 2.0 (the "License");
  5// you may not use this file except in compliance with the License.
  6// You may obtain a copy of the License at
  7//
  8//     http://www.apache.org/licenses/LICENSE-2.0
  9//
 10// Unless required by applicable law or agreed to in writing, software
 11// distributed under the License is distributed on an "AS IS" BASIS,
 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13// See the License for the specific language governing permissions and
 14// limitations under the License.
 15//
 16
 17package gitlab
 18
 19import (
 20	"encoding/json"
 21	"fmt"
 22	"strconv"
 23	"time"
 24)
 25
 26// ServicesService handles communication with the services related methods of
 27// the GitLab API.
 28//
 29// GitLab API docs: https://docs.gitlab.com/ce/api/services.html
 30type ServicesService struct {
 31	client *Client
 32}
 33
 34// Service represents a GitLab service.
 35//
 36// GitLab API docs: https://docs.gitlab.com/ce/api/services.html
 37type Service struct {
 38	ID                       int        `json:"id"`
 39	Title                    string     `json:"title"`
 40	CreatedAt                *time.Time `json:"created_at"`
 41	UpdatedAt                *time.Time `json:"updated_at"`
 42	Active                   bool       `json:"active"`
 43	PushEvents               bool       `json:"push_events"`
 44	IssuesEvents             bool       `json:"issues_events"`
 45	ConfidentialIssuesEvents bool       `json:"confidential_issues_events"`
 46	MergeRequestsEvents      bool       `json:"merge_requests_events"`
 47	TagPushEvents            bool       `json:"tag_push_events"`
 48	NoteEvents               bool       `json:"note_events"`
 49	ConfidentialNoteEvents   bool       `json:"confidential_note_events"`
 50	PipelineEvents           bool       `json:"pipeline_events"`
 51	JobEvents                bool       `json:"job_events"`
 52	WikiPageEvents           bool       `json:"wiki_page_events"`
 53}
 54
 55// SetGitLabCIServiceOptions represents the available SetGitLabCIService()
 56// options.
 57//
 58// GitLab API docs:
 59// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
 60type SetGitLabCIServiceOptions struct {
 61	Token      *string `url:"token,omitempty" json:"token,omitempty"`
 62	ProjectURL *string `url:"project_url,omitempty" json:"project_url,omitempty"`
 63}
 64
 65// SetGitLabCIService sets GitLab CI service for a project.
 66//
 67// GitLab API docs:
 68// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
 69func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCIServiceOptions, options ...OptionFunc) (*Response, error) {
 70	project, err := parseID(pid)
 71	if err != nil {
 72		return nil, err
 73	}
 74	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
 75
 76	req, err := s.client.NewRequest("PUT", u, opt, options)
 77	if err != nil {
 78		return nil, err
 79	}
 80
 81	return s.client.Do(req, nil)
 82}
 83
 84// DeleteGitLabCIService deletes GitLab CI service settings for a project.
 85//
 86// GitLab API docs:
 87// https://docs.gitlab.com/ce/api/services.html#delete-gitlab-ci-service
 88func (s *ServicesService) DeleteGitLabCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
 89	project, err := parseID(pid)
 90	if err != nil {
 91		return nil, err
 92	}
 93	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
 94
 95	req, err := s.client.NewRequest("DELETE", u, nil, options)
 96	if err != nil {
 97		return nil, err
 98	}
 99
100	return s.client.Do(req, nil)
101}
102
103// SetHipChatServiceOptions represents the available SetHipChatService()
104// options.
105//
106// GitLab API docs:
107// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
108type SetHipChatServiceOptions struct {
109	Token *string `url:"token,omitempty" json:"token,omitempty" `
110	Room  *string `url:"room,omitempty" json:"room,omitempty"`
111}
112
113// SetHipChatService sets HipChat service for a project
114//
115// GitLab API docs:
116// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
117func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServiceOptions, options ...OptionFunc) (*Response, error) {
118	project, err := parseID(pid)
119	if err != nil {
120		return nil, err
121	}
122	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
123
124	req, err := s.client.NewRequest("PUT", u, opt, options)
125	if err != nil {
126		return nil, err
127	}
128
129	return s.client.Do(req, nil)
130}
131
132// DeleteHipChatService deletes HipChat service for project.
133//
134// GitLab API docs:
135// https://docs.gitlab.com/ce/api/services.html#delete-hipchat-service
136func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...OptionFunc) (*Response, error) {
137	project, err := parseID(pid)
138	if err != nil {
139		return nil, err
140	}
141	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
142
143	req, err := s.client.NewRequest("DELETE", u, nil, options)
144	if err != nil {
145		return nil, err
146	}
147
148	return s.client.Do(req, nil)
149}
150
151// DroneCIService represents Drone CI service settings.
152//
153// GitLab API docs:
154// https://docs.gitlab.com/ce/api/services.html#drone-ci
155type DroneCIService struct {
156	Service
157	Properties *DroneCIServiceProperties `json:"properties"`
158}
159
160// DroneCIServiceProperties represents Drone CI specific properties.
161//
162// GitLab API docs:
163// https://docs.gitlab.com/ce/api/services.html#drone-ci
164type DroneCIServiceProperties struct {
165	Token                 string `json:"token"`
166	DroneURL              string `json:"drone_url"`
167	EnableSSLVerification bool   `json:"enable_ssl_verification"`
168}
169
170// GetDroneCIService gets Drone CI service settings for a project.
171//
172// GitLab API docs:
173// https://docs.gitlab.com/ce/api/services.html#get-drone-ci-service-settings
174func (s *ServicesService) GetDroneCIService(pid interface{}, options ...OptionFunc) (*DroneCIService, *Response, error) {
175	project, err := parseID(pid)
176	if err != nil {
177		return nil, nil, err
178	}
179	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
180
181	req, err := s.client.NewRequest("GET", u, nil, options)
182	if err != nil {
183		return nil, nil, err
184	}
185
186	svc := new(DroneCIService)
187	resp, err := s.client.Do(req, svc)
188	if err != nil {
189		return nil, resp, err
190	}
191
192	return svc, resp, err
193}
194
195// SetDroneCIServiceOptions represents the available SetDroneCIService()
196// options.
197//
198// GitLab API docs:
199// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
200type SetDroneCIServiceOptions struct {
201	Token                 *string `url:"token" json:"token" `
202	DroneURL              *string `url:"drone_url" json:"drone_url"`
203	EnableSSLVerification *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
204}
205
206// SetDroneCIService sets Drone CI service for a project.
207//
208// GitLab API docs:
209// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
210func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServiceOptions, options ...OptionFunc) (*Response, error) {
211	project, err := parseID(pid)
212	if err != nil {
213		return nil, err
214	}
215	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
216
217	req, err := s.client.NewRequest("PUT", u, opt, options)
218	if err != nil {
219		return nil, err
220	}
221
222	return s.client.Do(req, nil)
223}
224
225// DeleteDroneCIService deletes Drone CI service settings for a project.
226//
227// GitLab API docs:
228// https://docs.gitlab.com/ce/api/services.html#delete-drone-ci-service
229func (s *ServicesService) DeleteDroneCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
230	project, err := parseID(pid)
231	if err != nil {
232		return nil, err
233	}
234	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
235
236	req, err := s.client.NewRequest("DELETE", u, nil, options)
237	if err != nil {
238		return nil, err
239	}
240
241	return s.client.Do(req, nil)
242}
243
244// SlackService represents Slack service settings.
245//
246// GitLab API docs:
247// https://docs.gitlab.com/ce/api/services.html#slack
248type SlackService struct {
249	Service
250	Properties *SlackServiceProperties `json:"properties"`
251}
252
253// SlackServiceProperties represents Slack specific properties.
254//
255// GitLab API docs:
256// https://docs.gitlab.com/ce/api/services.html#slack
257type SlackServiceProperties struct {
258	// Note: NotifyOnlyBrokenPipelines and NotifyOnlyDefaultBranch are not
259	// just "bool" because in some cases gitlab returns
260	// "notify_only_broken_pipelines": true, and in other cases
261	// "notify_only_broken_pipelines": "1". The same is for
262	// "notify_only_default_branch" field.
263	// We need to handle this, until the bug will be fixed.
264	// Ref: https://gitlab.com/gitlab-org/gitlab-ce/issues/50122
265
266	NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines,omitempty"`
267	NotifyOnlyDefaultBranch   BoolValue `json:"notify_only_default_branch,omitempty"`
268	WebHook                   string    `json:"webhook,omitempty"`
269	Username                  string    `json:"username,omitempty"`
270	Channel                   string    `json:"channel,omitempty"`
271	PushChannel               string    `json:"push_channel,omitempty"`
272	IssueChannel              string    `json:"issue_channel,omitempty"`
273	ConfidentialIssueChannel  string    `json:"confidential_issue_channel,omitempty"`
274	MergeRequestChannel       string    `json:"merge_request_channel,omitempty"`
275	NoteChannel               string    `json:"note_channel,omitempty"`
276	ConfidentialNoteChannel   string    `json:"confidential_note_channel,omitempty"`
277	TagPushChannel            string    `json:"tag_push_channel,omitempty"`
278	PipelineChannel           string    `json:"pipeline_channel,omitempty"`
279	WikiPageChannel           string    `json:"wiki_page_channel,omitempty"`
280}
281
282// GetSlackService gets Slack service settings for a project.
283//
284// GitLab API docs:
285// https://docs.gitlab.com/ce/api/services.html#get-slack-service-settings
286func (s *ServicesService) GetSlackService(pid interface{}, options ...OptionFunc) (*SlackService, *Response, error) {
287	project, err := parseID(pid)
288	if err != nil {
289		return nil, nil, err
290	}
291	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
292
293	req, err := s.client.NewRequest("GET", u, nil, options)
294	if err != nil {
295		return nil, nil, err
296	}
297
298	svc := new(SlackService)
299	resp, err := s.client.Do(req, svc)
300	if err != nil {
301		return nil, resp, err
302	}
303
304	return svc, resp, err
305}
306
307// SetSlackServiceOptions represents the available SetSlackService()
308// options.
309//
310// GitLab API docs:
311// https://docs.gitlab.com/ce/api/services.html#edit-slack-service
312type SetSlackServiceOptions struct {
313	WebHook                   *string `url:"webhook,omitempty" json:"webhook,omitempty"`
314	Username                  *string `url:"username,omitempty" json:"username,omitempty"`
315	Channel                   *string `url:"channel,omitempty" json:"channel,omitempty"`
316	NotifyOnlyBrokenPipelines *bool   `url:"notify_only_broken_pipelines,omitempty" json:"notify_only_broken_pipelines,omitempty"`
317	NotifyOnlyDefaultBranch   *bool   `url:"notify_only_default_branch,omitempty" json:"notify_only_default_branch,omitempty"`
318	PushEvents                *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
319	PushChannel               *string `url:"push_channel,omitempty" json:"push_channel,omitempty"`
320	IssuesEvents              *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
321	IssueChannel              *string `url:"issue_channel,omitempty" json:"issue_channel,omitempty"`
322	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
323	ConfidentialIssueChannel  *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"`
324	MergeRequestsEvents       *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
325	MergeRequestChannel       *string `url:"merge_request_channel,omitempty" json:"merge_request_channel,omitempty"`
326	TagPushEvents             *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
327	TagPushChannel            *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"`
328	NoteEvents                *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
329	NoteChannel               *string `url:"note_channel,omitempty" json:"note_channel,omitempty"`
330	ConfidentialNoteEvents    *bool   `url:"confidential_note_events" json:"confidential_note_events"`
331	// TODO: Currently, GitLab ignores this option (not implemented yet?), so
332	// there is no way to set it. Uncomment when this is fixed.
333	// See: https://gitlab.com/gitlab-org/gitlab-ce/issues/49730
334	//ConfidentialNoteChannel   *string `json:"confidential_note_channel,omitempty"`
335	PipelineEvents  *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
336	PipelineChannel *string `url:"pipeline_channel,omitempty" json:"pipeline_channel,omitempty"`
337	WikiPageChannel *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"`
338	WikiPageEvents  *bool   `url:"wiki_page_events" json:"wiki_page_events"`
339}
340
341// SetSlackService sets Slack service for a project
342//
343// GitLab API docs:
344// https://docs.gitlab.com/ce/api/services.html#edit-slack-service
345func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) {
346	project, err := parseID(pid)
347	if err != nil {
348		return nil, err
349	}
350	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
351
352	req, err := s.client.NewRequest("PUT", u, opt, options)
353	if err != nil {
354		return nil, err
355	}
356
357	return s.client.Do(req, nil)
358}
359
360// DeleteSlackService deletes Slack service for project.
361//
362// GitLab API docs:
363// https://docs.gitlab.com/ce/api/services.html#delete-slack-service
364func (s *ServicesService) DeleteSlackService(pid interface{}, options ...OptionFunc) (*Response, error) {
365	project, err := parseID(pid)
366	if err != nil {
367		return nil, err
368	}
369	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
370
371	req, err := s.client.NewRequest("DELETE", u, nil, options)
372	if err != nil {
373		return nil, err
374	}
375
376	return s.client.Do(req, nil)
377}
378
379// JiraService represents Jira service settings.
380//
381// GitLab API docs:
382// https://docs.gitlab.com/ce/api/services.html#jira
383type JiraService struct {
384	Service
385	Properties *JiraServiceProperties `json:"properties"`
386}
387
388// JiraServiceProperties represents Jira specific properties.
389//
390// GitLab API docs:
391// https://docs.gitlab.com/ce/api/services.html#jira
392type JiraServiceProperties struct {
393	URL                   string `json:"url,omitempty"`
394	APIURL                string `json:"api_url,omitempty"`
395	ProjectKey            string `json:"project_key,omitempty" `
396	Username              string `json:"username,omitempty" `
397	Password              string `json:"password,omitempty" `
398	JiraIssueTransitionID string `json:"jira_issue_transition_id,omitempty"`
399}
400
401// UnmarshalJSON decodes the Jira Service Properties.
402//
403// This allows support of JiraIssueTransitionID for both type string (>11.9) and float64 (<11.9)
404func (p *JiraServiceProperties) UnmarshalJSON(b []byte) error {
405	type Alias JiraServiceProperties
406	raw := struct {
407		*Alias
408		JiraIssueTransitionID interface{} `json:"jira_issue_transition_id"`
409	}{
410		Alias: (*Alias)(p),
411	}
412
413	if err := json.Unmarshal(b, &raw); err != nil {
414		return err
415	}
416
417	switch id := raw.JiraIssueTransitionID.(type) {
418	case nil:
419		// No action needed.
420	case string:
421		p.JiraIssueTransitionID = id
422	case float64:
423		p.JiraIssueTransitionID = strconv.Itoa(int(id))
424	default:
425		return fmt.Errorf("failed to unmarshal JiraTransitionID of type: %T", id)
426	}
427
428	return nil
429}
430
431// GetJiraService gets Jira service settings for a project.
432//
433// GitLab API docs:
434// https://docs.gitlab.com/ce/api/services.html#get-jira-service-settings
435func (s *ServicesService) GetJiraService(pid interface{}, options ...OptionFunc) (*JiraService, *Response, error) {
436	project, err := parseID(pid)
437	if err != nil {
438		return nil, nil, err
439	}
440	u := fmt.Sprintf("projects/%s/services/jira", pathEscape(project))
441
442	req, err := s.client.NewRequest("GET", u, nil, options)
443	if err != nil {
444		return nil, nil, err
445	}
446
447	svc := new(JiraService)
448	resp, err := s.client.Do(req, svc)
449	if err != nil {
450		return nil, resp, err
451	}
452
453	return svc, resp, err
454}
455
456// SetJiraServiceOptions represents the available SetJiraService()
457// options.
458//
459// GitLab API docs:
460// https://docs.gitlab.com/ce/api/services.html#edit-jira-service
461type SetJiraServiceOptions struct {
462	URL                   *string `url:"url,omitempty" json:"url,omitempty"`
463	APIURL                *string `url:"api_url,omitempty" json:"api_url,omitempty"`
464	ProjectKey            *string `url:"project_key,omitempty" json:"project_key,omitempty" `
465	Username              *string `url:"username,omitempty" json:"username,omitempty" `
466	Password              *string `url:"password,omitempty" json:"password,omitempty" `
467	JiraIssueTransitionID *string `url:"jira_issue_transition_id,omitempty" json:"jira_issue_transition_id,omitempty"`
468}
469
470// SetJiraService sets Jira service for a project
471//
472// GitLab API docs:
473// https://docs.gitlab.com/ce/api/services.html#edit-jira-service
474func (s *ServicesService) SetJiraService(pid interface{}, opt *SetJiraServiceOptions, options ...OptionFunc) (*Response, error) {
475	project, err := parseID(pid)
476	if err != nil {
477		return nil, err
478	}
479	u := fmt.Sprintf("projects/%s/services/jira", pathEscape(project))
480
481	req, err := s.client.NewRequest("PUT", u, opt, options)
482	if err != nil {
483		return nil, err
484	}
485
486	return s.client.Do(req, nil)
487}
488
489// DeleteJiraService deletes Jira service for project.
490//
491// GitLab API docs:
492// https://docs.gitlab.com/ce/api/services.html#delete-jira-service
493func (s *ServicesService) DeleteJiraService(pid interface{}, options ...OptionFunc) (*Response, error) {
494	project, err := parseID(pid)
495	if err != nil {
496		return nil, err
497	}
498	u := fmt.Sprintf("projects/%s/services/jira", pathEscape(project))
499
500	req, err := s.client.NewRequest("DELETE", u, nil, options)
501	if err != nil {
502		return nil, err
503	}
504
505	return s.client.Do(req, nil)
506}
507
508// JenkinsCIService represents Jenkins CI service settings.
509//
510// GitLab API docs:
511// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
512type JenkinsCIService struct {
513	Service
514	Properties *JenkinsCIServiceProperties `json:"properties"`
515}
516
517// JenkinsCIServiceProperties represents Jenkins CI specific properties.
518//
519// GitLab API docs:
520// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
521type JenkinsCIServiceProperties struct {
522	URL         string `json:"jenkins_url,omitempty"`
523	ProjectName string `json:"project_name,omitempty"`
524	Username    string `json:"username,omitempty"`
525}
526
527// GetJenkinsCIService gets Jenkins CI service settings for a project.
528//
529// GitLab API docs:
530// https://docs.gitlab.com/ee/api/services.html#get-jenkins-ci-service-settings
531func (s *ServicesService) GetJenkinsCIService(pid interface{}, options ...OptionFunc) (*JenkinsCIService, *Response, error) {
532	project, err := parseID(pid)
533	if err != nil {
534		return nil, nil, err
535	}
536	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
537
538	req, err := s.client.NewRequest("GET", u, nil, options)
539	if err != nil {
540		return nil, nil, err
541	}
542
543	svc := new(JenkinsCIService)
544	resp, err := s.client.Do(req, svc)
545	if err != nil {
546		return nil, resp, err
547	}
548
549	return svc, resp, err
550}
551
552// SetJenkinsCIServiceOptions represents the available SetJenkinsCIService()
553// options.
554//
555// GitLab API docs:
556// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
557type SetJenkinsCIServiceOptions struct {
558	URL         *string `url:"jenkins_url,omitempty" json:"jenkins_url,omitempty"`
559	ProjectName *string `url:"project_name,omitempty" json:"project_name,omitempty"`
560	Username    *string `url:"username,omitempty" json:"username,omitempty"`
561	Password    *string `url:"password,omitempty" json:"password,omitempty"`
562}
563
564// SetJenkinsCIService sets Jenkins service for a project
565//
566// GitLab API docs:
567// https://docs.gitlab.com/ee/api/services.html#create-edit-jenkins-ci-service
568func (s *ServicesService) SetJenkinsCIService(pid interface{}, opt *SetJenkinsCIServiceOptions, options ...OptionFunc) (*Response, error) {
569	project, err := parseID(pid)
570	if err != nil {
571		return nil, err
572	}
573	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
574
575	req, err := s.client.NewRequest("PUT", u, opt, options)
576	if err != nil {
577		return nil, err
578	}
579
580	return s.client.Do(req, nil)
581}
582
583// DeleteJenkinsCIService deletes Jenkins CI service for project.
584//
585// GitLab API docs:
586// https://docs.gitlab.com/ce/api/services.html#delete-jira-service
587func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
588	project, err := parseID(pid)
589	if err != nil {
590		return nil, err
591	}
592	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
593
594	req, err := s.client.NewRequest("DELETE", u, nil, options)
595	if err != nil {
596		return nil, err
597	}
598
599	return s.client.Do(req, nil)
600}
601
602// MicrosoftTeamsService represents Microsoft Teams service settings.
603//
604// GitLab API docs:
605// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
606type MicrosoftTeamsService struct {
607	Service
608	Properties *MicrosoftTeamsServiceProperties `json:"properties"`
609}
610
611// MicrosoftTeamsServiceProperties represents Microsoft Teams specific properties.
612//
613// GitLab API docs:
614// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
615type MicrosoftTeamsServiceProperties struct {
616	WebHook string `json:"webhook"`
617}
618
619// GetMicrosoftTeamsService gets MicrosoftTeams service settings for a project.
620//
621// GitLab API docs:
622// https://docs.gitlab.com/ce/api/services.html#get-microsoft-teams-service-settings
623func (s *ServicesService) GetMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*MicrosoftTeamsService, *Response, error) {
624	project, err := parseID(pid)
625	if err != nil {
626		return nil, nil, err
627	}
628	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
629
630	req, err := s.client.NewRequest("GET", u, nil, options)
631	if err != nil {
632		return nil, nil, err
633	}
634
635	svc := new(MicrosoftTeamsService)
636	resp, err := s.client.Do(req, svc)
637	if err != nil {
638		return nil, resp, err
639	}
640
641	return svc, resp, err
642}
643
644// SetMicrosoftTeamsServiceOptions represents the available SetMicrosoftTeamsService()
645// options.
646//
647// GitLab API docs:
648// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
649type SetMicrosoftTeamsServiceOptions struct {
650	WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty"`
651}
652
653// SetMicrosoftTeamsService sets Microsoft Teams service for a project
654//
655// GitLab API docs:
656// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
657func (s *ServicesService) SetMicrosoftTeamsService(pid interface{}, opt *SetMicrosoftTeamsServiceOptions, options ...OptionFunc) (*Response, error) {
658	project, err := parseID(pid)
659	if err != nil {
660		return nil, err
661	}
662	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
663
664	req, err := s.client.NewRequest("PUT", u, opt, options)
665	if err != nil {
666		return nil, err
667	}
668	return s.client.Do(req, nil)
669}
670
671// DeleteMicrosoftTeamsService deletes Microsoft Teams service for project.
672//
673// GitLab API docs:
674// https://docs.gitlab.com/ce/api/services.html#delete-microsoft-teams-service
675func (s *ServicesService) DeleteMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*Response, error) {
676	project, err := parseID(pid)
677	if err != nil {
678		return nil, err
679	}
680	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
681
682	req, err := s.client.NewRequest("DELETE", u, nil, options)
683	if err != nil {
684		return nil, err
685	}
686
687	return s.client.Do(req, nil)
688}
689
690// ExternalWikiService represents External Wiki service settings.
691//
692// GitLab API docs:
693// https://docs.gitlab.com/ce/api/services.html#external-wiki
694type ExternalWikiService struct {
695	Service
696	Properties *ExternalWikiServiceProperties `json:"properties"`
697}
698
699// ExternalWikiServiceProperties represents External Wiki specific properties.
700//
701// GitLab API docs:
702// https://docs.gitlab.com/ce/api/services.html#external-wiki
703type ExternalWikiServiceProperties struct {
704	ExternalWikiURL string `json:"external_wiki_url"`
705}
706
707// GetExternalWikiService gets External Wiki service settings for a project.
708//
709// GitLab API docs:
710// https://docs.gitlab.com/ce/api/services.html#get-external-wiki-service-settings
711func (s *ServicesService) GetExternalWikiService(pid interface{}, options ...OptionFunc) (*ExternalWikiService, *Response, error) {
712	project, err := parseID(pid)
713	if err != nil {
714		return nil, nil, err
715	}
716	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
717
718	req, err := s.client.NewRequest("GET", u, nil, options)
719	if err != nil {
720		return nil, nil, err
721	}
722
723	svc := new(ExternalWikiService)
724	resp, err := s.client.Do(req, svc)
725	if err != nil {
726		return nil, resp, err
727	}
728
729	return svc, resp, err
730}
731
732// SetExternalWikiServiceOptions represents the available SetExternalWikiService()
733// options.
734//
735// GitLab API docs:
736// https://docs.gitlab.com/ce/api/services.html#createedit-external-wiki-service
737type SetExternalWikiServiceOptions struct {
738	ExternalWikiURL *string `url:"external_wiki_url,omitempty" json:"external_wiki_url,omitempty"`
739}
740
741// SetExternalWikiService sets External Wiki service for a project.
742//
743// GitLab API docs:
744// https://docs.gitlab.com/ce/api/services.html#createedit-external-wiki-service
745func (s *ServicesService) SetExternalWikiService(pid interface{}, opt *SetExternalWikiServiceOptions, options ...OptionFunc) (*Response, error) {
746	project, err := parseID(pid)
747	if err != nil {
748		return nil, err
749	}
750	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
751
752	req, err := s.client.NewRequest("PUT", u, opt, options)
753	if err != nil {
754		return nil, err
755	}
756
757	return s.client.Do(req, nil)
758}
759
760// DeleteExternalWikiService deletes External Wiki service for project.
761//
762// GitLab API docs:
763// https://docs.gitlab.com/ce/api/services.html#delete-external-wiki-service
764func (s *ServicesService) DeleteExternalWikiService(pid interface{}, options ...OptionFunc) (*Response, error) {
765	project, err := parseID(pid)
766	if err != nil {
767		return nil, err
768	}
769	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
770
771	req, err := s.client.NewRequest("DELETE", u, nil, options)
772	if err != nil {
773		return nil, err
774	}
775
776	return s.client.Do(req, nil)
777}