refactor(images): build FROM the distribution base image, not a pkgmgr one

The container this project builds installs its own python, ansible and docker
CLI, so the package manager riding along in the image it built FROM was never
used. That layer now lives in its own repository, which publishes one
multi-platform image per distribution, and meta/distros.yml points at it:
`base` replaces `pkgmgr_virgin`, and utils.distros grows base_image() where
pkgmgr_virgin_image() stood. The pkgmgr image itself stays, because the
`pkgmgr install` test still boots it.

Three references carried the pkgmgr-era tag `stable`, which base-images does
not publish: it pushes `latest` and the major release, and for a rolling
distribution only `latest`, so `latest` is the one value that exists for all
five. INFINITO_PARENT_IMAGE_TAG and the two install tests move to it.

The guard that keeps image references inside the SPOT only matched
`pkgmgr-[{$]`. Renaming the family made it blind to exactly half its surface,
which is how scripts/tests/install/make.sh kept `base-${d}:stable` while
pkgmgr.sh was caught. It now matches `base-` too.

INFINITO_ARCHITECTURE and INFINITO_ARCHITECTURES appear here because
default.env is shared with the architecture axis that follows. They are empty
and inert until it lands; the alternative was a commit whose build fails by
construction, with `base-` declared and `stable` still requested.

From here nothing builds until base-images has published: `docker pull` of the
parent answers `manifest unknown`, and every make target that depends on
build-dependency fails there.

Verified: tests/lint/repository/test_distros_spot.py passes, and the widened
pattern is shown to catch the line the old one missed rather than merely not
breaking.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-09-19 06:50:45 +02:00
1 parent 0cd7af9a42
commit 962c3d550d
7 files changed
+28 -25

No files matched your search

