Skip to content

flashbox-l1: document BuilderNet bottom-of-block in readme (#166) #55

flashbox-l1: document BuilderNet bottom-of-block in readme (#166)

flashbox-l1: document BuilderNet bottom-of-block in readme (#166) #55

Workflow file for this run

# GitHub Actions workflow for building mkosi images using Nix.
#
# Triggers on:
# - Pushes to main branch: Builds all images (flashbox-l1, flashbox-l2) in parallel
#
# - Manual dispatch: Allows specifying:
# - Branch to build from (default: main)
# - Images to build (default: flashbox-l1)
# - "all" → builds flashbox-l1 and flashbox-l2
# - "flashbox-l1" → builds only flashbox-l1
# - "flashbox-l2" → builds only flashbox-l2
# - "flashbox-l1,flashbox-l2" → builds both
# - Reproducibility test (default: false)
# - Adds a second build on a separate runner and compares SHA256 hashes
name: Build mkosi images
on:
push:
branches:
- main
workflow_dispatch:
inputs:
branch:
description: 'Branch to build'
required: false
default: 'main'
type: string
images:
description: 'Images to build (comma-separated: flashbox-l1,flashbox-l2 or "all")'
required: false
default: 'flashbox-l1'
type: string
reprotest:
description: 'Run reproducibility test (builds on 2 machines and compares hashes)'
required: false
default: false
type: boolean
jobs:
validate:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Validate images
id: set-matrix
shell: python3 {0}
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_IMAGES: ${{ inputs.images }}
run: |
import json
import os
import sys
VALID_IMAGES = ["flashbox-l1", "flashbox-l2"]
event = os.environ["EVENT_NAME"]
requested = os.environ.get("INPUT_IMAGES", "all").strip()
if event == "workflow_dispatch" and requested != "all":
images = [img.strip() for img in requested.split(",") if img.strip()]
invalid = [img for img in images if img not in VALID_IMAGES]
if invalid:
print(f"❌ Error: Invalid image(s): {', '.join(invalid)}")
print(f"Valid images are: {', '.join(VALID_IMAGES)}")
sys.exit(1)
else:
images = VALID_IMAGES
matrix = json.dumps(images)
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write(f"matrix={matrix}\n")
print(f"✓ Building images: {matrix}")
build:
needs: validate
strategy:
fail-fast: false
matrix:
image: ${{ fromJSON(needs.validate.outputs.matrix) }}
name: build ${{ matrix.image }} image
runs-on: warp-ubuntu-latest-x64-32x
steps:
- uses: actions/checkout@v5
with:
ref: ${{ inputs.branch || github.ref }}
- name: Install tools
run: |
sudo apt-get update && sudo apt-get install -y debian-archive-keyring
- name: Install Nix
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Enable user namespaces
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Build ${{ matrix.image }} image
run: |
umask 022
nix develop --command mkosi --force -I images/${{ matrix.image }}.conf --image-id=${{ matrix.image }}
- name: Fix permissions
run: |
sudo chown -R $(id -u):$(id -g) build/
- name: Show build artifacts
run: |
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 Image: ${{ matrix.image }}"
echo "🔖 Commit: ${{ github.sha }}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ -d "build" ]; then
echo ""
# Show only filename and size for matching files
ls -lh build/ | grep -E "${{ matrix.image }}" | awk '{print $9, "(" $5 ")"}'
else
echo "⚠️ Build directory not found"
fi
- name: Generate SHA256 checksums
run: |
sha256sum build/${{ matrix.image }}_*.efi | tee build/checksum.sha256
- name: Upload checksum for reprotest
if: inputs.reprotest == true
uses: actions/upload-artifact@v4
with:
name: checksum-${{ matrix.image }}-build-1
path: build/checksum.sha256
retention-days: 1
reprotest-build:
needs: validate
if: inputs.reprotest == true
strategy:
fail-fast: false
matrix:
image: ${{ fromJSON(needs.validate.outputs.matrix) }}
name: reprotest ${{ matrix.image }}
runs-on: warp-ubuntu-latest-x64-32x
steps:
- uses: actions/checkout@v5
with:
ref: ${{ inputs.branch || github.ref }}
- name: Install tools
run: |
sudo apt-get update && sudo apt-get install -y debian-archive-keyring
- name: Install Nix
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Enable user namespaces
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Build ${{ matrix.image }} image
run: |
umask 022
nix develop --command mkosi --force -I images/${{ matrix.image }}.conf --image-id=${{ matrix.image }}
sudo chown -R $(id -u):$(id -g) build/
- name: Generate SHA256 checksum
run: |
sha256sum build/${{ matrix.image }}_*.efi | tee build/checksum.sha256
- name: Upload checksum
uses: actions/upload-artifact@v4
with:
name: checksum-${{ matrix.image }}-build-2
path: build/checksum.sha256
retention-days: 1
reprotest-compare:
needs: [validate, build, reprotest-build]
if: inputs.reprotest == true
strategy:
fail-fast: false
matrix:
image: ${{ fromJSON(needs.validate.outputs.matrix) }}
name: reprotest compare ${{ matrix.image }}
runs-on: ubuntu-latest
steps:
- name: Download checksums
uses: actions/download-artifact@v4
with:
pattern: checksum-${{ matrix.image }}-*
path: checksums/
- name: Compare SHA256 hashes
run: |
echo "=== Reproducibility Check for ${{ matrix.image }} ==="
echo "Build 1 (all artifacts):"
cat checksums/checksum-${{ matrix.image }}-build-1/*.sha256
echo "Build 2 (EFI only):"
cat checksums/checksum-${{ matrix.image }}-build-2/checksum.sha256
# Extract only the .efi hash from build-1 to compare with build-2
hash1=$(grep '\.efi$' checksums/checksum-${{ matrix.image }}-build-1/*.sha256 | awk '{print $1}')
hash2=$(awk '{print $1}' checksums/checksum-${{ matrix.image }}-build-2/checksum.sha256)
echo ""
echo "EFI hash build-1: $hash1"
echo "EFI hash build-2: $hash2"
if [ "$hash1" = "$hash2" ]; then
echo "✅ SUCCESS: ${{ matrix.image }} images are identical (reproducible build verified)"
else
echo "❌ FAILURE: ${{ matrix.image }} images differ (reproducible build failed)"
exit 1
fi