name: Release
on:
workflow_dispatch:
inputs:
version:
description: "Crate version to publish (e.g., 0.2.0)"
required: true
type: string
dry_run:
description: "Run cargo publish --dry-run only"
required: false
default: false
type: boolean
env:
CARGO_TERM_COLOR: always
jobs:
release:
name: Publish
runs-on: ubuntu-latest
environment:
name: release
permissions:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure Git
run: |
git config --global user.name "movable-ref release bot"
git config --global user.email "actions@github.com"
- name: Install Rust (stable)
uses: dtolnay/rust-toolchain@stable
with:
components: cargo,clippy
- name: Install release tooling
run: cargo install cargo-edit --locked
- name: Verify working tree is clean
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "Working tree is not clean" >&2
git status --short >&2
exit 1
fi
- name: Update crate version
run: cargo set-version ${{ inputs.version }}
- name: Tests
run: |
cargo test
cargo clippy --all-targets -- -D warnings
- name: Commit version bump
if: ${{ !inputs.dry_run }}
run: |
git add Cargo.toml Cargo.lock || true
git commit -m "Release ${{ inputs.version }}"
- name: Cargo publish (dry-run)
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
if [ "${{ inputs.dry_run }}" = "true" ]; then
cargo publish --dry-run --allow-dirty
else
cargo publish --dry-run
fi
- name: Cargo publish
if: ${{ !inputs.dry_run }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish
- name: Push changes
if: ${{ !inputs.dry_run }}
run: git push origin HEAD:main
- name: Create tag
if: ${{ !inputs.dry_run }}
run: |
git tag v${{ inputs.version }}
git push origin v${{ inputs.version }}
- name: Create GitHub release
if: ${{ !inputs.dry_run }}
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ inputs.version }}
name: v${{ inputs.version }}
body_path: RELEASE_NOTES.md