use crate::cli::OutputFormat;
use crate::error::CommandError;
use crate::project;
use crate::tool::{HealthReport, HealthStatus, Tool, certification_status, probe};
pub(crate) fn execute(format: OutputFormat, checks_only: bool) -> Result<(), CommandError> {
if checks_only {
return crate::system_check::execute(format);
}
execute_environment(format)
}
fn execute_environment(format: OutputFormat) -> Result<(), CommandError> {
let mut report = HealthReport::default();
report.push(
"platform",
HealthStatus::Ok,
format!("{} {}", std::env::consts::OS, std::env::consts::ARCH),
);
add_tool(&mut report, Tool::Rustc);
add_tool(&mut report, Tool::Cargo);
add_tool(&mut report, Tool::Node);
add_tool(&mut report, Tool::Pnpm);
match project::discover() {
Ok(project) => {
add_project(&mut report, &project);
add_certified_stack(&mut report, &project);
}
Err(error) => report.push("project", HealthStatus::Warning, error.to_string()),
}
output(&report, format)?;
if report.has_error() {
Err(CommandError::Unhealthy("environment"))
} else {
Ok(())
}
}
fn add_certified_stack(report: &mut HealthReport, project: &project::ProjectConfig) {
let contract = crate::stack::load();
report.push(
"certified stack",
HealthStatus::Ok,
format!(
"snapshot {} (arcature {})",
contract.snapshot.date, contract.snapshot.arcature_version
),
);
let lockfile = project.root().join("Cargo.lock");
crate::stack::check_cargo_lock(&contract, &lockfile, report);
let package_json = project.frontend_root().join("package.json");
crate::stack::check_frontend(&contract, &package_json, report);
for (name, service) in &contract.services {
report.push(
"service",
HealthStatus::Ok,
format!(
"{} {} (certified: {})",
name,
service.role,
service.certified_versions.join(", ")
),
);
}
}
fn add_tool(report: &mut HealthReport, tool: Tool) {
match probe(tool) {
Ok(version) => report.push(
tool.program(),
certification_status(tool, version),
version.to_string(),
),
Err(error) => report.push(tool.program(), HealthStatus::Error, error.to_string()),
}
}
fn add_project(report: &mut HealthReport, project: &project::ProjectConfig) {
report.push(
"project",
HealthStatus::Ok,
format!(
"{} ({})",
project.root().display(),
project.frontend.as_str()
),
);
let lockfile = project.frontend_root().join("pnpm-lock.yaml");
report.push(
"lockfile",
if lockfile.is_file() {
HealthStatus::Ok
} else {
HealthStatus::Error
},
lockfile.display().to_string(),
);
let manifest = project.frontend_root().join("package.json");
let vite = std::fs::read_to_string(&manifest)
.map_err(|error| error.to_string())
.and_then(|contents| {
serde_json::from_str::<serde_json::Value>(&contents).map_err(|error| error.to_string())
})
.ok()
.and_then(|value| {
value
.get("devDependencies")?
.get("vite")?
.as_str()
.map(str::to_owned)
});
match vite {
Some(version) => report.push(
"vite",
if version == "8.2.1" {
HealthStatus::Ok
} else {
HealthStatus::Unverified
},
version,
),
None => report.push(
"vite",
HealthStatus::Error,
format!("missing or invalid dependency in {}", manifest.display()),
),
}
}
fn output(report: &HealthReport, format: OutputFormat) -> Result<(), serde_json::Error> {
match format {
OutputFormat::Human => {
report.print_human();
Ok(())
}
OutputFormat::Json => report.print_json(),
}
}