Container image monorepo. Every subdirectory with a Containerfile becomes an image at ghcr.io/makeitworkcloud/<dir>.
Agents are authorized to push directly to main in this repository.
tfroot-runner/— gha-runner-scale-set runner image layered onghcr.io/actions/actions-runner. Carries kubectl, kustomize, sops, ansible-core, openssh, pre-commit, OpenTofu, tflint, terraform-docs, infracost, checkov, hcledit, tfupdate, yq, jq.gh-cli/— Alpine +ghfor short-lived automation Jobs (e.g., the ArgoCD postsync token sync).
tfroot-runner/pre-commit-config.yaml is the source of truth for pre-commit hooks across every tfroot-* repo. The runner image pre-caches its hook environments; the shared OpenTofu workflow in shared-workflows fetches it at CI time.
Do not edit .pre-commit-config.yaml files in individual tfroot-* repos — they pull from here.
Single workflow, two jobs, both on ubuntu-latest.
- detect — enumerates which images to build:
workflow_dispatchwithimageinput → just that oneworkflow_dispatchwith no input → all images (make list-images-json)- push/PR → only directories changed since the previous commit (
make changed-images)
- build — fan-out matrix over the detected list:
- install buildah, podman, hadolint
- run pre-commit (with
SKIP=no-commit-to-branchso the hook doesn't block CI) redhat-actions/buildah-build@v2with--squash- on
pushtomainorworkflow_dispatch, push to GHCR with tagslatestand${{ github.sha }}
PRs build but do not push.
make list-images— newline-separated list of directories with aContainerfilemake list-images-json— same as a JSON arraymake changed-images— JSON array of directories that changed in the previous commit
These targets are the contract the detect job depends on.
mkdir <name>and add aContainerfile- Open a PR — confirm the build matrix picks up the new directory
- Merge — image publishes at
ghcr.io/makeitworkcloud/<name>:latest
Workloads pull directly from ghcr.io/makeitworkcloud/<image>:latest (or :<sha> for pinned references). The k3s nodes have anonymous pull access to public GHCR packages; private packages need a pull secret in the consuming namespace.
- Transient SSL/network failures while downloading toolchain binaries (OpenTofu, hadolint) can break the build. Re-run the workflow.
--squashon the buildah build means each image is one big layer — fine for our scale, but expect full rebuilds when any layer-affecting input changes.
shared-workflows— reusable GitHub Actions workflows that consume thetfroot-runnerimagetfroot-aws,tfroot-cloudflare,tfroot-github,tfroot-libvirt— IaC roots that run on thetfroot-runnerimage viashared-workflowskustomize-cluster— runsgh-cliin a postsync Job to sync the cluster SA token to GitHub Actions secrets