diff --git a/docs/api-objects.rst b/docs/api-objects.rst index 8221f63b8..cd57f977b 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -24,6 +24,7 @@ API examples gl_objects/geo_nodes gl_objects/groups gl_objects/issues + gl_objects/iterations gl_objects/boards gl_objects/labels gl_objects/notifications diff --git a/docs/gl_objects/iterations.rst b/docs/gl_objects/iterations.rst new file mode 100644 index 000000000..cc2099961 --- /dev/null +++ b/docs/gl_objects/iterations.rst @@ -0,0 +1,63 @@ +########## +Iterations +########## + +Project Iterations +================== + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectIteration` + + :class:`gitlab.v4.objects.ProjectIterationManager` + + :attr:`gitlab.v4.objects.Project.iterations` + + + :class:`gitlab.v4.objects.GroupIteration` + + :class:`gitlab.v4.objects.GroupIterationManager` + + :attr:`gitlab.v4.objects.Group.iterations` + +* GitLab API: + + + https://docs.gitlab.com/ee/api/iterations.html + + https://docs.gitlab.com/ee/api/group_iterations.html + +Examples +-------- + +List the iterations for a project or a group:: + + p_iterations = project.iterations.list() + g_iterations = group.iterations.list() + +You can filter the list using the following parameters: + +* ``iids``: unique IDs of iterations for the project +* ``state``: either ``opened``, ``upcoming``, ``started``, ``closed``, or ``all`` iterations. Defaults to ``all``. +* ``search``: search only iterations with a title matching the provided string. + + +:: + + p_iterationss = project.iterations.list(state='closed') + g_iterationss = group.iterations.list(state='opened') + +Get a single iteration:: + + p_iteration = project.iterations.get(interation_id) + g_iteration = group.iterations.get(interation_id) + +Create a iteration:: + + iteration = project.iterations.create({'title': 'Week 22-23'}) + +Edit an interation:: + + iteration.description = 'v 1.0 release' + iterations.save() + + +List the issues related to a milestone:: + + issues = iteration.issues() diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py index edeff044e..6b59332c3 100644 --- a/gitlab/v4/objects/__init__.py +++ b/gitlab/v4/objects/__init__.py @@ -1084,6 +1084,7 @@ class GroupIssueManager(ListMixin, RESTManager): "state", "labels", "milestone", + "iteration", "order_by", "sort", "iids", @@ -1296,6 +1297,40 @@ class GroupMilestoneManager(CRUDMixin, RESTManager): _list_filters = ("iids", "state", "search") +class GroupIteration(SaveMixin, ObjectDeleteMixin, RESTObject): + _short_print_attr = "title" + + @cli.register_custom_action("GroupIteration") + @exc.on_http_error(exc.GitlabListError) + def issues(self, **kwargs): + """List issues related to this Iteration. + + 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: + The list of issues + """ + manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent) + return manager.list(iteration_id=self.get_id(), **kwargs) + + +class GroupIterationManager(CRUDMixin, RESTManager): + _path = "/groups/%(group_id)s/iterations" + _obj_cls = GroupIteration + _from_parent_attrs = {"group_id": "id"} + _create_attrs = (("title",), ("description", "due_date", "start_date")) + _update_attrs = ( + tuple(), + ("title", "description", "due_date", "start_date", "state"), + ) + _list_filters = ("iids", "state", "search") + + class GroupNotificationSettings(NotificationSettings): pass @@ -1396,6 +1431,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject): ("members", "GroupMemberManager"), ("mergerequests", "GroupMergeRequestManager"), ("milestones", "GroupMilestoneManager"), + ("iterations", "GroupIterationManager"), ("notificationsettings", "GroupNotificationSettingsManager"), ("packages", "GroupPackageManager"), ("projects", "GroupProjectManager"), @@ -1648,6 +1684,7 @@ class IssueManager(ListMixin, RESTManager): "state", "labels", "milestone", + "iteration", "scope", "author_id", "assignee_id", @@ -2781,6 +2818,7 @@ class ProjectIssueManager(CRUDMixin, RESTManager): "state", "labels", "milestone", + "iteration", "scope", "author_id", "assignee_id", @@ -2801,6 +2839,7 @@ class ProjectIssueManager(CRUDMixin, RESTManager): "assignee_ids", "assignee_id", "milestone_id", + "iteration_id", "labels", "created_at", "due_date", @@ -2817,6 +2856,7 @@ class ProjectIssueManager(CRUDMixin, RESTManager): "assignee_ids", "assignee_id", "milestone_id", + "iteration_id", "labels", "state_event", "updated_at", @@ -2913,11 +2953,11 @@ class ProjectPagesDomainManager(CRUDMixin, RESTManager): _update_attrs = (tuple(), ("certificate", "key")) -class ProjectRelease(RESTObject): +class ProjectRelease(SaveMixin, RESTObject): _id_attr = "tag_name" -class ProjectReleaseManager(NoUpdateMixin, RESTManager): +class ProjectReleaseManager(CRUDMixin, RESTManager): _path = "/projects/%(project_id)s/releases" _obj_cls = ProjectRelease _from_parent_attrs = {"project_id": "id"} @@ -3576,6 +3616,45 @@ class ProjectMilestoneManager(CRUDMixin, RESTManager): _list_filters = ("iids", "state", "search") +class ProjectIteration(SaveMixin, ObjectDeleteMixin, RESTObject): + _short_print_attr = "title" + + @cli.register_custom_action("ProjectIteration") + @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: + The list of issues + """ + + manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent) + + return manager.list(iteration_id=self.get_id(), **kwargs) + + +class ProjectIterationManager(CRUDMixin, RESTManager): + _path = "/projects/%(project_id)s/iterations" + _obj_cls = ProjectIteration + _from_parent_attrs = {"project_id": "id"} + _create_attrs = ( + ("title",), + ("description", "due_date", "start_date", "state"), + ) + _update_attrs = ( + tuple(), + ("title", "description", "due_date", "start_date", "state"), + ) + _list_filters = ("iids", "state", "search") + + class ProjectLabel(SubscribableMixin, SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "name" @@ -4690,6 +4769,7 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject): ("members", "ProjectMemberManager"), ("mergerequests", "ProjectMergeRequestManager"), ("milestones", "ProjectMilestoneManager"), + ("iterations", "ProjectIterationManager"), ("notes", "ProjectNoteManager"), ("notificationsettings", "ProjectNotificationSettingsManager"), ("packages", "ProjectPackageManager"),