mirror of
https://github.com/block/goose.git
synced 2026-04-28 03:29:36 +00:00
Tweak the release process: no more merge to main (#7994)
This commit is contained in:
parent
69e7fdc4b5
commit
59c74e1b7d
12 changed files with 403 additions and 327 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
32
.github/workflows/check-release-pr.yaml
vendored
32
.github/workflows/check-release-pr.yaml
vendored
|
|
@ -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
|
||||
|
|
|
|||
59
.github/workflows/close-release-pr-on-tag.yaml
vendored
Normal file
59
.github/workflows/close-release-pr-on-tag.yaml
vendored
Normal 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
|
||||
88
.github/workflows/create-release-branch.yaml
vendored
Normal file
88
.github/workflows/create-release-branch.yaml
vendored
Normal 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 }}
|
||||
118
.github/workflows/create-release-pr.yaml
vendored
118
.github/workflows/create-release-pr.yaml
vendored
|
|
@ -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 }}
|
||||
77
.github/workflows/create-version-bump-pr.yaml
vendored
Normal file
77
.github/workflows/create-version-bump-pr.yaml
vendored
Normal 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 }}
|
||||
148
.github/workflows/merge-release-pr-on-tag.yaml
vendored
148
.github/workflows/merge-release-pr-on-tag.yaml
vendored
|
|
@ -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
|
||||
4
.github/workflows/minor-release.yaml
vendored
4
.github/workflows/minor-release.yaml
vendored
|
|
@ -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 }}
|
||||
|
|
|
|||
95
.github/workflows/patch-release.yaml
vendored
95
.github/workflows/patch-release.yaml
vendored
|
|
@ -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 }}
|
||||
|
|
|
|||
19
.github/workflows/update-release-pr.yaml
vendored
19
.github/workflows/update-release-pr.yaml
vendored
|
|
@ -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
|
||||
|
|
|
|||
37
Justfile
37
Justfile
|
|
@ -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 \
|
||||
|
|
|
|||
47
RELEASE.md
47
RELEASE.md
|
|
@ -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>
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue