diff --git a/src/main/python/ddadevops/infrastructure/release_mixin/__init__.py b/src/main/python/ddadevops/infrastructure/release_mixin/__init__.py deleted file mode 100644 index 9d311aa..0000000 --- a/src/main/python/ddadevops/infrastructure/release_mixin/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .infrastructure_api import FileHandler, JsonFileHandler, GradleFileHandler, PythonFileHandler, ClojureFileHandler -from .repo import VersionRepository, ReleaseContextRepository, ReleaseTypeRepository diff --git a/src/main/python/ddadevops/infrastructure/release_mixin/infrastructure_api.py b/src/main/python/ddadevops/infrastructure/release_mixin/infrastructure_api.py deleted file mode 100644 index 0babdc1..0000000 --- a/src/main/python/ddadevops/infrastructure/release_mixin/infrastructure_api.py +++ /dev/null @@ -1,184 +0,0 @@ -import json -import re -from abc import ABC, abstractmethod -from typing import Optional -from pathlib import Path -from os import environ -from ..infrastructure import ExecutionApi - -# TODO: jem, zam - 2023_04_18: Discuss if we can move more functionality to domain? -class FileHandler(ABC): - def __init__(self) -> None: - self.config_file_path: Optional[Path | None] = None - self.config_file_type: Optional[Path | None] = None - - @classmethod - def from_file_path(cls, file_path): - config_file_type = file_path.suffix - match config_file_type: - case '.json': - file_handler = JsonFileHandler() - case '.gradle': - file_handler = GradleFileHandler() - case '.clj': - file_handler = ClojureFileHandler() - case '.py': - file_handler = PythonFileHandler() - case _: - raise RuntimeError( - f'The file type "{config_file_type}" is not implemented') - # TODO: Attribute is only set in classmethod. Should this be initialized outside of this class? - file_handler.config_file_path = file_path - file_handler.config_file_type = config_file_type - return file_handler - - @abstractmethod - def parse(self) -> tuple[list[int], bool]: - pass - - @abstractmethod - def write(self, version_string): - pass - - -class JsonFileHandler(FileHandler): - - def parse(self) -> tuple[list[int], bool]: - if self.config_file_path is None: - raise ValueError("No file name given.") - with open(self.config_file_path, 'r', encoding='utf-8') as json_file: - json_version = json.load(json_file)['version'] - is_snapshot = False - if '-SNAPSHOT' in json_version: - is_snapshot = True - json_version = json_version.replace('-SNAPSHOT', '') - version = [int(x) for x in json_version.split('.')] - return version, is_snapshot - - def write(self, version_string): - with open(self.config_file_path, 'r+', encoding='utf-8') as json_file: - json_data = json.load(json_file) - json_data['version'] = version_string - json_file.seek(0) - json.dump(json_data, json_file, indent=4) - json_file.truncate() - - -class GradleFileHandler(FileHandler): - - def parse(self) -> tuple[list[int], bool]: - if self.config_file_path is None: - raise ValueError("No file name given.") - with open(self.config_file_path, 'r', encoding='utf-8') as gradle_file: - contents = gradle_file.read() - version_line = re.search("\nversion = .*", contents) - exception = Exception("Version not found in gradle file") - if version_line is None: - raise exception - - version_line_group = version_line.group() - version_string = re.search( - '[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?', version_line_group) - if version_string is None: - raise exception - - version_string_group = version_string.group() - is_snapshot = False - if '-SNAPSHOT' in version_string_group: - is_snapshot = True - version_string_group = version_string_group.replace('-SNAPSHOT', '') - - version = [int(x) for x in version_string_group.split('.')] - - return version, is_snapshot - - def write(self, version_string): - with open(self.config_file_path, 'r+', encoding='utf-8') as gradle_file: - contents = gradle_file.read() - version_substitute = re.sub( - '\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents) - gradle_file.seek(0) - gradle_file.write(version_substitute) - gradle_file.truncate() - - -class PythonFileHandler(FileHandler): - - def parse(self) -> tuple[list[int], bool]: - if self.config_file_path is None: - raise ValueError("No file name given.") - with open(self.config_file_path, 'r', encoding='utf-8') as python_file: - contents = python_file.read() - version_line = re.search("\nversion = .*\n", contents) - exception = Exception("Version not found in gradle file") - if version_line is None: - raise exception - - version_line_group = version_line.group() - version_string = re.search( - '[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?', version_line_group) - if version_string is None: - raise exception - - version_string_group = version_string.group() - is_snapshot = False - if '-SNAPSHOT' in version_string_group: - is_snapshot = True - version_string_group = version_string_group.replace('-SNAPSHOT', '') - - version = [int(x) for x in version_string_group.split('.')] - - return version, is_snapshot - - def write(self, version_string): - with open(self.config_file_path, 'r+', encoding='utf-8') as python_file: - contents = python_file.read() - version_substitute = re.sub( - '\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents) - python_file.seek(0) - python_file.write(version_substitute) - python_file.truncate() - - -class ClojureFileHandler(FileHandler): - - def parse(self) -> tuple[list[int], bool]: - if self.config_file_path is None: - raise ValueError("No file name given.") - with open(self.config_file_path, 'r', encoding='utf-8') as clj_file: - contents = clj_file.read() - version_line = re.search("^\\(defproject .*\n", contents) - exception = Exception("Version not found in clj file") - if version_line is None: - raise exception - - version_line_group = version_line.group() - version_string = re.search( - '[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?', version_line_group) - if version_string is None: - raise exception - - version_string_group = version_string.group() - is_snapshot = False - if '-SNAPSHOT' in version_string_group: - is_snapshot = True - version_string_group = version_string_group.replace('-SNAPSHOT', '') - - version = [int(x) for x in version_string_group.split('.')] - - return version, is_snapshot - - def write(self, version_string): - with open(self.config_file_path, 'r+', encoding='utf-8') as clj_file: - clj_first = clj_file.readline() - clj_rest = clj_file.read() - version_substitute = re.sub( - '[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?', f'"{version_string}"\n', clj_first) - clj_file.seek(0) - clj_file.write(version_substitute) - clj_file.write(clj_rest) - clj_file.truncate() - - - - diff --git a/src/main/python/ddadevops/infrastructure/release_mixin/repo.py b/src/main/python/ddadevops/infrastructure/release_mixin/repo.py deleted file mode 100644 index 011c58c..0000000 --- a/src/main/python/ddadevops/infrastructure/release_mixin/repo.py +++ /dev/null @@ -1,125 +0,0 @@ - -from src.main.python.ddadevops.domain import ( - Version, - ReleaseType, - EnvironmentKeys, -) -from src.main.python.ddadevops.infrastructure.release_mixin.infrastructure_api import ( - FileHandler, - GitApi, -) -from src.main.python.ddadevops.infrastructure import EnvironmentApi - - -class VersionRepository: - def __init__(self, file): - self.file = file - self.file_handler = None - - def load_file(self): - self.file_handler = FileHandler.from_file_path(self.file) - return self.file_handler - - def write_file(self, version_string): - if self.file_handler is None: - raise RuntimeError("Version was not created by load_file method.") - self.file_handler.write(version_string) - - def parse_file(self): - version_list, is_snapshot = self.file_handler.parse() - return version_list, is_snapshot - - def get_version(self) -> Version: - self.file_handler = self.load_file() - version_list, is_snapshot = self.parse_file() - version = Version(self.file, version_list) - version.is_snapshot = is_snapshot - - return version - - -class ReleaseTypeRepository: - def __init__( - self, - git_api: GitApi = GitApi(), - environment_api: EnvironmentApi = EnvironmentApi(), - ): - self.git_api: GitApi = git_api - self.environment_api: EnvironmentApi = environment_api - self.get_from_git: bool = False - self.get_from_env: bool = False - - @classmethod - def from_git(cls, git_api: GitApi): - release_type_repo = cls(git_api=git_api) - release_type_repo.get_from_git = True - return release_type_repo - - @classmethod - def from_environment(cls, environment_api: EnvironmentApi): - release_type_repo = cls(environment_api=environment_api) - release_type_repo.get_from_env = True - return release_type_repo - - def __get_release_type_git(self) -> ReleaseType | None: - latest_commit = self.git_api.get_latest_commit() - - match latest_commit.upper(): - case ReleaseType.MAJOR.name: - return ReleaseType.MAJOR - case ReleaseType.MINOR.name: - return ReleaseType.MINOR - case ReleaseType.PATCH.name: - return ReleaseType.PATCH - case ReleaseType.SNAPSHOT.name: - return ReleaseType.SNAPSHOT - case _: - return None - - def __get_release_type_environment(self) -> ReleaseType | None: - release_name = self.environment_api.get( - EnvironmentKeys.DDADEVOPS_RELEASE_TYPE.name - ) - - if release_name is None: - raise ValueError( - "Release Name not found. Is the Environment correctly configured?" - ) - - match release_name.upper(): - case ReleaseType.MAJOR.name: - return ReleaseType.MAJOR - case ReleaseType.MINOR.name: - return ReleaseType.MINOR - case ReleaseType.PATCH.name: - return ReleaseType.PATCH - case ReleaseType.SNAPSHOT.name: - return ReleaseType.SNAPSHOT - case _: - return None - - def get_release_type(self) -> ReleaseType | None: - if self.get_from_git: - return self.__get_release_type_git() - if self.get_from_env: - return self.__get_release_type_environment() - raise ValueError("No valid api passed to ReleaseTypeRepository") - - -class ReleaseContextRepository: - def __init__( - self, - version_repository: VersionRepository, - release_type_repository: ReleaseTypeRepository, - ): - self.version_repository = version_repository - self.release_type_repository = release_type_repository - - # def get_release(self, main_branch: str) -> ReleaseContext: - # result = ReleaseContext( - # self.release_type_repository.get_release_type(), - # self.version_repository.get_version(), - # main_branch, - # ) - # result.throw_if_invalid() - # return result diff --git a/src/test/python/release_mixin/__init__.py b/src/test/python/release_mixin/__init__.py deleted file mode 100644 index 1514703..0000000 --- a/src/test/python/release_mixin/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .mock_infrastructure import MockReleaseRepository, MockReleaseTypeRepository, MockVersionRepository -from .mock_infrastructure_api import MockGitApi diff --git a/src/test/python/release_mixin/helper.py b/src/test/python/release_mixin/helper.py deleted file mode 100644 index c9843ca..0000000 --- a/src/test/python/release_mixin/helper.py +++ /dev/null @@ -1,12 +0,0 @@ -from pathlib import Path -from src.main.python.ddadevops.infrastructure import ExecutionApi - -class Helper(): - def __init__(self, file_name = 'config.json'): - self.TEST_FILE_NAME = file_name - self.TEST_FILE_ROOT = Path('src/test/resources/') - self.TEST_FILE_PATH = self.TEST_FILE_ROOT / self.TEST_FILE_NAME - - def copy_files(self, source: Path, target: Path): - api = ExecutionApi() - api.execute(f"cp {source} {target}") diff --git a/src/test/python/release_mixin/mock_infrastructure.py b/src/test/python/release_mixin/mock_infrastructure.py deleted file mode 100644 index 9cf6b06..0000000 --- a/src/test/python/release_mixin/mock_infrastructure.py +++ /dev/null @@ -1,43 +0,0 @@ -from pathlib import Path - -from src.main.python.ddadevops.domain import ReleaseType, Version, Release - -from .mock_infrastructure_api import MockGitApi - -class MockVersionRepository(): - - def __init__(self): - self.file = None - self.file_handler = None - self.write_file_count = 0 - - def load_file(self): - pass - - def write_file(self, version_string): - self.write_file_count += 1 - pass - - def parse_file(self): - pass - - def get_version(self) -> Version: - return Version(Path(), [0,0,0]) - -class MockReleaseTypeRepository(): - def __init__(self, mock_git_api: MockGitApi): - self.git_api = mock_git_api - - def get_release_type(self): - return ReleaseType.MINOR - -class MockReleaseRepository(): - def __init__(self, version_repository: MockVersionRepository, release_type_repository: MockReleaseTypeRepository, main_branch: str): - self.version_repository = version_repository - self.release_type_repository = release_type_repository - self.main_branch = main_branch - self.get_release_count = 0 - - def get_release(self) -> Release: - self.get_release_count += 1 - return Release(self.release_type_repository.get_release_type(), self.version_repository.get_version(), self.main_branch) diff --git a/src/test/python/release_mixin/mock_infrastructure_api.py b/src/test/python/release_mixin/mock_infrastructure_api.py deleted file mode 100644 index 368203b..0000000 --- a/src/test/python/release_mixin/mock_infrastructure_api.py +++ /dev/null @@ -1,73 +0,0 @@ -class MockSystemApi(): - - def __init__(self): - self.stdout = [""] - self.stderr = [""] - - def run(self, args): - pass - - def run_checked(self, *args): - self.run(args) - pass - -class MockGitApi(): - - def __init__(self, commit_string = ""): - self.system_api = MockSystemApi() - self.get_latest_commit_count = 0 - self.commit_string = commit_string - self.tag_annotated_count = 0 - self.add_file_count = 0 - self.commit_count = 0 - self.push_count = 0 - - def get_latest_n_commits(self, n: int): - return " " - - def get_latest_commit(self): - self.get_latest_commit_count += 1 - return self.commit_string - - def tag_annotated(self, annotation: str, message: str, count: int): - self.tag_annotated_count += 1 - return " " - - def tag_annotated_second_last(self, annotation: str, message: str): - self.tag_annotated(annotation, message, 1) - return " " - - def get_latest_tag(self): - return " " - - def get_current_branch(self): - return " " - - def init(self): - pass - - def add_file(self, file_path): - self.add_file_count += 1 - return " " - - def commit(self, commit_message: str): - self.commit_count += 1 - return commit_message - - def push(self): - self.push_count += 1 - return " " - - def checkout(self, branch: str): - return " " - -class MockEnvironmentApi(): - - def __init__(self, environ_map): - self.environ = environ_map - - def get(self, name): - return self.environ.get(name) - - def set(self, name, value): - self.environ[name] = value diff --git a/src/test/python/release_mixin/test_infrastructure.py b/src/test/python/release_mixin/test_infrastructure.py deleted file mode 100644 index 6233c64..0000000 --- a/src/test/python/release_mixin/test_infrastructure.py +++ /dev/null @@ -1,86 +0,0 @@ -from src.main.python.ddadevops.domain import ReleaseType -from src.main.python.ddadevops.infrastructure.release_mixin import ReleaseTypeRepository, VersionRepository, ReleaseContextRepository -from .mock_infrastructure_api import MockGitApi, MockEnvironmentApi -from .helper import Helper - -def test_version_repository(tmp_path): - # init - th = Helper() - th.copy_files(th.TEST_FILE_PATH, tmp_path) - sut = VersionRepository(th.TEST_FILE_PATH) - version = sut.get_version() - - #test - assert version is not None - - -def test_release_repository(tmp_path): - # init - th = Helper() - th.copy_files( th.TEST_FILE_PATH, tmp_path) - version_repo = VersionRepository(th.TEST_FILE_PATH) - release_type_repo = ReleaseTypeRepository.from_git(MockGitApi('MINOR test')) - - # test - sut = ReleaseContextRepository(version_repo, release_type_repo) - - release = sut.get_release('main') - - assert release is not None - - -def test_release_type_repository_git(): - sut = ReleaseTypeRepository.from_git(MockGitApi('MINOR test')) - release_type = sut.get_release_type() - assert release_type is ReleaseType.MINOR - - sut = ReleaseTypeRepository.from_git(MockGitApi('MINOR bla')) - release_type = sut.get_release_type() - assert release_type is ReleaseType.MINOR - - sut = ReleaseTypeRepository.from_git(MockGitApi('Major bla')) - release_type = sut.get_release_type() - assert release_type == ReleaseType.MAJOR - - sut = ReleaseTypeRepository.from_git(MockGitApi('PATCH bla')) - release_type = sut.get_release_type() - assert release_type == ReleaseType.PATCH - - sut = ReleaseTypeRepository.from_git(MockGitApi('SNAPSHOT bla')) - release_type = sut.get_release_type() - assert release_type == ReleaseType.SNAPSHOT - - sut = ReleaseTypeRepository.from_git(MockGitApi('bla')) - release_type = sut.get_release_type() - assert release_type == None - -def test_release_type_repository_env(): - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'MINOR test'})) - release_type = sut.get_release_type() - assert release_type is ReleaseType.MINOR - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'MINOR'})) - release_type = sut.get_release_type() - assert release_type is ReleaseType.MINOR - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'Major bla'})) - release_type = sut.get_release_type() - assert release_type == ReleaseType.MAJOR - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'Patch bla'})) - release_type = sut.get_release_type() - assert release_type == ReleaseType.PATCH - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'Snapshot bla'})) - release_type = sut.get_release_type() - assert release_type == ReleaseType.SNAPSHOT - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'DDADEVOPS_RELEASE_TYPE': 'Random text'})) - release_type = sut.get_release_type() - assert release_type == None - - sut = ReleaseTypeRepository.from_environment(MockEnvironmentApi({'REL_TYPE': 'Not the right variable'})) - try: - release_type = sut.get_release_type() - except: - assert release_type == None diff --git a/src/test/python/release_mixin/test_infrastructure_api.py b/src/test/python/release_mixin/test_infrastructure_api.py deleted file mode 100644 index f2ba909..0000000 --- a/src/test/python/release_mixin/test_infrastructure_api.py +++ /dev/null @@ -1,103 +0,0 @@ -from pathlib import Path -import pytest as pt - -from src.main.python.ddadevops.infrastructure.release_mixin import GitApi, EnvironmentApi, JsonFileHandler -from src.main.python.ddadevops.infrastructure.release_mixin import VersionRepository -from src.main.python.ddadevops.domain.release import ReleaseType - -from .helper import Helper - -def change_test_dir( tmp_path: Path, monkeypatch: pt.MonkeyPatch): - monkeypatch.chdir(tmp_path) - -def test_environment_api(): - # init - env_api = EnvironmentApi() - key = "TEST_ENV_KEY" - value = "data" - env_api.set(key, value) - - #test - assert env_api.get(key) == value - -def test_git_api(tmp_path: Path, monkeypatch: pt.MonkeyPatch): - # init - th = Helper() - th.copy_files(th.TEST_FILE_PATH, tmp_path) - - # change the context of the script execution to tmp_path - change_test_dir(tmp_path, monkeypatch) - - 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("MINOR release") - - # test - latest_commit = git_api.get_latest_commit() - assert "MINOR release" in latest_commit - -# file handler tests -def test_gradle(tmp_path): - # init - th = Helper('config.gradle') - th.copy_files(th.TEST_FILE_PATH, tmp_path) - th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME - - # test - repo = VersionRepository(th.TEST_FILE_PATH) - version = repo.get_version() - version = version.create_release_version(ReleaseType.SNAPSHOT) - repo.write_file(version.get_version_string()) - - # check - assert 'version = "12.4.678-SNAPSHOT"' in th.TEST_FILE_PATH.read_text() - - -def test_json(tmp_path): - # init - th = Helper('config.json') - th.copy_files(th.TEST_FILE_PATH, tmp_path) - th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME - - # test - repo = VersionRepository(th.TEST_FILE_PATH) - version = repo.get_version() - version = version.create_release_version(ReleaseType.SNAPSHOT) - repo.write_file(version.get_version_string()) - - # check - assert '"version": "123.123.456-SNAPSHOT"' in th.TEST_FILE_PATH.read_text() - - -def test_clojure(tmp_path): - # init - th = Helper('config.clj') - th.copy_files(th.TEST_FILE_PATH, tmp_path) - th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME - - # test - repo = VersionRepository(th.TEST_FILE_PATH) - version = repo.get_version() - version = version.create_release_version(ReleaseType.SNAPSHOT) - repo.write_file(version.get_version_string()) - - # check - assert '1.1.3-SNAPSHOT' in th.TEST_FILE_PATH.read_text() - - -def test_python(tmp_path): - # init - th = Helper('config.py') - th.copy_files(th.TEST_FILE_PATH, tmp_path) - th.TEST_FILE_PATH = tmp_path / th.TEST_FILE_NAME - - # test - repo = VersionRepository(th.TEST_FILE_PATH) - version = repo.get_version() - version = version.create_release_version(ReleaseType.SNAPSHOT) - repo.write_file(version.get_version_string()) - - # check - assert '3.1.3-SNAPSHOT' in th.TEST_FILE_PATH.read_text() diff --git a/src/test/python/release_mixin/test_services.py b/src/test/python/release_mixin/test_services.py deleted file mode 100644 index 35063d8..0000000 --- a/src/test/python/release_mixin/test_services.py +++ /dev/null @@ -1,32 +0,0 @@ -from src.main.python.ddadevops.application import PrepareReleaseService, TagAndPushReleaseService -from src.test.python.release_mixin import MockReleaseRepository, MockReleaseTypeRepository, MockVersionRepository -from src.test.python.release_mixin import MockGitApi - -def test_prepare_release_service(): - # init - mock_release_repo = MockReleaseRepository(MockVersionRepository(), MockReleaseTypeRepository(MockGitApi()), 'main') - prepare_release_service = PrepareReleaseService() - prepare_release_service.git_api = MockGitApi() - prepare_release_service.write_and_commit_release(mock_release_repo.get_release(), mock_release_repo.version_repository) - - #test - assert prepare_release_service.git_api.add_file_count == 1 - assert prepare_release_service.git_api.commit_count == 1 - - # init - prepare_release_service.write_and_commit_bump(mock_release_repo.get_release(), mock_release_repo.version_repository) - - # test - assert prepare_release_service.git_api.add_file_count == 2 - assert prepare_release_service.git_api.commit_count == 2 - -def test_tag_and_push_release_service(): - # init - mock_release_repo = MockReleaseRepository(MockVersionRepository(), MockReleaseTypeRepository(MockGitApi()), 'main') - tag_and_push_release_service = TagAndPushReleaseService(MockGitApi()) - tag_and_push_release_service.tag_release(mock_release_repo) - tag_and_push_release_service.push_release() - - #test - assert tag_and_push_release_service.git_api.tag_annotated_count == 1 - assert tag_and_push_release_service.git_api.push_count == 1