From 3bca821d3e2944a20b62f126b0eb000e3571dc57 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Wed, 29 Apr 2026 10:58:26 +0300 Subject: [PATCH] Add auto fast-path ISO rebuild via squashfs surgery When only light files changed since the last full lb build (Go source, overlay scripts/configs), the build is now automatically done in ~5-8 min instead of 30+ min: - unsquashfs existing squashfs from prior build - rsync overlay-stage on top - mksquashfs repack (zstd, same block size) - xorriso ISO repack with -boot_image any replay (preserves EFI/MBR hybrid) Heavy changes (VERSIONS, package-lists, hooks, archives, Dockerfile, auto/config) still trigger a full lb build. Tracking is via a marker file (.bee-full-build-marker) written after each successful full build. No change to build-in-container.sh or the full build path. Co-Authored-By: Claude Sonnet 4.6 --- iso/builder/build.sh | 82 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/iso/builder/build.sh b/iso/builder/build.sh index 03c571a..d28dcb1 100755 --- a/iso/builder/build.sh +++ b/iso/builder/build.sh @@ -848,6 +848,72 @@ reset_live_build_stage() { done } +# Marker written after every successful full lb build for this variant +FULL_BUILD_MARKER="${BUILD_WORK_DIR}/.bee-full-build-marker" + +# Returns 0 if full lb build is needed, 1 if fast-path is safe. +# Fast-path is safe when only light files changed since the last full build +# (Go source, overlay scripts/configs). Heavy changes (VERSIONS, package lists, +# hooks, archives, Dockerfile, auto/config) require a full lb build. +needs_full_build() { + [ -f "${FULL_BUILD_MARKER}" ] || return 0 + [ -f "${BUILD_WORK_DIR}/binary/live/filesystem.squashfs" ] || return 0 + [ -f "${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso" ] || return 0 + + _heavy=$(find \ + "${BUILDER_DIR}/VERSIONS" \ + "${BUILDER_DIR}/auto/config" \ + "${BUILDER_DIR}/Dockerfile" \ + "${BUILDER_DIR}/config/package-lists" \ + "${BUILDER_DIR}/config/hooks" \ + "${BUILDER_DIR}/config/archives" \ + -newer "${FULL_BUILD_MARKER}" 2>/dev/null | head -1) + + if [ -n "$_heavy" ]; then + echo "=== full build required: heavy config changed: $(basename "$_heavy") ===" + return 0 + fi + + return 1 +} + +# Fast-path: unsquash existing filesystem, rsync overlay on top, repack. +# Requires ~10 GB free in BEE_CACHE_DIR for the unpacked squashfs. +fast_path_repack_squashfs() { + _sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs" + _tmp="${BEE_CACHE_DIR}/fast-unsquash-${BUILD_VARIANT}" + echo "=== fast-path: unsquash ($(du -sh "$_sq" | cut -f1) compressed) ===" + rm -rf "$_tmp" + unsquashfs -d "$_tmp" "$_sq" + echo "=== fast-path: syncing overlay stage ===" + rsync -a --checksum "${OVERLAY_STAGE_DIR}/" "$_tmp/" + echo "=== fast-path: repacking squashfs ===" + _sq_new="${_sq}.new" + rm -f "$_sq_new" + mksquashfs "$_tmp" "$_sq_new" -comp zstd -b 1048576 -noappend -no-progress + mv "$_sq_new" "$_sq" + rm -rf "$_tmp" + echo "=== fast-path: squashfs repacked ($(du -sh "$_sq" | cut -f1)) ===" +} + +# Fast-path: rebuild ISO by replacing only live/filesystem.squashfs via xorriso. +# Boot structure (El Torito, EFI, MBR hybrid) is replayed from the prior ISO. +fast_path_rebuild_iso() { + _sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs" + _prior="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso" + _new="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso.new" + echo "=== fast-path: rebuilding ISO with xorriso ===" + rm -f "$_new" + xorriso \ + -indev "$_prior" \ + -outdev "$_new" \ + -map "$_sq" /live/filesystem.squashfs \ + -boot_image any replay \ + -commit + mv "$_new" "$_prior" + echo "=== fast-path: ISO rebuilt ===" +} + recover_iso_memtest() { lb_dir="$1" iso_path="$2" @@ -1487,6 +1553,21 @@ if [ -f "${LB_INCLUDES}/root/.ssh/authorized_keys" ]; then chmod 600 "${LB_INCLUDES}/root/.ssh/authorized_keys" fi +# --- auto fast-path: squashfs surgery if only light files changed --- +if ! needs_full_build; then + echo "=== fast-path build (no heavy config changes since last full build) ===" + fast_path_repack_squashfs + fast_path_rebuild_iso + ISO_RAW="${LB_DIR}/live-image-amd64.hybrid.iso" + validate_iso_live_boot_entries "$ISO_RAW" + validate_iso_nvidia_runtime "$ISO_RAW" + cp "$ISO_RAW" "$ISO_OUT" + echo "" + echo "=== done (${BUILD_VARIANT}, fast-path) ===" + echo "ISO: $ISO_OUT" + exit 0 +fi + # --- build ISO using live-build --- echo "" echo "=== building ISO (variant: ${BUILD_VARIANT}) ===" @@ -1535,6 +1616,7 @@ if [ -f "$ISO_RAW" ]; then validate_iso_live_boot_entries "$ISO_RAW" validate_iso_nvidia_runtime "$ISO_RAW" cp "$ISO_RAW" "$ISO_OUT" + touch "${FULL_BUILD_MARKER}" echo "" echo "=== done (${BUILD_VARIANT}) ===" echo "ISO: $ISO_OUT"