use crate::analyzer::helmlint::lint::LintResult;
use crate::analyzer::helmlint::types::Severity;
pub fn format(result: &LintResult) -> String {
let mut output = String::new();
for error in &result.parse_errors {
output.push_str(&format!(
"::error file={},title=Parse Error::{}\n",
result.chart_path, error
));
}
for failure in &result.failures {
let level = match failure.severity {
Severity::Error => "error",
Severity::Warning => "warning",
Severity::Info => "notice",
Severity::Style => "notice",
Severity::Ignore => continue, };
let file = failure.file.display().to_string();
let line = failure.line;
let title = &failure.code;
let message = escape_message(&failure.message);
let annotation = match failure.column {
Some(col) => format!(
"::{}file={},line={},col={},title={}::{}\n",
level, file, line, col, title, message
),
None => format!(
"::{}file={},line={},title={}::{}\n",
level, file, line, title, message
),
};
output.push_str(&annotation);
}
if !result.failures.is_empty() || !result.parse_errors.is_empty() {
let total = result.failures.len() + result.parse_errors.len();
let summary = format!(
"Helmlint found {} {} ({} errors, {} warnings)",
total,
if total == 1 { "issue" } else { "issues" },
result.error_count + result.parse_errors.len(),
result.warning_count
);
if result.error_count > 0 || !result.parse_errors.is_empty() {
output.push_str(&format!("::error::{}\n", summary));
} else {
output.push_str(&format!("::warning::{}\n", summary));
}
}
output
}
fn escape_message(message: &str) -> String {
message
.replace('%', "%25")
.replace('\r', "%0D")
.replace('\n', "%0A")
.replace(':', "%3A")
.replace(',', "%2C")
}
#[cfg(test)]
mod tests {
use super::*;
use crate::analyzer::helmlint::types::{CheckFailure, RuleCategory, Severity};
#[test]
fn test_github_format_empty() {
let result = LintResult::new("test-chart");
let output = format(&result);
assert!(output.is_empty());
}
#[test]
fn test_github_format_error() {
let mut result = LintResult::new("test-chart");
result.failures.push(CheckFailure::new(
"HL1001",
Severity::Error,
"Missing Chart.yaml",
"Chart.yaml",
1,
RuleCategory::Structure,
));
result.error_count = 1;
let output = format(&result);
assert!(output.contains("::error"));
assert!(output.contains("file=Chart.yaml"));
assert!(output.contains("line=1"));
assert!(output.contains("title=HL1001"));
}
#[test]
fn test_github_format_warning() {
let mut result = LintResult::new("test-chart");
result.failures.push(CheckFailure::new(
"HL1006",
Severity::Warning,
"Missing description",
"Chart.yaml",
5,
RuleCategory::Structure,
));
result.warning_count = 1;
let output = format(&result);
assert!(output.contains("::warning"));
}
#[test]
fn test_escape_message() {
assert_eq!(escape_message("hello:world"), "hello%3Aworld");
assert_eq!(escape_message("a,b"), "a%2Cb");
assert_eq!(escape_message("line1\nline2"), "line1%0Aline2");
}
}