fix: Use lenient_semver for build drivers version check to handle pre-release versions

This commit is contained in:
Gerald Pinder 2025-02-10 18:48:35 -05:00
parent e88c7561a9
commit 003e473de1
11 changed files with 66 additions and 26 deletions

6
Cargo.lock generated
View file

@ -411,7 +411,6 @@ dependencies = [
"indexmap 2.7.1", "indexmap 2.7.1",
"indicatif", "indicatif",
"indicatif-log-bridge", "indicatif-log-bridge",
"lenient_semver",
"log", "log",
"log4rs", "log4rs",
"miette", "miette",
@ -481,10 +480,12 @@ dependencies = [
"directories", "directories",
"docker_credential", "docker_credential",
"format_serde_error", "format_serde_error",
"lenient_semver",
"log", "log",
"miette", "miette",
"process_control", "process_control",
"rstest", "rstest",
"semver",
"serde", "serde",
"serde_json", "serde_json",
"serde_yml", "serde_yml",
@ -4057,9 +4058,6 @@ name = "semver"
version = "1.0.25" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde" name = "serde"

View file

@ -19,10 +19,10 @@ comlexr = "1"
indexmap = { version = "2", features = ["serde"] } indexmap = { version = "2", features = ["serde"] }
indicatif = { version = "0.17", features = ["improved_unicode"] } indicatif = { version = "0.17", features = ["improved_unicode"] }
log = "0.4" log = "0.4"
miette = "7"
nix = { version = "0.29" } nix = { version = "0.29" }
oci-distribution = { version = "0.11", default-features = false } oci-distribution = { version = "0.11", default-features = false }
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] } reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
miette = "7"
rstest = "0.18" rstest = "0.18"
semver = "1" semver = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View file

@ -14,7 +14,6 @@ path = "process.rs"
anyhow = "1" anyhow = "1"
blue-build-utils = { version = "=0.9.6", path = "../utils" } blue-build-utils = { version = "=0.9.6", path = "../utils" }
indicatif-log-bridge = "0.2" indicatif-log-bridge = "0.2"
lenient_semver = "0.4"
log4rs = { version = "1", features = ["background_rotation"] } log4rs = { version = "1", features = ["background_rotation"] }
nu-ansi-term = { version = "0.50", features = ["gnu_legacy"] } nu-ansi-term = { version = "0.50", features = ["gnu_legacy"] }
once_cell = "1" once_cell = "1"
@ -36,7 +35,7 @@ miette.workspace = true
nix = { workspace = true, features = ["signal", "user"] } nix = { workspace = true, features = ["signal", "user"] }
oci-distribution.workspace = true oci-distribution.workspace = true
reqwest.workspace = true reqwest.workspace = true
semver = { workspace = true, features = ["serde"] } semver.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
tempfile.workspace = true tempfile.workspace = true

View file

