Skip to content

feat(api): add merge request pipeline manager and deprecate mr.pipelines() method #1323

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 25 additions & 4 deletions docs/gl_objects/mrs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,6 @@ List the changes of a MR::

changes = mr.changes()

List the pipelines for a MR::

pipelines = mr.pipelines()

List issues that will close on merge::

mr.closes_issues()
Expand Down Expand Up @@ -185,3 +181,28 @@ Get user agent detail for the issue (admin only)::
Attempt to rebase an MR::

mr.rebase()

Merge Request Pipelines
=======================

Reference
---------

* v4 API:

+ :class:`gitlab.v4.objects.ProjectMergeRequestPipeline`
+ :class:`gitlab.v4.objects.ProjectMergeRequestPipelineManager`
+ :attr:`gitlab.v4.objects.ProjectMergeRequest.pipelines`

* GitLab API: https://docs.gitlab.com/ee/api/merge_requests.html#list-mr-pipelines

Examples
--------

List pipelines for a merge request::

pipelines = mr.pipelines.list()

Create a pipeline for a merge request::

pipeline = mr.pipelines.create()
3 changes: 2 additions & 1 deletion gitlab/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def register_custom_action(
cls_names: Union[str, Tuple[str, ...]],
mandatory: Tuple[str, ...] = tuple(),
optional: Tuple[str, ...] = tuple(),
custom_action: Optional[str] = None,
) -> Callable[[__F], __F]:
def wrap(f: __F) -> __F:
@functools.wraps(f)
Expand All @@ -74,7 +75,7 @@ def wrapped_f(*args: Any, **kwargs: Any) -> Any:
if final_name not in custom_actions:
custom_actions[final_name] = {}

action = f.__name__.replace("_", "-")
action = custom_action or f.__name__.replace("_", "-")
custom_actions[final_name][action] = (mandatory, optional, in_obj)

return cast(__F, wrapped_f)
Expand Down
21 changes: 2 additions & 19 deletions gitlab/v4/objects/merge_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
ProjectMergeRequestApprovalRuleManager,
)
from .notes import ProjectMergeRequestNoteManager # noqa: F401
from .pipelines import ProjectMergeRequestPipelineManager # noqa: F401

__all__ = [
"MergeRequest",
Expand Down Expand Up @@ -145,6 +146,7 @@ class ProjectMergeRequest(
("diffs", "ProjectMergeRequestDiffManager"),
("discussions", "ProjectMergeRequestDiscussionManager"),
("notes", "ProjectMergeRequestNoteManager"),
("pipelines", "ProjectMergeRequestPipelineManager"),
("resourcelabelevents", "ProjectMergeRequestResourceLabelEventManager"),
("resourcemilestoneevents", "ProjectMergeRequestResourceMilestoneEventManager"),
("resourcestateevents", "ProjectMergeRequestResourceStateEventManager"),
Expand Down Expand Up @@ -240,25 +242,6 @@ def changes(self, **kwargs):
path = "%s/%s/changes" % (self.manager.path, self.get_id())
return self.manager.gitlab.http_get(path, **kwargs)

@cli.register_custom_action("ProjectMergeRequest")
@exc.on_http_error(exc.GitlabListError)
def pipelines(self, **kwargs):
"""List the merge request pipelines.

Args:
**kwargs: Extra options to send to the server (e.g. sudo)

Raises:
GitlabAuthenticationError: If authentication is not correct
GitlabListError: If the list could not be retrieved

Returns:
RESTObjectList: List of changes
"""

path = "%s/%s/pipelines" % (self.manager.path, self.get_id())
return self.manager.gitlab.http_get(path, **kwargs)

@cli.register_custom_action("ProjectMergeRequest", tuple(), ("sha",))
@exc.on_http_error(exc.GitlabMRApprovalError)
def approve(self, sha=None, **kwargs):
Expand Down
41 changes: 41 additions & 0 deletions gitlab/v4/objects/pipelines.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import warnings

from gitlab import cli
from gitlab import exceptions as exc
from gitlab.base import RequiredOptional, RESTManager, RESTObject
Expand All @@ -15,6 +17,8 @@
)

__all__ = [
"ProjectMergeRequestPipeline",
"ProjectMergeRequestPipelineManager",
"ProjectPipeline",
"ProjectPipelineManager",
"ProjectPipelineJob",
Expand All @@ -32,6 +36,43 @@
]


class ProjectMergeRequestPipeline(RESTObject):
pass


class ProjectMergeRequestPipelineManager(CreateMixin, ListMixin, RESTManager):
_path = "/projects/%(project_id)s/merge_requests/%(mr_iid)s/pipelines"
_obj_cls = ProjectMergeRequestPipeline
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}

# If the manager was called directly as a callable via
# mr.pipelines(), execute the deprecated method for now.
# TODO: in python-gitlab 3.0.0, remove this method entirely.

@cli.register_custom_action("ProjectMergeRequest", custom_action="pipelines")
@exc.on_http_error(exc.GitlabListError)
def __call__(self, **kwargs):
"""List the merge request pipelines.

Args:
**kwargs: Extra options to send to the server (e.g. sudo)

Raises:
GitlabAuthenticationError: If authentication is not correct
GitlabListError: If the list could not be retrieved

Returns:
RESTObjectList: List of changes
"""
warnings.warn(
"Calling the ProjectMergeRequest.pipelines() method on "
"merge request objects directly is deprecated and will be replaced "
"by ProjectMergeRequest.pipelines.list() in python-gitlab 3.0.0.\n",
DeprecationWarning,
)
return self.list(**kwargs)


class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
_managers = (
("jobs", "ProjectPipelineJobManager"),
Expand Down
64 changes: 64 additions & 0 deletions tests/unit/objects/test_merge_request_pipelines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
GitLab API: https://docs.gitlab.com/ee/api/merge_requests.html#list-mr-pipelines
"""
import pytest
import responses

from gitlab.v4.objects import ProjectMergeRequestPipeline

pipeline_content = {
"id": 1,
"sha": "959e04d7c7a30600c894bd3c0cd0e1ce7f42c11d",
"ref": "master",
"status": "success",
}


@pytest.fixture()
def resp_list_merge_request_pipelines():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.GET,
url="http://localhost/api/v4/projects/1/merge_requests/1/pipelines",
json=[pipeline_content],
content_type="application/json",
status=200,
)
yield rsps


@pytest.fixture()
def resp_create_merge_request_pipeline():
with responses.RequestsMock() as rsps:
rsps.add(
method=responses.POST,
url="http://localhost/api/v4/projects/1/merge_requests/1/pipelines",
json=pipeline_content,
content_type="application/json",
status=201,
)
yield rsps


def test_merge_requests_pipelines_deprecated_raises_warning(
project, resp_list_merge_request_pipelines
):
with pytest.deprecated_call():
pipelines = project.mergerequests.get(1, lazy=True).pipelines()

assert len(pipelines) == 1
assert isinstance(pipelines[0], ProjectMergeRequestPipeline)
assert pipelines[0].sha == pipeline_content["sha"]


def test_list_merge_requests_pipelines(project, resp_list_merge_request_pipelines):
pipelines = project.mergerequests.get(1, lazy=True).pipelines.list()
assert len(pipelines) == 1
assert isinstance(pipelines[0], ProjectMergeRequestPipeline)
assert pipelines[0].sha == pipeline_content["sha"]


def test_create_merge_requests_pipelines(project, resp_create_merge_request_pipeline):
pipeline = project.mergerequests.get(1, lazy=True).pipelines.create()
assert isinstance(pipeline, ProjectMergeRequestPipeline)
assert pipeline.sha == pipeline_content["sha"]