@@ -32,59 +32,64 @@ jobs:
32
32
run : |
33
33
PR_NUMBER=${{ github.event.pull_request.number }}
34
34
echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_OUTPUT
35
-
36
35
- name : Checkout code
37
36
uses : actions/checkout@v4
38
37
with :
39
38
ref : master
40
39
sparse-checkout : MAINTAINERS
41
40
persist-credentials : false
42
-
43
41
- name : Get changed files
44
42
id : changed_files
45
43
run : |
46
- # 获取 PR 的变更文件列表
44
+ # 通过 GitHub API 获取 PR 的变更文件列表
47
45
changed_files=$(curl -s \
48
46
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.extract-pr.outputs.PR_NUMBER }}/files" | \
49
- jq -r '.[].filename')
47
+ jq -r '.[].filename') # 使用 jq 提取文件名
50
48
echo "$changed_files" | grep -v '^MAINTAINERS$' > changed_files.txt
51
-
52
- # 检查现有 bot 评论
49
+
53
50
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')
56
53
57
54
echo "=== Changed Files ==="
58
55
cat changed_files.txt
59
56
echo "====================="
60
57
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
67
69
fi
68
- echo "COMMENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
70
+ echo "COMMENT_TIME=${comment_time}"
71
+
69
72
70
73
- name : Parse MAINTAINERS file
71
74
id : parse_maintainer
72
75
run : |
73
- # 解析 MAINTAINERS 文件,提取 tag、path 和 owners
76
+ # 使用 AWK 解析 MAINTAINERS 文件格式:
77
+ # 提取 tag(标签)、path(路径)和 owners(维护者 GitHub ID)
74
78
awk '
75
79
/^tag:/ {
76
- tag = substr($0, index($0, $2))
80
+ tag = substr($0, index($0, $2)) # 提取标签内容
77
81
}
78
82
/^path:/ {
83
+ # 提取 path 字段并去除前后空格
79
84
path = substr($0, index($0, $2))
80
- gsub(/^[ \t]+|[ \t]+$/, "", path)
85
+ gsub(/^[ \t]+|[ \t]+$/, "", path) # 清理前后空格和制表符
81
86
}
82
87
/^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(括号内内容)
85
90
github_ids = ""
86
91
for (i=2; i<=length(parts); i+=2) {
87
- github_ids = github_ids "@" parts[i] " "
92
+ github_ids = github_ids "@" parts[i] " " # 拼接为 @user 格式
88
93
}
89
94
print tag "|" path "|" github_ids
90
95
}
@@ -93,148 +98,154 @@ jobs:
93
98
- name : Generate reviewers list
94
99
id : generate_reviewers
95
100
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
98
103
99
104
while IFS='|' read -r tag path reviewers; do
100
105
# 转义路径中的正则特殊字符
101
106
escaped_path=$(sed 's/[.[\*^$]/\\&/g' <<< "$path")
102
- # 匹配路径及其子目录
107
+
108
+ # 使用增强型正则匹配路径及其所有子目录
103
109
if grep -qE "^$escaped_path(/.*)*" changed_files.txt; then
104
110
echo "$reviewers" | tr -s ' ' '\n' | sed '/^$/d' >> triggered_reviewers.txt
105
111
echo "$tag" >> triggered_tags.txt
106
112
echo "Matched: $path → $tag"
107
113
fi
108
114
done < tag_data.csv
109
115
110
- # 生成去重后的审阅者和标签列表
111
- sort triggered_reviewers.txt | uniq > unique_reviewers.txt
112
- sort triggered_tags.txt | uniq > unique_tags.txt
113
-
114
116
echo "=== Matched Paths ==="
115
- cat unique_tags .txt
117
+ cat triggered_tags .txt
116
118
echo "=== Matched Reviewers ==="
117
- cat unique_reviewers .txt
119
+ cat triggered_reviewers .txt
118
120
119
121
- name : Restore Reviewers Cache
120
- id : reviewers-cache-restore
122
+ id : reviewers-cache-restore
121
123
if : ${{ steps.changed_files.outputs.COMMENT_TIME != '' }}
122
124
uses : actions/cache/restore@v4
123
- with :
125
+ with :
124
126
path : |
125
127
unique_tags_bak.txt
126
128
unique_reviewers_bak.txt
127
129
key : ${{ runner.os }}-auto-assign-reviewers-${{ steps.extract-pr.outputs.PR_NUMBER }}-${{ steps.changed_files.outputs.COMMENT_TIME }}
128
-
129
130
- name : Get approval status
130
131
id : get_approval
131
132
run : |
132
133
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
-
141
134
reviewers=$(cat unique_reviewers.txt | tr '\n' '|')
142
-
135
+
143
136
# 获取 PR 的所有评论
144
137
comments=$(curl -s \
145
138
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments")
146
139
147
140
echo '#!/bin/bash' > approval_data.sh
148
141
echo 'declare -A approvals=()' >> approval_data.sh
149
-
150
- # 解析 LGTM 评论
142
+
143
+ # 使用 jq 解析包含 LGTM 的有效评论
151
144
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 评论(不区分大小写)
155
148
.user.login as $user |
156
149
"@\($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)\"" # 记录审批时间
163
152
' <<< "$comments" >> approval_data.sh
164
-
165
- # 加载审批数据
153
+
154
+ # 加载审查数据并生成状态报告
166
155
chmod +x approval_data.sh
167
156
source ./approval_data.sh
168
157
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
+
170
168
notified_users=""
171
169
if [[ -f unique_reviewers_bak.txt ]]; then
172
170
notified_users=$(cat unique_reviewers_bak.txt | xargs)
171
+ else
172
+ notified_users=""
173
173
fi
174
174
175
175
{
176
176
echo "---"
177
177
echo "### 📊 Current Review Status (Last Updated: $current_time)"
178
178
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
+
180
188
if [[ -n "${approvals[$reviewer]}" ]]; then
181
189
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"
183
192
else
184
- echo "- ⌛ **$display_name ** Pending Review"
193
+ echo "- ⌛ **$formatted_reviewers ** Pending Review"
185
194
fi
186
195
done < unique_reviewers.txt
187
196
} > review_status.md
188
-
197
+
189
198
echo "CURRENT_TIME=${current_time}" >> $GITHUB_OUTPUT
190
-
191
199
- name : Generate review data
192
200
id : generate_review
193
201
run : |
202
+ unique_tags=""
194
203
unique_tags=$(cat unique_tags.txt | xargs)
195
204
unique_tags_bak=""
196
205
if [[ -f unique_tags_bak.txt ]]; then
197
206
unique_tags_bak=$(cat unique_tags_bak.txt | xargs)
198
207
fi
199
208
200
- # 确定新标签
201
209
existing_tags=""
202
210
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
204
214
existing_tags+="$r "
205
215
fi
206
216
done
207
217
218
+ current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
208
219
{
220
+
221
+ # 生成审查分配信息
209
222
echo "## 📌 Code Review Assignment"
210
223
echo ""
211
224
212
225
while IFS='|' read -r tag path reviewers; do
213
226
if grep -qE "^$path(/|$)" changed_files.txt; then
214
227
echo "### 🏷️ Tag: $tag"
215
- echo "**Path:** \`$path\`"
228
+ echo "**Path:** \`$path\` "
216
229
217
- # 根据标签是否为新标签决定是否移除 @
218
- if [[ " $existing_tags " =~ " $tag " ]]; then
219
- echo "**Reviewers:** $reviewers"
230
+ if [[ " ${existing_tags[@]} " =~ " $tag " ]]; then
231
+ echo "**Reviewers:** $reviewers "
220
232
else
221
233
formatted_reviewers=""
222
234
for r in $reviewers; do
223
235
formatted_reviewers+="${r#@} "
224
236
done
225
- echo "**Reviewers:** $formatted_reviewers"
237
+ echo "**Reviewers:** $formatted_reviewers "
226
238
fi
227
239
228
240
echo "<details>"
229
241
echo "<summary><b>Changed Files</b> (Click to expand)</summary>"
230
242
echo ""
231
- grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /'
243
+ grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /' # 列出匹配的变更文件
232
244
echo ""
233
245
echo "</details>"
234
246
echo ""
235
247
fi
236
248
done < tag_data.csv
237
-
238
249
# 插入审查状态
239
250
cat review_status.md
240
251
@@ -253,43 +264,43 @@ jobs:
253
264
echo "> ℹ️ **刷新CI状态操作需要具备仓库写入权限。**"
254
265
echo "> ℹ️ **Refresh CI status operation requires repository Write permission.**"
255
266
} > review_data.md
256
-
257
267
- name : Post/Update comment
258
268
id : post_comment
259
269
run : |
260
- # 查找现有 bot 评论
270
+ # 查找现有的 bot 评论
261
271
existing_comment=$(curl -s \
262
272
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
263
273
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.extract-pr.outputs.PR_NUMBER }}/comments" | \
264
274
jq -r '.[] | select(.user.login == "github-actions[bot]") | {id: .id, body: .body} | @base64')
265
-
275
+
266
276
if [[ -n "$existing_comment" ]]; then
267
277
# 更新现有评论
268
278
comment_id=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .id)
269
279
echo "Updating existing comment $comment_id"
270
- curl -s -X PATCH \
280
+ response=$( curl -s -X PATCH \
271
281
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
272
282
-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")
274
284
else
275
285
# 创建新评论
276
286
echo "Creating new comment"
277
- curl -s -X POST \
287
+ response=$( curl -s -X POST \
278
288
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
279
289
-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")
281
291
fi
282
-
283
292
- name : Get Comment Time
284
293
id : get_comment_time
285
294
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)
288
300
echo "CURRENT_TIME=${comment_time}" >> $GITHUB_OUTPUT
289
301
cp unique_reviewers.txt unique_reviewers_bak.txt
290
302
cp unique_tags.txt unique_tags_bak.txt
291
-
292
- - name : Save Reviewers Cache
303
+ - name : Restore Reviewers Save
293
304
id : reviewers-cache-save
294
305
uses : actions/cache/save@v4
295
306
with :
0 commit comments