- Shell 50.6%
- Dockerfile 49.4%
|
All checks were successful
build tooling images / Resolve tag and image list (push) Successful in 1s
build tooling images / Build amd64 (push) Successful in 3m7s
build tooling images / Build arm64 (push) Successful in 25m50s
build tooling images / Publish multi-architecture manifests (push) Successful in 27s
|
||
|---|---|---|
| .forgejo/workflows | ||
| images | ||
| scripts | ||
| README.md | ||
ci-images
Prebuilt tooling images for the Forgejo Actions runners in the homelab cluster.
Before this repo existed, nearly every job started from a bare debian or
node image and ran apt-get install as its first step — the manifest
validation in homelab-gitops installed kubectl, ripgrep and yamllint on every
push, and every container build installed Buildah from scratch. That is the
same download, unpacked again, on every run.
These images ship that tooling instead. Jobs start working immediately.
Images
| Image | Base | Contains |
|---|---|---|
forgejo.chief-detektor.dev/andre/ci-base |
debian:trixie-slim |
kubectl (pinned to the cluster version), yamllint, ripgrep, shellcheck, jq, perl, curl, git |
forgejo.chief-detektor.dev/andre/ci-buildah |
data.forgejo.org/oci/node:22-trixie |
buildah, crun, netavark, fuse-overlayfs, jq, curl, git, Node (for actions/checkout) |
Both are multi-architecture manifest lists (amd64 and arm64), built
natively on a runner of each architecture — the workers are arm64 SBCs and the
control plane is amd64, and runs-on: docker may land on either.
ci-base deliberately has no Node runtime. The jobs that use it check out with
plain git rather than actions/checkout, so a Node runtime would be ~150 MB
that nothing executes. Jobs that want actions/checkout should use
ci-buildah, or keep their own base image.
Tags
:latest— moved by the most recent successful build. This is what the consuming workflows reference.:YYYYMMDD— the build date, for pinning or for rolling back a job to last week's tooling.
:latest is only updated once both architectures have been pushed, so a
job container can never be pulled for an architecture that does not exist yet.
When they are built
- Weekly, Mondays at 04:17 UTC. That is enough to pick up ordinary Debian security updates.
- Manually, via Actions → build tooling images → Run workflow. Use this
when a CVE advisory lands and waiting for Monday is not acceptable. The
dispatch form has an
imagesinput to rebuild onlybaseor onlybuildah. - On push to
mainwhenimages/**or the workflow itself changes.
Builds never reuse a layer cache — the entire point of a weekly rebuild is to
re-resolve the apt packages, and a cached apt-get install layer would defeat
that.
Consuming an image
jobs:
validate:
runs-on: docker
container:
image: forgejo.chief-detektor.dev/andre/ci-base:latest
steps:
- name: Validate
run: ./scripts/validate.sh
For container builds, ci-buildah ships
/usr/local/bin/configure-buildah-storage, which picks overlay +
fuse-overlayfs when the job container has /dev/fuse and falls back to vfs
otherwise. Call it once before the first buildah command:
- name: Configure Buildah storage
run: configure-buildah-storage
Registry access
No long-lived credential is stored in Forgejo Actions. The build exchanges the
run's Forgejo OIDC identity token for a short-lived Vault token and reads the
shared registry credential from secret/data/container-registry — the same
path and the same flow the rosenhammer-dev-relaunch container job uses.
The automatic per-run Actions token is not an option here: it cannot
authenticate against the package registry and fails with
invalid username/password.
This requires a Vault role named ci-images under the forgejo-actions JWT
auth mount, bound to this repository:
$ vault write auth/forgejo-actions/role/ci-images \
role_type=jwt \
user_claim=sub \
bound_audiences=vault \
bound_claims_type=string \
bound_claims=repository=andre/ci-images \
token_policies=container-registry-read \
token_ttl=10m \
token_max_ttl=10m
container-registry-read is the existing read-only policy on
secret/data/container-registry.
The packages must stay public so that the runner's Docker daemon can pull them as job containers without credentials — it has no registry login.
Bumping kubectl
images/base/Containerfile pins KUBECTL_VERSION so that kubectl kustomize
in CI behaves like the one in Argo CD's repo-server. Bump it in the same change
that upgrades the cluster.