Skip to content
Open
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
34 changes: 30 additions & 4 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ on:
workflow_call:
workflow_dispatch:

permissions:
contents: read

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python 3
uses: actions/setup-python@v5
with:
Expand All @@ -25,6 +30,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python 3
uses: actions/setup-python@v5
with:
Expand All @@ -43,6 +50,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
Expand All @@ -57,6 +66,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python 3
uses: actions/setup-python@v5
with:
Expand All @@ -72,10 +83,25 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup operator environment
uses: charmed-kubernetes/actions-operator@main
with:
provider: lxd
juju-channel: 3.6/stable
persist-credentials: false
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install tox
run: pip install tox~=4.2
- name: Install Concierge
run: sudo snap install --classic concierge
- name: Prepare for deploying machine charms
run: sudo concierge prepare -p machine
- name: Pack test charm
run: |
charm_dir=tests/integration/juju_systemd_notices/notices-charm
cp lib/charms/operator_libs_linux/v1/systemd.py "$charm_dir/lib/charms/operator_libs_linux/v1/"
cp lib/charms/operator_libs_linux/v0/juju_systemd_notices.py "$charm_dir/lib/charms/operator_libs_linux/v0/"
cd "$charm_dir"
charmcraft pack --verbose
echo "CHARM_PATH=$(pwd)/$(ls *.charm)" >> "$GITHUB_ENV"
- name: Run integration tests (juju-systemd-notices)
run: tox run -e integration-juju-systemd-notices
3 changes: 3 additions & 0 deletions .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
uses: ./.github/workflows/build-and-test.yaml
8 changes: 6 additions & 2 deletions .github/workflows/release-libs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ on:
branches:
- main

permissions:
contents: write

jobs:
release-libs:
name: Release any bumped library
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
with:
fetch-depth: 0
persist-credentials: false
- name: Release any bumped charm library
uses: canonical/charming-actions/release-libraries@2.2.3
uses: canonical/charming-actions/release-libraries@f87f8885aeb69e668b50c6c6095af5eadac457d2 # 2.2.3
with:
credentials: "${{ secrets.CHARMHUB_TOKEN }}"
github-token: "${{ secrets.GITHUB_TOKEN }}"
10 changes: 7 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
uses: ./.github/workflows/build-and-test.yaml
Expand All @@ -26,14 +29,15 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
with:
fetch-depth: 0
persist-credentials: false
- name: Select charmhub channel
uses: canonical/charming-actions/channel@2.2.3
uses: canonical/charming-actions/channel@f87f8885aeb69e668b50c6c6095af5eadac457d2 # 2.2.3
id: channel
- name: Upload charm to charmhub
uses: canonical/charming-actions/upload-charm@2.2.3
uses: canonical/charming-actions/upload-charm@f87f8885aeb69e668b50c6c6095af5eadac457d2 # 2.2.3
with:
credentials: "${{ secrets.CHARMHUB_TOKEN }}"
github-token: "${{ secrets.GITHUB_TOKEN }}"
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/zizmor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Workflow static checks

on:
push:
branches: ["main"]
pull_request:
branches: ["**"]

permissions: {}

jobs:
zizmor:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0

- name: Run zizmor
run: uvx zizmor@v1.23.1 --format=sarif . > results.sarif
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
category: zizmor
7 changes: 7 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
rules:
unpinned-uses:
config:
policies:
"actions/*": ref-pin
"github/*": ref-pin
"pypa/*": ref-pin
59 changes: 45 additions & 14 deletions tests/integration/juju_systemd_notices/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,62 @@

"""Configure integration tests for the juju_systemd_notices library."""

import logging
import os
import pathlib
import shutil
from pathlib import Path
import sys
import time

import jubilant
import pytest
from pytest_operator.plugin import OpsTest

test_charm_root = Path("tests/integration/juju_systemd_notices/notices-charm")
lib_root = Path("lib/charms/operator_libs_linux")
logger = logging.getLogger(__name__)

test_charm_root = pathlib.Path("tests/integration/juju_systemd_notices/notices-charm")
lib_root = pathlib.Path("lib/charms/operator_libs_linux")
systemd_path = lib_root / "v1/systemd.py"
notices_path = lib_root / "v0/juju_systemd_notices.py"


@pytest.fixture(scope="module")
def juju(request: pytest.FixtureRequest):
"""Create a temporary Juju model for running tests."""
with jubilant.temp_model() as juju:
yield juju

if request.session.testsfailed:
logger.info("Collecting Juju logs...")
time.sleep(0.5)
log = juju.debug_log(limit=1000)
print(log, end="", file=sys.stderr)


@pytest.fixture(scope="module", autouse=True)
def copy_machine_libs_into_test_charm(ops_test: OpsTest):
def copy_machine_libs_into_test_charm():
"""Copy the systemd and juju_systemd_notices to the test charm."""
shutil.copy(systemd_path, test_charm_root / systemd_path)
shutil.copy(notices_path, test_charm_root / notices_path)


