diff --git a/group_hooks.go b/group_hooks.go index 414a8d086..320f03840 100644 --- a/group_hooks.go +++ b/group_hooks.go @@ -229,6 +229,25 @@ func (s *GroupsService) DeleteGroupHook(pid interface{}, hook int, options ...Re return s.client.Do(req, nil) } +// TriggerTestGroupHook triggers a test hook for a specified group. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/group_webhooks.html#trigger-a-test-group-hook +func (s *GroupsService) TriggerTestGroupHook(pid interface{}, hook int, trigger GroupHookTrigger, options ...RequestOptionFunc) (*Response, error) { + group, err := parseID(pid) + if err != nil { + return nil, err + } + u := fmt.Sprintf("groups/%s/hooks/%d/test/%s", PathEscape(group), hook, trigger) + + req, err := s.client.NewRequest(http.MethodPost, u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} + // SetGroupCustomHeader creates or updates a group custom webhook header. // // GitLab API docs: diff --git a/group_hooks_test.go b/group_hooks_test.go index 06e55445c..4f8fe1990 100644 --- a/group_hooks_test.go +++ b/group_hooks_test.go @@ -358,6 +358,78 @@ func TestEditGroupHook(t *testing.T) { } } +func TestTriggerTestGroupHook(t *testing.T) { + mux, client := setup(t) + + mux.HandleFunc("/api/v4/groups/1/hooks/1/test/push_events", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + w.WriteHeader(http.StatusCreated) + fmt.Fprint(w, `{"message":"201 Created"}`) + }) + + mux.HandleFunc("/api/v4/groups/1/hooks/1/test/invalid_trigger", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, `{"error": "trigger does not have a valid value"}`) + }) + + tests := []struct { + name string + groupID interface{} + hookID int + trigger GroupHookTrigger + wantErr bool + wantStatus int + wantErrMsg string + }{ + { + name: "Valid trigger", + groupID: 1, + hookID: 1, + trigger: GroupHookTriggerPush, + wantErr: false, + wantStatus: http.StatusCreated, + }, + { + name: "Invalid group ID", + groupID: "invalid", + hookID: 1, + trigger: GroupHookTriggerPush, + wantErr: true, + wantStatus: http.StatusNotFound, + }, + { + name: "Invalid trigger type", + groupID: 1, + hookID: 1, + trigger: "invalid_trigger", + wantErr: true, + wantStatus: http.StatusBadRequest, + wantErrMsg: "trigger does not have a valid value", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resp, err := client.Groups.TriggerTestGroupHook(tt.groupID, tt.hookID, tt.trigger) + + if tt.wantErr { + assert.Error(t, err) + if tt.wantStatus != 0 { + assert.Equal(t, tt.wantStatus, resp.StatusCode) + } + if tt.wantErrMsg != "" { + assert.Contains(t, err.Error(), tt.wantErrMsg) + } + } else { + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, tt.wantStatus, resp.StatusCode) + } + }) + } +} + func TestDeleteGroupHook(t *testing.T) { mux, client := setup(t) diff --git a/types.go b/types.go index 5b7f74eb3..d3a9ecab4 100644 --- a/types.go +++ b/types.go @@ -440,6 +440,26 @@ func GenericPackageStatus(v GenericPackageStatusValue) *GenericPackageStatusValu return Ptr(v) } +// GroupHookTrigger represents the type of event to trigger for a group +// hook test. +type GroupHookTrigger string + +// List of available group hook trigger types. +const ( + GroupHookTriggerPush GroupHookTrigger = "push_events" + GroupHookTriggerTagPush GroupHookTrigger = "tag_push_events" + GroupHookTriggerIssue GroupHookTrigger = "issues_events" + GroupHookTriggerConfidentialIssue GroupHookTrigger = "confidential_issues_events" + GroupHookTriggerNote GroupHookTrigger = "note_events" + GroupHookTriggerMergeRequest GroupHookTrigger = "merge_requests_events" + GroupHookTriggerJob GroupHookTrigger = "job_events" + GroupHookTriggerPipeline GroupHookTrigger = "pipeline_events" + GroupHookTriggerWikiPage GroupHookTrigger = "wiki_page_events" + GroupHookTriggerRelease GroupHookTrigger = "releases_events" + GroupHookTriggerEmoji GroupHookTrigger = "emoji_events" + GroupHookTriggerResourceAccessToken GroupHookTrigger = "resource_access_token_events" +) + // ISOTime represents an ISO 8601 formatted date. type ISOTime time.Time