pkgwatch/src/state.rs

61 lines
1.9 KiB
Rust
Raw Normal View History

use anyhow::Result;
use std::path::Path;
/// Last-known-published version per package, so re-runs don't re-flag a
/// version already handled. Deliberately just one file per package for
/// now — this is where a real review-queue persistence layer plugs in
/// later (see SPEC.md > Architecture > Reviewer queue).
pub fn load_last_version(state_dir: &Path, name: &str) -> Option<String> {
std::fs::read_to_string(state_dir.join(format!("{name}.version")))
.ok()
.map(|s| s.trim().to_string())
}
pub fn save_last_version(state_dir: &Path, name: &str, version: &str) -> Result<()> {
std::fs::create_dir_all(state_dir)?;
std::fs::write(state_dir.join(format!("{name}.version")), version)?;
Ok(())
}
Add shift-left quality gates: cognitive complexity, coverage, dependency fix Adds two new gates to the existing format/lint/test/audit pipeline (Makefile.toml `cargo make ci`, .forgejo/workflows/ci.yml): - Cognitive complexity via clippy's nursery cognitive_complexity lint (clippy.toml, threshold 15), scoped to --bins so test code's naturally higher branch count doesn't get gated. Went with this over the closest real cyclomatic-complexity tool (rust-code-analysis-cli) because that crate hasn't shipped a release since Jan 2023. - Test coverage via cargo-llvm-cov, chosen over cargo-tarpaulin for friendlier behavior in containerized/dind CI (no ptrace). Report-only for now (no --fail-under-lines) since a real threshold needs real usage data first — see below. main.rs is excluded: it's orchestration glue exercised by the real end-to-end `cargo run`, not unit tests. Getting both gates running required writing pkgwatch's first tests (previously zero). To make the GitHub-facing modules unit-testable without hitting real github.com/api.github.com, added `GithubEndpoints` (src/github.rs) so checker/fetcher/verifier take injectable base URLs, and added mockito + tempfile as dev-dependencies. Result: 27 tests, 94% region / 96% line coverage excluding main.rs. Also: cargo audit (now wired into `cargo make ci`) immediately caught a real, currently-open advisory (RUSTSEC-2026-0285, published days ago) in the transitive rustls dependency — bumped 0.23.44 -> 0.23.45 to clear it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 07:16:14 +00:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn load_last_version_missing_file_returns_none() {
let dir = tempfile::tempdir().unwrap();
assert_eq!(load_last_version(dir.path(), "nonexistent"), None);
}
#[test]
fn save_then_load_roundtrips() {
let dir = tempfile::tempdir().unwrap();
save_last_version(dir.path(), "uv", "0.12.15").unwrap();
assert_eq!(
load_last_version(dir.path(), "uv"),
Some("0.12.15".to_string())
);
}
#[test]
fn load_last_version_trims_trailing_whitespace() {
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("uv.version"), "0.12.15\n").unwrap();
assert_eq!(
load_last_version(dir.path(), "uv"),
Some("0.12.15".to_string())
);
}
#[test]
fn save_last_version_creates_state_dir_if_missing() {
let dir = tempfile::tempdir().unwrap();
let nested = dir.path().join("nested/state");
save_last_version(&nested, "uv", "0.12.15").unwrap();
assert_eq!(
load_last_version(&nested, "uv"),
Some("0.12.15".to_string())
);
}
}