Verified Commit 3da45f80 authored by David Runge's avatar David Runge
Browse files

gitlab: Implement download of promotion artifact

Add `download_promotion_artifact()` to allow download of a project
release's promotion artifact to a directory.

Add tests for `download_promotion_artifact()`.
parent 403d18ee
from pathlib import Path
from typing import List, Optional
from urllib import request
import gitlab
......@@ -126,6 +127,46 @@ class Upstream(gitlab.Gitlab):
return artifact_zip
def download_promotion_artifact(self, tag_name: str, temp_dir: Path) -> Path:
"""Download the promotion artifact of a project's release
tag_name: str
The tag_name of the release to download
temp_dir: Path
The directory into which to download
The file path of the downloaded file
project = self.projects.get(
artifact_links: List[str] = []
for release in project.releases.list():
# only select releases that are promoted
if release.tag_name == tag_name and any( == "Promotion artifact" for link in release.links.list()):
artifact_links += [link.url for link in release.links.list() if == "Promotion artifact"]
if not artifact_links:
raise RuntimeError(
f"There is no promotion artifact to download for the release '{tag_name}' of project '{}'."
if len(artifact_links) > 1:
raise RuntimeError(
f"There is more than one promotion artifact to download for the release '{tag_name}' "
f"of project '{}'. Something is wrong!"
print(f"Downloading promotion artifact of release '{tag_name}' for '{}'...")
filename, headers = request.urlretrieve(artifact_links[0], filename=temp_dir / Path(""))
return Path(filename)
def promote_release(self, tag_name: str, file: str) -> None:
"""Upload a promotion file to the project and add it as a link to a release
from contextlib import nullcontext as does_not_raise
from pathlib import Path
from typing import Optional
from typing import ContextManager, Optional
from unittest.mock import Mock, patch
from gitlab.exceptions import GitlabGetError
from pytest import mark
from pytest import mark, raises
from arch_release_promotion import gitlab
......@@ -129,6 +130,75 @@ def test_gitlab_download_release() -> None:
upstream.download_release(tag_name="0.1.0", temp_dir=Path("/tmp"), job_name="job")
"releases_available, tag_name, multi_promotion, has_link, link_name, link_url, expectation",
(True, "0.1.0", False, True, "Promotion artifact", "", does_not_raise()),
(True, "0.1.0", False, True, "Foo artifact", "", raises(RuntimeError)),
"Promotion artifact",
"Promotion artifact",
def test_gitlab_download_promotion_artifact(
urlretrieve_mock: Mock,
releases_available: bool,
tag_name: str,
multi_promotion: bool,
has_link: bool,
link_name: str,
link_url: str,
expectation: ContextManager[str],
) -> None:
urlretrieve_mock.return_value = ("foo", None)
upstream = gitlab.Upstream(
link = Mock() = link_name
link.url = link_url
links = Mock()
links.list.return_value = [link]
release = Mock()
release.links = links
release.tag_name = tag_name
releases = Mock()
releases.list.return_value = [release] if releases_available else []
if releases_available and multi_promotion:
releases.list.return_value = [release, release]
project = Mock()
project.releases = releases
projects = Mock()
projects.get.return_value = project
upstream.projects = projects
with expectation:
upstream.download_promotion_artifact(tag_name="0.1.0", temp_dir=Path("/tmp"))
urlretrieve_mock.assert_called_once_with(link_url, filename=Path("/tmp") / Path(""))
@mark.parametrize("same_tag_name", [(True), (False)])
def test_gitlab_promote_release(same_tag_name: bool) -> None:
upstream = gitlab.Upstream(
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment