diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml old mode 100755 new mode 100644 diff --git a/python/rpdk/typescript/codegen.py b/python/rpdk/typescript/codegen.py index e958691..250cfd4 100644 --- a/python/rpdk/typescript/codegen.py +++ b/python/rpdk/typescript/codegen.py @@ -55,6 +55,7 @@ def __init__(self): self.package_name = None self.package_root = None self._use_docker = None + self._no_docker = None self._protocol_version = "2.0.0" self._build_command = None self._lib_path = None @@ -72,14 +73,30 @@ def _init_from_project(self, project): def _init_settings(self, project): LOG.debug("Writing settings") - self._use_docker = self._use_docker or input_with_validation( - "Use docker for platform-independent packaging (Y/n)?\n", - validate_no, - "This is highly recommended unless you are experienced \n" - "with cross-platform Typescript packaging.", - ) + # If use_docker specified in .rpdk-config file or cli switch + # Ensure only 1 is true, with preference to use_docker + if project.settings.get("use_docker") is True: + self._use_docker = True + self._no_docker = False + # If no_docker specified in .rpdk-config file or cli switch + elif project.settings.get("no_docker") is True: + self._use_docker = False + self._no_docker = True + else: + # If neither no_docker nor use_docker specified in .rpdk-config + # file or cli switch, prompt to use containers or not + self._use_docker = input_with_validation( + "Use docker for platform-independent packaging (Y/n)?\n", + validate_no, + "This is highly recommended unless you are experienced \n" + "with cross-platform Typescript packaging.", + ) + self._no_docker = not self._use_docker + # switched to 'use_docker' from 'useDocker' to be in line with python version + # project.settings will get saved into .rpdk-config by cloudformation-cli project.settings["use_docker"] = self._use_docker + project.settings["no_docker"] = self._no_docker project.settings["protocolVersion"] = self._protocol_version def init(self, project): diff --git a/python/rpdk/typescript/parser.py b/python/rpdk/typescript/parser.py index 2caf567..1819a77 100644 --- a/python/rpdk/typescript/parser.py +++ b/python/rpdk/typescript/parser.py @@ -6,7 +6,9 @@ def setup_subparser(subparsers, parents): ) parser.set_defaults(language="typescript") - parser.add_argument( + group = parser.add_mutually_exclusive_group() + + group.add_argument( "-d", "--use-docker", action="store_true", @@ -15,4 +17,11 @@ def setup_subparser(subparsers, parents): with cross-platform TypeScript packaging.""", ) + group.add_argument( + "--no-docker", + action="store_true", + help="""Generally not recommended unless you are experienced + with cross-platform Typescript packaging.""", + ) + return parser diff --git a/tests/plugin/codegen_test.py b/tests/plugin/codegen_test.py index fa1dcc7..736d4b1 100644 --- a/tests/plugin/codegen_test.py +++ b/tests/plugin/codegen_test.py @@ -52,6 +52,69 @@ def project(tmp_path: str): return project +@pytest.fixture +def project_use_docker(tmp_path: str): + project_use_docker = Project(root=tmp_path) + + patch_plugins = patch.dict( + "rpdk.core.plugin_registry.PLUGIN_REGISTRY", + {TypescriptLanguagePlugin.NAME: lambda: TypescriptLanguagePlugin}, + clear=True, + ) + with patch_plugins: + current_path = os.path.abspath(__file__) + lib_abspath = os.path.abspath(os.path.join(current_path, "..", "..", "..")) + TypescriptLanguagePlugin.SUPPORT_LIB_URI = f"file:{lib_abspath}" + project_use_docker.init( + TYPE_NAME, + TypescriptLanguagePlugin.NAME, + settings={"use_docker": True, "no_docker": False}, + ) + return project_use_docker + + +@pytest.fixture +def project_no_docker(tmp_path: str): + project_no_docker = Project(root=tmp_path) + + patch_plugins = patch.dict( + "rpdk.core.plugin_registry.PLUGIN_REGISTRY", + {TypescriptLanguagePlugin.NAME: lambda: TypescriptLanguagePlugin}, + clear=True, + ) + with patch_plugins: + current_path = os.path.abspath(__file__) + lib_abspath = os.path.abspath(os.path.join(current_path, "..", "..", "..")) + TypescriptLanguagePlugin.SUPPORT_LIB_URI = f"file:{lib_abspath}" + project_no_docker.init( + TYPE_NAME, + TypescriptLanguagePlugin.NAME, + settings={"use_docker": False, "no_docker": True}, + ) + return project_no_docker + + +@pytest.fixture +def project_both_true(tmp_path: str): + project_both_true = Project(root=tmp_path) + + patch_plugins = patch.dict( + "rpdk.core.plugin_registry.PLUGIN_REGISTRY", + {TypescriptLanguagePlugin.NAME: lambda: TypescriptLanguagePlugin}, + clear=True, + ) + with patch_plugins: + current_path = os.path.abspath(__file__) + lib_abspath = os.path.abspath(os.path.join(current_path, "..", "..", "..")) + TypescriptLanguagePlugin.SUPPORT_LIB_URI = f"file:{lib_abspath}" + project_both_true.init( + TYPE_NAME, + TypescriptLanguagePlugin.NAME, + settings={"use_docker": True, "no_docker": True}, + ) + return project_both_true + + def get_files_in_project(project: Project): return { str(child.relative_to(project.root)): child for child in project.root.rglob("*") @@ -92,11 +155,35 @@ def test__remove_build_artifacts_file_not_found(tmp_path: str): mock_log.debug.assert_called_once() -def test_initialize(project: Project): - lib_path = project._plugin._lib_path - assert project.settings == {"use_docker": False, "protocolVersion": "2.0.0"} +@pytest.fixture +def project_no_docker_use_docker_values( + request, project, project_use_docker, project_no_docker, project_both_true +): + return [ + (project, True, False), + (project_use_docker, False, True), + (project_no_docker, True, False), + (project_both_true, False, True), + ][request.param] + + +@pytest.mark.parametrize( + "project_no_docker_use_docker_values", [0, 1, 2, 3], indirect=True +) +def test_initialize(project_no_docker_use_docker_values): + ( + project_value, + no_docker_value, + use_docker_value, + ) = project_no_docker_use_docker_values + lib_path = project_value._plugin._lib_path + assert project_value.settings == { + "protocolVersion": "2.0.0", + "no_docker": no_docker_value, + "use_docker": use_docker_value, + } - files = get_files_in_project(project) + files = get_files_in_project(project_value) assert set(files) == { ".gitignore", ".npmrc", @@ -122,12 +209,12 @@ def test_initialize(project: Project): assert lib_path in package_json readme = files["README.md"].read_text() - assert project.type_name in readme + assert project_value.type_name in readme assert SUPPORT_LIB_NAME in readme assert "handlers.ts" in readme assert "models.ts" in readme - assert project.entrypoint in files["template.yml"].read_text() + assert project_value.entrypoint in files["template.yml"].read_text() def test_generate(project: Project): diff --git a/tests/plugin/parser_test.py b/tests/plugin/parser_test.py index d5c4135..cf457bc 100644 --- a/tests/plugin/parser_test.py +++ b/tests/plugin/parser_test.py @@ -1,5 +1,6 @@ import argparse +import pytest from rpdk.typescript.parser import setup_subparser @@ -12,11 +13,22 @@ def test_setup_subparser(): args = sub_parser.parse_args([]) assert args.language == "typescript" assert args.use_docker is False + assert args.no_docker is False short_args = sub_parser.parse_args(["-d"]) assert short_args.language == "typescript" assert short_args.use_docker is True + assert short_args.no_docker is False long_args = sub_parser.parse_args(["--use-docker"]) assert long_args.language == "typescript" assert long_args.use_docker is True + assert long_args.no_docker is False + + no_docker = sub_parser.parse_args(["--no-docker"]) + assert no_docker.language == "typescript" + assert no_docker.use_docker is False + assert no_docker.no_docker is True + + with pytest.raises(SystemExit): + sub_parser.parse_args(["--no-docker", "--use-docker"])