name: Publish to crates.io
on:
push:
branches:
- main
- master
workflow_dispatch:
jobs:
check-version:
runs-on: ubuntu-latest
outputs:
is_new: ${{ steps.check.outputs.is_new }}
version: ${{ steps.check.outputs.version }}
name: ${{ steps.check.outputs.name }}
steps:
- uses: actions/checkout@v5
- name: Check if version is new on crates.io
id: check
run: |
NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*= *"\(.*\)"/\1/')
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*= *"\(.*\)"/\1/')
echo "name=$NAME" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "User-Agent: ${NAME} release workflow" "https://crates.io/api/v1/crates/${NAME}/${VERSION}")
if [ "$STATUS" = "404" ]; then
echo "is_new=true" >> "$GITHUB_OUTPUT"
elif [ "$STATUS" = "200" ]; then
echo "is_new=false" >> "$GITHUB_OUTPUT"
fi
test:
needs: check-version
if: needs.check-version.outputs.is_new == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
toolchain: [stable, beta]
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Format check
if: matrix.os == 'ubuntu-latest' && matrix.toolchain == 'stable'
run: cargo fmt --all -- --check
- name: Clippy
if: matrix.os == 'ubuntu-latest' && matrix.toolchain == 'stable'
run: cargo clippy --all-targets -- -D warnings
- name: Build
run: cargo build --release --verbose
- name: Test
run: cargo test --release --verbose
- name: Doctests
run: cargo test --doc --verbose
- name: Docs build
if: matrix.os == 'ubuntu-latest' && matrix.toolchain == 'stable'
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps
publish:
needs: [check-version, test]
if: needs.check-version.outputs.is_new == 'true'
runs-on: ubuntu-latest
environment: crates-io
permissions:
contents: write
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
- name: Tag release
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
TAG="v${{ needs.check-version.outputs.version }}"
git tag "$TAG"
git push origin "$TAG"