name: Publish to crates.io
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
dry_run:
description: "Dry run (cargo publish --dry-run)"
required: false
default: "false"
type: boolean
env:
CARGO_TERM_COLOR: always
jobs:
publish:
name: Publish
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set version from tag
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/}"
TAG_VERSION="${TAG_VERSION#v}"
sed -i "s/^version = \".*\"/version = \"$TAG_VERSION\"/" Cargo.toml
echo "TAG_VERSION=$TAG_VERSION" >> "$GITHUB_ENV"
echo "Version set to $TAG_VERSION"
- name: Commit version bump to main
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if ! git diff --quiet Cargo.toml; then
git add Cargo.toml
git commit -m "chore: bump version to $TAG_VERSION"
git push origin HEAD:main
else
echo "Cargo.toml version already matched tag — no commit needed"
fi
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.94.0"
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: Check formatting
run: cargo fmt --check
- name: Clippy
run: cargo clippy -- -D warnings
- name: Test
run: cargo test
- name: Publish (dry run)
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run == 'true' }}
run: cargo publish --dry-run
- name: Publish
if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != 'true') }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish