Skip to content

Commit

Permalink
Merge pull request #2 from canonical/CSS-3449-cicd-tests
Browse files Browse the repository at this point in the history
CSS-3449: Add CI/CD, unit and integration tests
  • Loading branch information
kelkawi-a authored Apr 4, 2023
2 parents f302ff5 + f911481 commit 7106f1d
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 60 deletions.
31 changes: 0 additions & 31 deletions .github/workflows/ci.yaml

This file was deleted.

27 changes: 27 additions & 0 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Integration tests

on:
pull_request:

jobs:
integration-test-microk8s:
name: Integration tests (microk8s)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup operator environment
uses: charmed-kubernetes/actions-operator@main
with:
juju-channel: 3.1/stable
provider: microk8s
channel: 1.25-strict/stable
- name: Run integration tests
# set a predictable model name so it can be consumed by charm-logdump-action
run: tox -e integration -- --model testing
- name: Dump logs
uses: canonical/charm-logdump-action@main
if: failure()
with:
app: temporal-ui-k8s
model: testing
10 changes: 0 additions & 10 deletions .github/workflows/on_pull_request.yaml

This file was deleted.

14 changes: 0 additions & 14 deletions .github/workflows/on_push.yaml

This file was deleted.

26 changes: 26 additions & 0 deletions .github/workflows/promote_charm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Promote charm

on:
workflow_dispatch:
inputs:
origin-channel:
type: choice
description: 'Origin Channel'
options:
- latest/edge
destination-channel:
type: choice
description: 'Destination Channel'
options:
- latest/stable
secrets:
CHARMHUB_TOKEN:
required: true

jobs:
promote-charm:
uses: canonical/operator-workflows/.github/workflows/promote_charm.yaml@main
with:
origin-channel: ${{ github.event.inputs.origin-channel }}
destination-channel: ${{ github.event.inputs.destination-channel }}
secrets: inherit
9 changes: 9 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: Tests

on:
pull_request:

jobs:
unit-tests:
uses: canonical/operator-workflows/.github/workflows/test.yaml@main
secrets: inherit
23 changes: 23 additions & 0 deletions .github/workflows/test_and_publish_charm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Publish to edge

# On push to a "special" branch, we:
# * always publish to charmhub at latest/edge/branchname
# * always run tests
# where a "special" branch is one of main/master or track/**, as
# by convention these branches are the source for a corresponding
# charmhub edge channel.

