summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNejc Habjan <nejc.habjan@siemens.com>2022-02-04 22:35:12 +0100
committerNejc Habjan <nejc.habjan@siemens.com>2022-07-27 00:00:56 +0200
commit2eeb0a46e8e8fd90b02cc1930c357aa5c55d059d (patch)
tree3716b0ee752340552cbb4c7253e5acced1c035af
parent4b798fc2fdc44b73790c493c329147013464de14 (diff)
downloadgitlab-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.rst32
-rw-r--r--gitlab/v4/objects/artifacts.py116
-rw-r--r--gitlab/v4/objects/jobs.py83
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)