From 0b6f79928c5ec86c0977b5bc0d030c0de7219efe Mon Sep 17 00:00:00 2001 From: Bartlomiej Gmerek <42570669+Gmerold@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:02:42 +0200 Subject: [PATCH] chore: Building charm in independent step (#139) --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependabot_pr.yaml | 2 +- .github/workflows/issues.yaml | 2 +- .github/workflows/main.yaml | 30 ++++++++++++--------- .github/workflows/promote.yaml | 2 +- CONTRIBUTING.md | 12 ++++++--- tests/integration/conftest.py | 38 +++++++++++++++++++++++++++ tests/integration/test_integration.py | 22 ++++++++-------- 8 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 tests/integration/conftest.py diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 17bb7d3..68a7930 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -8,4 +8,4 @@ on: jobs: codeql: name: CodeQL Analysis - uses: canonical/sdcore-github-workflows/.github/workflows/codeql-analysis.yml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/codeql-analysis.yml@v1.0.0 diff --git a/.github/workflows/dependabot_pr.yaml b/.github/workflows/dependabot_pr.yaml index 528785b..17556b1 100644 --- a/.github/workflows/dependabot_pr.yaml +++ b/.github/workflows/dependabot_pr.yaml @@ -9,4 +9,4 @@ permissions: jobs: auto-merge: - uses: canonical/sdcore-github-workflows/.github/workflows/dependabot_pr.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/dependabot_pr.yaml@v1.0.0 diff --git a/.github/workflows/issues.yaml b/.github/workflows/issues.yaml index f38c29f..c356881 100644 --- a/.github/workflows/issues.yaml +++ b/.github/workflows/issues.yaml @@ -7,6 +7,6 @@ on: jobs: update: name: Update Issue - uses: canonical/sdcore-github-workflows/.github/workflows/issues.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/issues.yaml@v1.0.0 secrets: JIRA_URL: ${{ secrets.JIRA_URL }} diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index b6075d5..5933fab 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -10,26 +10,34 @@ on: jobs: check-libraries: - uses: canonical/sdcore-github-workflows/.github/workflows/check-libraries.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/check-libraries.yaml@v1.0.0 secrets: CHARMCRAFT_AUTH: ${{ secrets.CHARMCRAFT_AUTH }} lint-report: - uses: canonical/sdcore-github-workflows/.github/workflows/lint-report.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/lint-report.yaml@v1.0.0 terraform-check: - uses: canonical/sdcore-github-workflows/.github/workflows/terraform.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/terraform.yaml@v1.0.0 static-analysis: - uses: canonical/sdcore-github-workflows/.github/workflows/static-analysis.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/static-analysis.yaml@v1.0.0 unit-tests-with-coverage: - uses: canonical/sdcore-github-workflows/.github/workflows/unit-test.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/unit-test.yaml@v1.0.0 + + build: + needs: + - lint-report + - static-analysis + - unit-tests-with-coverage + uses: canonical/sdcore-github-workflows/.github/workflows/build.yaml@v1.0.0 + secrets: inherit integration-test: - uses: canonical/sdcore-github-workflows/.github/workflows/integration-test.yaml@v0.0.1 - with: - charm-file-name: "sdcore-pcf-k8s_ubuntu-22.04-amd64.charm" + needs: + - build + uses: canonical/sdcore-github-workflows/.github/workflows/integration-test.yaml@v1.0.0 publish-charm: name: Publish Charm @@ -39,9 +47,8 @@ jobs: - unit-tests-with-coverage - integration-test if: ${{ github.ref_name == 'main' }} - uses: canonical/sdcore-github-workflows/.github/workflows/publish-charm.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/publish-charm.yaml@v1.0.0 with: - charm-file-name: "sdcore-pcf-k8s_ubuntu-22.04-amd64.charm" track-name: 1.5 secrets: CHARMCRAFT_AUTH: ${{ secrets.CHARMCRAFT_AUTH }} @@ -54,10 +61,9 @@ jobs: - unit-tests-with-coverage - integration-test if: ${{ (github.ref_name != 'main') && (github.event_name == 'push') }} - uses: canonical/sdcore-github-workflows/.github/workflows/publish-charm.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/publish-charm.yaml@v1.0.0 with: branch-name: ${{ github.ref_name }} - charm-file-name: "sdcore-pcf-k8s_ubuntu-22.04-amd64.charm" track-name: 1.5 secrets: CHARMCRAFT_AUTH: ${{ secrets.CHARMCRAFT_AUTH }} \ No newline at end of file diff --git a/.github/workflows/promote.yaml b/.github/workflows/promote.yaml index 6db6223..d138b3f 100644 --- a/.github/workflows/promote.yaml +++ b/.github/workflows/promote.yaml @@ -22,7 +22,7 @@ on: jobs: promote: name: Promote Charm - uses: canonical/sdcore-github-workflows/.github/workflows/promote.yaml@v0.0.1 + uses: canonical/sdcore-github-workflows/.github/workflows/promote.yaml@v1.0.0 with: promotion: ${{ github.event.inputs.promotion }} track-name: ${{ github.event.inputs.track-name }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6adc8d4..7548a22 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,10 +45,14 @@ There are some pre-configured environments that can be used for linting and formatting code when you're preparing contributions to the charm: ```shell -tox -e lint # code style -tox -e static # static analysis -tox -e unit # unit tests -tox -e integration # integration tests +tox -e lint # code style +tox -e static # static analysis +tox -e unit # unit tests +tox -e integration -- --charm_path=PATH_TO_BUILD_CHARM # integration tests +``` + +```note +Integration tests require the charm to be built with `charmcraft pack` first. ``` ## Build diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..f5543e3 --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# Copyright 2024 Canonical Ltd. +# See LICENSE file for licensing details. + +import os + +import pytest + + +def pytest_addoption(parser: pytest.Parser) -> None: + """Add options to the pytest command line. + + This is a pytest hook that is called when the pytest command line is being parsed. + + Args: + parser: The pytest command line parser. + """ + parser.addoption( + "--charm_path", + action="store", + default=None, + help="Path to the charm under test" + ) + + +def pytest_configure(config: pytest.Config) -> None: + """Validate the options provided by the user. + + This is a pytest hook that is called after command line options have been parsed. + + Args: + config: The pytest configuration object. + """ + charm_path = str(config.getoption("--charm_path")) + if not charm_path: + pytest.exit("The --charm_path option is required. Tests aborted.") + if not os.path.exists(charm_path): + pytest.exit(f"The path specified for the charm under test does not exist: {charm_path}") diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index a037a92..47ec86f 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -66,9 +66,9 @@ async def _deploy_grafana_agent(ops_test: OpsTest): @pytest.fixture(scope="module") @pytest.mark.abort_on_fail -async def build_and_deploy(ops_test: OpsTest): - """Build the charm-under-test and deploy it.""" - charm = await ops_test.build_charm(".") +async def deploy(ops_test: OpsTest, request): + """Deploy necessary components.""" + charm = Path(request.config.getoption("--charm_path")).resolve() resources = { "pcf-image": METADATA["resources"]["pcf-image"]["upstream-source"], } @@ -86,7 +86,7 @@ async def build_and_deploy(ops_test: OpsTest): @pytest.mark.abort_on_fail async def test_given_charm_is_built_when_deployed_then_status_is_blocked( - ops_test: OpsTest, build_and_deploy + ops_test: OpsTest, deploy ): await ops_test.model.wait_for_idle( # type: ignore[union-attr] apps=[APPLICATION_NAME], @@ -96,7 +96,7 @@ async def test_given_charm_is_built_when_deployed_then_status_is_blocked( @pytest.mark.abort_on_fail -async def test_relate_and_wait_for_active_status(ops_test: OpsTest, build_and_deploy): +async def test_relate_and_wait_for_active_status(ops_test: OpsTest, deploy): assert ops_test.model await ops_test.model.integrate(relation1=NRF_APP_NAME, relation2=DATABASE_APP_NAME) await ops_test.model.integrate(relation1=NRF_APP_NAME, relation2=TLS_PROVIDER_NAME) @@ -117,13 +117,13 @@ async def test_relate_and_wait_for_active_status(ops_test: OpsTest, build_and_de @pytest.mark.abort_on_fail -async def test_remove_nrf_and_wait_for_blocked_status(ops_test: OpsTest, build_and_deploy): +async def test_remove_nrf_and_wait_for_blocked_status(ops_test: OpsTest, deploy): await ops_test.model.remove_application(NRF_APP_NAME, block_until_done=True) # type: ignore[union-attr] # noqa: E501 await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="blocked", timeout=60) # type: ignore[union-attr] # noqa: E501 @pytest.mark.abort_on_fail -async def test_restore_nrf_and_wait_for_active_status(ops_test: OpsTest, build_and_deploy): +async def test_restore_nrf_and_wait_for_active_status(ops_test: OpsTest, deploy): assert ops_test.model await _deploy_nrf(ops_test) await ops_test.model.integrate( @@ -135,14 +135,14 @@ async def test_restore_nrf_and_wait_for_active_status(ops_test: OpsTest, build_a @pytest.mark.abort_on_fail -async def test_remove_tls_and_wait_for_blocked_status(ops_test: OpsTest, build_and_deploy): +async def test_remove_tls_and_wait_for_blocked_status(ops_test: OpsTest, deploy): assert ops_test.model await ops_test.model.remove_application(TLS_PROVIDER_NAME, block_until_done=True) await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="blocked", timeout=60) @pytest.mark.abort_on_fail -async def test_restore_tls_and_wait_for_active_status(ops_test: OpsTest, build_and_deploy): +async def test_restore_tls_and_wait_for_active_status(ops_test: OpsTest, deploy): assert ops_test.model await _deploy_tls_provider(ops_test) await ops_test.model.integrate(relation1=APPLICATION_NAME, relation2=TLS_PROVIDER_NAME) @@ -153,7 +153,7 @@ async def test_restore_tls_and_wait_for_active_status(ops_test: OpsTest, build_a reason="Bug in MongoDB: https://github.com/canonical/mongodb-k8s-operator/issues/218" ) @pytest.mark.abort_on_fail -async def test_remove_database_and_wait_for_blocked_status(ops_test: OpsTest, build_and_deploy): +async def test_remove_database_and_wait_for_blocked_status(ops_test: OpsTest, deploy): assert ops_test.model await ops_test.model.remove_application(DATABASE_APP_NAME, block_until_done=True) await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="blocked", timeout=60) @@ -163,7 +163,7 @@ async def test_remove_database_and_wait_for_blocked_status(ops_test: OpsTest, bu reason="Bug in MongoDB: https://github.com/canonical/mongodb-k8s-operator/issues/218" ) @pytest.mark.abort_on_fail -async def test_restore_database_and_wait_for_active_status(ops_test: OpsTest, build_and_deploy): +async def test_restore_database_and_wait_for_active_status(ops_test: OpsTest, deploy): assert ops_test.model await _deploy_database(ops_test) await ops_test.model.integrate(relation1=APPLICATION_NAME, relation2=DATABASE_APP_NAME)