use anyhow::Result;
use pmat::cli::analysis_utilities::{
calculate_provability_score, check_dead_code, check_entropy, QualityViolation,
};
use std::collections::HashMap;
use std::path::Path;
#[derive(Default)]
struct QualityReport {
passed: bool,
checks: HashMap<String, CheckResult>,
}
struct CheckResult {
passed: bool,
score: Option<f64>,
violations: Vec<QualityViolation>,
message: String,
}
#[tokio::main]
async fn main() -> Result<()> {
println!("🚦 Custom Quality Gate Example\n");
let project_path = std::env::args()
.nth(1)
.map(|p| Path::new(&p).to_path_buf())
.unwrap_or_else(|| Path::new(".").to_path_buf());
println!("Running quality gate for: {}\n", project_path.display());
let mut report = QualityReport {
passed: true,
..Default::default()
};
let dead_code_threshold = 10.0; let entropy_threshold = 0.6; let provability_threshold = 0.7;
println!("🔍 Checking dead code (max {}%)...", dead_code_threshold);
match check_dead_code(&project_path, dead_code_threshold).await {
Ok(violations) => {
let passed = violations.is_empty();
if !passed {
report.passed = false;
}
let message = if passed {
"✅ PASS: No excessive dead code found".to_string()
} else {
format!("❌ FAIL: Found {} dead code violations", violations.len())
};
println!(" {}", message);
report.checks.insert(
"dead_code".to_string(),
CheckResult {
passed,
score: None,
violations,
message,
},
);
}
Err(e) => {
println!(" ⚠️ WARNING: Could not check dead code: {}", e);
}
}
println!("\n🔍 Checking code entropy (min {})...", entropy_threshold);
match check_entropy(&project_path, entropy_threshold).await {
Ok(violations) => {
let passed = violations.is_empty();
if !passed {
report.passed = false;
}
let message = if passed {
"✅ PASS: Code diversity is acceptable".to_string()
} else {
format!(
"❌ FAIL: {} files have low code diversity",
violations.len()
)
};
println!(" {}", message);
report.checks.insert(
"entropy".to_string(),
CheckResult {
passed,
score: None,
violations,
message,
},
);
}
Err(e) => {
println!(" ⚠️ WARNING: Could not check entropy: {}", e);
}
}
println!(
"\n🔍 Checking provability (min {})...",
provability_threshold
);
match calculate_provability_score(&project_path).await {
Ok(score) => {
let passed = score >= provability_threshold;
if !passed {
report.passed = false;
}
let message = if passed {
format!("✅ PASS: Provability score {:.2} meets threshold", score)
} else {
format!(
"❌ FAIL: Provability score {:.2} below threshold {}",
score, provability_threshold
)
};
println!(" {}", message);
report.checks.insert(
"provability".to_string(),
CheckResult {
passed,
score: Some(score),
violations: vec![],
message,
},
);
}
Err(e) => {
println!(" ⚠️ WARNING: Could not check provability: {}", e);
}
}
println!("\n{}", "=".repeat(50));
println!("📊 QUALITY GATE SUMMARY");
println!("{}", "=".repeat(50));
let passed_checks = report.checks.values().filter(|c| c.passed).count();
let total_checks = report.checks.len();
println!("Checks passed: {}/{}", passed_checks, total_checks);
println!(
"Overall status: {}",
if report.passed {
"✅ PASSED"
} else {
"❌ FAILED"
}
);
println!("\n📈 Check scores:");
for (check_name, result) in &report.checks {
if let Some(score) = result.score {
println!(" - {}: {:.2}", check_name, score);
}
}
if !report.passed {
println!("\n📋 Failed checks:");
for (check_name, result) in &report.checks {
if !result.passed {
println!(" - {}: {}", check_name, result.message);
if !result.violations.is_empty() {
println!(" First few violations:");
for violation in result.violations.iter().take(3) {
println!(" • {} - {}", violation.file, violation.message);
}
}
}
}
println!("\n💡 Note: In CI/CD, this would exit with code 1");
}
Ok(())
}