summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGauvain Pocentek <gauvain@pocentek.net>2018-06-11 22:08:55 +0200
committerGauvain Pocentek <gauvain@pocentek.net>2018-06-11 22:08:55 +0200
commit59a19ca36c6790e3c813cb2742efdf8c5fdb122e (patch)
tree6786aae10ad4528556495fffb8d91152ed7f58f5
parent8df6de9ea520e08f1e142ae962090a0a9499bfaf (diff)
downloadgitlab-59a19ca36c6790e3c813cb2742efdf8c5fdb122e.tar.gz
Implement MR-level approvals
Fixes #323
-rw-r--r--docs/gl_objects/mr_approvals.rst37
-rw-r--r--gitlab/v4/objects.py44
-rwxr-xr-xtools/ee-test.py15
3 files changed, 77 insertions, 19 deletions
diff --git a/docs/gl_objects/mr_approvals.rst b/docs/gl_objects/mr_approvals.rst
index 69d44a5..e1a5d7b 100644
--- a/docs/gl_objects/mr_approvals.rst
+++ b/docs/gl_objects/mr_approvals.rst
@@ -1,6 +1,9 @@
-##############################################
-Project-level merge request approvals settings
-##############################################
+################################
+Merge request approvals settings
+################################
+
+Merge request approvals can be defined at the project level or at the merge
+request level.
References
----------
@@ -10,21 +13,33 @@ References
+ :class:`gitlab.v4.objects.ProjectApproval`
+ :class:`gitlab.v4.objects.ProjectApprovalManager`
+ :attr:`gitlab.v4.objects.Project.approvals`
+ + :class:`gitlab.v4.objects.ProjectMergeRequestApproval`
+ + :class:`gitlab.v4.objects.ProjectMergeRequestApprovalManager`
+ + :attr:`gitlab.v4.objects.ProjectMergeRequest.approvals`
-* GitLab API: https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
+* GitLab API: https://docs.gitlab.com/ee/api/merge_request_approvals.html
Examples
--------
-Get project-level MR approvals settings::
+Get project-level or MR-level MR approvals settings::
+
+ p_mras = project.approvals.get()
+
+ mr_mras = mr.approvals.get()
+
+Change project-level or MR-level MR approvals settings::
- mras = project.approvals.get()
+ p_mras.approvals_before_merge = 2
+ p_mras.save()
-Change project-level MR approvals settings::
+ mr_mras.approvals_before_merge = 2
+ mr_mras.save()
- mras.approvals_before_merge = 2
- mras.save()
+Change project-level or MR-level MR allowed approvers::
-Change project-level MR allowed approvers::
+ project.approvals.set_approvers(approver_ids=[105],
+ approver_group_ids=[653, 654])
- project.approvals.set_approvers(approver_ids = [105], approver_group_ids=[653, 654])
+ mr.approvals.set_approvers(approver_ids=[105],
+ approver_group_ids=[653, 654])
diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py
index 2db2e39..d01d32f 100644
--- a/gitlab/v4/objects.py
+++ b/gitlab/v4/objects.py
@@ -1795,6 +1795,37 @@ class ProjectTagManager(NoUpdateMixin, RESTManager):
_create_attrs = (('tag_name', 'ref'), ('message',))
+class ProjectMergeRequestApproval(SaveMixin, RESTObject):
+ _id_attr = None
+
+
+class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin,
+ RESTManager):
+ _path = '/projects/%(project_id)s/merge_requests/%(mr_iid)s/approvals'
+ _obj_cls = ProjectMergeRequestApproval
+ _from_parent_attrs = {'project_id': 'project_id', 'mr_iid': 'iid'}
+ _update_attrs = (('approvals_required',), tuple())
+ _update_uses_post = True
+
+ @exc.on_http_error(exc.GitlabUpdateError)
+ def set_approvers(self, approver_ids=[], approver_group_ids=[], **kwargs):
+ """Change MR-level allowed approvers and approver groups.
+
+ Args:
+ approver_ids (list): User IDs that can approve MRs
+ approver_group_ids (list): Group IDs whose members can approve MRs
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabUpdateError: If the server failed to perform the request
+ """
+ path = '%s/%s/approvers' % (self._parent.manager.path,
+ self._parent.get_id())
+ data = {'approver_ids': approver_ids,
+ 'approver_group_ids': approver_group_ids}
+ self.gitlab.http_put(path, post_data=data, **kwargs)
+
+
class ProjectMergeRequestAwardEmoji(ObjectDeleteMixin, RESTObject):
pass
@@ -1879,6 +1910,7 @@ class ProjectMergeRequest(SubscribableMixin, TodoMixin, TimeTrackingMixin,
_id_attr = 'iid'
_managers = (
+ ('approvals', 'ProjectMergeRequestApprovalManager'),
('awardemojis', 'ProjectMergeRequestAwardEmojiManager'),
('diffs', 'ProjectMergeRequestDiffManager'),
('discussions', 'ProjectMergeRequestDiscussionManager'),
@@ -2761,13 +2793,12 @@ class ProjectApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
_update_uses_post = True
@exc.on_http_error(exc.GitlabUpdateError)
- def set_approvers(self, approver_ids=[], approver_group_ids=[],
- **kwargs):
+ def set_approvers(self, approver_ids=[], approver_group_ids=[], **kwargs):
"""Change project-level allowed approvers and approver groups.
Args:
- approver_ids (list): User IDs that can approve MRs.
- approver_group_ids (list): Group IDs whose members can approve MRs.
+ approver_ids (list): User IDs that can approve MRs
+ approver_group_ids (list): Group IDs whose members can approve MRs
Raises:
GitlabAuthenticationError: If authentication is not correct
@@ -2777,10 +2808,7 @@ class ProjectApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
path = '/projects/%s/approvers' % self._parent.get_id()
data = {'approver_ids': approver_ids,
'approver_group_ids': approver_group_ids}
- try:
- self.gitlab.http_put(path, post_data=data, **kwargs)
- except exc.GitlabHttpError as e:
- raise exc.GitlabUpdateError(e.response_code, e.error_message)
+ self.gitlab.http_put(path, post_data=data, **kwargs)
class ProjectDeployment(RESTObject):
diff --git a/tools/ee-test.py b/tools/ee-test.py
index 748130d..760ac7e 100755
--- a/tools/ee-test.py
+++ b/tools/ee-test.py
@@ -5,6 +5,7 @@ import gitlab
P1 = 'root/project1'
P2 = 'root/project2'
+MR_P1 = 1
I_P1 = 1
I_P2 = 1
G1 = 'group1'
@@ -26,6 +27,7 @@ project2 = gl.projects.get(P2)
issue_p1 = project1.issues.get(I_P1)
issue_p2 = project2.issues.get(I_P2)
group1 = gl.groups.get(G1)
+mr = project1.mergerequests.get(1)
start_log('MR approvals')
approval = project1.approvals.get()
@@ -37,6 +39,19 @@ assert(v != approval.reset_approvals_on_push)
project1.approvals.set_approvers([1], [])
approval = project1.approvals.get()
assert(approval.approvers[0]['user']['id'] == 1)
+
+approval = mr.approvals.get()
+approval.approvals_required = 2
+approval.save()
+approval = mr.approvals.get()
+assert(approval.approvals_required == 2)
+approval.approvals_required = 3
+approval.save()
+approval = mr.approvals.get()
+assert(approval.approvals_required == 3)
+mr.approvals.set_approvers([1], [])
+approval = mr.approvals.get()
+assert(approval.approvers[0]['user']['id'] == 1)
end_log()
start_log('geo nodes')