Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

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

Provide feedback

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

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: adds missing status check methods for merge requests#3128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
SachinKSingh28 wants to merge1 commit intopython-gitlab:main
base:main
Choose a base branch
Loading
fromSachinKSingh28:fix/add-missing-status-check-methods
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletionsdocs/gl_objects/status_checks.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,11 +24,11 @@ Examples

List external status checks for a project::

status_checks = project.external_status_checks.list(get_all=True)
external_status_checks = project.external_status_checks.list()

Create an external status check with shared secret::

status_checks = project.external_status_checks.create({
external_status_checks = project.external_status_checks.create({
"name": "mr_blocker",
"external_url": "https://example.com/mr-status-check",
"shared_secret": "secret-string"
Expand All@@ -38,7 +38,7 @@ Create an external status check with shared secret for protected branches::

protected_branch = project.protectedbranches.get('main')

status_check = project.external_status_checks.create({
external_status_check = project.external_status_checks.create({
"name": "mr_blocker",
"external_url": "https://example.com/mr-status-check",
"shared_secret": "secret-string",
Expand All@@ -48,10 +48,25 @@ Create an external status check with shared secret for protected branches::

Update an external status check::

status_check.external_url = "https://example.com/mr-blocker"
status_check.save()
external_status_check.external_url = "https://example.com/mr-blocker"
external_status_check.save()

Delete an external status check::

status_check.delete(status_check_id)
external_status_check.delete(externa_status_check_id)
Copy link
Preview

CopilotAIJun 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

There is a typo in the variable name 'externa_status_check_id'; it should be 'external_status_check_id'.

Suggested change
external_status_check.delete(externa_status_check_id)
external_status_check.delete(external_status_check_id)

Copilot uses AI. Check for mistakes.


List external status check for a project merge request::

merge_request = project.mergerequests.get(1)

merge_request.external_status_checks.list()

Set external status check for a project merge request::

merge_request = project.mergerequests.get(1)

merge_request.external_status_check_response.update({
"external_status_check_id": external_status_check_id,
"status": "passed",
"sha": merge_request.sha
})
8 changes: 6 additions & 2 deletionsgitlab/v4/objects/merge_requests.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,7 +46,10 @@
from .notes import ProjectMergeRequestNoteManager # noqa: F401
from .pipelines import ProjectMergeRequestPipelineManager # noqa: F401
from .reviewers import ProjectMergeRequestReviewerDetailManager
from .status_checks import ProjectMergeRequestStatusCheckManager
from .status_checks import (
ProjectMergeRequestStatusCheckManager,
ProjectMergeRequestStatusCheckResponseManager,
)

__all__ = [
"MergeRequest",
Expand DownExpand Up@@ -170,7 +173,8 @@ class ProjectMergeRequest(
resourcemilestoneevents: ProjectMergeRequestResourceMilestoneEventManager
resourcestateevents: ProjectMergeRequestResourceStateEventManager
reviewer_details: ProjectMergeRequestReviewerDetailManager
status_checks: ProjectMergeRequestStatusCheckManager
external_status_checks: ProjectMergeRequestStatusCheckManager
external_status_check_response: ProjectMergeRequestStatusCheckResponseManager

@cli.register_custom_action(cls_names="ProjectMergeRequest")
@exc.on_http_error(exc.GitlabMROnBuildSuccessError)
Expand Down
41 changes: 35 additions & 6 deletionsgitlab/v4/objects/status_checks.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
from gitlab.base import RESTObject
from typing import Any, Dict, Optional

from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import (
CreateMixin,
DeleteMixin,
Expand DownExpand Up@@ -27,6 +29,7 @@ class ProjectExternalStatusCheckManager(
CreateMixin[ProjectExternalStatusCheck],
UpdateMixin[ProjectExternalStatusCheck],
DeleteMixin[ProjectExternalStatusCheck],
RESTManager[ProjectExternalStatusCheck],
):
_path = "/projects/{project_id}/external_status_checks"
_obj_cls = ProjectExternalStatusCheck
Expand All@@ -41,15 +44,41 @@ class ProjectExternalStatusCheckManager(
_types = {"protected_branch_ids": ArrayAttribute}


classProjectMergeRequestStatusCheck(SaveMixin, RESTObject):
classProjectMergeRequestStatusCheckResponse(SaveMixin, RESTObject):
pass


class ProjectMergeRequestStatusCheckManager(ListMixin[ProjectMergeRequestStatusCheck]):
_path = "/projects/{project_id}/merge_requests/{merge_request_iid}/status_checks"
_obj_cls = ProjectMergeRequestStatusCheck
_from_parent_attrs = {"project_id": "project_id", "merge_request_iid": "iid"}
class ProjectMergeRequestStatusCheckResponseManager(
UpdateMixin[ProjectMergeRequestStatusCheckResponse],
RESTManager[ProjectMergeRequestStatusCheckResponse],
):
_path = "/projects/{project_id}/merge_requests/{mr_iid}/status_check_responses"
_obj_cls = ProjectMergeRequestStatusCheckResponse
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}
_update_attrs = RequiredOptional(
required=("sha", "external_status_check_id", "status")
)
_update_method = UpdateMethod.POST

def update( # type: ignore[override]
self, new_data: Optional[Dict[str, Any]] = None, **kwargs: Any
) -> Dict[str, Any]:
"""Update a Label on the server.

Args:
**kwargs: Extra options to send to the server (e.g. sudo)
"""
return super().update(id=None, new_data=new_data, **kwargs)


class ProjectMergeRequestStatusCheck(RESTObject):
pass


class ProjectMergeRequestStatusCheckManager(
ListMixin[ProjectMergeRequestStatusCheck],
RESTManager[ProjectMergeRequestStatusCheck],
):
_path = "/projects/{project_id}/merge_requests/{mr_iid}/status_checks"
_obj_cls = ProjectMergeRequestStatusCheck
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}
43 changes: 43 additions & 0 deletionstests/functional/api/test_merge_requests.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -300,3 +300,46 @@ def test_merge_request_merge_ref_should_fail(project, merge_request) -> None:
with pytest.raises(gitlab.exceptions.GitlabGetError):
response = merge_request.merge_ref()
assert "commit_id" not in response


@pytest.mark.gitlab_premium
def test_merge_request_external_status_check_set_status(project, merge_request):
project.external_status_checks.create(
{
"name": "external_status_check",
"external_url": "https://example.com/mr-blocker",
}
)

mr_external_status_checks = merge_request.external_status_checks.list()
assert len(mr_external_status_checks) == 1

expected_external_status_check = None

for mr_external_status_check in mr_external_status_checks:
if mr_external_status_check.name == "external_status_check":
expected_external_status_check = mr_external_status_check
break

assert expected_external_status_check is not None

# set the external status check value to 'passed'
merge_request.external_status_check_response.update(
{
"external_status_check_id": expected_external_status_check.id,
"status": "passed",
"sha": merge_request.sha,
}
)

time.sleep(2)

# Check the status again to validate the passed status
mr_status_checks = merge_request.external_status_checks.list()

for mr_status_check in mr_status_checks:
if mr_status_check.name == "external_status_check":
expected_status_check = mr_status_check
break

assert expected_status_check.status == "passed"
118 changes: 118 additions & 0 deletionstests/unit/objects/test_status_checks.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,6 +5,49 @@
import pytest
import responses

mr_content = {
"id": 1,
"iid": 1,
"project_id": 1,
"title": "test1",
"description": "fixed login page css paddings",
"state": "merged",
"sha": "somerandomstring",
"merged_by": {
"id": 87854,
"name": "Douwe Maan",
"username": "DouweM",
"state": "active",
"avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
"web_url": "https://gitlab.com/DouweM",
},
"reviewers": [
{
"id": 2,
"name": "Sam Bauch",
"username": "kenyatta_oconnell",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
"web_url": "http://gitlab.example.com//kenyatta_oconnell",
}
],
}

external_status_checks_content = [
{
"id": 2,
"name": "Service 2",
"external_url": "https://gitlab.example.com/test-endpoint-2",
"status": "pending",
},
{
"id": 1,
"name": "Service 1",
"external_url": "https://gitlab.example.com/test-endpoint-1",
"status": "pending",
},
]


@pytest.fixture
def external_status_check():
Expand DownExpand Up@@ -104,6 +147,54 @@ def resp_delete_external_status_checks():
content_type="application/json",
status=200,
)

yield rsps


@pytest.fixture
def resp_list_merge_requests_status_checks():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/merge_requests/1",
json=mr_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/merge_requests/1/status_checks",
json=external_status_checks_content,
content_type="application/json",
status=200,
)
yield rsps


@pytest.fixture
def resp_list_merge_requests_status_checks_set_value():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/merge_requests/1",
json=mr_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/merge_requests/1/status_checks",
json=external_status_checks_content,
content_type="application/json",
status=200,
)
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/projects/1/merge_requests/1/status_check_responses",
json={"status": "passed"},
content_type="application/json",
status=200,
)
yield rsps


Expand All@@ -125,3 +216,30 @@ def test_delete_external_status_checks(gl, resp_delete_external_status_checks):
gl.projects.get(1, lazy=True).external_status_checks.delete(1)
status_checks = gl.projects.get(1, lazy=True).external_status_checks.list()
assert len(status_checks) == 0


def test_get_merge_request_external_status_checks(
gl, resp_list_merge_requests_status_checks
):
merge_request = gl.projects.get(1, lazy=True).mergerequests.get(1)
external_status_checks = merge_request.external_status_checks.list()
assert len(external_status_checks) == 2


def test_get_merge_request_external_status_checks_set_value(
gl, resp_list_merge_requests_status_checks_set_value
):
merge_request = gl.projects.get(1, lazy=True).mergerequests.get(1)
external_status_checks = merge_request.external_status_checks.list()

assert len(external_status_checks) == 2
for external_status_check in external_status_checks:
if external_status_check.name == "Service 2":
response = merge_request.external_status_check_response.update(
{
"external_status_check_id": external_status_check.id,
"status": "passed",
"sha": merge_request.sha,
}
)
response["status"] == "passed"
Copy link
Preview

CopilotAIJun 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The status update check is currently a no-op; use an assertion (e.g., assert response["status"] == "passed") to properly validate the response.

Suggested change
response["status"]=="passed"
assertresponse["status"]=="passed"

Copilot uses AI. Check for mistakes.

Loading

[8]ページ先頭

©2009-2025 Movatter.jp