@ -1,11 +1,10 @@
use std::{io::Write, process::Stdio}; use std::{io::Write, process::Stdio};
use blue_build_utils::credentials::Credentials; use blue_build_utils::{credentials::Credentials, semver::Version};
use colored::Colorize; use colored::Colorize;
use comlexr::cmd; use comlexr::cmd;
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use miette::{bail, miette, IntoDiagnostic, Result}; use miette::{bail, miette, IntoDiagnostic, Result};
use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use crate::{drivers::types::Platform, logging::CommandLogging}; use crate::{drivers::types::Platform, logging::CommandLogging};
@ -36,10 +35,13 @@ impl DriverVersion for BuildahDriver {
fn version() -> Result<Version> { fn version() -> Result<Version> {
trace!("BuildahDriver::version()"); trace!("BuildahDriver::version()");
trace!("buildah version --json"); let output = {
let output = cmd!("buildah", "version", "--json") let c = cmd!("buildah", "version", "--json");
.output() trace!("{c:?}");
.into_diagnostic()?; c
}
.output()
.into_diagnostic()?;
let version_json: BuildahVersionJson = serde_json::from_slice(&output.stdout) let version_json: BuildahVersionJson = serde_json::from_slice(&output.stdout)
.inspect_err(|e| error!("{e}: {}", String::from_utf8_lossy(&output.stdout))) .inspect_err(|e| error!("{e}: {}", String::from_utf8_lossy(&output.stdout)))

View file

@ -8,6 +8,7 @@ use std::{
use blue_build_utils::{ use blue_build_utils::{
constants::{BB_BUILDKIT_CACHE_GHA, DOCKER_HOST, GITHUB_ACTIONS}, constants::{BB_BUILDKIT_CACHE_GHA, DOCKER_HOST, GITHUB_ACTIONS},
credentials::Credentials, credentials::Credentials,
semver::Version,
string_vec, string_vec,
}; };
use cached::proc_macro::cached; use cached::proc_macro::cached;
@ -17,7 +18,6 @@ use log::{debug, info, trace, warn};
use miette::{bail, IntoDiagnostic, Result}; use miette::{bail, IntoDiagnostic, Result};
use oci_distribution::Reference; use oci_distribution::Reference;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use tempfile::TempDir; use tempfile::TempDir;
@ -124,6 +124,8 @@ impl DriverVersion for DockerDriver {
const VERSION_REQ: &'static str = ">=23"; const VERSION_REQ: &'static str = ">=23";
fn version() -> Result<Version> { fn version() -> Result<Version> {
trace!("DockerDriver::version()");
let output = { let output = {
let c = cmd!("docker", "version", "-f", "json"); let c = cmd!("docker", "version", "-f", "json");
trace!("{c:?}"); trace!("{c:?}");

View file

@ -5,7 +5,7 @@ use std::{
time::Duration, time::Duration,
}; };
use blue_build_utils::credentials::Credentials; use blue_build_utils::{credentials::Credentials, semver::Version};
use cached::proc_macro::cached; use cached::proc_macro::cached;
use colored::Colorize; use colored::Colorize;
use comlexr::{cmd, pipe}; use comlexr::{cmd, pipe};
@ -13,7 +13,6 @@ use indicatif::{ProgressBar, ProgressStyle};
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use miette::{bail, miette, IntoDiagnostic, Report, Result}; use miette::{bail, miette, IntoDiagnostic, Report, Result};
use oci_distribution::Reference; use oci_distribution::Reference;
use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use tempfile::TempDir; use tempfile::TempDir;
@ -114,10 +113,13 @@ impl DriverVersion for PodmanDriver {
fn version() -> Result<Version> { fn version() -> Result<Version> {
trace!("PodmanDriver::version()"); trace!("PodmanDriver::version()");
trace!("podman version -f json"); let output = {
let output = cmd!("podman", "version", "-f", "json") let c = cmd!("podman", "version", "-f", "json");
.output() trace!("{c:?}");
.into_diagnostic()?; c
}
.output()
.into_diagnostic()?;
let version_json: PodmanVersionJson = serde_json::from_slice(&output.stdout) let version_json: PodmanVersionJson = serde_json::from_slice(&output.stdout)
.inspect_err(|e| error!("{e}: {}", String::from_utf8_lossy(&output.stdout))) .inspect_err(|e| error!("{e}: {}", String::from_utf8_lossy(&output.stdout)))

View file

@ -4,11 +4,11 @@ use std::{
process::{ExitStatus, Output}, process::{ExitStatus, Output},
}; };
use blue_build_utils::{constants::COSIGN_PUB_PATH, retry, string_vec}; use blue_build_utils::{constants::COSIGN_PUB_PATH, retry, semver::Version, string_vec};
use log::{debug, info, trace}; use log::{debug, info, trace};
use miette::{bail, Context, IntoDiagnostic, Result}; use miette::{bail, Context, IntoDiagnostic, Result};
use oci_distribution::Reference; use oci_distribution::Reference;
use semver::{Version, VersionReq}; use semver::VersionReq;
use crate::drivers::{functions::get_private_key, types::CiDriverType, Driver}; use crate::drivers::{functions::get_private_key, types::CiDriverType, Driver};

View file

@ -1,6 +1,9 @@
use std::{collections::HashMap, env}; use std::{collections::HashMap, env};
use blue_build_utils::constants::{GITHUB_ACTIONS, GITLAB_CI, IMAGE_VERSION_LABEL}; use blue_build_utils::{
constants::{GITHUB_ACTIONS, GITLAB_CI, IMAGE_VERSION_LABEL},
semver::Version,
};
use clap::ValueEnum; use clap::ValueEnum;
use log::trace; use log::trace;
use serde::Deserialize; use serde::Deserialize;
@ -233,9 +236,9 @@ impl ImageMetadata {
pub fn get_version(&self) -> Option<u64> { pub fn get_version(&self) -> Option<u64> {
Some( Some(
self.labels self.labels
.get(IMAGE_VERSION_LABEL)? .get(IMAGE_VERSION_LABEL)
.as_str() .map(ToOwned::to_owned)
.and_then(|v| lenient_semver::parse(v).ok())? .and_then(|v| serde_json::from_value::<Version>(v).ok())?
.major, .major,
) )
} }

View file

@ -16,6 +16,7 @@ constcat = "0.6"
directories = "6" directories = "6"
docker_credential = "1" docker_credential = "1"
format_serde_error = "0.3" format_serde_error = "0.3"
lenient_semver = "0.4"
process_control = { version = "4", features = ["crossbeam-channel"] } process_control = { version = "4", features = ["crossbeam-channel"] }
which = "7" which = "7"
@ -24,6 +25,7 @@ clap = { workspace = true, features = ["derive", "env"] }
comlexr.workspace = true comlexr.workspace = true
log.workspace = true log.workspace = true
miette.workspace = true miette.workspace = true
semver.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true

View file

@ -2,6 +2,7 @@ pub mod command_output;
pub mod constants; pub mod constants;
pub mod credentials; pub mod credentials;
mod macros; mod macros;
pub mod semver;
pub mod syntax_highlighting; pub mod syntax_highlighting;
#[cfg(feature = "test")] #[cfg(feature = "test")]
pub mod test_utils; pub mod test_utils;

31
utils/src/semver.rs Normal file
View file

@ -0,0 +1,31 @@
use serde::{de::Error, Deserialize};
#[derive(Debug)]
pub struct Version(semver::Version);
impl std::ops::Deref for Version {
type Target = semver::Version;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::fmt::Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<'de> Deserialize<'de> for Version {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let ver = String::deserialize(deserializer)?;
lenient_semver::parse(&ver)
.ok()
.map(Self)
.ok_or_else(|| D::Error::custom(format!("Failed to deserialize version {ver}")))
}
}