Files
SilverMetal/linux/build/scripts/diagnose-divergence.sh
SysAdmin 4444dc11f3 feat(linux/build): scaffold reproducible ISO build pipeline (M1.1)
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>
2026-04-26 04:25:48 +01:00

62 lines
2.6 KiB
Bash
Executable File

#!/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}"