-
Notifications
You must be signed in to change notification settings - Fork 2
182 lines (153 loc) · 7.26 KB
/
merge-from-milestone.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
name: Merge PRs from Milestone
permissions:
contents: write
pull-requests: write
issues: write
on:
workflow_dispatch:
inputs:
milestone_name:
description: 'Milestone name to collect closed PRs from'
required: true
default: 'v3.8.2'
target_branch:
description: 'Target branch to merge the consolidated PR'
required: true
default: 'pre-release-v3.8.2'
schedule:
- cron: '0 10 * * 0'
env:
MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.2' }}
TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.2' }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
LABEL_NAME: cherry-picked
jobs:
cherry_pick_milestone_prs:
runs-on: ubuntu-latest
steps:
# Step 1: Checkout repository with full history
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.BOT_TOKEN }}
# Step 2: Setup Git user configuration for the bot
- name: Setup Git User for OpenIM-Robot
run: |
git config --global user.email "[email protected]"
git config --global user.name "OpenIM-Robot"
# Step 3: Fetch Milestone ID and filter PR numbers without the 'cherry-picked' label
- name: Fetch Milestone ID and Filter PR Numbers
env:
MILESTONE_NAME: ${{ env.MILESTONE_NAME }}
run: |
# Fetch all milestones and find the one with the specified name
milestones=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/milestones")
milestone_id=$(echo "$milestones" | grep -B3 "\"title\": \"$MILESTONE_NAME\"" | grep '"number":' | head -n1 | grep -o '[0-9]\+')
echo "Milestone ID: $milestone_id"
# Fetch all issues for the milestone and filter out PRs without the 'cherry-picked' label
issues=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100")
> pr_numbers.txt
for pr_number in $(echo "$issues" | jq -r '.[] | select(.pull_request != null) | .number'); do
labels=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" | jq -r '.[].name')
# Only include PRs that do not have the 'cherry-picked' label
if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
echo "$pr_number" >> pr_numbers.txt
fi
done
echo "Filtered PR numbers:"
cat pr_numbers.txt
# Sort PR numbers in ascending order
sort -n pr_numbers.txt -o pr_numbers.txt
echo "Sorted PR numbers:"
cat pr_numbers.txt
# Step 4: Fetch merge commit SHA for each filtered PR and prepare PR title and body
- name: Fetch Merge Commits for PRs and Prepare PR Title and Body
run: |
> commit_hashes.txt
> pr_title.txt
> pr_body.txt
# Collect PR details and format the title and body for the new PR
for pr_number in $(cat pr_numbers.txt); do
pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
pr_title=$(echo "$pr_details" | jq -r '.title')
merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)
commit_url="https://github.com/${{ github.repository }}/commit/$merge_commit"
pr_url="https://github.com/${{ github.repository }}/pull/$pr_number"
# Prepare PR title
echo "#$pr_number" >> pr_title.txt
# Prepare PR body
echo "* **$pr_title**: ([#$pr_number]($pr_url)) ([\`$short_commit_hash\`]($commit_url))" >> pr_body.txt
done
# Collect commit hashes and prepare the branch name for cherry-picking
pr_numbers_in_title=$(paste -sd " " pr_title.txt)
commit_hashes=$(cat commit_hashes.txt | tr '\n' ' ')
first_commit_hash=$(head -n 1 commit_hashes.txt)
cherry_pick_branch="cherry-pick-${first_commit_hash:0:7}"
echo "COMMIT_HASHES=$commit_hashes" >> $GITHUB_ENV
echo "CHERRY_PICK_BRANCH=$cherry_pick_branch" >> $GITHUB_ENV
# Step 5: Cherry-pick commits and push to remote
- name: Cherry-pick Commits and Push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
run: |
# Fetch and pull the latest changes from the target branch
git fetch origin
git checkout $TARGET_BRANCH
git pull origin $TARGET_BRANCH
# Create a new branch for cherry-picking
git checkout -b $CHERRY_PICK_BRANCH
# Cherry-pick the commits and resolve conflicts by taking the incoming changes
for commit_hash in $COMMIT_HASHES; do
echo "Attempting to cherry-pick commit $commit_hash"
if ! git cherry-pick "$commit_hash" --strategy=recursive -X theirs; then
if git diff --cached --quiet; then
echo "Empty commit, continuing..."
git cherry-pick --continue --allow-empty
else
echo "Conflict resolved with incoming content"
git cherry-pick --continue
fi
fi
done
# Push the new branch with cherry-picked commits
git push origin $CHERRY_PICK_BRANCH
# Step 6: Use curl to create the Pull Request
- name: Create Pull Request using curl
run: |
pr_title="deps: Merge $(cat pr_title.txt | paste -sd " ") PRs into $TARGET_BRANCH"
pr_body=$(cat pr_body.txt)
echo "Prepared PR title:"
echo "$pr_title"
echo "Prepared PR body:"
echo "$pr_body"
# Create the Pull Request using curl
curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d "$(jq -n --arg title "$pr_title" \
--arg head "$CHERRY_PICK_BRANCH" \
--arg base "$TARGET_BRANCH" \
--arg body "$pr_body" \
'{title: $title, head: $head, base: $base, body: $body}')"
# Step 7: Label PRs as cherry-picked after success
- name: Label Successfully Cherry-Picked PRs
if: ${{ success() }}
run: |
for pr_number in $(cat pr_numbers.txt); do
curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" \
-d "$(jq -n --arg label "${LABEL_NAME}" '{labels: [$label]}')"
done