#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" IMAGE_TAG="${IMAGE_TAG:-ours-rp-runtime-arm64:dev}" BUILDER_IMAGE="${BUILDER_IMAGE:-ours-rp-base-rust-amd64:1-bookworm}" RUNTIME_IMAGE="${RUNTIME_IMAGE:-ours-rp-base-debian-arm64:bookworm-slim}" OUT_DIR="${OUT_DIR:-$REPO_ROOT/target/arm64-docker}" DOCKERFILE="${DOCKERFILE:-$REPO_ROOT/docker/ours-rp-runtime.Dockerfile}" BUILDER_NAME="${BUILDER_NAME:-default}" INSTALL_BINFMT="${INSTALL_BINFMT:-1}" SAVE_IMAGE="${SAVE_IMAGE:-1}" LOAD_IMAGE="${LOAD_IMAGE:-1}" usage() { cat <<'USAGE' Usage: scripts/docker/build_arm64_runtime_image.sh [options] Options: --image Docker image tag (default: ours-rp-runtime-arm64:dev) --out-dir Directory for docker save tar.gz (default: target/arm64-docker) --dockerfile Dockerfile path --builder buildx builder name --no-binfmt Do not install binfmt/qemu --no-save Build image but do not docker save it --no-load Use buildx output tar instead of --load -h, --help Show this help USAGE } while [[ $# -gt 0 ]]; do case "$1" in --image) IMAGE_TAG="$2" shift 2 ;; --out-dir) OUT_DIR="$2" shift 2 ;; --dockerfile) DOCKERFILE="$2" shift 2 ;; --builder) BUILDER_NAME="$2" shift 2 ;; --no-binfmt) INSTALL_BINFMT=0 shift ;; --no-save) SAVE_IMAGE=0 shift ;; --no-load) LOAD_IMAGE=0 shift ;; -h|--help) usage exit 0 ;; *) echo "unknown option: $1" >&2 usage >&2 exit 2 ;; esac done require_command() { command -v "$1" >/dev/null 2>&1 || { echo "missing required command: $1" >&2 exit 2 } } safe_tag_name() { printf '%s' "$1" | tr '/:' '--' } require_command docker mkdir -p "$OUT_DIR" require_docker_image() { local image="$1" if ! docker image inspect "$image" >/dev/null 2>&1; then cat >&2 </dev/null 2>&1; then docker buildx create --name "$BUILDER_NAME" --driver docker-container --use >/dev/null else docker buildx use "$BUILDER_NAME" >/dev/null fi docker buildx inspect --bootstrap >/dev/null metadata_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build-metadata.json" tar_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").tar.gz" build_log="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build.log" echo "building linux/arm64 image: $IMAGE_TAG" echo "repo: $REPO_ROOT" echo "dockerfile: $DOCKERFILE" echo "builder_image: $BUILDER_IMAGE" echo "runtime_image: $RUNTIME_IMAGE" start_epoch="$(date +%s)" if [[ "$LOAD_IMAGE" == "1" ]]; then docker buildx build \ --platform linux/arm64 \ --builder "$BUILDER_NAME" \ --load \ --build-arg BUILDKIT_INLINE_CACHE=1 \ --build-arg "BUILDER_IMAGE=$BUILDER_IMAGE" \ --build-arg "RUNTIME_IMAGE=$RUNTIME_IMAGE" \ --metadata-file "$metadata_path" \ -t "$IMAGE_TAG" \ -f "$DOCKERFILE" \ "$REPO_ROOT" 2>&1 | tee "$build_log" else raw_tar_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").tar" docker buildx build \ --platform linux/arm64 \ --builder "$BUILDER_NAME" \ --output "type=docker,dest=$raw_tar_path" \ --build-arg BUILDKIT_INLINE_CACHE=1 \ --build-arg "BUILDER_IMAGE=$BUILDER_IMAGE" \ --build-arg "RUNTIME_IMAGE=$RUNTIME_IMAGE" \ --metadata-file "$metadata_path" \ -t "$IMAGE_TAG" \ -f "$DOCKERFILE" \ "$REPO_ROOT" 2>&1 | tee "$build_log" gzip -f "$raw_tar_path" tar_path="${raw_tar_path}.gz" fi elapsed_secs=$(( $(date +%s) - start_epoch )) if [[ "$SAVE_IMAGE" == "1" && "$LOAD_IMAGE" == "1" ]]; then echo "saving image to $tar_path" docker save "$IMAGE_TAG" | gzip -c > "$tar_path" fi { echo "image=$IMAGE_TAG" echo "platform=linux/arm64" echo "builder_image=$BUILDER_IMAGE" echo "runtime_image=$RUNTIME_IMAGE" echo "elapsed_secs=$elapsed_secs" echo "metadata=$metadata_path" echo "tar=$tar_path" echo "tar_size_bytes=$(wc -c < "$tar_path" 2>/dev/null || echo 0)" echo "git_commit=$(git -C "$REPO_ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)" echo "git_status_count=$(git -C "$REPO_ROOT" status --short 2>/dev/null | wc -l | tr -d ' ')" echo "built_at_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)" } > "$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build-summary.env" echo "build complete: elapsed=${elapsed_secs}s tar=$tar_path"