name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: '-D warnings'
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all --check
clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features -- -D warnings
test:
name: test ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --all-features
- run: cargo test --doc --all-features
deny:
name: cargo-deny
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check
publish:
name: Publish to crates.io
needs: [fmt, clippy, test, deny]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Verify tag matches Cargo.toml version
shell: bash
run: |
CARGO_VER=$(awk -F'"' '/^version[[:space:]]*=/ {print $2; exit}' Cargo.toml)
if [ "v$CARGO_VER" != "$GITHUB_REF_NAME" ]; then
echo "::error::tag $GITHUB_REF_NAME does not match Cargo.toml version v$CARGO_VER"
exit 1
fi
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Publish to crates.io (idempotent)
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
shell: bash
run: |
set -euo pipefail
CRATE=$(awk -F'"' '/^name[[:space:]]*=/ {print $2; exit}' Cargo.toml)
VERSION=$(awk -F'"' '/^version[[:space:]]*=/ {print $2; exit}' Cargo.toml)
URL="https://crates.io/api/v1/crates/${CRATE}/${VERSION}"
if curl -fsS -A "${CRATE}-release-ci" -o /dev/null "$URL"; then
echo "::notice::${CRATE}@${VERSION} already on crates.io, skipping"
exit 0
fi
cargo publish