name: release
on:
push:
tags: ["v*"]
permissions:
contents: read
jobs:
verify:
name: Verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Tag points at main
run: |
git fetch --no-tags origin "+refs/heads/main:refs/remotes/origin/main"
git merge-base --is-ancestor "$GITHUB_SHA" refs/remotes/origin/main
- name: Tag matches Cargo.toml version
run: |
version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)"
if [ "v${version}" != "$GITHUB_REF_NAME" ]; then
echo "tag $GITHUB_REF_NAME does not match Cargo.toml version $version"
exit 1
fi
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- run: cargo fmt --check
- run: cargo clippy --all-targets --locked -- -D warnings
- run: cargo test --locked
publish:
name: Publish
needs: verify
runs-on: ubuntu-latest
permissions:
contents: write id-token: write steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check if the version is already published
id: published
run: |
package="$(sed -n 's/^name = "\(.*\)"$/\1/p' Cargo.toml | head -n1)"
version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)"
status="$(curl -sS -o /dev/null -w '%{http_code}' \
-A 'atomic-bitflags release workflow' \
"https://crates.io/api/v1/crates/${package}/${version}")"
if [ "$status" = "200" ]; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "${package} ${version} is already on crates.io; skipping publish"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- uses: dtolnay/rust-toolchain@stable
- uses: rust-lang/crates-io-auth-action@v1
id: auth
if: steps.published.outputs.exists != 'true'
- name: Publish to crates.io
if: steps.published.outputs.exists != 'true'
run: cargo publish --locked
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
- name: Create GitHub release
run: |
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
echo "release $GITHUB_REF_NAME already exists"
else
gh release create "$GITHUB_REF_NAME" --generate-notes
fi
env:
GH_TOKEN: ${{ github.token }}