Skip to content

Commit 4a52234

Browse files
authored
Introduce comment-to-code ratio check (#765)
1 parent e2f269c commit 4a52234

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

.github/workflows/c2c-ratio-pr.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Comment-to-code (C2C) ratio
2+
3+
on:
4+
pull_request:
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
8+
cancel-in-progress: >-
9+
${{ github.ref != 'refs/heads/master' &&
10+
github.event_name != 'merge_group' &&
11+
!startsWith(github.ref, 'refs/heads/gh-readonly-queue') }}
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
comment-to-code-ratio:
18+
runs-on: ubuntu-24.04
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v6
22+
with:
23+
fetch-depth: 0
24+
25+
- name: Install cloc
26+
run: npm install --global cloc
27+
28+
- name: Generate report
29+
continue-on-error: true
30+
uses: deep5050/comment-to-code-ratio-action@v1.0.1
31+
with:
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
issue_number: ${{ github.event.pull_request.number }}
34+
options: >-
35+
--quiet
36+
--git
37+
--diff
38+
${{ github.event.pull_request.base.sha }}
39+
${{ github.event.pull_request.head.sha }}
40+
--md
41+
--out=report.md
42+
--exclude-dir=.git,3rdparty,build
43+
44+
- name: Check ratio
45+
id: ratio
46+
run: python3 scripts/check_comment_to_code_ratio.py report.md --limit 10
47+
48+
- name: Print final percentage
49+
if: always()
50+
run: |
51+
echo "Comment percentage for PR changes: ${{ steps.ratio.outputs.comment_percentage || 'N/A' }}%"
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import argparse
2+
import os
3+
import sys
4+
from pathlib import Path
5+
6+
EXPECTED_HEADER_SUFFIX = [
7+
"== files",
8+
"!= files",
9+
"+ files",
10+
"- files",
11+
"== blank",
12+
"!= blank",
13+
"+ blank",
14+
"- blank",
15+
"== comment",
16+
"!= comment",
17+
"+ comment",
18+
"- comment",
19+
"== code",
20+
"!= code",
21+
"+ code",
22+
"- code",
23+
]
24+
# Zero-based indices in `cloc --diff --md` rows after splitting by `|`.
25+
COMMENT_COLUMN_INDICES = (10, 11, 12)
26+
CODE_COLUMN_INDICES = (14, 15, 16)
27+
28+
29+
def parse_changed_totals(report_path):
30+
changed_comments = 0
31+
changed_code = 0
32+
header_found = False
33+
34+
for raw_line in report_path.read_text(encoding="utf-8").splitlines():
35+
if "|" not in raw_line:
36+
continue
37+
38+
cells = [cell.strip() for cell in raw_line.split("|")]
39+
if cells and cells[-1] == "":
40+
cells = cells[:-1]
41+
42+
if cells and cells[0] in {"Language", "File"}:
43+
if cells[1:] != EXPECTED_HEADER_SUFFIX:
44+
sys.exit("Unexpected cloc diff table format.")
45+
header_found = True
46+
continue
47+
48+
if not cells:
49+
continue
50+
if cells[0].startswith((":", "-", "SUM:")):
51+
continue
52+
if not header_found:
53+
continue
54+
55+
try:
56+
changed_comments += sum(
57+
int(cells[index]) for index in COMMENT_COLUMN_INDICES
58+
)
59+
changed_code += sum(int(cells[index]) for index in CODE_COLUMN_INDICES)
60+
except (IndexError, ValueError):
61+
continue
62+
63+
if not header_found:
64+
print("Unable to find cloc diff table header in report.")
65+
sys.exit(1)
66+
67+
return changed_comments, changed_code
68+
69+
70+
def main():
71+
parser = argparse.ArgumentParser()
72+
parser.add_argument("report")
73+
parser.add_argument("--limit", type=float, default=10.0)
74+
args = parser.parse_args()
75+
76+
report_path = Path(args.report)
77+
if not report_path.exists():
78+
print(f"{report_path} was not generated by the comment ratio action.")
79+
sys.exit(1)
80+
81+
changed_comments, changed_code = parse_changed_totals(report_path)
82+
total_changed_nonblank = changed_comments + changed_code
83+
comment_percentage = (
84+
0.0
85+
if total_changed_nonblank == 0
86+
else changed_comments * 100.0 / total_changed_nonblank
87+
)
88+
89+
print(f"Comment percentage for PR changes: {comment_percentage:.2f}%")
90+
91+
github_output = os.getenv("GITHUB_OUTPUT")
92+
if github_output:
93+
with Path(github_output).open("a", encoding="utf-8") as output:
94+
output.write(f"changed_comments={changed_comments}\n")
95+
output.write(f"changed_code={changed_code}\n")
96+
output.write(f"comment_percentage={comment_percentage:.2f}\n")
97+
98+
if comment_percentage > args.limit:
99+
print(
100+
f"Comment percentage for PR changes is {comment_percentage:.2f}%, "
101+
f"which exceeds {args.limit:.2f}%.",
102+
file=sys.stderr,
103+
)
104+
sys.exit(1)
105+
106+
107+
if __name__ == "__main__":
108+
main()

0 commit comments

Comments
 (0)