name: Release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
tag:
description: "Tag to release (e.g. v0.1.0)"
required: true
type: string
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
verify:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Tag must match Cargo.toml version
id: version
run: |
tag="${{ github.event.inputs.tag || github.ref_name }}"
tag_version="${tag#v}"
crate_version=$(cargo metadata --no-deps --format-version 1 \
| jq -r '.packages[0].version')
if [ "$tag_version" != "$crate_version" ]; then
echo "::error::tag $tag implies version $tag_version, but Cargo.toml says $crate_version"
exit 1
fi
echo "version=$crate_version" >> "$GITHUB_OUTPUT"
echo "releasing $crate_version"
- name: Reject a pre-release version on a stable tag
run: |
tag="${{ github.event.inputs.tag || github.ref_name }}"
if [[ "${{ steps.version.outputs.version }}" == *-* && "$tag" != *-* ]]; then
echo "::error::Cargo.toml holds a pre-release version but the tag does not"
exit 1
fi
check:
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with: { components: rustfmt, clippy }
- uses: Swatinem/rust-cache@v2
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features
- run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
- name: Verify the packaged crate builds
run: cargo publish --dry-run --all-features
publish:
needs: [verify, check]
runs-on: ubuntu-latest
environment: crates-io
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Publish to crates.io
run: cargo publish --all-features
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
github-release:
needs: [verify, publish]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build release notes
id: notes
run: |
tag="${{ github.event.inputs.tag || github.ref_name }}"
previous=$(git describe --tags --abbrev=0 "${tag}^" 2>/dev/null || true)
{
echo "## meterstore ${{ needs.verify.outputs.version }}"
echo
if [ -n "$previous" ]; then
echo "### Changes since $previous"
echo
git log --no-merges --pretty='- %s (%h)' "$previous..$tag"
else
echo "First release."
fi
echo
echo '```toml'
echo 'meterstore = "${{ needs.verify.outputs.version }}"'
echo '```'
} > notes.md
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
body_path: notes.md
prerelease: ${{ contains(needs.verify.outputs.version, '-') }}