chore: added checking for browser autoupdater by published_at (#823)

This commit is contained in:
Maciek 2026-09-13 00:34:37 +02:00 • committed by GitHub
parent 44dfa32233
commit 53b27a1c7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -7,6 +7,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use chrono::{DateTime, Utc};
use futures_util::StreamExt; use futures_util::StreamExt;
use oneclient_common::domain::ProviderId; use oneclient_common::domain::ProviderId;
@ -83,6 +84,7 @@ struct Candidate {
version_id: String, version_id: String,
display_name: String, display_name: String,
display_version: String, display_version: String,
published_at: Option<DateTime<Utc>>,
} }
/// A missing bundle tracking row is the marker for "the user added this themselves" /// A missing bundle tracking row is the marker for "the user added this themselves"
@ -108,6 +110,7 @@ fn browser_installed(
.clone() .clone()
.unwrap_or_else(|| info.file_name.clone()), .unwrap_or_else(|| info.file_name.clone()),
display_version: info.display_version.clone().unwrap_or_default(), display_version: info.display_version.clone().unwrap_or_default(),
published_at: info.published_at.as_deref().and_then(parse_published),
}) })
}) })
.collect() .collect()
@ -201,7 +204,16 @@ pub async fn check_browser_package_updates(
Ok(check) Ok(check)
} }
/// `None` when the installed version is already the newest compatible one fn parse_published(raw: &str) -> Option<DateTime<Utc>> {
DateTime::parse_from_rfc3339(raw)
.ok()
.map(|at| at.with_timezone(&Utc))
}
fn is_upgrade(installed_published: Option<DateTime<Utc>>, latest_published: DateTime<Utc>) -> bool {
installed_published.is_none_or(|installed| latest_published > installed)
}
async fn latest_for( async fn latest_for(
candidate: &Candidate, candidate: &Candidate,
cluster: &ClusterRow, cluster: &ClusterRow,
@ -216,6 +228,16 @@ async fn latest_for(
return Ok(None); return Ok(None);
} }
if !is_upgrade(candidate.published_at, latest.published) {
tracing::debug!(
project_id = %candidate.project_id,
installed = %candidate.version_id,
offered = %latest.version_id,
"update not offered, the installed version is not older than the pick"
);
return Ok(None);
}
let name = if latest.version_number.is_empty() { let name = if latest.version_number.is_empty() {
latest.name latest.name
} else { } else {
@ -447,6 +469,10 @@ mod tests {
use super::*; use super::*;
use oneclient_common::domain::ContentType; use oneclient_common::domain::ContentType;
fn at(raw: &str) -> DateTime<Utc> {
parse_published(raw).expect("test dates are rfc 3339")
}
fn linked( fn linked(
hash: &str, hash: &str,
provider: Option<ProviderId>, provider: Option<ProviderId>,
@ -548,4 +574,54 @@ mod tests {
assert_eq!(pending.len(), 1); assert_eq!(pending.len(), 1);
assert_eq!(pending[0].hash, "b"); assert_eq!(pending[0].hash, "b");
} }
#[test]
fn a_newer_pick_is_an_upgrade() {
assert!(is_upgrade(
Some(at("2026-01-01T00:00:00Z")),
at("2026-02-01T00:00:00Z")
));
}
#[test]
fn a_pick_older_than_the_installed_build_is_not_an_upgrade() {
assert!(
!is_upgrade(
Some(at("2026-02-01T00:00:00Z")),
at("2026-01-01T00:00:00Z")
),
"a hand-installed build newer than the provider pick must not be offered a downgrade"
);
}
#[test]
fn a_pick_published_at_the_same_moment_is_not_an_upgrade() {
assert!(!is_upgrade(
Some(at("2026-02-01T00:00:00Z")),
at("2026-02-01T00:00:00Z")
));
}
#[test]
fn an_unknown_installed_date_still_offers_the_update() {
assert!(is_upgrade(None, at("2026-02-01T00:00:00Z")));
}
#[test]
fn candidates_carry_the_installed_publish_date() {
let mut info = linked("a", Some(ProviderId::Modrinth), Some("sodium"), Some("v1"));
info.published_at = Some("2026-02-01T00:00:00Z".into());
let found = browser_installed(&[info], &HashSet::new());
assert_eq!(found[0].published_at, Some(at("2026-02-01T00:00:00Z")));
}
#[test]
fn an_unparseable_publish_date_leaves_the_candidate_undated() {
let mut info = linked("a", Some(ProviderId::Modrinth), Some("sodium"), Some("v1"));
info.published_at = Some("not a date".into());
let found = browser_installed(&[info], &HashSet::new());
assert_eq!(found[0].published_at, None);
}
} }