Skip to content

Commit 6bd04ca

Browse files
fix: adds missing status check methods for merge requests
1 parent f62dda7 commit 6bd04ca

File tree

5 files changed

+135
-7
lines changed

5 files changed

+135
-7
lines changed

docs/gl_objects/status_checks.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,18 @@ Delete an external status check::
5555

5656
status_check.delete(status_check_id)
5757

58+
List external status check for a project merge request::
59+
60+
merge_request = project.mergerequests.get(1)
61+
62+
merge_request.status_checks.list()
63+
64+
Set external status check for a project merge request::
65+
66+
merge_request = project.mergerequests.get(1)
67+
68+
merge_request.status_check_response.update({
69+
"external_status_check_id": status_check_id,
70+
"status": "passed",
71+
"sha": merge_request.sha
72+
})

gitlab/v4/objects/merge_requests.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@
4646
from .notes import ProjectMergeRequestNoteManager # noqa: F401
4747
from .pipelines import ProjectMergeRequestPipelineManager # noqa: F401
4848
from .reviewers import ProjectMergeRequestReviewerDetailManager
49-
from .status_checks import ProjectMergeRequestStatusCheckManager
49+
from .status_checks import (
50+
ProjectMergeRequestStatusCheckManager,
51+
ProjectMergeRequestStatusCheckResponseManager,
52+
)
5053

