Skip to content

Commit 4c614f6

Browse files
matejclaude
andcommitted
Improve PR review summary with detailed breakdown
- Add category-based grouping of findings with descriptions - Show severity breakdown (HIGH/MEDIUM/LOW counts) - Provide clearer recommendations based on severity: - HIGH: "Action Required" - must fix before merge - MEDIUM: "Approved with Suggestions" - consider fixing - LOW only: "Approved" - minor suggestions - Use markdown formatting for better readability Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 681ae06 commit 4c614f6

2 files changed

Lines changed: 69 additions & 19 deletions

File tree

scripts/comment-pr-findings.bun.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ describe('comment-pr-findings.js', () => {
157157

158158
expect(reviewDataCaptured).toBeTruthy();
159159
expect(reviewDataCaptured.event).toBe('APPROVE');
160-
expect(reviewDataCaptured.body).toContain('Summary: No findings were reported.');
161-
expect(reviewDataCaptured.body).toContain('Assessment:');
160+
expect(reviewDataCaptured.body).toContain('No issues were identified');
161+
expect(reviewDataCaptured.body).toContain('Recommendation');
162162
});
163163

164164
test('should process findings correctly', async () => {
@@ -231,8 +231,8 @@ describe('comment-pr-findings.js', () => {
231231
expect(reviewDataCaptured).toBeTruthy();
232232
expect(reviewDataCaptured.comments).toHaveLength(1);
233233
expect(reviewDataCaptured.event).toBe('REQUEST_CHANGES');
234-
expect(reviewDataCaptured.body).toContain('Summary: 1 finding');
235-
expect(reviewDataCaptured.body).toContain('Assessment:');
234+
expect(reviewDataCaptured.body).toContain('Found **1 issue**');
235+
expect(reviewDataCaptured.body).toContain('Recommendation');
236236
});
237237

238238
test('should approve when findings are medium or low only', async () => {
@@ -299,8 +299,8 @@ describe('comment-pr-findings.js', () => {
299299

300300
expect(reviewDataCaptured).toBeTruthy();
301301
expect(reviewDataCaptured.event).toBe('APPROVE');
302-
expect(reviewDataCaptured.body).toContain('Summary: 2 findings');
303-
expect(reviewDataCaptured.body).toContain('HIGH: 0');
302+
expect(reviewDataCaptured.body).toContain('Found **2 issues**');
303+
expect(reviewDataCaptured.body).toContain('Approved with Suggestions');
304304
expect(reviewDataCaptured.comments).toHaveLength(2);
305305
});
306306

@@ -350,7 +350,7 @@ describe('comment-pr-findings.js', () => {
350350

351351
expect(reviewDataCaptured).toBeTruthy();
352352
expect(reviewDataCaptured.event).toBe('REQUEST_CHANGES');
353-
expect(reviewDataCaptured.body).toContain('Summary: 1 finding');
353+
expect(reviewDataCaptured.body).toContain('Found **1 issue**');
354354
expect(reviewDataCaptured.comments).toBeUndefined();
355355
});
356356
});

scripts/comment-pr-findings.js

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -126,34 +126,84 @@ async function run() {
126126
function buildReviewSummary(findings) {
127127
const total = findings.length;
128128
const files = new Set();
129+
const categories = {};
130+
129131
for (const finding of findings) {
130132
const file = finding.file || finding.path;
131133
if (file) {
132134
files.add(file);
133135
}
136+
// Group by category
137+
const category = finding.category || 'other';
138+
if (!categories[category]) {
139+
categories[category] = [];
140+
}
141+
categories[category].push(finding);
134142
}
135143

136144
const { high, medium, low } = countSeverities(findings);
137-
let summaryLine;
145+
146+
// Build the summary
147+
let summary = '## Code Review Summary\n\n';
138148

139149
if (total === 0) {
140-
summaryLine = 'Summary: No findings were reported.';
141-
} else {
142-
const fileCount = files.size;
143-
const fileText = fileCount > 0 ? ` across ${fileCount} file${fileCount === 1 ? '' : 's'}` : '';
144-
summaryLine = `Summary: ${total} finding${total === 1 ? '' : 's'}${fileText} (HIGH: ${high}, MEDIUM: ${medium}, LOW: ${low}).`;
150+
summary += 'No issues were identified in this review.\n\n';
151+
summary += '**Recommendation:** Approved - the changes look good.';
152+
return summary;
153+
}
154+
155+
// Overview line
156+
const fileCount = files.size;
157+
const fileText = fileCount > 0 ? ` across ${fileCount} file${fileCount === 1 ? '' : 's'}` : '';
158+
summary += `Found **${total} issue${total === 1 ? '' : 's'}**${fileText}.\n\n`;
159+
160+
// Severity breakdown
161+
summary += '### Severity Breakdown\n';
162+
if (high > 0) summary += `- **HIGH:** ${high}\n`;
163+
if (medium > 0) summary += `- **MEDIUM:** ${medium}\n`;
164+
if (low > 0) summary += `- **LOW:** ${low}\n`;
165+
summary += '\n';
166+
167+
// Category breakdown with descriptions
168+
const categoryDescriptions = {
169+
security: 'Security vulnerabilities that could be exploited',
170+
correctness: 'Logic errors or bugs that may cause incorrect behavior',
171+
performance: 'Inefficiencies that could impact performance',
172+
reliability: 'Issues that may cause crashes or failures',
173+
maintainability: 'Code quality issues affecting long-term maintenance',
174+
testing: 'Missing or inadequate test coverage',
175+
other: 'Other issues'
176+
};
177+
178+
summary += '### Issues by Category\n';
179+
for (const [category, categoryFindings] of Object.entries(categories)) {
180+
const catHigh = categoryFindings.filter(f => normalizeSeverity(f.severity) === 'HIGH').length;
181+
const catMedium = categoryFindings.filter(f => normalizeSeverity(f.severity) === 'MEDIUM').length;
182+
const catLow = categoryFindings.filter(f => normalizeSeverity(f.severity) === 'LOW' || !f.severity).length;
183+
184+
const severityParts = [];
185+
if (catHigh > 0) severityParts.push(`${catHigh} high`);
186+
if (catMedium > 0) severityParts.push(`${catMedium} medium`);
187+
if (catLow > 0) severityParts.push(`${catLow} low`);
188+
189+
const description = categoryDescriptions[category] || category;
190+
summary += `- **${category.charAt(0).toUpperCase() + category.slice(1)}** (${severityParts.join(', ')}): ${description}\n`;
145191
}
192+
summary += '\n';
146193

147-
let assessmentLine;
194+
// Recommendation
195+
summary += '### Recommendation\n';
148196
if (high > 0) {
149-
assessmentLine = 'Assessment: High-severity issues were found that should be addressed before merge.';
150-
} else if (total > 0) {
151-
assessmentLine = 'Assessment: Changes look acceptable overall; consider addressing the findings.';
197+
summary += `**Action Required:** ${high} high-severity issue${high === 1 ? '' : 's'} must be addressed before merging. `;
198+
summary += 'Please review the inline comments and apply the suggested fixes.\n';
199+
} else if (medium > 0) {
200+
summary += `**Approved with Suggestions:** No blocking issues found, but ${medium} medium-severity issue${medium === 1 ? '' : 's'} should be considered. `;
201+
summary += 'Review the inline comments for improvement opportunities.\n';
152202
} else {
153-
assessmentLine = 'Assessment: Changes look good; no high-severity issues detected.';
203+
summary += `**Approved:** Only minor issues found. Consider addressing the ${low} low-severity suggestion${low === 1 ? '' : 's'} when convenient.\n`;
154204
}
155205

156-
return `${summaryLine}\n${assessmentLine}`;
206+
return summary;
157207
}
158208

159209
const { high: highSeverityCount } = countSeverities(newFindings);

0 commit comments

Comments
 (0)