forked from sonic-net/sonic-mgmt
-
Notifications
You must be signed in to change notification settings - Fork 0
192 lines (181 loc) · 9.26 KB
/
Copy pathpr_cherrypick_prestep.yml
File metadata and controls
192 lines (181 loc) · 9.26 KB
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
183
184
185
186
187
188
189
190
191
192
name: PreCherryPick
on:
pull_request_target:
types:
- labeled
- closed
branches:
- master
jobs:
pre_cherry_pick:
if: github.repository_owner == 'sonic-net' && github.event.pull_request.merged == true && ( (github.event.action == 'closed' && contains(join(github.event.pull_request.labels.*.name, ','), 'Approved for 20')) || (github.event.action == 'labeled' && startsWith(github.event.label.name, 'Approved for 20')) )
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false
- name: Debug
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo $GITHUB_CONTEXT | jq
- name: Main
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
TOKEN: ${{ secrets.TOKEN }}
run: |
set -e
sha=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.merge_commit_sha")
pr_id=$(echo $GITHUB_CONTEXT | jq -r ".event.number")
pr_url=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request._links.html.href")
repository=$(echo $GITHUB_CONTEXT | jq -r ".repository")
labels=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.labels[].name")
author=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.user.login")
branches=$(git branch -a --list 'origin/20????' | awk -F/ '{print$3}' | grep -E "202[0-9]{3}")
if [[ $(echo $GITHUB_CONTEXT | jq -r ".event.action") == "labeled" ]];then
labels=$(echo $GITHUB_CONTEXT | jq -r ".event.label.name")
fi
title=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.title")
body=$(echo $GITHUB_CONTEXT | jq -r ".event.pull_request.body")
echo =============================
echo SHA: $sha
echo PRID: $pr_id
echo pr_url: $pr_url
echo repository: $repository
echo branches: $branches
echo labels:
echo "$labels"
echo ${TOKEN} | gh auth login --with-token
echo author: $author
echo title: $title
echo body: "$body"
echo =============================
git config user.name mssonicbld
git config user.email sonicbld@microsoft.com
git config credential.https://github.com.username mssonicbld
git remote add mssonicbld https://mssonicbld:${TOKEN}@github.com/mssonicbld/sonic-mgmt
git fetch mssonicbld
git remote -vv
cherry_pick(){
set -e
local action=$(echo $GITHUB_CONTEXT | jq -r ".event.action")
# Authorization check: only applies when a label is being added
if [[ "$action" == "labeled" ]]; then
local event_label=$(echo $GITHUB_CONTEXT | jq -r ".event.label.name")
if [[ "$event_label" == "Approved for $branch branch" ]]; then
local sender=$(echo $GITHUB_CONTEXT | jq -r ".event.sender.login")
local org=$(echo $repository | cut -d/ -f1)
local authorized=0
if [[ "$sender" == "StormLiangMS" ]]; then
authorized=1
elif [[ "$(gh api "orgs/${org}/teams/release-manager-${branch}/memberships/${sender}" --jq '.state' 2>/dev/null)" == "active" ]]; then
authorized=1
fi
if [[ "$authorized" != "1" ]]; then
echo "User $sender is not authorized to approve cherry-pick to $branch branch. Removing label."
local release_team="release-manager-${branch}"
local members=$(gh api "orgs/${org}/teams/${release_team}/members" --jq '.[].login' 2>/dev/null | sed 's/^/@/' | tr '\n' ' ')
gh pr edit "$pr_url" --remove-label "$event_label"
gh pr comment "$pr_url" --body "The label \`$event_label\` can only be added by an active member of the @${org}/${release_team} team or @StormLiangMS. Removing the label. Please contact @StormLiangMS or one of the release managers: ${members} to approve the cherry pick."
return 0
fi
fi
fi
local create_pr=''
while read label
do
echo label: $label
if [[ "$label" == "Approved for $branch branch" ]];then
create_pr=1
fi
if [[ "$label" == "Created PR to $branch branch" ]];then
echo "already has tag: Created PR to $branch branch, return"
return 0
fi
if [[ "$label" == "Included in $branch branch" ]];then
echo "already has tag: Included in $branch branch, return"
return 0
fi
if [[ "$label" == "Cherry Pick Conflict_$branch" ]];then
echo "already has tag: Cherry Pick Conflict_$branch, return"
return 0
fi
done <<< "$labels"
if [[ "$create_pr" != "1" ]];then
echo "Didn't find 'Approved for $branch branch' tag."
return 0
fi
# For 'closed' events, verify the label was added by an authorized user.
# Guards against race condition where label was added before merge.
if [[ "$action" == "closed" ]]; then
local org=$(echo $repository | cut -d/ -f1)
local label_adder=$(gh api "repos/${repository}/issues/${pr_id}/events" --paginate \
--jq ".[] | select(.event == \"labeled\" and .label.name == \"Approved for ${branch} branch\") | .actor.login" \
2>/dev/null | tail -1)
local authorized=0
if [[ "$label_adder" == "StormLiangMS" ]]; then
authorized=1
elif [[ -n "$label_adder" ]] && [[ "$(gh api "orgs/${org}/teams/release-manager-${branch}/memberships/${label_adder}" --jq '.state' 2>/dev/null)" == "active" ]]; then
authorized=1
fi
if [[ "$authorized" != "1" ]]; then
echo "Label 'Approved for $branch branch' was added by unauthorized user '${label_adder}'. Skipping cherry-pick."
local release_team="release-manager-${branch}"
local members=$(gh api "orgs/${org}/teams/${release_team}/members" --jq '.[].login' 2>/dev/null | sed 's/^/@/' | tr '\n' ' ')
gh pr edit "$pr_url" --remove-label "Approved for ${branch} branch"
gh pr comment "$pr_url" --body "The label \`Approved for ${branch} branch\` was added by @${label_adder} who is not authorized to approve cherry-picks. Removing the label. Please contact @StormLiangMS or one of the release managers: ${members} to approve the cherry pick."
return 0
fi
fi
# Begin to cherry-pick PR
git cherry-pick --abort 2>/dev/null || true
git clean -xdff 2>/dev/null || true
git reset HEAD --hard || true
git checkout -b $branch --track origin/$branch
git status | grep "working tree clean"
if ! cherry_pick_output=$(git cherry-pick -s "$sha" 2>&1); then
echo "$cherry_pick_output"
if echo "$cherry_pick_output" | grep -qiF "cherry-pick is now empty"; then
echo "Changes are already present in $branch branch."
git cherry-pick --abort
git status | grep "working tree clean"
gh pr edit "$pr_url" --remove-label "Cherry Pick Conflict_$branch" || true
gh pr edit "$pr_url" --add-label "Included in $branch branch"
gh pr comment "$pr_url" --body "No cherry-pick PR is needed for $branch because these changes are already present in the target branch. Added the \`Included in $branch branch\` label."
return 0
fi
echo 'cherry-pick failed.'
git cherry-pick --abort
git status | grep "working tree clean"
# Add label
gh pr edit $pr_url --add-label "Cherry Pick Conflict_$branch"
echo 'Add label "Cherry Pick Conflict_$branch" success'
gh pr comment $pr_url --body "@${author} PR conflicts with $branch branch"
echo 'Add commnet "@${author} PR conflicts with $branch branch"'
else
# Create PR to release branch
git push mssonicbld HEAD:cherry/$branch/${pr_id} -f
result=$(gh pr create -R ${repository} -H mssonicbld:cherry/$branch/${pr_id} -B $branch -t "[action] [PR:$pr_id] $title" -b "$body" 2>&1 || true)
new_pr_url=$(echo $result | grep -Eo https://github.com/sonic-net/sonic-mgmt/pull/[0-9]*)
echo new_pr_url: $new_pr_url
# Add label to old PR
gh pr edit $pr_url --add-label "Created PR to $branch branch"
echo Add label Created PR to $branch branch
# Add comment to old PR
gh pr comment $pr_url --body "Cherry-pick PR to $branch: ${new_pr_url}"
echo Add comment to old PR
# Add label to new PR
gh pr edit $new_pr_url --add-label "automerge"
echo Add label automerge to new PR
# Add comment to new PR
gh pr comment $new_pr_url --body "Original PR: ${pr_url}"
echo Add comment to new PR
fi
}
for branch in $branches
do
echo -------------------------------------------
echo Begin to parse Branch: $branch
cherry_pick
done