Cherry-pick bot2

This commit is contained in:
Conrad Irwin 2025-08-25 14:38:43 -06:00
parent 0470baca50
commit 5eb04c7b28

151
.github/workflows/cherry-pick.yml vendored Normal file
View file

@ -0,0 +1,151 @@
name: Cherry Pick
on:
issue_comment:
types: [created]
pull_request_target:
types: [closed]
jobs:
cherry-pick:
# This job will run when a PR is merged with a specific comment,
# or when a comment is added to an already merged PR.
runs-on: ubuntu-latest
# Use pull_request_target so that we can add comments back to the PR
# if the cherry-pick fails.
permissions:
pull-requests: write
contents: write
issues: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Required to get all history for cherry-picking
- name: Extract info and determine trigger
id: info
run: |
# Default to failure unless a valid trigger is found
echo "valid=false" >> $GITHUB_OUTPUT
if [[ "${{ github.event_name }}" == "pull_request_target" && "${{ github.event.pull_request.merged }}" == "true" ]]; then
echo "Triggered by PR merge"
PR_NUMBER="${{ github.event.pull_request.number }}"
# Check PR body first, then fall back to comments
TEXT_TO_SEARCH="${{ github.event.pull_request.body }}"
if [[ ! "$TEXT_TO_SEARCH" =~ /cherry-pick[[:space:]]+(stable|preview) ]]; then
echo "Command not found in PR body. Checking comments..."
TEXT_TO_SEARCH=$(gh pr view $PR_NUMBER --json comments -q '.comments[].body' | tail -n 100)
fi
if [[ "$TEXT_TO_SEARCH" =~ /cherry-pick[[:space:]]+(stable|preview) ]]; then
echo "Found cherry-pick command."
MERGE_SHA="${{ github.event.pull_request.merge_commit_sha }}"
# Get the last matching command in the text
CHANNEL=$(echo "$TEXT_TO_SEARCH" | grep -oP '/cherry-pick[[:space:]]+\K(stable|preview)' | tail -n1)
echo "valid=true" >> $GITHUB_OUTPUT
echo "merge_sha=$MERGE_SHA" >> $GITHUB_OUTPUT
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "channel=$CHANNEL" >> $GITHUB_OUTPUT
else
echo "No cherry-pick command found in PR body or recent comments. Exiting."
exit 0
fi
elif [[ "${{ github.event_name }}" == "issue_comment" && "${{ github.event.issue.pull_request }}" != "" ]]; then
echo "Triggered by issue comment"
COMMENT_BODY="${{ github.event.comment.body }}"
if [[ ! "$COMMENT_BODY" =~ /cherry-pick[[:space:]]+(stable|preview) ]]; then
echo "Comment does not contain cherry-pick command. Exiting."
exit 0
fi
PR_NUMBER="${{ github.event.issue.number }}"
# Check if the PR is merged
MERGE_SHA=$(gh pr view $PR_NUMBER --json mergeCommit -q .mergeCommit.oid)
if [[ -z "$MERGE_SHA" ]]; then
echo "PR #$PR_NUMBER is not merged. Exiting."
exit 0
fi
CHANNEL=$(echo "$COMMENT_BODY" | grep -oP '/cherry-pick[[:space:]]+\K(stable|preview)' | head -n1)
echo "valid=true" >> $GITHUB_OUTPUT
echo "merge_sha=$MERGE_SHA" >> $GITHUB_OUTPUT
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "channel=$CHANNEL" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Cherry-pick
if: steps.info.outputs.valid == 'true'
run: |
set -e
CHANNEL="${{ steps.info.outputs.channel }}"
MERGE_SHA="${{ steps.info.outputs.merge_sha }}"
PR_NUMBER="${{ steps.info.outputs.pr_number }}"
# Get the latest version for the channel
echo "Fetching latest version for '$CHANNEL' channel..."
query=""
case $CHANNEL in
stable)
;;
preview)
query="&preview=1"
;;
*)
echo "Invalid channel: $CHANNEL" >&2
exit 1
;;
esac
LATEST_VERSION=$(curl -s "https://zed.dev/api/releases/latest?asset=zed&os=macos&arch=aarch64$query" | jq -r .version)
if [[ -z "$LATEST_VERSION" ]]; then
echo "Could not fetch latest version for channel '$CHANNEL'"
gh pr comment $PR_NUMBER --body "Could not fetch latest version for channel '$CHANNEL' from zed.dev API."
exit 1
fi
echo "Latest version is $LATEST_VERSION"
# Construct target branch name (e.g., v0.85.4 -> v0.85.x)
TARGET_BRANCH=$(echo "$LATEST_VERSION" | sed -E 's/v([0-9]+\.[0-9]+)\..*/v\1.x/')
echo "Target branch is $TARGET_BRANCH"
# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Create and push the cherry-pick branch
NEW_BRANCH="cherry-pick/pr-${PR_NUMBER}-to-${TARGET_BRANCH}"
git fetch origin $TARGET_BRANCH
git checkout -b $NEW_BRANCH "origin/$TARGET_BRANCH"
echo "Attempting to cherry-pick $MERGE_SHA..."
if ! git cherry-pick $MERGE_SHA; then
echo "Cherry-pick failed. Please resolve conflicts manually."
gh pr comment $PR_NUMBER --body "Automated cherry-pick to \`$TARGET_BRANCH\` failed due to conflicts. Please resolve them manually."
exit 1
fi
echo "Pushing new branch $NEW_BRANCH..."
git push -u origin $NEW_BRANCH
# Create the pull request
echo "Creating pull request..."
gh pr create \
--title "Cherry-pick PR #${PR_NUMBER} to ${TARGET_BRANCH}" \
--body "This PR cherry-picks the changes from #${PR_NUMBER} to the \`$TARGET_BRANCH\` branch." \
--base $TARGET_BRANCH \
--head $NEW_BRANCH \
--reviewer "${{ github.actor }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}