Compare commits
5 commits
700a0a2f4f
...
bfcdcbb78a
Author | SHA1 | Date | |
---|---|---|---|
bfcdcbb78a | |||
caaf804fd3 | |||
a876fdc799 | |||
e0150e6fcc | |||
b861087e9d |
7 changed files with 121 additions and 24 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import json
|
||||||
from typing import List
|
from typing import List
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from ..infrastructure import GitApi, ArtifactDeploymentApi, BuildFileRepository
|
from ..infrastructure import GitApi, ArtifactDeploymentApi, BuildFileRepository
|
||||||
|
@ -61,16 +62,44 @@ class ReleaseService:
|
||||||
self.git_api.push_follow_tags()
|
self.git_api.push_follow_tags()
|
||||||
|
|
||||||
def publish_artifacts(self, release: Release):
|
def publish_artifacts(self, release: Release):
|
||||||
|
release_id = self.__parse_forgejo_release_id__(
|
||||||
|
self.artifact_deployment_api.create_forgejo_release(
|
||||||
|
release.forgejo_release_api_endpoint(),
|
||||||
|
release.version.to_string(),
|
||||||
|
release.release_artifact_token,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
artifacts_to_attach = []
|
||||||
for artifact_path in release.release_artifacts:
|
for artifact_path in release.release_artifacts:
|
||||||
self.artifact_deployment_api.calculate_checksums(artifact_path)
|
self.artifact_deployment_api.calculate_checksums(artifact_path)
|
||||||
self.artifact_deployment_api.create_forgejo_release(
|
# TODO: make api more explizit to have the path calculation & decision which shas to take clear
|
||||||
release.forgejo_release_api_endpoint(),
|
artifacts_to_attach += [{
|
||||||
release.version.to_string(),
|
"path": artifact_path,
|
||||||
release.release_artifact_token
|
# TODO: it will not always be a jar file -> move type to release input-side.
|
||||||
)
|
"type": "application/x-java-archive",
|
||||||
# create release
|
},
|
||||||
# add artifacts to release
|
{
|
||||||
pass
|
"path": f"{artifact_path}.sha256",
|
||||||
|
"type": "text/plain",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": f"{artifact_path}.sha512",
|
||||||
|
"type": "text/plain",
|
||||||
|
}]
|
||||||
|
|
||||||
|
# TODO: use structure created above
|
||||||
|
for artifact in artifacts_to_attach:
|
||||||
|
self.artifact_deployment_api.add_asset_to_release(
|
||||||
|
release.forgejo_release_asset_api_endpoint(release_id),
|
||||||
|
"todo",
|
||||||
|
"todo",
|
||||||
|
release.release_artifact_token,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __parse_forgejo_release_id__(self, release_response: str) -> int:
|
||||||
|
parsed = json.loads(release_response)
|
||||||
|
return parsed["id"]
|
||||||
|
|
||||||
def __set_version_and_commit__(
|
def __set_version_and_commit__(
|
||||||
self, version: Version, build_file_ids: List[str], message: str
|
self, version: Version, build_file_ids: List[str], message: str
|
||||||
|
|
|
@ -77,7 +77,7 @@ class Release(Validateable):
|
||||||
result += self.release_secondary_build_files
|
result += self.release_secondary_build_files
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def forgejo_release_api_endpoint(self):
|
def forgejo_release_api_endpoint(self) -> str:
|
||||||
validation = self.validate_for_artifact()
|
validation = self.validate_for_artifact()
|
||||||
if validation != []:
|
if validation != []:
|
||||||
raise RuntimeError(f"not valid for creating artifacts: {validation}")
|
raise RuntimeError(f"not valid for creating artifacts: {validation}")
|
||||||
|
@ -89,6 +89,9 @@ class Release(Validateable):
|
||||||
repository = self.release_repository_name.removeprefix("/").removesuffix("/")
|
repository = self.release_repository_name.removeprefix("/").removesuffix("/")
|
||||||
return f"{server_url}/api/v1/repos/{organisation}/{repository}/releases"
|
return f"{server_url}/api/v1/repos/{organisation}/{repository}/releases"
|
||||||
|
|
||||||
|
def forgejo_release_asset_api_endpoint(self, id: int) -> str:
|
||||||
|
return f"{self.forgejo_release_api_endpoint()}/{id}/assets"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_mapping_default(cls) -> List[Dict[str, str]]:
|
def get_mapping_default(cls) -> List[Dict[str, str]]:
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -218,31 +218,30 @@ class ArtifactDeploymentApi:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.execution_api = ExecutionApi()
|
self.execution_api = ExecutionApi()
|
||||||
|
|
||||||
def create_forgejo_release(self, target_url: str, tag: str, token: str):
|
def create_forgejo_release(self, api_endpoint_url: str, tag: str, token: str):
|
||||||
return self.execution_api.execute_secure(
|
return self.execution_api.execute_secure(
|
||||||
f'curl -X "POST" "{target_url}" '
|
f'curl -X "POST" "{api_endpoint_url}" '
|
||||||
+ '-H "accept: application/json" -H "Content-Type: application/json" '
|
+ '-H "accept: application/json" -H "Content-Type: application/json" '
|
||||||
+ f'-d "{{ "body": "Provides files for release {tag} Attention: The "Source Code"-files below are not up-to-date!", "tag_name": "{tag}"}}" ' # noqa: E501
|
+ f'-d "{{ "body": "Provides files for release {tag} Attention: The "Source Code"-files below are not up-to-date!", "tag_name": "{tag}"}}" ' # noqa: E501
|
||||||
+ f'-H "Authorization: token {token}"',
|
+ f'-H "Authorization: token {token}"',
|
||||||
sanitized_command=f'curl -X "POST" "{target_url}" '
|
sanitized_command=f'curl -X "POST" "{api_endpoint_url}" '
|
||||||
+ '-H "accept: application/json" -H "Content-Type: application/json" '
|
+ '-H "accept: application/json" -H "Content-Type: application/json" '
|
||||||
+ f'-d "{{ "body": "Provides files for release {tag} Attention: The "Source Code"-files below are not up-to-date!", "tag_name": "{tag}"}}" ',
|
+ f'-d "{{ "body": "Provides files for release {tag} Attention: The "Source Code"-files below are not up-to-date!", "tag_name": "{tag}"}}" ',
|
||||||
) # noqa: E501
|
) # noqa: E501
|
||||||
|
|
||||||
def post_asset(
|
def add_asset_to_release(
|
||||||
self,
|
self,
|
||||||
target_url: str,
|
api_endpoint_url: str,
|
||||||
release_id: str,
|
|
||||||
attachment: str,
|
attachment: str,
|
||||||
attachment_type: str,
|
attachment_type: str,
|
||||||
token: str,
|
token: str,
|
||||||
):
|
):
|
||||||
return self.execution_api.execute_secure(
|
return self.execution_api.execute_secure(
|
||||||
f'curl -X "POST" "{target_url}/{release_id}/assets" ' # {target_url}/{release_id}/assets move to Domain
|
f'curl -X "POST" "{api_endpoint_url}" '
|
||||||
+ f'-H "accept: application/json" -H "Authorization: token {token}" '
|
+ f'-H "accept: application/json" -H "Authorization: token {token}" '
|
||||||
+ '-H "Content-Type: multipart/form-data" '
|
+ '-H "Content-Type: multipart/form-data" '
|
||||||
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
||||||
sanitized_command=f'curl -X "POST" "{target_url}/{release_id}/assets" ' # see above
|
sanitized_command=f'curl -X "POST" "{api_endpoint_url}" '
|
||||||
+ '-H "accept: application/json" '
|
+ '-H "accept: application/json" '
|
||||||
+ '-H "Content-Type: multipart/form-data" '
|
+ '-H "Content-Type: multipart/form-data" '
|
||||||
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from src.main.python.ddadevops.domain import (
|
from src.main.python.ddadevops.domain import (
|
||||||
ReleaseType,
|
ReleaseType,
|
||||||
MixinType,
|
MixinType,
|
||||||
)
|
)
|
||||||
from src.test.python.domain.helper import (
|
from src.test.python.domain.helper import (
|
||||||
|
@ -12,8 +12,11 @@ from src.test.python.domain.helper import (
|
||||||
)
|
)
|
||||||
from src.main.python.ddadevops.application import ReleaseService
|
from src.main.python.ddadevops.application import ReleaseService
|
||||||
|
|
||||||
|
|
||||||
def test_sould_update_release_type():
|
def test_sould_update_release_type():
|
||||||
sut = ReleaseService(GitApiMock(), ArtifactDeploymentApiMock(), BuildFileRepositoryMock("build.py"))
|
sut = ReleaseService(
|
||||||
|
GitApiMock(), ArtifactDeploymentApiMock(), BuildFileRepositoryMock("build.py")
|
||||||
|
)
|
||||||
devops = build_devops({})
|
devops = build_devops({})
|
||||||
release = devops.mixins[MixinType.RELEASE]
|
release = devops.mixins[MixinType.RELEASE]
|
||||||
sut.update_release_type(release, "MAJOR")
|
sut.update_release_type(release, "MAJOR")
|
||||||
|
@ -21,3 +24,40 @@ def test_sould_update_release_type():
|
||||||
|
|
||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
sut.update_release_type(release, "NOT_EXISTING")
|
sut.update_release_type(release, "NOT_EXISTING")
|
||||||
|
|
||||||
|
|
||||||
|
def test_sould_publish_artifacts():
|
||||||
|
mock = ArtifactDeploymentApiMock(release='{"id": 2345}')
|
||||||
|
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||||
|
devops = build_devops(
|
||||||
|
{
|
||||||
|
"release_artifacts": ["target/art"],
|
||||||
|
"release_artifact_server_url": "http://repo.test/",
|
||||||
|
"release_organisation": "orga",
|
||||||
|
"release_repository_name": "repo",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
release = devops.mixins[MixinType.RELEASE]
|
||||||
|
sut.publish_artifacts(release)
|
||||||
|
assert 2345 == mock.add_asset_to_release_id
|
||||||
|
|
||||||
|
def test_sould_throw_exception_if_there_was_an_error_in_publish_artifacts():
|
||||||
|
devops = build_devops(
|
||||||
|
{
|
||||||
|
"release_artifacts": ["target/art"],
|
||||||
|
"release_artifact_server_url": "http://repo.test/",
|
||||||
|
"release_organisation": "orga",
|
||||||
|
"release_repository_name": "repo",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
release = devops.mixins[MixinType.RELEASE]
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
mock = ArtifactDeploymentApiMock(release='')
|
||||||
|
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||||
|
sut.publish_artifacts(release)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
mock = ArtifactDeploymentApiMock(release='{"message": "there was an error", "url":"some-url"}')
|
||||||
|
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||||
|
sut.publish_artifacts(release)
|
||||||
|
|
|
@ -158,13 +158,19 @@ class GitApiMock:
|
||||||
|
|
||||||
|
|
||||||
class ArtifactDeploymentApiMock:
|
class ArtifactDeploymentApiMock:
|
||||||
def __init__(self):
|
def __init__(self, release=""):
|
||||||
pass
|
self.release = release
|
||||||
|
self.create_forgejo_release_count = 0
|
||||||
|
self.add_asset_to_release_count = 0
|
||||||
|
self.add_asset_to_release_id = ""
|
||||||
|
|
||||||
def post_release(self, target_url: str, tag: str, token: str):
|
def create_forgejo_release(self, target_url: str, tag: str, token: str):
|
||||||
pass
|
self.create_forgejo_release_count += 1
|
||||||
|
return self.release
|
||||||
|
|
||||||
def post_asset(self, target_url: str, release_id: str, attachment: str, attachment_type: str, token: str):
|
def add_asset_to_release(self, target_url: str, release_id: str, attachment: str, attachment_type: str, token: str):
|
||||||
|
self.add_asset_to_release_count += 1
|
||||||
|
self.add_asset_to_release_id = release_id
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def calculate_checksums(self, build_path: str):
|
def calculate_checksums(self, build_path: str):
|
||||||
|
|
|
@ -115,3 +115,21 @@ def test_should_calculate_forgejo_release_api_endpoint():
|
||||||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||||
)
|
)
|
||||||
sut.forgejo_release_api_endpoint()
|
sut.forgejo_release_api_endpoint()
|
||||||
|
|
||||||
|
def test_should_calculate_forgejo_release_asset_api_endpoint():
|
||||||
|
sut = Release(
|
||||||
|
devops_config(
|
||||||
|
{
|
||||||
|
"release_artifacts": ["x"],
|
||||||
|
"release_artifact_token": "y",
|
||||||
|
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||||
|
"release_organisation": "meissa",
|
||||||
|
"release_repository_name": "provs",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
"https://repo.prod.meissa.de/api/v1/repos/meissa/provs/releases/123/assets"
|
||||||
|
== sut.forgejo_release_asset_api_endpoint(123)
|
||||||
|
)
|
||||||
|
|
|
@ -14,6 +14,8 @@ def test_release_mixin(tmp_path):
|
||||||
copy_resource(Path("package.json"), tmp_path)
|
copy_resource(Path("package.json"), tmp_path)
|
||||||
project = Project(str_tmp_path, name="name")
|
project = Project(str_tmp_path, name="name")
|
||||||
|
|
||||||
|
os.environ["RELEASE_ARTIFACT_TOKEN"] = "ratoken"
|
||||||
|
|
||||||
sut = ReleaseMixin(
|
sut = ReleaseMixin(
|
||||||
project,
|
project,
|
||||||
devops_config(
|
devops_config(
|
||||||
|
|
Loading…
Reference in a new issue