Skip to content

Commit

Permalink
Add unit tests, linting and tests CI/CD (#6)
Browse files Browse the repository at this point in the history
* add unit tests and linting

* add tests ci/cd
  • Loading branch information
kelkawi-a authored Jun 6, 2024
1 parent 6f4109d commit 205db6e
Show file tree
Hide file tree
Showing 12 changed files with 506 additions and 124 deletions.
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@cea2ac306b4f4c1475d73b1a4c766d62e5b1c8a9
secrets: inherit
37 changes: 37 additions & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
header:
license:
spdx-id: Apache-2.0
copyright-owner: Canonical Ltd.
copyright-year: 2024
content: |
Copyright [year] [owner]
See LICENSE file for licensing details.
paths:
- '**'
paths-ignore:
- '.github/**'
- '**/.gitkeep'
- '**/*.cfg'
- '**/*.conf'
- '**/*.j2'
- '**/*.json'
- '**/*.md'
- '**/*.rule'
- '**/*.tmpl'
- '**/*.txt'
- '**/*.jinja'
- '.codespellignore'
- '.dockerignore'
- '.flake8'
- '.jujuignore'
- '.gitignore'
- '.licenserc.yaml'
- '.trivyignore'
- '.woke.yaml'
- '.woke.yml'
- 'CODEOWNERS'
- 'icon.svg'
- 'LICENSE'
- 'trivy.yaml'
- 'lib/**'
comment: on-failure
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/nginx_route.py
rules:
# Ignore "master" - the database relation event received from the library.
- name: master
3 changes: 3 additions & 0 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.

# This file configures Charmcraft.
# See https://juju.is/docs/sdk/charmcraft-config for guidance.

Expand Down
56 changes: 27 additions & 29 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Copyright 2024 Canonical 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 All @@ -11,36 +19,26 @@ log_cli_level = "INFO"

# Formatting tools configuration
[tool.black]
line-length = 99
line-length = 120
target-version = ["py38"]

# Linting tools configuration
[tool.ruff]
line-length = 99
select = ["E", "W", "F", "C", "N", "D", "I001"]
extend-ignore = [
"D203",
"D204",
"D213",
"D215",
"D400",
"D404",
"D406",
"D407",
"D408",
"D409",
"D413",
]
ignore = ["E501", "D107"]
extend-exclude = ["__pycache__", "*.egg_info"]
per-file-ignores = {"tests/*" = ["D100","D101","D102","D103","D104"]}
[tool.isort]
profile = "black"

[tool.ruff.mccabe]
# Linting tools configuration
[tool.flake8]
max-line-length = 120
max-doc-length = 99
max-complexity = 10

[tool.codespell]
skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage"

[tool.pyright]
include = ["src/**.py"]

exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"]
select = ["E", "W", "F", "C", "N", "R", "D", "H"]
# Ignore W503, E501 because using black creates errors with this
# Ignore D107 Missing docstring in __init__
ignore = ["W503", "E501", "D107"]
# D100, D101, D102, D103: Ignore missing docstrings in tests
per-file-ignores = ["tests/*:D100,D101,D102,D103,D104"]
docstring-convention = "google"
# Check for properly formatted copyright header in each file
copyright-check = "True"
copyright-author = "Canonical Ltd."
copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s"
28 changes: 25 additions & 3 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
import logging

from charms.nginx_ingress_integrator.v0.nginx_route import require_nginx_route
from log import log_event_handler
from ops import main, pebble
from ops.charm import CharmBase
from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus
from ops.pebble import CheckStatus

from log import log_event_handler
from relations.airbyte_server import AirbyteServer
from state import State

Expand All @@ -23,14 +24,24 @@


class AirbyteUIK8sOperatorCharm(CharmBase):
"""Charm the application."""
"""Airbyte UI charm.
Attrs:
_state: used to store data that is persisted across invocations.
external_hostname: DNS listing used for external connections.
"""

@property
def external_hostname(self):
"""Return the DNS listing used for external connections."""
return self.config["external-hostname"] or self.app.name

def __init__(self, *args):
"""Construct.
Args:
args: Ignore.
"""
super().__init__(*args)
self._state = State(self.app, lambda: self.model.get_relation("peer"))

Expand Down Expand Up @@ -59,7 +70,11 @@ def _require_nginx_route(self):

@log_event_handler(logger)
def _on_pebble_ready(self, event):
"""Handle pebble-ready event."""
"""Handle pebble ready event.
Args:
event: The event triggered when the relation changed.
"""
self._update(event)

@log_event_handler(logger)
Expand All @@ -78,6 +93,11 @@ def _on_update_status(self, event):
Args:
event: The `update-status` event triggered at intervals.
"""
try:
self._validate()
except ValueError:
return

container = self.unit.get_container(self.name)
valid_pebble_plan = self._validate_pebble_plan(container)
if not valid_pebble_plan:
Expand Down Expand Up @@ -154,8 +174,10 @@ def _update(self, event):
context = {
"API_URL": "/api/v1/",
"AIRBYTE_EDITION": "community",
"AIRBYTE_SERVER_HOST": f"{server_svc}:{INTERNAL_API_PORT}",
"INTERNAL_API_HOST": f"{server_svc}:{INTERNAL_API_PORT}",
"CONNECTOR_BUILDER_API_HOST": f"{server_svc}:{CONNECTOR_BUILDER_API_PORT}",
"CONNECTOR_BUILDER_API_URL": "/connector-builder-api",
"KEYCLOAK_INTERNAL_HOST": "localhost",
}

Expand Down
15 changes: 5 additions & 10 deletions src/relations/airbyte_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

import logging

from log import log_event_handler
from ops import framework

from log import log_event_handler

logger = logging.getLogger(__name__)


Expand All @@ -22,15 +23,9 @@ def __init__(self, charm):
"""
super().__init__(charm, "airbyte-server")
self.charm = charm
charm.framework.observe(
charm.on.airbyte_server_relation_joined, self._on_airbyte_server_relation_changed
)
charm.framework.observe(
charm.on.airbyte_server_relation_changed, self._on_airbyte_server_relation_changed
)
charm.framework.observe(
charm.on.airbyte_server_relation_broken, self._on_airbyte_server_relation_broken
)
charm.framework.observe(charm.on.airbyte_server_relation_joined, self._on_airbyte_server_relation_changed)
charm.framework.observe(charm.on.airbyte_server_relation_changed, self._on_airbyte_server_relation_changed)
charm.framework.observe(charm.on.airbyte_server_relation_broken, self._on_airbyte_server_relation_broken)

@log_event_handler(logger)
def _on_airbyte_server_relation_changed(self, event):
Expand Down
9 changes: 4 additions & 5 deletions tests/integration/test_charm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
# Copyright 2024 Ali
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.

"""Charm integration tests."""

import asyncio
import logging
from pathlib import Path
Expand Down Expand Up @@ -29,7 +30,5 @@ async def test_build_and_deploy(ops_test: OpsTest):
# Deploy the charm and wait for active/idle status
await asyncio.gather(
ops_test.model.deploy(charm, resources=resources, application_name=APP_NAME),
ops_test.model.wait_for_idle(
apps=[APP_NAME], status="active", raise_on_blocked=True, timeout=1000
),
ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", raise_on_blocked=True, timeout=1000),
)
9 changes: 9 additions & 0 deletions tests/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright 2024 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 205db6e

Please sign in to comment.