diff --git a/tests/trestlebot/entrypoints/test_autosync.py b/tests/trestlebot/entrypoints/test_autosync.py index b6d7ccc5..5f923d2a 100644 --- a/tests/trestlebot/entrypoints/test_autosync.py +++ b/tests/trestlebot/entrypoints/test_autosync.py @@ -136,37 +136,3 @@ def test_invalid_working_dir(valid_args_dict: Dict[str, str], caplog: Any) -> No and "Root path . is not a valid trestle project root" in record.message for record in caplog.records ) - - -@patch( - "trestlebot.entrypoints.log.configure_logger", - Mock(side_effect=configure_test_logger), -) -def test_with_target_branch( - tmp_trestle_dir: str, valid_args_dict: Dict[str, str], caplog: Any -) -> None: - """Test with target branch set an an unsupported Git provider""" - args_dict = valid_args_dict - - args_dict["target-branch"] = "main" - args_dict["working-dir"] = tmp_trestle_dir - - # Patch is_github_actions since these tests will be running in - # GitHub Actions - with patch( - "trestlebot.entrypoints.entrypoint_base.is_github_actions" - ) as mock_check, patch("sys.argv", ["trestlebot", *args_dict_to_list(args_dict)]): - mock_check.return_value = False - - with pytest.raises(SystemExit, match="2"): - cli_main() - - assert any( - record.levelno == logging.ERROR - and "Invalid args --target-branch: target-branch flag is set with an " - "unset git provider. To test locally, set the GITHUB_ACTIONS or GITLAB_CI environment variable." - in record.message - for record in caplog.records - ) - - mock_check.assert_called_once() diff --git a/tests/trestlebot/entrypoints/test_entrypoint_base.py b/tests/trestlebot/entrypoints/test_entrypoint_base.py index 87618c42..e47f14a4 100644 --- a/tests/trestlebot/entrypoints/test_entrypoint_base.py +++ b/tests/trestlebot/entrypoints/test_entrypoint_base.py @@ -25,7 +25,12 @@ def test_set_git_provider_with_github() -> None: """Test set_git_provider function in Entrypoint Base for GitHub Actions""" provider: Optional[GitProvider] fake_token = StringIO("fake_token") - args = argparse.Namespace(target_branch="main", with_token=fake_token) + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="", + git_server_url="", + ) provider = EntrypointBase.set_git_provider(args=args) assert isinstance(provider, GitHub) @@ -43,7 +48,12 @@ def test_set_git_provider_with_gitlab() -> None: """Test set_git_provider function in Entrypoint Base for GitLab CI""" provider: Optional[GitProvider] fake_token = StringIO("fake_token") - args = argparse.Namespace(target_branch="main", with_token=fake_token) + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="", + git_server_url="", + ) provider = EntrypointBase.set_git_provider(args=args) assert isinstance(provider, GitLab) @@ -52,7 +62,12 @@ def test_set_git_provider_with_gitlab() -> None: def test_set_git_provider_with_gitlab_with_failure() -> None: """Trigger error with GitLab provider with insufficient environment variables""" fake_token = StringIO("fake_token") - args = argparse.Namespace(target_branch="main", with_token=fake_token) + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="", + git_server_url="", + ) with pytest.raises( GitProviderException, match="Set CI_SERVER_PROTOCOL and CI SERVER HOST environment variables", @@ -65,13 +80,17 @@ def test_set_git_provider_with_none() -> None: """Test set_git_provider function when no git provider is set""" fake_token = StringIO("fake_token") provider: Optional[GitProvider] - args = argparse.Namespace(target_branch="main", with_token=fake_token) + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="", + git_server_url="", + ) with pytest.raises( EntrypointInvalidArgException, - match="Invalid args --target-branch: " - "target-branch flag is set with an unset git provider. To test locally, set the " - "GITHUB_ACTIONS or GITLAB_CI environment variable.", + match="Invalid args --target-branch, --git-provider-type: " + "Could not detect Git provider from environment or inputs", ): EntrypointBase.set_git_provider(args=args) @@ -90,3 +109,37 @@ def test_set_provider_with_no_token() -> None: "with-token flag must be set when using target-branch", ): EntrypointBase.set_git_provider(args=args) + + +def test_set_provider_with_input() -> None: + """Test set_git_provider function with type and server url input.""" + provider: Optional[GitProvider] + fake_token = StringIO("fake_token") + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="github", + git_server_url="", + ) + provider = EntrypointBase.set_git_provider(args=args) + assert isinstance(provider, GitHub) + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="gitlab", + git_server_url="", + ) + provider = EntrypointBase.set_git_provider(args=args) + assert isinstance(provider, GitLab) + + args = argparse.Namespace( + target_branch="main", + with_token=fake_token, + git_provider_type="github", + git_server_url="https://notgithub.com", + ) + with pytest.raises( + EntrypointInvalidArgException, + match="Invalid args --server-url: GitHub provider does not support custom server URLs", + ): + EntrypointBase.set_git_provider(args=args) diff --git a/trestlebot/const.py b/trestlebot/const.py index 76560a8c..9075338c 100644 --- a/trestlebot/const.py +++ b/trestlebot/const.py @@ -47,3 +47,7 @@ COMMIT = "commit" PR_NUMBER = "pr_number" CHANGES = "changes" + +# Git Provider Types +GITHUB = "github" +GITLAB = "gitlab" diff --git a/trestlebot/entrypoints/entrypoint_base.py b/trestlebot/entrypoints/entrypoint_base.py index 360190e0..09e00012 100644 --- a/trestlebot/entrypoints/entrypoint_base.py +++ b/trestlebot/entrypoints/entrypoint_base.py @@ -66,7 +66,7 @@ def setup_common_arguments(self) -> None: def _set_required_git_args(self) -> None: """Create an argument group for required git-related configuration.""" required_git_arg_group = self.parser.add_argument_group( - "required git configuration" + "required arguments for git operations" ) required_git_arg_group.add_argument( "--branch", @@ -90,7 +90,7 @@ def _set_required_git_args(self) -> None: def _set_optional_git_args(self) -> None: """Create an argument group for optional git-related configuration.""" optional_git_arg_group = self.parser.add_argument_group( - "optional git configuration" + "optional arguments for git operations" ) optional_git_arg_group.add_argument( "--file-patterns", @@ -122,7 +122,7 @@ def _set_optional_git_args(self) -> None: def _set_git_provider_args(self) -> None: """Create an argument group for optional git-provider configuration.""" git_provider_arg_group = self.parser.add_argument_group( - "git provider configuration" + "optional arguments for interacting with the git provider" ) git_provider_arg_group.add_argument( "--target-branch", @@ -147,6 +147,20 @@ def _set_git_provider_args(self) -> None: default="Automatic updates from trestlebot", help="Customized title for submitted pull requests", ) + git_provider_arg_group.add_argument( + "--git-provider-type", + required=False, + choices=[const.GITHUB, const.GITLAB], + help="Optional supported Git provider identify. " + "Defaults to auto detection based on pre-defined CI environment variables.", + ) + git_provider_arg_group.add_argument( + "--git-server-url", + type=str, + required=False, + help="Optional git server url for supported type. " + "Defaults to auto detection based on pre-defined CI environment variables.", + ) @staticmethod def set_git_provider(args: argparse.Namespace) -> Optional[GitProvider]: @@ -160,11 +174,17 @@ def set_git_provider(args: argparse.Namespace) -> Optional[GitProvider]: ) access_token = args.with_token.read().strip() try: - git_provider = GitProviderFactory.provider_factory(access_token) + git_provider_type = args.git_provider_type + git_server_url = args.git_server_url + git_provider = GitProviderFactory.provider_factory( + access_token, git_provider_type, git_server_url + ) except ValueError as e: raise EntrypointInvalidArgException("--server-url", str(e)) except RuntimeError as e: - raise EntrypointInvalidArgException("--target-branch", str(e)) from e + raise EntrypointInvalidArgException( + "--target-branch, --git-provider-type", str(e) + ) from e return git_provider @staticmethod diff --git a/trestlebot/provider_factory.py b/trestlebot/provider_factory.py index a01cd390..d8608b6c 100644 --- a/trestlebot/provider_factory.py +++ b/trestlebot/provider_factory.py @@ -4,6 +4,7 @@ import logging from typing import Optional +from trestlebot import const from trestlebot.github import GitHub, is_github_actions from trestlebot.gitlab import GitLab, get_gitlab_root_url, is_gitlab_ci from trestlebot.provider import GitProvider @@ -41,14 +42,17 @@ def provider_factory( git_provider: Optional[GitProvider] = None - if type == "github": + if type == const.GITHUB: logger.debug("Creating GitHub provider") if server_url and server_url != "https://github.com": raise ValueError("GitHub provider does not support custom server URLs") git_provider = GitHub(access_token=access_token) - elif type == "gitlab": + elif type == const.GITLAB: logger.debug("Creating GitLab provider") - git_provider = GitLab(api_token=access_token, server_url=server_url) + if not server_url: + git_provider = GitLab(api_token=access_token) + else: + git_provider = GitLab(api_token=access_token, server_url=server_url) else: logger.debug( "No type or server_url provided." @@ -57,7 +61,9 @@ def provider_factory( git_provider = GitProviderFactory._detect_from_environment(access_token) if git_provider is None: - raise RuntimeError("Could not detect Git provider from environment") + raise RuntimeError( + "Could not detect Git provider from environment or inputs" + ) return git_provider