diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 872d8dc..65cde63 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -139,6 +139,11 @@ jobs: echo '```' ls -lh dist/ echo '```' + echo "disk after build:" + echo '```' + df -h / + du -sh build/obj-${{ matrix.target }} build/linux 2>/dev/null || true + echo '```' } >> "$GITHUB_STEP_SUMMARY" - uses: actions/upload-artifact@v4 @@ -162,18 +167,34 @@ jobs: env: GH_TOKEN: ${{ github.token }} TAG: ${{ needs.prepare.outputs.release_tag }} + env: + KERNEL_REF: ${{ needs.prepare.outputs.kernel_ref }} + KERNEL_SHA: ${{ needs.prepare.outputs.kernel_sha }} run: | ls -lh dist/ - if ! gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then - gh release create "$TAG" --repo "$GITHUB_REPOSITORY" \ - --title "$TAG" \ - --notes "PREEMPT_RT kernel packages built from \`${{ needs.prepare.outputs.kernel_ref }}\` (raspberrypi/linux \`${{ needs.prepare.outputs.kernel_sha }}\`). - Install on the Pi with: - \`\`\` - sudo dpkg -i linux-image-*.deb + + # Written to a file: a multi-line --notes argument means shell quoting + # rules apply to markdown backticks, and this step only ever runs after + # a successful build, so a quoting slip costs a full build to discover. + cat > notes.md <<'NOTES' + PREEMPT_RT kernel packages for Raspberry Pi 4 and 5. + + Install on the Pi: + + ```sh + sudo dpkg -i linux-image-*.deb linux-headers-*.deb sudo ./rpi-boot-install.sh sudo reboot - \`\`\` - \`-v8-rt\` = Pi 4 (BCM2711), \`-v8-16k-rt\` = Pi 5 (BCM2712)." + ``` + + `-v8-rt` = Pi 4 (BCM2711), `-v8-16k-rt` = Pi 5 (BCM2712). + NOTES + printf '\nBuilt from `%s` (raspberrypi/linux `%s`).\n' "$KERNEL_REF" "$KERNEL_SHA" >> notes.md + + if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" --notes-file notes.md + else + gh release create "$TAG" --repo "$GITHUB_REPOSITORY" \ + --title "$TAG" --notes-file notes.md fi gh release upload "$TAG" --repo "$GITHUB_REPOSITORY" --clobber dist/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28ee635..20676fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sudo apt-get update sudo apt-get install -y --no-install-recommends shellcheck } - shellcheck --version | head -2 + shellcheck --version shellcheck scripts/*.sh packaging/*.sh - name: workflows parse diff --git a/scripts/build.sh b/scripts/build.sh index af2bd13..73eb8f9 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -129,7 +129,7 @@ if [ ${#missing[@]} -gt 0 ]; then fi # CONFIG_DEBUG_INFO_BTF requires pahole >= 1.21 (DWARF 5). pahole_version="$(pahole --version | tr -dc '0-9.')" -if [ "$(printf '%s\n1.21\n' "$pahole_version" | sort -V | head -1)" != "1.21" ]; then +if [ "$(printf '%s\n1.21\n' "$pahole_version" | sort -V | sed -n 1p)" != "1.21" ]; then echo "error: pahole $pahole_version is too old for CONFIG_DEBUG_INFO_BTF (need >= 1.21)" >&2 exit 1 fi diff --git a/scripts/resolve-kernel-ref.sh b/scripts/resolve-kernel-ref.sh index f65a67d..3f1d060 100755 --- a/scripts/resolve-kernel-ref.sh +++ b/scripts/resolve-kernel-ref.sh @@ -61,9 +61,20 @@ esac [ -z "$extra" ] || die "$BAD" BRANCH="rpi-$MAJ.$MIN.y" +# Reads from a file or a here-string, never from a pipe, and reads its input to +# the end. An awk that exits at EXTRAVERSION closes the pipe while curl or git +# is still writing the ~70 KB Makefile; the writer then fails (curl exits 23, +# "Failure writing output to destination") and `set -o pipefail` turns that into +# a failure of this whole script, three seconds into a release build. Whether it +# happens at all depends on who wins the pipe-buffer race, so it passed here and +# failed on the runner. parse_makefile_version() { - awk '/^VERSION =/{v=$3} /^PATCHLEVEL =/{p=$3} /^SUBLEVEL =/{s=$3} - /^EXTRAVERSION/{print v "." p "." s; exit}' + awk ' + /^VERSION =/ { if (v == "") v = $3 } + /^PATCHLEVEL =/ { if (p == "") p = $3 } + /^SUBLEVEL =/ { if (s == "") s = $3 } + END { if (v != "" && p != "" && s != "") print v "." p "." s } + ' } REPO_URL="https://github.com/$REPO_SLUG.git" @@ -71,8 +82,13 @@ REPO_URL="https://github.com/$REPO_SLUG.git" TIP="$(git ls-remote "$REPO_URL" "refs/heads/$BRANCH" | cut -f1)" [ -n "$TIP" ] || die "branch $BRANCH not found in $REPO_SLUG" -TIP_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/$REPO_SLUG/$TIP/Makefile" | - parse_makefile_version)" +# Downloaded to a file rather than piped: see parse_makefile_version. +TIP_MAKEFILE="$(mktemp)" +trap 'rm -f "$TIP_MAKEFILE"' EXIT +curl -fsSL "https://raw.githubusercontent.com/$REPO_SLUG/$TIP/Makefile" -o "$TIP_MAKEFILE" || + die "cannot fetch the Makefile at $BRANCH tip $TIP" +TIP_VERSION="$(parse_makefile_version <"$TIP_MAKEFILE")" +[ -n "$TIP_VERSION" ] || die "cannot read the Makefile version at $BRANCH tip $TIP" if [ "$TIP_VERSION" = "$VERSION" ]; then note "$VERSION is at the tip of $BRANCH" @@ -95,7 +111,8 @@ COMMITS="$HISTORY_DIR/first-parent.txt" git -C "$HISTORY_DIR" log --first-parent --format=%H FETCH_HEAD >"$COMMITS" version_at() { - git -C "$HISTORY_DIR" show "$1:Makefile" 2>/dev/null | parse_makefile_version + # Command substitution, not a pipe: git runs to completion either way. + parse_makefile_version <<<"$(git -C "$HISTORY_DIR" show "$1:Makefile" 2>/dev/null)" } # Versions are non-increasing as the list goes back in time, so binary search