name: build-image description: >- Build a kas project in a persistent directory and expose the flashable images. The workspace is synced into the build dir instead of built in place, because checkout cleans ignored files (build/, extern/) and bitbake reuse depends on sstate-cache surviving between runs. inputs: project: description: kas configuration file, relative to the repository required: false default: .config.yaml machine: description: Machine the images are deployed for required: false default: raspberrypi4-64 image-prefix: description: Artifact filename prefix in the deploy dir required: false default: rpilinux-image skip-build: description: Set to true to only collect images from an existing build dir required: false default: "false" outputs: build-dir: description: Persistent project directory on the runner value: ${{ steps.locate.outputs.build-dir }} image-dir: description: Deploy dir bitbake wrote to value: ${{ steps.locate.outputs.image-dir }} images: description: Newline separated artifact filenames value: ${{ steps.collect.outputs.images }} runs: using: composite steps: - name: Sync workspace into persistent build dir if: ${{ inputs.skip-build != 'true' }} shell: bash run: | set -euo pipefail SRC="$(pwd)" DST="${YOCTO_HOME:-$HOME/yocto-build}/$(basename "$GITHUB_REPOSITORY")" # checkout deletes ignored files, so the build tree must live elsewhere if [ "$SRC" = "$DST" ]; then echo "::error::workspace == build dir ($SRC); point YOCTO_HOME somewhere else" exit 1 fi echo "syncing $SRC -> $DST" mkdir -p "$DST" # .git stays (kas requires a repo); extern/ + build/ only exist in DST, # so --delete cannot reach them rsync -a --delete --exclude /build/ --exclude /extern/ ./ "$DST/" - name: kas build if: ${{ inputs.skip-build != 'true' }} shell: bash run: | set -euo pipefail cd "${YOCTO_HOME:-$HOME/yocto-build}/$(basename "$GITHUB_REPOSITORY")" git config --global --add safe.directory "$PWD" || true "${YOCTO_HOME:-$HOME/yocto-build}/venv/bin/kas" build - name: Locate deploy dir id: locate shell: bash run: | set -euo pipefail BUILD_DIR="${YOCTO_HOME:-$HOME/yocto-build}/$(basename "$GITHUB_REPOSITORY")" IMAGE_DIR="$(find "$BUILD_DIR/build" -type d -path "*/tmp/deploy/images/${{ inputs.machine }}" | head -1)" if [ -z "$IMAGE_DIR" ]; then echo "::error::no deploy dir for ${{ inputs.machine }} under $BUILD_DIR/build" exit 1 fi echo "build-dir=$BUILD_DIR" >> "$GITHUB_OUTPUT" echo "image-dir=$IMAGE_DIR" >> "$GITHUB_OUTPUT" - name: Collect artifacts id: collect shell: bash run: | set -euo pipefail IMAGE_DIR="${{ steps.locate.outputs.image-dir }}" shopt -s nullglob # only the timestamped names: the short ones are hardlinks to the same # inode and would upload every image twice FILES=("${IMAGE_DIR}/${{ inputs.image-prefix }}."*.rootfs-[0-9]*.wic.* \ "${IMAGE_DIR}/${{ inputs.image-prefix }}-*.rootfs-[0-9]*.wic.*") if [ "${#FILES[@]}" -eq 0 ]; then echo "::error::no flashable .wic image for ${{ inputs.machine }} in $IMAGE_DIR" exit 1 fi mkdir -p dist cp -v "${FILES[@]}" dist/ ( cd dist && sha256sum * > SHA256SUMS ) ls -lh dist printf 'images=%s\n' "$(ls dist | tr '\n' ' ')" >> "$GITHUB_OUTPUT" - name: Summarise shell: bash run: | set -euo pipefail SUMMARY="${GITHUB_STEP_SUMMARY:-}" [ -n "$SUMMARY" ] || exit 0 { echo "## ${{ inputs.image-prefix }} for ${{ inputs.machine }}" echo echo "| artifact | sha256 |" echo "| --- | --- |" ( cd dist && while read -r sum file; do [ "$file" = SHA256SUMS ] || echo "| \`$file\` | \`${sum:0:16}\` |" done < SHA256SUMS ) echo echo "Flash with \`bzcat | sudo dd of=/dev/sdX bs=4M status=progress\`." echo echo "Incremental build tree: \`${{ steps.locate.outputs.build-dir }}\`" } >> "$SUMMARY"