From 64c78941aa9a3fd579cb85f86126104e6635b1d0 Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Mon, 10 Apr 2023 14:42:50 -0500 Subject: [PATCH 1/5] Adds the list group hooks endpoint https://docs.gitlab.com/ee/api/groups.html#hooks --- lib/gitlab/client/groups.rb | 11 +++++++++++ spec/fixtures/group_hooks.json | 27 +++++++++++++++++++++++++++ spec/gitlab/client/groups_spec.rb | 17 +++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 spec/fixtures/group_hooks.json diff --git a/lib/gitlab/client/groups.rb b/lib/gitlab/client/groups.rb index 7a0bf216a..003d3e14d 100644 --- a/lib/gitlab/client/groups.rb +++ b/lib/gitlab/client/groups.rb @@ -354,5 +354,16 @@ def add_group_custom_attribute(key, value, group_id) def delete_group_custom_attribute(key, group_id = nil) delete("/groups/#{group_id}/custom_attributes/#{key}") end + + # List all the specified groups hooks + # + # @example + # Gitlab.list_group_hooks(3) + # + # @param [Integer] group_id The ID of a group. + # @return [Gitlab::PaginatedResponse] List of registered hooks https://docs.gitlab.com/ee/api/groups.html#hooks + def list_group_hooks(group_id) + get("/groups/#{group_id}/hooks") + end end end diff --git a/spec/fixtures/group_hooks.json b/spec/fixtures/group_hooks.json new file mode 100644 index 000000000..963112657 --- /dev/null +++ b/spec/fixtures/group_hooks.json @@ -0,0 +1,27 @@ +[ + { + "id": 1, + "url": "http://example.com/hook", + "group_id": 3, + "push_events": true, + "push_events_branch_filter": "", + "issues_events": true, + "confidential_issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "confidential_note_events": true, + "job_events": true, + "pipeline_events": true, + "wiki_page_events": true, + "deployment_events": true, + "releases_events": true, + "subgroup_events": true, + "enable_ssl_verification": true, + "repository_update_events": false, + "alert_status": "executable", + "disabled_until": null, + "url_variables": [], + "created_at": "2012-10-12T17:04:47Z" + } +] diff --git a/spec/gitlab/client/groups_spec.rb b/spec/gitlab/client/groups_spec.rb index 351ce7682..4cbfcd680 100644 --- a/spec/gitlab/client/groups_spec.rb +++ b/spec/gitlab/client/groups_spec.rb @@ -446,4 +446,21 @@ end end end + + describe '.list_group_hooks' do + before do + stub_get('/groups/3/hooks', 'group_hooks') + @hooks = Gitlab.list_group_hooks(3) + end + + it 'gets the correct resource' do + expect(a_get('/groups/3/hooks')).to have_been_made + end + + it 'returns a list of registered group hooks based on the group id' do + expect(@hooks).to be_a Gitlab::PaginatedResponse + expect(@hooks.size).to eq(1) + expect(@hooks[0].url).to eq('http://example.com/hook') + end + end end From 19159897299ff4112fd02dcdabc027139476ea7a Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Mon, 10 Apr 2023 14:49:56 -0500 Subject: [PATCH 2/5] Adds fetching a group hook based on hook id https://docs.gitlab.com/ee/api/groups.html#get-group-hook --- lib/gitlab/client/groups.rb | 12 ++++++++++++ spec/fixtures/group_hook.json | 25 +++++++++++++++++++++++++ spec/gitlab/client/groups_spec.rb | 16 ++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 spec/fixtures/group_hook.json diff --git a/lib/gitlab/client/groups.rb b/lib/gitlab/client/groups.rb index 003d3e14d..797459c23 100644 --- a/lib/gitlab/client/groups.rb +++ b/lib/gitlab/client/groups.rb @@ -365,5 +365,17 @@ def delete_group_custom_attribute(key, group_id = nil) def list_group_hooks(group_id) get("/groups/#{group_id}/hooks") end + + # get specified group hook + # + # @example + # Gitlab.group_hook(3, 1) + # + # @param [Integer] group_id The ID of a group. + # @param [Integer] hook_id The ID of the hook. + # @return [Gitlab::ObjectifiedHash] The hook https://docs.gitlab.com/ee/api/groups.html#get-group-hook + def group_hook(group_id, hook_id) + get("/groups/#{group_id}/hooks/#{hook_id}") + end end end diff --git a/spec/fixtures/group_hook.json b/spec/fixtures/group_hook.json new file mode 100644 index 000000000..986b3ec20 --- /dev/null +++ b/spec/fixtures/group_hook.json @@ -0,0 +1,25 @@ +{ + "id": 1, + "url": "http://example.com/hook", + "group_id": 3, + "push_events": true, + "push_events_branch_filter": "", + "issues_events": true, + "confidential_issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "confidential_note_events": true, + "job_events": true, + "pipeline_events": true, + "wiki_page_events": true, + "deployment_events": true, + "releases_events": true, + "subgroup_events": true, + "enable_ssl_verification": true, + "repository_update_events": false, + "alert_status": "executable", + "disabled_until": null, + "url_variables": [], + "created_at": "2012-10-12T17:04:47Z" +} diff --git a/spec/gitlab/client/groups_spec.rb b/spec/gitlab/client/groups_spec.rb index 4cbfcd680..6b6db55fa 100644 --- a/spec/gitlab/client/groups_spec.rb +++ b/spec/gitlab/client/groups_spec.rb @@ -463,4 +463,20 @@ expect(@hooks[0].url).to eq('http://example.com/hook') end end + + describe '.group_hook(group_id, hook_id)' do + before do + stub_get('/groups/3/hooks/1', 'group_hook') + @hook = Gitlab.group_hook(3,1) + end + + it 'gets the correct resource' do + expect(a_get('/groups/3/hooks/1')).to have_been_made + end + + it 'returns information about the requested group hook' do + expect(@hook).to be_a Gitlab::ObjectifiedHash + expect(@hook.url).to eq('http://example.com/hook') + end + end end From 1517103032f7301b7c6ee813aeba7b3187748d66 Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Mon, 10 Apr 2023 15:50:52 -0500 Subject: [PATCH 3/5] Add group hook https://docs.gitlab.com/ee/api/groups.html#add-group-hook --- lib/gitlab/client/groups.rb | 29 ++++++++++++++++++++++++++++ spec/gitlab/client/groups_spec.rb | 32 ++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lib/gitlab/client/groups.rb b/lib/gitlab/client/groups.rb index 797459c23..5229a3526 100644 --- a/lib/gitlab/client/groups.rb +++ b/lib/gitlab/client/groups.rb @@ -377,5 +377,34 @@ def list_group_hooks(group_id) def group_hook(group_id, hook_id) get("/groups/#{group_id}/hooks/#{hook_id}") end + + # Add a new group hook + # + # @example + # Gitlab.add_group_hook(3, "https://example.com/my-hook-receiver", {token: "verify me"}) + # + # @param [Integer] group_id The ID of a group. + # @param [String] the hook url which will receive the selected events + # @option options [Boolean] :name The name of the group. + # @option options [Boolean] :push_events Trigger hook on push events + # @potion options [String] :push_events_branch_filter Trigger hook on push events for matching branches only. + # @option options [Boolean] :issues_events Trigger hook on issues events + # @option options [Boolean] :confidential_issues_events Trigger hook on confidential issues events + # @option options [Boolean] :merge_requests_events Trigger hook on merge requests events + # @option options [Boolean] :tag_push_events Trigger hook on tag push events + # @option options [Boolean] :note_events Trigger hook on note events + # @option options [Boolean] :confidential_note_events Trigger hook on confidential note events + # @option options [Boolean] :job_events Trigger hook on job events + # @option options [Boolean] :pipeline_events Trigger hook on pipeline events + # @option options [Boolean] :wiki_page_events Trigger hook on wiki page events + # @option options [Boolean] :deployment_events Trigger hook on deployment events + # @option options [Boolean] :releases_events Trigger hook on release events + # @option options [Boolean] :subgroup_events Trigger hook on subgroup events + # @option options [Boolean] :enable_ssl_verification Do SSL verification when triggering the hook + # @option options [String] :token Secret token to validate received payloads; not returned in the response + # @return [Gitlab::ObjectifiedHash] Response body matches https://docs.gitlab.com/ee/api/groups.html#get-group-hook + def add_group_hook(group_id, url, options = {}) + post("/groups/#{group_id}/hooks", body: options.merge(url: url)) + end end end diff --git a/spec/gitlab/client/groups_spec.rb b/spec/gitlab/client/groups_spec.rb index 6b6db55fa..b1c9b7897 100644 --- a/spec/gitlab/client/groups_spec.rb +++ b/spec/gitlab/client/groups_spec.rb @@ -42,7 +42,7 @@ it 'gets the correct resource' do expect(a_post('/groups') - .with(body: { path: 'gitlab-path', name: 'GitLab-Group' })).to have_been_made + .with(body: { path: 'gitlab-path', name: 'GitLab-Group' })).to have_been_made end it 'returns information about a created group' do @@ -59,8 +59,8 @@ it 'gets the correct resource' do expect(a_post('/groups') - .with(body: { path: 'gitlab-path', name: 'GitLab-Group', - description: 'gitlab group description' })).to have_been_made + .with(body: { path: 'gitlab-path', name: 'GitLab-Group', + description: 'gitlab group description' })).to have_been_made end it 'returns information about a created group' do @@ -218,7 +218,7 @@ it 'gets the correct resource' do expect(a_put('/groups/3/members/1') - .with(body: { access_level: '50' })).to have_been_made + .with(body: { access_level: '50' })).to have_been_made end it 'returns information about the edited member' do @@ -467,7 +467,7 @@ describe '.group_hook(group_id, hook_id)' do before do stub_get('/groups/3/hooks/1', 'group_hook') - @hook = Gitlab.group_hook(3,1) + @hook = Gitlab.group_hook(3, 1) end it 'gets the correct resource' do @@ -479,4 +479,26 @@ expect(@hook.url).to eq('http://example.com/hook') end end + + describe '.add_group_hook(group_id, url, options)' do + before do + stub_post('/groups/3/hooks', 'group_hook') + @hook = Gitlab.add_group_hook(3, 'http://example.com', { + push_events: true, + push_events_branch_filter: 'main', + enable_ssl_verification: true, + token: 'foofoofoo1234' + }) + end + + it 'creates the correct resource' do + expect(a_post('/groups/3/hooks') + .with(body: { url: 'http://example.com', push_events: true, push_events_branch_filter: 'main', enable_ssl_verification: true, token: 'foofoofoo1234' })).to have_been_made + end + + it 'returns the created group hook matching the format of GET hook' do + expect(@hook).to be_a Gitlab::ObjectifiedHash + expect(@hook.url).to eq('http://example.com/hook') + end + end end From 28c97a8440ca34057550ccea336cd74612bc4e6a Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Mon, 10 Apr 2023 16:04:42 -0500 Subject: [PATCH 4/5] Edit an existing group hook https://docs.gitlab.com/ee/api/groups.html#edit-group-hook --- lib/gitlab/client/groups.rb | 30 ++++++++++++++++++++++++++++++ spec/gitlab/client/groups_spec.rb | 17 +++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/gitlab/client/groups.rb b/lib/gitlab/client/groups.rb index 5229a3526..313217d69 100644 --- a/lib/gitlab/client/groups.rb +++ b/lib/gitlab/client/groups.rb @@ -406,5 +406,35 @@ def group_hook(group_id, hook_id) def add_group_hook(group_id, url, options = {}) post("/groups/#{group_id}/hooks", body: options.merge(url: url)) end + + # Edit a group hook + # + # @example + # Gitlab.edit_group_hook(3, 1, "https://example.com/my-hook-receiver", {token: "verify me"}) + # + # @param [Integer] group_id The ID of a group. + # @param [Integer] hook_id The ID of a group. + # @param [String] the hook url which will receive the selected events + # @option options [Boolean] :name The name of the group. + # @option options [Boolean] :push_events Trigger hook on push events + # @potion options [String] :push_events_branch_filter Trigger hook on push events for matching branches only. + # @option options [Boolean] :issues_events Trigger hook on issues events + # @option options [Boolean] :confidential_issues_events Trigger hook on confidential issues events + # @option options [Boolean] :merge_requests_events Trigger hook on merge requests events + # @option options [Boolean] :tag_push_events Trigger hook on tag push events + # @option options [Boolean] :note_events Trigger hook on note events + # @option options [Boolean] :confidential_note_events Trigger hook on confidential note events + # @option options [Boolean] :job_events Trigger hook on job events + # @option options [Boolean] :pipeline_events Trigger hook on pipeline events + # @option options [Boolean] :wiki_page_events Trigger hook on wiki page events + # @option options [Boolean] :deployment_events Trigger hook on deployment events + # @option options [Boolean] :releases_events Trigger hook on release events + # @option options [Boolean] :subgroup_events Trigger hook on subgroup events + # @option options [Boolean] :enable_ssl_verification Do SSL verification when triggering the hook + # @option options [String] :token Secret token to validate received payloads; not returned in the response + # @return [Gitlab::ObjectifiedHash] Response body matches https://docs.gitlab.com/ee/api/groups.html#edit-group-hook + def edit_group_hook(group_id, hook_id, url, options = {}) + post("/groups/#{group_id}/hooks/#{hook_id}", body: options.merge(url: url)) + end end end diff --git a/spec/gitlab/client/groups_spec.rb b/spec/gitlab/client/groups_spec.rb index b1c9b7897..3436bfba7 100644 --- a/spec/gitlab/client/groups_spec.rb +++ b/spec/gitlab/client/groups_spec.rb @@ -501,4 +501,21 @@ expect(@hook.url).to eq('http://example.com/hook') end end + + describe '.edit_group_hook(group_id, hook_id, url)' do + before do + stub_post('/groups/3/hooks/1', 'group_hook') + @hook = Gitlab.edit_group_hook(3, 1, 'http://example.com', { push_events: false, token: 'foofoofoo1234' }) + end + + it 'updates the correct resource' do + expect(a_post('/groups/3/hooks/1') + .with(body: { url: 'http://example.com', push_events: false, token: 'foofoofoo1234' })).to have_been_made + end + + it 'returns the updated group hook resource' do + expect(@hook).to be_a Gitlab::ObjectifiedHash + expect(@hook.url).to eq('http://example.com/hook') + end + end end From 998b1b1b7ec14794f81469cd42cbc9bf97406155 Mon Sep 17 00:00:00 2001 From: Michael McCormick Date: Mon, 10 Apr 2023 16:29:30 -0500 Subject: [PATCH 5/5] Delete group hook https://docs.gitlab.com/ee/api/groups.html#delete-group-hook The API returns status and empty body. The library converts the empty body into an empty Gitlab::ObjectifiedHash. In test, the stub converts an empty body to False. Decided to represent all of this by making the fixture accuractly represent the response body and have the test method call out the discrepancy. --- lib/gitlab/client/groups.rb | 12 ++++++++++++ spec/fixtures/group_hook_delete.json | 0 spec/gitlab/client/groups_spec.rb | 15 +++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 spec/fixtures/group_hook_delete.json diff --git a/lib/gitlab/client/groups.rb b/lib/gitlab/client/groups.rb index 313217d69..f4f14b09e 100644 --- a/lib/gitlab/client/groups.rb +++ b/lib/gitlab/client/groups.rb @@ -436,5 +436,17 @@ def add_group_hook(group_id, url, options = {}) def edit_group_hook(group_id, hook_id, url, options = {}) post("/groups/#{group_id}/hooks/#{hook_id}", body: options.merge(url: url)) end + + # Delete a group hook + # + # @example + # Gitlab.delete_group_hook(3, 1) + # + # @param [Integer] group_id The ID of a group. + # @param [Integer] hook_id The ID of a group. + # @return [Gitlab::ObjectifiedHash] no body, will evaluate to an empty hash. https://docs.gitlab.com/ee/api/groups.html#delete-group-hook + def delete_group_hook(group_id, hook_id) + delete("/groups/#{group_id}/hooks/#{hook_id}") + end end end diff --git a/spec/fixtures/group_hook_delete.json b/spec/fixtures/group_hook_delete.json new file mode 100644 index 000000000..e69de29bb diff --git a/spec/gitlab/client/groups_spec.rb b/spec/gitlab/client/groups_spec.rb index 3436bfba7..b7e6f19c5 100644 --- a/spec/gitlab/client/groups_spec.rb +++ b/spec/gitlab/client/groups_spec.rb @@ -518,4 +518,19 @@ expect(@hook.url).to eq('http://example.com/hook') end end + + describe '.delete_group_hook(group_id, hook_id)' do + before do + stub_delete('/groups/3/hooks/1', 'group_hook_delete') + @hook = Gitlab.delete_group_hook(3, 1) + end + + it 'delete the resource' do + expect(a_delete('/groups/3/hooks/1')).to have_been_made + end + + it 'returns false in test but in real life it returns status without a body which is converted to ObjectifiedHash' do + expect(@hook).to eq(false) + end + end end