Skip to content

Commit 8873eda

Browse files
author
Gauvain Pocentek
committed
Add support for issue links (EE)
Fixes #422
1 parent 39c8ad5 commit 8873eda

File tree

4 files changed

+102
-7
lines changed

4 files changed

+102
-7
lines changed

docs/gl_objects/geo_nodes.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Reference
1111
+ :class:`gitlab.v4.objects.GeoNodeManager`
1212
+ :attr:`gitlab.Gitlab.geonodes`
1313

14-
* GitLab API: https://docs.gitlab.com/ee/api/geo_nodes.html
14+
* GitLab API: https://docs.gitlab.com/ee/api/geo_nodes.html (EE feature)
1515

1616
Examples
1717
--------

docs/gl_objects/issues.rst

+38
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,41 @@ Get the list of merge requests that will close an issue when merged::
159159
Get the list of participants::
160160

161161
users = issue.participants()
162+
163+
Issue links
164+
===========
165+
166+
Reference
167+
---------
168+
169+
* v4 API:
170+
171+
+ :class:`gitlab.v4.objects.ProjectIssueLink`
172+
+ :class:`gitlab.v4.objects.ProjectIssueLinkManager`
173+
+ :attr:`gitlab.v4.objects.ProjectIssue.links`
174+
175+
* GitLab API: https://docs.gitlab.com/ee/api/issue_links.html (EE feature)
176+
177+
Examples
178+
--------
179+
180+
List the issues linked to ``i1``::
181+
182+
links = i1.links.list()
183+
184+
Link issue ``i1`` to issue ``i2``::
185+
186+
data = {
187+
'target_project_id': i2.project_id,
188+
'target_issue_iid': i2.iid
189+
}
190+
src_issue, dest_issue = i1.links.create(data)
191+
192+
.. note::
193+
194+
The ``create()`` method returns the source and destination ``ProjectIssue``
195+
objects, not a ``ProjectIssueLink`` object.
196+
197+
Delete a link::
198+
199+
i1.links.delete(issue_link_id)

gitlab/v4/objects.py

+38
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,43 @@ class ProjectIssueDiscussionManager(RetrieveMixin, CreateMixin, RESTManager):
15391539
_create_attrs = (('body',), ('created_at',))
15401540

15411541

1542+
class ProjectIssueLink(ObjectDeleteMixin, RESTObject):
1543+
_id_attr = 'issue_link_id'
1544+
1545+
1546+
class ProjectIssueLinkManager(ListMixin, CreateMixin, DeleteMixin,
1547+
RESTManager):
1548+
_path = '/projects/%(project_id)s/issues/%(issue_iid)s/links'
1549+
_obj_cls = ProjectIssueLink
1550+
_from_parent_attrs = {'project_id': 'project_id', 'issue_iid': 'iid'}
1551+
_create_attrs = (('target_project_id', 'target_issue_iid'), tuple())
1552+
1553+
@exc.on_http_error(exc.GitlabCreateError)
1554+
def create(self, data, **kwargs):
1555+
"""Create a new object.
1556+
1557+
Args:
1558+
data (dict): parameters to send to the server to create the
1559+
resource
1560+
**kwargs: Extra options to send to the Gitlab server (e.g. sudo)
1561+
1562+
Returns:
1563+
RESTObject, RESTObject: The source and target issues
1564+
1565+
Raises:
1566+
GitlabAuthenticationError: If authentication is not correct
1567+
GitlabCreateError: If the server cannot perform the request
1568+
"""
1569+
self._check_missing_create_attrs(data)
1570+
server_data = self.gitlab.http_post(self.path, post_data=data,
1571+
**kwargs)
1572+
source_issue = ProjectIssue(self._parent.manager,
1573+
server_data['source_issue'])
1574+
target_issue = ProjectIssue(self._parent.manager,
1575+
server_data['target_issue'])
1576+
return source_issue, target_issue
1577+
1578+
15421579
class ProjectIssue(UserAgentDetailMixin, SubscribableMixin, TodoMixin,
15431580
TimeTrackingMixin, ParticipantsMixin, SaveMixin,
15441581
ObjectDeleteMixin, RESTObject):
@@ -1547,6 +1584,7 @@ class ProjectIssue(UserAgentDetailMixin, SubscribableMixin, TodoMixin,
15471584
_managers = (
15481585
('awardemojis', 'ProjectIssueAwardEmojiManager'),
15491586
('discussions', 'ProjectIssueDiscussionManager'),
1587+
('links', 'ProjectIssueLinkManager'),
15501588
('notes', 'ProjectIssueNoteManager'),
15511589
)
15521590

tools/ee-test.py

+25-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import gitlab
44

55

6-
PROJECT_NAME = 'root/project1'
6+
P1 = 'root/project1'
7+
P2 = 'root/project2'
8+
I_P1 = 1
9+
I_P2 = 1
10+
711

812
def start_log(message):
913
print('Testing %s... ' % message, end='')
@@ -14,17 +18,20 @@ def end_log():
1418

1519

1620
gl = gitlab.Gitlab.from_config('ee')
17-
project = gl.projects.get(PROJECT_NAME)
21+
project1 = gl.projects.get(P1)
22+
project2 = gl.projects.get(P2)
23+
issue_p1 = project1.issues.get(I_P1)
24+
issue_p2 = project2.issues.get(I_P2)
1825

1926
start_log('MR approvals')
20-
approval = project.approvals.get()
27+
approval = project1.approvals.get()
2128
v = approval.reset_approvals_on_push
2229
approval.reset_approvals_on_push = not v
2330
approval.save()
24-
approval = project.approvals.get()
31+
approval = project1.approvals.get()
2532
assert(v != approval.reset_approvals_on_push)
26-
project.approvals.set_approvers([1], [])
27-
approval = project.approvals.get()
33+
project1.approvals.set_approvers([1], [])
34+
approval = project1.approvals.get()
2835
assert(approval.approvers[0]['user']['id'] == 1)
2936
end_log()
3037

@@ -33,3 +40,15 @@ def end_log():
3340
nodes = gl.geonodes.list()
3441
status = gl.geonodes.status()
3542
end_log()
43+
44+
start_log('issue links')
45+
# bit of cleanup just in case
46+
for link in issue_p1.links.list():
47+
issue_p1.links.delete(link.issue_link_id)
48+
49+
src, dst = issue_p1.links.create({'target_project_id': P2,
50+
'target_issue_iid': I_P2})
51+
links = issue_p1.links.list()
52+
link_id = links[0].issue_link_id
53+
issue_p1.links.delete(link_id)
54+
end_log()

0 commit comments

Comments
 (0)