mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2026-04-23 00:17:25 +08:00
9d72332aca
* [CI] Optimize unit test duration and fix PR title format
192 lines
7.1 KiB
YAML
192 lines
7.1 KiB
YAML
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"
|