#!/usr/bin/env bash # make-golden-bundle.sh # # Build the banger golden image from images/golden/Dockerfile and # package it as a .tar.zst bundle suitable for publishing to the # imagecat catalog. Does not upload — see publish-golden-image.sh. # # Pipeline: # docker build -> docker create -> docker export | banger internal make-bundle # # Usage: # scripts/make-golden-bundle.sh [--name ] [--kernel-ref ] \ # [--distro ] [--arch ] [--description "..."] \ # [--out ] [--size ] [--platform

] # # Defaults: # --name debian-bookworm # --kernel-ref generic-6.12 # --distro debian # --arch x86_64 # --platform linux/amd64 # --out /dist/-.tar.zst # # Environment overrides: # BANGER_BIN path to banger binary (default build/bin/banger) # BANGER_VSOCK_AGENT_BIN path to companion (default build/bin/banger-vsock-agent) set -euo pipefail log() { printf '[make-golden-bundle] %s\n' "$*" >&2; } die() { log "$*"; exit 1; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" DOCKERFILE="$REPO_ROOT/images/golden/Dockerfile" CONTEXT="$REPO_ROOT/images/golden" NAME="debian-bookworm" KERNEL_REF="generic-6.12" DISTRO="debian" ARCH="x86_64" DESCRIPTION="" OUT="" # 4G is a deliberate over-allocation for the golden image: it leaves # room for first-boot apt-installs of sshd on derived pulls and for # the user's own apt-installs during sandbox use. SIZE="4G" PLATFORM="linux/amd64" while [[ $# -gt 0 ]]; do case "$1" in --name) NAME="${2:-}"; shift 2;; --kernel-ref) KERNEL_REF="${2:-}"; shift 2;; --distro) DISTRO="${2:-}"; shift 2;; --arch) ARCH="${2:-}"; shift 2;; -d|--description) DESCRIPTION="${2:-}"; shift 2;; --out) OUT="${2:-}"; shift 2;; --size) SIZE="${2:-}"; shift 2;; --platform) PLATFORM="${2:-}"; shift 2;; -h|--help) sed -n '2,/^set -euo/p' "$0" | sed 's/^# \?//' | sed '$d' exit 0 ;; *) die "unknown option: $1";; esac done for tool in docker zstd sha256sum; do command -v "$tool" >/dev/null 2>&1 || die "missing required tool: $tool" done [[ -f "$DOCKERFILE" ]] || die "dockerfile missing: $DOCKERFILE" BANGER_BIN="${BANGER_BIN:-$REPO_ROOT/build/bin/banger}" [[ -x "$BANGER_BIN" ]] || die "banger binary not executable: $BANGER_BIN (run 'make build' or set BANGER_BIN)" VSOCK_AGENT="${BANGER_VSOCK_AGENT_BIN:-$REPO_ROOT/build/bin/banger-vsock-agent}" [[ -x "$VSOCK_AGENT" ]] || die "banger-vsock-agent not executable: $VSOCK_AGENT (run 'make build')" if [[ -z "$OUT" ]]; then OUT="$REPO_ROOT/dist/${NAME}-${ARCH}.tar.zst" fi mkdir -p "$(dirname "$OUT")" DOCKER_TAG="banger-golden:${NAME}" log "building $DOCKER_TAG (platform=$PLATFORM)" docker build --platform "$PLATFORM" -t "$DOCKER_TAG" -f "$DOCKERFILE" "$CONTEXT" log "creating docker container (not started)" CONTAINER_ID="$(docker create "$DOCKER_TAG")" cleanup() { docker rm -f "$CONTAINER_ID" >/dev/null 2>&1 || true; } trap cleanup EXIT log "piping container filesystem into banger internal make-bundle" SIZE_FLAG=() [[ -n "$SIZE" ]] && SIZE_FLAG=(--size "$SIZE") DESC_FLAG=() [[ -n "$DESCRIPTION" ]] && DESC_FLAG=(--description "$DESCRIPTION") KERNEL_REF_FLAG=() [[ -n "$KERNEL_REF" ]] && KERNEL_REF_FLAG=(--kernel-ref "$KERNEL_REF") export BANGER_VSOCK_AGENT_BIN="$VSOCK_AGENT" docker export "$CONTAINER_ID" | \ "$BANGER_BIN" internal make-bundle \ --rootfs-tar - \ --name "$NAME" \ --distro "$DISTRO" \ --arch "$ARCH" \ "${KERNEL_REF_FLAG[@]}" \ "${DESC_FLAG[@]}" \ "${SIZE_FLAG[@]}" \ --out "$OUT" SHA256="$(sha256sum "$OUT" | awk '{print $1}')" SIZE_BYTES="$(stat -c '%s' "$OUT")" HUMAN="$(numfmt --to=iec --suffix=B "$SIZE_BYTES" 2>/dev/null || echo "${SIZE_BYTES}B")" log "bundle: $OUT" log "sha256: $SHA256" log "size: $HUMAN ($SIZE_BYTES bytes)" printf '%s\n' "$OUT"