name: Publish to crates.io
on:
release:
types: [published]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
publish:
name: Publish crate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- name: Verify version matches tag
run: |
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
TAG=$(git describe --tags --exact-match 2>/dev/null || echo "unknown")
if [ "$TAG" != "v$VERSION" ]; then
echo "Version mismatch: Cargo.toml has $VERSION but git tag is $TAG"
exit 1
fi
- name: Format check
run: cargo fmt --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Test (all features)
run: cargo test --all-features
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set +e
output=$(cargo publish 2>&1)
status=$?
echo "$output"
if [ "$status" -eq 0 ]; then
echo "Published successfully."
elif echo "$output" | grep -q "already exists"; then
echo "::notice::This version is already on crates.io; skipping publish."
else
exit "$status"
fi