Vendors Kicksecure derivative-maker as a pinned submodule (18.1.7.4), adds the wrapper + verify + diagnose scripts, the pinned builder image, and the reproducibility-gated Gitea Actions workflow. Base flavour only — no hardening overlay (that's M1.2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
2.4 KiB
Bash
Executable File
87 lines
2.4 KiB
Bash
Executable File
#!/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:-<none>} B=${ISO_B:-<none>})" >&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
|