Skip to content

Commit 1bab662

Browse files
committed
[action/ci] show the PR status for Pull request
1 parent 7598581 commit 1bab662

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#
2+
# Copyright (c) 2006-2023, RT-Thread Development Team
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Change Logs:
7+
# Date Author Notes
8+
# 2025-05-15 Supper Thomas show the PR size
9+
#
10+
11+
name: PR status
12+
13+
# 这个ci主要用来显示当前的PR对于master节点上的增加的code size有多大
14+
on:
15+
pull_request:
16+
branches:
17+
- master
18+
19+
permissions:
20+
contents: read # to fetch code (actions/checkout)
21+
22+
jobs:
23+
build:
24+
runs-on: ubuntu-24.04
25+
name: PR status show
26+
27+
steps:
28+
- uses: actions/checkout@main
29+
- name: Set up Python
30+
uses: actions/setup-python@main
31+
with:
32+
python-version: 3.8
33+
34+
- name: fetch origin
35+
shell: bash
36+
run: |
37+
git config --global http.postBuffer 524288000
38+
git remote -v
39+
git fetch origin
40+
git rebase origin/master
41+
42+
- name: PR status show
43+
if: ${{ success() }}
44+
shell: bash
45+
run: |
46+
python git_diff_status_show.py origin/master

