From 639815388e4b40569078dfd920ebeba17c69d2ef Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Thu, 18 May 2023 18:23:51 +0200 Subject: [PATCH] minor fixes & initialize context for release --- .../application/release_mixin_services.py | 4 +- src/main/python/ddadevops/domain/__init__.py | 2 +- .../python/ddadevops/domain/devops_factory.py | 2 +- .../python/ddadevops/domain/init_service.py | 30 ++++++- src/main/python/ddadevops/domain/release.py | 22 +++-- .../infrastructure/infrastructure.py | 35 ++++---- src/main/python/ddadevops/release_mixin.py | 2 +- src/test/python/domain/helper.py | 41 +++++++++ src/test/python/domain/test_init_service.py | 8 +- src/test/python/test_c4k_build.py | 2 +- src/test/python/test_release_mixin.py | 86 +++++++------------ 11 files changed, 138 insertions(+), 96 deletions(-) diff --git a/src/main/python/ddadevops/application/release_mixin_services.py b/src/main/python/ddadevops/application/release_mixin_services.py index 655c230..c1744d2 100644 --- a/src/main/python/ddadevops/application/release_mixin_services.py +++ b/src/main/python/ddadevops/application/release_mixin_services.py @@ -9,10 +9,10 @@ class ReleaseService: self.build_file_repository = build_file_repository @classmethod - def prod(cls): + def prod(cls, base_dir: str): return cls( GitApi(), - BuildFileRepository(), + BuildFileRepository(base_dir), ) def prepare_release(self, release: Release): diff --git a/src/main/python/ddadevops/domain/__init__.py b/src/main/python/ddadevops/domain/__init__.py index 9b6ff1e..f55faa3 100644 --- a/src/main/python/ddadevops/domain/__init__.py +++ b/src/main/python/ddadevops/domain/__init__.py @@ -2,7 +2,7 @@ from .common import Validateable, DnsRecord, Devops, BuildType, MixinType, Relea from .devops_factory import DevopsFactory from .image import Image from .c4k import C4k -from .release import Release, EnvironmentKeys +from .release import Release from .credentials import Credentials, CredentialMapping, GopassType from .version import Version from .build_file import BuildFileType, BuildFile diff --git a/src/main/python/ddadevops/domain/devops_factory.py b/src/main/python/ddadevops/domain/devops_factory.py index 44a025a..f631c31 100644 --- a/src/main/python/ddadevops/domain/devops_factory.py +++ b/src/main/python/ddadevops/domain/devops_factory.py @@ -33,7 +33,7 @@ class DevopsFactory: return devops def merge(self, input: dict, context: dict, authorization: dict) -> dict: - return {} | input | context | authorization + return {} | context | authorization | input def __parse_build_types__(self, build_types: List[str]) -> List[BuildType]: result = [] diff --git a/src/main/python/ddadevops/domain/init_service.py b/src/main/python/ddadevops/domain/init_service.py index d15ec34..488c783 100644 --- a/src/main/python/ddadevops/domain/init_service.py +++ b/src/main/python/ddadevops/domain/init_service.py @@ -4,19 +4,22 @@ from .common import Devops, MixinType, BuildType from .credentials import Credentials, GopassType from .devops_factory import DevopsFactory from .version import Version +from .release import ReleaseType from src.main.python.ddadevops.infrastructure import ( BuildFileRepository, CredentialsApi, EnvironmentApi, + GitApi ) class InitService: - def __init__(self, devops_factory, build_file_repository, credentials_api, environment_api): + def __init__(self, devops_factory, build_file_repository, credentials_api, environment_api, git_api): self.devops_factory = devops_factory self.build_file_repository = build_file_repository self.credentials_api = credentials_api self.environment_api = environment_api + self.git_api = git_api @classmethod def prod(cls, base_dir: str): @@ -25,6 +28,7 @@ class InitService: BuildFileRepository(base_dir), CredentialsApi(), EnvironmentApi(), + GitApi(), ) def initialize(self, input: dict) -> Devops: @@ -47,9 +51,11 @@ class InitService: }, ] credentials = Credentials(input, default_mappings) - authorization = self.resolve_passwords(credentials) + authorization = self.authorization(credentials) - merged = self.devops_factory.merge(input, {}, authorization) + context = self.context() + + merged = self.devops_factory.merge(input, context, authorization) if MixinType.RELEASE in mixin_types: primary_build_file_id = merged.get( @@ -62,7 +68,23 @@ class InitService: return self.devops_factory.build_devops(merged, version=version) - def resolve_passwords(self, credentials: Credentials) -> List[str]: + def context(self) -> dict: + result = {} + + release_type = self.environment_api.get("RELEASE_TYPE") + if not release_type: + latest_commit = self.git_api.get_latest_commit() + if latest_commit in [ReleaseType.MAJOR.name, ReleaseType.MINOR.name, + ReleaseType.PATCH.name, ReleaseType.NONE.name]: + release_type = latest_commit + result["release_type"] = release_type + + result["release_current_branch"] = self.git_api.get_current_branch() + + return result + + + def authorization(self, credentials: Credentials) -> List[str]: result = {} for name in credentials.mappings.keys(): mapping = credentials.mappings[name] diff --git a/src/main/python/ddadevops/domain/release.py b/src/main/python/ddadevops/domain/release.py index 5c36fdc..78f69ad 100644 --- a/src/main/python/ddadevops/domain/release.py +++ b/src/main/python/ddadevops/domain/release.py @@ -11,19 +11,19 @@ from .version import ( ) -class EnvironmentKeys(Enum): - DDADEVOPS_RELEASE_TYPE = 0 - - class Release(Validateable): def __init__(self, input: dict, version: Version): self.release_type = ReleaseType[input.get("release_type", "NONE")] self.release_main_branch = input.get("release_main_branch", "main") self.release_current_branch = input.get("release_current_branch") - self.release_primary_build_file = input.get("release_primary_build_file", "./project.clj") - self.release_secondary_build_files = input.get("release_secondary_build_files", []) + self.release_primary_build_file = input.get( + "release_primary_build_file", "./project.clj" + ) + self.release_secondary_build_files = input.get( + "release_secondary_build_files", [] + ) self.version = version - + def validate(self): result = [] result += self.__validate_is_not_empty__("release_type") @@ -34,12 +34,16 @@ class Release(Validateable): try: Path(self.release_primary_build_file) except Exception as e: - result.append(f"release_primary_build_file must be a valid path but was {e}") + result.append( + f"release_primary_build_file must be a valid path but was {e}" + ) for path in self.release_secondary_build_files: try: Path(path) except Exception as e: - result.append(f"release_secondary_build_file must be contain valid paths but was {e}") + result.append( + f"release_secondary_build_file must be contain valid paths but was {e}" + ) if self.version: result += self.version.validate() if ( diff --git a/src/main/python/ddadevops/infrastructure/infrastructure.py b/src/main/python/ddadevops/infrastructure/infrastructure.py index 9146e3c..54932db 100644 --- a/src/main/python/ddadevops/infrastructure/infrastructure.py +++ b/src/main/python/ddadevops/infrastructure/infrastructure.py @@ -3,7 +3,6 @@ from sys import stdout from os import chmod, environ from pkg_resources import resource_string import yaml -import deprecation from subprocess import check_output, Popen, PIPE, run from ..domain import Devops, Image, C4k, Release, BuildFile @@ -135,52 +134,50 @@ class CredentialsApi: return credential -class GitApi(): - +class GitApi: def __init__(self): self.execution_api = ExecutionApi() # pylint: disable=invalid-name def get_latest_n_commits(self, n: int): - return self.execution_api.execute( - f'git log --oneline --format="%s %b" -n {n}') + return self.execution_api.execute(f'git log --oneline --format="%s %b" -n {n}') def get_latest_commit(self): return self.get_latest_n_commits(1) def tag_annotated(self, annotation: str, message: str, count: int): return self.execution_api.execute( - f'git tag -a {annotation} -m {message} HEAD~{count}') + f"git tag -a {annotation} -m {message} HEAD~{count}" + ) - def tag_annotated_second_last(self, annotation: str, message:str): + def tag_annotated_second_last(self, annotation: str, message: str): return self.tag_annotated(annotation, message, 1) def get_latest_tag(self): - return self.execution_api.execute('git describe --tags --abbrev=0') + return self.execution_api.execute("git describe --tags --abbrev=0") def get_current_branch(self): - return ''.join(self.execution_api.execute('git branch --show-current')).rstrip() + return "".join(self.execution_api.execute("git branch --show-current")).rstrip() def init(self, default_branch: str = "main"): - self.execution_api.execute('git init') - self.execution_api.execute(f'git checkout -b {default_branch}') + self.execution_api.execute("git init") + self.execution_api.execute(f"git checkout -b {default_branch}") def set_user_config(self, email: str, name: str): - self.execution_api.execute(f'git config user.email {email}') - self.execution_api.execute(f'git config user.name {name}') + self.execution_api.execute(f"git config user.email {email}") + self.execution_api.execute(f"git config user.name {name}") def add_file(self, file_path: Path): - return self.execution_api.execute(f'git add {file_path}') + return self.execution_api.execute(f"git add {file_path}") def add_remote(self, origin: str, url: str): - return self.execution_api.execute(f'git remote add {origin} {url}') + return self.execution_api.execute(f"git remote add {origin} {url}") def commit(self, commit_message: str): - return self.execution_api.execute( - f'git commit -m "{commit_message}"') + return self.execution_api.execute(f'git commit -m "{commit_message}"') def push(self): - return self.execution_api.execute('git push') + return self.execution_api.execute("git push") def checkout(self, branch: str): - return self.execution_api.execute(f'git checkout {branch}') + return self.execution_api.execute(f"git checkout {branch}") diff --git a/src/main/python/ddadevops/release_mixin.py b/src/main/python/ddadevops/release_mixin.py index 8488f61..15ce281 100644 --- a/src/main/python/ddadevops/release_mixin.py +++ b/src/main/python/ddadevops/release_mixin.py @@ -7,7 +7,7 @@ from src.main.python.ddadevops.domain import MixinType class ReleaseMixin(DevopsBuild): def __init__(self, project: Project, input: dict): super().__init__(project, input) - self.release_service = ReleaseService.prod() + self.release_service = ReleaseService.prod(project.basedir) devops = self.devops_repo.get_devops(self.project) if MixinType.RELEASE not in devops.mixins: raise ValueError(f"ReleaseMixin requires MixinType.RELEASE") diff --git a/src/test/python/domain/helper.py b/src/test/python/domain/helper.py index a810036..3c6fdd0 100644 --- a/src/test/python/domain/helper.py +++ b/src/test/python/domain/helper.py @@ -74,3 +74,44 @@ class CredentialsApiMock: def gopass_password_from_path(self, path): return self.mappings.get(path, None) + + +class GitApiMock: + def get_latest_n_commits(self, n: int): + pass + + def get_latest_commit(self): + pass + + def tag_annotated(self, annotation: str, message: str, count: int): + pass + + def tag_annotated_second_last(self, annotation: str, message: str): + pass + + def get_latest_tag(self): + pass + + def get_current_branch(self): + pass + + def init(self, default_branch: str = "main"): + pass + + def set_user_config(self, email: str, name: str): + pass + + def add_file(self, file_path: Path): + pass + + def add_remote(self, origin: str, url: str): + pass + + def commit(self, commit_message: str): + pass + + def push(self): + pass + + def checkout(self, branch: str): + pass diff --git a/src/test/python/domain/test_init_service.py b/src/test/python/domain/test_init_service.py index 475e8fe..686ec98 100644 --- a/src/test/python/domain/test_init_service.py +++ b/src/test/python/domain/test_init_service.py @@ -10,6 +10,7 @@ from .helper import ( BuildFileRepositoryMock, EnvironmentApiMock, CredentialsApiMock, + GitApiMock, devops_config, ) @@ -23,6 +24,7 @@ def test_should_load_build_file(): "server/meissa/grafana-cloud": "gopass-gfc-password", }), EnvironmentApiMock({}), + GitApiMock(), ) assert ( Version.from_str("1.1.5-SNAPSHOT") @@ -41,8 +43,12 @@ def test_should_resolve_passwords(): } ), EnvironmentApiMock({"C4K_GRAFANA_CLOUD_USER": "env-gfc-user"}), + GitApiMock(), ) - devops = sut.initialize(devops_config({})) + config = devops_config({}) + del config["c4k_grafana_cloud_user"] + del config["c4k_grafana_cloud_password"] + devops = sut.initialize(config) c4k = devops.specialized_builds[BuildType.C4K] assert { "mon-auth": { diff --git a/src/test/python/test_c4k_build.py b/src/test/python/test_c4k_build.py index a45e1d2..3db4c35 100644 --- a/src/test/python/test_c4k_build.py +++ b/src/test/python/test_c4k_build.py @@ -5,7 +5,7 @@ from src.main.python.ddadevops.c4k_build import C4kBuild, add_c4k_mixin_config from .domain.helper import devops_config -def test_c4k_mixin(tmp_path): +def test_c4k_build(tmp_path): str_tmp_path = str(tmp_path) project = Project(str_tmp_path, name="name") diff --git a/src/test/python/test_release_mixin.py b/src/test/python/test_release_mixin.py index 8a579a7..a266630 100644 --- a/src/test/python/test_release_mixin.py +++ b/src/test/python/test_release_mixin.py @@ -1,83 +1,55 @@ import pytest as pt +import os from pathlib import Path from pybuilder.core import Project from src.main.python.ddadevops.release_mixin import ReleaseMixin from src.main.python.ddadevops.domain import Devops, Release - -from .resource_helper import ResourceHelper -from .domain.test_helper import devops_config - -MAIN_BRANCH = "main" -STAGE = "test" -PROJECT_ROOT_PATH = "." -MODULE = "test" -BUILD_DIR_NAME = "build_dir" - - -def change_test_dir(tmp_path: Path, monkeypatch: pt.MonkeyPatch): - monkeypatch.chdir(tmp_path) - - -def initialize_with_object(project, CONFIG_FILE): - project.build_depends_on("ddadevops>=3.1.2") - build = ReleaseMixin( - project, - devops_config( - { - "name": "release_test", - "stage": "test", - "module": MODULE, - "project_root_path": PROJECT_ROOT_PATH, - "build_types": [], - "mixin_types": ["RELEASE"], - "build_dir_name": BUILD_DIR_NAME, - "release_main_branch": MAIN_BRANCH, - "release_config_file": CONFIG_FILE, - } - ), - ) - return build - +from .domain.helper import devops_config +from .resource_helper import copy_resource def test_release_mixin(tmp_path): - tmp_path_str = str(tmp_path) + str_tmp_path = str(tmp_path) + copy_resource(Path('package.json'), tmp_path) + project = Project(str_tmp_path, name="name") - project = Project(tmp_path_str, name="name") sut = ReleaseMixin( project, devops_config( { - "project_root_path": tmp_path_str, - "build_types": [], + "project_root_path": str_tmp_path, "mixin_types": ["RELEASE"], + "build_types": [], + "module": "release-test", } ), ) - assert sut is not None + + sut.initialize_build_dir() + assert sut.build_path() == f"{str_tmp_path}/target/name/release-test" -def test_release_mixin_git(tmp_path: Path, monkeypatch: pt.MonkeyPatch): - # init - th = ResourceHelper() - th.copy_files(th.TEST_FILE_PATH, tmp_path) - th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME +# def test_release_mixin_git(tmp_path: Path, monkeypatch: pt.MonkeyPatch): +# # init +# th = ResourceHelper() +# th.copy_files(th.TEST_FILE_PATH, tmp_path) +# th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME - change_test_dir(tmp_path, monkeypatch) - project = Project(tmp_path) +# change_test_dir(tmp_path, monkeypatch) +# project = Project(tmp_path) - git_api = GitApi() - git_api.init() - git_api.set_user_config("ex.ample@mail.com", "Ex Ample") - git_api.add_file(th.TEST_FILE_NAME) - git_api.commit("MAJOR release") +# git_api = GitApi() +# git_api.init() +# git_api.set_user_config("ex.ample@mail.com", "Ex Ample") +# git_api.add_file(th.TEST_FILE_NAME) +# git_api.commit("MAJOR release") - build = initialize_with_object(project, th.TEST_FILE_PATH) - build.prepare_release() - release_version = build.release_repo.version_repository.get_version() +# build = initialize_with_object(project, th.TEST_FILE_PATH) +# build.prepare_release() +# release_version = build.release_repo.version_repository.get_version() - # test - assert "124.0.1-SNAPSHOT" in release_version.get_version_string() +# # test +# assert "124.0.1-SNAPSHOT" in release_version.get_version_string() # def test_release_mixin_environment(tmp_path: Path, monkeypatch: pt.MonkeyPatch):