Skip to content
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
11 changes: 7 additions & 4 deletions .github/workflows/docs_spread.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ on:

jobs:
tutorial-spread-test:
uses: canonical/operator-workflows/.github/workflows/docs_spread.yaml@main
uses: canonical/charm-ci/.github/workflows/integration-test.yml@main
secrets: inherit
permissions:
contents: read
packages: write
actions: read
with:
input-file: docs/tutorial.md
output-dir: tests/spread/tutorial/
spread-job: github-ci:ubuntu-24.04-64:tests/spread/tutorial
working-directory: .
spread-jobs-include: "*tests/spread/tutorial*"
44 changes: 23 additions & 21 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,31 @@ on:
- cron: "0 15 * * SAT"

jobs:
integration-tests:
strategy:
fail-fast: false
matrix:
base:
- "20.04"
- "22.04"
- "24.04"
Comment thread
florentianayuwono marked this conversation as resolved.
Resolved
uses: canonical/operator-workflows/.github/workflows/integration_test.yaml@main
integration-test:
uses: canonical/charm-ci/.github/workflows/integration-test.yml@main
secrets: inherit
permissions:
contents: read
packages: write
actions: read
with:
trivy-fs-enabled: true
trivy-image-config: "trivy.yaml"
self-hosted-runner: true
self-hosted-runner-label: "edge"
juju-channel: "3/stable"
provider: "lxd"
extra-arguments: "--base ${{ matrix.base }}"
with-uv: true
allure-report:
if: ${{ !cancelled() && github.event_name == 'schedule' }}
working-directory: .
spread-jobs-include: "*tests/integration*"
build-timeout-minutes: 120
required_status_checks:
name: Required Integration Test Status Checks
runs-on: ubuntu-latest
needs:
- integration-tests
uses: canonical/operator-workflows/.github/workflows/allure_report.yaml@main
- integration-test
if: always() && !cancelled()
timeout-minutes: 5
steps:
- name: Check integration-test status
run: |
RESULT="${{ needs.integration-test.result }}"
if [ "$RESULT" = "success" ] || [ "$RESULT" = "skipped" ]; then
exit 0
else
echo "integration-test failed with status: $RESULT"
exit 1
fi
6 changes: 3 additions & 3 deletions .github/workflows/publish_charm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ on:

jobs:
publish-to-edge:
uses: canonical/operator-workflows/.github/workflows/publish_charm.yaml@main
uses: canonical/charm-ci/.github/workflows/publish-artifacts.yml@main
permissions:
actions: read
contents: write
actions: read
secrets: inherit
with:
channel: latest/edge
integration-test-workflow-file: integration_test.yaml
integration-workflow-name: integration_test.yaml
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
venv/
build/
*.charm
artifacts.build.yaml
.tox/
.coverage
__pycache__/
Expand Down
16 changes: 16 additions & 0 deletions artifacts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2026 Canonical Ltd.
# See LICENSE file for licensing details.

version: 1
charms:
- name: aproxy
charmcraft-yaml: charmcraft.yaml
platforms:
- arch: amd64
runner: [ubuntu-24.04]
- arch: arm64
runner: [ubuntu-24.04-arm]
- arch: ppc64el
runner: [self-hosted-linux-ppc64el-noble-edge]
- arch: s390x
runner: [self-hosted-linux-s390x-noble-medium]
9 changes: 9 additions & 0 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ description: |

platforms:
ubuntu@20.04:amd64:
ubuntu@20.04:arm64:
ubuntu@20.04:ppc64el:
ubuntu@20.04:s390x:
ubuntu@22.04:amd64:
ubuntu@22.04:arm64:
ubuntu@22.04:ppc64el:
ubuntu@22.04:s390x:
ubuntu@24.04:amd64:
ubuntu@24.04:arm64:
ubuntu@24.04:ppc64el:
ubuntu@24.04:s390x:

requires:
juju-info:
Expand Down
14 changes: 14 additions & 0 deletions concierge.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2026 Canonical Ltd.
# See LICENSE file for licensing details.