tools/ci/git_diff_status_show.py

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#
2+
# Copyright (c) 2025, RT-Thread Development Team
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Change Logs:
7+
# Date Author Notes
8+
# 2025-05-15 supperthomas add PR status show
9+
#
10+
#!/usr/bin/env python3
11+
import subprocess
12+
import sys
13+
import os
14+
import re
15+
import argparse
16+
import locale
17+
from typing import List, Dict
18+
19+
class FileDiff:
20+
def __init__(self, path: str, status: str, size_change: int = 0, old_size: int = 0, new_size: int = 0):
21+
self.path = path
22+
self.status = status # A (added), M (modified), D (deleted), R (renamed)
23+
self.size_change = size_change
24+
self.old_size = old_size
25+
self.new_size = new_size
26+
27+
def __str__(self):
28+
if self.status == 'A':
29+
return f"Added {self.path}: {self.size_change} bytes"
30+
elif self.status == 'D':
31+
return f"Deleted {self.path}: was {self.old_size} bytes"
32+
elif self.status == 'M' or self.status == 'R':
33+
return f"Modified {self.path}: {self.size_change} bytes change"
34+
else:
35+
return f"{self.status} {self.path}"
36+
37+
class GitDiffAnalyzer:
38+
def __init__(self, target_branch: str):
39+
self.target_branch = target_branch
40+
self.encoding = locale.getpreferredencoding()
41+
42+
def get_diff_files(self) -> List[FileDiff]:
43+
"""获取当前分支与目标分支之间的差异文件"""
44+
# 获取差异文件列表
45+
diff_cmd = f"git diff --name-status {self.target_branch}"
46+
print(diff_cmd)
47+
try:
48+
output = subprocess.check_output(diff_cmd.split(), stderr=subprocess.STDOUT)
49+
output = output.decode(self.encoding).strip()
50+
print(output)
51+
except subprocess.CalledProcessError as e:
52+
print(f"Error executing git diff: {e.output.decode(self.encoding)}")
53+
sys.exit(1)
54+
55+
if not output:
56+
print("No differences between current branch and target branch")
57+
sys.exit(0)
58+
59+
# 处理可能的换行符问题
60+
output = output.replace('\r\n', '\n')
61+
lines = output.split('\n')
62+
63+
file_diffs = []
64+
for line in lines:
65+
line = line.strip()
66+
if not line:
67+
continue
68+
69+
parts = line.split('\t')
70+
if len(parts) < 2:
71+
# 可能是重命名文件,格式为 "RXXX\told_path\tnew_path"
72+
match = re.match(r'R(\d+)\t(.+)\t(.+)', line)
73+
if match:
74+
status = 'R'
75+
old_path = match.group(2)
76+
new_path = match.group(3)
77+
# 计算重命名文件的修改大小
78+
old_size = self.get_file_size(old_path, self.target_branch)
79+
new_size = self.get_file_size(new_path, 'HEAD')
80+
size_change = new_size - old_size if old_size > 0 else new_size
81+
file_diffs.append(FileDiff(new_path, status, size_change, old_size, new_size))
82+
else:
83+
status = parts[0][0] # 取状态码的第一个字符
84+
path = parts[1]
85+
86+
if status == 'A':
87+
# 新增文件,计算大小
88+
size = self.get_file_size(path, 'HEAD')
89+
file_diffs.append(FileDiff(path, status, size, 0, size))
90+
elif status == 'D':
91+
# 删除文件,计算原大小
92+
size = self.get_file_size(path, self.target_branch)
93+
file_diffs.append(FileDiff(path, status, 0, size, 0))
94+
elif status == 'M':
95+
# 修改文件,计算大小变化
96+
old_size = self.get_file_size(path, self.target_branch)
97+
new_size = self.get_file_size(path, 'HEAD')
98+
size_change = new_size - old_size
99+
file_diffs.append(FileDiff(path, status, size_change, old_size, new_size))
100+
101+
return file_diffs
102+
103+
def get_file_size(self, path: str, ref: str) -> int:
104+
"""获取指定分支上文件的大小"""
105+
try:
106+
# 使用 git cat-file 来获取文件内容,然后计算其大小
107+
cmd = f"git cat-file blob {ref}:{path}"
108+
output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
109+
return len(output)
110+
except subprocess.CalledProcessError:
111+
# 如果文件不存在或无法获取,返回0
112+
return 0
113+
114+
def format_size(size: int) -> str:
115+
"""将字节大小转换为人类可读的格式"""
116+
if size < 1024:
117+
return f"{size} bytes"
118+
elif size < 1024 * 1024:
119+
return f"{size / 1024:.1f} KB"
120+
elif size < 1024 * 1024 * 1024:
121+
return f"{size / (1024 * 1024):.1f} MB"
122+
else:
123+
return f"{size / (1024 * 1024 * 1024):.1f} GB"
124+
125+
def main():
126+
parser = argparse.ArgumentParser(description='Compare current branch with target branch and show file differences.')
127+
parser.add_argument('target_branch', help='Target branch to compare against (e.g., master)')
128+
args = parser.parse_args()
129+
130+
analyzer = GitDiffAnalyzer(args.target_branch)
131+
file_diffs = analyzer.get_diff_files()
132+
133+
# 生成报告
134+
generate_report(file_diffs, args.target_branch)
135+
136+
def generate_report(file_diffs: List[FileDiff], target_branch: str):
137+
"""生成差异报告"""
138+
print(f"\n=== Comparison between {target_branch} and current branch ===\n")
139+
140+
# 分类统计
141+
added_files = [f for f in file_diffs if f.status == 'A']
142+
removed_files = [f for f in file_diffs if f.status == 'D']
143+
modified_files = [f for f in file_diffs if f.status == 'M']
144+
renamed_files = [f for f in file_diffs if f.status == 'R']
145+
146+
# 计算总变化量
147+
total_added = sum(f.size_change for f in added_files)
148+
total_removed = sum(f.old_size for f in removed_files)
149+
total_modified = sum(abs(f.size_change) for f in modified_files)
150+
# 计算总的大小变化
151+
total_size_change = sum(f.size_change for f in file_diffs)
152+
153+
print(f"Total changes: {len(file_diffs)} files")
154+
print(f"Added: {len(added_files)} files ({format_size(total_added)})")
155+
print(f"Removed: {len(removed_files)} files ({format_size(total_removed)})")
156+
print(f"Modified: {len(modified_files)} files ({format_size(total_modified)})")
157+
print(f"Renamed: {len(renamed_files)} files")
158+
print(f"\nTotal size change: {format_size(total_size_change)}")
159+
print("\n" + "="*60 + "\n")
160+
161+
# 显示详细差异
162+
for diff in file_diffs:
163+
print(diff)
164+
165+
# 详细展示修改和新增的文件大小
166+
if diff.status == 'A':
167+
print(f" Size: {format_size(diff.new_size)}")
168+
elif diff.status == 'M':
169+
print(f" Original size: {format_size(diff.old_size)}")
170+
print(f" New size: {format_size(diff.new_size)}")
171+
print(f" Size change: {format_size(abs(diff.size_change))}")
172+
elif diff.status == 'R':
173+
print(f" Original size: {format_size(diff.old_size)}")
174+
print(f" New size: {format_size(diff.new_size)}")
175+
print(f" Size change: {format_size(abs(diff.size_change))}")
176+
elif diff.status == 'D':
177+
print(f" Original size: {format_size(diff.old_size)}")
178+
179+
print("-" * 50)
180+
181+
if __name__ == "__main__":
182+
main()

0 commit comments

Comments
 (0)