Compare commits
No commits in common. "700a0a2f4f6d4e09991c2f2db9fef444dc415cc8" and "cb41ad0719f1816cadc9deffa87653746bcceb2a" have entirely different histories.
700a0a2f4f
...
cb41ad0719
6 changed files with 41 additions and 97 deletions
|
@ -8,8 +8,8 @@ class ReleaseService:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
git_api: GitApi,
|
git_api: GitApi,
|
||||||
artifact_deployment_api: ArtifactDeploymentApi,
|
|
||||||
build_file_repository: BuildFileRepository,
|
build_file_repository: BuildFileRepository,
|
||||||
|
artifact_deployment_api: ArtifactDeploymentApi,
|
||||||
):
|
):
|
||||||
self.git_api = git_api
|
self.git_api = git_api
|
||||||
self.artifact_deployment_api = artifact_deployment_api
|
self.artifact_deployment_api = artifact_deployment_api
|
||||||
|
@ -63,12 +63,7 @@ class ReleaseService:
|
||||||
def publish_artifacts(self, release: Release):
|
def publish_artifacts(self, release: Release):
|
||||||
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(
|
self.artifact_deployment_api.create_forgejo_release(release.forgejo_release_api_endpoint) # create release
|
||||||
release.forgejo_release_api_endpoint(),
|
|
||||||
release.version.to_string(),
|
|
||||||
release.release_artifact_token
|
|
||||||
)
|
|
||||||
# create release
|
|
||||||
# add artifacts to release
|
# add artifacts to release
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ from .provider_digitalocean import Digitalocean
|
||||||
from .provider_hetzner import Hetzner
|
from .provider_hetzner import Hetzner
|
||||||
from .c4k import C4k
|
from .c4k import C4k
|
||||||
from .image import Image
|
from .image import Image
|
||||||
from .release import ReleaseType, Release
|
from .release import ReleaseType
|
||||||
from ..infrastructure import BuildFileRepository, CredentialsApi, EnvironmentApi, GitApi
|
from ..infrastructure import BuildFileRepository, CredentialsApi, EnvironmentApi, GitApi
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,6 @@ class InitService:
|
||||||
Path(primary_build_file_id)
|
Path(primary_build_file_id)
|
||||||
)
|
)
|
||||||
version = primary_build_file.get_version()
|
version = primary_build_file.get_version()
|
||||||
default_mappings += Release.get_mapping_default()
|
|
||||||
|
|
||||||
credentials = Credentials(inp, default_mappings)
|
credentials = Credentials(inp, default_mappings)
|
||||||
authorization = self.authorization(credentials)
|
authorization = self.authorization(credentials)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Optional, List, Dict
|
from typing import Optional, List
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .common import (
|
from .common import (
|
||||||
Validateable,
|
Validateable,
|
||||||
|
@ -17,7 +17,9 @@ class Release(Validateable):
|
||||||
self.release_primary_build_file = inp.get(
|
self.release_primary_build_file = inp.get(
|
||||||
"release_primary_build_file", "./project.clj"
|
"release_primary_build_file", "./project.clj"
|
||||||
)
|
)
|
||||||
self.release_artifacts = inp.get("release_artifacts", [])
|
self.release_artifacts = inp.get(
|
||||||
|
"release_artifacts", []
|
||||||
|
)
|
||||||
self.release_secondary_build_files = inp.get(
|
self.release_secondary_build_files = inp.get(
|
||||||
"release_secondary_build_files", []
|
"release_secondary_build_files", []
|
||||||
)
|
)
|
||||||
|
@ -25,7 +27,6 @@ class Release(Validateable):
|
||||||
self.release_artifact_server_url = inp.get("release_artifact_server_url")
|
self.release_artifact_server_url = inp.get("release_artifact_server_url")
|
||||||
self.release_organisation = inp.get("release_organisation")
|
self.release_organisation = inp.get("release_organisation")
|
||||||
self.release_repository_name = inp.get("release_repository_name")
|
self.release_repository_name = inp.get("release_repository_name")
|
||||||
self.release_artifact_token = inp.get("release_artifact_token")
|
|
||||||
|
|
||||||
def update_release_type(self, release_type: ReleaseType):
|
def update_release_type(self, release_type: ReleaseType):
|
||||||
self.release_type = release_type
|
self.release_type = release_type
|
||||||
|
@ -58,18 +59,7 @@ class Release(Validateable):
|
||||||
and self.release_type != ReleaseType.NONE
|
and self.release_type != ReleaseType.NONE
|
||||||
and self.release_main_branch != self.release_current_branch
|
and self.release_main_branch != self.release_current_branch
|
||||||
):
|
):
|
||||||
result.append(
|
result.append(f"Releases are allowed only on {self.release_main_branch}")
|
||||||
f"Releases are allowed only on {self.release_main_branch}"
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def validate_for_artifact(self):
|
|
||||||
result = []
|
|
||||||
result += self.__validate_is_not_empty__("release_artifact_server_url")
|
|
||||||
result += self.__validate_is_not_empty__("release_organisation")
|
|
||||||
result += self.__validate_is_not_empty__("release_repository_name")
|
|
||||||
result += self.__validate_is_not_empty__("release_artifacts")
|
|
||||||
result += self.__validate_is_not_empty__("release_artifact_token")
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def build_files(self) -> List[str]:
|
def build_files(self) -> List[str]:
|
||||||
|
@ -78,22 +68,10 @@ class Release(Validateable):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def forgejo_release_api_endpoint(self):
|
def forgejo_release_api_endpoint(self):
|
||||||
validation = self.validate_for_artifact()
|
if self.release_artifact_server_url == None or self.release_organisation == None or self.release_repository_name == None:
|
||||||
if validation != []:
|
raise RuntimeError("when doing artifact release, release_artifact_server_url, release_organisation, release_repository_name may not be None.")
|
||||||
raise RuntimeError(f"not valid for creating artifacts: {validation}")
|
|
||||||
|
server_url = self.release_artifact_server_url.removeprefix("/").removesuffix("/")
|
||||||
server_url = self.release_artifact_server_url.removeprefix("/").removesuffix(
|
|
||||||
"/"
|
|
||||||
)
|
|
||||||
organisation = self.release_organisation.removeprefix("/").removesuffix("/")
|
organisation = self.release_organisation.removeprefix("/").removesuffix("/")
|
||||||
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"
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_mapping_default(cls) -> List[Dict[str, str]]:
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
"gopass_path": "server/meissa/repo/buero-rw",
|
|
||||||
"name": "release_artifact_token",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
|
@ -65,12 +65,16 @@ class ImageApi:
|
||||||
def dockerhub_login(self, username: str, password: str):
|
def dockerhub_login(self, username: str, password: str):
|
||||||
self.execution_api.execute_secure(
|
self.execution_api.execute_secure(
|
||||||
f"docker login --username {username} --password {password}",
|
f"docker login --username {username} --password {password}",
|
||||||
"docker login --username ***** --password *****",
|
"docker login --username ***** --password *****"
|
||||||
)
|
)
|
||||||
|
|
||||||
def dockerhub_publish(self, name: str, username: str, tag: str):
|
def dockerhub_publish(self, name: str, username: str, tag: str):
|
||||||
self.execution_api.execute_live(f"docker tag {name} {username}/{name}:{tag}")
|
self.execution_api.execute_live(
|
||||||
self.execution_api.execute_live(f"docker push {username}/{name}:{tag}")
|
f"docker tag {name} {username}/{name}:{tag}"
|
||||||
|
)
|
||||||
|
self.execution_api.execute_live(
|
||||||
|
f"docker push {username}/{name}:{tag}"
|
||||||
|
)
|
||||||
|
|
||||||
def test(self, name: str, path: Path):
|
def test(self, name: str, path: Path):
|
||||||
self.execution_api.execute_live(
|
self.execution_api.execute_live(
|
||||||
|
@ -91,24 +95,14 @@ class ExecutionApi:
|
||||||
check=check,
|
check=check,
|
||||||
stdout=PIPE,
|
stdout=PIPE,
|
||||||
stderr=PIPE,
|
stderr=PIPE,
|
||||||
text=True,
|
text=True).stdout
|
||||||
).stdout
|
|
||||||
output = output.rstrip()
|
output = output.rstrip()
|
||||||
except CalledProcessError as exc:
|
except CalledProcessError as exc:
|
||||||
print(
|
print(f"Command failed with code: {exc.returncode} and message: {exc.stderr}")
|
||||||
f"Command failed with code: {exc.returncode} and message: {exc.stderr}"
|
|
||||||
)
|
|
||||||
raise exc
|
raise exc
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def execute_secure(
|
def execute_secure(self, command: str, sanitized_command: str, dry_run=False, shell=True, check=True):
|
||||||
self,
|
|
||||||
command: str,
|
|
||||||
sanitized_command: str,
|
|
||||||
dry_run=False,
|
|
||||||
shell=True,
|
|
||||||
check=True,
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
output = self.execute(command, dry_run, shell, check)
|
output = self.execute(command, dry_run, shell, check)
|
||||||
return output
|
return output
|
||||||
|
@ -219,42 +213,25 @@ class ArtifactDeploymentApi:
|
||||||
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, target_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" "{target_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" "{target_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
|
|
||||||
|
|
||||||
def post_asset(
|
def post_asset(self, target_url: str, release_id: str, attachment: str, attachment_type: str, token: str):
|
||||||
self,
|
return self.execution_api.execute_secure(f'curl -X "POST" "{target_url}/{release_id}/assets" ' # {target_url}/{release_id}/assets move to Domain
|
||||||
target_url: str,
|
+ f'-H "accept: application/json" -H "Authorization: token {token}" '
|
||||||
release_id: str,
|
+ '-H "Content-Type: multipart/form-data" '
|
||||||
attachment: str,
|
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
||||||
attachment_type: str,
|
sanitized_command=f'curl -X "POST" "{target_url}/{release_id}/assets" ' # see above
|
||||||
token: str,
|
+ '-H "accept: application/json" '
|
||||||
):
|
+ '-H "Content-Type: multipart/form-data" '
|
||||||
return self.execution_api.execute_secure(
|
+ f'-F "attachment=@{attachment};type={attachment_type}"')
|
||||||
f'curl -X "POST" "{target_url}/{release_id}/assets" ' # {target_url}/{release_id}/assets move to Domain
|
|
||||||
+ f'-H "accept: application/json" -H "Authorization: token {token}" '
|
|
||||||
+ '-H "Content-Type: multipart/form-data" '
|
|
||||||
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
|
||||||
sanitized_command=f'curl -X "POST" "{target_url}/{release_id}/assets" ' # see above
|
|
||||||
+ '-H "accept: application/json" '
|
|
||||||
+ '-H "Content-Type: multipart/form-data" '
|
|
||||||
+ f'-F "attachment=@{attachment};type={attachment_type}"',
|
|
||||||
)
|
|
||||||
|
|
||||||
def calculate_checksums(self, artifact_path: str):
|
def calculate_checksums(self, artifact_path: str):
|
||||||
# self.execution_api.execute(f"find {artifact_path} -type f
|
# self.execution_api.execute(f"find {artifact_path} -type f -exec sha256sum {{}}; | sort > {artifact_path} sha256sum.lst") relevant für provs
|
||||||
# -exec sha256sum {{}}; | sort > {artifact_path} sha256sum.lst")
|
self.execution_api(f"sha256sum {artifact_path} > {artifact_path}.sha256",)
|
||||||
# relevant für provs
|
self.execution_api(f"sha512sum {artifact_path} > {artifact_path}.sha512",)
|
||||||
self.execution_api(
|
|
||||||
f"sha256sum {artifact_path} > {artifact_path}.sha256",
|
|
||||||
)
|
|
||||||
self.execution_api(
|
|
||||||
f"sha512sum {artifact_path} > {artifact_path}.sha512",
|
|
||||||
)
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ def devops_config(overrides: dict) -> dict:
|
||||||
"release_primary_build_file": "./package.json",
|
"release_primary_build_file": "./package.json",
|
||||||
"release_secondary_build_file": [],
|
"release_secondary_build_file": [],
|
||||||
"release_artifacts": [],
|
"release_artifacts": [],
|
||||||
"release_artifact_token": "release_artifact_token",
|
|
||||||
"release_artifact_server_url": None,
|
"release_artifact_server_url": None,
|
||||||
"release_organisation": None,
|
"release_organisation": None,
|
||||||
"release_repository_name": None,
|
"release_repository_name": None,
|
||||||
|
|
|
@ -68,8 +68,6 @@ def test_should_calculate_forgejo_release_api_endpoint():
|
||||||
sut = Release(
|
sut = Release(
|
||||||
devops_config(
|
devops_config(
|
||||||
{
|
{
|
||||||
"release_artifacts": ["x"],
|
|
||||||
"release_artifact_token": "y",
|
|
||||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||||
"release_organisation": "meissa",
|
"release_organisation": "meissa",
|
||||||
"release_repository_name": "provs",
|
"release_repository_name": "provs",
|
||||||
|
@ -85,8 +83,6 @@ def test_should_calculate_forgejo_release_api_endpoint():
|
||||||
sut = Release(
|
sut = Release(
|
||||||
devops_config(
|
devops_config(
|
||||||
{
|
{
|
||||||
"release_artifacts": ["x"],
|
|
||||||
"release_artifact_token": "y",
|
|
||||||
"release_artifact_server_url": "https://repo.prod.meissa.de/",
|
"release_artifact_server_url": "https://repo.prod.meissa.de/",
|
||||||
"release_organisation": "/meissa/",
|
"release_organisation": "/meissa/",
|
||||||
"release_repository_name": "provs",
|
"release_repository_name": "provs",
|
||||||
|
|
Loading…
Reference in a new issue