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

CSS-3449: Add CI/CD, unit and integration tests #2

Merged
merged 7 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
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
kelkawi-a marked this conversation as resolved.
Show resolved Hide resolved
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