Skip to content

Commit bcd703f

Browse files
committed
update new milestone
1 parent a52fcff commit bcd703f

File tree

1 file changed

+310
-0
lines changed

1 file changed

+310
-0
lines changed
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
name: Milestone Migration
2+
3+
permissions:
4+
contents: write
5+
pull-requests: write
6+
issues: write
7+
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
milestone_name:
12+
description: "Milestone name:"
13+
required: true
14+
default: "v3.8.4"
15+
target_branch:
16+
description: "Target branch"
17+
required: true
18+
default: "pre-release-v3.8.4"
19+
sort_by:
20+
description: "Sort by"
21+
required: true
22+
options:
23+
- merged_at
24+
- pr_number
25+
default: "merged_at"
26+
27+
env:
28+
MILESTONE_NAME: ${{ github.event.inputs.milestone_name }}
29+
TARGET_BRANCH: ${{ github.event.inputs.target_branch }}
30+
SORT_BY: ${{ github.event.inputs.sort_by }}
31+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
33+
LABEL_NEW: "milestone-merge"
34+
LABEL_ORIGIN: "merged-to-prerelease"
35+
36+
jobs:
37+
migrate_milestone_prs:
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: Initialize working directory
41+
run: |
42+
mkdir -p /tmp/milestone_migration
43+
touch /tmp/milestone_migration/{pr_data.json,sorted_prs.json,results.json}
44+
echo "[]" > /tmp/milestone_migration/results.json
45+
46+
- name: Checkout repository
47+
uses: actions/checkout@v4
48+
with:
49+
fetch-depth: 0
50+
token: ${{ env.BOT_TOKEN }}
51+
52+
- name: Setup Git user
53+
run: |
54+
git config --global user.email "OpenIM-Robot@users.noreply.github.com"
55+
git config --global user.name "OpenIM-Robot"
56+
57+
- name: Get milestone information
58+
id: get_milestone
59+
run: |
60+
echo "Getting milestone $MILESTONE_NAME info..."
61+
62+
response=$(curl -s -H "Authorization: token $BOT_TOKEN" \
63+
"https://api.github.com/repos/${{ github.repository }}/milestones?state=all")
64+
65+
milestone_id=$(echo "$response" | jq -r --arg NAME "$MILESTONE_NAME" \
66+
'.[] | select(.title == $NAME) | .number')
67+
68+
if [ -z "$milestone_id" ] || [ "$milestone_id" = "null" ]; then
69+
echo "Error: Milestone '$MILESTONE_NAME' not found"
70+
exit 1
71+
fi
72+
73+
echo "Found milestone ID: $milestone_id"
74+
echo "milestone_id=$milestone_id" >> $GITHUB_ENV
75+
76+
- name: Get PRs in milestone
77+
run: |
78+
echo "Getting PRs from milestone #$milestone_id..."
79+
80+
# Initialize JSON file to store PR data
81+
echo "[]" > /tmp/milestone_migration/pr_data.json
82+
83+
page=1
84+
while true; do
85+
echo "Getting page $page..."
86+
87+
issues_page=$(curl -s -H "Authorization: token $BOT_TOKEN" \
88+
"https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100&page=$page")
89+
90+
# Extract merged PRs
91+
echo "$issues_page" | jq '[.[] | select(.pull_request != null)]' > /tmp/milestone_migration/page_data.json
92+
93+
# Exit loop if page is empty
94+
if [ "$(jq '. | length' /tmp/milestone_migration/page_data.json)" = "0" ]; then
95+
break
96+
fi
97+
98+
# Get details for each PR
99+
jq -c '.[]' /tmp/milestone_migration/page_data.json | while read -r issue; do
100+
pr_number=$(echo "$issue" | jq -r '.number')
101+
102+
# Get PR details to confirm it's merged
103+
pr_data=$(curl -s -H "Authorization: token $BOT_TOKEN" \
104+
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
105+
106+
merged=$(echo "$pr_data" | jq -r '.merged')
107+
108+
if [ "$merged" = "true" ]; then
109+
echo "Merged PR #$pr_number"
110+
111+
# Build PR data
112+
pr_json=$(echo "$pr_data" | jq '{
113+
number: .number,
114+
title: .title,
115+
body: .body,
116+
merge_commit_sha: .merge_commit_sha,
117+
merged_at: .merged_at,
118+
user: {
119+
login: .user.login
120+
},
121+
head: {
122+
ref: .head.ref
123+
},
124+
base: {
125+
ref: .base.ref
126+
}
127+
}')
128+
129+
# Add to PR data file
130+
jq --argjson pr "$pr_json" '. += [$pr]' /tmp/milestone_migration/pr_data.json > /tmp/milestone_migration/pr_data.json.tmp
131+
mv /tmp/milestone_migration/pr_data.json.tmp /tmp/milestone_migration/pr_data.json
132+
fi
133+
done
134+
135+
page=$((page + 1))
136+
done
137+
138+
# Show count of found PRs
139+
pr_count=$(jq '. | length' /tmp/milestone_migration/pr_data.json)
140+
echo "Found $pr_count merged PRs"
141+
142+
- name: Sort PR list
143+
run: |
144+
if [ "$SORT_BY" = "merged_at" ]; then
145+
echo "Sorting PRs by merge time..."
146+
jq 'sort_by(.merged_at)' /tmp/milestone_migration/pr_data.json > /tmp/milestone_migration/sorted_prs.json
147+
else
148+
echo "Sorting PRs by PR number..."
149+
jq 'sort_by(.number)' /tmp/milestone_migration/pr_data.json > /tmp/milestone_migration/sorted_prs.json
150+
fi
151+
152+
# Display sorted PR list
153+
echo "Processing order:"
154+
jq -r '.[] | "PR #\(.number) - \(.title) (merged at \(.merged_at))"' /tmp/milestone_migration/sorted_prs.json
155+
156+
- name: Ensure target branch is up to date
157+
run: |
158+
echo "Updating target branch $TARGET_BRANCH..."
159+
git fetch origin
160+
161+
# Check if target branch exists
162+
if git ls-remote --heads origin $TARGET_BRANCH | grep -q $TARGET_BRANCH; then
163+
git checkout -B $TARGET_BRANCH origin/$TARGET_BRANCH
164+
else
165+
echo "Target branch $TARGET_BRANCH does not exist, creating from main"
166+
git checkout -B $TARGET_BRANCH origin/main
167+
git push origin $TARGET_BRANCH
168+
fi
169+
170+
- name: Process each PR and create new PRs
171+
run: |
172+
echo "Starting to process PRs..."
173+
174+
# Ensure we're on the target branch
175+
git checkout $TARGET_BRANCH
176+
git pull origin $TARGET_BRANCH
177+
178+
# Process sorted PRs
179+
jq -c '.[]' /tmp/milestone_migration/sorted_prs.json | while read -r pr; do
180+
pr_number=$(echo "$pr" | jq -r '.number')
181+
pr_title=$(echo "$pr" | jq -r '.title')
182+
pr_body=$(echo "$pr" | jq -r '.body')
183+
merge_sha=$(echo "$pr" | jq -r '.merge_commit_sha')
184+
pr_creator=$(echo "$pr" | jq -r '.user.login')
185+
186+
echo "===================================================="
187+
echo "Processing PR #$pr_number: $pr_title"
188+
echo "Merge commit: $merge_sha"
189+
echo "Original author: $pr_creator"
190+
191+
# Create new branch
192+
new_branch="milestone-$MILESTONE_NAME-pr-$pr_number"
193+
git checkout -B $new_branch $TARGET_BRANCH
194+
195+
# Get PR file changes
196+
pr_files=$(curl -s -H "Authorization: token $BOT_TOKEN" \
197+
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number/files" | jq -r '.[] | .filename')
198+
199+
# Get PR diff
200+
pr_diff=$(curl -s -H "Accept: application/vnd.github.v3.diff" -H "Authorization: token $BOT_TOKEN" \
201+
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
202+
203+
# Save diff to file
204+
echo "$pr_diff" > /tmp/pr_diff.patch
205+
206+
# Try to apply patch
207+
if git apply --check /tmp/pr_diff.patch 2>/dev/null; then
208+
echo "Applying changes..."
209+
git apply /tmp/pr_diff.patch
210+
211+
# Add modified files
212+
if [ -n "$pr_files" ]; then
213+
for file in $pr_files; do
214+
if [ -f "$file" ]; then
215+
git add "$file"
216+
fi
217+
done
218+
fi
219+
220+
# Commit changes
221+
git commit -m "Apply changes from PR #$pr_number: $pr_title"
222+
223+
# Push new branch
224+
git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
225+
git push -f origin $new_branch
226+
227+
# Create new PR
228+
new_pr_title="[$MILESTONE_NAME] $pr_title"
229+
new_pr_body="This PR applies changes from PR #$pr_number (submitted by @$pr_creator) to the \`$TARGET_BRANCH\` branch.\n\nOriginal PR: #$pr_number\n\n---\n\n$pr_body"
230+
231+
pr_response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
232+
-H "Accept: application/vnd.github+json" \
233+
"https://api.github.com/repos/${{ github.repository }}/pulls" \
234+
-d "$(jq -n --arg title "$new_pr_title" \
235+
--arg body "$new_pr_body" \
236+
--arg head "$new_branch" \
237+
--arg base "$TARGET_BRANCH" \
238+
'{title: $title, body: $body, head: $head, base: $base}')")
239+
240+
new_pr_number=$(echo "$pr_response" | jq -r '.number')
241+
242+
if [ "$new_pr_number" != "null" ]; then
243+
echo "✅ Successfully created new PR #$new_pr_number"
244+
245+
# Add labels
246+
curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
247+
-H "Accept: application/vnd.github+json" \
248+
"https://api.github.com/repos/${{ github.repository }}/issues/$new_pr_number/labels" \
249+
-d "{\"labels\":[\"$LABEL_NEW\"]}"
250+
251+
# Record successful result
252+
jq --argjson result "{\"original_pr\": $pr_number, \"new_pr\": $new_pr_number, \"status\": \"success\", \"message\": \"Successfully created PR #$new_pr_number\"}" \
253+
'.+= [$result]' /tmp/milestone_migration/results.json > /tmp/milestone_migration/results.json.tmp
254+
mv /tmp/milestone_migration/results.json.tmp /tmp/milestone_migration/results.json
255+
else
256+
echo "❌ Failed to create PR"
257+
# Record failure
258+
jq --argjson result "{\"original_pr\": $pr_number, \"status\": \"failure\", \"message\": \"Failed to create PR\"}" \
259+
'.+= [$result]' /tmp/milestone_migration/results.json > /tmp/milestone_migration/results.json.tmp
260+
mv /tmp/milestone_migration/results.json.tmp /tmp/milestone_migration/results.json
261+
fi
262+
else
263+
echo "❌ Failed to apply patch, possible conflicts"
264+
# Record failure
265+
jq --argjson result "{\"original_pr\": $pr_number, \"status\": \"failure\", \"message\": \"Failed to apply patch, possible conflicts\"}" \
266+
'.+= [$result]' /tmp/milestone_migration/results.json > /tmp/milestone_migration/results.json.tmp
267+
mv /tmp/milestone_migration/results.json.tmp /tmp/milestone_migration/results.json
268+
fi
269+
270+
# Switch back to target branch
271+
git checkout $TARGET_BRANCH
272+
done
273+
274+
- name: Create results report
275+
run: |
276+
echo "Generating results report..."
277+
278+
# Extract successful and failed PRs
279+
success_count=$(jq '[.[] | select(.status == "success")] | length' /tmp/milestone_migration/results.json)
280+
failure_count=$(jq '[.[] | select(.status == "failure")] | length' /tmp/milestone_migration/results.json)
281+
total_count=$(jq '. | length' /tmp/milestone_migration/results.json)
282+
283+
# Create report Markdown
284+
report_title="Milestone $MILESTONE_NAME migration to $TARGET_BRANCH results"
285+
report_body="## Milestone $MILESTONE_NAME Migration Report\n\n"
286+
report_body+="- Total processed: $total_count PRs\n"
287+
report_body+="- Success: $success_count PRs\n"
288+
report_body+="- Failed: $failure_count PRs\n\n"
289+
290+
if [ "$success_count" -gt 0 ]; then
291+
report_body+="### Successfully processed PRs:\n\n"
292+
success_prs=$(jq -r '.[] | select(.status == "success") | "- PR #\(.original_pr) → New PR #\(.new_pr)"' /tmp/milestone_migration/results.json)
293+
report_body+="$success_prs\n\n"
294+
fi
295+
296+
if [ "$failure_count" -gt 0 ]; then
297+
report_body+="### Failed PRs:\n\n"
298+
failure_prs=$(jq -r '.[] | select(.status == "failure") | "- PR #\(.original_pr): \(.message)"' /tmp/milestone_migration/results.json)
299+
report_body+="$failure_prs\n\n"
300+
fi
301+
302+
# Create issue
303+
issue_response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
304+
-H "Accept: application/vnd.github+json" \
305+
"https://api.github.com/repos/${{ github.repository }}/issues" \
306+
-d "{\"title\":\"$report_title\", \"body\":\"$report_body\", \"labels\":[\"report\"]}")
307+
308+
issue_number=$(echo "$issue_response" | jq -r '.number')
309+
310+
echo "Created results report issue #$issue_number"

0 commit comments

Comments
 (0)