summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/gl_objects/milestones.py10
-rw-r--r--docs/gl_objects/milestones.rst12
-rw-r--r--gitlab/v4/objects.py80
-rw-r--r--tools/python_test_v4.py16
4 files changed, 106 insertions, 12 deletions
diff --git a/docs/gl_objects/milestones.py b/docs/gl_objects/milestones.py
index 19770bc..d1985d9 100644
--- a/docs/gl_objects/milestones.py
+++ b/docs/gl_objects/milestones.py
@@ -1,13 +1,16 @@
# list
-milestones = project.milestones.list()
+p_milestones = project.milestones.list()
+g_milestones = group.milestones.list()
# end list
# filter
-milestones = project.milestones.list(state='closed')
+p_milestones = project.milestones.list(state='closed')
+g_milestones = group.milestones.list(state='active')
# end filter
# get
-milestone = project.milestones.get(milestone_id)
+p_milestone = project.milestones.get(milestone_id)
+g_milestone = group.milestones.get(milestone_id)
# end get
# create
@@ -36,4 +39,3 @@ issues = milestone.issues()
# merge_requests
merge_requests = milestone.merge_requests()
# end merge_requests
-
diff --git a/docs/gl_objects/milestones.rst b/docs/gl_objects/milestones.rst
index fbe5d87..c96560a 100644
--- a/docs/gl_objects/milestones.rst
+++ b/docs/gl_objects/milestones.rst
@@ -11,6 +11,10 @@ Reference
+ :class:`gitlab.v4.objects.ProjectMilestoneManager`
+ :attr:`gitlab.v4.objects.Project.milestones`
+ + :class:`gitlab.v4.objects.GroupMilestone`
+ + :class:`gitlab.v4.objects.GroupMilestoneManager`
+ + :attr:`gitlab.v4.objects.Group.milestones`
+
* v3 API:
+ :class:`gitlab.v3.objects.ProjectMilestone`
@@ -18,12 +22,15 @@ Reference
+ :attr:`gitlab.v3.objects.Project.milestones`
+ :attr:`gitlab.Gitlab.project_milestones`
-* GitLab API: https://docs.gitlab.com/ce/api/milestones.html
+* GitLab API:
+
+ + https://docs.gitlab.com/ce/api/milestones.html
+ + https://docs.gitlab.com/ce/api/group_milestones.html
Examples
--------
-List the milestones for a project:
+List the milestones for a project or a group:
.. literalinclude:: milestones.py
:start-after: # list
@@ -33,6 +40,7 @@ You can filter the list using the following parameters:
* ``iid``: unique ID of the milestone for the project
* ``state``: either ``active`` or ``closed``
+* ``search``: to search using a string
.. literalinclude:: milestones.py
:start-after: # filter
diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py
index 1fb32b4..535c23c 100644
--- a/gitlab/v4/objects.py
+++ b/gitlab/v4/objects.py
@@ -395,6 +395,75 @@ class GroupMemberManager(GetFromListMixin, CreateMixin, UpdateMixin,
_update_attrs = (('access_level', ), ('expires_at', ))
+class GroupMergeRequest(RESTObject):
+ pass
+
+
+class GroupMergeRequestManager(RESTManager):
+ pass
+
+
+class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
+ _short_print_attr = 'title'
+
+ @cli.register_custom_action('GroupMilestone')
+ @exc.on_http_error(exc.GitlabListError)
+ def issues(self, **kwargs):
+ """List issues related to this milestone.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: The list of issues
+ """
+
+ path = '%s/%s/issues' % (self.manager.path, self.get_id())
+ data_list = self.manager.gitlab.http_list(path, as_list=False,
+ **kwargs)
+ manager = GroupIssueManager(self.manager.gitlab,
+ parent=self.manager._parent)
+ # FIXME(gpocentek): the computed manager path is not correct
+ return RESTObjectList(manager, GroupIssue, data_list)
+
+ @cli.register_custom_action('GroupMilestone')
+ @exc.on_http_error(exc.GitlabListError)
+ def merge_requests(self, **kwargs):
+ """List the merge requests related to this milestone.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabListError: If the list could not be retrieved
+
+ Returns:
+ RESTObjectList: The list of merge requests
+ """
+ path = '%s/%s/merge_requests' % (self.manager.path, self.get_id())
+ data_list = self.manager.gitlab.http_list(path, as_list=False,
+ **kwargs)
+ manager = GroupIssueManager(self.manager.gitlab,
+ parent=self.manager._parent)
+ # FIXME(gpocentek): the computed manager path is not correct
+ return RESTObjectList(manager, GroupMergeRequest, data_list)
+
+
+class GroupMilestoneManager(CRUDMixin, RESTManager):
+ _path = '/groups/%(group_id)s/milestones'
+ _obj_cls = GroupMilestone
+ _from_parent_attrs = {'group_id': 'id'}
+ _create_attrs = (('title', ), ('description', 'due_date', 'start_date'))
+ _update_attrs = (tuple(), ('title', 'description', 'due_date',
+ 'start_date', 'state_event'))
+ _list_filters = ('iids', 'state', 'search')
+
+
class GroupNotificationSettings(NotificationSettings):
pass
@@ -434,6 +503,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
_managers = (
('accessrequests', 'GroupAccessRequestManager'),
('members', 'GroupMemberManager'),
+ ('milestones', 'GroupMilestoneManager'),
('notificationsettings', 'GroupNotificationSettingsManager'),
('projects', 'GroupProjectManager'),
('issues', 'GroupIssueManager'),
@@ -1293,8 +1363,8 @@ class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
path = '%s/%s/issues' % (self.manager.path, self.get_id())
data_list = self.manager.gitlab.http_list(path, as_list=False,
**kwargs)
- manager = ProjectCommitManager(self.manager.gitlab,
- parent=self.manager._parent)
+ manager = ProjectIssueManager(self.manager.gitlab,
+ parent=self.manager._parent)
# FIXME(gpocentek): the computed manager path is not correct
return RESTObjectList(manager, ProjectIssue, data_list)
@@ -1316,8 +1386,8 @@ class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
path = '%s/%s/merge_requests' % (self.manager.path, self.get_id())
data_list = self.manager.gitlab.http_list(path, as_list=False,
**kwargs)
- manager = ProjectCommitManager(self.manager.gitlab,
- parent=self.manager._parent)
+ manager = ProjectMergeRequestManager(self.manager.gitlab,
+ parent=self.manager._parent)
# FIXME(gpocentek): the computed manager path is not correct
return RESTObjectList(manager, ProjectMergeRequest, data_list)
@@ -1330,7 +1400,7 @@ class ProjectMilestoneManager(CRUDMixin, RESTManager):
'state_event'))
_update_attrs = (tuple(), ('title', 'description', 'due_date',
'start_date', 'state_event'))
- _list_filters = ('iids', 'state')
+ _list_filters = ('iids', 'state', 'search')
class ProjectLabel(SubscribableMixin, SaveMixin, ObjectDeleteMixin,
diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py
index 386b59b..1c1d4d3 100644
--- a/tools/python_test_v4.py
+++ b/tools/python_test_v4.py
@@ -170,6 +170,18 @@ settings.save()
settings = group2.notificationsettings.get()
assert(settings.level == 'disabled')
+# group milestones
+gm1 = group1.milestones.create({'title': 'groupmilestone1'})
+assert(len(group1.milestones.list()) == 1)
+gm1.due_date = '2020-01-01T00:00:00Z'
+gm1.save()
+gm1.state_event = 'close'
+gm1.save()
+gm1 = group1.milestones.get(gm1.id)
+assert(gm1.state == 'closed')
+assert(len(gm1.issues()) == 0)
+assert(len(gm1.merge_requests()) == 0)
+
# group variables
group1.variables.create({'key': 'foo', 'value': 'bar'})
g_v = group1.variables.get('foo')
@@ -330,8 +342,10 @@ m1.due_date = '2020-01-01T00:00:00Z'
m1.save()
m1.state_event = 'close'
m1.save()
-m1 = admin_project.milestones.get(1)
+m1 = admin_project.milestones.get(m1.id)
assert(m1.state == 'closed')
+assert(len(m1.issues()) == 0)
+assert(len(m1.merge_requests()) == 0)
# issues
issue1 = admin_project.issues.create({'title': 'my issue 1',