Skip to content

Commit 1886208

Browse files
committed
1
1 parent 0372583 commit 1886208

File tree

2 files changed

+137
-65
lines changed

2 files changed

+137
-65
lines changed

.github/workflows/cn.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 137 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,165 @@
1-
name: Single PR for Closed Milestone PRs
1+
name: Create Individual PRs from Milestone
2+
3+
permissions:
4+
contents: write
5+
pull-requests: write
6+
issues: write
27

38
on:
4-
workflow_dispatch: # Manual trigger
9+
workflow_dispatch:
510
inputs:
6-
milestone:
7-
description: 'Milestone name to collect closed PRs from'
11+
milestone_name:
12+
description: "Milestone name to collect closed PRs from"
813
required: true
9-
default: 'v3.8.2' # Default milestone set to v3.8.2
14+
default: "v3.8.4"
1015
target_branch:
11-
description: 'Target branch to merge the consolidated PR'
16+
description: "Target branch to merge the consolidated PR"
1217
required: true
13-
default: 'pre-release-v3.8.2' # Default target branch with pre-release-v*.* format
14-
schedule:
15-
- cron: '0 0 * * 0' # Scheduled to run every Sunday at 00:00 UTC
18+
default: "pre-release-v3.8.4"
1619

1720
env:
21+
MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.4' }}
22+
TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.4' }}
1823
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24+
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
25+
LABEL_NAME: cherry-picked
26+
TEMP_DIR: /tmp
1927

2028
jobs:
21-
cherry_pick_closed_milestone_prs:
29+
merge_milestone_prs:
2230
runs-on: ubuntu-latest
2331
steps:
24-
# Step 1: Checkout the repository code
32+
- name: Setup temp directory
33+
run: |
34+
# Create the temporary directory and initialize necessary files
35+
mkdir -p ${{ env.TEMP_DIR }}
36+
touch ${{ env.TEMP_DIR }}/pr_numbers.txt
37+
touch ${{ env.TEMP_DIR }}/commit_hashes.txt
38+
touch ${{ env.TEMP_DIR }}/pr_title.txt
39+
touch ${{ env.TEMP_DIR }}/pr_body.txt
40+
touch ${{ env.TEMP_DIR }}/created_pr_number.txt
41+
2542
- name: Checkout repository
26-
uses: actions/checkout@v2
43+
uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0
46+
token: ${{ secrets.BOT_TOKEN }}
2747

