diff --git a/docs/commands/create-pr-preview.md b/docs/commands/create-pr-preview.md index a3947396..d9327baf 100644 --- a/docs/commands/create-pr-preview.md +++ b/docs/commands/create-pr-preview.md @@ -22,13 +22,17 @@ gitopscli create-pr-preview \ ## Usage ``` -usage: gitopscli create-pr-preview [-h] --username USERNAME --password PASSWORD - [--git-user GIT_USER] [--git-email GIT_EMAIL] - --organisation ORGANISATION --repository-name - REPOSITORY_NAME [--git-provider GIT_PROVIDER] - [--git-provider-url GIT_PROVIDER_URL] - --pr-id PR_ID - [--parent-id PARENT_ID] [-v [VERBOSE]] +usage: gitopscli create-pr-preview [-h] --username USERNAME --password + PASSWORD [--git-user GIT_USER] + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME + [--git-provider GIT_PROVIDER] + [--git-provider-url GIT_PROVIDER_URL] + --pr-id PR_ID [--parent-id PARENT_ID] + [-v [VERBOSE]] options: -h, --help show this help message and exit @@ -39,6 +43,10 @@ options: --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/docs/commands/create-preview.md b/docs/commands/create-preview.md index 54449ddd..f62e5cb2 100644 --- a/docs/commands/create-preview.md +++ b/docs/commands/create-preview.md @@ -36,10 +36,12 @@ gitopscli create-preview \ ``` usage: gitopscli create-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] - --preview-id PREVIEW_ID + --git-hash GIT_HASH --preview-id PREVIEW_ID [-v [VERBOSE]] options: @@ -51,6 +53,10 @@ options: --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/docs/commands/delete-pr-preview.md b/docs/commands/delete-pr-preview.md index f1343b26..0abbd942 100644 --- a/docs/commands/delete-pr-preview.md +++ b/docs/commands/delete-pr-preview.md @@ -20,9 +20,11 @@ gitopscli delete-pr-preview \ ``` usage: gitopscli delete-pr-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation - ORGANISATION --repository-name - REPOSITORY_NAME + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] --branch BRANCH @@ -38,6 +40,10 @@ options: --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/docs/commands/delete-preview.md b/docs/commands/delete-preview.md index 910e1d96..c51144c4 100644 --- a/docs/commands/delete-preview.md +++ b/docs/commands/delete-preview.md @@ -20,6 +20,8 @@ gitopscli delete-preview \ ``` usage: gitopscli delete-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -36,6 +38,10 @@ options: --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/docs/commands/deploy.md b/docs/commands/deploy.md index 2ddb8c3f..9f8093c2 100644 --- a/docs/commands/deploy.md +++ b/docs/commands/deploy.md @@ -125,26 +125,37 @@ usage: gitopscli deploy [-h] --file FILE --values VALUES [--single-commit [SINGLE_COMMIT]] [--commit-message COMMIT_MESSAGE] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation ORGANISATION - --repository-name REPOSITORY_NAME - [--git-provider GIT_PROVIDER] + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION --repository-name + REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] [--create-pr [CREATE_PR]] [--auto-merge [AUTO_MERGE]] - [--merge-method MERGE_METHOD] [-v [VERBOSE]] + [--merge-method MERGE_METHOD] [--json [JSON]] + [--pr-labels PR_LABELS] + [--merge-parameters MERGE_PARAMETERS] [-v [VERBOSE]] options: -h, --help show this help message and exit --file FILE YAML file path - --values VALUES YAML/JSON object with the YAML path as key and the desired value as value + --values VALUES YAML/JSON object with the YAML path as key and the + desired value as value --single-commit [SINGLE_COMMIT] Create only single commit for all updates --commit-message COMMIT_MESSAGE Specify exact commit message of deployment commit - --username USERNAME Git username (alternative: GITOPSCLI_USERNAME env variable) - --password PASSWORD Git password or token (alternative: GITOPSCLI_PASSWORD env variable) + --username USERNAME Git username (alternative: GITOPSCLI_USERNAME env + variable) + --password PASSWORD Git password or token (alternative: GITOPSCLI_PASSWORD + env variable) --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/docs/commands/sync-apps.md b/docs/commands/sync-apps.md index 2e57ff21..df5437d7 100644 --- a/docs/commands/sync-apps.md +++ b/docs/commands/sync-apps.md @@ -101,6 +101,8 @@ gitopscli sync-apps \ ``` usage: gitopscli sync-apps [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -117,6 +119,10 @@ options: --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME diff --git a/gitopscli/cliparser.py b/gitopscli/cliparser.py index 1550be9b..14473105 100644 --- a/gitopscli/cliparser.py +++ b/gitopscli/cliparser.py @@ -219,6 +219,8 @@ def __add_git_credentials_args(deploy_p: ArgumentParser) -> None: def __add_git_commit_user_args(deploy_p: ArgumentParser) -> None: deploy_p.add_argument("--git-user", help="Git Username", default="GitOpsCLI") deploy_p.add_argument("--git-email", help="Git User Email", default="gitopscli@baloise.dev") + deploy_p.add_argument("--git-author-name", help="Git Author Name") + deploy_p.add_argument("--git-author-email", help="Git Author Email") def __add_git_org_and_repo_args(deploy_p: ArgumentParser) -> None: diff --git a/gitopscli/commands/create_pr_preview.py b/gitopscli/commands/create_pr_preview.py index aa901e8f..4ac271f6 100644 --- a/gitopscli/commands/create_pr_preview.py +++ b/gitopscli/commands/create_pr_preview.py @@ -11,6 +11,9 @@ class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -37,6 +40,8 @@ def execute(self) -> None: password=args.password, git_user=args.git_user, git_email=args.git_email, + git_author_name=args.git_author_name, + git_author_email=args.git_author_email, organisation=args.organisation, repository_name=args.repository_name, git_provider=args.git_provider, diff --git a/gitopscli/commands/create_preview.py b/gitopscli/commands/create_preview.py index 09cf6edf..202ece1a 100644 --- a/gitopscli/commands/create_preview.py +++ b/gitopscli/commands/create_preview.py @@ -2,7 +2,7 @@ import os import shutil from dataclasses import dataclass -from typing import Any, Callable +from typing import Any, Callable, Optional from gitopscli.git_api import GitApiConfig, GitRepo, GitRepoApi, GitRepoApiFactory from gitopscli.io_api.yaml_util import update_yaml_file, YAMLException, yaml_file_dump from gitopscli.gitops_config import GitOpsConfig @@ -17,6 +17,9 @@ class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -82,7 +85,13 @@ def execute(self) -> None: self.__deployment_updated_callback(gitops_config.get_updated_message(context)) def __commit_and_push(self, git_repo: GitRepo, message: str) -> None: - git_repo.commit(self.__args.git_user, self.__args.git_email, message) + git_repo.commit( + self.__args.git_user, + self.__args.git_email, + self.__args.git_author_name, + self.__args.git_author_email, + message, + ) git_repo.push() def __get_gitops_config(self) -> GitOpsConfig: diff --git a/gitopscli/commands/delete_pr_preview.py b/gitopscli/commands/delete_pr_preview.py index e6516fb6..de2ea678 100644 --- a/gitopscli/commands/delete_pr_preview.py +++ b/gitopscli/commands/delete_pr_preview.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Optional from gitopscli.git_api import GitApiConfig from .delete_preview import DeletePreviewCommand from .command import Command @@ -10,6 +11,9 @@ class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -27,6 +31,8 @@ def execute(self) -> None: password=args.password, git_user=args.git_user, git_email=args.git_email, + git_author_name=args.git_author_name, + git_author_email=args.git_author_email, organisation=args.organisation, repository_name=args.repository_name, git_provider=args.git_provider, diff --git a/gitopscli/commands/delete_preview.py b/gitopscli/commands/delete_preview.py index ca6f20a6..6c870fa4 100644 --- a/gitopscli/commands/delete_preview.py +++ b/gitopscli/commands/delete_preview.py @@ -1,6 +1,7 @@ import logging import os import shutil +from typing import Optional from dataclasses import dataclass from gitopscli.git_api import GitApiConfig, GitRepo, GitRepoApiFactory, GitRepoApi from gitopscli.gitops_config import GitOpsConfig @@ -15,6 +16,9 @@ class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -60,7 +64,13 @@ def __create_preview_target_git_repo_api(self, gitops_config: GitOpsConfig) -> G ) def __commit_and_push(self, git_repo: GitRepo, message: str) -> None: - git_repo.commit(self.__args.git_user, self.__args.git_email, message) + git_repo.commit( + self.__args.git_user, + self.__args.git_email, + self.__args.git_author_name, + self.__args.git_author_email, + message, + ) git_repo.push() @staticmethod diff --git a/gitopscli/commands/deploy.py b/gitopscli/commands/deploy.py index 9ca8a06c..e81b3c3c 100644 --- a/gitopscli/commands/deploy.py +++ b/gitopscli/commands/deploy.py @@ -10,11 +10,15 @@ class DeployCommand(Command): + # pylint: disable=too-many-instance-attributes @dataclass(frozen=True) class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -119,6 +123,12 @@ def __create_pull_request_title_and_description(self, updated_values: Dict[str, return title, description def __commit(self, git_repo: GitRepo, message: str) -> None: - commit_hash = git_repo.commit(self.__args.git_user, self.__args.git_email, message) + commit_hash = git_repo.commit( + self.__args.git_user, + self.__args.git_email, + self.__args.git_author_name, + self.__args.git_author_email, + message, + ) if commit_hash: self.__commit_hashes.append(commit_hash) diff --git a/gitopscli/commands/sync_apps.py b/gitopscli/commands/sync_apps.py index 5b63b852..2d11da6f 100644 --- a/gitopscli/commands/sync_apps.py +++ b/gitopscli/commands/sync_apps.py @@ -1,4 +1,5 @@ import logging +from typing import Optional from dataclasses import dataclass from gitopscli.git_api import GitApiConfig, GitRepo, GitRepoApiFactory from gitopscli.gitops_exception import GitOpsException @@ -14,6 +15,9 @@ class Args(GitApiConfig): git_user: str git_email: str + git_author_name: Optional[str] + git_author_email: Optional[str] + organisation: str repository_name: str @@ -32,11 +36,25 @@ def _sync_apps_command(args: SyncAppsCommand.Args) -> None: root_config_git_repo_api = GitRepoApiFactory.create(args, args.root_organisation, args.root_repository_name) with GitRepo(team_config_git_repo_api) as team_config_git_repo: with GitRepo(root_config_git_repo_api) as root_config_git_repo: - __sync_apps(team_config_git_repo, root_config_git_repo, args.git_user, args.git_email) + __sync_apps( + team_config_git_repo, + root_config_git_repo, + args.git_user, + args.git_email, + args.git_author_name, + args.git_author_email, + ) # TODO: BETTER NAMES FOR STUFF HERE pylint: disable=fixme -def __sync_apps(tenant_git_repo: GitRepo, root_git_repo: GitRepo, git_user: str, git_email: str) -> None: +def __sync_apps( + tenant_git_repo: GitRepo, + root_git_repo: GitRepo, + git_user: str, + git_email: str, + git_author_name: Optional[str], + git_author_email: Optional[str], +) -> None: logging.info("Team config repository: %s", tenant_git_repo.get_clone_url()) logging.info("Root config repository: %s", root_git_repo.get_clone_url()) root_repo = create_root_repo(root_repo=root_git_repo) @@ -55,14 +73,30 @@ def __sync_apps(tenant_git_repo: GitRepo, root_git_repo: GitRepo, git_user: str, logging.info("Appling changes to: %s", root_repo_tenant.file_path) yaml_file_dump(root_repo_tenant.yaml, root_repo_tenant.file_path) logging.info("Commiting and pushing changes to %s", root_git_repo.get_clone_url()) - __commit_and_push(tenant_git_repo, root_git_repo, git_user, git_email, root_repo_tenant.file_path) + __commit_and_push( + tenant_git_repo, + root_git_repo, + git_user, + git_email, + git_author_name, + git_author_email, + root_repo_tenant.file_path, + ) else: logging.info("No changes applied to %s", root_repo_tenant.file_path) def __commit_and_push( - team_config_git_repo: GitRepo, root_config_git_repo: GitRepo, git_user: str, git_email: str, app_file_name: str + team_config_git_repo: GitRepo, + root_config_git_repo: GitRepo, + git_user: str, + git_email: str, + git_author_name: Optional[str], + git_author_email: Optional[str], + app_file_name: str, ) -> None: author = team_config_git_repo.get_author_from_last_commit() - root_config_git_repo.commit(git_user, git_email, f"{author} updated " + app_file_name) + root_config_git_repo.commit( + git_user, git_email, git_author_name, git_author_email, f"{author} updated " + app_file_name + ) root_config_git_repo.push() diff --git a/gitopscli/git_api/git_repo.py b/gitopscli/git_api/git_repo.py index a7fe072b..d4b03381 100644 --- a/gitopscli/git_api/git_repo.py +++ b/gitopscli/git_api/git_repo.py @@ -70,7 +70,15 @@ def new_branch(self, branch: str) -> None: except GitError as ex: raise GitOpsException(f"Error creating new branch '{branch}'.") from ex - def commit(self, git_user: str, git_email: str, message: str) -> Optional[str]: + def commit( + self, + git_user: str, + git_email: str, + git_author_name: Optional[str], + git_author_email: Optional[str], + message: str, + ) -> Optional[str]: + self.__validate_git_author(git_author_name, git_author_email) repo = self.__get_repo() try: repo.git.add("--all") @@ -78,12 +86,19 @@ def commit(self, git_user: str, git_email: str, message: str) -> Optional[str]: logging.info("Creating commit with message: %s", message) repo.config_writer().set_value("user", "name", git_user).release() repo.config_writer().set_value("user", "email", git_email).release() - repo.git.commit("-m", message, "--author", f"{git_user} <{git_email}>") + if not git_author_name or not git_author_email: + git_author_name = git_user + git_author_email = git_email + repo.git.commit("-m", message, "--author", f"{git_author_name} <{git_author_email}>") return str(repo.head.commit.hexsha) except GitError as ex: raise GitOpsException("Error creating commit.") from ex return None + def __validate_git_author(self, name: Optional[str], email: Optional[str]) -> None: + if (name and not email) or (not name and email): + raise GitOpsException("Please provide the name and email address of the Git author or provide neither!") + def push(self, branch: Optional[str] = None) -> None: repo = self.__get_repo() if not branch: diff --git a/tests/commands/test_create_pr_preview.py b/tests/commands/test_create_pr_preview.py index 346dc578..b6904c7b 100644 --- a/tests/commands/test_create_pr_preview.py +++ b/tests/commands/test_create_pr_preview.py @@ -33,6 +33,8 @@ def test_create_pr_preview(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -57,6 +59,8 @@ def test_create_pr_preview(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, diff --git a/tests/commands/test_create_preview.py b/tests/commands/test_create_preview.py index 48d8bbfe..99e2b30a 100644 --- a/tests/commands/test_create_preview.py +++ b/tests/commands/test_create_preview.py @@ -17,6 +17,8 @@ password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name="GIT_AUTHOR_NAME", + git_author_email="GIT_AUTHOR_EMAIL", organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -193,6 +195,8 @@ def test_create_new_preview(self): call.GitRepo.commit( "GIT_USER", "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", "Create new preview environment for 'my-app' and git hash '3361723dbd91fcfae7b5b8b8b7d462fbc14187a9'.", ), call.GitRepo.push(), @@ -293,6 +297,8 @@ def test_create_new_preview_from_same_template_target_repo(self): call.GitRepo.commit( "GIT_USER", "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", "Create new preview environment for 'my-app' and git hash '3361723dbd91fcfae7b5b8b8b7d462fbc14187a9'.", ), call.GitRepo.push(), @@ -359,6 +365,8 @@ def test_update_existing_preview(self): call.GitRepo.commit( "GIT_USER", "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", "Update preview environment for 'my-app' and git hash '3361723dbd91fcfae7b5b8b8b7d462fbc14187a9'.", ), call.GitRepo.push(), diff --git a/tests/commands/test_delete_pr_preview.py b/tests/commands/test_delete_pr_preview.py index 643c381d..d7f6f67f 100644 --- a/tests/commands/test_delete_pr_preview.py +++ b/tests/commands/test_delete_pr_preview.py @@ -22,6 +22,8 @@ def test_delete_pr_preview(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -37,6 +39,8 @@ def test_delete_pr_preview(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, diff --git a/tests/commands/test_delete_preview.py b/tests/commands/test_delete_preview.py index 2eddcd6d..f246a32b 100644 --- a/tests/commands/test_delete_preview.py +++ b/tests/commands/test_delete_preview.py @@ -69,6 +69,8 @@ def test_delete_existing_happy_flow(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name="GIT_AUTHOR_NAME", + git_author_email="GIT_AUTHOR_EMAIL", organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -87,7 +89,11 @@ def test_delete_existing_happy_flow(self): call.os.path.exists("/tmp/created-tmp-dir/app-685912d3-preview"), call.shutil.rmtree("/tmp/created-tmp-dir/app-685912d3-preview", ignore_errors=True), call.GitRepo.commit( - "GIT_USER", "GIT_EMAIL", "Delete preview environment for 'APP' and preview id 'PREVIEW_ID'." + "GIT_USER", + "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", + "Delete preview environment for 'APP' and preview id 'PREVIEW_ID'.", ), call.GitRepo.push(), ] @@ -100,6 +106,8 @@ def test_delete_missing_happy_flow(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -129,6 +137,8 @@ def test_delete_missing_but_expected_error(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, @@ -158,6 +168,8 @@ def test_missing_gitops_config_yaml_error(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, organisation="ORGA", repository_name="REPO", git_provider=GitProvider.GITHUB, diff --git a/tests/commands/test_deploy.py b/tests/commands/test_deploy.py index 37d3e4e6..853249cb 100644 --- a/tests/commands/test_deploy.py +++ b/tests/commands/test_deploy.py @@ -59,6 +59,8 @@ def test_happy_flow(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name="GIT_AUTHOR_NAME", + git_author_email="GIT_AUTHOR_EMAIL", create_pr=False, auto_merge=False, single_commit=False, @@ -80,10 +82,22 @@ def test_happy_flow(self, mock_print): call.GitRepo.get_full_file_path("test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.c", "foo"), call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.c' to 'foo' in test/file.yml"), + call.GitRepo.commit( + "GIT_USER", + "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", + "changed 'a.b.c' to 'foo' in test/file.yml", + ), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.d", "bar"), call.logging.info("Updated yaml property %s to %s", "a.b.d", "bar"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.d' to 'bar' in test/file.yml"), + call.GitRepo.commit( + "GIT_USER", + "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", + "changed 'a.b.d' to 'bar' in test/file.yml", + ), call.GitRepo.push(), ] @@ -99,6 +113,8 @@ def test_create_pr_single_value_change_happy_flow_with_output(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=True, auto_merge=False, single_commit=False, @@ -122,7 +138,7 @@ def test_create_pr_single_value_change_happy_flow_with_output(self, mock_print): call.GitRepo.get_full_file_path("test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.c", "foo"), call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.c' to 'foo' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.c' to 'foo' in test/file.yml"), call.GitRepo.push(), call.GitRepoApi.create_pull_request_to_default_branch( "gitopscli-deploy-b973b5bb", @@ -151,6 +167,8 @@ def test_create_pr_multiple_value_changes_happy_flow_with_output(self, mock_prin password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=True, auto_merge=False, single_commit=False, @@ -174,10 +192,10 @@ def test_create_pr_multiple_value_changes_happy_flow_with_output(self, mock_prin call.GitRepo.get_full_file_path("test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.c", "foo"), call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.c' to 'foo' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.c' to 'foo' in test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.d", "bar"), call.logging.info("Updated yaml property %s to %s", "a.b.d", "bar"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.d' to 'bar' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.d' to 'bar' in test/file.yml"), call.GitRepo.push(), call.GitRepoApi.create_pull_request_to_default_branch( "gitopscli-deploy-b973b5bb", @@ -209,6 +227,8 @@ def test_create_pr_and_merge_happy_flow(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=True, auto_merge=True, single_commit=False, @@ -232,10 +252,10 @@ def test_create_pr_and_merge_happy_flow(self, mock_print): call.GitRepo.get_full_file_path("test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.c", "foo"), call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.c' to 'foo' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.c' to 'foo' in test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.d", "bar"), call.logging.info("Updated yaml property %s to %s", "a.b.d", "bar"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.d' to 'bar' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.d' to 'bar' in test/file.yml"), call.GitRepo.push(), call.GitRepoApi.create_pull_request_to_default_branch( "gitopscli-deploy-b973b5bb", @@ -258,6 +278,8 @@ def test_single_commit_happy_flow(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=True, @@ -284,6 +306,8 @@ def test_single_commit_happy_flow(self, mock_print): call.GitRepo.commit( "GIT_USER", "GIT_EMAIL", + None, + None, "updated 2 values in test/file.yml\n\na.b.c: foo\na.b.d: bar", ), call.GitRepo.push(), @@ -301,6 +325,8 @@ def test_single_commit_single_value_change_happy_flow(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=True, @@ -322,7 +348,7 @@ def test_single_commit_single_value_change_happy_flow(self, mock_print): call.GitRepo.get_full_file_path("test/file.yml"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.c", "foo"), call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "changed 'a.b.c' to 'foo' in test/file.yml"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "changed 'a.b.c' to 'foo' in test/file.yml"), call.GitRepo.push(), ] @@ -338,6 +364,8 @@ def test_commit_message_multiple_value_changes_happy_flow(self, mock_print): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, @@ -361,7 +389,7 @@ def test_commit_message_multiple_value_changes_happy_flow(self, mock_print): call.logging.info("Updated yaml property %s to %s", "a.b.c", "foo"), call.update_yaml_file("/tmp/created-tmp-dir/test/file.yml", "a.b.d", "bar"), call.logging.info("Updated yaml property %s to %s", "a.b.d", "bar"), - call.GitRepo.commit("GIT_USER", "GIT_EMAIL", "testcommit"), + call.GitRepo.commit("GIT_USER", "GIT_EMAIL", None, None, "testcommit"), call.GitRepo.push(), ] @@ -379,6 +407,8 @@ def test_clone_error(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, @@ -411,6 +441,8 @@ def test_file_not_found(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, @@ -445,6 +477,8 @@ def test_file_parse_error(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, @@ -479,6 +513,8 @@ def test_key_not_found(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, @@ -513,6 +549,8 @@ def test_nothing_to_update(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, create_pr=False, auto_merge=False, single_commit=False, diff --git a/tests/commands/test_sync_apps.py b/tests/commands/test_sync_apps.py index 38e67545..92695924 100644 --- a/tests/commands/test_sync_apps.py +++ b/tests/commands/test_sync_apps.py @@ -16,6 +16,8 @@ password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name="GIT_AUTHOR_NAME", + git_author_email="GIT_AUTHOR_EMAIL", root_organisation="ROOT_ORGA", root_repository_name="ROOT_REPO", organisation="TEAM_ORGA", @@ -143,7 +145,11 @@ def test_sync_apps_happy_flow(self): call.logging.info("Commiting and pushing changes to %s", "https://repository.url/root/root-config.git"), call.GitRepo_team.get_author_from_last_commit(), call.GitRepo_root.commit( - "GIT_USER", "GIT_EMAIL", "author updated /tmp/root-config-repo/apps/team-non-prod.yaml" + "GIT_USER", + "GIT_EMAIL", + "GIT_AUTHOR_NAME", + "GIT_AUTHOR_EMAIL", + "author updated /tmp/root-config-repo/apps/team-non-prod.yaml", ), call.GitRepo_root.push(), ] @@ -233,6 +239,8 @@ def test_sync_apps_missing_bootstrap_element_in_bootstrap_yaml(self): password="PASSWORD", git_user="GIT_USER", git_email="GIT_EMAIL", + git_author_name=None, + git_author_email=None, root_organisation="ROOT_ORGA", root_repository_name="ROOT_REPO", organisation="TEAM_ORGA", diff --git a/tests/git_api/test_git_repo.py b/tests/git_api/test_git_repo.py index 707aa18d..0cf23d5d 100644 --- a/tests/git_api/test_git_repo.py +++ b/tests/git_api/test_git_repo.py @@ -208,7 +208,13 @@ def test_commit(self, logging_mock): with open(testee.get_full_file_path("README.md"), "w") as outfile: outfile.write("new content") - commit_hash = testee.commit(git_user="john doe", git_email="john@doe.com", message="new commit") + commit_hash = testee.commit( + git_user="john doe", + git_email="john@doe.com", + git_author_name=None, + git_author_email=None, + message="new commit", + ) repo = Repo(testee.get_full_file_path(".")) commits = list(repo.iter_commits("master")) @@ -216,19 +222,90 @@ def test_commit(self, logging_mock): self.assertRegex(commit_hash, "^[a-f0-9]{40}$", "Not a long commit hash") self.assertEqual(2, len(commits)) self.assertEqual("new commit\n", commits[0].message) + self.assertEqual("john doe", commits[0].committer.name) + self.assertEqual("john@doe.com", commits[0].committer.email) self.assertEqual("john doe", commits[0].author.name) self.assertEqual("john@doe.com", commits[0].author.email) self.assertIn("foo.md", commits[0].stats.files) self.assertIn("README.md", commits[0].stats.files) logging_mock.info.assert_called_once_with("Creating commit with message: %s", "new commit") + @patch("gitopscli.git_api.git_repo.logging") + def test_commit_with_custom_author(self, logging_mock): + with GitRepo(self.__mock_repo_api) as testee: + testee.clone() + logging_mock.reset_mock() + + with open(testee.get_full_file_path("foo.md"), "w") as outfile: + outfile.write("new file") + with open(testee.get_full_file_path("README.md"), "w") as outfile: + outfile.write("new content") + + commit_hash = testee.commit( + git_user="john doe", + git_email="john@doe.com", + git_author_name="custom author", + git_author_email="custom@author.com", + message="new commit", + ) + repo = Repo(testee.get_full_file_path(".")) + commits = list(repo.iter_commits("master")) + + self.assertIsNotNone(commit_hash) + self.assertRegex(commit_hash, "^[a-f0-9]{40}$", "Not a long commit hash") + self.assertEqual(2, len(commits)) + self.assertEqual("new commit\n", commits[0].message) + self.assertEqual("john doe", commits[0].committer.name) + self.assertEqual("john@doe.com", commits[0].committer.email) + self.assertEqual("custom author", commits[0].author.name) + self.assertEqual("custom@author.com", commits[0].author.email) + self.assertIn("foo.md", commits[0].stats.files) + self.assertIn("README.md", commits[0].stats.files) + logging_mock.info.assert_called_once_with("Creating commit with message: %s", "new commit") + + @patch("gitopscli.git_api.git_repo.logging") + def test_commit_with_custom_author_name_but_no_email_returns_validation_error(self, logging_mock): + with GitRepo(self.__mock_repo_api) as testee: + with pytest.raises(GitOpsException) as ex: + testee.commit( + git_user="john doe", + git_email="john@doe.com", + git_author_name="custom author", + git_author_email="", # missing + message="new commit", + ) + assert str(ex.value).startswith( + "Please provide the name and email address of the Git author or provide neither!" + ) + + @patch("gitopscli.git_api.git_repo.logging") + def test_commit_with_custom_author_email_but_no_name_returns_validation_error(self, logging_mock): + with GitRepo(self.__mock_repo_api) as testee: + with pytest.raises(GitOpsException) as ex: + testee.commit( + git_user="john doe", + git_email="john@doe.com", + git_author_name="", # missing + git_author_email="custom@author.com", + message="new commit", + ) + assert str(ex.value).startswith( + "Please provide the name and email address of the Git author or provide neither!" + ) + @patch("gitopscli.git_api.git_repo.logging") def test_commit_nothing_to_commit(self, logging_mock): with GitRepo(self.__mock_repo_api) as testee: testee.clone() logging_mock.reset_mock() - commit_hash = testee.commit(git_user="john doe", git_email="john@doe.com", message="empty commit") + commit_hash = testee.commit( + git_user="john doe", + git_email="john@doe.com", + git_author_name=None, + git_author_email=None, + message="empty commit", + ) repo = Repo(testee.get_full_file_path(".")) commits = list(repo.iter_commits("master")) diff --git a/tests/test_cliparser.py b/tests/test_cliparser.py index 7cd69519..355730b7 100644 --- a/tests/test_cliparser.py +++ b/tests/test_cliparser.py @@ -85,6 +85,8 @@ EXPECTED_CREATE_PREVIEW_NO_ARGS_ERROR = """\ usage: gitopscli create-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -95,9 +97,11 @@ EXPECTED_CREATE_PR_PREVIEW_NO_ARGS_ERROR = """\ usage: gitopscli create-pr-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation - ORGANISATION --repository-name - REPOSITORY_NAME + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] --pr-id PR_ID [--parent-id PARENT_ID] @@ -108,6 +112,8 @@ EXPECTED_CREATE_PREVIEW_HELP = """\ usage: gitopscli create-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -123,6 +129,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -142,9 +152,11 @@ EXPECTED_CREATE_PR_PREVIEW_HELP = """\ usage: gitopscli create-pr-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation - ORGANISATION --repository-name - REPOSITORY_NAME + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] --pr-id PR_ID [--parent-id PARENT_ID] @@ -159,6 +171,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -178,6 +194,8 @@ EXPECTED_DELETE_PREVIEW_NO_ARGS_ERROR = """\ usage: gitopscli delete-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -190,9 +208,11 @@ EXPECTED_DELETE_PR_PREVIEW_NO_ARGS_ERROR = """\ usage: gitopscli delete-pr-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation - ORGANISATION --repository-name - REPOSITORY_NAME + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] --branch BRANCH @@ -204,6 +224,8 @@ EXPECTED_DELETE_PREVIEW_HELP = """\ usage: gitopscli delete-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -220,6 +242,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -240,9 +266,11 @@ EXPECTED_DELETE_PR_PREVIEW_HELP = """\ usage: gitopscli delete-pr-preview [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation - ORGANISATION --repository-name - REPOSITORY_NAME + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION + --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] --branch BRANCH @@ -258,6 +286,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -279,9 +311,11 @@ [--single-commit [SINGLE_COMMIT]] [--commit-message COMMIT_MESSAGE] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation ORGANISATION - --repository-name REPOSITORY_NAME - [--git-provider GIT_PROVIDER] + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION --repository-name + REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] [--create-pr [CREATE_PR]] [--auto-merge [AUTO_MERGE]] [--merge-method MERGE_METHOD] [--json [JSON]] @@ -295,9 +329,11 @@ [--single-commit [SINGLE_COMMIT]] [--commit-message COMMIT_MESSAGE] --username USERNAME --password PASSWORD [--git-user GIT_USER] - [--git-email GIT_EMAIL] --organisation ORGANISATION - --repository-name REPOSITORY_NAME - [--git-provider GIT_PROVIDER] + [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] + --organisation ORGANISATION --repository-name + REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] [--create-pr [CREATE_PR]] [--auto-merge [AUTO_MERGE]] [--merge-method MERGE_METHOD] [--json [JSON]] @@ -320,6 +356,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -349,6 +389,8 @@ EXPECTED_SYNC_APPS_NO_ARGS_ERROR = """\ usage: gitopscli sync-apps [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -361,6 +403,8 @@ EXPECTED_SYNC_APPS_HELP = """\ usage: gitopscli sync-apps [-h] --username USERNAME --password PASSWORD [--git-user GIT_USER] [--git-email GIT_EMAIL] + [--git-author-name GIT_AUTHOR_NAME] + [--git-author-email GIT_AUTHOR_EMAIL] --organisation ORGANISATION --repository-name REPOSITORY_NAME [--git-provider GIT_PROVIDER] [--git-provider-url GIT_PROVIDER_URL] @@ -377,6 +421,10 @@ --git-user GIT_USER Git Username --git-email GIT_EMAIL Git User Email + --git-author-name GIT_AUTHOR_NAME + Git Author Name + --git-author-email GIT_AUTHOR_EMAIL + Git Author Email --organisation ORGANISATION Apps Git organisation/projectKey --repository-name REPOSITORY_NAME @@ -442,40 +490,46 @@ def _capture_parse_args(args): def assertType(self, o: object, t: type): self.assertTrue(isinstance(o, t)) + def assertEqualIgnoringWhitespaceAndNewlines(self, expected, actual): + def normalize_string(s): + return " ".join(s.split()) + + self.assertEqual(normalize_string(expected), normalize_string(actual)) + def test_no_args(self): exit_code, stdout, stderr = self._capture_parse_args([]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_GITOPSCLI_HELP, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_GITOPSCLI_HELP, stderr) def test_help(self): exit_code, stdout, stderr = self._capture_parse_args(["--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_GITOPSCLI_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_GITOPSCLI_HELP, stdout) self.assertEqual("", stderr) def test_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["-h"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_GITOPSCLI_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_GITOPSCLI_HELP, stdout) self.assertEqual("", stderr) def test_add_pr_comment_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["add-pr-comment"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_ADD_PR_COMMENT_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_ADD_PR_COMMENT_NO_ARGS_ERROR, stderr) def test_add_pr_comment_help(self): exit_code, stdout, stderr = self._capture_parse_args(["add-pr-comment", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_ADD_PR_COMMENT_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_ADD_PR_COMMENT_HELP, stdout) self.assertEqual("", stderr) def test_add_pr_comment_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["add-pr-comment", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_ADD_PR_COMMENT_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_ADD_PR_COMMENT_HELP, stdout) self.assertEqual("", stderr) def test_add_pr_comment_required_args(self): @@ -586,18 +640,18 @@ def test_create_preview_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["create-preview"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_CREATE_PREVIEW_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PREVIEW_NO_ARGS_ERROR, stderr) def test_create_preview_help(self): exit_code, stdout, stderr = self._capture_parse_args(["create-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_CREATE_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_create_preview_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["create-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_CREATE_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_create_preview_required_args(self): @@ -651,6 +705,10 @@ def test_create_preview_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "Bitbucket-Server", "--git-provider-url", @@ -672,6 +730,8 @@ def test_create_preview_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.git_hash, "c0784a34e834117e1489973327ff4ff3c2582b94") @@ -685,18 +745,18 @@ def test_create_pr_preview_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["create-pr-preview"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_CREATE_PR_PREVIEW_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PR_PREVIEW_NO_ARGS_ERROR, stderr) def test_create_pr_preview_help(self): exit_code, stdout, stderr = self._capture_parse_args(["create-pr-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_CREATE_PR_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PR_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_create_pr_preview_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["create-pr-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_CREATE_PR_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_CREATE_PR_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_create_pr_preview_required_args(self): @@ -748,6 +808,10 @@ def test_create_pr_preview_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "Github", "--git-provider-url", @@ -769,6 +833,8 @@ def test_create_pr_preview_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.pr_id, 4711) @@ -782,18 +848,18 @@ def test_delete_preview_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-preview"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_DELETE_PREVIEW_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PREVIEW_NO_ARGS_ERROR, stderr) def test_delete_preview_help(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DELETE_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_delete_preview_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DELETE_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_delete_preview_required_args(self): @@ -845,6 +911,10 @@ def test_delete_preview_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "bitbucket-server", "--git-provider-url", @@ -866,6 +936,8 @@ def test_delete_preview_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.preview_id, "abc123") @@ -879,18 +951,18 @@ def test_delete_pr_preview_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-pr-preview"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_DELETE_PR_PREVIEW_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PR_PREVIEW_NO_ARGS_ERROR, stderr) def test_delete_pr_preview_help(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-pr-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DELETE_PR_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PR_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_delete_pr_preview_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["delete-pr-preview", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DELETE_PR_PREVIEW_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DELETE_PR_PREVIEW_HELP, stdout) self.assertEqual("", stderr) def test_delete_pr_preview_required_args(self): @@ -942,6 +1014,10 @@ def test_delete_pr_preview_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "github", "--git-provider-url", @@ -963,6 +1039,8 @@ def test_delete_pr_preview_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.branch, "BRANCH") @@ -976,18 +1054,18 @@ def test_deploy_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["deploy"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_DEPLOY_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DEPLOY_NO_ARGS_ERROR, stderr) def test_deploy_help(self): exit_code, stdout, stderr = self._capture_parse_args(["deploy", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DEPLOY_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DEPLOY_HELP, stdout) self.assertEqual("", stderr) def test_deploy_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["deploy", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_DEPLOY_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_DEPLOY_HELP, stdout) self.assertEqual("", stderr) def test_deploy_required_args(self): @@ -1044,6 +1122,10 @@ def test_deploy_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "Bitbucket-Server", "--git-provider-url", @@ -1069,6 +1151,8 @@ def test_deploy_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.file, "FILE") @@ -1085,18 +1169,18 @@ def test_sync_apps_no_args(self): exit_code, stdout, stderr = self._capture_parse_args(["sync-apps"]) self.assertEqual(exit_code, 2) self.assertEqual("", stdout) - self.assertEqual(EXPECTED_SYNC_APPS_NO_ARGS_ERROR, stderr) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_SYNC_APPS_NO_ARGS_ERROR, stderr) def test_sync_apps_help(self): exit_code, stdout, stderr = self._capture_parse_args(["sync-apps", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_SYNC_APPS_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_SYNC_APPS_HELP, stdout) self.assertEqual("", stderr) def test_sync_apps_help_shortcut(self): exit_code, stdout, stderr = self._capture_parse_args(["sync-apps", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_SYNC_APPS_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_SYNC_APPS_HELP, stdout) self.assertEqual("", stderr) def test_sync_apps_required_args(self): @@ -1150,6 +1234,10 @@ def test_sync_apps_all_args(self): "GIT_USER", "--git-email", "GIT_EMAIL", + "--git-author-name", + "GIT_AUTHOR_NAME", + "--git-author-email", + "GIT_AUTHOR_EMAIL", "--git-provider", "GitHub", "--git-provider-url", @@ -1172,6 +1260,8 @@ def test_sync_apps_all_args(self): self.assertEqual(args.password, "PASS") self.assertEqual(args.git_user, "GIT_USER") self.assertEqual(args.git_email, "GIT_EMAIL") + self.assertEqual(args.git_author_name, "GIT_AUTHOR_NAME") + self.assertEqual(args.git_author_email, "GIT_AUTHOR_EMAIL") self.assertEqual(args.organisation, "ORG") self.assertEqual(args.repository_name, "REPO") self.assertEqual(args.root_organisation, "ROOT_ORGA") @@ -1188,7 +1278,7 @@ def test_version_args(self): def test_version_help(self): exit_code, stdout, stderr = self._capture_parse_args(["version", "--help"]) self.assertEqual(exit_code, 0) - self.assertEqual(EXPECTED_VERSION_HELP, stdout) + self.assertEqualIgnoringWhitespaceAndNewlines(EXPECTED_VERSION_HELP, stdout) self.assertEqual("", stderr) def test_invalid_boolean(self):