Repository: xanzy/go-gitlab
Pull request #703 (2019-10-08 12:59:22)

add service pipelines-email

svanharmelen: @itscaro same for this PR. I rebased and updated the code a little. If you can check it and let me know if it still works for you, then I will merge the PR and release a new version. Thanks!

Patch:
diff --git a/services.go b/services.go
index b898ab1..ba64576 100644
--- a/services.go
+++ b/services.go
@@ -52,26 +52,71 @@ type Service struct {
 	WikiPageEvents           bool       `json:"wiki_page_events"`
 }
 
-// SetGitLabCIServiceOptions represents the available SetGitLabCIService()
+// DroneCIService represents Drone CI service settings.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/services.html#drone-ci
+type DroneCIService struct {
+	Service
+	Properties *DroneCIServiceProperties `json:"properties"`
+}
+
+// DroneCIServiceProperties represents Drone CI specific properties.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/services.html#drone-ci
+type DroneCIServiceProperties struct {
+	Token                 string `json:"token"`
+	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/ce/api/services.html#get-drone-ci-service-settings
+func (s *ServicesService) GetDroneCIService(pid interface{}, options ...OptionFunc) (*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("GET", 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, err
+}
+
+// SetDroneCIServiceOptions represents the available SetDroneCIService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.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"`
+// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
+type SetDroneCIServiceOptions struct {
+	Token                 *string `url:"token" json:"token" `
+	DroneURL              *string `url:"drone_url" json:"drone_url"`
+	EnableSSLVerification *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
 }
 
-// SetGitLabCIService sets GitLab CI service for a project.
+// SetDroneCIService sets Drone CI service for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
-func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCIServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
+func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
@@ -81,16 +126,105 @@ func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCISe
 	return s.client.Do(req, nil)
 }
 
-// DeleteGitLabCIService deletes GitLab CI service settings for a project.
+// DeleteDroneCIService deletes Drone CI service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-gitlab-ci-service
-func (s *ServicesService) DeleteGitLabCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-drone-ci-service
+func (s *ServicesService) DeleteDroneCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
+
+	req, err := s.client.NewRequest("DELETE", 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/ce/api/services.html#external-wiki
+type ExternalWikiService struct {
+	Service
+	Properties *ExternalWikiServiceProperties `json:"properties"`
+}
+
+// ExternalWikiServiceProperties represents External Wiki specific properties.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/services.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/ce/api/services.html#get-external-wiki-service-settings
+func (s *ServicesService) GetExternalWikiService(pid interface{}, options ...OptionFunc) (*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("GET", 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, err
+}
+
+// SetExternalWikiServiceOptions represents the available SetExternalWikiService()
+// options.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/services.html#createedit-external-wiki-service
+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/ce/api/services.html#createedit-external-wiki-service
+func (s *ServicesService) SetExternalWikiService(pid interface{}, opt *SetExternalWikiServiceOptions, options ...OptionFunc) (*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("PUT", 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/ce/api/services.html#delete-external-wiki-service
+func (s *ServicesService) DeleteExternalWikiService(pid interface{}, options ...OptionFunc) (*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("DELETE", u, nil, options)
 	if err != nil {
@@ -192,26 +326,26 @@ func (s *ServicesService) DeleteGithubService(pid interface{}, options ...Option
 	return s.client.Do(req, nil)
 }
 
-// SetHipChatServiceOptions represents the available SetHipChatService()
+// SetGitLabCIServiceOptions represents the available SetGitLabCIService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
-type SetHipChatServiceOptions struct {
-	Token *string `url:"token,omitempty" json:"token,omitempty" `
-	Room  *string `url:"room,omitempty" json:"room,omitempty"`
+// https://docs.gitlab.com/ce/api/services.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"`
 }
 
-// SetHipChatService sets HipChat service for a project
+// SetGitLabCIService sets GitLab CI service for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
-func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
+func (s *ServicesService) SetGitLabCIService(pid interface{}, opt *SetGitLabCIServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
@@ -221,16 +355,16 @@ func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServ
 	return s.client.Do(req, nil)
 }
 
-// DeleteHipChatService deletes HipChat service for project.
+// DeleteGitLabCIService deletes GitLab CI service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-hipchat-service
-func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-gitlab-ci-service
+func (s *ServicesService) DeleteGitLabCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/gitlab-ci", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {
@@ -240,71 +374,26 @@ func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...Optio
 	return s.client.Do(req, nil)
 }
 
-// DroneCIService represents Drone CI service settings.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#drone-ci
-type DroneCIService struct {
-	Service
-	Properties *DroneCIServiceProperties `json:"properties"`
-}
-
-// DroneCIServiceProperties represents Drone CI specific properties.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#drone-ci
-type DroneCIServiceProperties struct {
-	Token                 string `json:"token"`
-	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/ce/api/services.html#get-drone-ci-service-settings
-func (s *ServicesService) GetDroneCIService(pid interface{}, options ...OptionFunc) (*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("GET", 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, err
-}
-
-// SetDroneCIServiceOptions represents the available SetDroneCIService()
+// SetHipChatServiceOptions represents the available SetHipChatService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
-type SetDroneCIServiceOptions struct {
-	Token                 *string `url:"token" json:"token" `
-	DroneURL              *string `url:"drone_url" json:"drone_url"`
-	EnableSSLVerification *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
+// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
+type SetHipChatServiceOptions struct {
+	Token *string `url:"token,omitempty" json:"token,omitempty" `
+	Room  *string `url:"room,omitempty" json:"room,omitempty"`
 }
 
-// SetDroneCIService sets Drone CI service for a project.
+// SetHipChatService sets HipChat service for a project
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#createedit-drone-ci-service
-func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#edit-hipchat-service
+func (s *ServicesService) SetHipChatService(pid interface{}, opt *SetHipChatServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
@@ -314,16 +403,16 @@ func (s *ServicesService) SetDroneCIService(pid interface{}, opt *SetDroneCIServ
 	return s.client.Do(req, nil)
 }
 
-// DeleteDroneCIService deletes Drone CI service settings for a project.
+// DeleteHipChatService deletes HipChat service for project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-drone-ci-service
-func (s *ServicesService) DeleteDroneCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-hipchat-service
+func (s *ServicesService) DeleteHipChatService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/drone-ci", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/hipchat", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {
@@ -333,55 +422,42 @@ func (s *ServicesService) DeleteDroneCIService(pid interface{}, options ...Optio
 	return s.client.Do(req, nil)
 }
 
-// SlackService represents Slack service settings.
+// JenkinsCIService represents Jenkins CI service settings.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#slack
-type SlackService struct {
+// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
+type JenkinsCIService struct {
 	Service
-	Properties *SlackServiceProperties `json:"properties"`
-}
-
-// SlackServiceProperties represents Slack specific properties.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#slack
-type SlackServiceProperties struct {
-	WebHook                   string    `json:"webhook,omitempty"`
-	Username                  string    `json:"username,omitempty"`
-	Channel                   string    `json:"channel,omitempty"`
-	NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines,omitempty"`
-	NotifyOnlyDefaultBranch   BoolValue `json:"notify_only_default_branch,omitempty"`
-	BranchesToBeNotified      string    `json:"branches_to_be_notified,omitempty"`
-	ConfidentialIssueChannel  string    `json:"confidential_issue_channel,omitempty"`
-	ConfidentialNoteChannel   string    `json:"confidential_note_channel,omitempty"`
-	DeploymentChannel         string    `json:"deployment_channel,omitempty"`
-	IssueChannel              string    `json:"issue_channel,omitempty"`
-	MergeRequestChannel       string    `json:"merge_request_channel,omitempty"`
-	NoteChannel               string    `json:"note_channel,omitempty"`
-	TagPushChannel            string    `json:"tag_push_channel,omitempty"`
-	PipelineChannel           string    `json:"pipeline_channel,omitempty"`
-	PushChannel               string    `json:"push_channel,omitempty"`
-	WikiPageChannel           string    `json:"wiki_page_channel,omitempty"`
+	Properties *JenkinsCIServiceProperties `json:"properties"`
 }
 
-// GetSlackService gets Slack service settings for a project.
+// JenkinsCIServiceProperties represents Jenkins CI specific properties.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#get-slack-service-settings
-func (s *ServicesService) GetSlackService(pid interface{}, options ...OptionFunc) (*SlackService, *Response, error) {
+// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
+type JenkinsCIServiceProperties struct {
+	URL         string `json:"jenkins_url,omitempty"`
+	ProjectName string `json:"project_name,omitempty"`
+	Username    string `json:"username,omitempty"`
+}
+
+// GetJenkinsCIService gets Jenkins CI service settings for a project.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/services.html#get-jenkins-ci-service-settings
+func (s *ServicesService) GetJenkinsCIService(pid interface{}, options ...OptionFunc) (*JenkinsCIService, *Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
 
 	req, err := s.client.NewRequest("GET", u, nil, options)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	svc := new(SlackService)
+	svc := new(JenkinsCIService)
 	resp, err := s.client.Do(req, svc)
 	if err != nil {
 		return nil, resp, err
@@ -390,53 +466,28 @@ func (s *ServicesService) GetSlackService(pid interface{}, options ...OptionFunc
 	return svc, resp, err
 }
 
-// SetSlackServiceOptions represents the available SetSlackService()
+// SetJenkinsCIServiceOptions represents the available SetJenkinsCIService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.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"`
-	ConfidentialIssueChannel  *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"`
-	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
-	// TODO: Currently, GitLab ignores this option (not implemented yet?), so
-	// there is no way to set it. Uncomment when this is fixed.
-	// See: https://gitlab.com/gitlab-org/gitlab-ce/issues/49730
-	//ConfidentialNoteChannel   *string `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"`
-	TagPushChannel         *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"`
-	TagPushEvents          *bool   `url:"tag_push_events,omitempty" json:"tag_push_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"`
-	WikiPageChannel        *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"`
-	WikiPageEvents         *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
+// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
+type SetJenkinsCIServiceOptions struct {
+	URL         *string `url:"jenkins_url,omitempty" json:"jenkins_url,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"`
 }
 
-// SetSlackService sets Slack service for a project
+// SetJenkinsCIService sets Jenkins service for a project
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#edit-slack-service
-func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ee/api/services.html#create-edit-jenkins-ci-service
+func (s *ServicesService) SetJenkinsCIService(pid interface{}, opt *SetJenkinsCIServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
@@ -446,16 +497,16 @@ func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceO
 	return s.client.Do(req, nil)
 }
 
-// DeleteSlackService deletes Slack service for project.
+// DeleteJenkinsCIService deletes Jenkins CI service for project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-slack-service
-func (s *ServicesService) DeleteSlackService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-jira-service
+func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {
@@ -594,42 +645,40 @@ func (s *ServicesService) DeleteJiraService(pid interface{}, options ...OptionFu
 	return s.client.Do(req, nil)
 }
 
-// JenkinsCIService represents Jenkins CI service settings.
+// MicrosoftTeamsService represents Microsoft Teams service settings.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
-type JenkinsCIService struct {
+// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
+type MicrosoftTeamsService struct {
 	Service
-	Properties *JenkinsCIServiceProperties `json:"properties"`
+	Properties *MicrosoftTeamsServiceProperties `json:"properties"`
 }
 
-// JenkinsCIServiceProperties represents Jenkins CI specific properties.
+// MicrosoftTeamsServiceProperties represents Microsoft Teams specific properties.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
-type JenkinsCIServiceProperties struct {
-	URL         string `json:"jenkins_url,omitempty"`
-	ProjectName string `json:"project_name,omitempty"`
-	Username    string `json:"username,omitempty"`
+// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
+type MicrosoftTeamsServiceProperties struct {
+	WebHook string `json:"webhook"`
 }
 
-// GetJenkinsCIService gets Jenkins CI service settings for a project.
+// GetMicrosoftTeamsService gets MicrosoftTeams service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/services.html#get-jenkins-ci-service-settings
-func (s *ServicesService) GetJenkinsCIService(pid interface{}, options ...OptionFunc) (*JenkinsCIService, *Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#get-microsoft-teams-service-settings
+func (s *ServicesService) GetMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*MicrosoftTeamsService, *Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
 
 	req, err := s.client.NewRequest("GET", u, nil, options)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	svc := new(JenkinsCIService)
+	svc := new(MicrosoftTeamsService)
 	resp, err := s.client.Do(req, svc)
 	if err != nil {
 		return nil, resp, err
@@ -638,47 +687,43 @@ func (s *ServicesService) GetJenkinsCIService(pid interface{}, options ...Option
 	return svc, resp, err
 }
 
-// SetJenkinsCIServiceOptions represents the available SetJenkinsCIService()
+// SetMicrosoftTeamsServiceOptions represents the available SetMicrosoftTeamsService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/services.html#jenkins-ci
-type SetJenkinsCIServiceOptions struct {
-	URL         *string `url:"jenkins_url,omitempty" json:"jenkins_url,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"`
+// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
+type SetMicrosoftTeamsServiceOptions struct {
+	WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty"`
 }
 
-// SetJenkinsCIService sets Jenkins service for a project
+// SetMicrosoftTeamsService sets Microsoft Teams service for a project
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/services.html#create-edit-jenkins-ci-service
-func (s *ServicesService) SetJenkinsCIService(pid interface{}, opt *SetJenkinsCIServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
+func (s *ServicesService) SetMicrosoftTeamsService(pid interface{}, opt *SetMicrosoftTeamsServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
 		return nil, err
 	}
-
 	return s.client.Do(req, nil)
 }
 
-// DeleteJenkinsCIService deletes Jenkins CI service for project.
+// DeleteMicrosoftTeamsService deletes Microsoft Teams service for project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-jira-service
-func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-microsoft-teams-service
+func (s *ServicesService) DeleteMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/jenkins", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {
@@ -688,40 +733,42 @@ func (s *ServicesService) DeleteJenkinsCIService(pid interface{}, options ...Opt
 	return s.client.Do(req, nil)
 }
 
-// MicrosoftTeamsService represents Microsoft Teams service settings.
+// PipelinesEmailService represents Pipelines Email service settings.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
-type MicrosoftTeamsService struct {
+// https://docs.gitlab.com/ee/api/services.html#pipeline-emails
+type PipelinesEmailService struct {
 	Service
-	Properties *MicrosoftTeamsServiceProperties `json:"properties"`
+	Properties *PipelinesEmailProperties `json:"properties"`
 }
 
-// MicrosoftTeamsServiceProperties represents Microsoft Teams specific properties.
+// PipelinesEmailProperties represents PipelinesEmail specific properties.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#microsoft-teams
-type MicrosoftTeamsServiceProperties struct {
-	WebHook string `json:"webhook"`
+// https://docs.gitlab.com/ee/api/services.html#pipeline-emails
+type PipelinesEmailProperties struct {
+	Recipients                string    `json:"recipients,omitempty"`
+	NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines,omitempty"`
+	NotifyOnlyDefaultBranch   BoolValue `json:"notify_only_default_branch,omitempty"`
 }
 
-// GetMicrosoftTeamsService gets MicrosoftTeams service settings for a project.
+// GetPipelinesEmailService gets Pipelines Email service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#get-microsoft-teams-service-settings
-func (s *ServicesService) GetMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*MicrosoftTeamsService, *Response, error) {
+// https://docs.gitlab.com/ee/api/services.html#get-pipeline-emails-service-settings
+func (s *ServicesService) GetPipelinesEmailService(pid interface{}, options ...OptionFunc) (*PipelinesEmailService, *Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/pipelines-email", pathEscape(project))
 
 	req, err := s.client.NewRequest("GET", u, nil, options)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	svc := new(MicrosoftTeamsService)
+	svc := new(PipelinesEmailService)
 	resp, err := s.client.Do(req, svc)
 	if err != nil {
 		return nil, resp, err
@@ -730,43 +777,49 @@ func (s *ServicesService) GetMicrosoftTeamsService(pid interface{}, options ...O
 	return svc, resp, err
 }
 
-// SetMicrosoftTeamsServiceOptions represents the available SetMicrosoftTeamsService()
+// SetPipelinesEmailServiceOptions represents the available SetPipelinesEmailService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
-type SetMicrosoftTeamsServiceOptions struct {
-	WebHook *string `url:"webhook,omitempty" json:"webhook,omitempty"`
+// https://docs.gitlab.com/ee/api/services.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"`
 }
 
-// SetMicrosoftTeamsService sets Microsoft Teams service for a project
+// SetPipelinesEmailService sets Pipelines Email service for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#create-edit-microsoft-teams-service
-func (s *ServicesService) SetMicrosoftTeamsService(pid interface{}, opt *SetMicrosoftTeamsServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ee/api/services.html#pipeline-emails
+func (s *ServicesService) SetPipelinesEmailService(pid interface{}, opt *SetPipelinesEmailServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/pipelines-email", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
 		return nil, err
 	}
+
 	return s.client.Do(req, nil)
 }
 
-// DeleteMicrosoftTeamsService deletes Microsoft Teams service for project.
+// DeletePipelinesEmailService deletes Pipelines Email service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-microsoft-teams-service
-func (s *ServicesService) DeleteMicrosoftTeamsService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ee/api/services.html#delete-pipeline-emails-service
+func (s *ServicesService) DeletePipelinesEmailService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/microsoft-teams", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/pipelines-email", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {
@@ -776,40 +829,55 @@ func (s *ServicesService) DeleteMicrosoftTeamsService(pid interface{}, options .
 	return s.client.Do(req, nil)
 }
 
-// ExternalWikiService represents External Wiki service settings.
+// SlackService represents Slack service settings.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#external-wiki
-type ExternalWikiService struct {
+// https://docs.gitlab.com/ce/api/services.html#slack
+type SlackService struct {
 	Service
-	Properties *ExternalWikiServiceProperties `json:"properties"`
+	Properties *SlackServiceProperties `json:"properties"`
 }
 
-// ExternalWikiServiceProperties represents External Wiki specific properties.
+// SlackServiceProperties represents Slack specific properties.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#external-wiki
-type ExternalWikiServiceProperties struct {
-	ExternalWikiURL string `json:"external_wiki_url"`
+// https://docs.gitlab.com/ce/api/services.html#slack
+type SlackServiceProperties struct {
+	WebHook                   string    `json:"webhook,omitempty"`
+	Username                  string    `json:"username,omitempty"`
+	Channel                   string    `json:"channel,omitempty"`
+	NotifyOnlyBrokenPipelines BoolValue `json:"notify_only_broken_pipelines,omitempty"`
+	NotifyOnlyDefaultBranch   BoolValue `json:"notify_only_default_branch,omitempty"`
+	BranchesToBeNotified      string    `json:"branches_to_be_notified,omitempty"`
+	ConfidentialIssueChannel  string    `json:"confidential_issue_channel,omitempty"`
+	ConfidentialNoteChannel   string    `json:"confidential_note_channel,omitempty"`
+	DeploymentChannel         string    `json:"deployment_channel,omitempty"`
+	IssueChannel              string    `json:"issue_channel,omitempty"`
+	MergeRequestChannel       string    `json:"merge_request_channel,omitempty"`
+	NoteChannel               string    `json:"note_channel,omitempty"`
+	TagPushChannel            string    `json:"tag_push_channel,omitempty"`
+	PipelineChannel           string    `json:"pipeline_channel,omitempty"`
+	PushChannel               string    `json:"push_channel,omitempty"`
+	WikiPageChannel           string    `json:"wiki_page_channel,omitempty"`
 }
 
-// GetExternalWikiService gets External Wiki service settings for a project.
+// GetSlackService gets Slack service settings for a project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#get-external-wiki-service-settings
-func (s *ServicesService) GetExternalWikiService(pid interface{}, options ...OptionFunc) (*ExternalWikiService, *Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#get-slack-service-settings
+func (s *ServicesService) GetSlackService(pid interface{}, options ...OptionFunc) (*SlackService, *Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
 
 	req, err := s.client.NewRequest("GET", u, nil, options)
 	if err != nil {
 		return nil, nil, err
 	}
 
-	svc := new(ExternalWikiService)
+	svc := new(SlackService)
 	resp, err := s.client.Do(req, svc)
 	if err != nil {
 		return nil, resp, err
@@ -818,25 +886,53 @@ func (s *ServicesService) GetExternalWikiService(pid interface{}, options ...Opt
 	return svc, resp, err
 }
 
-// SetExternalWikiServiceOptions represents the available SetExternalWikiService()
+// SetSlackServiceOptions represents the available SetSlackService()
 // options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#createedit-external-wiki-service
-type SetExternalWikiServiceOptions struct {
-	ExternalWikiURL *string `url:"external_wiki_url,omitempty" json:"external_wiki_url,omitempty"`
+// https://docs.gitlab.com/ce/api/services.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"`
+	ConfidentialIssueChannel  *string `url:"confidential_issue_channel,omitempty" json:"confidential_issue_channel,omitempty"`
+	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
+	// TODO: Currently, GitLab ignores this option (not implemented yet?), so
+	// there is no way to set it. Uncomment when this is fixed.
+	// See: https://gitlab.com/gitlab-org/gitlab-ce/issues/49730
+	//ConfidentialNoteChannel   *string `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"`
+	TagPushChannel         *string `url:"tag_push_channel,omitempty" json:"tag_push_channel,omitempty"`
+	TagPushEvents          *bool   `url:"tag_push_events,omitempty" json:"tag_push_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"`
+	WikiPageChannel        *string `url:"wiki_page_channel,omitempty" json:"wiki_page_channel,omitempty"`
+	WikiPageEvents         *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
 }
 
-// SetExternalWikiService sets External Wiki service for a project.
+// SetSlackService sets Slack service for a project
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#createedit-external-wiki-service
-func (s *ServicesService) SetExternalWikiService(pid interface{}, opt *SetExternalWikiServiceOptions, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#edit-slack-service
+func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
 
 	req, err := s.client.NewRequest("PUT", u, opt, options)
 	if err != nil {
@@ -846,16 +942,16 @@ func (s *ServicesService) SetExternalWikiService(pid interface{}, opt *SetExtern
 	return s.client.Do(req, nil)
 }
 
-// DeleteExternalWikiService deletes External Wiki service for project.
+// DeleteSlackService deletes Slack service for project.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ce/api/services.html#delete-external-wiki-service
-func (s *ServicesService) DeleteExternalWikiService(pid interface{}, options ...OptionFunc) (*Response, error) {
+// https://docs.gitlab.com/ce/api/services.html#delete-slack-service
+func (s *ServicesService) DeleteSlackService(pid interface{}, options ...OptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
-	u := fmt.Sprintf("projects/%s/services/external-wiki", pathEscape(project))
+	u := fmt.Sprintf("projects/%s/services/slack", pathEscape(project))
 
 	req, err := s.client.NewRequest("DELETE", u, nil, options)
 	if err != nil {


Test patch:
diff --git a/services_test.go b/services_test.go
index 70f14f1..eef51f4 100644
--- a/services_test.go
+++ b/services_test.go
@@ -56,59 +56,6 @@ func TestDeleteDroneCIService(t *testing.T) {
 	}
 }
 
-func TestGetSlackService(t *testing.T) {
-	mux, server, client := setup()
-	defer teardown(server)
-
-	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{"id":1}`)
-	})
-	want := &SlackService{Service: Service{ID: 1}}
-
-	service, _, err := client.Services.GetSlackService(1)
-	if err != nil {
-		t.Fatalf("Services.GetSlackService returns an error: %v", err)
-	}
-	if !reflect.DeepEqual(want, service) {
-		t.Errorf("Services.GetSlackService returned %+v, want %+v", service, want)
-	}
-}
-
-func TestSetSlackService(t *testing.T) {
-	mux, server, client := setup()
-	defer teardown(server)
-
-	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-	})
-
-	opt := &SetSlackServiceOptions{
-		WebHook:  String("webhook_uri"),
-		Username: String("username"),
-		Channel:  String("#development"),
-	}
-
-	_, err := client.Services.SetSlackService(1, opt)
-	if err != nil {
-		t.Fatalf("Services.SetSlackService returns an error: %v", err)
-	}
-}
-
-func TestDeleteSlackService(t *testing.T) {
-	mux, server, client := setup()
-	defer teardown(server)
-
-	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-	})
-
-	_, err := client.Services.DeleteSlackService(1)
-	if err != nil {
-		t.Fatalf("Services.DeleteSlackService returns an error: %v", err)
-	}
-}
-
 func TestGetJiraService(t *testing.T) {
 	mux, server, client := setup()
 	defer teardown(server)
@@ -206,3 +153,112 @@ func TestDeleteJiraService(t *testing.T) {
 		t.Fatalf("Services.DeleteJiraService returns an error: %v", err)
 	}
 }
+
+func TestGetSlackService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{"id":1}`)
+	})
+	want := &SlackService{Service: Service{ID: 1}}
+
+	service, _, err := client.Services.GetSlackService(1)
+	if err != nil {
+		t.Fatalf("Services.GetSlackService returns an error: %v", err)
+	}
+	if !reflect.DeepEqual(want, service) {
+		t.Errorf("Services.GetSlackService returned %+v, want %+v", service, want)
+	}
+}
+
+func TestSetSlackService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+	})
+
+	opt := &SetSlackServiceOptions{
+		WebHook:  String("webhook_uri"),
+		Username: String("username"),
+		Channel:  String("#development"),
+	}
+
+	_, err := client.Services.SetSlackService(1, opt)
+	if err != nil {
+		t.Fatalf("Services.SetSlackService returns an error: %v", err)
+	}
+}
+
+func TestDeleteSlackService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/slack", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	_, err := client.Services.DeleteSlackService(1)
+	if err != nil {
+		t.Fatalf("Services.DeleteSlackService returns an error: %v", err)
+	}
+}
+
+func TestGetPipelinesEmailService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/pipelines-email", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{"id":1}`)
+	})
+	want := &PipelinesEmailService{Service: Service{ID: 1}}
+
+	service, _, err := client.Services.GetPipelinesEmailService(1)
+	if err != nil {
+		t.Fatalf("Services.GetPipelinesEmailService returns an error: %v", err)
+	}
+	if !reflect.DeepEqual(want, service) {
+		t.Errorf("Services.GetPipelinesEmailService returned %+v, want %+v", service, want)
+	}
+}
+
+func TestSetPipelinesEmailService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/pipelines-email", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+	})
+
+	opt := &SetPipelinesEmailServiceOptions{
+		Recipients:                String("test@email.com"),
+		NotifyOnlyBrokenPipelines: Bool(true),
+		NotifyOnlyDefaultBranch:   Bool(false),
+		AddPusher:                 nil,
+		BranchesToBeNotified:      nil,
+		PipelineEvents:            nil,
+	}
+
+	_, err := client.Services.SetPipelinesEmailService(1, opt)
+	if err != nil {
+		t.Fatalf("Services.SetPipelinesEmailService returns an error: %v", err)
+	}
+}
+
+func TestDeletePipelinesEmailService(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	mux.HandleFunc("/api/v4/projects/1/services/pipelines-email", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	_, err := client.Services.DeletePipelinesEmailService(1)
+	if err != nil {
+		t.Fatalf("Services.DeletePipelinesEmailService returns an error: %v", err)
+	}
+}