diff --git a/docs/gl_objects/merge_request_approvals.rst b/docs/gl_objects/merge_request_approvals.rst index 2c1b8404d..661e0c16e 100644 --- a/docs/gl_objects/merge_request_approvals.rst +++ b/docs/gl_objects/merge_request_approvals.rst @@ -75,6 +75,14 @@ List MR-level MR approval rules:: mr.approval_rules.list() +Delete MR-level MR approval rule:: + + rules = mr.approval_rules.list() + rules[0].delete() + + # or + mr.approval_rules.delete(approval_id) + Change MR-level MR approval rule:: mr_approvalrule.user_ids = [105] diff --git a/gitlab/v4/objects/merge_request_approvals.py b/gitlab/v4/objects/merge_request_approvals.py index 45016d522..d34484b2e 100644 --- a/gitlab/v4/objects/merge_request_approvals.py +++ b/gitlab/v4/objects/merge_request_approvals.py @@ -163,7 +163,7 @@ def set_approvers( return approval_rules.create(data=data) -class ProjectMergeRequestApprovalRule(SaveMixin, RESTObject): +class ProjectMergeRequestApprovalRule(SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "approval_rule_id" _short_print_attr = "approval_rule" id: int @@ -192,7 +192,7 @@ def save(self, **kwargs: Any) -> None: class ProjectMergeRequestApprovalRuleManager( - ListMixin, UpdateMixin, CreateMixin, RESTManager + ListMixin, UpdateMixin, CreateMixin, DeleteMixin, RESTManager ): _path = "/projects/{project_id}/merge_requests/{mr_iid}/approval_rules" _obj_cls = ProjectMergeRequestApprovalRule diff --git a/tests/unit/objects/test_project_merge_request_approvals.py b/tests/unit/objects/test_project_merge_request_approvals.py index 8c2920df4..5a87552c3 100644 --- a/tests/unit/objects/test_project_merge_request_approvals.py +++ b/tests/unit/objects/test_project_merge_request_approvals.py @@ -24,102 +24,7 @@ @pytest.fixture -def resp_snippet(): - merge_request_content = [ - { - "id": 1, - "iid": 1, - "project_id": 1, - "title": "test1", - "description": "fixed login page css paddings", - "state": "merged", - "merged_by": { - "id": 87854, - "name": "Douwe Maan", - "username": "DouweM", - "state": "active", - "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png", - "web_url": "https://gitlab.com/DouweM", - }, - "merged_at": "2018-09-07T11:16:17.520Z", - "closed_by": None, - "closed_at": None, - "created_at": "2017-04-29T08:46:00Z", - "updated_at": "2017-04-29T08:46:00Z", - "target_branch": "main", - "source_branch": "test1", - "upvotes": 0, - "downvotes": 0, - "author": { - "id": 1, - "name": "Administrator", - "username": "admin", - "state": "active", - "avatar_url": None, - "web_url": "https://gitlab.example.com/admin", - }, - "assignee": { - "id": 1, - "name": "Administrator", - "username": "admin", - "state": "active", - "avatar_url": None, - "web_url": "https://gitlab.example.com/admin", - }, - "assignees": [ - { - "name": "Miss Monserrate Beier", - "username": "axel.block", - "id": 12, - "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", - "web_url": "https://gitlab.example.com/axel.block", - } - ], - "source_project_id": 2, - "target_project_id": 3, - "labels": ["Community contribution", "Manage"], - "work_in_progress": None, - "milestone": { - "id": 5, - "iid": 1, - "project_id": 3, - "title": "v2.0", - "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", - "state": "closed", - "created_at": "2015-02-02T19:49:26.013Z", - "updated_at": "2015-02-02T19:49:26.013Z", - "due_date": "2018-09-22", - "start_date": "2018-08-08", - "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1", - }, - "merge_when_pipeline_succeeds": None, - "merge_status": "can_be_merged", - "sha": "8888888888888888888888888888888888888888", - "merge_commit_sha": None, - "squash_commit_sha": None, - "user_notes_count": 1, - "discussion_locked": None, - "should_remove_source_branch": True, - "force_remove_source_branch": False, - "allow_collaboration": False, - "allow_maintainer_to_push": False, - "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1", - "references": { - "short": "!1", - "relative": "my-group/my-project!1", - "full": "my-group/my-project!1", - }, - "time_stats": { - "time_estimate": 0, - "total_time_spent": 0, - "human_time_estimate": None, - "human_total_time_spent": None, - }, - "squash": False, - "task_completion_status": {"count": 0, "completed_count": 0}, - } - ] +def resp_mr_approval_rules(): mr_ars_content = [ { "id": approval_rule_id, @@ -188,20 +93,6 @@ def resp_snippet(): } with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: - rsps.add( - method=responses.GET, - url="http://localhost/api/v4/projects/1/merge_requests", - json=merge_request_content, - content_type="application/json", - status=200, - ) - rsps.add( - method=responses.GET, - url="http://localhost/api/v4/projects/1/merge_requests/1", - json=merge_request_content[0], - content_type="application/json", - status=200, - ) rsps.add( method=responses.GET, url="http://localhost/api/v4/projects/1/merge_requests/1/approval_rules", @@ -248,7 +139,20 @@ def resp_snippet(): yield rsps -def test_project_approval_manager_update_uses_post(project, resp_snippet): +@pytest.fixture +def resp_delete_mr_approval_rule(no_content): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.DELETE, + url="http://localhost/api/v4/projects/1/merge_requests/1/approval_rules/1", + json=no_content, + content_type="application/json", + status=204, + ) + yield rsps + + +def test_project_approval_manager_update_uses_post(project): """Ensure the gitlab.v4.objects.merge_request_approvals.ProjectApprovalManager object has _update_uses_post set to True""" @@ -259,15 +163,20 @@ def test_project_approval_manager_update_uses_post(project, resp_snippet): assert approvals._update_uses_post is True -def test_list_merge_request_approval_rules(project, resp_snippet): - approval_rules = project.mergerequests.get(1).approval_rules.list() +def test_list_merge_request_approval_rules(project, resp_mr_approval_rules): + approval_rules = project.mergerequests.get(1, lazy=True).approval_rules.list() assert len(approval_rules) == 1 assert approval_rules[0].name == approval_rule_name assert approval_rules[0].id == approval_rule_id -def test_update_merge_request_approvals_set_approvers(project, resp_snippet): - approvals = project.mergerequests.get(1).approvals +def test_delete_merge_request_approval_rule(project, resp_delete_mr_approval_rule): + merge_request = project.mergerequests.get(1, lazy=True) + merge_request.approval_rules.delete(approval_rule_id) + + +def test_update_merge_request_approvals_set_approvers(project, resp_mr_approval_rules): + approvals = project.mergerequests.get(1, lazy=True).approvals assert isinstance( approvals, gitlab.v4.objects.merge_request_approvals.ProjectMergeRequestApprovalManager, @@ -286,8 +195,8 @@ def test_update_merge_request_approvals_set_approvers(project, resp_snippet): assert response.name == approval_rule_name -def test_create_merge_request_approvals_set_approvers(project, resp_snippet): - approvals = project.mergerequests.get(1).approvals +def test_create_merge_request_approvals_set_approvers(project, resp_mr_approval_rules): + approvals = project.mergerequests.get(1, lazy=True).approvals assert isinstance( approvals, gitlab.v4.objects.merge_request_approvals.ProjectMergeRequestApprovalManager, @@ -305,8 +214,8 @@ def test_create_merge_request_approvals_set_approvers(project, resp_snippet): assert response.name == new_approval_rule_name -def test_create_merge_request_approval_rule(project, resp_snippet): - approval_rules = project.mergerequests.get(1).approval_rules +def test_create_merge_request_approval_rule(project, resp_mr_approval_rules): + approval_rules = project.mergerequests.get(1, lazy=True).approval_rules data = { "name": new_approval_rule_name, "approvals_required": new_approval_rule_approvals_required, @@ -321,8 +230,8 @@ def test_create_merge_request_approval_rule(project, resp_snippet): assert response.name == new_approval_rule_name -def test_update_merge_request_approval_rule(project, resp_snippet): - approval_rules = project.mergerequests.get(1).approval_rules +def test_update_merge_request_approval_rule(project, resp_mr_approval_rules): + approval_rules = project.mergerequests.get(1, lazy=True).approval_rules ar_1 = approval_rules.list()[0] ar_1.user_ids = updated_approval_rule_user_ids ar_1.approvals_required = updated_approval_rule_approvals_required @@ -333,8 +242,8 @@ def test_update_merge_request_approval_rule(project, resp_snippet): assert ar_1.eligible_approvers[0]["id"] == updated_approval_rule_user_ids[0] -def test_get_merge_request_approval_state(project, resp_snippet): - merge_request = project.mergerequests.get(1) +def test_get_merge_request_approval_state(project, resp_mr_approval_rules): + merge_request = project.mergerequests.get(1, lazy=True) approval_state = merge_request.approval_state.get() assert isinstance( approval_state,