#!/bin/bash # build.sh — build the n-OS-tr live ISO set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WORKSPACE_ISO_DIR="$REPO_ROOT/iso" WORKSPACE_ISO="$WORKSPACE_ISO_DIR/live-image-amd64.hybrid.iso" BUILD_LOG="$WORKSPACE_ISO_DIR/build.log" ARTIFACTS_DIR="$WORKSPACE_ISO_DIR/config/includes.chroot_before_packages/live-artifacts" BUILD_BINARIES_SCRIPT="$REPO_ROOT/scripts/build-binaries.sh" ISSUE_TEMPLATE_PATH="$REPO_ROOT/iso/config/templates/issue.template" CLEAN_REQUESTED=0 # Fast iteration defaults: # - skip includes/ binary compilation # - skip re-config if existing lb config is present # - disallow network downloads during lb build ISO_ONLY=1 RECONFIGURE=0 OFFLINE=1 usage() { cat >&2 <<'EOF' usage: ./build.sh [options] Default (no flags): fastest iteration build - no includes/ binary rebuild - no lb reconfigure if already configured - offline build (no new downloads) options: --with-binaries rebuild includes/ artifacts before ISO build --reconfigure run lb config before build --online allow network downloads during lb build --clean remove iso/.build cache, chroot, binary outputs first --iso-only compatibility alias (same as default fast mode) -h, --help show this help EOF } while [[ "$#" -gt 0 ]]; do case "$1" in --clean) CLEAN_REQUESTED=1 shift ;; --iso-only) ISO_ONLY=1 shift ;; --with-binaries) ISO_ONLY=0 shift ;; --reconfigure) RECONFIGURE=1 shift ;; --online) OFFLINE=0 shift ;; -h|--help) usage exit 0 ;; *) echo "[build.sh] unsupported arguments: $*" >&2 usage exit 2 ;; esac done home_opts="$(findmnt -n -o OPTIONS /home 2>/dev/null || true)" if [[ "$home_opts" == *nodev* ]]; then NEED_BIND=1 else NEED_BIND=0 fi cleanup_artifacts() { echo "[build.sh] cleaning prior build artifacts in $WORKSPACE_ISO_DIR" sudo rm -rf \ "$WORKSPACE_ISO_DIR/.build" \ "$WORKSPACE_ISO_DIR/cache" \ "$WORKSPACE_ISO_DIR/chroot" \ "$WORKSPACE_ISO_DIR/binary" sudo rm -f \ "$WORKSPACE_ISO_DIR"/live-image-* \ "$WORKSPACE_ISO_DIR"/chroot.* \ "$WORKSPACE_ISO_DIR"/binary.modified_timestamps \ "$WORKSPACE_ISO_DIR"/build.log } stage_slice_bc_artifacts() { echo "[build.sh] staging artifacts via $BUILD_BINARIES_SCRIPT" if [[ ! -x "$BUILD_BINARIES_SCRIPT" ]]; then echo "[build.sh] ERROR: missing or non-executable $BUILD_BINARIES_SCRIPT" >&2 exit 1 fi "$BUILD_BINARIES_SCRIPT" } determine_build_version() { local latest_tag latest_tag="$(git -C "$REPO_ROOT" tag -l 'v*.*.*' | sort -V | tail -n 1 || true)" if [[ -z "$latest_tag" ]]; then latest_tag="v0.0.0" echo "[build.sh] warning: no semantic git tags found; defaulting to $latest_tag" fi local short_hash short_hash="$(git -C "$REPO_ROOT" rev-parse --short HEAD)" BUILD_VERSION_STRING="n-os-tr ${latest_tag} (${short_hash})" } stage_version_metadata() { determine_build_version local version_dir="$BUILD_DIR/config/includes.chroot/etc/n-os-tr" local version_file="$version_dir/version" local issue_file="$BUILD_DIR/config/includes.chroot/etc/issue" mkdir -p "$version_dir" printf '%s\n' "$BUILD_VERSION_STRING" > "$version_file" if [[ ! -f "$ISSUE_TEMPLATE_PATH" ]]; then echo "[build.sh] missing issue template: $ISSUE_TEMPLATE_PATH" >&2 exit 1 fi sed "s|__N_OS_TR_VERSION__|$BUILD_VERSION_STRING|g" "$ISSUE_TEMPLATE_PATH" > "$issue_file" echo "[build.sh] stamped version: $BUILD_VERSION_STRING" echo "[build.sh] wrote: $version_file" echo "[build.sh] rendered: $issue_file" } if [[ "$CLEAN_REQUESTED" -eq 1 ]]; then cleanup_artifacts fi SCRATCH="" BUILD_DIR="" CLEANUP() { if [[ -n "$SCRATCH" ]]; then if mountpoint -q "$SCRATCH"; then sudo umount -R "$SCRATCH" 2>/dev/null || sudo umount -l "$SCRATCH" || true fi rmdir "$SCRATCH" 2>/dev/null || true fi } trap CLEANUP EXIT if [[ "$NEED_BIND" -eq 1 ]]; then echo "[build.sh] /home has nodev mount option; building via bind-mounted scratch workspace" SCRATCH="/var/tmp/n-os-tr-build-$$-$(date +%s)" mkdir -p "$SCRATCH" sudo mount --bind "$REPO_ROOT" "$SCRATCH" echo "[build.sh] remounting scratch bind with dev to allow chroot /dev/null usage" sudo mount -o remount,bind,dev "$SCRATCH" scratch_opts="$(findmnt -n -o OPTIONS "$SCRATCH" 2>/dev/null || true)" if [[ "$scratch_opts" == *nodev* ]]; then echo "[build.sh] ERROR: scratch bind still has nodev after remount: $scratch_opts" >&2 echo "[build.sh] cannot safely run live-build chroot on a nodev mount" >&2 exit 1 fi BUILD_DIR="$SCRATCH/iso" else echo "[build.sh] /home is not nodev; building directly in workspace" BUILD_DIR="$WORKSPACE_ISO_DIR" fi if [[ ! -d "$BUILD_DIR" ]]; then echo "[build.sh] build directory missing: $BUILD_DIR" >&2 exit 1 fi stage_version_metadata if [[ "$ISO_ONLY" -eq 1 ]]; then echo "[build.sh] fast mode: skipping includes/ binary rebuild" else stage_slice_bc_artifacts fi cd "$BUILD_DIR" if [[ "$RECONFIGURE" -eq 1 || ! -f "$BUILD_DIR/config/bootstrap" ]]; then echo "[build.sh] running lb config" sudo "$REPO_ROOT/lb-wrapper.sh" config else echo "[build.sh] skipping lb config (use --reconfigure to force)" fi if [[ "$OFFLINE" -eq 1 ]]; then echo "[build.sh] offline mode: network downloads disabled (use --online to allow)" sudo env http_proxy=http://127.0.0.1:9 https_proxy=http://127.0.0.1:9 ftp_proxy=http://127.0.0.1:9 no_proxy=localhost,127.0.0.1 "$REPO_ROOT/lb-wrapper.sh" build 2>&1 | tee "$BUILD_LOG" else echo "[build.sh] online mode: network downloads allowed" sudo "$REPO_ROOT/lb-wrapper.sh" build 2>&1 | tee "$BUILD_LOG" fi if [[ ! -f "$WORKSPACE_ISO" ]]; then echo "[build.sh] build produced no ISO at $WORKSPACE_ISO; see $BUILD_LOG" >&2 exit 1 fi ls -lh "$WORKSPACE_ISO"