name: Release
on:
push:
branches:
- main
paths:
- Cargo.toml
release:
types: [published]
jobs:
create-release:
name: Create GitHub release
if: github.event_name == 'push'
runs-on: macos-latest
permissions:
contents: write
outputs:
changed: ${{ steps.version.outputs.changed }}
tag: ${{ steps.version.outputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Check whether version changed
id: version
shell: bash
run: |
set -euo pipefail
NEW_VERSION="$(
cargo metadata --no-deps --format-version 1 |
python3 -c '
import json, sys
data = json.load(sys.stdin)
for package in data["packages"]:
if package["name"] == "multitouch":
print(package["version"])
break
'
)"
BEFORE="${{ github.event.before }}"
# Get the previous Cargo.toml from before this push.
if [[ "$BEFORE" == "0000000000000000000000000000000000000000" ]]; then
echo "No previous commit to compare against."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
OLD_VERSION="$(
git show "${BEFORE}:Cargo.toml" |
python3 -c '
import sys, tomllib
data = tomllib.loads(sys.stdin.read())
print(data["package"]["version"])
'
)"
echo "Previous version: $OLD_VERSION"
echo "Current version: $NEW_VERSION"
if [[ "$OLD_VERSION" == "$NEW_VERSION" ]]; then
echo "Cargo.toml changed, but the package version did not."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
TAG="v${NEW_VERSION}"
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Verify package
if: steps.version.outputs.changed == 'true'
run: cargo publish --package multitouch --dry-run
- name: Create tag and GitHub release
if: steps.version.outputs.changed == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail
# Makes this idempotent if the workflow is re-run.
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists."
exit 0
fi
gh release create "$TAG" \
--target "$GITHUB_SHA" \
--title "$TAG" \
--generate-notes
publish:
name: Publish to crates.io
needs: create-release
if: >-
always() &&
(
(
github.event_name == 'push' &&
needs.create-release.result == 'success' &&
needs.create-release.outputs.changed == 'true'
) ||
github.event_name == 'release'
)
runs-on: macos-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Verify release version
env:
CREATED_TAG: ${{ needs.create-release.outputs.tag }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
shell: bash
run: |
set -euo pipefail
VERSION="$(
cargo metadata --no-deps --format-version 1 |
python3 -c '
import json, sys
data = json.load(sys.stdin)
for package in data["packages"]:
if package["name"] == "multitouch":
print(package["version"])
break
'
)"
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="$RELEASE_TAG"
else
TAG="$CREATED_TAG"
fi
EXPECTED="v${VERSION}"
if [[ "$TAG" != "$EXPECTED" ]]; then
echo "Release tag '$TAG' does not match Cargo.toml version '$EXPECTED'."
exit 1
fi
echo "Publishing multitouch $VERSION"
- name: Authenticate with crates.io
id: auth
uses: rust-lang/crates-io-auth-action@v1
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
run: cargo publish --package multitouch