pkgwatch/src/main.rs

78 lines
2.4 KiB
Rust
Raw Normal View History

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(())
}