Skip to content

Commit d63b60e

Browse files
committed
feat: CI script assigns PR reviews based on the list of maintainers
1 parent 3436aa6 commit d63b60e

File tree

2 files changed

+234
-0
lines changed

2 files changed

+234
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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+
if: github.repository_owner == 'RT-Thread'
26+
permissions:
27+
issues: write
28+
pull-requests: write
29+
contents: read
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@v3
33+
34+
- name: Get changed files
35+
id: changed_files
36+
run: |
37+
changed_files=$(curl -s \
38+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN_AUTO_REVIEW }}" \
39+
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" | \
40+
jq -r '.[].filename')
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 '
48+
/^tag:/ {
49+
tag = substr($0, index($0, $2))
50+
}
51+
/^path:/ {
52+
path = substr($0, index($0, $2))
53+
}
54+
/^owners:/ {
55+
owners = substr($0, index($0, $2))
56+
split(owners, parts, /[()]/)
57+
github_ids = ""
58+
for (i=2; i<=length(parts); i+=2) {
59+
github_ids = github_ids "@" parts[i] " "
60+
}
61+
print tag "|" path "|" github_ids
62+
}
63+
' MAINTAINERS > tag_data.csv
64+
65+
- name: Generate reviewers list
66+
id: generate_reviewers
67+
run: |
68+
rm -f triggered_reviewers.txt
69+
while IFS='|' read -r tag path reviewers; do
70+
if grep -qE "^$path(/|$)" changed_files.txt; then
71+
echo "$reviewers" | tr ' ' '\n' >> triggered_reviewers.txt
72+
fi
73+
done < tag_data.csv
74+
awk 'NF && !seen[$0]++' triggered_reviewers.txt > unique_reviewers.txt
75+
76+
- name: Get approval status
77+
id: get_approval
78+
run: |
79+
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
80+
reviewers=$(cat unique_reviewers.txt | tr '\n' '|')
81+
82+
comments=$(curl -s \
83+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN_AUTO_REVIEW }}" \
84+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments")
85+
86+
echo '#!/bin/bash' > approval_data.sh
87+
echo 'declare -A approvals=()' >> approval_data.sh
88+
89+
jq -r --arg reviewers "$reviewers" '
90+
.[] |
91+
select(.user.login != "github-actions[bot]") |
92+
select(.body | test("^\\s*LGTM\\s*$"; "i")) |
93+
.user.login as $user |
94+
"@\($user)" as $mention |
95+
select($mention | inside($reviewers)) |
96+
"approvals[\"\($mention)\"]=\"\(.created_at)\""
97+
' <<< "$comments" >> approval_data.sh
98+
99+
chmod +x approval_data.sh
100+
source ./approval_data.sh
101+
102+
{
103+
echo "---"
104+
echo "### 📊 Current Review Status (Last Updated: $current_time)"
105+
while read -r reviewer; do
106+
if [[ -n "${approvals[$reviewer]}" ]]; then
107+
timestamp=$(date -d "${approvals[$reviewer]}" -u +"%Y-%m-%d %H:%M UTC")
108+
echo "- ✅ **$reviewer** Reviewed On $timestamp"
109+
else
110+
echo "- ⌛ **$reviewer** Pending Review"
111+
fi
112+
done < unique_reviewers.txt
113+
} > review_status.md
114+
115+
- name: Generate review data
116+
id: generate_review
117+
run: |
118+
current_time=$(date -u +"%Y-%m-%d %H:%M UTC")
119+
{
120+
echo "## 📌 Code Review Assignment"
121+
echo ""
122+
123+
while IFS='|' read -r tag path reviewers; do
124+
if grep -qE "^$path(/|$)" changed_files.txt; then
125+
echo "### 🏷️ Tag: $tag"
126+
echo "**Path:** \`$path\` "
127+
echo "**Reviewers:** $reviewers "
128+
echo "<details>"
129+
echo "<summary><b>Changed Files</b> (Click to expand)</summary>"
130+
echo ""
131+
grep -E "^$path(/|$)" changed_files.txt | sed 's/^/- /'
132+
echo ""
133+
echo "</details>"
134+
echo ""
135+
fi
136+
done < tag_data.csv
137+
138+
cat review_status.md
139+
140+
echo "---"
141+
echo "### 📝 Review Instructions"
142+
echo ""
143+
echo "1. **维护者可以通过单击此处来刷新审查状态:** [🔄 刷新状态](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
144+
echo " **Maintainers can refresh the review status by clicking here:** [🔄 Refresh Status](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
145+
echo ""
146+
echo "2. **确认审核通过后评论 \`LGTM/lgtm\`**"
147+
echo " **Comment \`LGTM/lgtm\` after confirming approval**"
148+
echo ""
149+
echo "3. **PR合并前需至少一位维护者确认**"
150+
echo " **PR must be confirmed by at least one maintainer before merging**"
151+
echo ""
152+
echo "> ℹ️ **刷新CI状态操作需要具备仓库写入权限。**"
153+
echo "> ℹ️ **Refresh CI status operation requires repository Write permission.**"
154+
} > review_data.md
155+
156+
- name: Post/Update comment
157+
id: post_comment
158+
run: |
159+
existing_comment=$(curl -s \
160+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN_AUTO_REVIEW }}" \
161+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" | \
162+
jq -r '.[] | select(.user.login == "github-actions[bot]") | {id: .id, body: .body} | @base64')
163+
164+
if [[ -n "$existing_comment" ]]; then
165+
comment_id=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .id)
166+
echo "Updating existing comment $comment_id"
167+
response=$(curl -s -X PATCH \
168+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN_AUTO_REVIEW }}" \
169+
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
170+
"https://api.github.com/repos/${{ github.repository }}/issues/comments/$comment_id")
171+
else
172+
echo "Creating new comment"
173+
response=$(curl -s -X POST \
174+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN_AUTO_REVIEW }}" \
175+
-d "$(jq -n --arg body "$(cat review_data.md)" '{body: $body}')" \
176+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments")
177+
fi

