From d6d4406c3cf74ea6d1d04c49868fc4c975bc8c0b Mon Sep 17 00:00:00 2001 From: ewuerger Date: Thu, 26 Sep 2024 13:53:29 +0200 Subject: [PATCH] refactor!: Use envvar in CLI options The CLI usage was simplified by using `envvar` on any flag or whenever possible. Special thanks for the hint and therefore: Co-authored-by: Wuestengecko --- capella2polarion/__main__.py | 57 ++++++-- ci-templates/gitlab/render_documents.yaml | 20 +-- ci-templates/gitlab/synchronise_elements.yml | 22 +-- tests/test_cli.py | 143 +++++++++++++++---- 4 files changed, 182 insertions(+), 60 deletions(-) diff --git a/capella2polarion/__main__.py b/capella2polarion/__main__.py index 9dbf786b..b5174d80 100644 --- a/capella2polarion/__main__.py +++ b/capella2polarion/__main__.py @@ -22,13 +22,15 @@ @click.group() -@click.option("--debug", is_flag=True, default=False) +@click.option( + "--debug", is_flag=True, envvar="CAPELLA2POLARION_DEBUG", default=False +) @click.option( "--polarion-project-id", type=str, required=False, default=None, - envvar="POLARION_PROJECT_ID", + envvar="CAPELLA2POLARION_PROJECT_ID", ) @click.option( "--polarion-url", @@ -36,8 +38,18 @@ type=str, ) @click.option("--polarion-pat", envvar="POLARION_PAT", type=str) -@click.option("--polarion-delete-work-items", is_flag=True, default=False) -@click.option("--capella-model", type=cli_helpers.ModelCLI(), default=None) +@click.option( + "--polarion-delete-work-items", + is_flag=True, + envvar="CAPELLA2POLARION_DELETE_WORK_ITEMS", + default=False, +) +@click.option( + "--capella-model", + type=cli_helpers.ModelCLI(), + envvar="CAPELLA2POLARION_CAPELLA_MODEL", + default=None, +) @click.pass_context def cli( ctx: click.core.Context, @@ -76,11 +88,27 @@ def print_cli_state(capella2polarion_cli: Capella2PolarionCli) -> None: @click.option( "--synchronize-config", type=click.File(mode="r", encoding="utf8"), + envvar="CAPELLA2POLARION_SYNCHRONIZE_CONFIG", default=None, ) -@click.option("--force-update", is_flag=True, default=False) -@click.option("--type-prefix", type=str, default="") -@click.option("--role-prefix", type=str, default="") +@click.option( + "--force-update", + is_flag=True, + envvar="CAPELLA2POLARION_FORCE_UPDATE", + default=False, +) +@click.option( + "--type-prefix", + type=str, + envvar="CAPELLA2POLARION_TYPE_PREFIX", + default="", +) +@click.option( + "--role-prefix", + type=str, + envvar="CAPELLA2POLARION_ROLE_PREFIX", + default="", +) @click.pass_context def synchronize( ctx: click.core.Context, @@ -133,10 +161,21 @@ def synchronize( @click.option( "--document-rendering-config", type=click.File(mode="r", encoding="utf8"), + envvar="CAPELLA2POLARION_DOCUMENT_CONFIG", default=None, ) -@click.option("--overwrite-layouts", is_flag=True, default=False) -@click.option("--overwrite-numbering", is_flag=True, default=False) +@click.option( + "--overwrite-layouts", + is_flag=True, + envvar="CAPELLA2POLARION_OVERWRITE_LAYOUTS", + default=False, +) +@click.option( + "--overwrite-numbering", + is_flag=True, + envvar="CAPELLA2POLARION_OVERWRITE_NUMBERING", + default=False, +) @click.pass_context def render_documents( ctx: click.core.Context, diff --git a/ci-templates/gitlab/render_documents.yaml b/ci-templates/gitlab/render_documents.yaml index bade9deb..e6156b68 100644 --- a/ci-templates/gitlab/render_documents.yaml +++ b/ci-templates/gitlab/render_documents.yaml @@ -3,6 +3,15 @@ variables: CAPELLA2POLARION_DEBUG: "0" + # Remember to set the following environment variables: + # POLARION_HOST + # POLARION_PAT + # CAPELLA2POLARION_PROJECT_ID + # CAPELLA2POLARION_CAPELLA_MODEL + # CAPELLA2POLARION_DOCUMENT_CONFIG + # Optional flags: + # CAPELLA2POLARION_OVERWRITE_LAYOUTS - Overwrite default Live-Doc layouts + # CAPELLA2POLARION_OVERWRITE_NUMBERING - Overwrite default heading numbering capella2polarion_render_documents: needs: @@ -12,13 +21,4 @@ capella2polarion_render_documents: script: - pip install "capella2polarion${CAPELLA2POLARION_VERSION:+==$CAPELLA2POLARION_VERSION}" - - > - python \ - -m capella2polarion \ - $([[ $CAPELLA2POLARION_DEBUG -eq 1 ]] && echo '--debug') \ - --polarion-project-id=${CAPELLA2POLARION_PROJECT_ID:?} \ - --capella-model="${CAPELLA2POLARION_MODEL_JSON:?}" \ - render-documents \ - $([[ $CAPELLA2POLARION_OVERWRITE_LAYOUTS -eq 1 ]] && echo '--overwrite-layouts') \ - $([[ $CAPELLA2POLARION_OVERWRITE_NUMBERING -eq 1 ]] && echo '--overwrite-numbering') \ - --document-rendering-config="${CAPELLA2POLARION_DOCUMENT_CONFIG:?}" + - python -m capella2polarion render-documents diff --git a/ci-templates/gitlab/synchronise_elements.yml b/ci-templates/gitlab/synchronise_elements.yml index efac5e79..72fd944e 100644 --- a/ci-templates/gitlab/synchronise_elements.yml +++ b/ci-templates/gitlab/synchronise_elements.yml @@ -3,6 +3,16 @@ variables: CAPELLA2POLARION_DEBUG: "1" + # Remember to set the following environment variables: + # POLARION_HOST + # POLARION_PAT + # CAPELLA2POLARION_PROJECT_ID + # CAPELLA2POLARION_CAPELLA_MODEL + # CAPELLA2POLARION_SYNCHRONIZE_CONFIG + # Optional flags: + # CAPELLA2POLARION_FORCE_UPDATE - Simulate initial run + # CAPELLA2POLARION_TYPE_PREFIX - Prefix for work item types + # CAPELLA2POLARION_ROLE_PREFIX - Prefix for work item link roles capella2polarion_synchronise_elements: needs: @@ -11,14 +21,4 @@ capella2polarion_synchronise_elements: script: - pip install "capella2polarion${CAPELLA2POLARION_VERSION:+==$CAPELLA2POLARION_VERSION}" - - > - python \ - -m capella2polarion \ - $([[ $CAPELLA2POLARION_DEBUG -eq 1 ]] && echo '--debug') \ - --polarion-project-id=${CAPELLA2POLARION_PROJECT_ID:?} \ - --capella-model="${CAPELLA2POLARION_MODEL_JSON:?}" \ - synchronize \ - --synchronize-config=${CAPELLA2POLARION_CONFIG:?} \ - $([[ $CAPELLA2POLARION_FORCE_UPDATE -eq 1 ]] && echo '--force-update') \ - ${CAPELLA2POLARION_TYPE_PREFIX:+--type-prefix="$CAPELLA2POLARION_TYPE_PREFIX"} \ - ${CAPELLA2POLARION_ROLE_PREFIX:+--role-prefix="$CAPELLA2POLARION_ROLE_PREFIX"} + - python -m capella2polarion synchronize diff --git a/tests/test_cli.py b/tests/test_cli.py index be6fc804..07f2d006 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -3,7 +3,9 @@ from __future__ import annotations +import collections.abc as cabc import json +import os from unittest import mock import polarion_rest_api_client as polarion_api @@ -22,7 +24,9 @@ ) -def test_migrate_model_elements(monkeypatch: pytest.MonkeyPatch): +def setup_sync_cli_test( + monkeypatch: pytest.MonkeyPatch, +) -> tuple[mock.MagicMock, ...]: mock_api_client = mock.MagicMock(spec=polarion_api.PolarionClient) monkeypatch.setattr(polarion_api, "PolarionClient", mock_api_client) mock_project_client = mock.MagicMock(spec=polarion_api.ProjectClient) @@ -57,37 +61,16 @@ def test_migrate_model_elements(monkeypatch: pytest.MonkeyPatch): "compare_and_update_work_items", mock_patch_work_items, ) - - command: list[str] = [ - "--polarion-project-id", - "{project-id}", - "--polarion-url", - "https://www.czy.de", - "--polarion-pat", - "PrivateAcessToken", - "--polarion-delete-work-items", - "--capella-model", - json.dumps(TEST_MODEL), - "synchronize", - "--synchronize-config", - str(TEST_MODEL_ELEMENTS_CONFIG), - ] - - result = testing.CliRunner().invoke(main.cli, command, terminal_width=60) - - assert result.exit_code == 0 - assert mock_get_polarion_wi_map.call_count == 1 - assert mock_generate_work_items.call_count == 2 - assert mock_generate_work_items.call_args_list[1][1] == { - "generate_links": True, - "generate_attachments": True, - } - assert mock_delete_work_items.call_count == 1 - assert mock_patch_work_items.call_count == 1 - assert mock_post_work_items.call_count == 1 + return ( + mock_get_polarion_wi_map, + mock_generate_work_items, + mock_delete_work_items, + mock_patch_work_items, + mock_post_work_items, + ) -def test_render_documents(monkeypatch: pytest.MonkeyPatch): +def setup_render_docs_cli_test(monkeypatch: pytest.MonkeyPatch): mock_api_client = mock.MagicMock(spec=polarion_api.PolarionClient) monkeypatch.setattr(polarion_api, "PolarionClient", mock_api_client) mock_project_client = mock.MagicMock(spec=polarion_api.ProjectClient) @@ -129,6 +112,59 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): "update_documents", mock_update_documents, ) + return ( + mock_get_polarion_wi_map, + mock_get_document, + mock_create_documents, + mock_update_documents, + ) + + +def test_migrate_model_elements(monkeypatch: pytest.MonkeyPatch): + ( + mock_get_polarion_wi_map, + mock_generate_work_items, + mock_delete_work_items, + mock_patch_work_items, + mock_post_work_items, + ) = setup_sync_cli_test(monkeypatch) + + command: list[str] = [ + "--polarion-project-id", + "{project-id}", + "--polarion-url", + "https://www.czy.de", + "--polarion-pat", + "PrivateAcessToken", + "--polarion-delete-work-items", + "--capella-model", + json.dumps(TEST_MODEL), + "synchronize", + "--synchronize-config", + str(TEST_MODEL_ELEMENTS_CONFIG), + ] + + result = testing.CliRunner().invoke(main.cli, command, terminal_width=60) + + assert result.exit_code == 0 + assert mock_get_polarion_wi_map.call_count == 1 + assert mock_generate_work_items.call_count == 2 + assert mock_generate_work_items.call_args_list[1][1] == { + "generate_links": True, + "generate_attachments": True, + } + assert mock_delete_work_items.call_count == 1 + assert mock_patch_work_items.call_count == 1 + assert mock_post_work_items.call_count == 1 + + +def test_render_documents(monkeypatch: pytest.MonkeyPatch): + ( + mock_get_polarion_wi_map, + mock_get_document, + mock_create_documents, + mock_update_documents, + ) = setup_render_docs_cli_test(monkeypatch) command: list[str] = [ "--polarion-project-id", @@ -172,3 +208,50 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): assert len(mock_update_documents.call_args_list[1].args[0]) == 0 assert mock_update_documents.call_args_list[0].args[1] is None assert mock_update_documents.call_args_list[1].args[1] == "TestProject" + + +@pytest.mark.parametrize( + ["command", "envvars", "setup_func"], + [ + pytest.param( + "synchronize", + { + "CAPELLA2POLARION_SYNCHRONIZE_CONFIG": str( + TEST_MODEL_ELEMENTS_CONFIG + ) + }, + setup_sync_cli_test, + id="Model Sync", + ), + pytest.param( + "render-documents", + { + "CAPELLA2POLARION_DOCUMENT_CONFIG": str( + TEST_COMBINED_DOCUMENT_CONFIG + ) + }, + setup_render_docs_cli_test, + id="Live-Doc rendering", + ), + ], +) +def test_cli_commands_with_environment_variables( + monkeypatch: pytest.MonkeyPatch, + command: list[str], + envvars: dict[str, str], + setup_func: cabc.Callable[ + [pytest.MonkeyPatch], tuple[mock.MagicMock, ...] + ], +): + os.environ["CAPELLA2POLARION_PROJECT_ID"] = "{project-id}" + os.environ["POLARION_HOST"] = "https://www.czy.de" + os.environ["POLARION_PAT"] = "PrivateAcessToken" + os.environ["CAPELLA2POLARION_CAPELLA_MODEL"] = json.dumps(TEST_MODEL) + os.environ["CAPELLA2POLARION_DELETE_WORK_ITEMS"] = "1" + setup_func(monkeypatch) + for key, value in envvars.items(): + os.environ[key] = value + + result = testing.CliRunner().invoke(main.cli, command, terminal_width=60) + + assert result.exit_code == 0