use crate::model::{CheckStatus, EvaluationReceipt};
use anyhow::Result;
use clap::ValueEnum;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
Text,
Json,
Markdown,
}
pub fn render_receipt(receipt: &EvaluationReceipt, format: OutputFormat) -> Result<String> {
match format {
OutputFormat::Text => Ok(render_text(receipt)),
OutputFormat::Json => Ok(format!("{}\n", serde_json::to_string_pretty(receipt)?)),
OutputFormat::Markdown => Ok(render_markdown(receipt)),
}
}
fn render_text(receipt: &EvaluationReceipt) -> String {
let mut out = String::new();
out.push_str("gha-expression-proof receipt\n");
out.push_str(&format!("mode: {}\n", receipt.mode));
if let Some(expression) = &receipt.expression {
out.push_str(&format!("expression: {expression}\n"));
}
if let Some(result) = &receipt.result_string {
out.push_str(&format!("result: {result}\n"));
}
if let Some(rendered) = &receipt.rendered {
out.push_str(&format!("rendered: {rendered}\n"));
}
out.push_str(&format!(
"summary: {} passed, {} warnings, {} failed, {} skipped\n",
receipt.summary.passed,
receipt.summary.warnings,
receipt.summary.failed,
receipt.summary.skipped
));
out.push_str("\nchecks:\n");
for check in &receipt.checks {
out.push_str(&format!(
"[{}] {} - {}\n",
check.status.as_str(),
check.id,
check.message
));
}
out
}
fn render_markdown(receipt: &EvaluationReceipt) -> String {
let mut out = String::new();
out.push_str("# gha-expression-proof Receipt\n\n");
out.push_str(&format!("- Mode: `{}`\n", receipt.mode));
if let Some(expression) = &receipt.expression {
out.push_str(&format!("- Expression: `{}`\n", escape_pipe(expression)));
}
if let Some(result) = &receipt.result_string {
out.push_str(&format!("- Result: `{}`\n", escape_pipe(result)));
}
if let Some(rendered) = &receipt.rendered {
out.push_str(&format!("- Rendered: `{}`\n", escape_pipe(rendered)));
}
out.push_str(&format!(
"- Summary: {} passed, {} warnings, {} failed, {} skipped\n",
receipt.summary.passed,
receipt.summary.warnings,
receipt.summary.failed,
receipt.summary.skipped
));
out.push_str("\n## Checks\n\n");
out.push_str("| Status | ID | Message |\n| --- | --- | --- |\n");
for check in &receipt.checks {
out.push_str(&format!(
"| `{}` | `{}` | {} |\n",
label(check.status),
check.id,
escape_pipe(&check.message)
));
}
out
}
fn label(status: CheckStatus) -> &'static str {
status.as_str()
}
fn escape_pipe(value: &str) -> String {
value.replace('|', "\\|").replace('\n', " ")
}