name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
verify:
name: Verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- run: cargo fmt --check
- run: cargo clippy --all-targets --all-features -- -D warnings
- run: cargo test --all-features
- name: Verify package
run: cargo package --locked
- name: Tag matches crate version
if: startsWith(github.ref, 'refs/tags/')
run: |
crate_version="$(cargo metadata --format-version 1 --no-deps \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["packages"][0]["version"])')"
tag_version="${GITHUB_REF_NAME#v}"
echo "crate=$crate_version tag=$tag_version"
test "$crate_version" = "$tag_version"
publish:
name: Publish crates.io
if: startsWith(github.ref, 'refs/tags/')
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- name: Check whether this version is already on crates.io
id: published
run: |
version="${GITHUB_REF_NAME#v}"
status="$(curl -sS -o /dev/null -w '%{http_code}' \
-H 'User-Agent: opi release workflow' \
"https://crates.io/api/v1/crates/opi/${version}")"
echo "already=$([ "$status" = "200" ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
echo "crates.io returned $status for opi ${version}"
- name: Publish crate
if: steps.published.outputs.already != 'true'
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --locked
release:
name: GitHub Release
if: startsWith(github.ref, 'refs/tags/')
needs: publish
runs-on: ubuntu-latest
steps:
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true