name: Release
on:
push:
branches: [main]
paths: ['Cargo.toml']
workflow_dispatch:
concurrency: release
permissions:
contents: write
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
new: ${{ steps.tag.outputs.new }}
version: ${{ steps.v.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
- name: Resolve version from Cargo.toml
id: v
run: echo "version=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[0].version')" >> "$GITHUB_OUTPUT"
- name: Is this version already tagged?
id: tag
run: |
if git rev-parse "v${{ steps.v.outputs.version }}" >/dev/null 2>&1; then
echo "new=false" >> "$GITHUB_OUTPUT"
echo "v${{ steps.v.outputs.version }} already exists - nothing to release"
else
echo "new=true" >> "$GITHUB_OUTPUT"
fi
- name: Require a changelog entry
if: steps.tag.outputs.new == 'true'
run: grep -q "^## \[${{ steps.v.outputs.version }}\]" CHANGELOG.md
publish:
needs: prepare
if: needs.prepare.outputs.new == 'true'
runs-on: ubuntu-latest
environment: crates-io
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
- name: Extract release notes for this version
run: |
awk -v ver="${{ needs.prepare.outputs.version }}" '
$0 ~ ("^## \\[" ver "\\]") { capture=1; next }
capture && /^## \[/ { exit }
capture && /^\[.*\]:/ { exit }
capture { print }
' CHANGELOG.md > "$RUNNER_TEMP/RELEASE_NOTES.md"
cat "$RUNNER_TEMP/RELEASE_NOTES.md"
- name: Publish to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
- name: Tag and create the GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.prepare.outputs.version }}
name: v${{ needs.prepare.outputs.version }}
body_path: ${{ runner.temp }}/RELEASE_NOTES.md