Hotfix release branches #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow is intended to be manually triggered via the GitHub Action tab. | |
# Given a hotfix branch, it will attempt to open a PR to all release branches and | |
# by default auto merge them | |
name: Hotfix release branches | |
on: | |
workflow_dispatch: | |
inputs: | |
hotfix_commit: | |
description: 'Hotfix commit hash' | |
required: true | |
hotfix_suffix: | |
description: 'Hotfix branch suffix (e.g. hotfix/v0.8-{suffix})' | |
required: true | |
release_branch_pattern: | |
description: 'Release branch pattern (regex)' | |
required: true | |
default: 'release/.*' | |
auto_merge: | |
description: 'Automatically merge the PRs if set to true' | |
required: false | |
default: 'true' | |
jobs: | |
hotfix_release_branches: | |
# See https://runs-on.com/runners/linux/ | |
# use a lower powered instance since this just does i/o to docker hub | |
runs-on: [runs-on,runner=2cpu-linux-x64,"run-id=${{ github.run_id }}"] | |
steps: | |
- name: Checkout Repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Fetch All Branches | |
run: | | |
git fetch --all --prune | |
- name: Verify Hotfix Commit Exists | |
run: | | |
git rev-parse --verify "${{ github.event.inputs.hotfix_commit }}" || { echo "Commit not found: ${{ github.event.inputs.hotfix_commit }}"; exit 1; } | |
- name: Get Release Branches | |
id: get_release_branches | |
run: | | |
BRANCHES=$(git branch -r | grep -E "${{ github.event.inputs.release_branch_pattern }}" | sed 's|origin/||' | tr -d ' ') | |
if [ -z "$BRANCHES" ]; then | |
echo "No release branches found matching pattern '${{ github.event.inputs.release_branch_pattern }}'." | |
exit 1 | |
fi | |
echo "Found release branches:" | |
echo "$BRANCHES" | |
# Join the branches into a single line separated by commas | |
BRANCHES_JOINED=$(echo "$BRANCHES" | tr '\n' ',' | sed 's/,$//') | |
# Set the branches as an output | |
echo "branches=$BRANCHES_JOINED" >> $GITHUB_OUTPUT | |
- name: Create and Merge Pull Requests to Matching Release Branches | |
env: | |
HOTFIX_COMMIT: ${{ github.event.inputs.hotfix_commit }} | |
HOTFIX_SUFFIX: ${{ github.event.inputs.hotfix_suffix }} | |
AUTO_MERGE: ${{ github.event.inputs.auto_merge }} | |
run: | | |
# Get the branches from the previous step | |
BRANCHES="${{ steps.get_release_branches.outputs.branches }}" | |
# Convert BRANCHES to an array | |
IFS=$',' read -ra BRANCH_ARRAY <<< "$BRANCHES" | |
# Loop through each release branch and create and merge a PR | |
for RELEASE_BRANCH in "${BRANCH_ARRAY[@]}"; do | |
echo "Processing $RELEASE_BRANCH..." | |
# Parse out the release version by removing "release/" from the branch name | |
RELEASE_VERSION=${RELEASE_BRANCH#release/} | |
echo "Release version parsed: $RELEASE_VERSION" | |
HOTFIX_BRANCH="hotfix/${RELEASE_VERSION}-${HOTFIX_SUFFIX}" | |
echo "Creating PR from $HOTFIX_BRANCH to $RELEASE_BRANCH" | |
# Checkout the release branch | |
echo "Checking out $RELEASE_BRANCH" | |
git checkout "$RELEASE_BRANCH" | |
# Create the new hotfix branch | |
echo "Branching $RELEASE_BRANCH to $HOTFIX_BRANCH" | |
git checkout -b "$HOTFIX_BRANCH" | |
# Cherry-pick the hotfix commit | |
echo "Cherry picking commit hash $HOTFIX_COMMIT onto $HOTFIX_BRANCH" | |
git cherry-pick "$HOTFIX_COMMIT" | |
if [ $? -ne 0 ]; then | |
echo "Cherry-pick failed for $HOTFIX_COMMIT on $HOTFIX_BRANCH. Aborting..." | |
git cherry-pick --abort | |
continue | |
fi | |
# Push the hotfix branch to the remote | |
echo "Pushing $HOTFIX_BRANCH..." | |
git push origin "$HOTFIX_BRANCH" | |
echo "Hotfix branch $HOTFIX_BRANCH created and pushed." | |
# Check if PR already exists | |
EXISTING_PR=$(gh pr list --head "$HOTFIX_BRANCH" --base "$RELEASE_BRANCH" --state open --json number --jq '.[0].number') | |
if [ -n "$EXISTING_PR" ]; then | |
echo "An open PR already exists: #$EXISTING_PR. Skipping..." | |
continue | |
fi | |
# Create a new PR | |
PR_URL=$(gh pr create --title "Merge $HOTFIX_BRANCH into $RELEASE_BRANCH" \ | |
--body "Automated PR to merge \`$HOTFIX_BRANCH\` into \`$RELEASE_BRANCH\`." \ | |
--head "$HOTFIX_BRANCH" --base "$RELEASE_BRANCH" --json url --jq '.url') | |
echo "Pull request created: $PR_URL" | |
# Extract PR number from URL | |
PR_NUMBER=$(basename "$PR_URL") | |
if [ "$AUTO_MERGE" == "true" ]; then | |
echo "Attempting to merge pull request #$PR_NUMBER" | |
# Attempt to merge the PR | |
gh pr merge "$PR_NUMBER" --merge --yes | |
if [ $? -eq 0 ]; then | |
echo "Pull request #$PR_NUMBER merged successfully." | |
else | |
# Optionally, handle the error or continue | |
echo "Failed to merge pull request #$PR_NUMBER." | |
fi | |
fi | |
done |