From 237068cc2c3410b994329fe5007e5fedaa4a9798 Mon Sep 17 00:00:00 2001 From: Michel de Graaf Date: Fri, 24 Jul 2026 12:55:04 +0200 Subject: [PATCH] ci: build musl targets with cargo instead of cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit upload-rust-binary-action reaches for `cross` on any *-musl target. Every entry in the matrix builds on a runner of its own architecture — only the libc differs — so cross buys nothing, and on the native arm64 runner it hard-failed: error: toolchain 'stable-x86_64-unknown-linux-gnu' may not be able to run on this system That cost v6.0.0 its aarch64-unknown-linux-musl archive; the other five targets uploaded because the matrix is fail-fast: false. Re-running the failed job from the Actions UI replays the old workflow file, which is useless when the workflow is the bug. So the Release workflow now takes an optional `tag` input that rebuilds and re-uploads binaries for an existing tag. That value reaches actions/checkout as `ref:` and is typed by whoever dispatches, so it is checked against a literal version tag first. --- .github/workflows/release.yml | 29 +++++++++++++++++++++++++---- RELEASE.md | 13 ++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90799c0..5f74fd1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,11 @@ on: push: branches: [master] workflow_dispatch: + inputs: + tag: + description: 'Existing tag to rebuild binaries for (e.g. v6.0.0). Leave empty for a normal release run.' + required: false + type: string permissions: contents: write @@ -68,16 +73,25 @@ jobs: # string on the runs where nothing was released, and fromJSON chokes on it. - name: Resolve tag id: tag - if: steps.release-plz.outputs.releases_created == 'true' + if: steps.release-plz.outputs.releases_created == 'true' || inputs.tag != '' env: RELEASES: ${{ steps.release-plz.outputs.releases }} - run: echo "tag=$(jq -r '.[0].tag' <<< "$RELEASES")" >> "$GITHUB_OUTPUT" + INPUT_TAG: ${{ inputs.tag }} + run: | + tag="${INPUT_TAG:-$(jq -r '.[0].tag' <<< "$RELEASES")}" + # This value is handed to actions/checkout as `ref:` and INPUT_TAG is + # attacker-shaped (anyone who can dispatch the workflow types it), so + # refuse anything that is not a literal version tag. + [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]] || { echo "::error::unexpected tag: $tag"; exit 1; } + echo "tag=$tag" >> "$GITHUB_OUTPUT" - # Attaches downloadable binaries to the release GitHub just created. + # Attaches downloadable binaries to the release GitHub just created, or to an + # existing tag when dispatched manually with `tag` (recovering a target that + # failed to upload needs a re-run of *this* file, not the old one). binaries: name: ${{ matrix.target }} needs: release - if: needs.release.outputs.created == 'true' + if: needs.release.outputs.created == 'true' || inputs.tag != '' runs-on: ${{ matrix.os }} strategy: # One flaky cross-linker must not hold back the five targets that built. @@ -111,10 +125,17 @@ jobs: # Builds, strips, archives (.tar.gz / .zip on Windows), writes a .sha256 # and uploads the lot to the release. + # + # build-tool is pinned to cargo because the action otherwise reaches for + # `cross` on any *-musl target. Every entry in the matrix builds on a + # runner of its own architecture — only the libc differs — so cross adds + # nothing, and on the native arm64 runner it hard-fails trying to install + # an x86_64 toolchain. - uses: taiki-e/upload-rust-binary-action@v1 with: bin: soulseek-rs target: ${{ matrix.target }} + build-tool: cargo archive: $bin-$tag-$target include: README.md,LICENSE checksum: sha256 diff --git a/RELEASE.md b/RELEASE.md index 9f10d9e..2511caa 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -41,11 +41,14 @@ Both crates always share one version, one tag, and one changelog — see `releas - A merge with no releasable commits (only `docs:`/`chore:`/`test:`) opens no release PR. That is intended. -- The release PR does not run CI: GitHub does not trigger workflows for PRs opened with - `GITHUB_TOKEN`. It only touches `Cargo.toml`, `Cargo.lock`, and `CHANGELOG.md`; CI already - ran on the commits it is releasing. -- If one target's build fails, the other five still upload (`fail-fast: false`). Re-run just - that matrix job from the Actions UI. +- The release PR does not run CI on its own, because GitHub does not trigger workflows for + PRs opened with `GITHUB_TOKEN`. Pushing any commit to that branch yourself does start it — + handy if you want the version bump validated before merging. +- If one target's build fails, the other five still upload (`fail-fast: false`). To retry, + run the **Release** workflow manually and set `tag` to the existing tag (e.g. `v6.0.0`); + it rebuilds and re-uploads every target for that tag. Re-running the failed job from the + Actions UI replays the *old* workflow file, so it is no use when the workflow is the thing + that needs fixing. - To skip a release for a commit that would otherwise trigger one, use a `chore:` type. ## Installing a release