name: Binary Release
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to attach binaries to (e.g. v3.16.0)'
required: true
type: string
permissions:
contents: write
concurrency:
group: binary-release-${{ github.event.release.tag_name || inputs.tag }}
cancel-in-progress: false
env:
CROSS_VERSION: v0.2.5
jobs:
build:
name: ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-musl
cross: false
- target: x86_64-unknown-linux-gnu
cross: false
- target: aarch64-unknown-linux-musl
cross: true
- target: aarch64-unknown-linux-gnu
cross: true
steps:
- name: Resolve release tag
id: tag
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
if [ -z "$TAG" ]; then
echo "::error::No tag resolved (release event missing tag_name and no dispatch input)"
exit 1
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "Building pmat for $TAG → ${{ matrix.target }}"
- name: Checkout at tag
uses: actions/checkout@v4
with:
ref: ${{ steps.tag.outputs.tag }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends musl-tools
- name: Install cross
if: matrix.cross
run: |
dir="$RUNNER_TEMP/cross"
mkdir -p "$dir"
curl -sL "https://github.com/cross-rs/cross/releases/download/${CROSS_VERSION}/cross-x86_64-unknown-linux-musl.tar.gz" \
| tar xz -C "$dir"
echo "$dir" >> "$GITHUB_PATH"
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: binary-${{ matrix.target }}
- name: Build pmat
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
cross build --release --bin pmat --target ${{ matrix.target }} --locked
else
cargo build --release --bin pmat --target ${{ matrix.target }} --locked
fi
- name: Strip binary
run: |
TARGET="${{ matrix.target }}"
BIN_PATH="target/${TARGET}/release/pmat"
# Each cross image ships the matching ${triple}-strip; the
# gnu image does NOT carry the musl variant and vice-versa
# (regression: v3.16.0 first run failed aarch64-musl because
# this step called aarch64-linux-gnu-strip in the musl image).
case "$TARGET" in
aarch64-unknown-linux-musl) STRIP=aarch64-linux-musl-strip ;;
aarch64-unknown-linux-gnu) STRIP=aarch64-linux-gnu-strip ;;
*) STRIP="" ;;
esac
if [ -n "$STRIP" ]; then
docker run --rm -v "$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${TARGET}:main" \
"$STRIP" "/$BIN_PATH"
else
strip "$BIN_PATH"
fi
ls -la "$BIN_PATH"
- name: Package archive
id: package
run: |
VERSION="${{ steps.tag.outputs.tag }}"
TARGET="${{ matrix.target }}"
ARCHIVE="pmat-${VERSION}-${TARGET}"
mkdir -p "$ARCHIVE"
cp "target/${TARGET}/release/pmat" "$ARCHIVE/"
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE; do
[ -f "$f" ] && cp "$f" "$ARCHIVE/"
done
tar czf "${ARCHIVE}.tar.gz" "$ARCHIVE"
shasum -a 256 "${ARCHIVE}.tar.gz" > "${ARCHIVE}.tar.gz.sha256"
echo "archive=${ARCHIVE}.tar.gz" >> "$GITHUB_OUTPUT"
echo "sha=${ARCHIVE}.tar.gz.sha256" >> "$GITHUB_OUTPUT"
du -h "${ARCHIVE}.tar.gz"
- name: Upload assets to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ steps.tag.outputs.tag }}" \
"${{ steps.package.outputs.archive }}" \
"${{ steps.package.outputs.sha }}" \
--clobber
summary:
name: Summary
needs: build
runs-on: ubuntu-latest
if: always()
steps:
- name: Write summary
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
STATUS="${{ needs.build.result }}"
{
echo "### Binary Release: $TAG"
echo ""
if [ "$STATUS" = "success" ]; then
echo "- Build matrix: **4/4 targets succeeded**"
else
echo "- Build matrix: **partial** (status=$STATUS)"
fi
echo "- Targets:"
echo " - x86_64-unknown-linux-musl"
echo " - x86_64-unknown-linux-gnu"
echo " - aarch64-unknown-linux-musl"
echo " - aarch64-unknown-linux-gnu"
} >> "$GITHUB_STEP_SUMMARY"