juju:
channel: 3.6/stable
model-defaults:
test-mode: "true"
automatically-retry-hooks: "false"

providers:
lxd:
enable: true
bootstrap: true

2 changes: 1 addition & 1 deletion docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,4 @@ multipass delete --purge my-juju-vm

## Next steps

Visit the [aproxy charm documentation](https://charmhub.io/aproxy/docs) for advanced usage and configuration options.
Visit the [aproxy charm documentation](https://charmhub.io/aproxy/docs) for more advanced usage and configuration options.
9 changes: 1 addition & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ lint = [
"ops[testing]",
"pep8-naming",
"pytest",
"pytest-asyncio",
"pytest-operator",
"requests",
"ruff",
"types-pyyaml",
Expand All @@ -54,14 +52,9 @@ static = [
"bandit[toml]",
]
integration = [
"allure-pytest>=2.8.18",
"allure-pytest-collection-report @ git+https://github.com/canonical/data-platform-workflows@v24.0.0#subdirectory=python/pytest_plugins/allure_pytest_collection_report",
"coverage[toml]",
"jubilant",
"juju==3.6.*",
"ops[testing]",
"opcli @ git+https://github.com/canonical/charm-ci.git ; python_full_version >= '3.12'",
"pytest",
"pytest-asyncio",
]

[tool.uv]
Expand Down
105 changes: 59 additions & 46 deletions spread.yaml
Original file line number Diff line number Diff line change
@@ -1,62 +1,75 @@
# Copyright 2026 Canonical Ltd.
# See LICENSE file for licensing details.

project: aproxy-operator
project: aproxy

path: /aproxy-operator
environment:
PROJECT_PATH: /aproxy-operator
path: /home/ubuntu/proj

kill-timeout: 60m
warn-timeout: 1m

# important to ensure adhoc and linode/qemu behave the same
SUDO_USER: ""
SUDO_UID: ""
backends:
integration-test:
type: integration-test
systems:
- ubuntu-24.04:
runner: [ubuntu-24.04]
arch: amd64
cpu: 4
memory: 8
disk: 40
- ubuntu-24.04-arm64:
runner: [ubuntu-24.04-arm]
arch: arm64
cpu: 4
memory: 8
disk: 40
- ubuntu-24.04-ppc64el:
runner: [self-hosted-linux-ppc64el-noble-edge]
arch: ppc64el
cpu: 4
memory: 8
disk: 40
- ubuntu-24.04-s390x:
runner: [self-hosted-linux-s390x-noble-medium]
arch: s390x
cpu: 4
memory: 8
disk: 40

LANG: "C.UTF-8"
LANGUAGE: "en"
environment:
CONCIERGE: '$(HOST: echo "${CONCIERGE:-concierge.yaml}")'
OPCLI_GIT_REF: '$(HOST: echo "${OPCLI_GIT_REF:-main}")'

exclude:
- .git
- .github
- .tox
- .venv
- .*_cache
- charmcraft
- libexec
- schema
- snap

backends:
github-ci:
type: adhoc
allocate: |
echo "Allocating ad-hoc $SPREAD_SYSTEM"
if [ -z "${GITHUB_RUN_ID:-}" ]; then
FATAL "this back-end only works inside GitHub CI"
exit 1
fi
echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/99-spread-users
ADDRESS localhost:22
discard: |
echo "Discarding ad-hoc $SPREAD_SYSTEM"
systems:
- ubuntu-24.04-64:
username: ubuntu
password: ubuntu
workers: 1

prepare: |
snap refresh --hold

if systemctl is-enabled unattended-upgrades.service; then
systemctl stop unattended-upgrades.service
systemctl mask unattended-upgrades.service
fi

sudo snap install --classic concierge
sudo concierge prepare -p machine

integration-suites:
tests/integration/:
working-dir: ./
summary: aproxy integration tests
auto-discover: false
backends:
- integration-test
environment:
MODULE/focal: tests/integration/test_charm.py
MODULE/jammy: tests/integration/test_charm.py
MODULE/noble: tests/integration/test_charm.py
BASE/focal: "20.04"
BASE/jammy: "22.04"
BASE/noble: "24.04"
pytest-arguments-template: |
--model testing
--keep-models
--base {{ env.get("BASE", "24.04") }}
suites:
tests/spread/:
summary: tutorial test
tests/spread/tutorial/:
summary: aproxy tutorial smoke test
systems:
- ubuntu-24.04-64
- ubuntu-24.04
environment:
TUTORIAL: docs/tutorial.md
6 changes: 0 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ def pytest_addoption(parser):
Args:
parser: The pytest command-line parser.
"""
parser.addoption(
"--charm-file",
action="append",
default=[],
help="Path(s) to built charm file(s) to use in tests",
)
parser.addoption(
"--model",
action="store",
Expand Down
46 changes: 10 additions & 36 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
# pylint: disable=unused-argument
"""Fixtures for charm tests."""

import pathlib
import subprocess # nosec B404
import typing

import jubilant
Expand All @@ -15,46 +13,22 @@


@pytest.fixture(name="aproxy_charm_file", scope="session")
def aproxy_charm_file_fixture(pytestconfig: pytest.Config) -> str:
"""Build or get the aproxy charm file.
def aproxy_charm_file_fixture(charm_paths: dict, pytestconfig: pytest.Config) -> str:
"""Return the path to the built aproxy charm for the requested base.

The ``charm_paths`` fixture is provided by the opcli (canonical/charm-ci)
pytest plugin and resolves builds from ``artifacts.build.yaml`` for the
current architecture.

Args:
charm_paths: Mapping of charm name to its per-base build paths.
pytestconfig: Pytest configuration object.

Returns:
Path to the built or provided aproxy charm file.
Path to the built aproxy charm file for the requested base.
"""
charms = pytestconfig.getoption("--charm-file")
base = pytestconfig.getoption("--base")

if charms:
# Filter by requested base
matching_charms = [file for file in charms if base in file]
if matching_charms:
return matching_charms[0]
raise AssertionError(f"No matching charm found for base {base}.")

# Otherwise, build the charm for the requested base
base_index_map = {"20.04": 0, "22.04": 1, "24.04": 2}
bases_index = base_index_map.get(base, 2)

try:
subprocess.run( # nosec B603
["/usr/bin/charmcraft", "pack", f"--bases-index={bases_index}"],
check=True,
capture_output=True,
text=True,
)
except subprocess.CalledProcessError as exc:
raise OSError(f"Error packing charm: {exc}; Stderr:\n{exc.stderr}") from None

charm_path = pathlib.Path(__file__).parent.parent.parent
charms = [p.absolute() for p in charm_path.glob("aproxy_*.charm")]
# Filter for the requested base
matching_charms = [c for c in charms if base in str(c)]
if matching_charms:
return str(matching_charms[0])
raise AssertionError(f"No matching charm found for base {base}.")
return str(charm_paths["aproxy"][f"ubuntu@{base}"])


@pytest.fixture(name="juju", scope="module")
Expand Down Expand Up @@ -103,7 +77,7 @@ def deploy_charms_fixture(
pytestconfig: Pytest configuration object.
"""
base = pytestconfig.getoption("--base", default="24.04")
juju.deploy("ubuntu", base=f"ubuntu@{base}", constraints={"virt-type": "virtual-machine"})
juju.deploy("ubuntu", base=f"ubuntu@{base}")
Comment thread
florentianayuwono marked this conversation as resolved.
Resolved
juju.deploy(aproxy_charm_file)
juju.integrate("ubuntu", "aproxy")
juju.cli("config", "aproxy", f"proxy-address={tinyproxy_url}:8888")
Expand Down
1 change: 0 additions & 1 deletion tests/integration/tinyproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def _on_install(self, _):
channel="latest/edge",
base=anycharm_base,
config={"src-overwrite": json.dumps({"any_charm.py": any_charm_py})},
constraints={"virt-type": "virtual-machine"},
)

# Wait until the service is up
Expand Down
Loading
Loading