Skip to content

Commit

Permalink
Merge pull request #1266 from gokeefe/gokeefe/group_push_rules
Browse files Browse the repository at this point in the history
#1259 Add GroupPushRules and GroupPushRulesManager classes
  • Loading branch information
nejch committed Jul 5, 2022
2 parents 3df404c + b5cdc09 commit 768890a
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 2 deletions.
34 changes: 34 additions & 0 deletions docs/gl_objects/groups.rst
Expand Up @@ -376,3 +376,37 @@ Delete a group hook::
group.hooks.delete(hook_id)
# or
hook.delete()

Group push rules
==================

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.GroupPushRules`
+ :class:`gitlab.v4.objects.GroupPushRulesManager`
+ :attr:`gitlab.v4.objects.Group.pushrules`

* GitLab API: https://docs.gitlab.com/ee/api/groups.html#push-rules

Examples
---------

Create group push rules (at least one rule is necessary)::

group.pushrules.create({'deny_delete_tag': True})

Get group push rules (returns None is there are no push rules)::

pr = group.pushrules.get()

Edit group push rules::

pr.branch_name_regex = '^(master|develop|support-\d+|release-\d+\..+|hotfix-.+|feature-.+)$'
pr.save()

Delete group push rules::

pr.delete()
2 changes: 2 additions & 0 deletions gitlab/v4/objects/groups.py
Expand Up @@ -33,6 +33,7 @@
from .notification_settings import GroupNotificationSettingsManager # noqa: F401
from .packages import GroupPackageManager # noqa: F401
from .projects import GroupProjectManager # noqa: F401
from .push_rules import GroupPushRulesManager
from .runners import GroupRunnerManager # noqa: F401
from .statistics import GroupIssuesStatisticsManager # noqa: F401
from .variables import GroupVariableManager # noqa: F401
Expand Down Expand Up @@ -75,6 +76,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
notificationsettings: GroupNotificationSettingsManager
packages: GroupPackageManager
projects: GroupProjectManager
pushrules: GroupPushRulesManager
runners: GroupRunnerManager
subgroups: "GroupSubgroupManager"
variables: GroupVariableManager
Expand Down
57 changes: 55 additions & 2 deletions gitlab/v4/objects/push_rules.py
Expand Up @@ -12,6 +12,8 @@
from gitlab.types import RequiredOptional

__all__ = [
"GroupPushRules",
"GroupPushRulesManager",
"ProjectPushRules",
"ProjectPushRulesManager",
]
Expand All @@ -27,16 +29,64 @@ class ProjectPushRulesManager(
_path = "/projects/{project_id}/push_rule"
_obj_cls = ProjectPushRules
_from_parent_attrs = {"project_id": "id"}
_create_attrs = RequiredOptional(
optional=(
"author_email_regex",
"branch_name_regex",
"commit_committer_check",
"commit_message_negative_regex",
"commit_message_regex",
"deny_delete_tag",
"file_name_regex",
"max_file_size",
"member_check",
"prevent_secrets",
"reject_unsigned_commits",
),
)
_update_attrs = RequiredOptional(
optional=(
"author_email_regex",
"branch_name_regex",
"commit_committer_check",
"commit_message_negative_regex",
"commit_message_regex",
"deny_delete_tag",
"file_name_regex",
"max_file_size",
"member_check",
"prevent_secrets",
"reject_unsigned_commits",
),
)

def get(self, **kwargs: Any) -> ProjectPushRules:
return cast(ProjectPushRules, super().get(**kwargs))


class GroupPushRules(SaveMixin, ObjectDeleteMixin, RESTObject):
_id_attr = None


class GroupPushRulesManager(
GetWithoutIdMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
):
_path = "/groups/{group_id}/push_rule"
_obj_cls = GroupPushRules
_from_parent_attrs = {"group_id": "id"}
_create_attrs = RequiredOptional(
optional=(
"deny_delete_tag",
"member_check",
"prevent_secrets",
"commit_message_regex",
"commit_message_negative_regex",
"branch_name_regex",
"author_email_regex",
"file_name_regex",
"max_file_size",
"commit_committer_check",
"reject_unsigned_commits",
),
)
_update_attrs = RequiredOptional(
Expand All @@ -45,12 +95,15 @@ class ProjectPushRulesManager(
"member_check",
"prevent_secrets",
"commit_message_regex",
"commit_message_negative_regex",
"branch_name_regex",
"author_email_regex",
"file_name_regex",
"max_file_size",
"commit_committer_check",
"reject_unsigned_commits",
),
)

def get(self, **kwargs: Any) -> ProjectPushRules:
return cast(ProjectPushRules, super().get(**kwargs))
def get(self, **kwargs: Any) -> GroupPushRules:
return cast(GroupPushRules, super().get(**kwargs))
103 changes: 103 additions & 0 deletions tests/unit/objects/test_groups.py
Expand Up @@ -38,6 +38,19 @@
"created_at": "2020-01-15T12:36:29.590Z",
},
]
push_rules_content = {
"id": 2,
"created_at": "2020-08-17T19:09:19.580Z",
"commit_message_regex": "[a-zA-Z]",
"commit_message_negative_regex": "[x+]",
"branch_name_regex": "[a-z]",
"deny_delete_tag": True,
"member_check": True,
"prevent_secrets": True,
"author_email_regex": "^[A-Za-z0-9.]+@gitlab.com$",
"file_name_regex": "(exe)$",
"max_file_size": 100,
}


@pytest.fixture
Expand Down Expand Up @@ -111,6 +124,72 @@ def resp_transfer_group():
yield rsps


@pytest.fixture
def resp_list_push_rules_group():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/groups/1/push_rule",
json=push_rules_content,
content_type="application/json",
status=200,
)
yield rsps


@pytest.fixture
def resp_create_push_rules_group():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/groups/1/push_rule",
json=push_rules_content,
content_type="application/json",
status=201,
)
yield rsps


@pytest.fixture
def resp_update_push_rules_group():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/groups/1/push_rule",
json=push_rules_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.PUT,
url="http://localhost/api/v4/groups/1/push_rule",
json=push_rules_content,
content_type="application/json",
status=201,
)
yield rsps


@pytest.fixture
def resp_delete_push_rules_group(no_content):
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/groups/1/push_rule",
json=push_rules_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.DELETE,
url="http://localhost/api/v4/groups/1/push_rule",
json=no_content,
content_type="application/json",
status=204,
)
yield rsps


def test_get_group(gl, resp_groups):
data = gl.groups.get(1)
assert isinstance(data, gitlab.v4.objects.Group)
Expand Down Expand Up @@ -173,3 +252,27 @@ def test_refresh_group_import_status(group, resp_groups):
def test_transfer_group(gl, resp_transfer_group):
group = gl.groups.get(1, lazy=True)
group.transfer("test-namespace")


def test_list_group_push_rules(group, resp_list_push_rules_group):
pr = group.pushrules.get()
assert pr
assert pr.deny_delete_tag


def test_create_group_push_rule(group, resp_create_push_rules_group):
group.pushrules.create({"deny_delete_tag": True})


def test_update_group_push_rule(
group,
resp_update_push_rules_group,
):
pr = group.pushrules.get()
pr.deny_delete_tag = False
pr.save()


def test_delete_group_push_rule(group, resp_delete_push_rules_group):
pr = group.pushrules.get()
pr.delete()

0 comments on commit 768890a

Please sign in to comment.