name: Build Release Binaries
on:
workflow_call:
inputs:
upload:
description: "Upload to release (requires a release to exist)"
required: false
default: "false"
type: string
tag:
description: "Release tag to upload to (only if upload is true)"
required: false
type: string
workflow_dispatch:
inputs:
upload:
description: "Upload to release (requires a release to exist)"
required: false
default: "false"
type: choice
options:
- "true"
- "false"
tag:
description: "Release tag to upload to (only if upload is true)"
required: false
type: string
jobs:
build-binaries:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
build_packages: true
glibc: "2.17"
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
build_packages: true
glibc: "2.17"
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
build_packages: false
- target: aarch64-unknown-linux-musl
os: ubuntu-24.04-arm
build_packages: false
- target: x86_64-apple-darwin
os: macos-15-intel
build_packages: false
- target: aarch64-apple-darwin
os: macos-latest
build_packages: false
- target: x86_64-pc-windows-msvc
os: windows-latest
build_packages: false
- target: aarch64-pc-windows-msvc
os: windows-11-arm
build_packages: false
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name || inputs.tag || github.ref }}
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
targets: ${{ matrix.target }}
toolchain: 1.94.1
- name: Cache Rust artifacts
uses: Swatinem/rust-cache@v2
with:
cache-bin: "false"
prefix-key: "v1-rust"
- name: Install musl toolchain
if: endsWith(matrix.target, '-unknown-linux-musl')
run: sudo apt-get update && sudo apt-get install -y musl-tools
- name: Install Zig
if: matrix.glibc
uses: mlugg/setup-zig@v2
with:
version: 0.14.1
- name: Install cargo-zigbuild
if: matrix.glibc
run: cargo install --locked cargo-zigbuild
- name: Build release binary (zigbuild)
if: matrix.glibc
run: cargo zigbuild --release --target ${{ matrix.target }}.${{ matrix.glibc }}
- name: Build release binary
if: ${{ !matrix.glibc }}
run: cargo build --release --target ${{ matrix.target }}
- name: Verify glibc floor
if: matrix.glibc
run: |
set -euo pipefail
bin="target/${{ matrix.target }}/release/panache"
max=$(objdump -T "$bin" 2>/dev/null \
| grep -oE 'GLIBC_[0-9]+(\.[0-9]+)+' \
| sed 's/GLIBC_//' | sort -V | tail -n1 || true)
echo "Highest required glibc symbol: ${max:-none}"
if [ -n "$max" ] && [ "$(printf '%s\n%s\n' "$max" "${{ matrix.glibc }}" | sort -V | tail -n1)" != "${{ matrix.glibc }}" ]; then
echo "::error::panache requires glibc $max, above the ${{ matrix.glibc }} floor"
exit 1
fi
- name: Strip binary (Unix)
if: runner.os != 'Windows'
run: strip target/${{ matrix.target }}/release/panache
- name: Upload raw binary artifact
uses: actions/upload-artifact@v7
with:
name: panache-binary-${{ matrix.target }}
path: target/${{ matrix.target }}/release/panache${{ runner.os == 'Windows' && '.exe' || '' }}
if-no-files-found: error
- name: Create archive (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p dist
cp target/${{ matrix.target }}/release/panache dist/
cp -r target/man dist/
cp -r target/completions dist/
cp LICENSE dist/
tar czf panache-${{ matrix.target }}.tar.gz -C dist .
rm -rf dist
- name: Create archive (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Path dist -Force
Copy-Item target/${{ matrix.target }}/release/panache.exe dist/
Copy-Item -Recurse target/man dist/
Copy-Item -Recurse target/completions dist/
Copy-Item LICENSE dist/
Compress-Archive -Path dist/* -DestinationPath panache-${{ matrix.target }}.zip
Remove-Item -Recurse -Force dist
- name: Upload artifact (for testing)
uses: actions/upload-artifact@v7
with:
name: panache-${{ matrix.target }}
path: |
panache-${{ matrix.target }}.tar.gz
panache-${{ matrix.target }}.zip
- name: Upload binary to release
if: inputs.upload == 'true'
shell: bash
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
if [ -f panache-${{ matrix.target }}.tar.gz ]; then
gh release upload --clobber "$TAG" panache-${{ matrix.target }}.tar.gz
fi
if [ -f panache-${{ matrix.target }}.zip ]; then
gh release upload --clobber "$TAG" panache-${{ matrix.target }}.zip
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload installer scripts to release
if: inputs.upload == 'true' && matrix.target == 'x86_64-unknown-linux-gnu'
shell: bash
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
gh release upload --clobber "$TAG" scripts/panache-installer.sh scripts/panache-installer.ps1
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install cargo-deb and cargo-generate-rpm
if: matrix.build_packages == true
run: |
cargo install cargo-deb
cargo install cargo-generate-rpm
- name: Build DEB package
if: matrix.build_packages == true
run: |
rm -rf target/${{ matrix.target }}/debian
cargo deb --target ${{ matrix.target }} --no-build
- name: Build RPM package
if: matrix.build_packages == true
run: |
rm -rf target/${{ matrix.target }}/generate-rpm
cargo generate-rpm --target ${{ matrix.target }}
- name: Upload DEB artifact (for testing)
if: matrix.build_packages == true
run: |
DEB_FILE=$(ls target/${{ matrix.target }}/debian/*.deb)
cp "$DEB_FILE" .
continue-on-error: true
- name: Upload RPM artifact (for testing)
if: matrix.build_packages == true
run: |
RPM_FILE=$(ls target/${{ matrix.target }}/generate-rpm/*.rpm)
cp "$RPM_FILE" .
continue-on-error: true
- name: Upload package artifacts
if: matrix.build_packages == true
uses: actions/upload-artifact@v7
with:
name: panache-packages-${{ matrix.target }}
path: |
*.deb
*.rpm
- name: Upload DEB package
if: matrix.build_packages == true && inputs.upload == 'true'
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
DEB_FILE=$(ls target/${{ matrix.target }}/debian/*.deb)
gh release upload --clobber "$TAG" "$DEB_FILE"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload RPM package
if: matrix.build_packages == true && inputs.upload == 'true'
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
RPM_FILE=$(ls target/${{ matrix.target }}/generate-rpm/*.rpm)
gh release upload --clobber "$TAG" "$RPM_FILE"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}