#!/usr/bin/env bash # Build + push the derived termux builder image (toolchain pre-baked). # # The image tag hashes the full pinned base digest and Dockerfile bytes, # so either a lock bump or a toolchain recipe change produces a new image. # Pushes to GHCR with the repo's CI identity (GITHUB_TOKEN); idempotent -- # an existing identical tag is left alone. # # Usage: build_builder_image.sh (build + push if missing) set -euo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$HERE/../.." && pwd)" cd "$REPO_ROOT" DIGEST="$(python3 -c 'import sys; sys.path.insert(0, "."); from pm.lock import termux_docker_digest; print(termux_docker_digest())')" [ -n "$DIGEST" ] || { echo "termux-docker digest missing" >&2; exit 1; } BASE="termux/termux-docker@${DIGEST}" DOCKERFILE="scripts/termux/termux-builder.Dockerfile" SHORT="$(python3 -c ' import hashlib, pathlib, sys identity = sys.argv[1].encode() + b"\0" + pathlib.Path(sys.argv[2]).read_bytes() print(hashlib.sha256(identity).hexdigest()[:12]) ' "$BASE" "$DOCKERFILE")" REGISTRY="ghcr.io" # macOS still ships Bash 3.2, which predates ${value,,} case conversion. OWNER="$(printf '%s' "$GITHUB_REPOSITORY_OWNER" | tr '[:upper:]' '[:lower:]')" IMAGE="${REGISTRY}/${OWNER}/hermes-termux-builder:${SHORT}" if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then echo "builder image already published: $IMAGE" echo "$IMAGE" exit 0 fi echo "building $IMAGE from $BASE" docker build \ -f "$DOCKERFILE" \ --build-arg "BASE=${BASE}" \ -t "$IMAGE" \ scripts/termux \ || { echo "builder image build failed" >&2; exit 1; } # Smoke: the baked image must answer the runtime probes termux_build.sh # performs (clang + rustc + cargo + make) before we publish it. /bin/sh is # linked at RUNTIME inside the wheelhouse phase's --tmpfs /bin, so it is # deliberately absent from the baked image. docker run --rm --platform linux/arm64 "$IMAGE" \ /data/data/com.termux/files/usr/bin/bash -c ' export PREFIX=/data/data/com.termux/files/usr for tool in clang rustc cargo make; do command -v "$tool" >/dev/null 2>&1 || { echo "smoke FAIL: $tool"; exit 1; } done echo "builder image smoke OK" ' || { echo "builder image failed its smoke test" >&2; exit 1; } echo "$GITHUB_TOKEN" | docker login "$REGISTRY" -u "${GITHUB_ACTOR:-x}" --password-stdin docker push "$IMAGE" || { echo "builder image push failed" >&2; exit 1; } echo "published $IMAGE" echo "$IMAGE"