← 返回首页
feat: introduce related_issues to merge requests (#2996) · python-gitlab/python-gitlab@174d992 · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Commit 174d992

Browse files
authored
feat: introduce related_issues to merge requests (#2996)
1 parent a2ab54c commit 174d992

3 files changed

Lines changed: 137 additions & 0 deletions

File tree

‎docs/gl_objects/merge_requests.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ List the changes of a MR::
144144

145145
changes = mr.changes()
146146

147+
List issues related to this merge request::
148+
149+
related_issues = mr.related_issues()
150+
147151
List issues that will close on merge::
148152

149153
mr.closes_issues()

‎gitlab/v4/objects/merge_requests.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,35 @@ def cancel_merge_when_pipeline_succeeds(self, **kwargs: Any) -> Dict[str, str]:
197197
assert isinstance(server_data, dict)
198198
return server_data
199199

200+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
201+
@exc.on_http_error(exc.GitlabListError)
202+
def related_issues(self, **kwargs: Any) -> RESTObjectList:
203+
"""List issues related to this merge request."
204+
205+
Args:
206+
all: If True, return all the items, without pagination
207+
per_page: Number of items to retrieve per request
208+
page: ID of the page to return (starts with page 1)
209+
**kwargs: Extra options to send to the server (e.g. sudo)
210+
211+
Raises:
212+
GitlabAuthenticationError: If authentication is not correct
213+
GitlabListError: If the list could not be retrieved
214+
215+
Returns:
216+
List of issues
217+
"""
218+
219+
path = f"{self.manager.path}/{self.encoded_id}/related_issues"
220+
data_list = self.manager.gitlab.http_list(path, iterator=True, **kwargs)
221+
222+
if TYPE_CHECKING:
223+
assert isinstance(data_list, gitlab.GitlabList)
224+
225+
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
226+
227+
return RESTObjectList(manager, ProjectIssue, data_list)
228+
200229
@cli.register_custom_action(cls_names="ProjectMergeRequest")
201230
@exc.on_http_error(exc.GitlabListError)
202231
def closes_issues(self, **kwargs: Any) -> RESTObjectList:

‎tests/unit/objects/test_merge_requests.py‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import pytest
1010
import responses
1111

12+
from gitlab.base import RESTObjectList
1213
from gitlab.v4.objects import (
1314
ProjectDeploymentMergeRequest,
15+
ProjectIssue,
1416
ProjectMergeRequest,
1517
ProjectMergeRequestReviewerDetail,
1618
)
@@ -57,6 +59,78 @@
5759
}
5860
]
5961

62+
related_issues = [
63+
{
64+
"id": 1,
65+
"iid": 1,
66+
"project_id": 1,
67+
"title": "Fake Title for Merge Requests via API",
68+
"description": "Something here",
69+
"state": "closed",
70+
"created_at": "2024-05-14T04:01:40.042Z",
71+
"updated_at": "2024-06-13T05:29:13.661Z",
72+
"closed_at": "2024-06-13T05:29:13.602Z",
73+
"closed_by": {
74+
"id": 2,
75+
"name": "Sam Bauch",
76+
"username": "kenyatta_oconnell",
77+
"state": "active",
78+
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
79+
"web_url": "http://gitlab.example.com/kenyatta_oconnell",
80+
},
81+
"labels": [
82+
"FakeCategory",
83+
"fake:ml",
84+
],
85+
"assignees": [
86+
{
87+
"id": 2,
88+
"name": "Sam Bauch",
89+
"username": "kenyatta_oconnell",
90+
"state": "active",
91+
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
92+
"web_url": "http://gitlab.example.com/kenyatta_oconnell",
93+
}
94+
],
95+
"author": {
96+
"id": 2,
97+
"name": "Sam Bauch",
98+
"username": "kenyatta_oconnell",
99+
"state": "active",
100+
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
101+
"web_url": "http://gitlab.example.com//kenyatta_oconnell",
102+
},
103+
"type": "ISSUE",
104+
"assignee": {
105+
"id": 4459593,
106+
"username": "fakeuser",
107+
"name": "Fake User",
108+
"state": "active",
109+
"locked": False,
110+
"avatar_url": "https://example.com/uploads/-/system/user/avatar/4459593/avatar.png",
111+
"web_url": "https://example.com/fakeuser",
112+
},
113+
"user_notes_count": 9,
114+
"merge_requests_count": 0,
115+
"upvotes": 1,
116+
"downvotes": 0,
117+
"due_date": None,
118+
"confidential": False,
119+
"discussion_locked": None,
120+
"issue_type": "issue",
121+
"web_url": "https://example.com/fakeorg/fakeproject/-/issues/461536",
122+
"time_stats": {
123+
"time_estimate": 0,
124+
"total_time_spent": 0,
125+
"human_time_estimate": None,
126+
"human_total_time_spent": None,
127+
},
128+
"task_completion_status": {"count": 0, "completed_count": 0},
129+
"weight": None,
130+
"blocking_issues_count": 0,
131+
}
132+
]
133+
60134

61135
@pytest.fixture
62136
def resp_list_merge_requests():
@@ -93,6 +167,26 @@ def resp_get_merge_request_reviewers():
93167
yield rsps
94168

95169

170+
@pytest.fixture
171+
def resp_list_merge_requests_related_issues():
172+
with responses.RequestsMock() as rsps:
173+
rsps.add(
174+
method=responses.GET,
175+
url="http://localhost/api/v4/projects/1/merge_requests/1",
176+
json=mr_content,
177+
content_type="application/json",
178+
status=200,
179+
)
180+
rsps.add(
181+
method=responses.GET,
182+
url="http://localhost/api/v4/projects/1/merge_requests/1/related_issues",
183+
json=related_issues,
184+
content_type="application/json",
185+
status=200,
186+
)
187+
yield rsps
188+
189+
96190
def test_list_project_merge_requests(project, resp_list_merge_requests):
97191
mrs = project.mergerequests.list()
98192
assert isinstance(mrs[0], ProjectMergeRequest)
@@ -115,3 +209,13 @@ def test_get_merge_request_reviewers(project, resp_get_merge_request_reviewers):
115209
assert mr.reviewers[0]["name"] == reviewers_details[0].user["name"]
116210
assert reviewers_details[0].state == "unreviewed"
117211
assert reviewers_details[0].created_at == "2022-07-27T17:03:27.684Z"
212+
213+
214+
def test_list_related_issues(project, resp_list_merge_requests_related_issues):
215+
mr = project.mergerequests.get(1)
216+
this_mr_related_issues = mr.related_issues()
217+
the_issue = next(iter(this_mr_related_issues))
218+
assert isinstance(mr, ProjectMergeRequest)
219+
assert isinstance(this_mr_related_issues, RESTObjectList)
220+
assert isinstance(the_issue, ProjectIssue)
221+
assert the_issue.title == related_issues[0]["title"]

0 commit comments

Comments
 (0)

Footer

© 2026 GitHub, Inc.