mod checker; mod config; mod fetcher; mod state; mod verifier; use anyhow::Result; use std::path::Path; /// First iteration: check -> fetch -> verify -> report, for whatever is /// in packages.d/. No build/publish step yet (see SPEC.md > Status). fn main() -> Result<()> { let client = reqwest::blocking::Client::builder() .user_agent("pkgwatch/0.1 (PoC; https://code.austinschaefer.com)") .build()?; let packages_dir = Path::new("packages.d"); let state_dir = Path::new("state"); let work_dir = Path::new("work"); let packages = config::load_packages_dir(packages_dir)?; if packages.is_empty() { println!("no packages configured under {}/", packages_dir.display()); return Ok(()); } for (name, pkg) in packages { println!("== {name} ({}) ==", pkg.repo); let latest = checker::latest_github_release(&client, &pkg.repo)?; let last_seen = state::load_last_version(state_dir, &name); if last_seen.as_deref() == Some(latest.as_str()) { println!(" up to date at {latest}"); continue; } println!(" new version detected: {latest} (previously: {last_seen:?})"); let dest_dir = work_dir.join(&name).join(&latest); let artifact_path = fetcher::download_asset(&client, &pkg.repo, &latest, &pkg.asset_pattern, &dest_dir)?; println!(" fetched {}", artifact_path.display()); let result = verifier::verify( &client, &pkg.verification, &pkg.repo, &latest, &artifact_path, &dest_dir, )?; println!( " verification (tier {}): {} — {}", result.tier, if result.passed { "PASS" } else { "FAIL" }, result.justification ); match (result.tier, result.passed) { (1..=3, true) => { println!(" tier 1-3 pass: would auto-build + publish (not yet implemented)"); state::save_last_version(state_dir, &name, &latest)?; } (_, true) => { println!(" tier 4-6 pass: flagging for human review, not auto-publishing"); println!( " (review-queue persistence not yet implemented — this is where it plugs in)" ); } (_, false) => { println!(" verification failed — not publishing, not updating state"); } } } Ok(()) }