Skip to main content

autom8/output/
pr_review.rs

1//! PR review workflow output.
2//!
3//! Output functions for the PR review analysis and fix workflow.
4
5use super::colors::*;
6
7/// Print a message when no unresolved comments are found on a PR.
8pub fn print_no_unresolved_comments(pr_number: u32, title: &str) {
9    println!();
10    println!(
11        "{GREEN}PR #{}{RESET} has no unresolved comments.",
12        pr_number
13    );
14    println!("{BLUE}Title:{RESET} {}", title);
15    println!();
16    println!("{GRAY}Nothing to review - all feedback has been addressed!{RESET}");
17}
18
19/// Print a summary of the PR context being analyzed.
20pub fn print_pr_context_summary(pr_number: u32, title: &str, comment_count: usize) {
21    println!();
22    println!("{CYAN}Analyzing PR #{}{RESET}: {}", pr_number, title);
23    println!(
24        "{BLUE}Found:{RESET} {} unresolved comment{}",
25        comment_count,
26        if comment_count == 1 { "" } else { "s" }
27    );
28    println!();
29}
30
31/// Print a single PR comment with its context.
32pub fn print_pr_comment(
33    index: usize,
34    author: &str,
35    body: &str,
36    file_path: Option<&str>,
37    line: Option<u32>,
38) {
39    println!("{GRAY}{}{RESET}", "-".repeat(57));
40    println!(
41        "{YELLOW}Comment {}{RESET} by {CYAN}{}{RESET}",
42        index + 1,
43        author
44    );
45
46    if let Some(path) = file_path {
47        if let Some(line_num) = line {
48            println!("{BLUE}Location:{RESET} {}:{}", path, line_num);
49        } else {
50            println!("{BLUE}Location:{RESET} {}", path);
51        }
52    }
53
54    println!();
55    for line in body.lines() {
56        println!("  {}", line);
57    }
58    println!();
59}
60
61/// Print the list of all unresolved comments for a PR.
62pub fn print_pr_comments_list(comments: &[crate::gh::PRComment]) {
63    println!("{BOLD}Unresolved Comments:{RESET}");
64    println!();
65
66    for (i, comment) in comments.iter().enumerate() {
67        print_pr_comment(
68            i,
69            &comment.author,
70            &comment.body,
71            comment.file_path.as_deref(),
72            comment.line,
73        );
74    }
75
76    println!("{GRAY}{}{RESET}", "-".repeat(57));
77}
78
79/// Print an error message for PR context gathering failures.
80pub fn print_pr_context_error(message: &str) {
81    println!();
82    println!("{RED}{BOLD}Failed to gather PR context:{RESET}");
83    println!("{RED}  {}{RESET}", message);
84    println!();
85}
86
87/// Print a header when starting PR review analysis.
88pub fn print_pr_review_start(pr_number: u32, title: &str, comment_count: usize) {
89    println!();
90    println!("{CYAN}{BOLD}╔════════════════════════════════════════════════════════╗{RESET}");
91    println!("{CYAN}{BOLD}║  PR Review Analysis                                    ║{RESET}");
92    println!("{CYAN}{BOLD}╚════════════════════════════════════════════════════════╝{RESET}");
93    println!();
94    println!("{BLUE}PR #{}{RESET}: {}", pr_number, title);
95    println!("{BLUE}Comments to analyze:{RESET} {}", comment_count);
96    println!();
97}
98
99/// Print status when spawning the Claude agent for PR review.
100pub fn print_pr_review_spawning() {
101    println!("{GRAY}Spawning Claude agent for PR review...{RESET}");
102    println!();
103}
104
105/// Print the PR review summary results.
106pub fn print_pr_review_summary(summary: &crate::claude::PRReviewSummary) {
107    println!();
108    println!("{GRAY}{}{RESET}", "─".repeat(57));
109    println!();
110    println!("{BOLD}PR Review Summary{RESET}");
111    println!();
112
113    println!(
114        "  {BLUE}Total comments analyzed:{RESET}    {}",
115        summary.total_comments
116    );
117    println!(
118        "  {GREEN}Real issues fixed:{RESET}         {}",
119        summary.real_issues_fixed
120    );
121    println!(
122        "  {YELLOW}Red herrings identified:{RESET}   {}",
123        summary.red_herrings
124    );
125    println!(
126        "  {GRAY}Legitimate suggestions:{RESET}    {}",
127        summary.legitimate_suggestions
128    );
129    println!();
130}
131
132/// Print a success message when PR review completes with fixes made.
133pub fn print_pr_review_complete_with_fixes(fixes_count: usize) {
134    println!();
135    println!("{GREEN}{BOLD}╔════════════════════════════════════════════════════════╗{RESET}");
136    println!("{GREEN}{BOLD}║  ✓ PR Review Complete                                  ║{RESET}");
137    println!("{GREEN}{BOLD}╚════════════════════════════════════════════════════════╝{RESET}");
138    println!();
139    println!(
140        "{GREEN}Fixed {} issue{}.{RESET}",
141        fixes_count,
142        if fixes_count == 1 { "" } else { "s" }
143    );
144    println!();
145}
146
147/// Print a message when PR review completes but no fixes were needed.
148pub fn print_pr_review_no_fixes_needed() {
149    println!();
150    println!("{CYAN}{BOLD}╔════════════════════════════════════════════════════════╗{RESET}");
151    println!("{CYAN}{BOLD}║  ✓ PR Review Complete - No Fixes Needed                ║{RESET}");
152    println!("{CYAN}{BOLD}╚════════════════════════════════════════════════════════╝{RESET}");
153    println!();
154    println!("{GRAY}All comments were either red herrings or suggestions.{RESET}");
155    println!("{GRAY}No code changes were required.{RESET}");
156    println!();
157}
158
159/// Print an error message when PR review fails.
160pub fn print_pr_review_error(message: &str) {
161    println!();
162    println!("{RED}{BOLD}╔════════════════════════════════════════════════════════╗{RESET}");
163    println!("{RED}{BOLD}║  ✗ PR Review Failed                                    ║{RESET}");
164    println!("{RED}{BOLD}╚════════════════════════════════════════════════════════╝{RESET}");
165    println!();
166    println!("{RED}Error:{RESET} {}", message);
167    println!();
168}
169
170/// Print a message when starting to stream Claude output for PR review.
171pub fn print_pr_review_streaming() {
172    println!("{GRAY}{}{RESET}", "─".repeat(57));
173    println!("{CYAN}Claude Analysis:{RESET}");
174    println!("{GRAY}{}{RESET}", "─".repeat(57));
175    println!();
176}
177
178/// Print a footer after streaming Claude output for PR review.
179pub fn print_pr_review_streaming_done() {
180    println!();
181    println!("{GRAY}{}{RESET}", "─".repeat(57));
182}
183
184/// Print a message when commit is skipped due to config.
185pub fn print_pr_commit_skipped_config() {
186    println!("{GRAY}Commit skipped (commit disabled in config){RESET}");
187}
188
189/// Print a message when push is skipped due to config.
190pub fn print_pr_push_skipped_config() {
191    println!("{GRAY}Push skipped (push disabled in config){RESET}");
192}
193
194/// Print a message when no fixes were made so no commit is needed.
195pub fn print_pr_no_commit_no_fixes() {
196    println!("{GRAY}No commit created (no fixes were made){RESET}");
197}
198
199/// Print a success message when PR review commit is created.
200pub fn print_pr_commit_success(commit_hash: &str) {
201    println!(
202        "{GREEN}Created commit {}{RESET} with PR review fixes",
203        commit_hash
204    );
205}
206
207/// Print an error message when PR review commit fails.
208pub fn print_pr_commit_error(message: &str) {
209    println!("{RED}Failed to create commit:{RESET} {}", message);
210}
211
212/// Print a success message when PR review push succeeds.
213pub fn print_pr_push_success(branch: &str) {
214    println!("{GREEN}Pushed{RESET} fixes to {CYAN}{}{RESET}", branch);
215}
216
217/// Print an error message when PR review push fails.
218pub fn print_pr_push_error(message: &str) {
219    println!("{RED}Failed to push:{RESET} {}", message);
220}
221
222/// Print a message when push reports already up-to-date.
223pub fn print_pr_push_up_to_date() {
224    println!("{GRAY}Branch already up-to-date on remote{RESET}");
225}
226
227/// Print a summary of what was done based on config.
228pub fn print_pr_review_actions_summary(
229    commit_enabled: bool,
230    push_enabled: bool,
231    commit_made: bool,
232    push_made: bool,
233    no_fixes_needed: bool,
234) {
235    println!();
236    println!("{BOLD}Actions:{RESET}");
237
238    if no_fixes_needed {
239        println!("  {GRAY}• No fixes needed - no commit created{RESET}");
240        return;
241    }
242
243    if !commit_enabled {
244        println!("  {GRAY}• Commit: disabled in config{RESET}");
245    } else if commit_made {
246        println!("  {GREEN}• Commit: created{RESET}");
247    } else {
248        println!("  {GRAY}• Commit: no changes to commit{RESET}");
249    }
250
251    if !push_enabled {
252        println!("  {GRAY}• Push: disabled in config{RESET}");
253    } else if !commit_made {
254        println!("  {GRAY}• Push: skipped (no commit){RESET}");
255    } else if push_made {
256        println!("  {GREEN}• Push: completed{RESET}");
257    } else {
258        println!("  {GRAY}• Push: already up-to-date{RESET}");
259    }
260
261    println!();
262}