Skip to content
Merged
Changes from all commits
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
48 changes: 44 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ concurrency:

permissions:
contents: write
pull-requests: write

jobs:
publish-rust:
Expand Down Expand Up @@ -107,16 +108,30 @@ jobs:
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' Cargo.toml
cargo update -p "$CRATE_NAME" --precise "$NEXT_VERSION"

- name: Commit version bump and tag
# `main` is protected by a repository ruleset that requires all
# changes to land through a pull request (no direct pushes), and the
# workflow's GITHUB_TOKEN is not on that ruleset's bypass list. So the
# version-bump commit is pushed to a throwaway release branch and
# landed on `main` via an auto-merged PR instead of `git push`ing
# `HEAD` straight at `main` (which the ruleset rejects with GH013).
- name: Commit version bump
id: commit
env:
NEXT_VERSION: ${{ steps.version.outputs.next_version }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

release_branch="release/${RELEASE_TAG}"
git checkout -b "${release_branch}"
git add Cargo.toml Cargo.lock
git commit -m "Release ${RELEASE_TAG}"
git tag -a "${RELEASE_TAG}" -m "Release ${RELEASE_TAG}"
git push origin "${release_branch}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make failed release runs safely retryable

If any step fails after this push but before the PR is merged—for example, packaging or a transient gh pr create failure—the remote release/vX.Y.Z branch remains while main retains the old version. A rerun therefore computes the same branch name, creates a new commit with a different timestamp/SHA, and fails here with a non-fast-forward rejection, requiring manual branch deletion before the release can be retried. Delete or safely replace a stale unmerged release branch, or make the branch name unique per run.

Useful? React with 👍 / 👎.


echo "branch=${release_branch}" >> "$GITHUB_OUTPUT"

# `$CRATE_NAME` (and its path dependency `tinycortex-api`) both carry
# `publish = false` right now: `tinycortex-api` depends on `tinymemory-api`
Expand Down Expand Up @@ -144,11 +159,36 @@ jobs:
if: steps.publishable.outputs.publishable == 'true'
run: cargo package --locked -p "$CRATE_NAME"

- name: Push release commit and tag
- name: Open and merge release PR
id: merge
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
RELEASE_BRANCH: ${{ steps.commit.outputs.branch }}
run: |
git push origin "HEAD:${GITHUB_REF_NAME}"
set -euo pipefail

pr_url="$(gh pr create \
--base "${GITHUB_REF_NAME}" \
--head "${RELEASE_BRANCH}" \
--title "Release ${RELEASE_TAG}" \
--body "Automated version bump for ${RELEASE_TAG}.")"
# This repository allows merge commits only (squash and rebase are
# both disabled), so the release PR must be merged with --merge.
gh pr merge "${pr_url}" --merge --delete-branch

git fetch origin "${GITHUB_REF_NAME}"
merge_sha="$(git rev-parse "origin/${GITHUB_REF_NAME}")"
echo "sha=${merge_sha}" >> "$GITHUB_OUTPUT"
Comment on lines +178 to +180

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive the release tag from the merged PR

When another PR lands between the release PR merge and this fetch, origin/main points at that later commit, so the workflow tags unrelated post-release changes rather than the squash commit produced for this release; the crate is still published from the local release branch, making the tag and published source disagree. The gh pr merge documentation confirms that --squash merges the PR into the base branch, so obtain that PR's mergeCommit SHA directly instead of sampling the moving branch head.

Useful? React with 👍 / 👎.


- name: Tag and push release
env:
RELEASE_TAG: ${{ steps.version.outputs.tag }}
MERGE_SHA: ${{ steps.merge.outputs.sha }}
run: |
set -euo pipefail

git tag -a "${RELEASE_TAG}" -m "Release ${RELEASE_TAG}" "${MERGE_SHA}"
git push origin "${RELEASE_TAG}"

- name: Publish to crates.io
Expand Down