#!/usr/bin/env bash # SilverMetal Linux — reproducibility-failure diagnostic. # # Invoked by verify-reproducibility.sh when two builds disagree, but also # safe to run by hand against any two ISOs: # # ISO_A=/path/a.iso ISO_B=/path/b.iso linux/build/scripts/diagnose-divergence.sh # # Produces a diffoscope report. The output is intentionally verbose — when # this script runs in anger we want everything we can get. set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." && pwd)" : "${ISO_A:?ISO_A must point to the first ISO}" : "${ISO_B:?ISO_B must point to the second ISO}" if [[ ! -f "${ISO_A}" || ! -f "${ISO_B}" ]]; then echo "diagnose: one of the ISOs is missing (A=${ISO_A} B=${ISO_B})" >&2 exit 1 fi REPORT_DIR="${REPORT_DIR:-${REPO_ROOT}/linux/build/output/_divergence-$(date -u +%Y%m%dT%H%M%SZ)}" mkdir -p "${REPORT_DIR}" echo "diagnose: writing report to ${REPORT_DIR}" # Quick wins first — these usually point straight at the culprit. sha256sum "${ISO_A}" "${ISO_B}" > "${REPORT_DIR}/sha256.txt" ls -la "${ISO_A}" "${ISO_B}" > "${REPORT_DIR}/sizes.txt" 2>&1 || true # diffoscope — html if available (richer), text always. if command -v diffoscope >/dev/null 2>&1; then diffoscope --max-report-size 100000000 \ --html "${REPORT_DIR}/diff.html" \ --text "${REPORT_DIR}/diff.txt" \ "${ISO_A}" "${ISO_B}" \ || true # non-zero exit just means "they differ"; that's why we're here elif command -v cmp >/dev/null 2>&1; then echo "diagnose: diffoscope not found, falling back to cmp" >&2 cmp -l "${ISO_A}" "${ISO_B}" > "${REPORT_DIR}/cmp.txt" || true fi # A first guess at the culprit, even when the diff is huge. { echo "## Likely-culprit checklist" echo "" echo "Walk these in order — most failures fall into the first two." echo "" echo " [ ] SOURCE_DATE_EPOCH was identical in both builds (compare BUILD_INFO files)" echo " [ ] snapshot.debian.org timestamp matched (compare snapshot-pin.env files)" echo " [ ] Same builder image digest (compare BUILD_INFO files)" echo " [ ] mksquashfs reproducibility flags survived (-no-exports -no-xattrs -reproducible)" echo " [ ] No build-id randomisation in kernel/initrd (look for differing .note.gnu.build-id)" echo " [ ] No host hostname/username leakage (grep for the runner host name)" echo " [ ] No locale drift (LC_ALL=C.UTF-8 enforced in container)" } > "${REPORT_DIR}/checklist.md" echo "diagnose: done. See ${REPORT_DIR}/checklist.md and ${REPORT_DIR}/diff.{html,txt}"