Skip to content

Commit

Permalink
Introduce tests to ensure branches and lp-recipes exist (#663)
Browse files Browse the repository at this point in the history
  • Loading branch information
addyess authored Sep 12, 2024
1 parent 898cce0 commit 7f1f0b5
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ jobs:
name: k8s.snap
path: k8s.snap

test-branches:
name: Test Branch Management
runs-on: ubuntu-20.04
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Install tox
run: pip install tox
- name: Run branch_management tests
run: |
tox -c tests/branch_management -e integration
test-integration:
name: Test ${{ matrix.os }}
strategy:
Expand Down
1 change: 1 addition & 0 deletions tests/branch_management/.copyright.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Copyright ${years} ${owner}.
5 changes: 5 additions & 0 deletions tests/branch_management/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
black==24.3.0
codespell==2.2.4
flake8==6.0.0
isort==5.12.0
licenseheaders==0.8.8
7 changes: 7 additions & 0 deletions tests/branch_management/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
coverage[toml]==7.2.5
pytest==7.3.1
PyYAML==6.0.1
tenacity==8.2.3
pylint==3.2.5
requests==2.32.3
semver==3.0.2
27 changes: 27 additions & 0 deletions tests/branch_management/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Copyright 2024 Canonical, Ltd.
#
from pathlib import Path

import pytest
import requests
import semver


@pytest.fixture
def upstream_release() -> semver.VersionInfo:
"""Return the latest stable k8s in the release series"""
release_url = "https://dl.k8s.io/release/stable.txt"
r = requests.get(release_url)
r.raise_for_status()
return semver.Version.parse(r.content.decode().lstrip("v"))


@pytest.fixture
def current_release() -> semver.VersionInfo:
"""Return the current branch k8s version"""
ver_file = (
Path(__file__).parent / "../../../build-scripts/components/kubernetes/version"
)
version = ver_file.read_text().strip()
return semver.Version.parse(version.lstrip("v"))
93 changes: 93 additions & 0 deletions tests/branch_management/tests/test_branches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#
# Copyright 2024 Canonical, Ltd.
#
from pathlib import Path
from subprocess import check_output

import requests


def _get_max_minor(major):
"""Get the latest minor release of the provided major.
For example if you use 1 as major you will get back X where X gives you latest 1.X release.
"""
minor = 0
while _upstream_release_exists(major, minor):
minor += 1
return minor - 1


def _upstream_release_exists(major, minor):
"""Return true if the major.minor release exists"""
release_url = "https://dl.k8s.io/release/stable-{}.{}.txt".format(major, minor)
r = requests.get(release_url)
return r.status_code == 200


def _confirm_branch_exists(branch):
cmd = f"git ls-remote --heads https://github.com/canonical/k8s-snap.git/ {branch}"
output = check_output(cmd.split()).decode("utf-8")
assert branch in output, f"Branch {branch} does not exist"


def _branch_flavours(branch: str = None):
patch_dir = Path("build-scripts/patches")
branch = "HEAD" if branch is None else branch
cmd = f"git ls-tree --full-tree -r --name-only {branch} {patch_dir}"
output = check_output(cmd.split()).decode("utf-8")
patches = set(
Path(f).relative_to(patch_dir).parents[0] for f in output.splitlines()
)
return [p.name for p in patches]


def _confirm_recipe(track, flavour):
recipe = f"https://launchpad.net/~containers/k8s/+snap/k8s-snap-{track}-{flavour}"
r = requests.get(recipe)
return r.status_code == 200


def test_branches(upstream_release):
"""Ensures git branches exist for prior releases.
We need to make sure the LP builders pointing to the main github branch are only pushing
to the latest and current k8s edge snap tracks. An indication that this is not enforced is
that we do not have a branch for the k8s release for the previous stable release. Let me
clarify with an example.
Assuming upstream stable k8s release is v1.12.x, there has to be a 1.11 github branch used
by the respective LP builders for building the v1.11.y.
"""
if upstream_release.minor != 0:
major = upstream_release.major
minor = upstream_release.minor - 1
else:
major = int(upstream_release.major) - 1
minor = _get_max_minor(major)

prior_branch = f"release-{major}.{minor}"
print(f"Current stable is {upstream_release}")
print(f"Checking {prior_branch} branch exists")
_confirm_branch_exists(prior_branch)
flavours = _branch_flavours(prior_branch)
for flavour in flavours:
prior_branch = f"autoupdate/{prior_branch}-{flavour}"
print(f"Checking {prior_branch} branch exists")
_confirm_branch_exists(prior_branch)


def test_launchpad_recipe(current_release):
"""Ensures the current recipes are available.
We should ensure that a launchpad recipe exists for this release to be build with
"""
track = f"{current_release.major}.{current_release.minor}"
print(f"Checking {track} recipe exists")
flavours = ["classic"] + _branch_flavours()
recipe_exists = {flavour: _confirm_recipe(track, flavour) for flavour in flavours}
if missing_recipes := [
flavour for flavour, exists in recipe_exists.items() if not exists
]:
assert (
not missing_recipes
), f"LP Recipes do not exist for {track} {missing_recipes}"
52 changes: 52 additions & 0 deletions tests/branch_management/tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[tox]
no_package = True
skip_missing_interpreters = True
env_list = format, lint, integration
min_version = 4.0.0

[testenv]
set_env =
PYTHONBREAKPOINT=pdb.set_trace
PY_COLORS=1
pass_env =
PYTHONPATH

[testenv:format]
description = Apply coding style standards to code
deps = -r {tox_root}/requirements-dev.txt
commands =
licenseheaders -t {tox_root}/.copyright.tmpl -cy -o 'Canonical, Ltd' -d {tox_root}/tests
isort {tox_root}/tests --profile=black
black {tox_root}/tests

[testenv:lint]
description = Check code against coding style standards
deps = -r {tox_root}/requirements-dev.txt
commands =
codespell {tox_root}/tests
flake8 {tox_root}/tests
licenseheaders -t {tox_root}/.copyright.tmpl -cy -o 'Canonical, Ltd' -d {tox_root}/tests --dry
isort {tox_root}/tests --profile=black --check
black {tox_root}/tests --check --diff

[testenv:test]
description = Run integration tests
deps =
-r {tox_root}/requirements-test.txt
commands =
pytest -v \
--maxfail 1 \
--tb native \
--log-cli-level DEBUG \
--disable-warnings \
{posargs} \
{tox_root}/tests
pass_env =
TEST_*

[flake8]
max-line-length = 120
select = E,W,F,C,N
ignore = W503
exclude = venv,.git,.tox,.tox_env,.venv,build,dist,*.egg_info
show-source = true

0 comments on commit 7f1f0b5

Please sign in to comment.