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>
141 lines
5.5 KiB
Bash
Executable File
141 lines
5.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SilverMetal Linux — ISO build wrapper.
|
|
#
|
|
# Runs the Kicksecure derivative-maker inside the pinned builder container
|
|
# with the reproducibility levers locked down. This script is the single
|
|
# entry point for both local developer builds and CI — there is no separate
|
|
# CI-only path. If you need to debug, run *this*, not lb directly.
|
|
#
|
|
# Usage:
|
|
# linux/build/scripts/build.sh # writes to linux/build/output/<commit>
|
|
# BUILD_DIR=/tmp/build-a linux/build/scripts/build.sh # override output root
|
|
#
|
|
# Exit codes:
|
|
# 0 ISO produced and SHA256SUMS written
|
|
# 1 argument / environment error
|
|
# 2 derivative-maker submodule missing
|
|
# 3 build failed
|
|
# 4 post-build hash/manifest step failed
|
|
|
|
set -euo pipefail
|
|
|
|
# --- Locate repo root -------------------------------------------------------
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." && pwd)"
|
|
cd "${REPO_ROOT}"
|
|
|
|
# --- Pinned builder image ---------------------------------------------------
|
|
# Bumped together with linux/build/docker/Dockerfile.builder. The digest form
|
|
# is required; refusing the tag-only form is what stops a silent host drift.
|
|
BUILDER_IMAGE="${BUILDER_IMAGE:-docker-registry:5000/silvermetal-builder@sha256:REPLACE_WITH_PUSHED_DIGEST}"
|
|
|
|
if [[ "${BUILDER_IMAGE}" != *"@sha256:"* ]]; then
|
|
echo "build.sh: BUILDER_IMAGE must be pinned by digest, got: ${BUILDER_IMAGE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --- Sanity: submodule present ---------------------------------------------
|
|
if [[ ! -f "linux/build/derivative-maker/.git" && ! -d "linux/build/derivative-maker/.git" ]]; then
|
|
echo "build.sh: linux/build/derivative-maker submodule is not initialised." >&2
|
|
echo " Run: git submodule update --init --recursive" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# --- Compute SOURCE_DATE_EPOCH ---------------------------------------------
|
|
# Order of preference:
|
|
# 1. Explicit env var passed in (CI may set it for cross-runner consistency)
|
|
# 2. config/source-date-epoch.env override (offline rebuilds)
|
|
# 3. git commit timestamp of HEAD (default)
|
|
# shellcheck disable=SC1091
|
|
source linux/build/config/source-date-epoch.env || true
|
|
if [[ -z "${SOURCE_DATE_EPOCH:-}" ]]; then
|
|
if [[ -n "${SOURCE_DATE_EPOCH_OVERRIDE:-}" ]]; then
|
|
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH_OVERRIDE}"
|
|
echo "build.sh: using SOURCE_DATE_EPOCH override = ${SOURCE_DATE_EPOCH}"
|
|
else
|
|
SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)"
|
|
fi
|
|
fi
|
|
export SOURCE_DATE_EPOCH
|
|
|
|
# --- Pinned snapshot timestamp ---------------------------------------------
|
|
# shellcheck disable=SC1091
|
|
source linux/build/config/snapshot-pin.env
|
|
export SNAPSHOT_TIMESTAMP
|
|
|
|
# --- Resolve commit & output dir -------------------------------------------
|
|
COMMIT_SHA="$(git rev-parse --short=12 HEAD)"
|
|
BUILD_DIR="${BUILD_DIR:-${REPO_ROOT}/linux/build/output/${COMMIT_SHA}}"
|
|
mkdir -p "${BUILD_DIR}"
|
|
|
|
echo "build.sh: commit=${COMMIT_SHA} epoch=${SOURCE_DATE_EPOCH} snapshot=${SNAPSHOT_TIMESTAMP}"
|
|
echo "build.sh: output -> ${BUILD_DIR}"
|
|
|
|
# --- Run the build inside the container ------------------------------------
|
|
# --privileged is required because live-build mounts loop devices and chroots.
|
|
# --network=host lets the container reach snapshot.debian.org without us
|
|
# fighting CI proxy config; tighten if/when that becomes a concern.
|
|
docker run --rm --privileged \
|
|
--network=host \
|
|
-e SOURCE_DATE_EPOCH \
|
|
-e SNAPSHOT_TIMESTAMP \
|
|
-e LC_ALL=C.UTF-8 \
|
|
-e LANG=C.UTF-8 \
|
|
-e TZ=UTC \
|
|
-v "${REPO_ROOT}:/work:rw" \
|
|
-v "${BUILD_DIR}:/out:rw" \
|
|
-w /work \
|
|
"${BUILDER_IMAGE}" \
|
|
bash -euo pipefail -c '
|
|
# shellcheck disable=SC1091
|
|
source /work/linux/build/config/silvermetal-base.conf
|
|
|
|
cd /work/linux/build/derivative-maker
|
|
|
|
./derivative-maker \
|
|
--build \
|
|
--target "${DERIVATIVE_BUILD_TARGET}" \
|
|
--flavour "${DERIVATIVE_FLAVOUR}" \
|
|
--arch "${DERIVATIVE_TARGET_ARCH}" \
|
|
--dist "${DERIVATIVE_DIST}" \
|
|
--config /work/linux/build/config/silvermetal-base.conf
|
|
|
|
# derivative-maker writes into its own build/ dir; collect into /out.
|
|
# Exact upstream output paths can shift between tags — keep this
|
|
# tolerant. Anything matching *.iso under the tree is what we want.
|
|
find . -maxdepth 6 -type f -name "*.iso" -print0 \
|
|
| xargs -0 -I{} cp -av "{}" /out/
|
|
|
|
# Manifest of file metadata that lives inside the ISO. Useful when
|
|
# diagnosing reproducibility regressions without re-extracting.
|
|
find . -maxdepth 6 -type f -name "*.manifest" -print0 \
|
|
| xargs -0 -I{} cp -av "{}" /out/ 2>/dev/null || true
|
|
' || { echo "build.sh: derivative-maker failed"; exit 3; }
|
|
|
|
# --- Hash artefacts ---------------------------------------------------------
|
|
# Run hashing on the host (not in the container) so a busted container image
|
|
# can't tamper with the digests we publish.
|
|
shopt -s nullglob
|
|
ISO_FILES=("${BUILD_DIR}"/*.iso)
|
|
shopt -u nullglob
|
|
if (( ${#ISO_FILES[@]} == 0 )); then
|
|
echo "build.sh: no ISO produced in ${BUILD_DIR}" >&2
|
|
exit 4
|
|
fi
|
|
|
|
(
|
|
cd "${BUILD_DIR}"
|
|
sha256sum -- *.iso > SHA256SUMS
|
|
cp -- "${REPO_ROOT}/linux/build/config/snapshot-pin.env" snapshot-pin.env
|
|
{
|
|
echo "commit=${COMMIT_SHA}"
|
|
echo "source_date_epoch=${SOURCE_DATE_EPOCH}"
|
|
echo "snapshot_timestamp=${SNAPSHOT_TIMESTAMP}"
|
|
echo "builder_image=${BUILDER_IMAGE}"
|
|
echo "host_uname=$(uname -srm)"
|
|
} > BUILD_INFO
|
|
)
|
|
|
|
echo "build.sh: SHA256SUMS:"
|
|
cat "${BUILD_DIR}/SHA256SUMS"
|