Skip to content

Commit 34ee870

Browse files
authored
Create auto-assign-reviewers.yml
1 parent 3469871 commit 34ee870

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#
2+
# Copyright (c) 2006-2025, RT-Thread Development Team
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Change Logs:
7+
# Date Author Notes
8+
# 2025-01-21 kurisaW Initial version
9+
#
10+
11+
# Script Function Description: Assign PR reviews based on the MAINTAINERS list.
12+
13+
name: Auto Review Assistant
14+
15+
on:
16+
pull_request:
17+
types: [opened, synchronize, reopened]
18+
workflow_dispatch:
19+
issue_comment:
20+
types: [created]
21+
22+
jobs:
23+
assign-reviewers:
24+
runs-on: ubuntu-22.04
25+
permissions:
26+
issues: write
27+
pull-requests: write
28+
contents: read
29+
steps:
30+
- name: Checkout code
31+
uses: actions/checkout@v3
32+
33+
- name: Get changed files
34+
id: changed_files
35+
run: |
36+
# 通过 GitHub API 获取 PR 的变更文件列表
37+
changed_files=$(curl -s \
38+
-H "Authorization: Bearer ${{ secrets.ACTION_TOKEN_AUTO_REVIEW }}" \
39+
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" | \
40+
jq -r '.[].filename') # 使用 jq 提取文件名
41+
42+
echo "$changed_files" | grep -v '^MAINTAINERS$' > changed_files.txt
43+
44+
- name: Parse MAINTAINERS file
45+
id: parse_maintainer
46+
run: |
47+
# 使用 AWK 解析 MAINTAINERS 文件格式:
48+
# 提取 tag(标签)、path(路径)和 owners(维护者 GitHub ID)
49+
awk '
50+
/^tag:/ {
51+
tag = substr($0, index($0, $2)) # 提取标签内容
52+
}
53+
/^path:/ {
54+
path = substr($0, index($0, $2)) # 提取路径内容
55+
}
56+
/^owners:/ {
57+
owners = substr($0, index($0, $2)) # 提取维护者信息
58+
split(owners, parts, /[()]/) # 拆分出 GitHub ID(括号内内容)
59+
github_ids = ""
60+
for (i=2; i<=length(parts); i+=2) {
61+
github_ids = github_ids "@" parts[i] " " # 拼接为 @user 格式
62+
}
63+
print tag "|" path "|" github_ids
64+
}
65+
' MAINTAINERS > tag_data.csv
66+
67+
- name: Generate reviewers list
68+
id: generate_reviewers
69+
run: |
70+
# 根据变更文件路径匹配维护者规则
71+
rm -f triggered_reviewers.txt
72+
while IFS='|' read -r tag path reviewers; do
73+
# 使用正则匹配路径(支持子目录)
74+
if grep -qE "^$path(/|$)" changed_files.txt; then
75+
echo "$reviewers" | tr ' ' '\n' >> triggered_reviewers.txt
76+
fi
77+
done < tag_data.csv
78+
# 去重处理
79+
awk 'NF && !seen[$0]++' triggered_reviewers.txt > unique_reviewers.txt
80+
81+
- name: Get approval status
82+
id: get_approval
83+
run: |
84+
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
85+
reviewers=$(cat unique_reviewers.txt | tr '\n' '|')
86+
87+
# 获取 PR 的所有评论
88+
comments=$(curl -s \
89+
-H "Authorization: Bearer ${{ secrets.ACTION_TOKEN_AUTO_REVIEW }}" \
90+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments")
91+
92+
echo '#!/bin/bash' > approval_data.sh
93+
echo 'declare -A approvals=()' >> approval_data.sh
94+
95+
# 使用 jq 解析包含 LGTM 的有效评论
96+
jq -r --arg reviewers "$reviewers" '
97+
.[] |
98+
select(.user.login != "github-actions[bot]") | # 排除 bot 的评论
99+
select(.body | test("^\\s*LGTM\\s*$"; "i")) | # 匹配 LGTM 评论(不区分大小写)
100+
.user.login as $user |
101+
"@\($user)" as $mention |
102+
select($mention | inside($reviewers)) | # 过滤有效审查者
103+
"approvals[\"\($mention)\"]=\"\(.created_at)\"" # 记录审批时间
104+
' <<< "$comments" >> approval_data.sh
105+
106+
# 加载审查数据并生成状态报告
107+
chmod +x approval_data.sh
108+
source ./approval_data.sh
109+
110+
{
111+
echo "---"
112+
echo "### 📊 Current Review Status (Last Updated: $current_time)"
113+
while read -r reviewer; do
114+
if [[ -n "${approvals[$reviewer]}" ]]; then
115+
timestamp=$(date -d "${approvals[$reviewer]}" -u +"%Y-%m-%d %H:%M UTC")
116+
echo "- ✅ **$reviewer** Reviewed On $timestamp"
117+
else
118+
echo "- ⌛ **$reviewer** Pending Review"
119+
fi
120+
done < unique_reviewers.txt
121+
} > review_status.md
122+
123+
- name: Generate review data
124+
id: generate_review
125+
run: |
126+
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
127+
{
128+
# 生成审查分配信息
129+
echo "## 📌 Code Review Assignment"
130+
echo ""
131+
132+
while IFS='|' read -r tag path reviewers; do
133+
if grep -qE "^$path(/|$)" changed_files.txt; then
134+
echo "### 🏷️ Tag: $tag"
135+
echo "**Path:** \`$path\` "
136+
echo "**Reviewers:** $reviewers "
137+
echo "<details>"
138+
echo "<summary><b>Changed Files</b> (Click to expand)</summary>"
139+
echo ""
140+
grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /' # 列出匹配的变更文件
141+
echo ""
142+
echo "</details>"
143+
echo ""
144+
fi
145+
done < tag_data.csv
146+
# 插入审查状态
147+
cat review_status.md
148+
149+
echo "---"
150+
echo "### 📝 Review Instructions"
151+
echo ""
152+
echo "1. **维护者可以通过单击此处来刷新审查状态:** [🔄 刷新状态](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
153+
echo " **Maintainers can refresh the review status by clicking here:** [🔄 Refresh Status](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
154+
echo ""
155+
echo "2. **确认审核通过后评论 \`LGTM/lgtm\`**"
156+
echo " **Comment \`LGTM/lgtm\` after confirming approval**"
157+
echo ""
158+
echo "3. **PR合并前需至少一位维护者确认**"
159+
echo " **PR must be confirmed by at least one maintainer before merging**"
160+
echo ""
161+
echo "> ℹ️ **刷新CI状态操作需要具备仓库写入权限。**"
162+
echo "> ℹ️ **Refresh CI status operation requires repository Write permission.**"
163+
} > review_data.md
164+
165+
- name: Post/Update comment
166+
id: post_comment
167+
run: |
168+
# 查找现有的 bot 评论
169+
existing_comment=$(curl -s \
170+
-H "Authorization: Bearer ${{ secrets.ACTION_TOKEN_AUTO_REVIEW }}" \
171+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" | \
172+
jq -r '.[] | select(.user.login == "github-actions[bot]") | {id: .id, body: .body} | @base64')
173+
174+
if [[ -n "$existing_comment" ]]; then
175+
# 更新现有评论
176+
comment_id=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .id)
177+
echo "Updating existing comment $comment_id"
178+
response=$(curl -s -X PATCH \
179+
-H "Authorization: Bearer ${{ secrets.ACTION_TOKEN_AUTO_REVIEW }}" \
180+
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
181+
"https://api.github.com/repos/${{ github.repository }}/issues/comments/$comment_id")
182+
else
183+
# 创建新评论
184+
echo "Creating new comment"
185+
response=$(curl -s -X POST \
186+
-H "Authorization: Bearer ${{ secrets.ACTION_TOKEN_AUTO_REVIEW }}" \
187+
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
188+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments")
189+
fi

0 commit comments

Comments
 (0)