+9 -6
View File
@@ -37,6 +37,12 @@ INFINITO_APP_VARIANTS=
# Ubuntu mirrors in failover order for image apt; the package-cache takes the first as primary, the second as fallback.
INFINITO_APT_UBUNTU_MIRRORS="http://de.archive.ubuntu.com/ubuntu/ http://ftp.fau.de/ubuntu/ http://ftp.halifax.rwth-aachen.de/ubuntu/ http://archive.ubuntu.com/ubuntu/"
# The CPU architecture the deploy matrix assigned one row; empty draws from INFINITO_ARCHITECTURES.
INFINITO_ARCHITECTURE=
# Space-separated subset of amd64/arm64 CI rows are spread over; empty draws from both.
INFINITO_ARCHITECTURES=
# Host interface(s) the compose stack binds published ports to.
INFINITO_BIND_IP=127.0.0.1
@@ -253,14 +259,11 @@ INFINITO_OUTER_NETWORK_MTU=1500
# Repo-relative path of the package build/install script.
INFINITO_PACKAGE_INSTALL_SCRIPT=scripts/install/package.sh
# GHCR owner of the pkgmgr base image. Composed into INFINITO_PARENT_IMAGE by utils/env/handlers/infinito/parent_image.py.
# GHCR owner of the distribution base image. Composed into INFINITO_PARENT_IMAGE by utils/env/handlers/infinito/parent_image.py.
INFINITO_PARENT_IMAGE_OWNER=kevinveenbirkenbach
# Tag of the pkgmgr base image. Composed into INFINITO_PARENT_IMAGE by utils/env/handlers/infinito/parent_image.py.
INFINITO_PARENT_IMAGE_TAG=stable
# Variant of the pkgmgr base image. Currently only `full` is supported.
INFINITO_PARENT_IMAGE_VARIANT=full
# Tag of the distribution base image. Composed into INFINITO_PARENT_IMAGE by utils/env/handlers/infinito/parent_image.py.
INFINITO_PARENT_IMAGE_TAG=latest
# `true` keeps Playwright trace, screenshot, and video for every test; default `false` retains them only on failure.
INFINITO_PLAYWRIGHT_KEEP=false
+1 -1
View File
@@ -30,8 +30,8 @@
# galaxy_platform_versions below.
images:
base: "ghcr.io/{owner}/base-{slug}:{tag}"
pkgmgr: "ghcr.io/{owner}/pkgmgr-{slug}:{tag}"
pkgmgr_virgin: "ghcr.io/{owner}/pkgmgr-{slug}-virgin:{tag}"
environment: "ghcr.io/{owner}/{repository}/{slug}:{tag}"
galaxy_platform_versions:
+2 -2
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
# Install & test Infinito via the Makefile in every distro's virgin
# Install & test Infinito via the Makefile in every distro's base
# container, all distros in parallel inside a single CI job (one runner
# instead of a matrix). Each distro gets its own copy of the checkout so
# the concurrent in-container installs never race on the shared tree.
@@ -38,7 +38,7 @@ for d in "${distros[@]}"; do
-e INFINITO_VENV_DIR="${INFINITO_VENV_DIR}" \
-v "${src}:${INFINITO_SRC_DIR}" \
-w "${INFINITO_SRC_DIR}" \
"ghcr.io/kevinveenbirkenbach/pkgmgr-${d}-virgin:stable" \
"ghcr.io/kevinveenbirkenbach/base-${d}:latest" \
bash -lc '
set -euo pipefail
make install
+1 -1
View File
@@ -35,7 +35,7 @@ for d in "${distros[@]}"; do
-e NIX_CONFIG="${NIX_CONFIG}" \
-e INFINITO_VENV_DIR="${INFINITO_VENV_DIR}" \
-v "${src}:/root/Repositories/github.com/kevinveenbirkenbach/infinito-nexus" \
"ghcr.io/kevinveenbirkenbach/pkgmgr-${d}:stable" \
"ghcr.io/kevinveenbirkenbach/pkgmgr-${d}:latest" \
bash -lc '
set -euo pipefail
make -C "/root/Repositories/github.com/kevinveenbirkenbach/infinito-nexus" install-system-python
+4 -4
View File
@@ -26,8 +26,8 @@ from utils.cache.files import read_text
from utils.cache.yaml import load_yaml_any
from utils.distros import (
FILE_META_DISTROS,
IMAGE_BASE,
IMAGE_PKGMGR,
IMAGE_PKGMGR_VIRGIN,
dev_runtime_images,
distro_names,
image_template,
@@ -45,7 +45,7 @@ _MATRIX_REF_RE = re.compile(
_STEP_REF_RE = re.compile(r"^\$\{\{\s*steps\.([\w-]+)\.outputs\.([\w-]+)\s*\}\}$")
_GITHUB_SHELL = ("bash", "--noprofile", "--norc", "-eo", "pipefail", "-c")
_INTERPOLATED_PKGMGR_RE = re.compile(r"pkgmgr-[{$]")
_INTERPOLATED_PKGMGR_RE = re.compile(r"(?:pkgmgr|base)-[{$]")
_SHELL_LOOP_SLUG = "${d}"
_LIST_SOURCES = ("*.yml", "*.sh", "*.md", "Makefile", "default.env")
@@ -182,7 +182,7 @@ class TestDistrosSpot(unittest.TestCase):
body = "\n".join(f" - {o}" for o in offenders)
self.fail(
f"pkgmgr image reference composed outside {FILE_META_DISTROS}:\n"
f"{body}\n\nRender it via utils.distros.pkgmgr_image() or read "
f"{body}\n\nRender it via utils.distros.base_image() or read "
"INFINITO_PARENT_IMAGE from the env layer."
)
@@ -197,7 +197,7 @@ class TestDistrosSpot(unittest.TestCase):
slug=_SHELL_LOOP_SLUG,
tag=static["INFINITO_PARENT_IMAGE_TAG"],
)
for kind in (IMAGE_PKGMGR, IMAGE_PKGMGR_VIRGIN)
for kind in (IMAGE_BASE, IMAGE_PKGMGR)
}
offenders = [
+7 -7
View File
@@ -30,8 +30,8 @@ from utils.yaml_bootstrap import load_block
FILE_META_DISTROS: str = "meta/distros.yml"
IMAGE_BASE = "base"
IMAGE_PKGMGR = "pkgmgr"
IMAGE_PKGMGR_VIRGIN = "pkgmgr_virgin"
IMAGE_ENVIRONMENT = "environment"
@@ -114,16 +114,16 @@ def _render(kind: str, distro: str, **fields: str) -> str:
return image_template(kind).format(slug=_spec(distro)["slug"], **fields)
def base_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the distribution base image a distro's container builds FROM."""
return _render(IMAGE_BASE, distro, owner=owner, tag=tag)
def pkgmgr_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the pkgmgr base image a distro's container builds FROM."""
"""Reference of the pkgmgr image the `pkgmgr install` test boots."""
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(
+4 -4
View File
@@ -1,24 +1,24 @@
"""INFINITO_PARENT_IMAGE: pkgmgr base image reference composed from
"""INFINITO_PARENT_IMAGE: distribution base image reference composed from
INFINITO_PARENT_IMAGE_OWNER, INFINITO_DISTRO and INFINITO_PARENT_IMAGE_TAG."""
from __future__ import annotations
from typing import TYPE_CHECKING
from utils.distros import pkgmgr_image
from utils.distros import base_image
if TYPE_CHECKING:
from utils.env.builder import BuildContext, EnvBuilder
KEY = "INFINITO_PARENT_IMAGE"
COMMENT = (
"pkgmgr base image (Dockerfile FROM) composed from "
"Distribution base image (Dockerfile FROM) composed from "
"INFINITO_PARENT_IMAGE_OWNER, INFINITO_DISTRO and INFINITO_PARENT_IMAGE_TAG."
)
def compose(owner: str, distro: str, tag: str) -> str:
return pkgmgr_image(distro, owner=owner, tag=tag)
return base_image(distro, owner=owner, tag=tag)
def apply(eb: EnvBuilder, ctx: BuildContext) -> None: