name: Release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
tag:
description: "Existing tag to build and attach binaries for (e.g. v0.2.1)"
required: true
env:
CARGO_TERM_COLOR: always
permissions:
contents: write
id-token: write attestations: write
jobs:
binaries:
name: build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: macos-latest
target: aarch64-apple-darwin
- os: macos-latest
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.tag || github.ref }}
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install libudev (Linux, for the yubikey feature)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libudev-dev pkg-config
- name: Build release binary
run: cargo build --release --locked --features yubikey --target ${{ matrix.target }}
- name: Package tarball (unix)
if: runner.os != 'Windows'
shell: bash
env:
TAG: ${{ github.event.inputs.tag || github.ref_name }}
TARGET: ${{ matrix.target }}
run: |
archive="svault-${TAG}-${TARGET}.tar.gz"
tar -czf "$archive" -C "target/${TARGET}/release" svault
# SHA-256 checksum so users can verify the download (finding #11).
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$archive" > "$archive.sha256"
else
shasum -a 256 "$archive" > "$archive.sha256"
fi
echo "ARCHIVE=$archive" >> "$GITHUB_ENV"
echo "CHECKSUM=$archive.sha256" >> "$GITHUB_ENV"
- name: Package zip (windows)
if: runner.os == 'Windows'
shell: pwsh
env:
TAG: ${{ github.event.inputs.tag || github.ref_name }}
TARGET: ${{ matrix.target }}
run: |
$archive = "svault-$env:TAG-$env:TARGET.zip"
Compress-Archive -Path "target/$env:TARGET/release/svault.exe" -DestinationPath $archive
# SHA-256 checksum so users can verify the download (finding #11).
$hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLower()
"$hash $archive" | Out-File -Encoding ascii "$archive.sha256"
"ARCHIVE=$archive" >> $env:GITHUB_ENV
"CHECKSUM=$archive.sha256" >> $env:GITHUB_ENV
- name: Attest build provenance
uses: actions/attest-build-provenance@v2
with:
subject-path: ${{ env.ARCHIVE }}
- name: Attach to release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
files: |
${{ env.ARCHIVE }}
${{ env.CHECKSUM }}
publish:
name: publish to crates.io
needs: binaries
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- name: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
echo "CARGO_REGISTRY_TOKEN not set — skipping crates.io publish."
exit 0
fi
# Idempotent: if this version is already on crates.io (e.g. published
# manually), skip instead of failing the release run.
version=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
status=$(curl -s -o /dev/null -w '%{http_code}' \
-H 'User-Agent: svault-release (https://github.com/nim444/Svault)' \
"https://crates.io/api/v1/crates/svault-ai/$version")
if [ "$status" = "200" ]; then
echo "svault-ai $version is already on crates.io — skipping publish."
exit 0
fi
cargo publish --locked