@pytest.fixture(scope="module")
async def test_charm(ops_test: OpsTest):
return await ops_test.build_charm("tests/integration/juju_systemd_notices/notices-charm")


def pytest_sessionfinish(session, exitstatus):
"""Clean up integration test after it has completed."""
yield
(test_charm_root / systemd_path).unlink(missing_ok=True)
(test_charm_root / notices_path).unlink(missing_ok=True)


@pytest.fixture(scope="session")
def test_charm():
"""Return the path of the charm under test."""
if "CHARM_PATH" in os.environ:
charm_path = pathlib.Path(os.environ["CHARM_PATH"])
if not charm_path.exists():
raise FileNotFoundError(f"Charm does not exist: {charm_path}")
return charm_path
charm_paths = list(test_charm_root.glob("*.charm"))
if not charm_paths:
raise FileNotFoundError(
f"No .charm file in {test_charm_root}. "
"Run 'charmcraft pack' first or set CHARM_PATH."
)
if len(charm_paths) > 1:
path_list = ", ".join(str(p) for p in charm_paths)
raise ValueError(f"More than one .charm file in {test_charm_root}: {path_list}")
return charm_paths[0]
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ summary: |
A charm with a minimal daemon for testing the juju-systemd-notices charm library.

type: charm
bases:
- build-on:
- name: ubuntu
channel: "22.04"
run-on:
- name: ubuntu
channel: "22.04"
base: ubuntu@22.04
platforms:
amd64:

parts:
charm:
plugin: charm

actions:
stop-service:
description: Stop internal test service inside charm

35 changes: 12 additions & 23 deletions tests/integration/juju_systemd_notices/test_juju_systemd_notices.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

"""Integration tests for juju_systemd_notices charm library."""

import asyncio
import logging

import jubilant
import pytest
from pytest_operator.plugin import OpsTest

logger = logging.getLogger(__name__)
APP_NAME = "test"
Expand All @@ -17,34 +16,24 @@

@pytest.mark.abort_on_fail
@pytest.mark.order(1)
async def test_service_start(ops_test: OpsTest, test_charm) -> None:
def test_service_start(juju: jubilant.Juju, test_charm) -> None:
"""Test that service_test_started event is properly handled by test charm."""
logger.info("Deploying test charm with internal test daemon")
await asyncio.gather(
ops_test.model.deploy(
str(await test_charm), application_name=APP_NAME, num_units=1, base="ubuntu@22.04"
)
)
juju.deploy(test_charm, app=APP_NAME, num_units=1, base="ubuntu@22.04")
logger.info("Waiting for test daemon to start...")
async with ops_test.fast_forward():
await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000)
assert (
ops_test.model.units.get(UNIT_NAME).workload_status_message
== "test service running :)"
)
status = juju.wait(lambda status: jubilant.all_active(status, APP_NAME), timeout=1000)
unit_status = status.apps[APP_NAME].units[UNIT_NAME]
assert unit_status.workload_status.message == "test service running :)"


@pytest.mark.abort_on_fail
@pytest.mark.order(2)
async def test_service_stop(ops_test: OpsTest) -> None:
def test_service_stop(juju: jubilant.Juju) -> None:
"""Test that service_test_stopped event is properly handled by test charm."""
logger.info("Stopping internal test daemon")
action = await ops_test.model.units.get(UNIT_NAME).run_action("stop-service")
await action.wait()
task = juju.run(UNIT_NAME, "stop-service")
task.raise_on_failure()
logger.info("Waiting for test daemon to stop...")
async with ops_test.fast_forward():
await ops_test.model.wait_for_idle(apps=[APP_NAME], status="blocked", timeout=1000)
assert (
ops_test.model.units.get(UNIT_NAME).workload_status_message
== "test service not running :("
)
status = juju.wait(lambda status: jubilant.all_blocked(status, APP_NAME), timeout=1000)
unit_status = status.apps[APP_NAME].units[UNIT_NAME]
assert unit_status.workload_status.message == "test service not running :("
2 changes: 2 additions & 0 deletions tests/integration/test_apt.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from typing import List
from urllib.request import urlopen

import pytest
from charms.operator_libs_linux.v0 import apt
from helpers import get_command_path

Expand Down Expand Up @@ -137,6 +138,7 @@ def test_install_higher_version_package_from_external_repository():
assert not get_command_path("fish")


@pytest.mark.skip(reason="HPE GPG signing key has expired, causing apt-get update to fail")
def test_install_hardware_observer_ssacli():
"""Test the ability to install a package used by the hardware-observer charm.

Expand Down
7 changes: 4 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,15 @@ commands =
description = Run juju systemd notices integration tests.
deps =
pytest
pytest-operator
pytest-order
juju
jubilant
-r {toxinidir}/requirements.txt
passenv =
CHARM_PATH
commands =
pytest -v \
-s \
--tb native \
--log-cli-level=INFO \
{[vars]tst_dir}integration/juju_systemd_notices
{[vars]tst_dir}integration/juju_systemd_notices \
{posargs}
Loading