Skip to content

Commit b072697

Browse files
Add tox tests (#270)
Co-authored-by: bertiethorpe <[email protected]> Co-authored-by: bertiethorpe <[email protected]>
1 parent d5e5540 commit b072697

File tree

17 files changed

+743
-581
lines changed

17 files changed

+743
-581
lines changed

.github/workflows/test-pr.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ concurrency:
2525
# TODO(mkjpryor): Change this in the future to use the CAPI management only variation
2626
#####
2727
jobs:
28+
# Run the unit tests on every PR, even from external repos
29+
unit_tests:
30+
uses: ./.github/workflows/tox.yaml
31+
with:
32+
ref: ${{ github.event.pull_request.head.sha }}
33+
2834
# This job exists so that PRs from outside the main repo are rejected
2935
fail_on_remote:
3036
runs-on: ubuntu-latest
@@ -33,7 +39,7 @@ jobs:
3339
run: exit ${{ github.event.pull_request.head.repo.full_name == 'azimuth-cloud/cluster-api-addon-provider' && '0' || '1' }}
3440

3541
publish_artifacts:
36-
needs: [fail_on_remote]
42+
needs: [unit_tests,fail_on_remote]
3743
uses: ./.github/workflows/build-push-artifacts.yaml
3844
with:
3945
ref: ${{ github.event.pull_request.head.sha }}

.github/workflows/tox.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Tox unit tests
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
ref:
7+
type: string
8+
description: The ref to build.
9+
required: true
10+
11+
jobs:
12+
build:
13+
name: Tox unit tests and linting
14+
runs-on: ubuntu-24.04
15+
strategy:
16+
matrix:
17+
python-version: ['3.10','3.12']
18+
19+
steps:
20+
- name: Check out the repository
21+
uses: actions/checkout@v4
22+
with:
23+
ref: ${{ inputs.ref || github.ref }}
24+
25+
- name: Set up Python ${{ matrix.python-version }}
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: ${{ matrix.python-version }}
29+
30+
- name: Install dependencies
31+
run: |
32+
python -m pip install --upgrade pip
33+
python -m pip install tox
34+
35+
- name: Test with tox
36+
run: tox
37+
38+
- name: Generate coverage reports
39+
run: tox -e cover
40+
41+
- name: Archive code coverage results
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: "code-coverage-report-${{ matrix.python-version }}"
45+
path: cover/

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
__pycache__
22
*.egg-info
3-
.python-version
3+
.python-version
4+
chart/charts/*
5+
chart/Chart.lock
6+
# ignore unit test stuff
7+
.stestr/*
8+
.tox/*
9+
.coverage*

.stestr.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[DEFAULT]
2+
test_path=./capi_addons/tests
3+
top_dir=./

capi_addons/config.py

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,124 @@
1-
import typing as t
2-
3-
from pydantic import Field, conint, constr, field_validator, ValidationInfo
4-
5-
from configomatic import Configuration as BaseConfiguration, Section, LoggingConfiguration
1+
from configomatic import (
2+
Configuration as BaseConfiguration,
3+
)
4+
from configomatic import (
5+
LoggingConfiguration,
6+
Section,
7+
)
8+
from pydantic import Field, ValidationInfo, conint, constr, field_validator
69

710

811
class HelmClientConfiguration(Section):
912
"""
1013
Configuration for the Helm client.
1114
"""
15+
1216
#: The default timeout to use with Helm releases
1317
#: Can be an integer number of seconds or a duration string like 5m, 5h
14-
default_timeout: t.Union[int, constr(min_length = 1)] = "1h"
18+
default_timeout: int | constr(min_length=1) = "1h"
1519
#: The executable to use
1620
#: By default, we assume Helm is on the PATH
17-
executable: constr(min_length = 1) = "helm"
21+
executable: constr(min_length=1) = "helm"
1822
#: The maximum number of revisions to retain in the history of releases
1923
history_max_revisions: int = 10
2024
#: Indicates whether to verify TLS when pulling charts
2125
insecure_skip_tls_verify: bool = False
2226
#: The directory to use for unpacking charts
2327
#: By default, the system temporary directory is used
24-
unpack_directory: t.Optional[str] = None
28+
unpack_directory: str | None = None
2529

2630

2731
class Configuration(
2832
BaseConfiguration,
29-
default_path = "/etc/capi-addon-provider/config.yaml",
30-
path_env_var = "CAPI_ADDON_PROVIDER_CONFIG",
31-
env_prefix = "CAPI_ADDON_PROVIDER"
33+
default_path="/etc/capi-addon-provider/config.yaml",
34+
path_env_var="CAPI_ADDON_PROVIDER_CONFIG",
35+
env_prefix="CAPI_ADDON_PROVIDER",
3236
):
3337
"""
3438
Top-level configuration model.
3539
"""
40+
3641
#: The logging configuration
37-
logging: LoggingConfiguration = Field(default_factory = LoggingConfiguration)
42+
logging: LoggingConfiguration = Field(default_factory=LoggingConfiguration)
3843

3944
#: The API group of the cluster CRDs
40-
api_group: constr(min_length = 1) = "addons.stackhpc.com"
45+
api_group: constr(min_length=1) = "addons.stackhpc.com"
4146
#: The prefix to use for operator annotations
42-
annotation_prefix: constr(min_length = 1) = Field(None, validate_default = True)
47+
annotation_prefix: constr(min_length=1) = Field(None, validate_default=True)
4348
#: A list of categories to place CRDs into
44-
crd_categories: t.List[constr(min_length = 1)] = Field(
45-
default_factory = lambda: ["cluster-api", "capi-addons"]
49+
crd_categories: list[constr(min_length=1)] = Field(
50+
default_factory=lambda: ["cluster-api", "capi-addons"]
4651
)
4752

4853
#: The field manager name to use for server-side apply
49-
easykube_field_manager: constr(min_length = 1) = "cluster-api-addon-provider"
54+
easykube_field_manager: constr(min_length=1) = "cluster-api-addon-provider"
5055

5156
#: The amount of time (seconds) before a watch is forcefully restarted
52-
watch_timeout: conint(gt = 0) = 600
57+
watch_timeout: conint(gt=0) = 600
5358

5459
#: The delay to use for temporary errors by default
55-
temporary_error_delay: conint(gt = 0) = 15
60+
temporary_error_delay: conint(gt=0) = 15
5661

5762
#: The Helm client configuration
58-
helm_client: HelmClientConfiguration = Field(default_factory = HelmClientConfiguration)
63+
helm_client: HelmClientConfiguration = Field(
64+
default_factory=HelmClientConfiguration
65+
)
5966

6067
#: Label indicating that an addon belongs to a cluster
61-
cluster_label: constr(min_length = 1) = Field(None, validate_default = True)
68+
cluster_label: constr(min_length=1) = Field(None, validate_default=True)
6269
#: Label indicating the target namespace for the addon
63-
release_namespace_label: constr(min_length = 1) = Field(None, validate_default = True)
70+
release_namespace_label: constr(min_length=1) = Field(None, validate_default=True)
6471
#: Label indicating the name of the release for the addon
65-
release_name_label: constr(min_length = 1) = Field(None, validate_default = True)
72+
release_name_label: constr(min_length=1) = Field(None, validate_default=True)
6673
#: Label indicating that a configmap or secret should be watched for changes
67-
watch_label: constr(min_length = 1) = Field(None, validate_default = True)
74+
watch_label: constr(min_length=1) = Field(None, validate_default=True)
6875
#: Prefix to use for annotations containing a configmap checksum
69-
configmap_annotation_prefix: constr(min_length = 1) = Field(None, validate_default = True)
76+
configmap_annotation_prefix: constr(min_length=1) = Field(
77+
None, validate_default=True
78+
)
7079
#: Prefix to use for annotations containing a secret checksum
71-
secret_annotation_prefix: constr(min_length = 1) = Field(None, validate_default = True)
80+
secret_annotation_prefix: constr(min_length=1) = Field(None, validate_default=True)
7281
#: Annotation to use to trigger restarts of workloads in lifecycle hooks
73-
lifecycle_hook_restart_annotation: constr(min_length = 1) = Field(None, validate_default = True)
82+
lifecycle_hook_restart_annotation: constr(min_length=1) = Field(
83+
None, validate_default=True
84+
)
7485

75-
@field_validator("annotation_prefix", mode = "before")
86+
@field_validator("annotation_prefix", mode="before")
7687
@classmethod
7788
def default_annotation_prefix(cls, v, info: ValidationInfo):
78-
return v or info.data['api_group']
89+
return v or info.data["api_group"]
7990

80-
@field_validator("cluster_label", mode = "before")
91+
@field_validator("cluster_label", mode="before")
8192
@classmethod
8293
def default_cluster_label(cls, v, info: ValidationInfo):
8394
return v or f"{info.data['api_group']}/cluster"
8495

85-
@field_validator("release_namespace_label", mode = "before")
96+
@field_validator("release_namespace_label", mode="before")
8697
@classmethod
8798
def default_release_namespace_label(cls, v, info: ValidationInfo):
8899
return v or f"{info.data['api_group']}/release-namespace"
89100

90-
@field_validator("release_name_label", mode = "before")
101+
@field_validator("release_name_label", mode="before")
91102
@classmethod
92103
def default_release_name_label(cls, v, info: ValidationInfo):
93104
return v or f"{info.data['api_group']}/release-name"
94105

95-
@field_validator("watch_label", mode = "before")
106+
@field_validator("watch_label", mode="before")
96107
@classmethod
97108
def default_watch_label(cls, v, info: ValidationInfo):
98109
return v or f"{info.data['api_group']}/watch"
99110

100-
@field_validator("configmap_annotation_prefix", mode = "before")
111+
@field_validator("configmap_annotation_prefix", mode="before")
101112
@classmethod
102113
def default_configmap_annotation_prefix(cls, v, info: ValidationInfo):
103114
return v or f"configmap.{info.data['annotation_prefix']}"
104115

105-
@field_validator("secret_annotation_prefix", mode = "before")
116+
@field_validator("secret_annotation_prefix", mode="before")
106117
@classmethod
107118
def default_secret_annotation_prefix(cls, v, info: ValidationInfo):
108119
return v or f"secret.{info.data['annotation_prefix']}"
109120

110-
@field_validator("lifecycle_hook_restart_annotation", mode = "before")
121+
@field_validator("lifecycle_hook_restart_annotation", mode="before")
111122
@classmethod
112123
def default_lifecycle_hook_restart_annotation(cls, v, info: ValidationInfo):
113124
return v or f"{info.data['annotation_prefix']}/restarted-at"
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from .base import *
2-
from .helm_release import *
3-
from .manifests import *
1+
from capi_addons.models.v1alpha1.base import * # noqa: F403
2+
from capi_addons.models.v1alpha1.helm_release import * # noqa: F403
3+
from capi_addons.models.v1alpha1.manifests import * # noqa: F403

0 commit comments

Comments
 (0)