name: Release
on:
push:
tags: ["v*"]
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
jobs:
verify:
name: verify tag
runs-on: ubuntu-latest
outputs:
version: ${{ steps.check.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- id: check
run: |
set -euo pipefail
tag="${GITHUB_REF_NAME#v}"
manifest=$(cargo metadata --no-deps --format-version 1 \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["packages"][0]["version"])')
if [ "$tag" != "$manifest" ]; then
echo "::error::tag v$tag does not match Cargo.toml version $manifest"
exit 1
fi
grep -q "\[$manifest\]" CHANGELOG.md \
|| { echo "::error::CHANGELOG.md has no section for $manifest"; exit 1; }
echo "version=$manifest" >> "$GITHUB_OUTPUT"
gates:
name: gates
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- run: cargo fmt --all --check
- run: cargo clippy --locked --all-features --all-targets -- -D warnings
- run: cargo test --locked --all-features --all-targets
- run: cargo test --locked --all-features --doc
- run: cargo package --locked
publish:
name: publish to crates.io
needs: [verify, gates]
runs-on: ubuntu-latest
environment: crates-io
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- run: cargo publish --locked
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
github-release:
name: github release
needs: [verify, publish]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- name: Create release from the changelog section
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.verify.outputs.version }}
run: |
set -euo pipefail
python3 - "$VERSION" > body.md <<'PY'
import re, sys
version = sys.argv[1]
text = open("CHANGELOG.md").read()
m = re.search(
rf"^## \[{re.escape(version)}\].*?$(.*?)(?=^## \[|\Z)",
text, re.M | re.S)
sys.stdout.write(m.group(1).strip() if m else "")
PY
gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file body.md