From 5c08c4852177c26786232a53df86d6082ffdbc50 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 8 Nov 2025 11:04:09 +0100 Subject: [PATCH 1/3] .github: trim down release tarballs Collect only the most relevant info for SBOM. The CycloneDX format seems to be what most tools are standardizing around, and they suggest saving manifest.csv and cpe.json files. This commit includes all *.csv files and drops sources and licenses for release builds, as decided in #1192 Fixes #1217 resolves #1192 Signed-off-by: Joachim Wiberg --- .github/workflows/build-release.yml | 19 ++++++++++++++++--- .github/workflows/release.yml | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 4b0e997a..334f64f2 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -1,3 +1,6 @@ +# Needed for make pkg-stats +# sudo apt install python3-aiohttp +--- name: Build Release on: @@ -75,7 +78,12 @@ jobs: - name: Generate SBOM from Build run: | + # Generate manifest files in CSV format for CycloneDX make legal-info + # Generate cpe.json for CycloneDX + make -s show-info > output/cpe.json + # Generate pkg-stats.{json,html} for humans + make pkg-stats - name: Build test specification run: | @@ -84,13 +92,18 @@ jobs: - name: Prepare Artifacts run: | cd output/ + + # Collect relevant files for SBOM and CPE info. for more info, see: + # https://github.com/CycloneDX/cyclonedx-buildroot + mkdir images/sbom + mv pkg-stats.* images/sbom/ + mv cpe.json images/sbom/ + mv legal-info/*.csv images/sbom/ + mv images ${{ steps.vars.outputs.dir }} ln -s ${{ steps.vars.outputs.dir }} images tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }} - mv legal-info legal-info-${{ matrix.target }}-${{ steps.vars.outputs.ver }} - tar cfz legal-info-${{ matrix.target }}-${{ steps.vars.outputs.ver }}.tar.gz legal-info-${{ matrix.target }}-${{ steps.vars.outputs.ver }} - - uses: actions/upload-artifact@v4 with: name: artifact-${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d9734393..7ded2bab 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -117,7 +117,7 @@ jobs: prerelease: ${{ steps.rel.outputs.pre }} makeLatest: ${{ steps.rel.outputs.latest }} discussionCategory: ${{ steps.rel.outputs.cat }} - bodyFile: release.md + bodyFile: release.md artifacts: "*.tar.gz*,*.qcow2*" - name: Summary From 7a6b1ea31144ea5a267004bb92245c5a83dd927c Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 8 Nov 2025 11:45:03 +0100 Subject: [PATCH 2/3] .github: only set latest tag on .0 releases Prevent patch releases from stealing the "latest" tag from newer minor versions. Only vXX.YY and vXX.YY.0 releases should be marked as latest. Fixes #1187 Signed-off-by: Joachim Wiberg --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ded2bab..8af13817 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,7 +75,7 @@ jobs: if echo $ver | grep -qE 'v[0-9.]+(-alpha|-beta|-rc)[0-9]*'; then echo "pre=true" >> $GITHUB_OUTPUT echo "latest=false" >> $GITHUB_OUTPUT - elif echo $ver | grep -qE '^v[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then + elif echo $ver | grep -qE '^v[0-9]+\.[0-9]+(\.0)?$'; then echo "pre=false" >> $GITHUB_OUTPUT echo "latest=true" >> $GITHUB_OUTPUT echo "cat=Releases" >> $GITHUB_OUTPUT From 94fa7ea21cfe99cfc06196421cda70d8c7fe3c15 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 8 Nov 2025 12:01:34 +0100 Subject: [PATCH 3/3] .github: drop rootfs.squashfs from release tarballs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release tarballs waste ~131MB per architecture by including both rootfs.itb and rootfs.squashfs, even though rootfs.itb already contains the squashfs (itb = 4096-byte header + squashfs). This change removes rootfs.squashfs from releases and provides two solutions for users who need it: 1. utils/extract-squashfs.sh - Full-featured utility for extracting squashfs from release tarballs or .itb files. Includes validation and helpful error messages. 2. board/common/qemu/qemu.sh - Auto-extraction support. When running in initrd mode, automatically extracts rootfs.squashfs from rootfs.itb if missing. Zero user impact - ./qemu.sh just works! Space savings: ~262MB per release (2 architectures × 131MB) Fixes #858 Signed-off-by: Joachim Wiberg --- .github/workflows/build-release.yml | 4 ++ board/common/qemu/qemu.sh | 27 ++++++++ utils/extract-squashfs.sh | 103 ++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100755 utils/extract-squashfs.sh diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 334f64f2..85b729c1 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -100,6 +100,10 @@ jobs: mv cpe.json images/sbom/ mv legal-info/*.csv images/sbom/ + # Remove rootfs.squashfs from release (can be extracted from rootfs.itb) + # Saves ~131MB per architecture. See issue #858 + rm -f images/rootfs.squashfs + mv images ${{ steps.vars.outputs.dir }} ln -s ${{ steps.vars.outputs.dir }} images tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }} diff --git a/board/common/qemu/qemu.sh b/board/common/qemu/qemu.sh index 0de195da..d72d147b 100755 --- a/board/common/qemu/qemu.sh +++ b/board/common/qemu/qemu.sh @@ -313,8 +313,35 @@ gdb_args() echo -n "-gdb chardev:gdbqemu" } +extract_squashfs() +{ + # Extract rootfs.squashfs from rootfs.itb if missing + # The .itb file is rootfs.itbh (4096 bytes) + rootfs.squashfs + input="${1:-rootfs.itb}" + output="${2:-rootfs.squashfs}" + + [ -f "$input" ] || die "Cannot extract $output: $input not found" + + echo "Extracting $output from $input (skipping 4096-byte FIT header)..." + dd if="$input" of="$output" bs=4096 skip=1 2>/dev/null \ + || die "Failed to extract $output from $input" + + echo "Successfully created $output" +} + run_qemu() { + # Auto-extract rootfs.squashfs from rootfs.itb if needed for initrd mode + if [ "$CONFIG_QEMU_ROOTFS_INITRD" = "y" ]; then + if [ "$CONFIG_QEMU_ROOTFS" = "rootfs.squashfs" ] && [ ! -f "rootfs.squashfs" ]; then + if [ -f "rootfs.itb" ]; then + extract_squashfs "rootfs.itb" "rootfs.squashfs" + else + die "Missing rootfs.squashfs and cannot find rootfs.itb to extract it from" + fi + fi + fi + if [ "$CONFIG_QEMU_ROOTFS_VSCSI" = "y" ]; then if ! qemu-img check "qemu.qcow2"; then rm -f "qemu.qcow2" diff --git a/utils/extract-squashfs.sh b/utils/extract-squashfs.sh new file mode 100755 index 00000000..3dc55492 --- /dev/null +++ b/utils/extract-squashfs.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# +# Extract rootfs.squashfs from a release tarball's rootfs.itb file +# +# Usage: extract-squashfs.sh [output-file] +# + +set -e + +usage() { + cat < [output-file] + +Extract rootfs.squashfs from a release tarball or .itb file. + +Arguments: + Release tarball (*.tar.gz) or rootfs.itb file + [output-file] Output squashfs file (default: rootfs.squashfs) + +Examples: + # From release tarball + $(basename "$0") infix-x86_64-25.09.0.tar.gz + + # From .itb file directly + $(basename "$0") output/images/rootfs.itb + + # Custom output location + $(basename "$0") infix-x86_64-25.09.0.tar.gz /tmp/my-rootfs.squashfs + +The script skips the 4096-byte FIT header to extract the SquashFS image. +EOF +} + +die() { + echo "ERROR: $*" >&2 + exit 1 +} + +# Parse arguments +case "$1" in + -h|--help) + usage + exit 0 + ;; + "") + usage + exit 1 + ;; +esac + +input="$1" +output="${2:-rootfs.squashfs}" + +[ -f "$input" ] || die "File not found: $input" + +# Detect if input is a tarball or .itb file +case "$input" in + *.tar.gz) + echo "Extracting rootfs.itb from tarball..." + itb_file=$(tar -tzf "$input" | grep -m1 'rootfs\.itb$') \ + || die "No rootfs.itb found in tarball" + + echo "Found: $itb_file" + echo "Extracting SquashFS (skipping 4096-byte FIT header)..." + + tar -xzOf "$input" "$itb_file" | dd bs=4096 skip=1 of="$output" 2>/dev/null \ + || die "Failed to extract SquashFS" + ;; + *.itb) + echo "Extracting SquashFS from .itb file (skipping 4096-byte FIT header)..." + dd if="$input" of="$output" bs=4096 skip=1 2>/dev/null \ + || die "Failed to extract SquashFS" + ;; + *) + die "Unsupported file type. Expected *.tar.gz or *.itb" + ;; +esac + +# Verify output +if [ -f "$output" ]; then + size=$(stat --format=%s "$output" 2>/dev/null || stat -f%z "$output") + file_type=$(file "$output") + + # Try to format size nicely, fall back to bytes if numfmt not available + if command -v numfmt >/dev/null 2>&1; then + size_str=$(numfmt --to=iec-i --suffix=B "$size") + else + size_str="$size bytes" + fi + + echo "Success! Created: $output ($size_str)" + echo "Type: $file_type" + + # Quick sanity check for squashfs magic + if echo "$file_type" | grep -qi squashfs; then + echo "✓ Verified: Valid SquashFS filesystem" + else + echo "⚠ Warning: Output may not be a valid SquashFS image" + exit 1 + fi +else + die "Failed to create output file" +fi