#!/bin/bash # build_builder_image.sh — build and publish the DP-007 CI builder image to the # Gitea container registry. # # TRACES: DP-007 | PR-004 # # Usage: # scripts/ci/build_builder_image.sh # build only, tag v1 # scripts/ci/build_builder_image.sh --push # build and push # scripts/ci/build_builder_image.sh --tag v2 --push # bump the pinned tag # scripts/ci/build_builder_image.sh --no-cache # force a clean rebuild # # The tag is the contract with CI. .gitea/workflows/unit-tests.yml names an # explicit tag in its `container:` block and never `latest`, so that rebuilding # the image cannot silently change what a previous green build meant. Bumping # the dependency set means bumping the tag AND editing the workflow — the two # edits landing in the same commit is the point, not an inconvenience. # # Registry auth: this script does not log in. Do it once, out of band: # docker login gitea.tourolle.paris # The CI host is already authenticated this way (its cached credentials in # ~/.docker/config.json are what the kpnpp-builder push relies on), so a # workflow that calls this script needs no secret plumbing. set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" REGISTRY="gitea.tourolle.paris" OWNER="dtourolle" IMAGE="sae-builder-cpu" DOCKERFILE="Dockerfile.builder-cpu" # The tag CI pins to today. Keep this in step with the `container.image` line in # .gitea/workflows/unit-tests.yml; the workflow asserts at run time that the # image it landed in reports this same version, so a drift shows up as a failed # job rather than as a build against the wrong toolchain. TAG="v1" PUSH=0 EXTRA_ARGS=() while [ $# -gt 0 ]; do case "$1" in --push) PUSH=1 ;; --tag) TAG="${2:?--tag needs a value}"; shift ;; --no-cache) EXTRA_ARGS+=(--no-cache) ;; -h|--help) sed -n '2,30p' "${BASH_SOURCE[0]}"; exit 0 ;; *) echo "error: unknown argument '$1'" >&2; exit 2 ;; esac shift done if [ "$TAG" = "latest" ]; then echo "error: refusing to build the tag 'latest'." >&2 echo "DP-007 requires CI to pin an immutable tag. A moving 'latest' means a" >&2 echo "rebuild retroactively changes what every earlier green build proved." >&2 exit 2 fi REF="${REGISTRY}/${OWNER}/${IMAGE}:${TAG}" # A second tag carrying the commit that produced the image. The workflow pins # the human-readable tag; this one is the audit trail — given any image you can # recover the Dockerfile that built it. SHA="$(git -C "$REPO_ROOT" rev-parse --short HEAD)" REF_SHA="${REGISTRY}/${OWNER}/${IMAGE}:${TAG}-${SHA}" # The Dockerfile COPYs nothing from the repository on purpose (see its closing # comment), so the build context is an empty directory rather than the repo # root. Sending ~1 GB of models, fixtures and experiment data to the daemon for # a build that reads none of it is pure latency. CONTEXT="$(mktemp -d)" trap 'rm -rf "$CONTEXT"' EXIT echo "=== building ${REF}" echo " dockerfile: ${REPO_ROOT}/${DOCKERFILE}" echo " context: (empty — the image embeds no repository content)" echo echo " Expect this to take a while: OpenCV 5 is compiled from source because" echo " no Debian release ships it. That cost is paid once per image, which is" echo " the entire reason DP-007 asks for a prebuilt image instead of" echo " installing dependencies inside each CI run." echo docker build \ "${EXTRA_ARGS[@]}" \ --build-arg "IMAGE_TAG=${TAG}" \ -f "${REPO_ROOT}/${DOCKERFILE}" \ -t "${REF}" \ -t "${REF_SHA}" \ "${CONTEXT}" echo echo "=== built" docker image inspect "${REF}" --format ' {{.RepoTags}} {{.Size}} bytes' docker run --rm "${REF}" sh -c 'echo " SAE_BUILDER=$SAE_BUILDER version=$SAE_BUILDER_VERSION ort=$SAE_ORT_VERSION opencv=$SAE_OPENCV_VERSION"' if [ "$PUSH" -eq 0 ]; then echo echo "Not pushed. Re-run with --push, or push by hand:" echo " docker push ${REF}" echo " docker push ${REF_SHA}" exit 0 fi echo echo "=== pushing" # No `latest` tag is pushed, by design. Publishing one invites a workflow to use # it, and DP-007 exists to prevent exactly that. docker push "${REF}" docker push "${REF_SHA}" echo echo "=== published ${REF}" echo "If this was a dependency-set change, bump the tag in" echo " .gitea/workflows/unit-tests.yml (container.image)" echo " scripts/ci/build_builder_image.sh (TAG, above)" echo "in the same commit, so no run can build against an image the repository" echo "does not describe."