#!/usr/bin/env bash # SilverMetal Linux — reproducibility gate. # # Builds the ISO twice from clean clones of HEAD and compares SHA256. # This is the M1.1 exit-criterion check; CI runs it on every push. # # Usage: # linux/build/scripts/verify-reproducibility.sh # COMMIT=abc1234 linux/build/scripts/verify-reproducibility.sh # specific SHA # # Exit codes: # 0 Both builds produced byte-identical ISOs # 1 Mismatch — diagnose-divergence.sh has been invoked # 2 Setup / clone error # 3 One of the builds failed before producing an ISO set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." && pwd)" COMMIT="${COMMIT:-$(git -C "${REPO_ROOT}" rev-parse HEAD)}" WORKROOT="${WORKROOT:-/tmp/silvermetal-repro-$$}" DIR_A="${WORKROOT}/build-a" DIR_B="${WORKROOT}/build-b" cleanup() { if [[ "${KEEP_BUILD_DIRS:-0}" != "1" ]]; then rm -rf "${WORKROOT}" else echo "verify: kept ${WORKROOT} for inspection" fi } trap cleanup EXIT mkdir -p "${DIR_A}" "${DIR_B}" clone_one() { local dest="$1" git clone --recurse-submodules "${REPO_ROOT}" "${dest}/repo" >/dev/null 2>&1 \ || { echo "verify: clone -> ${dest} failed" >&2; exit 2; } git -C "${dest}/repo" checkout --quiet "${COMMIT}" git -C "${dest}/repo" submodule update --init --recursive --quiet } build_one() { local dest="$1" BUILD_DIR="${dest}/out" "${dest}/repo/linux/build/scripts/build.sh" \ || { echo "verify: build in ${dest} failed" >&2; exit 3; } } echo "verify: cloning two copies at ${COMMIT}" clone_one "${DIR_A}" clone_one "${DIR_B}" echo "verify: building copy A" build_one "${DIR_A}" echo "verify: building copy B" build_one "${DIR_B}" ISO_A="$(ls "${DIR_A}/out"/*.iso 2>/dev/null | head -n1 || true)" ISO_B="$(ls "${DIR_B}/out"/*.iso 2>/dev/null | head -n1 || true)" if [[ -z "${ISO_A}" || -z "${ISO_B}" ]]; then echo "verify: missing ISO (A=${ISO_A:-} B=${ISO_B:-})" >&2 exit 3 fi HASH_A="$(sha256sum "${ISO_A}" | cut -d' ' -f1)" HASH_B="$(sha256sum "${ISO_B}" | cut -d' ' -f1)" echo "verify: A = ${HASH_A} ${ISO_A}" echo "verify: B = ${HASH_B} ${ISO_B}" if [[ "${HASH_A}" == "${HASH_B}" ]]; then echo "verify: PASS — reproducible at ${COMMIT}" exit 0 fi echo "verify: FAIL — running diffoscope" KEEP_BUILD_DIRS=1 ISO_A="${ISO_A}" ISO_B="${ISO_B}" \ "${REPO_ROOT}/linux/build/scripts/diagnose-divergence.sh" \ || true exit 1