syncable_cli/analyzer/helmlint/formatter/
json.rs

1//! JSON formatter for helmlint results.
2//!
3//! Produces machine-readable JSON output.
4
5use crate::analyzer::helmlint::lint::LintResult;
6use serde::Serialize;
7
8/// JSON output structure for a lint failure.
9#[derive(Serialize)]
10struct JsonFailure {
11    code: String,
12    severity: String,
13    message: String,
14    file: String,
15    line: u32,
16    column: Option<u32>,
17    category: String,
18    fixable: bool,
19}
20
21/// JSON output structure for lint results.
22#[derive(Serialize)]
23struct JsonOutput {
24    chart_path: String,
25    files_checked: usize,
26    error_count: usize,
27    warning_count: usize,
28    failures: Vec<JsonFailure>,
29    parse_errors: Vec<String>,
30}
31
32/// Format a lint result as JSON.
33pub fn format(result: &LintResult) -> String {
34    let output = JsonOutput {
35        chart_path: result.chart_path.clone(),
36        files_checked: result.files_checked,
37        error_count: result.error_count,
38        warning_count: result.warning_count,
39        failures: result
40            .failures
41            .iter()
42            .map(|f| JsonFailure {
43                code: f.code.to_string(),
44                severity: format!("{:?}", f.severity).to_lowercase(),
45                message: f.message.clone(),
46                file: f.file.display().to_string(),
47                line: f.line,
48                column: f.column,
49                category: format!("{:?}", f.category),
50                fixable: f.fixable,
51            })
52            .collect(),
53        parse_errors: result.parse_errors.clone(),
54    };
55
56    serde_json::to_string_pretty(&output).unwrap_or_else(|_| "{}".to_string())
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::analyzer::helmlint::types::{CheckFailure, RuleCategory, Severity};
63
64    #[test]
65    fn test_json_format_empty() {
66        let result = LintResult::new("test-chart");
67        let json = format(&result);
68        assert!(json.contains("\"chart_path\": \"test-chart\""));
69        assert!(json.contains("\"failures\": []"));
70    }
71
72    #[test]
73    fn test_json_format_with_failures() {
74        let mut result = LintResult::new("test-chart");
75        result.failures.push(CheckFailure::new(
76            "HL1001",
77            Severity::Error,
78            "Missing Chart.yaml",
79            ".",
80            1,
81            RuleCategory::Structure,
82        ));
83        result.error_count = 1;
84
85        let json = format(&result);
86        assert!(json.contains("\"code\": \"HL1001\""));
87        assert!(json.contains("\"severity\": \"error\""));
88    }
89}