ryra 0.1.1

A tool to test and deploy self-hosted services on a Linux server using rootless Podman and systemd. Built-in VM testing gives AI agents fast feedback loops for building infrastructure and deploying apps.
use anyhow::Result;
use ryra_core::system::doctor::{Issue, Severity, check_all};

pub fn run() -> Result<()> {
    let paths = ryra_core::config::ConfigPaths::resolve()?;
    let config = ryra_core::config::load_or_default(&paths.config_file)?;
    let issues = check_all(&config);

    if config.has_secrets() {
        println!(
            "Credentials: {} and ~/.local/share/services/*/.env (all mode 0600).",
            paths.config_file.display()
        );
        println!();
    }

    if issues.is_empty() {
        println!("No issues found.");
        return Ok(());
    }

    let mut blockers = 0;
    let mut warnings = 0;
    let mut infos = 0;
    for i in &issues {
        match i.severity() {
            Severity::Blocker => blockers += 1,
            Severity::Warning => warnings += 1,
            Severity::Info => infos += 1,
        }
    }

    println!(
        "{} issue{} found ({blockers} blocker{}, {warnings} warning{}, {infos} info).\n",
        issues.len(),
        plural(issues.len()),
        plural(blockers),
        plural(warnings),
    );

    print_section(&issues, Severity::Blocker, "blocker");
    print_section(&issues, Severity::Warning, "warning");
    print_section(&issues, Severity::Info, "info");

    if blockers > 0 {
        std::process::exit(1);
    }
    Ok(())
}

fn print_section(issues: &[Issue], sev: Severity, label: &str) {
    let filtered: Vec<&Issue> = issues.iter().filter(|i| i.severity() == sev).collect();
    if filtered.is_empty() {
        return;
    }
    for issue in filtered {
        println!("[{label}] {issue}\n");
    }
}

fn plural(n: usize) -> &'static str {
    if n == 1 { "" } else { "s" }
}