name: Prepare Release
on:
workflow_dispatch:
inputs:
version:
description: "Stable version without v (for example 0.3.0)"
required: true
type: string
permissions:
contents: read
concurrency:
group: prepare-release
cancel-in-progress: false
env:
CARGO_TERM_COLOR: always
jobs:
prepare:
runs-on: ubuntu-24.04
timeout-minutes: 15
environment:
name: release-preparation
deployment: false
env:
GH_REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with:
fetch-depth: 0
persist-credentials: false
- name: Validate release request
env:
VERSION: ${{ inputs.version }}
GH_TOKEN: ${{ github.token }}
run: |
scripts/release/check-version.sh main
scripts/release/check-version.sh stable "$VERSION"
current="$(source scripts/release/lib.sh; release_manifest_version)"
scripts/release/check-version.sh newer "$VERSION" "$current"
if gh release view "v${VERSION}" >/dev/null 2>&1 ||
git ls-remote --exit-code --tags origin "refs/tags/v${VERSION}" >/dev/null 2>&1; then
echo "::error::v${VERSION} already exists as a tag or release"
exit 1
fi
- name: Install cargo-edit
uses: taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 with:
tool: cargo-edit@0.13.13
- name: Build the version commit
env:
VERSION: ${{ inputs.version }}
run: |
branch="release/v${VERSION}"
git checkout -B "$branch" "$GITHUB_SHA"
cargo set-version "$VERSION"
scripts/release/check-version.sh manifest "$VERSION"
unexpected="$(git diff --name-only | grep -Ev '^(Cargo\.toml|Cargo\.lock)$' || true)"
if [ -n "$unexpected" ]; then
echo "::error::version preparation changed unexpected files"
printf '%s\n' "$unexpected"
exit 1
fi
git diff --check
git config user.name "github-actions-release[bot]"
git config user.email "github-actions-release[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock
git commit -m "Bump version to ${VERSION}"
- name: Mint release App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 with:
app-id: ${{ vars.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: ${{ github.event.repository.name }}
- name: Push branch and open the PR
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
VERSION: ${{ inputs.version }}
run: |
branch="release/v${VERSION}"
if git ls-remote --exit-code --heads origin "$branch" >/dev/null 2>&1; then
git fetch origin "$branch:refs/remotes/origin/$branch"
if ! git diff --quiet "origin/$branch" HEAD; then
echo "::error::$branch already exists with different content"
exit 1
fi
else
gh auth setup-git
git push origin "HEAD:$branch"
fi
state="$(gh pr view "$branch" --json state --jq .state 2>/dev/null || echo absent)"
case "$state" in
OPEN)
gh pr view "$branch" --json url --jq .url
;;
absent)
gh pr create \
--base main \
--head "$branch" \
--title "Release v${VERSION}" \
--body "Automated version bump for v${VERSION}. Merge only after the normal required checks pass."
;;
*)
echo "::error::existing PR for $branch is $state, not open"
exit 1
;;
esac