arduino_report_size_deltas/summarize/
mod.rs

1//! A module to define functions that generate a markdown comment.
2mod helpers;
3use std::{fs, path::Path};
4mod structs;
5use crate::{CommentAssemblyError, reports::parse_json};
6pub use helpers::COMMENT_MARKER;
7use helpers::{generate_detailed_table, generate_general_table};
8
9/// Generate the comment to be posted for a PR.
10///
11/// The given `sketches_path` shall point to the directory containing JSON files.
12/// The comment is generated from the parsed JSON data.
13///
14/// When successful, this returns a [`String`] in markdown syntax.
15pub fn generate_comment<P: AsRef<Path>>(sketches_path: P) -> Result<String, CommentAssemblyError> {
16    let mut reports = vec![];
17    for entry in fs::read_dir(&sketches_path)? {
18        let path = entry?.path();
19        if path
20            .extension()
21            .is_some_and(|ext| ext.to_string_lossy() == "json")
22        {
23            let report = parse_json(&path)?;
24            if report.is_valid() {
25                reports.push(report);
26            } else {
27                log::warn!("Skipping {path:?} since it does not contain sufficient information.");
28            }
29        } else {
30            log::debug!("Ignoring non-JSON file: {}", path.to_string_lossy());
31        }
32    }
33    if reports.is_empty() {
34        log::error!(
35            "No delta size data found in the PR's artifacts (in path {}). \
36            Ensure the `enable-size-deltas-report` input for `arduino/compile-sketches` action is enabled.",
37            sketches_path.as_ref().to_string_lossy()
38        );
39        return Err(CommentAssemblyError::NotFound);
40    }
41    reports.sort_by_key(|k| k.boards[0].board.clone());
42
43    let mut comment = String::from(COMMENT_MARKER);
44    comment.push_str(format!("### Memory usage change @ {}\n\n", reports[0].commit_hash).as_str());
45
46    generate_general_table(&reports, &mut comment);
47    generate_detailed_table(&reports, &mut comment);
48
49    Ok(comment)
50}
51
52#[cfg(test)]
53mod test {
54    use super::{CommentAssemblyError, generate_comment};
55    use std::fs;
56
57    #[test]
58    fn use_new_test_assets() {
59        let comment = generate_comment("tests/size-deltas-reports-new").unwrap();
60        fs::write("tests/size-deltas-reports-new/out.md", comment).unwrap();
61    }
62
63    #[test]
64    fn use_old_test_assets() {
65        assert!(matches!(
66            generate_comment("tests/size-deltas-reports-old"),
67            Err(CommentAssemblyError::NotFound)
68        ));
69    }
70
71    #[test]
72    fn use_actual_assets() {
73        let comment = generate_comment("tests/test_assets").unwrap();
74        fs::write("tests/test_assets/out.md", comment).unwrap();
75    }
76}