Files
computer-playbook/tests/unit/python/utils/docker/test_image_discovery_lifecycle.py
T
kevinveenbirkenbachandClaude Opus 5.5 8a29ba0bfd fix(images): leave eol roles out of image discovery
The scheduled mirror job has failed every day since 2026-09-25 on the same two
images: quay.io/minio/minio and quay.io/minio/mc answer `unauthorized` to
anonymous pulls ("2/197 failed", run 38352569503). Both belong to
web-app-minio, an eol role outside the lifecycle envelope that default.env
tests, so no CI deploy pulls them.

iter_role_images now skips every role that is_maintained() reports as
unmaintained, the check the version updaters already apply to the same list.
On the tree the discovery yields 187 images instead of 192; the five it drops
belong to the four eol roles web-app-confluence, web-app-jira, web-app-minio
and web-app-phpldapadmin. The mirror sync, resolver and wait read this list,
and their descriptions and mirror.md now say so.

The roles directory is resolved first: is_maintained reads a relative path as
a role name and would keep every role.

475ab9b386 on feature/store-i18n takes the same approach with a lifecycle
reader of its own; main already has is_maintained for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:19:28 +02:00

68 lines
2.0 KiB
Python

from __future__ import annotations
import os
import tempfile
import unittest
from pathlib import Path
from utils.docker.image.discovery import iter_role_images
from utils.roles.mapping import ROLE_FILE_META_SERVICES
SUPPORTED = """---
demo:
image: libretranslate/libretranslate
version: v1.9.6
lifecycle: stable
helper:
image: alpine
version: "3.22"
"""
RETIRED = """---
demo:
image: quay.io/minio/minio
version: RELEASE.2025-09-07T16-13-09Z
lifecycle: eol
client:
image: quay.io/minio/mc
version: RELEASE.2025-08-13T08-35-41Z
"""
UNSTAGED = """---
demo:
image: libretranslate/libretranslate
version: v1.9.6
"""
class TestImageDiscoveryLifecycle(unittest.TestCase):
def _images(self, services_yaml: str, *, relative: bool = False) -> set[str]:
"""Discover the images of one role written into a temporary repository.
Args:
services_yaml: the role's ``meta/services.yml``.
relative: pass the repository root relative to the working directory.
"""
with tempfile.TemporaryDirectory() as tmp:
services = Path(tmp) / "roles" / "web-app-demo" / ROLE_FILE_META_SERVICES
services.parent.mkdir(parents=True)
services.write_text(services_yaml, encoding="utf-8")
root = Path(os.path.relpath(tmp)) if relative else Path(tmp)
return {ref.service for ref in iter_role_images(root)}
def test_a_supported_role_yields_every_service(self) -> None:
self.assertEqual({"demo", "helper"}, self._images(SUPPORTED))
def test_a_retired_role_yields_none_of_its_services(self) -> None:
self.assertEqual(set(), self._images(RETIRED))
def test_a_role_that_names_no_stage_is_kept(self) -> None:
self.assertEqual({"demo"}, self._images(UNSTAGED))
def test_a_relative_root_still_leaves_a_retired_role_out(self) -> None:
self.assertEqual(set(), self._images(RETIRED, relative=True))
if __name__ == "__main__":
unittest.main()