on:
push:
branches:
- main
- track/**

jobs:
publish-to-edge:
uses: canonical/operator-workflows/.github/workflows/test_and_publish_charm.yaml@main
secrets: inherit
with:
integration-test-provider: microk8s
integration-test-provider-channel: 1.25-strict/stable
integration-test-juju-channel: 3.1/stable
7 changes: 7 additions & 0 deletions .woke.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ignore_files:
# Ignore ingress charm library as it uses non compliant terminology:
# whitelist.
- lib/charms/nginx_ingress_integrator/v0/ingress.py
rules:
# Ignore "master" - the database relation event received from the library.
- name: master
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[![Charmhub Badge](https://charmhub.io/temporal-ui-k8s/badge.svg)](https://charmhub.io/temporal-ui-k8s)
[![Release Edge](https://github.com/canonical/temporal-ui-k8s-operator/actions/workflows/test_and_publish_charm.yaml/badge.svg)](https://github.com/canonical/temporal-ui-k8s-operator/actions/workflows/test_and_publish_charm.yaml)

# Temporal UI K8s Operator

This is the Kubernetes Python Operator for the
Expand Down
4 changes: 3 additions & 1 deletion metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ description: |
This charm provides the web UI which can be related to the Temporal server
charm to view workflow runs.
maintainer: Commercial Systems <jaas-crew@lists.canonical.com>
maintainers:
- Commercial Systems <jaas-crew@lists.canonical.com>
docs: https://discourse.charmhub.io/t/temporal-ui-documentation-overview/9232
tags:
- temporal
- workflow
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Copyright 2022 Canonical Ltd Ltd.
# See LICENSE file for licensing details.

[tool.bandit]
exclude_dirs = ["/venv/"]
[tool.bandit.assert_used]
skips = ["*/*test.py", "*/test_*.py", "*tests/*.py"]

# Testing tools configuration
[tool.coverage.run]
branch = true
Expand Down
2 changes: 1 addition & 1 deletion src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def render(template_name, context):
"""
charm_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
loader = FileSystemLoader(os.path.join(charm_dir, "templates"))
return Environment(loader=loader).get_template(template_name).render(**context)
return Environment(loader=loader, autoescape=True).get_template(template_name).render(**context)


class TemporalUiK8SOperatorCharm(CharmBase):
Expand Down
4 changes: 2 additions & 2 deletions src/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def log_event_handler(logger):
"""

def decorator(method):
"""Logging decorator wrapper.
"""Log decorator wrapper.
Args:
method: method wrapped by the decorator.
Expand All @@ -28,7 +28,7 @@ def decorator(method):

@functools.wraps(method)
def decorated(self, event):
"""Logging decorator method.
"""Log decorator method.
Args:
event: The event triggered when the relation changes.
Expand Down
88 changes: 88 additions & 0 deletions tests/integration/test_charm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
# Copyright 2023 Canonical Ltd Ltd.
# See LICENSE file for licensing details.


"""Temporal UI charm integration tests."""

import logging
from pathlib import Path

import pytest
import pytest_asyncio
import requests
import yaml
from pytest_operator.plugin import OpsTest

logger = logging.getLogger(__name__)

METADATA = yaml.safe_load(Path("./metadata.yaml").read_text())
APP_NAME = METADATA["name"]

APP_NAME_SERVER = "temporal-k8s"
APP_NAME_ADMIN = "temporal-admin-k8s"


@pytest_asyncio.fixture(name="deploy", scope="module")
async def deploy(ops_test: OpsTest):
"""The app is up and running."""
charm = await ops_test.build_charm(".")
resources = {"temporal-ui-image": METADATA["containers"]["temporal-ui"]["upstream-source"]}

# Deploy temporal server, temporal admin and postgresql charms.
await ops_test.model.deploy(charm, resources=resources, application_name=APP_NAME)
await ops_test.model.deploy(APP_NAME_SERVER, channel="edge")
await ops_test.model.deploy(APP_NAME_ADMIN, channel="edge")
await ops_test.model.deploy("postgresql-k8s", channel="edge", trust=True)

async with ops_test.fast_forward():
await ops_test.model.wait_for_idle(
apps=[APP_NAME, APP_NAME_SERVER, APP_NAME_ADMIN],
status="blocked",
raise_on_blocked=False,
timeout=1200,
)
await ops_test.model.wait_for_idle(
apps=["postgresql-k8s"],
status="active",
raise_on_blocked=False,
timeout=1200,
)

assert ops_test.model.applications[APP_NAME].units[0].workload_status == "blocked"
await ops_test.model.integrate(f"{APP_NAME_SERVER}:db", "postgresql-k8s:db")
await ops_test.model.integrate(f"{APP_NAME_SERVER}:visibility", "postgresql-k8s:db")
await ops_test.model.integrate(f"{APP_NAME_SERVER}:admin", f"{APP_NAME_ADMIN}:admin")
await ops_test.model.wait_for_idle(
apps=[APP_NAME_SERVER, APP_NAME_ADMIN],
status="active",
raise_on_blocked=False,
timeout=300,
)

await ops_test.model.integrate(f"{APP_NAME}:ui", f"{APP_NAME_SERVER}:ui")

await ops_test.model.wait_for_idle(
apps=[APP_NAME],
status="active",
raise_on_blocked=False,
timeout=300,
)

assert ops_test.model.applications[APP_NAME].units[0].workload_status == "active"


@pytest.mark.abort_on_fail
@pytest.mark.usefixtures("deploy")
class TestDeployment:
"""Integration tests for Temporal UI charm."""

async def test_basic_client(self, ops_test: OpsTest):
"""Perform GET request on the Temporal UI host."""
status = await ops_test.model.get_status() # noqa: F821
address = status["applications"][APP_NAME]["units"][f"{APP_NAME}/0"]["address"]
url = f"http://{address}:8080"
logger.info("curling app address: %s", url)

response = requests.get(url, timeout=300)
assert response.status_code == 200
3 changes: 3 additions & 0 deletions tests/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.


"""Unit tests config."""

import ops.testing

ops.testing.SIMULATE_CAN_CONNECT = True
Loading

0 comments on commit 7106f1d

Please sign in to comment.