From c9880d6a842de0e12f9156b6fa99e5ee4d6ccb4a Mon Sep 17 00:00:00 2001 From: Samueru-sama Date: Fri, 4 Sep 2026 13:12:11 -0400 Subject: [PATCH] Ship all six architectures in the release, not just two The release workflow hardcoded x86_64 and aarch64 in the build matrix, the asset collection loop and the manifest verification loop, so v0.2.2 published only those two even though the gates already build six. The matrix now matches the gates: x86_64, aarch64, riscv64, ppc64, ppc64le and loongarch64, both variants. release-notes.sh refused on two floors, and loongarch64 builds on glibc 2.36 while the rest build on 2.31. The body now derives the floors from the manifests and states each architecture's floor, and still refuses when the two variants of one architecture disagree. --- .github/workflows/release.yml | 25 +++++++------- scripts/release-notes.sh | 63 +++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8dbc662..215d497 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,11 +78,13 @@ jobs: build: name: build and package ${{ matrix.arch }} needs: gate - # ⛔ BOTH architectures build on ubuntu-latest, and that is deliberate. - # scripts/build.sh CROSS-compiles aarch64 inside the x86-64 floor image. - # `podman run --platform linux/arm64` would pull a tag for another - # platform, REPLACE the cached image for that tag, and leave the next - # x86-64 job with "Exec format error". docs/building.md says what it cost. + # ⛔ ALL SIX architectures build on ubuntu-latest, and that is deliberate. + # scripts/build.sh CROSS-compiles every non-x86-64 target inside the x86-64 + # floor image. `podman run --platform linux/arm64` would pull a tag for + # another platform, REPLACE the cached image for that tag, and leave the + # next x86-64 job with "Exec format error". docs/building.md says what it + # cost. The matrix below is the same six the gates build, so a release can + # never silently lag what the default branch already proved. runs-on: ubuntu-latest timeout-minutes: 30 # ⭐ Two variants, so nobody has to build one by hand. `default` reads @@ -93,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [x86_64, aarch64] + arch: [x86_64, aarch64, riscv64, ppc64, ppc64le, loongarch64] variant: [default, portable] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -177,15 +179,14 @@ jobs: path: staged # download-artifact writes one directory per uploaded artifact, so the - # two architectures arrive as staged/release-x86_64/... and - # staged/release-aarch64/.... Flatten them into the layout the two - # scripts expect, and fail if either is missing rather than publishing - # half a release. + # six architectures arrive as staged/release-/... Flatten them into + # the layout the two scripts expect, and fail if any is missing rather + # than publishing half a release. - name: collect every architecture and variant run: | set -eu mkdir -p dist build - for a in x86_64 aarch64; do + for a in x86_64 aarch64 riscv64 ppc64 ppc64le loongarch64; do for v in default portable; do src=staged/release-$a-$v [ -d "$src/dist" ] || { echo "no dist/ for $a/$v"; exit 1; } @@ -210,7 +211,7 @@ jobs: # ⚠ Only the DEFAULT variant ships loose files to check this way. # The portable set ships as archives, and package-release.sh already # checked every object in it against its manifest before archiving. - for a in x86_64 aarch64; do + for a in x86_64 aarch64 riscv64 ppc64 ppc64le loongarch64; do man=build/$a/build-manifest.json for f in $(jq -r '.artifacts | keys[]' "$man"); do want=$(jq -r --arg f "$f" '.artifacts[$f].sha256' "$man") diff --git a/scripts/release-notes.sh b/scripts/release-notes.sh index c000513..4b5e963 100644 --- a/scripts/release-notes.sh +++ b/scripts/release-notes.sh @@ -41,28 +41,65 @@ for d in "$BUILDS"/*; do done [ -n "$dirs" ] || { echo "release-notes: no build-manifest.json under $BUILDS" >&2; exit 2; } -# The floor is a property of the build environment and every build here uses -# the same one. If two manifests disagree, that is a finding and not something -# to paper over with the first value. -floor="" +# The floor is a property of the build environment. Every build here uses the +# same one, except loongarch64, whose floor is 2.36 because that is the first +# glibc release that runs loongarch64 at all (docs/building.md). The header +# below must not assert a single value across two floors, and the two variants +# of one architecture must still agree: they are the same build in the same +# environment, and a disagreement there is a finding rather than a value to +# print past. +floorlist="" for d in $dirs; do - f=$(jq -r '.floor_glibc' "$BUILDS/$d/build-manifest.json") - if [ -z "$floor" ]; then floor=$f - elif [ "$floor" != "$f" ]; then - echo "release-notes: manifests disagree about the floor: $floor and $f" >&2 + m=$BUILDS/$d/build-manifest.json + floorlist="$floorlist $(jq -r '.arch' "$m"):$(jq -r '.floor_glibc' "$m")" +done + +# ⛔ One architecture, one floor. If the default and portable manifests of the +# same architecture disagree, refuse rather than printing a body that cannot +# be true. +for a in $(printf '%s\n' "$floorlist" | tr ' ' '\n' | sed '/^$/d;s/:.*//' | sort -u); do + n=$(printf '%s\n' "$floorlist" | tr ' ' '\n' | + grep "^$a:" | sed 's/.*://' | sort -u | grep -c .) + [ "$n" -le 1 ] || { + echo "release-notes: $a has $n floors in its manifests" >&2 exit 2 - fi + } done +nfloors=$(printf '%s\n' "$floorlist" | tr ' ' '\n' | sed '/^$/d;s/.*://' | sort -u | grep -c .) +if [ "$nfloors" -le 1 ]; then + floor=$(printf '%s\n' "$floorlist" | tr ' ' '\n' | sed '/^$/d;s/.*://' | sort -u) +fi + printf '## cross-libc `dlopen` %s\n\n' "$TAG" printf 'Load the host'"'"'s GPU drivers into a process that carries its own libc.\n' printf 'See the [README](https://github.com/pkgforge-dev/cross-libc-dlopen#readme)\n' printf 'for what the two gaps are and which one your symptom is.\n\n' -printf '**Built on glibc %s**, which is the floor every artefact here is held\n' "$floor" -printf 'to. An object needing a symbol version above it would fail to load inside\n' -printf 'a bundle whose glibc is older, so the build refuses to produce one and\n' -printf 'the packaging step refuses to publish one.\n\n' +if [ "$nfloors" -le 1 ]; then + printf '**Built on glibc %s**, which is the floor every artefact here is held\n' "$floor" + printf 'to. An object needing a symbol version above it would fail to load inside\n' + printf 'a bundle whose glibc is older, so the build refuses to produce one and\n' + printf 'the packaging step refuses to publish one.\n\n' +else + # ⛔ The floors come out of the manifests, not out of this text: loongarch64 + # is built on 2.36 because that is the first glibc that runs it at all, and + # the rest on 2.31. Spelled here, a floor change would silently leave the + # body claiming a number the builds no longer used. + printf '**Built on the glibc floor for each architecture.** ' + first_floor=1 + for f in $(printf '%s\n' "$floorlist" | tr ' ' '\n' | sed '/^$/d;s/.*://' | sort -uV); do + arches=$(printf '%s\n' "$floorlist" | tr ' ' '\n' | + grep ":$f$" | sed 's/:.*//' | sort -u | tr '\n' ' ' | sed 's/ $//') + if [ "$first_floor" = 1 ]; then first_floor=0 + else printf '; ' + fi + printf '%s are held to glibc %s' "$arches" "$f" + done + printf '. An object needing a symbol version above its floor would fail to\n' + printf 'load inside a bundle whose glibc is older, so the build refuses to\n' + printf 'produce one and the packaging step refuses to publish one.\n\n' +fi # ------------------------------------------------------------- the changelog -- printf '### Changes\n\n'