5154
__all__ = [
5255
"MergeRequest",
@@ -171,6 +174,7 @@ class ProjectMergeRequest(
171174
resourcestateevents: ProjectMergeRequestResourceStateEventManager
172175
reviewer_details: ProjectMergeRequestReviewerDetailManager
173176
status_checks: ProjectMergeRequestStatusCheckManager
177+
status_check_response: ProjectMergeRequestStatusCheckResponseManager
174178

175179
@cli.register_custom_action(cls_names="ProjectMergeRequest")
176180
@exc.on_http_error(exc.GitlabMROnBuildSuccessError)

gitlab/v4/objects/status_checks.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from gitlab.base import RESTObject
1+
from typing import Any, Dict, Optional
2+
3+
from gitlab.base import RESTManager, RESTObject
24
from gitlab.mixins import (
35
CreateMixin,
46
DeleteMixin,
@@ -27,6 +29,7 @@ class ProjectExternalStatusCheckManager(
2729
CreateMixin[ProjectExternalStatusCheck],
2830
UpdateMixin[ProjectExternalStatusCheck],
2931
DeleteMixin[ProjectExternalStatusCheck],
32+
RESTManager[ProjectExternalStatusCheck],
3033
):
3134
_path = "/projects/{project_id}/external_status_checks"
3235
_obj_cls = ProjectExternalStatusCheck
@@ -41,15 +44,41 @@ class ProjectExternalStatusCheckManager(
4144
_types = {"protected_branch_ids": ArrayAttribute}
4245

4346

44-
class ProjectMergeRequestStatusCheck(SaveMixin, RESTObject):
47+
class ProjectMergeRequestStatusCheckResponse(SaveMixin, RESTObject):
4548
pass
4649

4750

48-
class ProjectMergeRequestStatusCheckManager(ListMixin[ProjectMergeRequestStatusCheck]):
49-
_path = "/projects/{project_id}/merge_requests/{merge_request_iid}/status_checks"
50-
_obj_cls = ProjectMergeRequestStatusCheck
51-
_from_parent_attrs = {"project_id": "project_id", "merge_request_iid": "iid"}
51+
class ProjectMergeRequestStatusCheckResponseManager(
52+
UpdateMixin[ProjectMergeRequestStatusCheckResponse],
53+
RESTManager[ProjectMergeRequestStatusCheckResponse],
54+
):
55+
_path = "/projects/{project_id}/merge_requests/{mr_iid}/status_check_responses"
56+
_obj_cls = ProjectMergeRequestStatusCheckResponse
57+
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}
5258
_update_attrs = RequiredOptional(
5359
required=("sha", "external_status_check_id", "status")
5460
)
5561
_update_method = UpdateMethod.POST
62+
63+
def update( # type: ignore[override]
64+
self, new_data: Optional[Dict[str, Any]] = None, **kwargs: Any
65+
) -> Dict[str, Any]:
66+
"""Update a Label on the server.
67+
68+
Args:
69+
**kwargs: Extra options to send to the server (e.g. sudo)
70+
"""
71+
return super().update(id=None, new_data=new_data, **kwargs)
72+
73+
74+
class ProjectMergeRequestStatusCheck(RESTObject):
75+
pass
76+
77+
78+
class ProjectMergeRequestStatusCheckManager(
79+
ListMixin[ProjectMergeRequestStatusCheck],
80+
RESTManager[ProjectMergeRequestStatusCheck],
81+
):
82+
_path = "/projects/{project_id}/merge_requests/{mr_iid}/status_checks"
83+
_obj_cls = ProjectMergeRequestStatusCheck
84+
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}

tests/functional/api/test_merge_requests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,15 @@ def test_merge_request_merge_ref_should_fail(project, merge_request) -> None:
300300
with pytest.raises(gitlab.exceptions.GitlabGetError):
301301
response = merge_request.merge_ref()
302302
assert "commit_id" not in response
303+
304+
305+
@pytest.mark.gitlab_premium
306+
def test_merge_request_external_status_check_list(project, merge_request):
307+
project.external_status_checks.create(
308+
{"name": "MR blocker", "external_url": "https://example.com/mr-blocker"}
309+
)
310+
311+
time.sleep(3)
312+
313+
mr_status_checks = merge_request.status_checks.list()
314+
assert len(mr_status_checks) == 1

tests/unit/objects/test_status_checks.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,48 @@
55
import pytest
66
import responses
77

8+
mr_content = {
9+
"id": 1,
10+
"iid": 1,
11+
"project_id": 1,
12+
"title": "test1",
13+
"description": "fixed login page css paddings",
14+
"state": "merged",
15+
"merged_by": {
16+
"id": 87854,
17+
"name": "Douwe Maan",
18+
"username": "DouweM",
19+
"state": "active",
20+
"avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
21+
"web_url": "https://gitlab.com/DouweM",
22+
},
23+
"reviewers": [
24+
{
25+
"id": 2,
26+
"name": "Sam Bauch",
27+
"username": "kenyatta_oconnell",
28+
"state": "active",
29+
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
30+
"web_url": "http://gitlab.example.com//kenyatta_oconnell",
31+
}
32+
],
33+
}
34+
35+
external_status_checks_content = [
36+
{
37+
"id": 2,
38+
"name": "Service 2",
39+
"external_url": "https://gitlab.example.com/test-endpoint-2",
40+
"status": "passed",
41+
},
42+
{
43+
"id": 1,
44+
"name": "Service 1",
45+
"external_url": "https://gitlab.example.com/test-endpoint-1",
46+
"status": "pending",
47+
},
48+
]
49+
850

951
@pytest.fixture
1052
def external_status_check():
@@ -107,6 +149,26 @@ def resp_delete_external_status_checks():
107149
yield rsps
108150

109151

152+
@pytest.fixture
153+
def resp_list_merge_requests_status_checks():
154+
with responses.RequestsMock() as rsps:
155+
rsps.add(
156+
method=responses.GET,
157+
url="http://localhost/api/v4/projects/1/merge_requests/1",
158+
json=mr_content,
159+
content_type="application/json",
160+
status=200,
161+
)
162+
rsps.add(
163+
method=responses.GET,
164+
url="http://localhost/api/v4/projects/1/merge_requests/1/status_checks",
165+
json=external_status_checks_content,
166+
content_type="application/json",
167+
status=200,
168+
)
169+
yield rsps
170+
171+
110172
def test_list_external_status_checks(gl, resp_list_external_status_checks):
111173
status_checks = gl.projects.get(1, lazy=True).external_status_checks.list()
112174
assert len(status_checks) == 1
@@ -125,3 +187,9 @@ def test_delete_external_status_checks(gl, resp_delete_external_status_checks):
125187
gl.projects.get(1, lazy=True).external_status_checks.delete(1)
126188
status_checks = gl.projects.get(1, lazy=True).external_status_checks.list()
127189
assert len(status_checks) == 0
190+
191+
192+
def test_get_merge_request_status_checks(gl, resp_list_merge_requests_status_checks):
193+
merge_request = gl.projects.get(1, lazy=True).mergerequests.get(1)
194+
status_checks = merge_request.status_checks.list()
195+
assert len(status_checks) == 2

0 commit comments

Comments
 (0)