name: Build RPi image # Yocto (kas) build of rpilinux-image for raspberrypi4-64. # # Runs on the dedicated host runner (label "yocto:host", Ryzen 9 box "ada"). # Everything persists in $YOCTO_HOME: extern/ (layer clones) + build/ (sstate) # survive between runs -> incremental builds after the first. # $YOCTO_HOME comes from the runner config (runner.envs.YOCTO_HOME = # /home/bl/yocto-build, on the 1.8T disk); falls back to $HOME/yocto-build. # # First build takes hours (poky fetch + full image) -> runner.timeout >= 8h. # # First build takes hours (poky fetch + full image) -> runner.timeout >= 8h. on: push: branches: [main] workflow_dispatch: # Never run two builds at once on the same (single) runner. concurrency: group: yocto-rpi-build cancel-in-progress: false permissions: contents: read jobs: build: runs-on: yocto timeout-minutes: 600 steps: - uses: builtin:checkout - name: Probe environment and host dependencies run: | echo "=== runner environment ===" uname -a [ -r /etc/os-release ] && . /etc/os-release && echo "$PRETTY_NAME" echo "HOME=$HOME workspace=$(pwd) nproc=$(nproc)" df -h "$HOME" | tail -1 free -h 2>/dev/null | sed -n 2p || true command -v docker >/dev/null && docker info --format 'docker: {{.ServerVersion}}' 2>/dev/null || echo "no docker daemon" echo "=== dependency check ===" set -e missing="" for t in git python3 curl wget rsync gawk xz diffstat chrpath node npm; do command -v "$t" >/dev/null 2>&1 || missing="$missing $t" done if [ -n "$missing" ]; then echo "::error::Missing host tools:$missing" echo "Install on the runner host, e.g.:" echo ' sudo apt-get install -y --no-install-recommends build-essential \ bison flex chrpath curl diffstat file gawk git libpython3-dev libssl-dev \ make python3 python3-venv python3-pip python3-dev rsync swig unzip \ wget xz-utils zstd bzip2 nodejs npm' exit 1 fi - name: Set up kas (persistent venv) run: | set -e export YOCTO_HOME="${YOCTO_HOME:-$HOME/yocto-build}" mkdir -p "$YOCTO_HOME" [ -d "$YOCTO_HOME/venv" ] || python3 -m venv "$YOCTO_HOME/venv" "$YOCTO_HOME/venv/bin/pip" -q install -U kas "$YOCTO_HOME/venv/bin/kas" --version - name: Sync to persistent build dir and build run: | set -euo pipefail export YOCTO_HOME="${YOCTO_HOME:-$HOME/yocto-build}" SRC="$(pwd)" DST="$YOCTO_HOME/yocto_rpi" # Safety: builtin:checkout cleans ignored files (build/, extern/), # so the build tree must NOT be the ephemeral workspace. if [ "$SRC" = "$DST" ]; then echo "::error::workspace == persistent dir ($SRC); keep the runner WorkingDirectory outside YOCTO_HOME" exit 1 fi echo "syncing $SRC -> $DST" mkdir -p "$DST" # .git is copied (kas expects a git repo); extern/ and build/ exist # only in DST and are excluded, so --delete cannot touch them. rsync -a --delete --exclude /build/ --exclude /extern/ ./ "$DST/" cd "$DST" git config --global --add safe.directory "$DST" || true "$YOCTO_HOME/venv/bin/kas" build - name: Collect images run: | set -euo pipefail export YOCTO_HOME="${YOCTO_HOME:-$HOME/yocto-build}" WS="$(pwd)" # workspace; upload-artifact's path is relative to it cd "$YOCTO_HOME/yocto_rpi" IMG_DIR="$(find build -type d -path '*/tmp/deploy/images/raspberrypi4-64' | head -1)" if [ -z "$IMG_DIR" ]; then echo "::error::no deploy dir found under build/" exit 1 fi echo "images in: $IMG_DIR" mkdir -p "$WS/dist" shopt -s nullglob # only the timestamped canonical names - the short "...rootfs.wic.bz2" # entries are hardlinks to the same inode (would double the upload) FILES=("$IMG_DIR"/rpilinux-image-*.rootfs-[0-9]*.wic.bz2 "$IMG_DIR"/rpilinux-image-*.rootfs-[0-9]*.wic.bmap) if [ ${#FILES[@]} -eq 0 ]; then echo "::error::no flashable .wic image found in $IMG_DIR" exit 1 fi cp -v "${FILES[@]}" "$WS/dist/" ( cd "$WS/dist" && sha256sum * > SHA256SUMS ) ls -lh "$WS/dist" SUMMARY="${GITEA_STEP_SUMMARY:-${GITHUB_STEP_SUMMARY:-}}" if [ -n "$SUMMARY" ]; then { echo "## RPi4 image built" echo echo "| file | sha256 |" echo "|---|---|" ( cd "$WS/dist" && while read -r sum f; do echo "| \`$f\` | \`${sum:0:16}\` |"; done < SHA256SUMS ) echo echo "Flash: \`bzcat | sudo dd of=/dev/sdX bs=4M status=progress\`" echo echo "Build tree (incremental) on runner host: \`$YOCTO_HOME/yocto_rpi\`" } >> "$SUMMARY" fi - name: Upload images uses: actions/upload-artifact@v4 with: name: rpilinux-image-rpi4 path: dist/ retention-days: 14