Merge pull request 'Add matrixed container base image build' (#1) from container-scaffold into main
ci/woodpecker/tag/docker Pipeline was successful
ci/woodpecker/tag/docker Pipeline was successful
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-merge-conflict
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
|
||||
- repo: https://github.com/AleksaC/hadolint-py
|
||||
rev: v2.15.1
|
||||
hooks:
|
||||
- id: hadolint
|
||||
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.11.0.1
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
# No upstream equivalent: a distro added under distros/ but left out of a
|
||||
# Woodpecker matrix silently never gets built.
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-distros
|
||||
name: distros match the woodpecker matrices
|
||||
entry: ci/check-distros.sh
|
||||
language: system
|
||||
pass_filenames: false
|
||||
@@ -0,0 +1,33 @@
|
||||
when:
|
||||
- event: pull_request
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# One entry per distro. Adding a distro: add distros/<name>/ and one entry here.
|
||||
- DISTRO: alma9
|
||||
IMAGE: almalinux9
|
||||
BASE_IMAGE: "docker.io/almalinux:9"
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: "artifactapi.k8s.syd1.au.unkin.net/docker-internal/plugin-docker-buildx:latest"
|
||||
settings:
|
||||
repo: "artifactapi.k8s.syd1.au.unkin.net/docker-internal/${IMAGE}"
|
||||
target: image
|
||||
dry_run: true
|
||||
build_args:
|
||||
BASE_IMAGE: "${BASE_IMAGE}"
|
||||
DISTRO: "${DISTRO}"
|
||||
buildkit_config: |
|
||||
[registry."artifactapi.k8s.syd1.au.unkin.net"]
|
||||
ca = ["/etc/docker/certs.d/artifactapi.k8s.syd1.au.unkin.net/ca.crt"]
|
||||
backend_options:
|
||||
kubernetes:
|
||||
serviceAccountName: default
|
||||
resources:
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 1
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
@@ -0,0 +1,37 @@
|
||||
when:
|
||||
- event: tag
|
||||
ref: refs/tags/v*
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# One entry per distro. Adding a distro: add distros/<name>/ and one entry here.
|
||||
- DISTRO: alma9
|
||||
IMAGE: almalinux9
|
||||
BASE_IMAGE: "docker.io/almalinux:9"
|
||||
|
||||
steps:
|
||||
- name: docker
|
||||
image: "artifactapi.k8s.syd1.au.unkin.net/docker-internal/plugin-docker-buildx:latest"
|
||||
settings:
|
||||
registry: artifactapi.k8s.syd1.au.unkin.net
|
||||
repo: "artifactapi.k8s.syd1.au.unkin.net/docker-internal/${IMAGE}"
|
||||
target: image
|
||||
build_args:
|
||||
BASE_IMAGE: "${BASE_IMAGE}"
|
||||
DISTRO: "${DISTRO}"
|
||||
buildkit_config: |
|
||||
[registry."artifactapi.k8s.syd1.au.unkin.net"]
|
||||
ca = ["/etc/docker/certs.d/artifactapi.k8s.syd1.au.unkin.net/ca.crt"]
|
||||
tags:
|
||||
- "${CI_COMMIT_TAG##v}"
|
||||
- latest
|
||||
backend_options:
|
||||
kubernetes:
|
||||
serviceAccountName: default
|
||||
resources:
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 1
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
@@ -0,0 +1,18 @@
|
||||
when:
|
||||
- event: pull_request
|
||||
|
||||
steps:
|
||||
- name: pre-commit
|
||||
image: "git.unkin.net/unkin/almalinux9-gobuilder:20260606"
|
||||
commands:
|
||||
- uvx pre-commit run --all-files
|
||||
backend_options:
|
||||
kubernetes:
|
||||
serviceAccountName: default
|
||||
resources:
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 1
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 2
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
ARG BASE_IMAGE=artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/almalinux:9
|
||||
|
||||
FROM ${BASE_IMAGE} AS image
|
||||
ARG DISTRO=alma9
|
||||
COPY distros/${DISTRO}/ /tmp/distro/
|
||||
# DL3041: versions are pinned by the estate dnf repos, not here. SC2086: $PACKAGES is a
|
||||
# word list on purpose. DL4006: the only pipe ends in sha256sum, whose status is the
|
||||
# pipeline's, and set -e catches it.
|
||||
# hadolint ignore=DL3041,DL4006,SC2086
|
||||
RUN set -eux; \
|
||||
. /tmp/distro/distro.env; \
|
||||
rm -f /etc/yum.repos.d/*.repo; \
|
||||
curl -fsSL -o /tmp/ca.rpm "$CA_RPM_URL"; \
|
||||
echo "$CA_RPM_SHA256 /tmp/ca.rpm" | sha256sum -c -; \
|
||||
rpm -i /tmp/ca.rpm; \
|
||||
cp /tmp/distro/yum.repos.d/*.repo /etc/yum.repos.d/; \
|
||||
dnf makecache; \
|
||||
dnf update -y; \
|
||||
dnf install -y $PACKAGES; \
|
||||
dnf clean all; \
|
||||
rm -rf /var/cache/dnf /tmp/ca.rpm /tmp/distro
|
||||
CMD ["/bin/bash"]
|
||||
@@ -0,0 +1,39 @@
|
||||
REGISTRY := artifactapi.k8s.syd1.au.unkin.net/docker-internal
|
||||
DISTROS := $(notdir $(wildcard distros/*))
|
||||
VERSION ?= $(patsubst v%,%,$(or $(shell git describe --tags --exact-match 2>/dev/null),0.1.0-dev))
|
||||
|
||||
.PHONY: build clean pre-commit patch minor major
|
||||
build: $(addprefix build-,$(DISTROS))
|
||||
clean: $(addprefix clean-,$(DISTROS))
|
||||
|
||||
pre-commit:
|
||||
@uvx pre-commit run --all-files
|
||||
|
||||
# Not .PHONY: GNU make skips implicit-rule search for phony targets.
|
||||
|
||||
build-%:
|
||||
@set -eu; . ./distros/$*/distro.env; \
|
||||
docker build --build-arg "BASE_IMAGE=$$BASE_IMAGE" --build-arg "DISTRO=$*" \
|
||||
-t "$(REGISTRY)/$$IMAGE:$(VERSION)" .
|
||||
|
||||
clean-%:
|
||||
@set -eu; . ./distros/$*/distro.env; \
|
||||
docker rmi "$(REGISTRY)/$$IMAGE:$(VERSION)" 2>/dev/null || true
|
||||
|
||||
_LATEST := $(shell git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$$' | head -1)
|
||||
_BASE := $(if $(_LATEST),$(_LATEST),v0.0.0)
|
||||
_MAJ := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f1)
|
||||
_MIN := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f2)
|
||||
_PAT := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f3)
|
||||
|
||||
patch:
|
||||
@NEW=v$(_MAJ).$(_MIN).$(shell expr $(_PAT) + 1); \
|
||||
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
|
||||
|
||||
minor:
|
||||
@NEW=v$(_MAJ).$(shell expr $(_MIN) + 1).0; \
|
||||
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
|
||||
|
||||
major:
|
||||
@NEW=v$(shell expr $(_MAJ) + 1).0.0; \
|
||||
git tag $$NEW && echo "Tagged $$NEW" && git push origin $$NEW
|
||||
@@ -1,3 +1,35 @@
|
||||
# container-base
|
||||
|
||||
Base container images for the estate, carrying internal CA trust and dnf/repo configuration, built as a matrix across the supported distros.
|
||||
The estate's base container images, one per distro, replacing what `packer-images`
|
||||
built. Published as `artifactapi.k8s.syd1.au.unkin.net/docker-internal/<image>:<version>`
|
||||
— the image name is the distro (`almalinux9`), the repo's single semver is the tag.
|
||||
|
||||
| distro | image | from |
|
||||
| --- | --- | --- |
|
||||
| `alma9` | `almalinux9` | `dockerhub/library/almalinux:9` |
|
||||
|
||||
Each image bootstraps the internal CA, installs the estate dnf repository
|
||||
configuration pointed at artifactapi, and installs the base package set.
|
||||
|
||||
## Adding a distro
|
||||
|
||||
1. `distros/<name>/distro.env` — `BASE_IMAGE`, `IMAGE`, `CA_RPM_URL`, `CA_RPM_SHA256`, `PACKAGES`.
|
||||
2. `distros/<name>/yum.repos.d/*.repo` — repository configuration for that distro.
|
||||
3. One `include` entry in each of `.woodpecker/{build,docker}.yaml`.
|
||||
|
||||
The `check-distros` pre-commit hook fails if step 1 or 3 is incomplete.
|
||||
|
||||
## CA bootstrap
|
||||
|
||||
`unkin-ca-certificates` lives in artifactapi, but the image cannot trust artifactapi
|
||||
over HTTPS until it is installed. The package is therefore fetched over plain HTTP and
|
||||
checked against `CA_RPM_SHA256` before `rpm -i`; everything after that uses HTTPS. The
|
||||
pinned hash is the `pkgid` checksum recorded for the file in the repo's own repodata
|
||||
(`repodata/repomd.xml` → `*-primary.xml.gz`).
|
||||
|
||||
## Make
|
||||
|
||||
make build # build every distro
|
||||
make pre-commit # uvx pre-commit run --all-files
|
||||
make build-alma9 # one distro
|
||||
make patch|minor|major
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Every distros/<name>/ needs a complete distro.env and an entry in every Woodpecker
|
||||
# matrix, or a newly added distro silently never gets built.
|
||||
set -uo pipefail
|
||||
|
||||
KEYS="BASE_IMAGE IMAGE CA_RPM_URL CA_RPM_SHA256 ESTATE_REPO PACKAGES"
|
||||
WORKFLOWS=(.woodpecker/build.yaml .woodpecker/docker.yaml)
|
||||
|
||||
fail=0
|
||||
for d in distros/*/; do
|
||||
n=$(basename "$d")
|
||||
for k in $KEYS; do
|
||||
grep -q "^${k}=" "${d}distro.env" || { echo "${d}distro.env: missing ${k}"; fail=1; }
|
||||
done
|
||||
for wf in "${WORKFLOWS[@]}"; do
|
||||
grep -q "DISTRO: ${n}\$" "$wf" || { echo "${wf}: distro ${n} missing from matrix"; fail=1; }
|
||||
done
|
||||
done
|
||||
|
||||
exit "$fail"
|
||||
@@ -0,0 +1,18 @@
|
||||
# alma9 — AlmaLinux 9
|
||||
# Pulled through the artifactapi dockerhub remote: a buildkit FROM does its own pull
|
||||
# and ignores the nodes' containerd mirror. The library/ prefix is required — the
|
||||
# remote allowlists ^library/almalinux, so dockerhub/almalinux:9 returns 403.
|
||||
BASE_IMAGE="artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/almalinux:9"
|
||||
IMAGE="almalinux9"
|
||||
|
||||
# Bootstrap of the internal CA. The image cannot trust artifactapi over HTTPS until
|
||||
# this package is installed, so it is fetched over plain HTTP and verified against a
|
||||
# pinned sha256 before rpm -i. The hash is the pkgid checksum recorded for this file
|
||||
# in the rpm-vendor-el9 repodata (repodata/repomd.xml -> *-primary.xml.gz).
|
||||
CA_RPM_URL="http://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-vendor-el9/Packages/unkin-ca-certificates-2025.7.13-1.el9.x86_64.rpm"
|
||||
CA_RPM_SHA256="c12fb81ea639a92d19506e07e88df290635b15e175b1f8c063d4e8a2d86bab6e"
|
||||
|
||||
# Estate local repo used to prove HTTPS trust and dnf reachability.
|
||||
ESTATE_REPO="rpm-vendor-el9"
|
||||
|
||||
PACKAGES="git jq make python3.11 python3.11-pip python3.12 python3.12-pip uv wget"
|
||||
@@ -0,0 +1,27 @@
|
||||
[baseos]
|
||||
name=baseos repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/BaseOS/$basearch/os/
|
||||
gpgkey=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/BaseOS/$basearch/os/RPM-GPG-KEY-AlmaLinux-9
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
|
||||
[appstream]
|
||||
name=appstream repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/AppStream/$basearch/os/
|
||||
gpgkey=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/AppStream/$basearch/os/RPM-GPG-KEY-AlmaLinux-9
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
|
||||
[extras]
|
||||
name=extras repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/extras/$basearch/os/
|
||||
gpgkey=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/extras/$basearch/os/RPM-GPG-KEY-AlmaLinux-9
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
|
||||
[crb]
|
||||
name=crb repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/CRB/$basearch/os/
|
||||
gpgkey=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/almalinux/$releasever/CRB/$basearch/os/RPM-GPG-KEY-AlmaLinux-9
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
@@ -0,0 +1,6 @@
|
||||
[epel]
|
||||
name=epel repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/epel/$releasever/Everything/$basearch
|
||||
gpgkey=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/epel/RPM-GPG-KEY-EPEL-$releasever
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
@@ -0,0 +1,27 @@
|
||||
[rpm-internal-el9]
|
||||
name=rpm-internal-el9 repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-internal-el9/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
metadata_expire=60
|
||||
|
||||
[rpm-vendor-el9]
|
||||
name=rpm-vendor-el9 repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-vendor-el9/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
metadata_expire=60
|
||||
|
||||
[rpm-internal]
|
||||
name=rpm-internal repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-internal/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
metadata_expire=60
|
||||
|
||||
[rpm-vendor]
|
||||
name=rpm-vendor repository
|
||||
baseurl=https://artifactapi.k8s.syd1.au.unkin.net/api/v1/local/rpm-vendor/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
metadata_expire=60
|
||||
Reference in New Issue
Block a user