Files
FastDeploy/.github/workflows/cherry-pick.yml
T
YuBaoku 9d72332aca [CI] Optimize unittest and fix title format (#6464)
* [CI] Optimize unit test duration and fix PR title format
2026-02-11 20:48:56 +08:00

192 lines
7.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Cherry Pick
on:
pull_request_target:
branches: [develop]
types: [closed, labeled]
permissions:
contents: write
pull-requests: write
issues: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: false
jobs:
cherry-pick:
if: >
github.event.pull_request.merged == true &&
(
github.event.action == 'labeled' ||
contains(join(github.event.pull_request.labels.*.name, ' '), 'cherry-pick')
)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- name: Cherry Pick
env:
GH_TOKEN: ${{ secrets.CHERRY_PICK_BOT_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
MERGE_COMMIT_SHA: ${{ github.event.pull_request.merge_commit_sha }}
BOT_USERNAME: EmmonsCurse
REPO_NAME: EmmonsCurse/FastDeploy
run: |
# Function to post comment
post_comment() {
gh pr comment "$PR_NUMBER" --body "$1"
}
# Configure git for the original author
echo "Fetching author info for $PR_AUTHOR..."
AUTHOR_INFO=$(gh api "/users/$PR_AUTHOR" --jq '{email: .email, name: .name}')
AUTHOR_EMAIL=$(echo "$AUTHOR_INFO" | jq -r '.email')
AUTHOR_NAME=$(echo "$AUTHOR_INFO" | jq -r '.name')
if [ "$AUTHOR_EMAIL" = "null" ] || [ -z "$AUTHOR_EMAIL" ]; then
AUTHOR_EMAIL="${PR_AUTHOR}@users.noreply.github.com"
echo "Author email not found, using default: $AUTHOR_EMAIL"
fi
if [ "$AUTHOR_NAME" = "null" ] || [ -z "$AUTHOR_NAME" ]; then
AUTHOR_NAME="${PR_AUTHOR}"
echo "Author name not found, using username: $AUTHOR_NAME"
fi
git config user.name "$AUTHOR_NAME"
git config user.email "$AUTHOR_EMAIL"
# Capture current SHA to return to later
ORIGINAL_HEAD_SHA=$(git rev-parse HEAD)
# Get labels
LABELS=$(gh pr view "$PR_NUMBER" --json labels --jq '.labels[].name')
if [ -z "$LABELS" ]; then
echo "No labels found."
exit 0
fi
# Loop through labels
while read -r label; do
if [[ "$label" == cherry-pick:* ]]; then
TARGET_BRANCH=$(echo "${label#cherry-pick:}" | xargs)
if [ -z "$TARGET_BRANCH" ]; then
echo "Empty target branch for label '$label', skipping."
continue
fi
echo "Processing cherry-pick to $TARGET_BRANCH"
# Check if target branch exists on remote
if ! git ls-remote --exit-code --heads origin "$TARGET_BRANCH"; then
echo "Target branch $TARGET_BRANCH does not exist."
post_comment "❌ Cherry-pick failed: Target branch \`$TARGET_BRANCH\` does not exist."
continue
fi
# Create a new branch for the cherry-pick
NEW_BRANCH="cherry-pick/$PR_NUMBER/$TARGET_BRANCH"
# Clean up local branch if it exists (from previous run)
if git show-ref --verify --quiet "refs/heads/$NEW_BRANCH"; then
git branch -D "$NEW_BRANCH"
fi
# Fetch the target branch and checkout a new branch from it
git fetch origin "$TARGET_BRANCH"
git checkout -b "$NEW_BRANCH" "origin/$TARGET_BRANCH"
# Cherry pick
# Try standard cherry-pick first (for squash merges or single commits)
if git cherry-pick "$MERGE_COMMIT_SHA"; then
echo "Cherry-pick successful."
else
echo "Standard cherry-pick failed, trying with -m 1 (for merge commits)..."
git cherry-pick --abort
if git cherry-pick -m 1 "$MERGE_COMMIT_SHA"; then
echo "Cherry-pick with -m 1 successful."
else
echo "Cherry-pick failed."
git cherry-pick --abort
post_comment "❌ Cherry-pick failed: Conflicts detected when cherry-picking to \`$TARGET_BRANCH\`. Please resolve manually."
# Cleanup
git checkout "$ORIGINAL_HEAD_SHA"
git branch -D "$NEW_BRANCH"
continue
fi
fi
# Push
# Construct authenticated URL for the fork
FORK_URL_AUTH="https://${BOT_USERNAME}:${GH_TOKEN}@github.com/${REPO_NAME}.git"
echo "Pushing to fork..."
git push "$FORK_URL_AUTH" "$NEW_BRANCH" --force
# Create PR
# If PR_TITLE starts with "[", don't insert an extra space.
if [ "${PR_TITLE:0:1}" = "[" ]; then
NEW_TITLE="[Cherry-Pick]$PR_TITLE(#$PR_NUMBER)"
else
NEW_TITLE="[Cherry-Pick] $PR_TITLE(#$PR_NUMBER)"
fi
NEW_BODY="Cherry-pick of #$PR_NUMBER (authored by @${PR_AUTHOR}) to \`$TARGET_BRANCH\`.
devPR:https://github.com/PaddlePaddle/FastDeploy/pull/$PR_NUMBER <!-- For pass CI -->
---
$PR_BODY"
# Remove leading whitespace
NEW_BODY=$(echo "$NEW_BODY" | sed 's/^[ \t]*//')
# Prepare head ref for PR creation (owner:branch)
HEAD_REF="${BOT_USERNAME}:${NEW_BRANCH}"
# Check if PR already exists
EXISTING_PR=$(gh pr list --base "$TARGET_BRANCH" --head "$NEW_BRANCH" --json url --jq '.[0].url')
if [ -n "$EXISTING_PR" ]; then
echo "PR already exists: $EXISTING_PR"
post_comment "️ Cherry-pick PR already exists: $EXISTING_PR"
else
# Create PR using gh CLI, ignoring errors because of "Resource not accessible" false positives
gh pr create --base "$TARGET_BRANCH" --head "$HEAD_REF" --title "$NEW_TITLE" --body "$NEW_BODY" || true
# Wait a bit for eventual consistency
sleep 2
# Search for the created PR
CREATED_PR_URL=$(gh pr list --head "$NEW_BRANCH" --state all --json url --jq '.[0].url')
if [ -n "$CREATED_PR_URL" ]; then
echo "Created PR: $CREATED_PR_URL"
post_comment "✅ Cherry-pick successful! Created PR: $CREATED_PR_URL"
# Request review
gh pr review-request "$CREATED_PR_URL" --reviewer "$PR_AUTHOR" || true
else
echo "Failed to create PR."
post_comment "❌ Cherry-pick failed: Could not create PR to \`$TARGET_BRANCH\`."
continue
fi
fi
# Cleanup for next loop
git checkout "$ORIGINAL_HEAD_SHA"
git branch -D "$NEW_BRANCH"
fi
done <<< "$LABELS"