diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index bc03a58..8fee20e 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -66,18 +66,53 @@ jobs: with: persist-credentials: false ref: ${{ env.TAG }} + # A re-run against an existing tag (docs/RELEASING.md) must not rebuild + # what is already published: an archive is immutable once uploaded, and + # a macOS build of this graph is measured in hours. + - name: Already on the release? + id: published + env: + GH_TOKEN: ${{ github.token }} + TARGET: ${{ matrix.target }} + run: | + set -euo pipefail + archive="oxidelake-${TAG#v}-${TARGET}.tar.gz" + assets="$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json assets --jq '.assets[].name' 2>/dev/null || true)" + if printf '%s\n' "$assets" | grep -qxF "$archive"; then + echo "$archive is already attached to $TAG — nothing to build" + echo "present=true" >> "$GITHUB_OUTPUT" + else + echo "present=false" >> "$GITHUB_OUTPUT" + fi - name: Add the target's standard library + if: steps.published.outputs.present != 'true' env: TARGET: ${{ matrix.target }} run: rustup target add "$TARGET" - name: musl linker (Linux) - if: contains(matrix.target, 'musl') + if: steps.published.outputs.present != 'true' && contains(matrix.target, 'musl') run: sudo apt-get update -q && sudo apt-get install -y -q musl-tools + # One binary per invocation, on purpose. The release profile is fat LTO + # with a single codegen unit, so linking a binary is a whole-program LLVM + # pass over Arrow, DataFusion and Ballista. Cargo schedules the three + # binaries' links in parallel, and three of those do not fit in a 16 GB + # Linux runner that has no swap: the VM is torn down and the job ends + # with "The runner has received a shutdown signal", exit 143, at exactly + # this point — v0.1.0 (both musl targets) and v0.1.2 (aarch64 musl). + # macOS survives only by swapping, which is where its hours go. The + # dependencies still compile in parallel during the first invocation; + # the second and third only link. - name: Build + if: steps.published.outputs.present != 'true' env: TARGET: ${{ matrix.target }} - run: cargo build --release --locked -p oxidelake-runtime --target "$TARGET" + run: | + set -euo pipefail + for binary in oxide oxide-scheduler oxide-worker; do + cargo build --release --locked -p oxidelake-runtime --bin "$binary" --target "$TARGET" + done - name: Package + if: steps.published.outputs.present != 'true' env: TARGET: ${{ matrix.target }} run: | @@ -113,6 +148,7 @@ jobs: # Uploaded only if absent, never clobbered: a published archive is # immutable, and rebuilding a tag yields a different checksum. - name: Attach to the release + if: steps.published.outputs.present != 'true' env: GH_TOKEN: ${{ github.token }} run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index a394459..32e42d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ versions (0.x) may contain breaking changes; they are always listed under a ## [Unreleased] +### Fixed + +- **Linux release binaries build again.** `binaries.yml` links the three + binaries one at a time: the release profile's fat LTO made Cargo run three + whole-program links in parallel, which exhausted the 16 GB Linux runners + and ended every musl job with exit 143 (v0.1.0 and v0.1.2 both shipped + without Linux archives). A re-run against an existing tag now skips targets + whose archive is already attached instead of rebuilding them. + ## [0.1.2] - 2026-09-07 CI and build-gate changes only; no crate code changed since 0.1.1. diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 821901d..c4b1b16 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -26,7 +26,8 @@ Trusted Publishing. checksums; without the secret the job says so and the tap keeps the previous version. To refresh the formula for a tag whose release already ran (or ran from an older workflow): `gh workflow run binaries.yml --ref main -f tag=vX.Y.Z` - — archives already on the release are left alone, only the formula moves. + — targets whose archive is already on the release are skipped without + building, only the missing archives and the formula move. - A **`release` GitHub environment** whose deployment branches are restricted to `v*` tags, so an OIDC publish token can never be minted from a branch. - **`v*` tags protected by a ruleset**, so only a repository admin can create