Files
computer-playbook/utils/distros.py
T
kevinveenbirkenbachandClaude Opus 5 3257376fce refactor(ci): resolve the dev-runtime matrix through a named module
The workspace workflow asked the distro SPOT two questions through embedded python one-liners: the matrix image list, and the distro behind a matrix entry. Give both a name -- distro_of_dev_runtime_image() as the counterpart to dev_runtime_image(), and a cli.meta.ci.dev_runtime module shaped like its image_ref neighbour. The empty-SPOT guard that protected the matrix from silently skipping every job moves along with it. No caller yet; the workflow switches over in the next commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 22:47:30 +02:00

132 lines
4.5 KiB
Python

"""Distribution SPOT.
``meta/distros.yml`` declares every distribution the project builds, tests
and deploys on: the id used as ``INFINITO_DISTRO``, the ``os_family``
ansible reports for it, the Galaxy platform name, the upstream base image
the development-environment matrix boots it from, and the templates the
pkgmgr base image and the environment image references are rendered from.
Consumers MUST read the distro set through this module. A local tuple of
distro names or an f-string spelling out ``ghcr.io/.../pkgmgr-...`` is a
second source of truth and drifts; ``tests/lint/repository/test_distros_spot.py``
guards against reintroducing one.
Registry owner, repository and tag are *not* declared here — they stay in
``default.env``, which is their SPOT. This module only renders them into
the templates.
Keep this module free of Ansible imports and cheap to import: it is pulled
in by the env layer and by ``utils.packages.schema``, which reach contexts
where Ansible is not installed. It must also stay importable on the bare
bootstrap python, so the SPOT is read with the stdlib block reader instead
of PyYAML.
"""
from __future__ import annotations
from utils.cache import PROJECT_ROOT
from utils.cache.files import read_text
from utils.yaml_bootstrap import load_block
FILE_META_DISTROS: str = "meta/distros.yml"
IMAGE_PKGMGR = "pkgmgr"
IMAGE_PKGMGR_VIRGIN = "pkgmgr_virgin"
IMAGE_ENVIRONMENT = "environment"
class UnknownDistroError(ValueError):
"""Raised for a distro id or image that ``meta/distros.yml`` does not declare."""
def _doc() -> dict:
return load_block(read_text(str(PROJECT_ROOT / FILE_META_DISTROS)))
def _specs() -> dict[str, dict]:
return _doc()["distros"]
def _spec(distro: str) -> dict:
try:
return _specs()[distro]
except KeyError:
raise UnknownDistroError(
f"{distro!r} is not declared in {FILE_META_DISTROS}. "
f"Declared: {', '.join(distro_names())}."
) from None
def distro_names() -> tuple[str, ...]:
"""Every declared distro id, in declaration order."""
return tuple(_specs())
def distro_family() -> dict[str, str]:
"""Map each distro id onto the ``os_family`` ansible reports for it."""
return {name: spec["family"] for name, spec in _specs().items()}
def galaxy_platforms() -> list[dict[str, object]]:
"""Canonical ``galaxy_info.platforms`` block for every role's meta/main.yml.
Sorted by platform name, which is the order the role files carry and
which the schema lint compares against verbatim.
"""
versions = list(_doc()["galaxy_platform_versions"])
return [
{"name": name, "versions": list(versions)}
for name in sorted(spec["galaxy_platform"] for spec in _specs().values())
]
def dev_runtime_images() -> tuple[str, ...]:
"""Upstream base images of the development-environment test matrix."""
return tuple(spec["dev_runtime_image"] for spec in _specs().values())
def dev_runtime_image(distro: str) -> str:
"""Upstream base image the development environment boots a distro from."""
return _spec(distro)["dev_runtime_image"]
def distro_of_dev_runtime_image(image: str) -> str:
"""Distro id whose development environment boots from ``image``."""
for name, spec in _specs().items():
if spec["dev_runtime_image"] == image:
return name
raise UnknownDistroError(
f"{image!r} is not a dev_runtime_image in {FILE_META_DISTROS}. "
f"Declared: {', '.join(dev_runtime_images())}."
)
def image_template(kind: str) -> str:
"""Raw reference template, for callers rendering a non-distro slug.
The shell-side installer scripts loop over distros with their own
variable, so they render ``{slug}`` themselves rather than per distro.
"""
return _doc()["images"][kind]
def _render(kind: str, distro: str, **fields: str) -> str:
return image_template(kind).format(slug=_spec(distro)["slug"], **fields)
def pkgmgr_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the pkgmgr base image a distro's container builds FROM."""
return _render(IMAGE_PKGMGR, distro, owner=owner, tag=tag)
def pkgmgr_virgin_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the untouched pkgmgr image the install tests boot."""
return _render(IMAGE_PKGMGR_VIRGIN, distro, owner=owner, tag=tag)
def environment_image(distro: str, owner: str, repository: str, tag: str) -> str:
"""Reference of the environment image built for a distro."""
return _render(
IMAGE_ENVIRONMENT, distro, owner=owner, repository=repository, tag=tag
)