diff options
| -rw-r--r-- | docs/gl_objects/geo_nodes.rst | 2 | ||||
| -rw-r--r-- | docs/gl_objects/issues.rst | 38 | ||||
| -rw-r--r-- | gitlab/v4/objects.py | 38 | ||||
| -rwxr-xr-x | tools/ee-test.py | 31 |
4 files changed, 102 insertions, 7 deletions
diff --git a/docs/gl_objects/geo_nodes.rst b/docs/gl_objects/geo_nodes.rst index 44ed391..181ec91 100644 --- a/docs/gl_objects/geo_nodes.rst +++ b/docs/gl_objects/geo_nodes.rst @@ -11,7 +11,7 @@ Reference + :class:`gitlab.v4.objects.GeoNodeManager` + :attr:`gitlab.Gitlab.geonodes` -* GitLab API: https://docs.gitlab.com/ee/api/geo_nodes.html +* GitLab API: https://docs.gitlab.com/ee/api/geo_nodes.html (EE feature) Examples -------- diff --git a/docs/gl_objects/issues.rst b/docs/gl_objects/issues.rst index 0a6b254..7abaa78 100644 --- a/docs/gl_objects/issues.rst +++ b/docs/gl_objects/issues.rst @@ -159,3 +159,41 @@ Get the list of merge requests that will close an issue when merged:: Get the list of participants:: users = issue.participants() + +Issue links +=========== + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectIssueLink` + + :class:`gitlab.v4.objects.ProjectIssueLinkManager` + + :attr:`gitlab.v4.objects.ProjectIssue.links` + +* GitLab API: https://docs.gitlab.com/ee/api/issue_links.html (EE feature) + +Examples +-------- + +List the issues linked to ``i1``:: + + links = i1.links.list() + +Link issue ``i1`` to issue ``i2``:: + + data = { + 'target_project_id': i2.project_id, + 'target_issue_iid': i2.iid + } + src_issue, dest_issue = i1.links.create(data) + +.. note:: + + The ``create()`` method returns the source and destination ``ProjectIssue`` + objects, not a ``ProjectIssueLink`` object. + +Delete a link:: + + i1.links.delete(issue_link_id) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 8feb09b..f5160e5 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1539,6 +1539,43 @@ class ProjectIssueDiscussionManager(RetrieveMixin, CreateMixin, RESTManager): _create_attrs = (('body',), ('created_at',)) +class ProjectIssueLink(ObjectDeleteMixin, RESTObject): + _id_attr = 'issue_link_id' + + +class ProjectIssueLinkManager(ListMixin, CreateMixin, DeleteMixin, + RESTManager): + _path = '/projects/%(project_id)s/issues/%(issue_iid)s/links' + _obj_cls = ProjectIssueLink + _from_parent_attrs = {'project_id': 'project_id', 'issue_iid': 'iid'} + _create_attrs = (('target_project_id', 'target_issue_iid'), tuple()) + + @exc.on_http_error(exc.GitlabCreateError) + def create(self, data, **kwargs): + """Create a new object. + + Args: + data (dict): parameters to send to the server to create the + resource + **kwargs: Extra options to send to the Gitlab server (e.g. sudo) + + Returns: + RESTObject, RESTObject: The source and target issues + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabCreateError: If the server cannot perform the request + """ + self._check_missing_create_attrs(data) + server_data = self.gitlab.http_post(self.path, post_data=data, + **kwargs) + source_issue = ProjectIssue(self._parent.manager, + server_data['source_issue']) + target_issue = ProjectIssue(self._parent.manager, + server_data['target_issue']) + return source_issue, target_issue + + class ProjectIssue(UserAgentDetailMixin, SubscribableMixin, TodoMixin, TimeTrackingMixin, ParticipantsMixin, SaveMixin, ObjectDeleteMixin, RESTObject): @@ -1547,6 +1584,7 @@ class ProjectIssue(UserAgentDetailMixin, SubscribableMixin, TodoMixin, _managers = ( ('awardemojis', 'ProjectIssueAwardEmojiManager'), ('discussions', 'ProjectIssueDiscussionManager'), + ('links', 'ProjectIssueLinkManager'), ('notes', 'ProjectIssueNoteManager'), ) diff --git a/tools/ee-test.py b/tools/ee-test.py index 792c28e..77ccd2e 100755 --- a/tools/ee-test.py +++ b/tools/ee-test.py @@ -3,7 +3,11 @@ import gitlab -PROJECT_NAME = 'root/project1' +P1 = 'root/project1' +P2 = 'root/project2' +I_P1 = 1 +I_P2 = 1 + def start_log(message): print('Testing %s... ' % message, end='') @@ -14,17 +18,20 @@ def end_log(): gl = gitlab.Gitlab.from_config('ee') -project = gl.projects.get(PROJECT_NAME) +project1 = gl.projects.get(P1) +project2 = gl.projects.get(P2) +issue_p1 = project1.issues.get(I_P1) +issue_p2 = project2.issues.get(I_P2) start_log('MR approvals') -approval = project.approvals.get() +approval = project1.approvals.get() v = approval.reset_approvals_on_push approval.reset_approvals_on_push = not v approval.save() -approval = project.approvals.get() +approval = project1.approvals.get() assert(v != approval.reset_approvals_on_push) -project.approvals.set_approvers([1], []) -approval = project.approvals.get() +project1.approvals.set_approvers([1], []) +approval = project1.approvals.get() assert(approval.approvers[0]['user']['id'] == 1) end_log() @@ -33,3 +40,15 @@ start_log('geo nodes') nodes = gl.geonodes.list() status = gl.geonodes.status() end_log() + +start_log('issue links') +# bit of cleanup just in case +for link in issue_p1.links.list(): + issue_p1.links.delete(link.issue_link_id) + +src, dst = issue_p1.links.create({'target_project_id': P2, + 'target_issue_iid': I_P2}) +links = issue_p1.links.list() +link_id = links[0].issue_link_id +issue_p1.links.delete(link_id) +end_log() |
