Skip to main content

fallow_output/
pr_details.rs

1use serde::{Deserialize, Serialize};
2
3/// Schema discriminator serialized into [`PrDetailsArtifact::schema`].
4pub const PR_DETAILS_SCHEMA: &str = "fallow-pr-details/v1";
5
6/// Full-findings report artifact backing the PR summary comment's details
7/// link, grouped into per-area sections.
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub struct PrDetailsArtifact {
10    /// Schema discriminator; always [`PR_DETAILS_SCHEMA`].
11    pub schema: String,
12    /// Display title of the report.
13    pub title: String,
14    /// Per-area finding sections.
15    pub sections: Vec<PrDetailsSection>,
16}
17
18/// One findings section inside [`PrDetailsArtifact::sections`].
19#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
20pub struct PrDetailsSection {
21    /// Stable section identifier, e.g. `findings`.
22    pub id: String,
23    /// Display title of the section.
24    pub title: String,
25    /// Finding rows in the section.
26    pub rows: Vec<PrDetailsRow>,
27}
28
29/// One finding row inside [`PrDetailsSection::rows`].
30#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
31pub struct PrDetailsRow {
32    /// `path:line` location text.
33    pub location: String,
34    /// Rule identifier the finding belongs to.
35    pub rule: String,
36    /// Human-readable finding description.
37    pub description: String,
38    /// Suggested fix text, when one is known.
39    pub fix: Option<String>,
40    /// Stable finding fingerprint for cross-run tracking, when available.
41    pub fingerprint: Option<String>,
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn details_artifact_serializes_stable_schema() {
50        let artifact = PrDetailsArtifact {
51            schema: PR_DETAILS_SCHEMA.to_owned(),
52            title: "Fallow".to_owned(),
53            sections: vec![PrDetailsSection {
54                id: "findings".to_owned(),
55                title: "Findings".to_owned(),
56                rows: vec![PrDetailsRow {
57                    location: "src/app.ts:12".to_owned(),
58                    rule: "fallow/high-crap-score".to_owned(),
59                    description: "Function is hard to safely change.".to_owned(),
60                    fix: Some("Extract smaller units.".to_owned()),
61                    fingerprint: Some("abc123".to_owned()),
62                }],
63            }],
64        };
65
66        let json = serde_json::to_value(artifact).expect("serializes");
67
68        assert_eq!(json["schema"], PR_DETAILS_SCHEMA);
69        assert_eq!(json["sections"][0]["rows"][0]["location"], "src/app.ts:12");
70    }
71}