Improve GitHub PR comment formatting

This commit is contained in:
Luke Street
2025-04-20 16:17:13 -06:00
parent 0812b87b3b
commit 64413671e9
+104 -13
View File
@@ -1,4 +1,4 @@
use std::{cmp::Ordering, fmt::Display};
use std::{cmp::Ordering, fmt::Display, mem::take};
use anyhow::{Context, Result};
use axum::{
@@ -469,6 +469,46 @@ fn process_new_items(items: &[ReportItem]) -> Vec<ChangeItem> {
.collect()
}
fn measure_line_matched(
name: &str,
from: u64,
from_percent: f32,
to: u64,
to_percent: f32,
) -> String {
let emoji = if to > from { "📈" } else { "📉" };
let percent_diff = to_percent - from_percent;
let percent_str = if percent_diff < 0.0 {
format!("{percent_diff:.2}%")
} else {
format!("+{percent_diff:.2}%")
};
let bytes_diff = to as i64 - from as i64;
let bytes_str = match bytes_diff.cmp(&0) {
Ordering::Less => bytes_diff.to_string(),
Ordering::Equal | Ordering::Greater => format!("+{bytes_diff}"),
};
format!("{emoji} **{name}**: {to_percent:.2}% ({percent_str}, {bytes_str} bytes)\n")
}
fn measure_line_bytes(name: &str, from: u64, to: u64) -> String {
let diff = to as i64 - from as i64;
let diff_str = match diff.cmp(&0) {
Ordering::Less => diff.to_string(),
Ordering::Equal | Ordering::Greater => format!("+{diff}"),
};
format!("**{name}**: {to} bytes ({diff_str} bytes)\n")
}
fn measure_line_simple(name: &str, from: u64, to: u64) -> String {
let diff = to as i64 - from as i64;
let diff_str = match diff.cmp(&0) {
Ordering::Less => diff.to_string(),
Ordering::Equal | Ordering::Greater => format!("+{diff}"),
};
format!("**{name}**: {to} ({diff_str})\n")
}
fn generate_comment(
from: &FullReportFile,
to: &ProcessArtifactResult,
@@ -476,15 +516,60 @@ fn generate_comment(
changes: Changes,
) -> String {
let mut comment = format!(
"## Report for {} ({} - {})\n\n",
"### Report for {} ({} - {})\n\n",
to.version,
&from.commit.sha[..7],
&to_commit.sha[..7]
);
comment.push_str("### Changes\n");
for unit in changes.units {
for function in unit.functions {
let (from, to) = match (function.from, function.to) {
let mut measure_written = false;
let from_measures = from.report.measures;
let to_measures = to.report.measures.unwrap_or_default();
if from_measures.total_code != to_measures.total_code {
comment.push_str(&measure_line_bytes(
"Total code",
from_measures.total_code,
to_measures.total_code,
));
measure_written = true;
}
if from_measures.total_functions != to_measures.total_functions {
comment.push_str(&measure_line_simple(
"Total functions",
from_measures.total_functions as u64,
to_measures.total_functions as u64,
));
measure_written = true;
}
if from_measures.matched_code != to_measures.matched_code {
comment.push_str(&measure_line_matched(
"Matched code",
from_measures.matched_code,
from_measures.matched_code_percent,
to_measures.matched_code,
to_measures.matched_code_percent,
));
measure_written = true;
}
if from_measures.complete_code != to_measures.complete_code {
comment.push_str(&measure_line_matched(
"Linked code",
from_measures.complete_code,
from_measures.complete_code_percent,
to_measures.complete_code,
to_measures.complete_code_percent,
));
measure_written = true;
}
if measure_written {
comment.push('\n');
}
let mut total_changes = 0;
let mut iter = changes.units.into_iter().flat_map(|mut unit| {
let functions = take(&mut unit.functions);
functions.into_iter().map(move |f| (unit.clone(), f))
});
for (unit, item) in iter.by_ref() {
let (from, to) = match (item.from, item.to) {
(Some(from), Some(to)) => (from, to),
(None, Some(to)) => (ChangeItemInfo::default(), to),
(Some(from), None) => (from, ChangeItemInfo::default()),
@@ -505,17 +590,23 @@ fn generate_comment(
Ordering::Equal => "0".to_string(),
Ordering::Greater => format!("+{}", bytes_diff),
};
let name = function
.metadata
.as_ref()
.and_then(|m| m.demangled_name.as_deref())
.unwrap_or(&function.name);
let name =
item.metadata.as_ref().and_then(|m| m.demangled_name.as_deref()).unwrap_or(&item.name);
comment.push_str(&format!(
"- {} `{} | {}` {} bytes -> {:.2}%\n",
emoji, unit.name, name, bytes_str, to.fuzzy_match_percent
"{emoji} `{} | {}` {} bytes -> {:.2}%\n",
unit.name, name, bytes_str, to.fuzzy_match_percent
));
total_changes += 1;
if total_changes >= 30 {
break;
}
}
let remaining = iter.count();
if remaining > 0 {
comment.push_str(&format!("...and {} more items\n", remaining));
} else if total_changes == 0 {
comment.push_str("No changes\n");
}
comment
}