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 }}