name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- name: Tag matches Cargo.toml and pyproject.toml versions
run: |
tag="${GITHUB_REF_NAME#v}"
cargo_ver=$(grep -m1 '^version[[:space:]]*=' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')
py_ver=$(grep -m1 '^version[[:space:]]*=' pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')
echo "tag=$tag Cargo.toml=$cargo_ver pyproject.toml=$py_ver"
if [ -z "$tag" ] || [ -z "$cargo_ver" ] || [ -z "$py_ver" ]; then
echo "::error::could not parse a version (tag='$tag' cargo='$cargo_ver' pyproject='$py_ver')"
exit 1
fi
if [ "$tag" != "$cargo_ver" ]; then
echo "::error::git tag v$tag does not match Cargo.toml version $cargo_ver"
exit 1
fi
if [ "$tag" != "$py_ver" ]; then
echo "::error::git tag v$tag does not match pyproject.toml version $py_ver"
exit 1
fi
echo "OK: tag and both manifests agree on version $tag"
- name: Tests (all features)
run: cargo test --all-features --all
- name: Clippy (all features, all targets)
run: cargo clippy --all-features --all-targets -- -D warnings
- name: Check formatting
run: cargo fmt -- --check
- name: Build docs (deny warnings)
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps --all-features
- name: Crate packaging dry-run
run: cargo publish --dry-run
build-wheels:
needs: verify
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
manylinux: manylinux2014
- os: macos-latest
target: x86_64-apple-darwin
- os: macos-latest
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --features python
manylinux: ${{ matrix.manylinux || 'auto' }}
- uses: actions/upload-artifact@v4
with:
name: wheel-${{ matrix.target }}
path: target/wheels/*.whl
build-sdist:
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: PyO3/maturin-action@v1
with:
command: sdist
- uses: actions/upload-artifact@v4
with:
name: sdist
path: target/wheels/*.tar.gz
publish-crate:
needs: [build-wheels, build-sdist]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Publish to crates.io
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
publish-pypi:
needs: [build-wheels, build-sdist, publish-crate]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
path: dist/
merge-multiple: true
- uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
packages-dir: dist/
github-release:
needs: [publish-crate, publish-pypi]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: dist/
merge-multiple: true
- name: Create release
run: |
gh release create ${{ github.ref_name }} \
--title "${{ github.ref_name }}" \
--notes "See [CHANGELOG.md](CHANGELOG.md) for full details." \
dist/*
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}