diff options
author | Nejc Habjan <nejc.habjan@siemens.com> | 2022-02-04 22:35:12 +0100 |
---|---|---|
committer | Nejc Habjan <nejc.habjan@siemens.com> | 2022-07-27 00:00:56 +0200 |
commit | 2eeb0a46e8e8fd90b02cc1930c357aa5c55d059d (patch) | |
tree | 3716b0ee752340552cbb4c7253e5acced1c035af | |
parent | 4b798fc2fdc44b73790c493c329147013464de14 (diff) | |
download | gitlab-feat/job-artifacts-manager.tar.gz |
feat(objects): add a complete job artifacts managerfeat/job-artifacts-manager
-rw-r--r-- | docs/gl_objects/pipelines_and_jobs.rst | 32 | ||||
-rw-r--r-- | gitlab/v4/objects/artifacts.py | 116 | ||||
-rw-r--r-- | gitlab/v4/objects/jobs.py | 83 |
3 files changed, 142 insertions, 89 deletions
diff --git a/docs/gl_objects/pipelines_and_jobs.rst b/docs/gl_objects/pipelines_and_jobs.rst index f0bdd3a..9d0d914 100644 --- a/docs/gl_objects/pipelines_and_jobs.rst +++ b/docs/gl_objects/pipelines_and_jobs.rst @@ -242,7 +242,12 @@ List the jobs of a pipeline:: Get the artifacts of a job:: - build_or_job.artifacts() + job.artifacts.download() + +.. attention:: + + An older method ``job.artifacts()`` is deprecated and will be + removed in a future version. Get the artifacts of a job by its name from the latest successful pipeline of a branch or tag:: @@ -264,13 +269,13 @@ You can download artifacts as a stream. Provide a callable to handle the stream:: with open("archive.zip", "wb") as f: - build_or_job.artifacts(streamed=True, action=f.write) + job.artifacts.download(streamed=True, action=f.write) You can also directly stream the output into a file, and unzip it afterwards:: zipfn = "___artifacts.zip" with open(zipfn, "wb") as f: - build_or_job.artifacts(streamed=True, action=f.write) + job.artifacts.download(streamed=True, action=f.write) subprocess.run(["unzip", "-bo", zipfn]) os.unlink(zipfn) @@ -293,7 +298,12 @@ Delete all artifacts of a project that can be deleted:: Get a single artifact file:: - build_or_job.artifact('path/to/file') + job.artifacts.raw('path/to/file') + +.. attention:: + + An older method ``job.artifact()`` is deprecated and will be + removed in a future version. Get a single artifact file by branch and job:: @@ -306,15 +316,15 @@ Get a single artifact file by branch and job:: Mark a job artifact as kept when expiration is set:: - build_or_job.keep_artifacts() + job.keep_artifacts() Delete the artifacts of a job:: - build_or_job.delete_artifacts() + job.delete_artifacts() Get a job trace:: - build_or_job.trace() + job.trace() .. warning:: @@ -323,16 +333,16 @@ Get a job trace:: Cancel/retry a job:: - build_or_job.cancel() - build_or_job.retry() + job.cancel() + job.retry() Play (trigger) a job:: - build_or_job.play() + job.play() Erase a job (artifacts and trace):: - build_or_job.erase() + job.erase() Pipeline bridges diff --git a/gitlab/v4/objects/artifacts.py b/gitlab/v4/objects/artifacts.py index b4a4c0e..03972d9 100644 --- a/gitlab/v4/objects/artifacts.py +++ b/gitlab/v4/objects/artifacts.py @@ -2,6 +2,7 @@ GitLab API: https://docs.gitlab.com/ee/api/job_artifacts.html """ +import warnings from typing import Any, Callable, Iterator, Optional, TYPE_CHECKING, Union import requests @@ -11,7 +12,12 @@ from gitlab import exceptions as exc from gitlab import utils from gitlab.base import RESTManager, RESTObject -__all__ = ["ProjectArtifact", "ProjectArtifactManager"] +__all__ = [ + "ProjectArtifact", + "ProjectArtifactManager", + "ProjectJobArtifact", + "ProjectJobArtifactManager", +] class ProjectArtifact(RESTObject): @@ -165,3 +171,111 @@ class ProjectArtifactManager(RESTManager): return utils.response_content( result, streamed, action, chunk_size, iterator=iterator ) + + +class ProjectJobArtifact(RESTObject): + """Dummy object to manage custom actions on artifacts""" + + _id_attr = "artifact_path" + + +class ProjectJobArtifactManager(RESTManager): + _path = "/projects/{project_id}/jobs/{job_id}/artifacts" + _from_parent_attrs = {"project_id": "project_id", "job_id": "id"} + + @cli.register_custom_action("ProjectJob", custom_action="artifacts") + def __call__( + self, + *args: Any, + **kwargs: Any, + ) -> Optional[Union[bytes, Iterator[Any]]]: + warnings.warn( + "The job.artifacts() method is deprecated and will be " + "removed in a future version. Use job.artifacts.download() instead.\n", + DeprecationWarning, + ) + return self.download( + *args, + **kwargs, + ) + + @cli.register_custom_action("ProjectJobArtifactManager") + @exc.on_http_error(exc.GitlabGetError) + def download( + self, + streamed: bool = False, + action: Optional[Callable[..., Any]] = None, + chunk_size: int = 1024, + iterator: bool = False, + **kwargs: Any, + ) -> Optional[Union[bytes, Iterator[Any]]]: + """Get the job artifacts. + + Args: + streamed: If True the data will be processed by chunks of + `chunk_size` and each chunk is passed to `action` for + treatment + action: Callable responsible of dealing with chunk of + data + chunk_size: Size of each chunk + iterator: If True directly return the underlying response + iterator + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabGetError: If the artifacts could not be retrieved + + Returns: + The artifacts if `streamed` is False, None otherwise. + """ + if TYPE_CHECKING: + assert self.path is not None + result = self.gitlab.http_get(self.path, streamed=streamed, raw=True, **kwargs) + + if TYPE_CHECKING: + assert isinstance(result, requests.Response) + return utils.response_content( + result, streamed, action, chunk_size, iterator=iterator + ) + + @cli.register_custom_action("ProjectJobArtifactManager", ("artifact_path",)) + @cli.register_custom_action("ProjectJob") + @exc.on_http_error(exc.GitlabGetError) + def raw( + self, + path: str, + streamed: bool = False, + action: Optional[Callable[..., Any]] = None, + chunk_size: int = 1024, + iterator: bool = False, + **kwargs: Any, + ) -> Optional[Union[bytes, Iterator[Any]]]: + """Get a single artifact file from within the job's artifacts archive. + + Args: + path: Path of the artifact + streamed: If True the data will be processed by chunks of + `chunk_size` and each chunk is passed to `action` for + treatment + action: Callable responsible of dealing with chunk of + data + chunk_size: Size of each chunk + iterator: If True directly return the underlying response + iterator + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabGetError: If the artifacts could not be retrieved + + Returns: + The artifacts if `streamed` is False, None otherwise. + """ + path = f"{self.path}/{path}" + result = self.gitlab.http_get(path, streamed=streamed, raw=True, **kwargs) + if TYPE_CHECKING: + assert isinstance(result, requests.Response) + return utils.response_content( + result, streamed, action, chunk_size, iterator=iterator + ) diff --git a/gitlab/v4/objects/jobs.py b/gitlab/v4/objects/jobs.py index cfe1e62..52fff50 100644 --- a/gitlab/v4/objects/jobs.py +++ b/gitlab/v4/objects/jobs.py @@ -8,6 +8,8 @@ from gitlab import utils from gitlab.base import RESTManager, RESTObject from gitlab.mixins import RefreshMixin, RetrieveMixin +from .artifacts import ProjectJobArtifactManager # noqa: F401 + __all__ = [ "ProjectJob", "ProjectJobManager", @@ -15,6 +17,8 @@ __all__ = [ class ProjectJob(RefreshMixin, RESTObject): + artifacts: ProjectJobArtifactManager + @cli.register_custom_action("ProjectJob") @exc.on_http_error(exc.GitlabJobCancelError) def cancel(self, **kwargs: Any) -> Dict[str, Any]: @@ -113,87 +117,12 @@ class ProjectJob(RefreshMixin, RESTObject): @cli.register_custom_action("ProjectJob") @exc.on_http_error(exc.GitlabGetError) - def artifacts( - self, - streamed: bool = False, - action: Optional[Callable[..., Any]] = None, - chunk_size: int = 1024, - *, - iterator: bool = False, - **kwargs: Any, - ) -> Optional[Union[bytes, Iterator[Any]]]: - """Get the job artifacts. - - Args: - streamed: If True the data will be processed by chunks of - `chunk_size` and each chunk is passed to `action` for - treatment - iterator: If True directly return the underlying response - iterator - action: Callable responsible of dealing with chunk of - data - chunk_size: Size of each chunk - **kwargs: Extra options to send to the server (e.g. sudo) - - Raises: - GitlabAuthenticationError: If authentication is not correct - GitlabGetError: If the artifacts could not be retrieved - - Returns: - The artifacts if `streamed` is False, None otherwise. - """ - path = f"{self.manager.path}/{self.encoded_id}/artifacts" - result = self.manager.gitlab.http_get( - path, streamed=streamed, raw=True, **kwargs - ) - if TYPE_CHECKING: - assert isinstance(result, requests.Response) - return utils.response_content( - result, streamed, action, chunk_size, iterator=iterator - ) - - @cli.register_custom_action("ProjectJob") - @exc.on_http_error(exc.GitlabGetError) def artifact( self, - path: str, - streamed: bool = False, - action: Optional[Callable[..., Any]] = None, - chunk_size: int = 1024, - *, - iterator: bool = False, + *args: Any, **kwargs: Any, ) -> Optional[Union[bytes, Iterator[Any]]]: - """Get a single artifact file from within the job's artifacts archive. - - Args: - path: Path of the artifact - streamed: If True the data will be processed by chunks of - `chunk_size` and each chunk is passed to `action` for - treatment - iterator: If True directly return the underlying response - iterator - action: Callable responsible of dealing with chunk of - data - chunk_size: Size of each chunk - **kwargs: Extra options to send to the server (e.g. sudo) - - Raises: - GitlabAuthenticationError: If authentication is not correct - GitlabGetError: If the artifacts could not be retrieved - - Returns: - The artifacts if `streamed` is False, None otherwise. - """ - path = f"{self.manager.path}/{self.encoded_id}/artifacts/{path}" - result = self.manager.gitlab.http_get( - path, streamed=streamed, raw=True, **kwargs - ) - if TYPE_CHECKING: - assert isinstance(result, requests.Response) - return utils.response_content( - result, streamed, action, chunk_size, iterator=iterator - ) + return self.artifacts.raw(*args, **kwargs) @cli.register_custom_action("ProjectJob") @exc.on_http_error(exc.GitlabGetError) |