name: Release
on:
push:
tags:
- 'v[0-9]+.*'
env:
CARGO_TERM_COLOR: always
jobs:
plan:
name: Plan release
runs-on: ubuntu-latest
outputs:
targets: ${{ steps.plan.outputs.targets }}
steps:
- uses: actions/checkout@v7
with:
fetch-tags: true
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-dist
uses: axodotdev/cargo-dist-installer@v1
with:
version: "0.28.0"
- id: plan
run: |
TARGETS=$(cargo dist plan --target x86_64-unknown-linux-gnu --target x86_64-apple-darwin --target aarch64-apple-darwin --target x86_64-pc-windows-msvc --output-format json 2>&1 | jq -r '.releases[0].targets // ["x86_64-unknown-linux-gnu"] | @json')
echo "targets=$TARGETS" >> "$GITHUB_OUTPUT"
echo "Planning for targets: $TARGETS"
build:
name: Build ${{ matrix.target }}
needs: [plan]
strategy:
fail-fast: false
matrix:
target:
- x86_64-unknown-linux-gnu
- x86_64-apple-darwin
- aarch64-apple-darwin
- x86_64-pc-windows-msvc
runs-on: ${{ fromJSON('{
"x86_64-unknown-linux-gnu": "ubuntu-latest",
"x86_64-apple-darwin": "macos-13",
"aarch64-apple-darwin": "macos-latest",
"x86_64-pc-windows-msvc": "windows-latest"
}')[matrix.target] }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cargo-dist
uses: axodotdev/cargo-dist-installer@v1
with:
version: "0.28.0"
- name: Build release binary
run: cargo dist build --target ${{ matrix.target }} --output-format json
- name: Upload build artifacts
uses: actions/upload-artifact@v7
with:
name: dist-${{ matrix.target }}
path: target/dist/
retention-days: 7
# ── Publish ───────────────────────────────────────────────────────
# Upload all binaries to the GitHub Release
publish:
name: Upload binaries to GitHub Release
needs: [plan, build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Install cargo-dist
uses: axodotdev/cargo-dist-installer@v1
with:
version: "0.28.0"
- name: Download all build artifacts
uses: actions/download-artifact@v7
with:
pattern: dist-*
merge-multiple: true
path: target/dist/
- name: Upload artifacts to GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
# Find all archive/installer files built by cargo-dist
ARCHIVES=$(find target/dist -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.sh' -o -name '*.ps1' \) 2>/dev/null || true)
if [ -z "$ARCHIVES" ]; then
echo "⚠️ No cargo-dist artifacts found — falling back to manual binary upload"
BINARY="forge-guard"
EXT=""
if [ "${{ runner.os }}" = "Windows" ]; then
EXT=".exe"
fi
for dir in target/dist/*/release; do
if [ -f "$dir/$BINARY$EXT" ]; then
gh release upload "${{ github.ref_name }}" "$dir/$BINARY$EXT" --clobber
fi
done
else
echo "Found artifacts to upload:"
echo "$ARCHIVES"
for FILE in $ARCHIVES; do
echo " Uploading: $FILE"
gh release upload "${{ github.ref_name }}" "$FILE" --clobber
done
fi
- name: Show release summary
run: |
echo "✅ Binaries uploaded for ${{ github.ref_name }}"
echo ""
echo "Targets:"
echo " - x86_64-unknown-linux-gnu (Linux)"
echo " - x86_64-apple-darwin (macOS Intel)"
echo " - aarch64-apple-darwin (macOS Apple Silicon)"
echo " - x86_64-pc-windows-msvc (Windows)"