ci(cd): call the shared build-image script instead of inlining it (infra#309)
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped

A template is the highest-leverage copy of anything. This one carried its
own inline build step, so every generated repo was born with a private
fork of the build logic -- which is how rootless buildah reached a dozen
repos before infra#241, and why the fix then had to be rediscovered here
weeks after the app repos were done.

The step now calls .gitea/build-image.sh, a byte-identical copy of
mathias/infra's ci-templates/build-image.sh. Generated repos inherit the
script and the call; adding the new repo to infra's adopters.txt puts it
under the drift gate.

Invoked as `bash .gitea/build-image.sh` rather than relying on the exec
bit: files written through the Gitea API land 0644, and a template whose
CI depends on a file mode is a trap for every repo generated from it.
This commit is contained in:
2026-08-25 08:52:26 +00:00
parent cfd55aeedb
commit add5428e2f
+22 -34
View File
@@ -38,7 +38,7 @@ jobs:
# __PROJECT_NAME__/__MODULE_PATH__ are placeholders substituted only when # __PROJECT_NAME__/__MODULE_PATH__ are placeholders substituted only when
# a repo is generated from this template -- on the raw template repo # a repo is generated from this template -- on the raw template repo
# itself they're still literal, and `IMAGE: __PROJECT_NAME__` contains # itself they're still literal, and `IMAGE: __PROJECT_NAME__` contains
# uppercase letters, which buildah/Docker rejects outright ("repository # uppercase letters, which the registry rejects outright ("repository
# name must be lowercase"). Build/deploy can never succeed here; skip # name must be lowercase"). Build/deploy can never succeed here; skip
# them on this repo so its own CI reads green on what it can actually # them on this repo so its own CI reads green on what it can actually
# validate (the check job). # validate (the check job).
@@ -54,41 +54,29 @@ jobs:
SHA=$(git rev-parse --short HEAD) SHA=$(git rev-parse --short HEAD)
echo "sha-tag=${SHA}" >> "$GITHUB_OUTPUT" echo "sha-tag=${SHA}" >> "$GITHUB_OUTPUT"
# infra#241: buildctl, NOT buildah. Rootless buildah in gitea-runner's # infra#309: the implementation lives in .gitea/build-image.sh, a
# hardened securityContext (capabilities: drop [ALL], # byte-identical copy of mathias/infra's ci-templates/build-image.sh.
# allowPrivilegeEscalation: false) cannot remap the UID/GID range # Do not edit it here -- edit the canonical file, run `task ci:sync`,
# newuidmap/newgidmap need on a fresh base-image pull, and it has no OCI # and infra's drift gate will name any repo still carrying an old copy.
# runtime at all. buildctl talks to the host's buildkitd over a socket, so
# the privileged extraction happens in buildkitd on the host and never in
# this pod. Same pattern as mathias/infra's segment-embedder.yml.
# #
# This matters MORE in a template than anywhere else: every repo generated # This matters more in a template than anywhere else: every repo
# from here inherits its CI, so a buildah-based template manufactures new # generated from here inherits its CI, so a template that carries the
# instances of a bug that has already cost this estate several red builds. # build LOGIC manufactures a new copy of every bug in it. That is
# precisely how rootless buildah (infra#241) reached a dozen repos, and
# why the fix then had to be rediscovered here weeks later. A template
# that carries a CALL manufactures nothing.
#
# NEW REPOS: add yourself to mathias/infra's ci-templates/adopters.txt so
# the gate keeps this copy current. Until you do, the copy is unmanaged
# and will silently fall behind.
#
# `bash <script>` rather than executing it directly: files written via
# the Gitea API land 0644, and CI that depends on a file mode is a trap.
- name: Build and push to local registry - name: Build and push to local registry
run: | env:
set -e SHA_TAG: ${{ steps.meta.outputs.sha-tag }}
BUILDKIT_HOST="unix:///run/buildkit/buildkitd.sock" GIT_SHA: ${{ github.sha }}
REGISTRY="localhost:5000" run: bash .gitea/build-image.sh
REF="${REGISTRY}/${{ env.IMAGE }}:${{ steps.meta.outputs.sha-tag }}"
TAR_FILE="$(mktemp)"
trap 'rm -f "$TAR_FILE"' EXIT
buildctl --addr "$BUILDKIT_HOST" build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt label:org.opencontainers.image.revision="${{ github.sha }}" \
--output type=oci,dest="$TAR_FILE"
# buildctl has no registry-push equivalent to `buildah push`; skopeo
# copies the OCI archive up. Two copies because the buildah version
# tagged both :sha and :latest.
skopeo copy --dest-tls-verify=false \
oci-archive:"$TAR_FILE" docker://${REF}
skopeo copy --dest-tls-verify=false \
oci-archive:"$TAR_FILE" docker://${REGISTRY}/${{ env.IMAGE }}:latest
echo "✓ Image pushed to ${REF} and :latest"
deploy: deploy:
name: Deploy via GitOps name: Deploy via GitOps