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'