name: Release
on:
push:
tags:
- "v*"
jobs:
publish-crate:
name: Publish crate to crates.io
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install curl + python3
run: |
sudo apt-get update
sudo apt-get install -y curl python3
- name: Rust fmt check
run: cargo fmt --all -- --check
- name: Rust clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: Build and test
run: |
cargo build --all-targets --verbose
cargo test --all --verbose
- name: Cargo login
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo login "$CARGO_REGISTRY_TOKEN"
- name: Publish crate (dry-run + if needed)
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
shell: bash
run: |
set -euo pipefail
CRATE="$(cargo metadata --no-deps --format-version 1 | python3 -c 'import sys,json; m=json.load(sys.stdin); print(m["packages"][0]["name"])')"
VER="$(cargo metadata --no-deps --format-version 1 | python3 -c 'import sys,json; m=json.load(sys.stdin); print(m["packages"][0]["version"])')"
echo "Crate: ${CRATE} Version: ${VER}"
# Validate publish packaging/build without uploading
cargo publish --dry-run
CODE="$(curl -s -o /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/${CRATE}/${VER}" || true)"
if [ "$CODE" = "200" ]; then
echo "Already published: ${CRATE} ${VER} (skipping upload)."
exit 0
fi
cargo publish --no-verify