Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci, tests: pass charm artefacts to deploy and test charms #640

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/workflows/integrate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,23 @@ jobs:
# Pinned to 3.x/stable due to https://github.com/canonical/charmcraft/issues/1845
charmcraft-channel: 3.x/stable

- name: Download packed charm(s)
id: download-charms
timeout-minutes: 5
uses: actions/download-artifact@v4
with:
pattern: packed-charm-cache-true-.-charms-${{ matrix.charm }}-*
merge-multiple: true

- name: Integration tests
run: |
# Requires the model to be called kubeflow due to
# https://github.com/canonical/kfp-operators/issues/389
juju add-model kubeflow
sg snap_microk8s -c "tox -e ${{ matrix.charm }}-integration -- --model kubeflow"
# Pass the path where the charm artefact is downloaded to the tox command
# FIXME: Right now the complete path is half hardcoded to <charm name>_ubuntu-20.04-amd64.charm
# We need to find a better way to dynamically get this value
sg snap_microk8s -c "tox -e ${{ matrix.charm }}-integration -- --model kubeflow --charm-path=${{ github.workspace }}/charms/${{ matrix.charm }}/${{ matrix.charm }}_ubuntu-20.04-amd64.charm"

- name: Collect charm debug artifacts
uses: canonical/kubeflow-ci/actions/dump-charm-debug-artifacts@main
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-api/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
13 changes: 9 additions & 4 deletions charms/kfp-api/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,21 @@ class TestCharm:
"""Integration test charm"""

@pytest.mark.abort_on_fail
async def test_build_and_deploy(self, ops_test: OpsTest):
async def test_build_and_deploy(self, ops_test: OpsTest, request):
"""Deploy kfp-api with required charms and relations."""
built_charm_path = await ops_test.build_charm("./")
logger.info(f"Built charm {built_charm_path}")

image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path,
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-metadata-writer/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
18 changes: 13 additions & 5 deletions charms/kfp-metadata-writer/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,24 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy_with_relations(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm(CHARM_ROOT)
log.info(f"Built charm {built_charm_path}")

async def test_build_and_deploy_with_relations(ops_test: OpsTest, request):
image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path, application_name=APP_NAME, resources=resources, trust=True
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
)

await ops_test.model.deploy(entity_url=MLMD, channel=MLMD_CHANNEL, trust=True)
await ops_test.model.integrate(f"{MLMD}:grpc", f"{APP_NAME}:grpc")
await ops_test.model.wait_for_idle(apps=[APP_NAME, MLMD], status="active", timeout=10 * 60)
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-persistence/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
14 changes: 9 additions & 5 deletions charms/kfp-persistence/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,20 @@ class TestCharm:
"""Integration test charm"""

@pytest.mark.abort_on_fail
async def test_build_and_deploy(self, ops_test: OpsTest):
async def test_build_and_deploy(self, ops_test: OpsTest, request):
"""Deploy kfp-persistence with required charms and relations."""
built_charm_path = await ops_test.build_charm("./")
logger.info(f"Built charm {built_charm_path}")

image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path,
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-profile-controller/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
24 changes: 16 additions & 8 deletions charms/kfp-profile-controller/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,14 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm("./")
logger.info(f"Built charm {built_charm_path}")

image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}

async def test_build_and_deploy(ops_test: OpsTest, request):
# Deploy the admission webhook to apply the PodDefault CRD required by the charm workload
await ops_test.model.deploy(
entity_url=ADMISSION_WEBHOOK,
channel=ADMISSION_WEBHOOK_CHANNEL,
trust=ADMISSION_WEBHOOK_TRUST,
)

# TODO: The webhook charm must be active before the metacontroller is deployed, due to the bug
# described here: https://github.com/canonical/metacontroller-operator/issues/86
# Drop this wait_for_idle once the above issue is closed
Expand All @@ -72,8 +67,21 @@ async def test_build_and_deploy(ops_test: OpsTest):
trust=METACONTROLLER_TRUST,
)

# Deploy the charm under test
image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
built_charm_path, application_name=CHARM_NAME, resources=resources, trust=True
entity_url=entity_url,
resources=resources,
trust=True,
)

# Deploy required relations
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-schedwf/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
17 changes: 12 additions & 5 deletions charms/kfp-schedwf/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,22 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy_with_relations(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm(CHARM_ROOT)
log.info(f"Built charm {built_charm_path}")

async def test_build_and_deploy_with_relations(ops_test: OpsTest, request):
image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path, application_name=APP_NAME, resources=resources, trust=True
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
)

await ops_test.model.wait_for_idle(
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-ui/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
18 changes: 13 additions & 5 deletions charms/kfp-ui/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,24 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy_with_relations(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm(CHARM_ROOT)
log.info(f"Built charm {built_charm_path}")

async def test_build_and_deploy_with_relations(ops_test: OpsTest, request):
image_path = METADATA["resources"]["ml-pipeline-ui"]["upstream-source"]
resources = {"ml-pipeline-ui": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path, application_name=APP_NAME, resources=resources, trust=True
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
)

await ops_test.model.deploy(BUNDLE, trust=True)
await ops_test.model.integrate(f"{APP_NAME}:kfp-api", "kfp-api:kfp-api")
await ops_test.model.integrate(f"{APP_NAME}:object-storage", "minio:object-storage")
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-viewer/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
18 changes: 13 additions & 5 deletions charms/kfp-viewer/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,24 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy_with_relations(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm(CHARM_ROOT)
log.info(f"Built charm {built_charm_path}")

async def test_build_and_deploy_with_relations(ops_test: OpsTest, request):
image_path = METADATA["resources"]["kfp-viewer-image"]["upstream-source"]
resources = {"kfp-viewer-image": image_path}
# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)

await ops_test.model.deploy(
entity_url=built_charm_path, application_name=APP_NAME, resources=resources, trust=True
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
)

await ops_test.model.wait_for_idle(
apps=[APP_NAME],
status="active",
Expand Down
12 changes: 12 additions & 0 deletions charms/kfp-viz/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env python3
# Copyright 2025 Canonical Ltd.
# See LICENSE file for licensing details.

from _pytest.config.argparsing import Parser


def pytest_addoption(parser: Parser):
parser.addoption(
"--charm-path",
help="Path to charm file for performing tests on.",
)
19 changes: 13 additions & 6 deletions charms/kfp-viz/tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,23 @@


@pytest.mark.abort_on_fail
async def test_build_and_deploy_with_relations(ops_test: OpsTest):
built_charm_path = await ops_test.build_charm(CHARM_ROOT)
log.info(f"Built charm {built_charm_path}")

async def test_build_and_deploy_with_relations(ops_test: OpsTest, request):
image_path = METADATA["resources"]["oci-image"]["upstream-source"]
resources = {"oci-image": image_path}

# Keep the option to run the integration tests locally
# by building the charm and then deploying
entity_url = (
await ops_test.build_charm("./")
if not (entity_url := request.config.getoption("--charm-path"))
else entity_url
)
await ops_test.model.deploy(
entity_url=built_charm_path, application_name=APP_NAME, resources=resources, trust=True
entity_url=entity_url,
application_name=APP_NAME,
resources=resources,
trust=True,
)

await ops_test.model.wait_for_idle(
apps=[APP_NAME],
status="active",
Expand Down
Loading