diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c6b88a70d..ffe1cbcee 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -59,7 +59,6 @@ jobs: name: Integration test charm needs: - lint - - unit-test - build uses: ./.github/workflows/integration_test.yaml with: diff --git a/.github/workflows/integration_test.yaml b/.github/workflows/integration_test.yaml index b7d035f37..9b668a63a 100644 --- a/.github/workflows/integration_test.yaml +++ b/.github/workflows/integration_test.yaml @@ -42,7 +42,9 @@ jobs: _, runner, task, variant = job.split(":") # Example: "test_charm.py" task = task.removeprefix("tests/spread/") - if runner.endswith("-arm"): + if "s390x" in runner: + architecture = "s390x" + elif runner.endswith("-arm"): architecture = "arm64" else: architecture = "amd64" @@ -86,8 +88,9 @@ jobs: runs-on: ${{ matrix.job.runner }} timeout-minutes: 217 # Sum of steps `timeout-minutes` + 5 steps: - - name: Free up disk space + - name: (GitHub hosted) Free up disk space timeout-minutes: 1 + if: ${{ !contains(matrix.job.runner, 'self-hosted') }} run: | printf '\nDisk usage before cleanup\n' df --human-readable @@ -95,6 +98,10 @@ jobs: rm -r /opt/hostedtoolcache/ printf '\nDisk usage after cleanup\n' df --human-readable + - name: (IS hosted) Disk usage + timeout-minutes: 1 + if: ${{ contains(matrix.job.runner, 'self-hosted') }} + run: df --human-readable - name: Checkout timeout-minutes: 3 uses: actions/checkout@v4 diff --git a/concierge.yaml b/concierge.yaml index 361973cb8..95ee838d4 100644 --- a/concierge.yaml +++ b/concierge.yaml @@ -4,7 +4,7 @@ juju: providers: microk8s: enable: true - bootstrap: true + bootstrap: false addons: - dns - hostpath-storage diff --git a/spread.yaml b/spread.yaml index 7cd6e1a52..ac72e8599 100644 --- a/spread.yaml +++ b/spread.yaml @@ -86,6 +86,7 @@ backends: # Manually pass specific environment variables environment: CI: '$(HOST: echo $CI)' + DOCKERHUB_MIRROR: '$(HOST: echo $DOCKERHUB_MIRROR)' systems: - ubuntu-24.04: username: runner @@ -93,6 +94,21 @@ backends: username: runner variants: - -juju29 + - self-hosted-linux-s390x-noble-edge: + username: ubuntu + environment: + # Several python packages (e.g. cryptography, bcrypt) do not have s390x builds on PyPI, + # so they must be built from source. pkg-config & rust toolchain needed + # (These packages are being built when installing poetry or integration test Python + # dependencies) + CONCIERGE_EXTRA_DEBS: pipx,pkg-config,rustup + # s390x only available on edge risk of microk8s snap + # IS-hosted GitHub runners do not work with the strictly confined microk8s snap: + # https://github.com/canonical/microk8s/issues/5082 + # https://chat.canonical.com/canonical/pl/i6yydsx5ifrepp56khq5fq5dke + CONCIERGE_MICROK8S_CHANNEL: latest/edge + variants: + - -juju29 suites: tests/spread/: @@ -109,10 +125,42 @@ prepare: | snap refresh --hold chown -R root:root "$SPREAD_PATH" cd "$SPREAD_PATH" - snap install --classic concierge + # Install via snap after https://github.com/canonical/concierge/pull/81 released + go install github.com/canonical/concierge@latest + + if [[ -n "$DOCKERHUB_MIRROR" ]] + then + # Running on IS-hosted runner; configure microk8s to use Docker Hub mirror + # Run before concierge prepare because of https://github.com/canonical/concierge/issues/75 + + snap install microk8s --channel "$CONCIERGE_MICROK8S_CHANNEL" --classic + + # Wait for microk8s to populate iptables + # https://chat.canonical.com/canonical/pl/jo5cg6wqjjrudqd5ybj6hhttee + microk8s status --wait-ready + + tee /var/snap/microk8s/current/args/certs.d/docker.io/hosts.toml << EOF + server = "$DOCKERHUB_MIRROR" + [host."${DOCKERHUB_MIRROR#'https://'}"] + capabilities = ["pull", "resolve"] + EOF + microk8s stop + microk8s start + fi + + # Install charmcraft & pipx on lxd-vm backend and install pipx on IS-hosted runners + ~/go/bin/concierge prepare --trace + + microk8s config | juju add-k8s my-k8s --client + juju bootstrap my-k8s concierge-microk8s + juju add-model testing - # Install charmcraft & pipx (on lxd-vm backend) - concierge prepare --trace + if [[ $SPREAD_SYSTEM == *"s390x"* ]] + then + rustup set profile minimal + # TODO add renovate comment for rust version + rustup default 1.88.0 + fi pipx install tox poetry prepare-each: | @@ -124,7 +172,7 @@ prepare-each: | poetry add --lock --group integration juju@^2 fi # `concierge prepare` needs to be run for each spread job in case Juju version changed - concierge prepare --trace + ~/go/bin/concierge prepare --trace # Unable to set constraint on all models because of Juju bug: # https://bugs.launchpad.net/juju/+bug/2065050 diff --git a/tests/integration/markers.py b/tests/integration/markers.py index 46d84271d..d38ea4a4c 100644 --- a/tests/integration/markers.py +++ b/tests/integration/markers.py @@ -15,3 +15,6 @@ arm64_only = pytest.mark.skipif( architecture.architecture != "arm64", reason="Requires arm64 architecture" ) +s390x_only = pytest.mark.skipif( + architecture.architecture != "s390x", reason="Requires s390x architecture" +) diff --git a/tests/integration/test_architecture.py b/tests/integration/test_architecture.py index b7044c8c5..b8dd06f70 100644 --- a/tests/integration/test_architecture.py +++ b/tests/integration/test_architecture.py @@ -61,4 +61,25 @@ async def test_amd_charm_on_arm_host(ops_test: OpsTest) -> None: ) -# TODO: add s390x test +@markers.s390x_only +async def test_amd_charm_on_s390x_host(ops_test: OpsTest) -> None: + """Tries deploying an amd64 charm on s390x host.""" + charm = "./mysql-router-k8s_ubuntu@22.04-amd64.charm" + + resources = { + "mysql-router-image": METADATA["resources"]["mysql-router-image"]["upstream-source"] + } + + await ops_test.model.deploy( + charm, + application_name=MYSQL_ROUTER_APP_NAME, + num_units=1, + resources=resources, + base="ubuntu@22.04", + ) + + await ops_test.model.wait_for_idle( + apps=[MYSQL_ROUTER_APP_NAME], + status="error", + raise_on_error=False, + ) diff --git a/tests/integration/test_exporter_with_tls.py b/tests/integration/test_exporter_with_tls.py index b872bb8c1..bbc7601e1 100644 --- a/tests/integration/test_exporter_with_tls.py +++ b/tests/integration/test_exporter_with_tls.py @@ -34,8 +34,8 @@ if juju_.is_3_or_higher: tls_app_name = "self-signed-certificates" - if architecture.architecture == "arm64": - tls_channel = "latest/edge" + if architecture.architecture == "s390x": + tls_channel = "1/edge" else: tls_channel = "latest/stable" tls_config = {"ca-common-name": "Test CA"} @@ -138,7 +138,6 @@ async def test_exporter_endpoint(ops_test: OpsTest, charm) -> None: application_name=tls_app_name, channel=tls_channel, config=tls_config, - base="ubuntu@22.04", ) await ops_test.model.wait_for_idle([tls_app_name], status="active", timeout=SLOW_TIMEOUT) diff --git a/tests/integration/test_expose_external.py b/tests/integration/test_expose_external.py index 92f1348cc..32b2f93c4 100644 --- a/tests/integration/test_expose_external.py +++ b/tests/integration/test_expose_external.py @@ -36,8 +36,8 @@ TLS_SETUP_SLEEP_TIME = 30 if juju_.is_3_or_higher: TLS_APP_NAME = "self-signed-certificates" - if architecture.architecture == "arm64": - TLS_CHANNEL = "latest/edge" + if architecture.architecture == "s390x": + TLS_CHANNEL = "1/edge" else: TLS_CHANNEL = "latest/stable" TLS_CONFIG = {"ca-common-name": "Test CA"} @@ -197,7 +197,6 @@ async def test_expose_external_with_tls(ops_test: OpsTest) -> None: TLS_APP_NAME, channel=TLS_CHANNEL, config=TLS_CONFIG, - base="ubuntu@22.04", ) async with ops_test.fast_forward("60s"): await ops_test.model.wait_for_idle( diff --git a/tests/integration/test_tls.py b/tests/integration/test_tls.py index 00fb17f95..e21a434ba 100644 --- a/tests/integration/test_tls.py +++ b/tests/integration/test_tls.py @@ -30,8 +30,8 @@ if juju_.is_3_or_higher: tls_app_name = "self-signed-certificates" - if architecture.architecture == "arm64": - tls_channel = "latest/edge" + if architecture.architecture == "s390x": + tls_channel = "1/edge" else: tls_channel = "latest/stable" tls_config = {"ca-common-name": "Test CA"} @@ -79,7 +79,6 @@ async def test_deploy_and_relate(ops_test: OpsTest, charm) -> None: application_name=tls_app_name, channel=tls_channel, config=tls_config, - base="ubuntu@22.04", ), ops_test.model.deploy( TEST_APP_NAME, diff --git a/tests/spread/test_architecture.py/task.yaml b/tests/spread/test_architecture.py/task.yaml deleted file mode 100644 index cad863364..000000000 --- a/tests/spread/test_architecture.py/task.yaml +++ /dev/null @@ -1,9 +0,0 @@ -summary: test_architecture.py -environment: - TEST_MODULE: test_architecture.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results -backends: - - -lxd-vm # This task requires charm built on different architecture from host diff --git a/tests/spread/test_charm.py/task.yaml b/tests/spread/test_charm.py/task.yaml deleted file mode 100644 index 96450bdc3..000000000 --- a/tests/spread/test_charm.py/task.yaml +++ /dev/null @@ -1,7 +0,0 @@ -summary: test_charm.py -environment: - TEST_MODULE: test_charm.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results diff --git a/tests/spread/test_exporter.py/task.yaml b/tests/spread/test_exporter.py/task.yaml deleted file mode 100644 index 800f0c4a2..000000000 --- a/tests/spread/test_exporter.py/task.yaml +++ /dev/null @@ -1,9 +0,0 @@ -summary: test_exporter.py -environment: - TEST_MODULE: test_exporter.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results -systems: - - -ubuntu-24.04-arm diff --git a/tests/spread/test_exporter_with_tls.py/task.yaml b/tests/spread/test_exporter_with_tls.py/task.yaml deleted file mode 100644 index 4d7dce7fc..000000000 --- a/tests/spread/test_exporter_with_tls.py/task.yaml +++ /dev/null @@ -1,9 +0,0 @@ -summary: test_exporter_with_tls.py -environment: - TEST_MODULE: test_exporter_with_tls.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results -systems: - - -ubuntu-24.04-arm diff --git a/tests/spread/test_log_rotation.py/task.yaml b/tests/spread/test_log_rotation.py/task.yaml deleted file mode 100644 index 8e8900110..000000000 --- a/tests/spread/test_log_rotation.py/task.yaml +++ /dev/null @@ -1,7 +0,0 @@ -summary: test_log_rotation.py -environment: - TEST_MODULE: test_log_rotation.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results diff --git a/tests/spread/test_upgrade.py/task.yaml b/tests/spread/test_upgrade.py/task.yaml deleted file mode 100644 index a53e8a4ee..000000000 --- a/tests/spread/test_upgrade.py/task.yaml +++ /dev/null @@ -1,7 +0,0 @@ -summary: test_upgrade.py -environment: - TEST_MODULE: test_upgrade.py -execute: | - tox run -e integration -- "tests/integration/$TEST_MODULE" --model testing --alluredir="$SPREAD_TASK/allure-results" -artifacts: - - allure-results