Container image monorepo. Every direct child directory with a Containerfile becomes an image at ghcr.io/makeitworkcloud/<dir>.
Work on a branch and open a PR; do not push directly to main or push any
branch unless explicitly requested. A successful push to main publishes
affected images to GHCR with latest and commit SHA tags, so treat merges as
production publication.
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 and terraform-libvirt-domain. The runner image pre-caches its hook environments; the shared OpenTofu workflow in shared-workflows fetches it at CI time. Secret scanning uses Gitleaks alongside detect-private-key.
Do not edit .pre-commit-config.yaml files in individual tfroot-* repos or the generated module config — they pull from here. Merge runner/toolchain updates and verify image publication before merging shared-workflow changes that require the new runner runtime.
Single workflow, three jobs, all on ubuntu-latest.
- checks — runs pre-commit, including full-tree Gitleaks scanning,
hadolint, and actionlint, for every
mainpush, pull request, and manual dispatch. - 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 — after checks pass, fan out over the detected image matrix:
- install buildah and podman
redhat-actions/buildah-build@v3with--squash- on
pushtomain, orworkflow_dispatchwithmode=build & push, push to GHCR with tagslatestand${{ github.sha }}
PRs and workflow_dispatch with mode=build 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