Skip to content

Commit 183a735

Browse files
author
silas.jiang
committed
support auto cherry pick
Signed-off-by: jac <jacllovey@qq.com>
1 parent da333ee commit 183a735

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
name: Backport
2+
3+
on:
4+
pull_request_target:
5+
types:
6+
- closed
7+
- labeled
8+
workflow_dispatch:
9+
inputs:
10+
pr_number:
11+
description: 'PR number'
12+
required: true
13+
type: string
14+
target_branch:
15+
description: 'Target branch'
16+
required: true
17+
type: string
18+
19+
jobs:
20+
auto-backport:
21+
if: github.event_name == 'pull_request_target' && github.event.pull_request.merged == true
22+
permissions:
23+
contents: write
24+
pull-requests: write
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
30+
- name: Check Restricted Paths
31+
id: check_files
32+
env:
33+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34+
PR_NUMBER: ${{ github.event.pull_request.number }}
35+
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
36+
run: |
37+
CHANGED_FILES=$(gh pr view $PR_NUMBER --json files --jq '.files[].path')
38+
39+
if echo "$CHANGED_FILES" | grep -q "^proto_gen/"; then
40+
echo "should_skip=true" >> $GITHUB_OUTPUT
41+
gh pr comment $PR_NUMBER --body "⚠️ **Backport Skipped**
42+
43+
Hi @$PR_AUTHOR, this PR modifies \`proto_gen/\`. Please backport manually."
44+
else
45+
echo "should_skip=false" >> $GITHUB_OUTPUT
46+
fi
47+
48+
- name: Backport
49+
id: backport_step
50+
if: steps.check_files.outputs.should_skip != 'true'
51+
uses: korthout/backport-action@v3
52+
with:
53+
label_pattern: '^backport-to-(.*)$'
54+
pull_title: '[Backport ${target_branch}] ${pull_title}'
55+
pull_description: 'Backport of #${pull_number} to `${target_branch}`.'
56+
add_labels: 'backport'
57+
58+
# [NEW] Add 'cherry-picked' label to the ORIGINAL PR upon success
59+
- name: Label Original PR
60+
if: steps.backport_step.outcome == 'success'
61+
env:
62+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63+
PR_NUMBER: ${{ github.event.pull_request.number }}
64+
run: |
65+
gh pr edit $PR_NUMBER --add-label "cherry-picked"
66+
67+
manual-backport:
68+
if: github.event_name == 'workflow_dispatch'
69+
permissions:
70+
contents: write
71+
pull-requests: write
72+
runs-on: ubuntu-latest
73+
steps:
74+
- name: Checkout
75+
uses: actions/checkout@v4
76+
with:
77+
fetch-depth: 0
78+
79+
- name: Configure Git
80+
run: |
81+
git config user.name "github-actions[bot]"
82+
git config user.email "github-actions[bot]@users.noreply.github.com"
83+
84+
- name: Execute Manual Backport
85+
env:
86+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87+
PR_NUMBER: ${{ inputs.pr_number }}
88+
TARGET_BRANCH: ${{ inputs.target_branch }}
89+
run: |
90+
TARGET_BRANCH=$(echo "$TARGET_BRANCH" | xargs)
91+
92+
echo "Processing Manual Backport: PR #$PR_NUMBER -> $TARGET_BRANCH"
93+
94+
PR_DATA=$(gh pr view $PR_NUMBER --json mergeCommit,title,files,author,state --jq .)
95+
MERGE_COMMIT=$(echo "$PR_DATA" | jq -r .mergeCommit.oid)
96+
PR_TITLE=$(echo "$PR_DATA" | jq -r .title)
97+
PR_AUTHOR=$(echo "$PR_DATA" | jq -r .author.login)
98+
PR_STATE=$(echo "$PR_DATA" | jq -r .state)
99+
CHANGED_FILES=$(echo "$PR_DATA" | jq -r .files[].path)
100+
101+
if [ "$PR_STATE" != "MERGED" ]; then
102+
echo "::error::PR is not merged."
103+
gh pr comment $PR_NUMBER --body "❌ **Manual Backport Failed**
104+
PR #$PR_NUMBER is not merged yet."
105+
exit 1
106+
fi
107+
108+
if echo "$CHANGED_FILES" | grep -q "^proto_gen/"; then
109+
echo "::error::Skipping. PR modifies proto_gen/."
110+
gh pr comment $PR_NUMBER --body "⚠️ **Manual Backport Skipped**
111+
Hi @$PR_AUTHOR, this PR modifies \`proto_gen/\`. Automated handling is disabled."
112+
exit 1
113+
fi
114+
115+
if ! git ls-remote --exit-code --heads origin $TARGET_BRANCH; then
116+
echo "::error::Target branch '$TARGET_BRANCH' does not exist."
117+
gh pr comment $PR_NUMBER --body "❌ **Manual Backport Failed**
118+
Target branch \`$TARGET_BRANCH\` does not exist. Please check the branch name."
119+
exit 1
120+
fi
121+
122+
NEW_BRANCH="backport-$PR_NUMBER-to-manual-$(date +%s)"
123+
124+
git checkout -b $NEW_BRANCH origin/$TARGET_BRANCH
125+
126+
CP_ARGS="-s"
127+
if git rev-parse -q --verify "$MERGE_COMMIT^2" >/dev/null; then
128+
CP_ARGS="-s -m 1"
129+
fi
130+
131+
if git cherry-pick $CP_ARGS $MERGE_COMMIT; then
132+
git push origin $NEW_BRANCH
133+
134+
NEW_PR_URL=$(gh pr create \
135+
--base $TARGET_BRANCH \
136+
--head $NEW_BRANCH \
137+
--title "[Backport $TARGET_BRANCH] $PR_TITLE" \
138+
--body "Manual backport of #$PR_NUMBER to \`$TARGET_BRANCH\`." \
139+
--label "backport")
140+
141+
gh pr comment $PR_NUMBER --body "✅ **Manual Backport Success**
142+
Cherry-picked to \`$TARGET_BRANCH\` via manual trigger: $NEW_PR_URL"
143+
144+
# [NEW] Add label to original PR
145+
gh pr edit $PR_NUMBER --add-label "cherry-picked"
146+
else
147+
echo "::error::Cherry-pick failed due to conflicts."
148+
git cherry-pick --abort || true
149+
150+
gh pr comment $PR_NUMBER --body "❌ **Manual Backport Failed**
151+
Hi @$PR_AUTHOR, I could not cherry-pick this to \`$TARGET_BRANCH\` due to **merge conflicts**.
152+
153+
Please perform the backport locally:
154+
\`\`\`bash
155+
git checkout $TARGET_BRANCH
156+
git pull
157+
git cherry-pick -x $MERGE_COMMIT
158+
# Resolve conflicts...
159+
git push ...
160+
\`\`\`"
161+
exit 1
162+
fi

0 commit comments

Comments
 (0)