MAINTAINERS

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# List of maintainers of the RT-Thread open-source community
2+
#
3+
# This file manages the maintainers and their associated sections in the repository.
4+
# Developers should update this file according to project needs.
5+
# The following are explanations of each field and guidelines for adding new maintainer entries.
6+
#
7+
# When adding new entries, please follow the format:
8+
#
9+
# 1. **tag** - Assign a unique tag to each entry for identifying the code module or functionality.
10+
# - The tag should be concise and descriptive, such as `workflow`, `libc`...
11+
# - **Rule for Adding**: Use a new tag when adding a new functionality or module to ensure it clearly describes the area of responsibility.
12+
#
13+
# 2. **path** - Specify the directory or file path that the maintainer is responsible for.
14+
# - The path must be relative to the repository's root directory and can refer to either a single file or a folder.
15+
# - If the maintainer is responsible for all files in a directory, use the directory path; if it's for a specific file, provide the full file path.
16+
# - **Rule for Adding**: Ensure that the path correctly points to the relevant code location. Please note that a tag should correspond to only one path. Currently, multiple paths are not supported.
17+
#
18+
# 3. **owners** - List the maintainers responsible for the section, including their GitHub usernames and contact information.
19+
# - The owners should be listed as a comma-separated list if there are multiple maintainers.
20+
# - Format: `Name(GitHub username)<email address>`.
21+
# - **Rule for Adding**: Ensure that the listed GitHub usernames are correct, and the maintainers are aware of their responsibilities and duties.
22+
#
23+
# Example: How to Add a Maintainer Entry
24+
#
25+
# The following is a template for adding new entries in the MAINTAINER file:
26+
#
27+
# tag: <module-name>
28+
# path: <file-or-directory-path>
29+
# owners: <maintainer1>, <maintainer2>, ...
30+
#
31+
# When adding entries, please follow these guidelines:
32+
# - Ensure the `tag` is unique and descriptive.
33+
# - Ensure the `path` points to the correct location in the repository.
34+
# - Ensure the `owners` are accurate and that all new maintainers are aware of their responsibilities.
35+
#
36+
# Example Entry:
37+
# tag: example-module
38+
# path: example/module/path
39+
# owners: John Doe(johndoe)<johndoe@example.com>, Jane Smith(janesmith)<janesmith@example.com>
40+
41+
# Note:
42+
# - Each entry includes a `tag` that identifies the module or functionality, a `path` that points to the relevant code location, and `owners` who are the maintainers for that part of the codebase.
43+
# - If there are multiple entries, each entry should be separated by a blank line. Within a single entry, there is no need to insert blank lines between the tag, path, and owners.
44+
45+
# Below are existing maintainer entries, divided by module:
46+
47+
tag: workflow
48+
path: .github
49+
owners: Li Tao(supperthomas)<78900636@qq.com>
50+
51+
tag: stm32f407-rt-spark
52+
path: bsp/stm32/stm32f407-rt-spark
53+
owners: Zhang Bingru(Rbb666)<751061401@qq.com>, Wang Yuqiang(kurisaW)<2053731441@qq.com>
54+
55+
tag: libc
56+
path: components/libc
57+
owners: Man Jiantin(mysterywolf)<920369182@qq.com>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy