use crate::cli::colors;
use crate::cli::OutputFormat;
use anyhow::Result;
use serde::Serialize;
use std::path::PathBuf;
use tokio::task::JoinSet;
#[derive(Debug, Clone)]
pub struct HealthCheckConfig {
pub quick: bool,
pub all: bool,
pub check_build: bool,
pub check_tests: bool,
pub check_coverage: bool,
pub check_complexity: bool,
pub check_satd: bool,
}
impl HealthCheckConfig {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new(
quick: bool,
all: bool,
check_build: bool,
check_tests: bool,
check_coverage: bool,
check_complexity: bool,
check_satd: bool,
) -> Self {
Self {
quick,
all,
check_build,
check_tests,
check_coverage,
check_complexity,
check_satd,
}
}
}
#[derive(Debug, Serialize)]
pub struct HealthReport {
pub healthy: bool,
pub checks: Vec<HealthCheck>,
pub summary: HealthSummary,
}
#[derive(Debug, Serialize)]
pub struct HealthCheck {
pub name: String,
pub status: CheckStatus,
pub message: String,
pub details: Option<String>,
}
#[derive(Debug, Serialize, PartialEq)]
pub enum CheckStatus {
Pass,
Warn,
Fail,
Skip,
}
#[derive(Debug, Serialize)]
pub struct HealthSummary {
pub total_checks: usize,
pub passed: usize,
pub warned: usize,
pub failed: usize,
pub skipped: usize,
}
#[derive(Debug, Clone, Copy)]
enum CheckType {
Build,
Tests,
Coverage,
Complexity,
Satd,
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn run_health_checks_internal(
project_dir: &PathBuf,
config: &HealthCheckConfig,
) -> Result<HealthReport> {
let checks_to_run = determine_checks_to_run(
config.quick,
config.all,
config.check_build,
config.check_tests,
config.check_coverage,
config.check_complexity,
config.check_satd,
);
let mut check_types = Vec::new();
if checks_to_run.build {
check_types.push(CheckType::Build);
}
if checks_to_run.tests {
check_types.push(CheckType::Tests);
}
if checks_to_run.coverage {
check_types.push(CheckType::Coverage);
}
if checks_to_run.complexity {
check_types.push(CheckType::Complexity);
}
if checks_to_run.satd {
check_types.push(CheckType::Satd);
}
let checks = run_checks_parallel(project_dir, check_types).await?;
let summary = calculate_summary(&checks);
let report = HealthReport {
healthy: summary.failed == 0,
checks,
summary,
};
Ok(report)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn handle_maintain_health(
project_dir: PathBuf,
format: OutputFormat,
config: HealthCheckConfig,
) -> Result<()> {
let report = run_health_checks_internal(&project_dir, &config).await?;
print_health_report(&report, &format)?;
if !report.healthy {
std::process::exit(1);
}
Ok(())
}
include!("health_handler_output.rs");
include!("health_handler_checks.rs");
include!("health_handler_tests.rs");