Hotfix release branches #17
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 hotfix PRs' | |
required: true | |
type: choice | |
default: 'true' | |
options: | |
- true | |
- false | |
jobs: | |
hotfix_release_branches: | |
permissions: write-all | |
# 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: | |
# needs RKUO_DEPLOY_KEY for write access to merge PR's | |
- name: Checkout Repository | |
uses: actions/checkout@v4 | |
with: | |
ssh-key: "${{ secrets.RKUO_DEPLOY_KEY }}" | |
fetch-depth: 0 | |
- name: Set up Git user | |
run: | | |
git config user.name "Richard Kuo [bot]" | |
git config user.email "rkuo[bot]@danswer.ai" | |
- 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 | |
# notes on all the vagaries of wiring up automated PR's | |
# https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs | |
# we must use a custom token for GH_TOKEN to trigger the subsequent PR checks | |
- 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 }} | |
GH_TOKEN: ${{ secrets.RKUO_PERSONAL_ACCESS_TOKEN }} | |
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 | |
if git rev-parse --verify "$HOTFIX_BRANCH" >/dev/null 2>&1; then | |
echo "Hotfix branch $HOTFIX_BRANCH already exists. Skipping branch creation." | |
else | |
echo "Branching $RELEASE_BRANCH to $HOTFIX_BRANCH" | |
git checkout -b "$HOTFIX_BRANCH" | |
fi | |
# Check if the hotfix commit is a merge commit | |
if git rev-list --merges -n 1 "$HOTFIX_COMMIT" >/dev/null 2>&1; then | |
# -m 1 uses the target branch as the base (which is what we want) | |
echo "Hotfix commit $HOTFIX_COMMIT is a merge commit, using -m 1 for cherry-pick" | |
CHERRY_PICK_CMD="git cherry-pick -m 1 $HOTFIX_COMMIT" | |
else | |
CHERRY_PICK_CMD="git cherry-pick $HOTFIX_COMMIT" | |
fi | |
# Perform the cherry-pick | |
echo "Executing: $CHERRY_PICK_CMD" | |
eval "$CHERRY_PICK_CMD" | |
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 and capture the output | |
PR_OUTPUT=$(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") | |
# Extract the URL from the output | |
PR_URL=$(echo "$PR_OUTPUT" | grep -Eo 'https://github.com/[^ ]+') | |
echo "Pull request created: $PR_URL" | |
# Extract PR number from URL | |
PR_NUMBER=$(basename "$PR_URL") | |
echo "Pull request created: $PR_NUMBER" | |
if [ "$AUTO_MERGE" == "true" ]; then | |
echo "Attempting to merge pull request #$PR_NUMBER" | |
# Attempt to merge the PR | |
gh pr merge "$PR_NUMBER" --merge --auto --delete-branch | |
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 |