Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions .github/workflows/bump-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: bump-version

on:
workflow_dispatch:
inputs:
version:
description: "New version WITHOUT a leading v, e.g. 3.4.1"
required: true
update_crates:
description: "Run `cargo update` after bumping the version"
required: false
type: boolean
default: false

# Serialize version bumps so two concurrent runs cannot collide.
concurrency:
group: bump-version
cancel-in-progress: false

# Nothing at the top level; the bump job declares exactly what it needs.
permissions:
contents: read

jobs:
bump:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
# Push the version-bump branch.
contents: write
# Open the pull request.
pull-requests: write

steps:
# Reject malformed versions before touching the repository.
- name: Validate version input format
env:
VERSION: ${{ inputs.version }}
run: |
# Match the same version forms the release workflow accepts.
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
echo "::error::version must be semver like 3.4.1 or 3.4.1-rc1 (no leading 'v')."
exit 1
fi

# Ensure bumps are initiated from main so the PR merges cleanly.
- name: Restrict to main branch
# Compare the full ref because branch names alone are ambiguous.
if: github.ref != 'refs/heads/main'
run: |
echo "::error::This workflow must be run from main (ref was '${{ github.ref }}')."
exit 1

- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0, 2026-06-18
with:
ref: main

- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0

# Bump the package version in Cargo.toml.
- name: Update version in Cargo.toml
env:
VERSION: ${{ inputs.version }}
run: |
# Anchored so only the [package] version matches; dependency
# versions are inline or unversioned strings, never `^version = `.
sed -i -E 's/^version = "[^"]*"/version = "'"$VERSION"'"/' Cargo.toml
# Confirm Cargo itself sees the new version before going further.
manifest_version=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[0].version')
if [ "$manifest_version" != "$VERSION" ]; then
echo "::error::Cargo.toml now shows '$manifest_version', expected '$VERSION'."
exit 1
fi

# Optionally refresh the lockfile's dependency versions.
- name: Run cargo update
if: inputs.update_crates
run: cargo update

# Gate the PR on a clean compile, Cargo.lock updates included.
- name: Run cargo check
run: cargo check

- name: Push branch
env:
VERSION: ${{ inputs.version }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
BRANCH="chore/bump-version-v$VERSION"
git checkout -b "$BRANCH"
git add Cargo.toml Cargo.lock
git commit -m "chore: bump version to v$VERSION"
git push origin "$BRANCH"

# Privileged step: runs only after check passes.
- name: Open pull request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
run: |
# GITHUB_TOKEN-created PRs do not trigger other workflows, so CI
# must be dispatched manually; the check above is the verification.
gh pr create \
--base main \
--head "chore/bump-version-v$VERSION" \
--title "chore: bump version to v$VERSION" \
--body "Bump the crate version to v$VERSION (update_crates: ${{ inputs.update_crates }}). Validated with \`cargo check\`; note that CI on this PR will not run automatically because it was created with GITHUB_TOKEN."
Loading