From 6c4c705888ece0ffde72a2be488dc830c16c036a Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 10 May 2026 21:52:30 +0000 Subject: [PATCH] fix(cli): scope touch_cooldown version reuse to matching repo_slug (MR-612) cubic P2 follow-up. `touch_cooldown` previously carried forward `latest_version` from any prior cache entry, even one written by a binary pointed at a different fork. After this change we only reuse the cached version when its `repo_slug` matches the repo this binary was built for; otherwise we fall back to the current binary's own version, which never fires a spurious "newer available" notice. Adds two unit tests covering both cases. Co-Authored-By: Ragnor Comerford --- crates/omnigraph-cli/src/version_check.rs | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/omnigraph-cli/src/version_check.rs b/crates/omnigraph-cli/src/version_check.rs index a848e4c..c494fee 100644 --- a/crates/omnigraph-cli/src/version_check.rs +++ b/crates/omnigraph-cli/src/version_check.rs @@ -128,8 +128,14 @@ pub async fn refresh_cache_subcommand() -> Result<()> { /// Write a fresh `checked_at_unix` timestamp to the cache while keeping the /// previously-known `latest_version` (or, when there is none, recording the /// current binary's version so `version_is_newer` doesn't fire spuriously). +/// +/// We only reuse the cached `latest_version` when its `repo_slug` matches the +/// repo this binary was built against — otherwise a cache file left behind by +/// a fork's binary could relabel its tag as our own and trigger a spurious +/// upgrade notice. fn touch_cooldown(cache_path: &Path, previous: Option<&CacheEntry>) { let latest_version = previous + .filter(|p| p.repo_slug == REPO_SLUG) .map(|p| p.latest_version.clone()) .unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string()); let entry = CacheEntry { @@ -276,6 +282,41 @@ mod tests { assert!(read_cache(&path).is_none()); } + #[test] + fn touch_cooldown_ignores_cache_from_other_repo() { + // Cache populated by a binary pointed at a different fork must not + // be relabeled as our own — `touch_cooldown` should fall back to the + // current binary's version so `version_is_newer` doesn't fire. + let dir = tempdir().unwrap(); + let path = dir.path().join("update-check.json"); + let foreign = CacheEntry { + checked_at_unix: 1_700_000_000, + latest_version: "99.99.99".to_string(), + repo_slug: "someone/fork".to_string(), + }; + touch_cooldown(&path, Some(&foreign)); + let after = read_cache(&path).expect("cache should be written"); + assert_eq!(after.repo_slug, REPO_SLUG); + assert_eq!(after.latest_version, env!("CARGO_PKG_VERSION")); + } + + #[test] + fn touch_cooldown_preserves_version_from_same_repo() { + let dir = tempdir().unwrap(); + let path = dir.path().join("update-check.json"); + let previous = CacheEntry { + checked_at_unix: 1_600_000_000, + latest_version: "0.5.0".to_string(), + repo_slug: REPO_SLUG.to_string(), + }; + touch_cooldown(&path, Some(&previous)); + let after = read_cache(&path).expect("cache should be written"); + assert_eq!(after.repo_slug, REPO_SLUG); + assert_eq!(after.latest_version, "0.5.0"); + // The cooldown should have advanced the timestamp past the prior value. + assert!(after.checked_at_unix >= previous.checked_at_unix); + } + #[test] fn env_truthy_handles_common_falsy_values() { unsafe {