Add username
This commit is contained in:
parent
71654a6fe2
commit
07e582e2be
9 changed files with 358 additions and 192 deletions
104
src/strategy.rs
104
src/strategy.rs
|
|
@ -1,6 +1,6 @@
|
|||
use crate::config::UpdateStrategy;
|
||||
use crate::version::VersionInfo;
|
||||
use tracing::{debug, warn};
|
||||
use tracing::debug;
|
||||
|
||||
pub fn create_selector(strategy: &UpdateStrategy) -> Box<dyn VersionSelector> {
|
||||
match strategy {
|
||||
|
|
@ -34,8 +34,6 @@ impl VersionSelector for LatestVersionSelector {
|
|||
|
||||
if let Some(ref selected) = latest {
|
||||
debug!("Latest version selected: {}", selected.version);
|
||||
} else {
|
||||
warn!("No matching versions available");
|
||||
}
|
||||
|
||||
latest
|
||||
|
|
@ -55,29 +53,26 @@ impl VersionSelector for SmartPreviousMinorSelector {
|
|||
get_filtered_and_sorted_matching_versions(available, current_prefix, current_suffix);
|
||||
|
||||
let latest = &versions.first()?.version;
|
||||
let latest_line = (latest.major, latest.minor);
|
||||
debug!("Latest version available: {}", latest);
|
||||
|
||||
let (target_major, max_minor) = if latest.minor == 0 {
|
||||
if latest.major == 0 {
|
||||
debug!("Cannot go to previous version of 0.0.x");
|
||||
return None;
|
||||
}
|
||||
(latest.major - 1, None)
|
||||
} else {
|
||||
(latest.major, Some(latest.minor - 1))
|
||||
};
|
||||
|
||||
// The target is the highest patch of the newest release line strictly
|
||||
// below the latest one. Deriving that line by decrementing (`minor - 1`,
|
||||
// or `major - 1` when the latest is a `.0`) assumes releases never skip a
|
||||
// number, which registries routinely do: linuxserver/sonarr publishes 5.14
|
||||
// and 4.0.x with no 5.13, so a decrement searched for a 5.x line that does
|
||||
// not exist and returned nothing, stranding the image on its current tag.
|
||||
// Since `versions` is sorted descending, the first entry below the latest
|
||||
// line is exactly that.
|
||||
let selected = versions
|
||||
.iter()
|
||||
.find(|v| {
|
||||
v.version.major == target_major && max_minor.is_none_or(|m| v.version.minor <= m)
|
||||
})
|
||||
.find(|v| (v.version.major, v.version.minor) < latest_line)
|
||||
.cloned();
|
||||
|
||||
if let Some(ref selected) = selected {
|
||||
debug!("Selected version: {}", selected.version);
|
||||
} else {
|
||||
warn!("No matching versions available for previous minor strategy");
|
||||
debug!("No release line below {} to fall back to", latest);
|
||||
}
|
||||
|
||||
selected
|
||||
|
|
@ -199,6 +194,81 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
/// linuxserver/sonarr: the newest line is 5.14 with no 5.x below it, so the
|
||||
/// previous line is the 4.0 series. Decrementing the minor used to look for a
|
||||
/// nonexistent 5.13-or-lower and leave the image stuck on 4.0.15.
|
||||
#[test]
|
||||
fn test_previous_minor_steps_across_a_major_gap() {
|
||||
let selector = create_selector(&UpdateStrategy::LatestPatchOfPreviousMinor);
|
||||
|
||||
let available = vec![
|
||||
VersionInfo::from_tag("5.14").unwrap(),
|
||||
VersionInfo::from_tag("4.0.19").unwrap(),
|
||||
VersionInfo::from_tag("4.0.18").unwrap(),
|
||||
VersionInfo::from_tag("4.0.15").unwrap(),
|
||||
];
|
||||
|
||||
let target = selector.select_target_version(&available, None, None);
|
||||
assert_eq!(
|
||||
target.map(|v| v.version),
|
||||
Some(Version::parse("4.0.19").unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
/// linuxserver/qbittorrent: a stray legacy 14.3.9 tag sorts above every real
|
||||
/// release, and there is no 14.x line below it. The previous line is 5.2.
|
||||
#[test]
|
||||
fn test_previous_minor_skips_an_isolated_outlier_line() {
|
||||
let selector = create_selector(&UpdateStrategy::LatestPatchOfPreviousMinor);
|
||||
|
||||
let available = vec![
|
||||
VersionInfo::from_tag("14.3.9").unwrap(),
|
||||
VersionInfo::from_tag("5.2.3").unwrap(),
|
||||
VersionInfo::from_tag("5.2.0").unwrap(),
|
||||
VersionInfo::from_tag("5.1.4").unwrap(),
|
||||
];
|
||||
|
||||
let target = selector.select_target_version(&available, None, None);
|
||||
assert_eq!(
|
||||
target.map(|v| v.version),
|
||||
Some(Version::parse("5.2.3").unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
/// Skipped minors (2.5 -> 2.3, no 2.4) must not strand the image either.
|
||||
#[test]
|
||||
fn test_previous_minor_handles_skipped_minors() {
|
||||
let selector = create_selector(&UpdateStrategy::LatestPatchOfPreviousMinor);
|
||||
|
||||
let available = vec![
|
||||
VersionInfo::from_tag("2.5.2").unwrap(),
|
||||
VersionInfo::from_tag("2.3.5").unwrap(),
|
||||
VersionInfo::from_tag("2.3.0").unwrap(),
|
||||
];
|
||||
|
||||
let target = selector.select_target_version(&available, None, None);
|
||||
assert_eq!(
|
||||
target.map(|v| v.version),
|
||||
Some(Version::parse("2.3.5").unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
/// A single release line has nothing below it: staying put is correct, since
|
||||
/// the strategy exists to keep one line behind the newest.
|
||||
#[test]
|
||||
fn test_previous_minor_without_an_older_line() {
|
||||
let selector = create_selector(&UpdateStrategy::LatestPatchOfPreviousMinor);
|
||||
|
||||
let available = vec![
|
||||
VersionInfo::from_tag("1.0.2").unwrap(),
|
||||
VersionInfo::from_tag("1.0.1").unwrap(),
|
||||
];
|
||||
|
||||
assert!(selector
|
||||
.select_target_version(&available, None, None)
|
||||
.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cross_major_version_handling() {
|
||||
let selector = create_selector(&UpdateStrategy::LatestPatchOfPreviousMinor);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue