diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7bc5096..061badf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,9 +4,19 @@ name: Release # Blacksmith free tier is not consumed by surprise release builds. The # workflow stays local-by-default: an operator dispatches it after a manual # `cargo publish`. See docs/adr/0001-pr-check-blacksmith-local-release.md. +# +# The release matrix runs on GitHub-hosted runners. This repository is public, +# so those minutes are free, and a rare dispatch-only release then costs the +# shared Blacksmith pool nothing at all — which is what ADR 0001 set out to +# protect. PR Check stays on Blacksmith, unchanged. on: workflow_dispatch: + inputs: + tag: + description: "Release tag to build and attach assets to (e.g. v0.3.28)" + required: true + type: string env: CARGO_TERM_COLOR: always @@ -22,10 +32,15 @@ jobs: permissions: contents: read strategy: + # One unavailable runner must not cancel the legs that are healthy. + # In the v0.3.26 run, two legs failed to acquire a runner before any + # step executed, fail-fast cancelled the three healthy legs, and the + # release shipped with no assets at all. + fail-fast: false matrix: include: - target: x86_64-pc-windows-msvc - runner: blacksmith-4vcpu-windows-2025 + runner: windows-latest ext: .exe - target: x86_64-apple-darwin runner: macos-latest @@ -34,15 +49,17 @@ jobs: runner: macos-latest ext: "" - target: x86_64-unknown-linux-gnu - runner: blacksmith-4vcpu-ubuntu-2404 + runner: ubuntu-latest ext: "" - target: aarch64-unknown-linux-gnu - runner: blacksmith-4vcpu-ubuntu-2404 + runner: ubuntu-latest ext: "" use_cross: true steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + ref: ${{ inputs.tag }} - name: Install Linux keyring build deps if: runner.os == 'Linux' && !matrix.use_cross @@ -87,7 +104,9 @@ jobs: name: Upload Release Assets needs: build runs-on: ubuntu-latest - if: vars.CI_BUDGET_MODE != 'off' + # Ship whatever built. A partial asset set beats the empty asset set that + # `needs: build` produced whenever any single target failed. + if: ${{ !cancelled() && vars.CI_BUDGET_MODE != 'off' }} permissions: contents: write @@ -95,9 +114,19 @@ jobs: - name: Download all artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + - name: Verify at least one asset was built + run: | + count=$(find . -type f -name 'linear-cli-*' | wc -l | tr -d ' ') + echo "found $count asset(s)" + test "$count" -gt 0 + find . -type f -name 'linear-cli-*' -exec ls -l {} + + - name: Upload to release uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: + # Without an explicit tag the action falls back to github.ref, which + # is a branch ref whenever the workflow is dispatched from a branch. + tag_name: ${{ inputs.tag }} files: | linear-cli-*/linear-cli-* @@ -111,6 +140,8 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + ref: ${{ inputs.tag }} - name: Install Rust uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable