name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write
jobs:
verify-version:
name: Verify tag matches Cargo.toml
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check version match
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
echo "Tag version: $TAG_VERSION"
echo "Cargo.toml version: $CARGO_VERSION"
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "::error::Version mismatch! Tag is v$TAG_VERSION but Cargo.toml has $CARGO_VERSION"
exit 1
fi
echo "✓ Versions match"
build-release:
name: Build Release Artifacts
needs: verify-version
if: always() && (needs.verify-version.result == 'success' || needs.verify-version.result == 'skipped')
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact_name: cargo-copter
cross: true
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
artifact_name: cargo-copter
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
artifact_name: cargo-copter
cross: true
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-musl
artifact_name: cargo-copter
- os: macos-latest
target: aarch64-apple-darwin
artifact_name: cargo-copter
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact_name: cargo-copter.exe
- os: windows-latest
target: aarch64-pc-windows-msvc
artifact_name: cargo-copter.exe
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl tools (Linux musl targets)
if: contains(matrix.target, 'musl')
run: |
sudo apt-get update
sudo apt-get install -y musl-tools
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Test build
run: cargo test
- name: Build release binary (native)
if: matrix.cross != true
run: cargo build --release --target ${{ matrix.target }}
- name: Build release binary (cross)
if: matrix.cross == true
uses: houseabsolute/actions-rust-cross@v1.0.5
with:
command: build
target: ${{ matrix.target }}
args: --release
- name: Strip binary (Unix, native only)
if: runner.os != 'Windows' && matrix.cross != true
run: strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
- name: Create cargo-binstall compatible archive
shell: bash
run: |
cd target/${{ matrix.target }}/release
# cargo-binstall expects: {bin}-{target}.{tar.gz|zip}
if [ "${{ runner.os }}" = "Windows" ]; then
ARCHIVE="cargo-copter-${{ matrix.target }}.zip"
7z a "$ARCHIVE" "${{ matrix.artifact_name }}"
echo "ASSET=$ARCHIVE" >> $GITHUB_ENV
else
ARCHIVE="cargo-copter-${{ matrix.target }}.tar.gz"
tar czf "$ARCHIVE" "${{ matrix.artifact_name }}"
echo "ASSET=$ARCHIVE" >> $GITHUB_ENV
fi
# Generate SHA256 checksum for cargo-binstall verification
if [ "${{ runner.os }}" = "Windows" ]; then
certutil -hashfile "$ARCHIVE" SHA256 | grep -v "hash" | tr -d '[:space:]' > "$ARCHIVE.sha256"
else
shasum -a 256 "$ARCHIVE" | cut -d ' ' -f 1 > "$ARCHIVE.sha256"
fi
cd -
- name: Upload release asset
uses: softprops/action-gh-release@v1
with:
files: |
target/${{ matrix.target }}/release/${{ env.ASSET }}
target/${{ matrix.target }}/release/${{ env.ASSET }}.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-crate:
name: Publish to crates.io
needs: build-release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
continue-on-error: true