name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
publish:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Read crate metadata
id: meta
run: |
python - <<'PY' >> "$GITHUB_OUTPUT"
import json
import subprocess
metadata = json.loads(
subprocess.check_output(
["cargo", "metadata", "--no-deps", "--format-version", "1"],
text=True,
)
)
package = metadata["packages"][0]
print(f"name={package['name']}")
print(f"version={package['version']}")
PY
- name: Verify tag matches crate version
env:
CRATE_VERSION: ${{ steps.meta.outputs.version }}
run: |
tag_version="${GITHUB_REF_NAME#v}"
if [ "$tag_version" != "$CRATE_VERSION" ]; then
echo "tag $GITHUB_REF_NAME does not match Cargo.toml version $CRATE_VERSION" >&2
exit 1
fi
- name: Verify release tag points to main
run: |
git fetch origin main
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
echo "release tags must point to a commit reachable from origin/main" >&2
exit 1
fi
- run: cargo fmt -- --check
- run: cargo clippy --locked --all-targets --all-features -- -D warnings
- run: cargo test --locked
- run: cargo package --locked
- run: cargo publish --dry-run --locked
- name: Check crates.io for existing version
id: crates
env:
CRATE_NAME: ${{ steps.meta.outputs.name }}
CRATE_VERSION: ${{ steps.meta.outputs.version }}
run: |
status_code="$(
curl -s -o /dev/null -w "%{http_code}" \
-H "User-Agent: diskr-release-workflow" \
-H "Accept: application/json" \
"https://crates.io/api/v1/crates/$CRATE_NAME/$CRATE_VERSION"
)"
if [ "$status_code" = "200" ]; then
echo "already_published=true" >> "$GITHUB_OUTPUT"
elif [ "$status_code" = "404" ]; then
echo "already_published=false" >> "$GITHUB_OUTPUT"
else
echo "unexpected crates.io status: $status_code" >&2
exit 1
fi
- name: Publish to crates.io
if: steps.crates.outputs.already_published != 'true'
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
echo "CARGO_REGISTRY_TOKEN secret is not configured" >&2
exit 1
fi
cargo publish --locked
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}