Loading docs/gl_objects/groups.rst +8 −4 Original line number Diff line number Diff line Loading @@ -419,6 +419,10 @@ Update a group hook:: hook.push_events = 0 hook.save() Test a group hook:: hook.test("push_events") Delete a group hook:: group.hooks.delete(hook_id) Loading docs/gl_objects/projects.rst +7 −3 Original line number Diff line number Diff line Loading @@ -689,6 +689,10 @@ Update a project hook:: hook.push_events = 0 hook.save() Test a project hook:: hook.test("push_events") Delete a project hook:: project.hooks.delete(hook_id) Loading gitlab/exceptions.py +5 −0 Original line number Diff line number Diff line Loading @@ -316,6 +316,10 @@ class GitlabDeploymentApprovalError(GitlabOperationError): pass class GitlabHookTestError(GitlabOperationError): pass # For an explanation of how these type-hints work see: # https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators # Loading Loading @@ -370,6 +374,7 @@ __all__ = [ "GitlabGetError", "GitlabGroupTransferError", "GitlabHeadError", "GitlabHookTestError", "GitlabHousekeepingError", "GitlabHttpError", "GitlabImportError", Loading gitlab/v4/objects/hooks.py +29 −0 Original line number Diff line number Diff line from typing import Any, cast, Union from gitlab import exceptions as exc from gitlab.base import RESTManager, RESTObject from gitlab.mixins import CRUDMixin, NoUpdateMixin, ObjectDeleteMixin, SaveMixin from gitlab.types import RequiredOptional Loading Loading @@ -31,6 +32,20 @@ class HookManager(NoUpdateMixin, RESTManager): class ProjectHook(SaveMixin, ObjectDeleteMixin, RESTObject): _repr_attr = "url" @exc.on_http_error(exc.GitlabHookTestError) def test(self, trigger: str) -> None: """ Test a Project Hook Args: trigger: Type of trigger event to test Raises: GitlabHookTestError: If the hook test attempt failed """ path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}" self.manager.gitlab.http_post(path) class ProjectHookManager(CRUDMixin, RESTManager): _path = "/projects/{project_id}/hooks" Loading Loading @@ -78,6 +93,20 @@ class ProjectHookManager(CRUDMixin, RESTManager): class GroupHook(SaveMixin, ObjectDeleteMixin, RESTObject): _repr_attr = "url" @exc.on_http_error(exc.GitlabHookTestError) def test(self, trigger: str) -> None: """ Test a Group Hook Args: trigger: Type of trigger event to test Raises: GitlabHookTestError: If the hook test attempt failed """ path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}" self.manager.gitlab.http_post(path) class GroupHookManager(CRUDMixin, RESTManager): _path = "/groups/{group_id}/hooks" Loading tests/unit/objects/test_hooks.py +64 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import re import pytest import responses import gitlab from gitlab.v4.objects import GroupHook, Hook, ProjectHook hooks_content = [ Loading Loading @@ -89,6 +90,58 @@ def resp_hook_update(): yield rsps @pytest.fixture def resp_hook_test(): with responses.RequestsMock() as rsps: hook_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1" ) test_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1/test/[a-z_]+" ) rsps.add( method=responses.GET, url=hook_pattern, json=hook_content, content_type="application/json", status=200, ) rsps.add( method=responses.POST, url=test_pattern, json={"message": "201 Created"}, content_type="application/json", status=201, ) yield rsps @pytest.fixture def resp_hook_test_error(): with responses.RequestsMock() as rsps: hook_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1" ) test_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1/test/[a-z_]+" ) rsps.add( method=responses.GET, url=hook_pattern, json=hook_content, content_type="application/json", status=200, ) rsps.add( method=responses.POST, url=test_pattern, json={"message": "<html>error</html>"}, content_type="application/json", status=422, ) yield rsps @pytest.fixture def resp_hook_delete(): with responses.RequestsMock() as rsps: Loading Loading @@ -174,6 +227,17 @@ def test_delete_group_hook(group, resp_hook_delete): group.hooks.delete(1) def test_test_group_hook(group, resp_hook_test): hook = group.hooks.get(1) hook.test("push_events") def test_test_error_group_hook(group, resp_hook_test_error): hook = group.hooks.get(1) with pytest.raises(gitlab.exceptions.GitlabHookTestError): hook.test("push_events") def test_list_project_hooks(project, resp_hooks_list): hooks = project.hooks.list() assert hooks[0].id == 1 Loading Loading
docs/gl_objects/groups.rst +8 −4 Original line number Diff line number Diff line Loading @@ -419,6 +419,10 @@ Update a group hook:: hook.push_events = 0 hook.save() Test a group hook:: hook.test("push_events") Delete a group hook:: group.hooks.delete(hook_id) Loading
docs/gl_objects/projects.rst +7 −3 Original line number Diff line number Diff line Loading @@ -689,6 +689,10 @@ Update a project hook:: hook.push_events = 0 hook.save() Test a project hook:: hook.test("push_events") Delete a project hook:: project.hooks.delete(hook_id) Loading
gitlab/exceptions.py +5 −0 Original line number Diff line number Diff line Loading @@ -316,6 +316,10 @@ class GitlabDeploymentApprovalError(GitlabOperationError): pass class GitlabHookTestError(GitlabOperationError): pass # For an explanation of how these type-hints work see: # https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators # Loading Loading @@ -370,6 +374,7 @@ __all__ = [ "GitlabGetError", "GitlabGroupTransferError", "GitlabHeadError", "GitlabHookTestError", "GitlabHousekeepingError", "GitlabHttpError", "GitlabImportError", Loading
gitlab/v4/objects/hooks.py +29 −0 Original line number Diff line number Diff line from typing import Any, cast, Union from gitlab import exceptions as exc from gitlab.base import RESTManager, RESTObject from gitlab.mixins import CRUDMixin, NoUpdateMixin, ObjectDeleteMixin, SaveMixin from gitlab.types import RequiredOptional Loading Loading @@ -31,6 +32,20 @@ class HookManager(NoUpdateMixin, RESTManager): class ProjectHook(SaveMixin, ObjectDeleteMixin, RESTObject): _repr_attr = "url" @exc.on_http_error(exc.GitlabHookTestError) def test(self, trigger: str) -> None: """ Test a Project Hook Args: trigger: Type of trigger event to test Raises: GitlabHookTestError: If the hook test attempt failed """ path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}" self.manager.gitlab.http_post(path) class ProjectHookManager(CRUDMixin, RESTManager): _path = "/projects/{project_id}/hooks" Loading Loading @@ -78,6 +93,20 @@ class ProjectHookManager(CRUDMixin, RESTManager): class GroupHook(SaveMixin, ObjectDeleteMixin, RESTObject): _repr_attr = "url" @exc.on_http_error(exc.GitlabHookTestError) def test(self, trigger: str) -> None: """ Test a Group Hook Args: trigger: Type of trigger event to test Raises: GitlabHookTestError: If the hook test attempt failed """ path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}" self.manager.gitlab.http_post(path) class GroupHookManager(CRUDMixin, RESTManager): _path = "/groups/{group_id}/hooks" Loading
tests/unit/objects/test_hooks.py +64 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ import re import pytest import responses import gitlab from gitlab.v4.objects import GroupHook, Hook, ProjectHook hooks_content = [ Loading Loading @@ -89,6 +90,58 @@ def resp_hook_update(): yield rsps @pytest.fixture def resp_hook_test(): with responses.RequestsMock() as rsps: hook_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1" ) test_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1/test/[a-z_]+" ) rsps.add( method=responses.GET, url=hook_pattern, json=hook_content, content_type="application/json", status=200, ) rsps.add( method=responses.POST, url=test_pattern, json={"message": "201 Created"}, content_type="application/json", status=201, ) yield rsps @pytest.fixture def resp_hook_test_error(): with responses.RequestsMock() as rsps: hook_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1" ) test_pattern = re.compile( r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1/test/[a-z_]+" ) rsps.add( method=responses.GET, url=hook_pattern, json=hook_content, content_type="application/json", status=200, ) rsps.add( method=responses.POST, url=test_pattern, json={"message": "<html>error</html>"}, content_type="application/json", status=422, ) yield rsps @pytest.fixture def resp_hook_delete(): with responses.RequestsMock() as rsps: Loading Loading @@ -174,6 +227,17 @@ def test_delete_group_hook(group, resp_hook_delete): group.hooks.delete(1) def test_test_group_hook(group, resp_hook_test): hook = group.hooks.get(1) hook.test("push_events") def test_test_error_group_hook(group, resp_hook_test_error): hook = group.hooks.get(1) with pytest.raises(gitlab.exceptions.GitlabHookTestError): hook.test("push_events") def test_list_project_hooks(project, resp_hooks_list): hooks = project.hooks.list() assert hooks[0].id == 1 Loading