diff --git a/tests/test_bump.py b/tests/test_bump.py index 2da1cc7..703491f 100644 --- a/tests/test_bump.py +++ b/tests/test_bump.py @@ -9,6 +9,8 @@ from __future__ import annotations import base64 +import pytest + from image_tools.bump import Dependent, bump_all, load_dependents, open_or_update_pr, rewrite_pin @@ -137,6 +139,72 @@ def test_the_dependents_are_listed_in_the_repo(tmp_path): ] +@pytest.mark.parametrize("bad", ["", "base-os", "netork/base-os:1"]) +def test_an_odd_new_reference_is_refused(bad): + with pytest.raises(ValueError): + rewrite_pin("FROM x\n", "netork/base-os", bad) + + +def test_a_repo_without_the_file_yet_is_skipped(): + """The service repos start empty; a missing file is no pin to move, not a crash.""" + + class Empty(FakeGitea): + def __call__(self, method, path, body=None): + if method == "GET" and "/contents/" in path: + self.calls.append((method, path)) + raise FileNotFoundError(path) + return super().__call__(method, path, body) + + api = Empty({}) + + assert open_or_update_pr(api, DEP, "netork/base-os", NEW, "13-20261020.1", "r") is None + assert not [c for c in api.calls if c[0] in ("PUT", "POST")] + + +def test_a_dependent_without_a_workflow_gets_the_pr_only(): + """engine and satellite have no nightly run; their pull request is the trigger.""" + from image_tools.bump import dispatch + + calls = [] + dispatch(lambda *a: calls.append(a), Dependent("NetOrk/netork", ("x",), ""), {"base_ref": NEW}) + + assert calls == [] + + +def test_a_compose_pin_with_the_registry_variable_moves(): + """netork's compose files name the registry as ${REGISTRY_HOST:-registry.netork.io} + (tests/test_compose_image_names.py there); the variable stays, the pin moves.""" + old = ( + "${REGISTRY_HOST:-registry.netork.io}/netork/apt-cacher-ng:3.7.5-1-13-20261020.1-2026102017@sha256:" + + "a" * 64 + ) + new = ( + "registry.netork.io/netork/apt-cacher-ng:3.7.5-1-13-20261021.1-2026102103@sha256:" + + "b" * 64 + ) + text = f" apt-cacher-ng:\n image: {old}\n" + + moved = rewrite_pin(text, "netork/apt-cacher-ng", new) + + assert moved == ( + " apt-cacher-ng:\n image: ${REGISTRY_HOST:-registry.netork.io}/netork/apt-cacher-ng:" + "3.7.5-1-13-20261021.1-2026102103@sha256:" + "b" * 64 + "\n" + ) + + +def test_a_repo_the_bot_may_not_see_is_an_error_not_a_skip(): + """Gitea answers 404 for the repo and its files alike when the token's account + has no access; on 2026-10-22 that read as "no pin to move" everywhere.""" + + class Invisible(FakeGitea): + def __call__(self, method, path, body=None): + self.calls.append((method, path)) + raise FileNotFoundError(path) + + with pytest.raises(PermissionError, match="NetOrk/"): + open_or_update_pr(Invisible({}), DEP, "netork/base-os", NEW, "13-20261020.1", "r") + + class TestEveryDependent: """2026-10-22: netork's dependents entry named ui-nightly.yml, which does not exist yet; the dispatch's 404 ended the run with a traceback after the last