28-
# Step 2: Set up Git user details for making commits
29-
- name: Setup Git
48+
- name: Setup Git User for OpenIM-Robot
3049
run: |
31-
git config --global user.name "github-actions[bot]"
32-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
50+
git config --global user.email "OpenIM-Robot@users.noreply.github.com"
51+
git config --global user.name "OpenIM-Robot"
3352
34-
# Step 3: Install GitHub CLI to interact with milestones and PRs
35-
- name: Install GitHub CLI
36-
run: sudo apt install gh
53+
- name: Fetch Milestone ID and Filter PR Numbers
54+
env:
55+
MILESTONE_NAME: ${{ env.MILESTONE_NAME }}
56+
run: |
57+
# Fetch milestone details and extract milestone ID
58+
milestones=$(curl -s -H "Authorization: token $BOT_TOKEN" \
59+
-H "Accept: application/vnd.github+json" \
60+
"https://api.github.com/repos/${{ github.repository }}/milestones")
61+
milestone_id=$(echo "$milestones" | grep -B3 "\"title\": \"$MILESTONE_NAME\"" | grep '"number":' | head -n1 | grep -o '[0-9]\+')
62+
if [ -z "$milestone_id" ]; then
63+
echo "Milestone '$MILESTONE_NAME' not found. Exiting."
64+
exit 1
65+
fi
66+
echo "Milestone ID: $milestone_id"
67+
echo "MILESTONE_ID=$milestone_id" >> $GITHUB_ENV
3768
38-
# Step 4: Authenticate GitHub CLI using GITHUB_TOKEN
39-
- name: Authenticate GitHub CLI
40-
run: echo "${{ env.GITHUB_TOKEN }}" | gh auth login --with-token
69+
# Fetch issues for the milestone
70+
issues=$(curl -s -H "Authorization: token $BOT_TOKEN" \
71+
-H "Accept: application/vnd.github+json" \
72+
"https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100")
4173
42-
# Step 5: Fetch closed PRs from the specified milestone
43-
- name: Fetch Closed PRs from Milestone
44-
id: fetch_prs
45-
run: |
46-
milestone="${{ github.event.inputs.milestone }}"
47-
prs=$(gh pr list --search "milestone:$milestone is:closed" --json number,headRefName,mergeCommit)
48-
echo "::set-output name=prs::$prs"
74+
> ${{ env.TEMP_DIR }}/pr_numbers.txt
4975
50-
# Step 6: Create a new branch from main, cherry-pick PRs, and push to remote
51-
- name: Create and Cherry-pick Branch
52-
if: ${{ steps.fetch_prs.outputs.prs != '[]' }}
53-
run: |
54-
target_branch="${{ github.event.inputs.target_branch }}"
55-
cherry_pick_branch="milestone-cherry-pick-$(date +%Y%m%d%H%M%S)"
76+
# Filter PRs that do not have the 'cherry-picked' label
77+
for pr_number in $(echo "$issues" | jq -r '.[] | select(.pull_request != null) | .number'); do
78+
labels=$(curl -s -H "Authorization: token $BOT_TOKEN" \
79+
-H "Accept: application/vnd.github+json" \
80+
"https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" | jq -r '.[].name')
81+
82+
if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
83+
echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
84+
echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
85+
fi
86+
done
5687
57-
# Switch to main branch, pull latest changes, then create a new cherry-pick branch
58-
git checkout main
59-
git pull origin main
60-
git checkout -b $cherry_pick_branch
88+
sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt
6189
62-
# Iterate over closed PRs in the milestone and cherry-pick each merge commit
63-
echo "${{ steps.fetch_prs.outputs.prs }}" | jq -c '.[]' | while read -r pr; do
64-
pr_number=$(echo "$pr" | jq '.number')
65-
merge_commit=$(echo "$pr" | jq -r '.mergeCommit')
90+
- name: Create Individual PRs
91+
run: |
92+
for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
93+
pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
94+
-H "Accept: application/vnd.github+json" \
95+
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
96+
pr_title=$(echo "$pr_details" | jq -r '.title')
97+
pr_body=$(echo "$pr_details" | jq -r '.body')
98+
pr_creator=$(echo "$pr_details" | jq -r '.user.login')
99+
merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
100+
short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)
66101
67102
if [ "$merge_commit" != "null" ]; then
68-
# Check if the merge commit is already in the target branch
69-
if git merge-base --is-ancestor $merge_commit $target_branch; then
70-
echo "Skipping PR #$pr_number - Commit $merge_commit already in $target_branch"
103+
git fetch origin
104+
105+
echo "Checking out target branch: $TARGET_BRANCH"
106+
git checkout $TARGET_BRANCH
107+
108+
echo "Pulling latest changes from target branch: $TARGET_BRANCH"
109+
git pull origin $TARGET_BRANCH
110+
111+
cherry_pick_branch="cherry-pick-${short_commit_hash}"
112+
git checkout -b $cherry_pick_branch
113+
114+
echo "Cherry-picking commit: $merge_commit"
115+
if ! git cherry-pick "$merge_commit" --strategy=recursive -X theirs; then
116+
echo "Conflict detected for $merge_commit. Resolving with incoming changes."
117+
conflict_files=$(git diff --name-only --diff-filter=U)
118+
echo "Conflicting files:"
119+
echo "$conflict_files"
120+
121+
for file in $conflict_files; do
122+
if [ -f "$file" ]; then
123+
echo "Resolving conflict for $file"
124+
git add "$file"
125+
else
126+
echo "File $file has been deleted. Skipping."
127+
git rm "$file"
128+
fi
129+
done
130+
131+
echo "Conflicts resolved. Continuing cherry-pick."
132+
git cherry-pick --continue || { echo "Cherry-pick failed, but continuing to create PR."; }
71133
else
72-
echo "Cherry-picking PR #$pr_number with commit $merge_commit"
73-
git cherry-pick $merge_commit || git cherry-pick --abort
134+
echo "Cherry-pick successful for commit $merge_commit."
135+
fi
136+
137+
git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
138+
139+
echo "Pushing branch: $cherry_pick_branch"
140+
if ! git push origin $cherry_pick_branch --force; then
141+
echo "Push failed, but continuing to create PR..."
74142
fi
75-
else
76-
echo "Skipping PR #$pr_number as it does not have a merge commit."
77-
fi
78-
done
79143
80-
# Push the cherry-pick branch to the remote repository
81-
git push origin $cherry_pick_branch
144+
new_pr_title="$pr_title [Created by @$pr_creator from #$pr_number]"
145+
new_pr_body="$pr_body
146+
> This PR is created from original PR #$pr_number."
82147
83-
# Step 7: Create a single pull request to merge the cherry-pick branch into the target branch
84-
- name: Create Pull Request to Target Branch
85-
if: steps.fetch_prs.outputs.prs != "[]"
86-
uses: peter-evans/create-pull-request@v4
87-
with:
88-
token: ${{ secrets.GITHUB_TOKEN }}
89-
branch: $cherry_pick_branch
90-
base: ${{ github.event.inputs.target_branch }}
91-
title: "Consolidated Closed Milestone PRs for ${{ github.event.inputs.target_branch }}"
92-
body: "This PR includes all cherry-picked changes from closed PRs in milestone '${{ github.event.inputs.milestone }}' to ${{ github.event.inputs.target_branch }}."
148+
response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
149+
-H "Accept: application/vnd.github+json" \
150+
https://api.github.com/repos/${{ github.repository }}/pulls \
151+
-d "$(jq -n --arg title "$new_pr_title" \
152+
--arg head "$cherry_pick_branch" \
153+
--arg base "$TARGET_BRANCH" \
154+
--arg body "$new_pr_body" \
155+
'{title: $title, head: $head, base: $base, body: $body}')")
156+
157+
new_pr_number=$(echo "$response" | jq -r '.number')
158+
echo "Created PR #$new_pr_number"
159+
160+
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
161+
-H "Accept: application/vnd.github+json" \
162+
-d '{"labels": ["milestone-merge"]}' \
163+
"https://api.github.com/repos/${{ github.repository }}/issues/$new_pr_number/labels"
164+
fi
165+
done

0 commit comments

Comments
 (0)