Tweak the release process: no more merge to main (#7994)

This commit is contained in:
Jack Amadeo 2026-03-23 09:30:44 -04:00 committed by GitHub
parent 69e7fdc4b5
commit 59c74e1b7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 403 additions and 327 deletions

View file

@ -7,7 +7,11 @@ Push the release tag to trigger the release:
git fetch && git tag v{{VERSION}} origin/release/{{VERSION}}
git push origin v{{VERSION}}
```
This PR will auto-merge once the tag is pushed.
The tag push will trigger the release build. This PR will be automatically closed.
## Cherry-Picks
If you need to include additional fixes, cherry-pick them into the `release/{{VERSION}}` branch before tagging.
## Important Notes

View file

@ -18,7 +18,7 @@ jobs:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Check all PR commits exist in main
- name: Check all PR commits are empty or cherry-picked from main
run: |
git fetch origin main
@ -39,19 +39,25 @@ jobs:
exit 0
fi
COMMIT_COUNT=$(echo "$MISSING_COMMITS" | wc -l)
FIRST_COMMIT=$(git rev-list --reverse HEAD ^origin/main | head -1)
ALL_EMPTY=true
for commit in $MISSING_COMMITS; do
if [ -n "$(git diff-tree --no-commit-id --name-only -r "$commit")" ]; then
ALL_EMPTY=false
break
fi
done
if [ "$COMMIT_COUNT" -eq 1 ] && echo "$MISSING_COMMITS" | grep -q "$FIRST_COMMIT"; then
echo "✅ Only version bump commit is unique"
git log --oneline -1 "$FIRST_COMMIT"
else
echo "❌ Found commits that should exist in main:"
if [ "$ALL_EMPTY" = true ]; then
echo "✅ Only empty commits (release branch markers) are unique"
for commit in $MISSING_COMMITS; do
if [ "$commit" != "$FIRST_COMMIT" ]; then
git log --oneline -1 "$commit"
fi
git log --oneline -1 "$commit"
done
echo "Make sure commits have equivalents in main. If you've since updated main, re-run this job"
exit 1
exit 0
fi
echo "❌ Found commits with changes that don't exist in main:"
for commit in $MISSING_COMMITS; do
git log --oneline -1 "$commit"
done
echo "Cherry-pick these commits into main first, or re-run this job after updating main."
exit 1

View file

@ -0,0 +1,59 @@
name: Close release PR on tag push
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
permissions:
actions: write
contents: write
pull-requests: write
jobs:
close-release-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Extract version from tag
id: version
env:
TAG: ${{ github.ref_name }}
run: |
VERSION=${TAG#v}
BRANCH="release/${VERSION}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
echo "Tag: ${TAG}"
echo "Version: ${VERSION}"
echo "Expected branch: ${BRANCH}"
- name: Find and close matching PR
env:
GH_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.version.outputs.branch }}
TAG: ${{ steps.version.outputs.tag }}
VERSION: ${{ steps.version.outputs.version }}
run: |
PR_NUMBER=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -z "$PR_NUMBER" ]; then
echo " No open PR found for branch: $BRANCH (may already be closed)"
else
echo "✅ Found PR #$PR_NUMBER for branch: $BRANCH"
gh pr close "$PR_NUMBER" --comment "Release $TAG has been tagged and pushed. Closing this PR (version bump was already merged to main)."
echo "✅ Closed PR #$PR_NUMBER"
fi
- name: Trigger patch release
env:
BRANCH: ${{ steps.version.outputs.branch }}
GH_TOKEN: ${{ github.token }}
run: |
gh workflow run patch-release.yaml \
--field target_branch=$BRANCH

View file

@ -0,0 +1,88 @@
name: Create Release Branch
on:
pull_request:
types:
- closed
branches:
- main
permissions:
contents: write
pull-requests: write
jobs:
create-release-branch:
runs-on: ubuntu-latest
if: >
github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'version-bump/')
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 0
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: Extract version and base branch
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(just get-tag-version)
BASE_BRANCH="${{ github.event.pull_request.base.ref }}"
echo "version=$VERSION" >> $GITHUB_ENV
echo "base_branch=$BASE_BRANCH" >> $GITHUB_ENV
echo "Version: $VERSION"
echo "Base branch: $BASE_BRANCH"
PRIOR_TAG=$(just get-prior-version "$VERSION")
if [[ -z "$PRIOR_TAG" ]]; then
echo "No prior version (first release), using first commit"
PRIOR_TAG=$(git rev-list --max-parents=0 HEAD)
fi
echo "prior_ref=$PRIOR_TAG" >> $GITHUB_ENV
echo "Prior ref: $PRIOR_TAG"
- name: Create release branch
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
BRANCH_NAME="release/${{ env.version }}"
git switch -c "$BRANCH_NAME"
# Add an empty commit so GitHub can represent this as a PR
git commit --allow-empty --message "chore(release): open release branch for ${{ env.version }}"
git push origin "$BRANCH_NAME"
HEAD_REF=$(git rev-parse HEAD)
echo "branch_name=$BRANCH_NAME" >> $GITHUB_ENV
echo "head_ref=$HEAD_REF" >> $GITHUB_ENV
- name: Generate release notes
uses: ./.github/actions/generate-release-pr-body
with:
version: ${{ env.version }}
head_ref: ${{ env.head_ref }}
prior_ref: ${{ env.prior_ref }}
- name: Create Release PR
run: |
PR_URL=$(gh pr create \
-B "${{ env.base_branch }}" \
-H "${{ env.branch_name }}" \
--title "chore(release): release version ${{ env.version }}" \
--body-file pr_body.txt)
echo "pr_url=$PR_URL" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post release checklist comment
run: |
sed 's/{{VERSION}}/${{ env.version }}/g' RELEASE_CHECKLIST.md > checklist_comment.md
gh pr comment "${{ env.pr_url }}" --body-file checklist_comment.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,118 +0,0 @@
name: Release Workflow
on:
workflow_call:
inputs:
bump_type:
description: 'Type of version bump (minor or patch)'
required: true
type: string
target_branch:
description: 'Target branch for the pull request'
required: false
type: string
default: 'main'
secrets:
ANTHROPIC_API_KEY:
required: false
OPENAI_API_KEY:
required: false
GOOGLE_API_KEY:
required: false
OPENROUTER_API_KEY:
required: false
XAI_API_KEY:
required: false
TETRATE_API_KEY:
required: false
permissions:
contents: write
pull-requests: write
jobs:
create-release:
runs-on: ubuntu-latest
env:
BUMP_TYPE: ${{ inputs.bump_type }}
TARGET_BRANCH: ${{ inputs.target_branch }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ inputs.target_branch }}
fetch-depth: 0 # to generate complete release log
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: Validate input and set old version
run: |
if [[ "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "patch" ]]; then
echo "Error: bump_type must be 'minor' or 'patch'"
exit 1
fi
- name: install dependencies
run: |
sudo apt update -y
sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev
- name: create release branch
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
TETRATE_API_KEY: ${{ secrets.TETRATE_API_KEY }}
run: |
PRIOR_VERSION=$(just get-tag-version)
if [[ "$BUMP_TYPE" == "minor" ]]; then
VERSION=$(just get-next-minor-version)
else
VERSION=$(just get-next-patch-version)
fi
echo "prior_ref=v$PRIOR_VERSION" >> $GITHUB_ENV
echo "version=$VERSION" >> $GITHUB_ENV
echo "Version: $VERSION"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
just prepare-release $VERSION
BRANCH_NAME=$(git branch --show-current)
HEAD_REF=$(git rev-parse HEAD)
echo "branch_name=$BRANCH_NAME" >> $GITHUB_ENV
echo "head_ref=$HEAD_REF" >> $GITHUB_ENV
echo "Branch: $BRANCH_NAME"
- name: push release branch
run: |
git push origin "${{ env.branch_name }}"
- name: Generate release notes
uses: ./.github/actions/generate-release-pr-body
with:
version: ${{ env.version }}
head_ref: ${{ env.head_ref }}
prior_ref: ${{ env.prior_ref }}
- name: Create Pull Request
run: |
PR_URL=$(gh pr create \
-B "$TARGET_BRANCH" \
-H "${{ env.branch_name }}" \
--title "chore(release): release version ${{ env.version }} ($BUMP_TYPE)" \
--body-file pr_body.txt)
echo "pr_url=$PR_URL" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post release checklist comment
run: |
sed 's/{{VERSION}}/${{ env.version }}/g' RELEASE_CHECKLIST.md > checklist_comment.md
gh pr comment "${{ env.pr_url }}" --body-file checklist_comment.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -0,0 +1,77 @@
name: Create Version Bump PR
on:
workflow_call:
secrets:
ANTHROPIC_API_KEY:
required: false
OPENAI_API_KEY:
required: false
GOOGLE_API_KEY:
required: false
OPENROUTER_API_KEY:
required: false
XAI_API_KEY:
required: false
TETRATE_API_KEY:
required: false
permissions:
contents: write
pull-requests: write
jobs:
create-version-bump:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: main
fetch-depth: 0
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: install dependencies
run: |
sudo apt update -y
sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev
- name: Compute version and create bump branch
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
TETRATE_API_KEY: ${{ secrets.TETRATE_API_KEY }}
run: |
VERSION=$(just get-next-minor-version)
echo "version=$VERSION" >> $GITHUB_ENV
echo "Version: $VERSION (minor bump on main)"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
BRANCH_NAME="version-bump/$VERSION"
git switch -c "$BRANCH_NAME"
just prepare-release $VERSION
echo "branch_name=$BRANCH_NAME" >> $GITHUB_ENV
- name: Push bump branch
run: |
git push origin "${{ env.branch_name }}"
- name: Create Pull Request
run: |
PR_URL=$(gh pr create \
-B main \
-H "${{ env.branch_name }}" \
--title "chore(release): bump version to ${{ env.version }} (minor)" \
--body "Bumps version to **${{ env.version }}**. Merging this PR will trigger creation of the \`release/${{ env.version }}\` branch and release PR.")
echo "pr_url=$PR_URL" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,148 +0,0 @@
name: Merge release PR on tag push
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
permissions:
actions: write
contents: write
pull-requests: write
checks: read
jobs:
trigger-patch-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Extract version from tag
id: version
env:
TAG: ${{ github.ref_name }}
run: |
VERSION=${TAG#v}
BRANCH="release/${VERSION}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
echo "Tag: ${TAG}"
echo "Version: ${VERSION}"
echo "Expected branch: ${BRANCH}"
- name: Find matching PR
id: find_pr
env:
GH_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.version.outputs.branch }}
run: |
PR_NUMBER=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -z "$PR_NUMBER" ]; then
echo "❌ No open PR found for branch: $BRANCH"
echo "pr_found=false" >> $GITHUB_OUTPUT
exit 1
else
echo "✅ Found PR #$PR_NUMBER for branch: $BRANCH"
echo "pr_found=true" >> $GITHUB_OUTPUT
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
fi
- name: Get PR details and check status
if: steps.find_pr.outputs.pr_found == 'true'
id: pr_status
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.find_pr.outputs.pr_number }}
run: |
PR_DATA=$(gh pr view $PR_NUMBER --json title,headRefName,baseRefName,mergeable,statusCheckRollup)
TITLE=$(echo "$PR_DATA" | jq -r '.title')
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable')
echo "PR Title: $TITLE"
echo "Head Branch: $HEAD_BRANCH"
echo "Base Branch: $BASE_BRANCH"
echo "Mergeable: $MERGEABLE"
if [ "$MERGEABLE" != "MERGEABLE" ]; then
echo "❌ PR is not in a mergeable state: $MERGEABLE"
echo "can_merge=false" >> $GITHUB_OUTPUT
echo "merge_reason=PR is not mergeable (state: $MERGEABLE)" >> $GITHUB_OUTPUT
exit 0
fi
STATUS_CHECKS=$(echo "$PR_DATA" | jq -r '.statusCheckRollup[]? | select(.conclusion != null) | "\(.context): \(.conclusion)"')
FAILED_CHECKS=$(echo "$PR_DATA" | jq -r '.statusCheckRollup[]? | select(.conclusion == "FAILURE" or .conclusion == "CANCELLED" or .conclusion == "TIMED_OUT") | .context')
PENDING_CHECKS=$(echo "$PR_DATA" | jq -r '.statusCheckRollup[]? | select(.conclusion == null) | .context')
echo "Status checks:"
if [ -n "$STATUS_CHECKS" ]; then
echo "$STATUS_CHECKS"
else
echo "No status checks found"
fi
if [ -n "$FAILED_CHECKS" ]; then
echo "❌ Failed checks found:"
echo "$FAILED_CHECKS"
echo "can_merge=false" >> $GITHUB_OUTPUT
echo "merge_reason=Some checks are failing" >> $GITHUB_OUTPUT
exit 0
fi
if [ -n "$PENDING_CHECKS" ]; then
echo "⏳ Pending checks found:"
echo "$PENDING_CHECKS"
echo "can_merge=false" >> $GITHUB_OUTPUT
echo "merge_reason=Some checks are still pending" >> $GITHUB_OUTPUT
exit 0
fi
echo "✅ All checks are passing and PR is ready to merge"
echo "can_merge=true" >> $GITHUB_OUTPUT
- name: Get branch SHA before merge
if: steps.find_pr.outputs.pr_found == 'true' && steps.pr_status.outputs.can_merge == 'true'
id: branch_info
env:
BRANCH: ${{ steps.version.outputs.branch }}
run: |
git fetch origin "$BRANCH"
BRANCH_SHA=$(git rev-parse "origin/$BRANCH")
echo "branch_sha=$BRANCH_SHA" >> $GITHUB_OUTPUT
echo "Branch SHA: $BRANCH_SHA"
- name: Merge PR
if: steps.find_pr.outputs.pr_found == 'true' && steps.pr_status.outputs.can_merge == 'true'
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.find_pr.outputs.pr_number }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
run: |
gh pr merge $PR_NUMBER --squash --delete-branch --subject "Release $VERSION" --body "Auto-merged release PR after tag $TAG was pushed"
- name: Restore branch
if: steps.find_pr.outputs.pr_found == 'true' && steps.pr_status.outputs.can_merge == 'true'
env:
BRANCH: ${{ steps.version.outputs.branch }}
BRANCH_SHA: ${{ steps.branch_info.outputs.branch_sha }}
run: |
git checkout -b "$BRANCH" "$BRANCH_SHA"
git push origin "$BRANCH"
- name: Trigger patch release
env:
BRANCH: ${{ steps.version.outputs.branch }}
GH_TOKEN: ${{ github.token }}
run: |
gh workflow run patch-release.yaml \
--field target_branch=$BRANCH

View file

@ -12,9 +12,7 @@ on:
jobs:
release:
if: github.repository == 'block/goose'
uses: ./.github/workflows/create-release-pr.yaml
with:
bump_type: "minor"
uses: ./.github/workflows/create-version-bump-pr.yaml
secrets:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

View file

@ -1,4 +1,4 @@
name: Create Patch Release PR
name: Create Patch Release
permissions:
contents: write
@ -8,20 +8,87 @@ on:
workflow_dispatch:
inputs:
target_branch:
description: 'Target branch for hotfix'
description: 'Release branch for patch (e.g. release/1.25.0)'
required: true
type: string
jobs:
hotfix:
uses: ./.github/workflows/create-release-pr.yaml
with:
bump_type: "patch"
target_branch: ${{ inputs.target_branch }}
secrets:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
TETRATE_API_KEY: ${{ secrets.TETRATE_API_KEY }}
create-patch-release:
runs-on: ubuntu-latest
env:
TARGET_BRANCH: ${{ inputs.target_branch }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ inputs.target_branch }}
fetch-depth: 0
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: install dependencies
run: |
sudo apt update -y
sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev
- name: Compute version and create release branch
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
TETRATE_API_KEY: ${{ secrets.TETRATE_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(just get-next-patch-version)
echo "version=$VERSION" >> $GITHUB_ENV
echo "Version: $VERSION (patch on $TARGET_BRANCH)"
PRIOR_TAG=$(just get-prior-version "$VERSION")
if [[ -z "$PRIOR_TAG" ]]; then
echo "No prior version (first release), using first commit"
PRIOR_TAG=$(git rev-list --max-parents=0 HEAD)
fi
echo "prior_ref=$PRIOR_TAG" >> $GITHUB_ENV
echo "Prior ref: $PRIOR_TAG"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
BRANCH_NAME="release/$VERSION"
git switch -c "$BRANCH_NAME"
just prepare-release $VERSION
git push origin "$BRANCH_NAME"
HEAD_REF=$(git rev-parse HEAD)
echo "branch_name=$BRANCH_NAME" >> $GITHUB_ENV
echo "head_ref=$HEAD_REF" >> $GITHUB_ENV
- name: Generate release notes
uses: ./.github/actions/generate-release-pr-body
with:
version: ${{ env.version }}
head_ref: ${{ env.head_ref }}
prior_ref: ${{ env.prior_ref }}
- name: Create Release PR
run: |
PR_URL=$(gh pr create \
-B "$TARGET_BRANCH" \
-H "${{ env.branch_name }}" \
--title "chore(release): release version ${{ env.version }} (patch)" \
--body-file pr_body.txt)
echo "pr_url=$PR_URL" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post release checklist comment
run: |
sed 's/{{VERSION}}/${{ env.version }}/g' RELEASE_CHECKLIST.md > checklist_comment.md
gh pr comment "${{ env.pr_url }}" --body-file checklist_comment.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -19,12 +19,7 @@ jobs:
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # to generate complete release log
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ github.base_ref }}
path: './prior-version'
fetch-depth: 0
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
@ -39,10 +34,16 @@ jobs:
echo "Version: $VERSION"
- name: Get prior version
working-directory: './prior-version'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PRIOR_VERSION=$(just get-tag-version)
echo "prior_ref=v$PRIOR_VERSION" >> $GITHUB_ENV
PRIOR_TAG=$(just get-prior-version "${{ env.version }}")
if [[ -z "$PRIOR_TAG" ]]; then
echo "No prior version (first release), using first commit"
PRIOR_TAG=$(git rev-list --max-parents=0 HEAD)
fi
echo "prior_ref=$PRIOR_TAG" >> $GITHUB_ENV
echo "Prior ref: $PRIOR_TAG"
- name: Generate release notes
uses: ./.github/actions/generate-release-pr-body

View file

@ -306,20 +306,41 @@ get-next-minor-version:
get-next-patch-version:
@python -c "import sys; v=sys.argv[1].split('.'); print(f'{v[0]}.{v[1]}.{int(v[2])+1}')" $(just get-tag-version)
# set cargo and app versions, must be semver
prepare-release version:
# derive the prior release tag from a version
# patch bump (e.g. 1.25.1): prior is v1.25.0 (deterministic)
# minor bump (e.g. 1.26.0): prior is highest v1.25.* GitHub release
get-prior-version version:
#!/usr/bin/env bash
IFS='.' read -r major minor patch <<< "{{ version }}"
if [[ "$patch" -gt 0 ]]; then
echo "v${major}.${minor}.$((patch - 1))"
elif [[ "$minor" -gt 0 ]]; then
prev_minor=$((minor - 1))
prefix="v${major}.${prev_minor}."
best=$(gh release list --limit 100 --exclude-drafts --exclude-pre-releases \
--json tagName --jq "[.[] | select(.tagName | startswith(\"${prefix}\"))][0].tagName")
if [[ -n "$best" && "$best" != "null" ]]; then
echo "$best"
fi
fi
# update version numbers in all manifests
bump-version version:
@just validate {{ version }} || exit 1
@git switch -c "release/{{ version }}"
@uvx --from=toml-cli toml set --toml-path=Cargo.toml "workspace.package.version" {{ version }}
@cd ui/desktop && pnpm version {{ version }} --no-git-tag-version --allow-same-version
# see --workspace flag https://doc.rust-lang.org/cargo/commands/cargo-update.html
# used to update Cargo.lock after we've bumped versions in Cargo.toml
# update Cargo.lock after bumping versions in Cargo.toml
@cargo update --workspace
@just set-openapi-version {{ version }}
# rebuild canonical model registry and mapping report from models.dev
build-canonical-models:
@cargo run --bin build_canonical_models
# bump version, rebuild canonical models, and commit
prepare-release version:
@just bump-version {{ version }}
@just build-canonical-models
@git add \
Cargo.toml \
Cargo.lock \

View file

@ -2,28 +2,49 @@
You'll generally create one of two release types: a regular feature release (minor version bump like 1.20) or a bug-fixing patch release (patch version bump like 1.20.1).
Regular releases start on main, while patch releases start with an existing release tag. goose uses GitHub actions to automate the creation of release branches. The actual releases are triggered by tags.
For bug-fixing releases, you will cherry-pick fixes into that branch, test, and then release from it.
goose uses GitHub actions to automate the release process. The actual releases are triggered by tags.
## Minor version releases
These are typically done once per week. There is an [action](https://github.com/block/goose/actions/workflows/minor-release.yaml) that cuts the branch every Tuesday, but it can also be triggered manually. Commits from main can be cherry-picked into this branch as needed before release.
These are typically done once per week. The process has two automated phases:
To trigger the release, find [the corresponding PR](https://github.com/block/goose/pulls?q=is%3Apr+%22chore%28release%29%22+%22%28minor%29%22+author%3Aapp%2Fgithub-actions+) and follow the instructions in the PR description.
1. **Version bump PR** — An [action](https://github.com/block/goose/actions/workflows/minor-release.yaml) runs every Tuesday (or can be triggered manually) that creates a PR to bump the version on `main`. Review and merge this PR.
2. **Release branch + PR** — When the version bump PR merges, automation creates a `release/<version>` branch from `main` and opens a release PR with a QA checklist.
From there:
- Test locally if you can (`just run-ui`)
- Cherry-pick any last-minute fixes into the release branch if needed
- Download and test the .zip from the release PR
- When ready, follow the instructions on the release PR to tag and release
To trigger the release, find [the corresponding PR](https://github.com/block/goose/pulls?q=is%3Apr+%22chore%28release%29%22+author%3Aapp%2Fgithub-actions+) and follow the instructions in the PR description.
## Patch version releases
Minor and patch releases both trigger the creation of a branch for a follow-on patch release. These branches can be used to create patch releases, or can be safely ignored/closed.
You can cherry pick fixes into this branch.
When a minor release is tagged, automation immediately creates the next patch release branch (e.g. `release/1.25.1` from `release/1.25.0`) with the version already bumped and a release PR open. Cherry-pick fixes into this branch, then tag when ready.
To trigger the release, find [the corresponding PR](https://github.com/block/goose/pulls?q=is%3Apr+%22chore%28release%29%22+%22%28patch%29%22+author%3Aapp%2Fgithub-actions+) and follow the instructions in the PR description.
## High level release flow:
* check out and cherry-pick (if needed) changes to the branch you are going to release (eg the patch branch)
* Test locally if you can (just run-ui)
* Push changes to that branch, wait for build
* Download and test the .zip from the release PR
* If happy, follow the instructions on the release PR to tag and release (tagging will trigger the real release from there)
```
minor-release (cron/manual)
version-bump PR → main (merge this)
▼ (on merge)
release/<V> branch created from main
release PR opened (for QA, cherry-picks, testing)
▼ (when ready)
git tag v<V> origin/release/<V> && git push origin v<V>
├─► release PR auto-closed (no merge needed)
├─► release.yml builds & publishes
└─► patch release/<V+1> branch + PR auto-created
▼ (cherry-pick fixes, then when ready)
git tag v<V+1> origin/release/<V+1> && git push origin v<V+1>
```