Skip to content

Commit e9bc58b

Browse files
authored
Update auto-assign-reviewers.yml
1 parent 963a96b commit e9bc58b

File tree

1 file changed

+93
-82
lines changed

1 file changed

+93
-82
lines changed

.github/workflows/auto-assign-reviewers.yml

+93-82
Original file line numberDiff line numberDiff line change
@@ -32,59 +32,64 @@ jobs:
3232
run: |
3333
PR_NUMBER=${{ github.event.pull_request.number }}
3434
echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_OUTPUT
35-
3635
- name: Checkout code
3736
uses: actions/checkout@v4
3837
with:
3938
ref: master
4039
sparse-checkout: MAINTAINERS
4140
persist-credentials: false
42-
4341
- name: Get changed files
4442
id: changed_files
4543
run: |
46-
# 获取 PR 的变更文件列表
44+
# 通过 GitHub API 获取 PR 的变更文件列表
4745
changed_files=$(curl -s \
4846
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.extract-pr.outputs.PR_NUMBER }}/files" | \
49-
jq -r '.[].filename')
47+
jq -r '.[].filename') # 使用 jq 提取文件名
5048
echo "$changed_files" | grep -v '^MAINTAINERS$' > changed_files.txt
51-
52-
# 检查现有 bot 评论
49+
5350
existing_comment=$(curl -s \
54-
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments" | \
55-
jq -r '.[] | select(.user.login == "github-actions[bot]") | {body: .body} | @base64')
51+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments" | \
52+
jq -r '.[] | select(.user.login == "github-actions[bot]") | {body: .body} | @base64')
5653
5754
echo "=== Changed Files ==="
5855
cat changed_files.txt
5956
echo "====================="
6057
61-
comment_time=""
62-
if [[ -n "$existing_comment" ]]; then
63-
comment_body=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .body | sed -nE 's/.*Last Updated: ([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} UTC).*/\1/p')
64-
if [[ -n "$comment_body" ]]; then
65-
comment_time=$(date -d "$comment_body" +%s)
66-
fi
58+
comment_body=""
59+
if [[ ! -z "$existing_comment" ]]; then
60+
comment_body=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .body|sed -nE 's/.*Last Updated: ([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} UTC).*/\1/p')
61+
62+
comment_time=$(date -d "$comment_body" +%s)
63+
64+
echo "${comment_body}"
65+
echo "COMMENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
66+
else
67+
comment_time=""
68+
echo "COMMENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
6769
fi
68-
echo "COMMENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
70+
echo "COMMENT_TIME=${comment_time}"
71+
6972
7073
- name: Parse MAINTAINERS file
7174
id: parse_maintainer
7275
run: |
73-
# 解析 MAINTAINERS 文件,提取 tag、path 和 owners
76+
# 使用 AWK 解析 MAINTAINERS 文件格式:
77+
# 提取 tag(标签)、path(路径)和 owners(维护者 GitHub ID)
7478
awk '
7579
/^tag:/ {
76-
tag = substr($0, index($0, $2))
80+
tag = substr($0, index($0, $2)) # 提取标签内容
7781
}
7882
/^path:/ {
83+
# 提取 path 字段并去除前后空格
7984
path = substr($0, index($0, $2))
80-
gsub(/^[ \t]+|[ \t]+$/, "", path)
85+
gsub(/^[ \t]+|[ \t]+$/, "", path) # 清理前后空格和制表符
8186
}
8287
/^owners:/ {
83-
owners = substr($0, index($0, $2))
84-
split(owners, parts, /[()]/)
88+
owners = substr($0, index($0, $2)) # 提取维护者信息
89+
split(owners, parts, /[()]/) # 拆分出 GitHub ID(括号内内容)
8590
github_ids = ""
8691
for (i=2; i<=length(parts); i+=2) {
87-
github_ids = github_ids "@" parts[i] " "
92+
github_ids = github_ids "@" parts[i] " " # 拼接为 @user 格式
8893
}
8994
print tag "|" path "|" github_ids
9095
}
@@ -93,148 +98,154 @@ jobs:
9398
- name: Generate reviewers list
9499
id: generate_reviewers
95100
run: |
96-
rm -f triggered_reviewers.txt triggered_tags.txt unique_reviewers.txt unique_tags.txt
97-
touch triggered_reviewers.txt triggered_tags.txt unique_reviewers.txt unique_tags.txt
101+
rm -f triggered_reviewers.txt triggered_tags.txt
102+
touch triggered_reviewers.txt triggered_tags.txt
98103
99104
while IFS='|' read -r tag path reviewers; do
100105
# 转义路径中的正则特殊字符
101106
escaped_path=$(sed 's/[.[\*^$]/\\&/g' <<< "$path")
102-
# 匹配路径及其子目录
107+
108+
# 使用增强型正则匹配路径及其所有子目录
103109
if grep -qE "^$escaped_path(/.*)*" changed_files.txt; then
104110
echo "$reviewers" | tr -s ' ' '\n' | sed '/^$/d' >> triggered_reviewers.txt
105111
echo "$tag" >> triggered_tags.txt
106112
echo "Matched: $path → $tag"
107113
fi
108114
done < tag_data.csv
109115
110-
# 生成去重后的审阅者和标签列表
111-
sort triggered_reviewers.txt | uniq > unique_reviewers.txt
112-
sort triggered_tags.txt | uniq > unique_tags.txt
113-
114116
echo "=== Matched Paths ==="
115-
cat unique_tags.txt
117+
cat triggered_tags.txt
116118
echo "=== Matched Reviewers ==="
117-
cat unique_reviewers.txt
119+
cat triggered_reviewers.txt
118120
119121
- name: Restore Reviewers Cache
120-
id: reviewers-cache-restore
122+
id: reviewers-cache-restore
121123
if: ${{ steps.changed_files.outputs.COMMENT_TIME != '' }}
122124
uses: actions/cache/restore@v4
123-
with:
125+
with:
124126
path: |
125127
unique_tags_bak.txt
126128
unique_reviewers_bak.txt
127129
key: ${{ runner.os }}-auto-assign-reviewers-${{ steps.extract-pr.outputs.PR_NUMBER }}-${{ steps.changed_files.outputs.COMMENT_TIME }}
128-
129130
- name: Get approval status
130131
id: get_approval
131132
run: |
132133
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
133-
134-
# 检查 unique_reviewers.txt 是否存在
135-
if [[ ! -f unique_reviewers.txt ]]; then
136-
echo "Error: unique_reviewers.txt not found. Skipping approval status generation."
137-
echo "CURRENT_TIME=${current_time}" >> $GITHUB_OUTPUT
138-
exit 0
139-
fi
140-
141134
reviewers=$(cat unique_reviewers.txt | tr '\n' '|')
142-
135+
143136
# 获取 PR 的所有评论
144137
comments=$(curl -s \
145138
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments")
146139
147140
echo '#!/bin/bash' > approval_data.sh
148141
echo 'declare -A approvals=()' >> approval_data.sh
149-
150-
# 解析 LGTM 评论
142+
143+
# 使用 jq 解析包含 LGTM 的有效评论
151144
jq -r --arg reviewers "$reviewers" '
152-
.[] |
153-
select(.user.login != "github-actions[bot]") |
154-
select(.body | test("^\\s*LGTM\\s*$"; "i")) |
145+
.[] |
146+
select(.user.login != "github-actions[bot]") | # 排除 bot 的评论
147+
select(.body | test("^\\s*LGTM\\s*$"; "i")) | # 匹配 LGTM 评论(不区分大小写)
155148
.user.login as $user |
156149
"@\($user)" as $mention |
157-
($reviewers | split("\\|") | index($mention)) as $is_reviewer |
158-
if $is_reviewer != null then
159-
"approvals[\"\($mention)\"]=\"\(.created_at)\""
160-
else
161-
empty
162-
end
150+
select($mention | inside($reviewers)) | # 过滤有效审查者
151+
"approvals[\"\($mention)\"]=\"\(.created_at)\"" # 记录审批时间
163152
' <<< "$comments" >> approval_data.sh
164-
165-
# 加载审批数据
153+
154+
# 加载审查数据并生成状态报告
166155
chmod +x approval_data.sh
167156
source ./approval_data.sh
168157
169-
# 生成审批状态报告
158+
jq -r --arg reviewers "$reviewers" '
159+
.[] |
160+
select(.user.login != "github-actions[bot]") | # 排除 bot 的评论
161+
select(.body | test("^\\s*LGTM\\s*$"; "i")) | # 匹配 LGTM 评论(不区分大小写)
162+
.user.login as $user |
163+
"@\($user)" as $mention |
164+
select($mention | inside($reviewers)) | # 过滤有效审查者
165+
"\($mention) \(.created_at)" # 输出审查者和时间
166+
' <<< "$comments" >> approval_data.txt
167+
170168
notified_users=""
171169
if [[ -f unique_reviewers_bak.txt ]]; then
172170
notified_users=$(cat unique_reviewers_bak.txt | xargs)
171+
else
172+
notified_users=""
173173
fi
174174
175175
{
176176
echo "---"
177177
echo "### 📊 Current Review Status (Last Updated: $current_time)"
178178
while read -r reviewer; do
179-
display_name="${reviewer#@}"
179+
formatted_reviewers=""
180+
for r in $reviewers; do
181+
if [[ " ${notified_users[@]} " =~ " $reviewer " ]]; then
182+
formatted_reviewers+="${reviewer#@}"
183+
else
184+
formatted_reviewers+="$reviewer"
185+
fi
186+
done
187+
180188
if [[ -n "${approvals[$reviewer]}" ]]; then
181189
timestamp=$(date -d "${approvals[$reviewer]}" -u +"%Y-%m-%d %H:%M UTC")
182-
echo "- ✅ **$display_name** Reviewed On $timestamp"
190+
191+
echo "- ✅ **$formatted_reviewers** Reviewed On $timestamp"
183192
else
184-
echo "- ⌛ **$display_name** Pending Review"
193+
echo "- ⌛ **$formatted_reviewers** Pending Review"
185194
fi
186195
done < unique_reviewers.txt
187196
} > review_status.md
188-
197+
189198
echo "CURRENT_TIME=${current_time}" >> $GITHUB_OUTPUT
190-
191199
- name: Generate review data
192200
id: generate_review
193201
run: |
202+
unique_tags=""
194203
unique_tags=$(cat unique_tags.txt | xargs)
195204
unique_tags_bak=""
196205
if [[ -f unique_tags_bak.txt ]]; then
197206
unique_tags_bak=$(cat unique_tags_bak.txt | xargs)
198207
fi
199208
200-
# 确定新标签
201209
existing_tags=""
202210
for r in $unique_tags; do
203-
if [[ ! " $unique_tags_bak " =~ " $r " ]]; then
211+
if [[ " ${unique_tags_bak[@]} " =~ " $r " ]]; then
212+
echo "$r 不存在于数组中"
213+
else
204214
existing_tags+="$r "
205215
fi
206216
done
207217
218+
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
208219
{
220+
221+
# 生成审查分配信息
209222
echo "## 📌 Code Review Assignment"
210223
echo ""
211224
212225
while IFS='|' read -r tag path reviewers; do
213226
if grep -qE "^$path(/|$)" changed_files.txt; then
214227
echo "### 🏷️ Tag: $tag"
215-
echo "**Path:** \`$path\`"
228+
echo "**Path:** \`$path\` "
216229
217-
# 根据标签是否为新标签决定是否移除 @
218-
if [[ " $existing_tags " =~ " $tag " ]]; then
219-
echo "**Reviewers:** $reviewers"
230+
if [[ " ${existing_tags[@]} " =~ " $tag " ]]; then
231+
echo "**Reviewers:** $reviewers "
220232
else
221233
formatted_reviewers=""
222234
for r in $reviewers; do
223235
formatted_reviewers+="${r#@} "
224236
done
225-
echo "**Reviewers:** $formatted_reviewers"
237+
echo "**Reviewers:** $formatted_reviewers "
226238
fi
227239
228240
echo "<details>"
229241
echo "<summary><b>Changed Files</b> (Click to expand)</summary>"
230242
echo ""
231-
grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /'
243+
grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /' # 列出匹配的变更文件
232244
echo ""
233245
echo "</details>"
234246
echo ""
235247
fi
236248
done < tag_data.csv
237-
238249
# 插入审查状态
239250
cat review_status.md
240251
@@ -253,43 +264,43 @@ jobs:
253264
echo "> ℹ️ **刷新CI状态操作需要具备仓库写入权限。**"
254265
echo "> ℹ️ **Refresh CI status operation requires repository Write permission.**"
255266
} > review_data.md
256-
257267
- name: Post/Update comment
258268
id: post_comment
259269
run: |
260-
# 查找现有 bot 评论
270+
# 查找现有的 bot 评论
261271
existing_comment=$(curl -s \
262272
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
263273
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments" | \
264274
jq -r '.[] | select(.user.login == "github-actions[bot]") | {id: .id, body: .body} | @base64')
265-
275+
266276
if [[ -n "$existing_comment" ]]; then
267277
# 更新现有评论
268278
comment_id=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .id)
269279
echo "Updating existing comment $comment_id"
270-
curl -s -X PATCH \
280+
response=$(curl -s -X PATCH \
271281
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
272282
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
273-
"https://api.github.com/repos/${{ github.repository }}/issues/comments/$comment_id"
283+
"https://api.github.com/repos/${{ github.repository }}/issues/comments/$comment_id")
274284
else
275285
# 创建新评论
276286
echo "Creating new comment"
277-
curl -s -X POST \
287+
response=$(curl -s -X POST \
278288
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
279289
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
280-
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments"
290+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments")
281291
fi
282-
283292
- name: Get Comment Time
284293
id: get_comment_time
285294
run: |
286-
current_time="${{ steps.get_approval.outputs.CURRENT_TIME }}"
287-
comment_time=$(date -d "$current_time" +%s)
295+
existing_comment=$(curl -s \
296+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments" | \
297+
jq -r '.[] | select(.user.login == "github-actions[bot]") | {body: .body} | @base64')
298+
comment_body="${{ steps.get_approval.outputs.CURRENT_TIME }}"
299+
comment_time=$(date -d "$comment_body" +%s)
288300
echo "CURRENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
289301
cp unique_reviewers.txt unique_reviewers_bak.txt
290302
cp unique_tags.txt unique_tags_bak.txt
291-
292-
- name: Save Reviewers Cache
303+
- name: Restore Reviewers Save
293304
id: reviewers-cache-save
294305
uses: actions/cache/save@v4
295306
with:

0 commit comments

Comments
 (0)