From 3ed74045de980ea68411a22257935656c46b9663 Mon Sep 17 00:00:00 2001 From: hukla <129692708+huklaa@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:48:33 +0300 Subject: [PATCH] fix(quake): parse semver build metadata in image tags --- crates/quake/src/cli_version.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/quake/src/cli_version.rs b/crates/quake/src/cli_version.rs index 695e97ba..5f8256ef 100644 --- a/crates/quake/src/cli_version.rs +++ b/crates/quake/src/cli_version.rs @@ -89,11 +89,12 @@ const V0_6_0: (u64, u64, u64) = (0, 6, 0); /// Extract a `(major, minor, patch)` tuple from an image tag. /// /// Returns `Some` only for explicit parseable versions such as `v0.6.0`, -/// `arc_consensus:v0.5.1-rc1`, or `0.7.0`. Returns `None` for missing tags, -/// the `"latest"` tag, or tags that do not fit the `MAJOR.MINOR.PATCH[-...]` -/// pattern. Callers decide how to interpret `None` — [`check_cli_version`] -/// distinguishes `latest` from unparsable, while [`apply_version_compat`] -/// treats every `None` uniformly as "assume the target supports every flag". +/// `arc_consensus:v0.5.1-rc1`, `v0.6.0+build.1`, or `0.7.0`. Returns `None` +/// for missing tags, the `"latest"` tag, or tags that do not fit the +/// `MAJOR.MINOR.PATCH[-...][+...]` pattern. Callers decide how to interpret +/// `None` — [`check_cli_version`] distinguishes `latest` from unparsable, while +/// [`apply_version_compat`] treats every `None` uniformly as "assume the target +/// supports every flag". fn parse_image_semver(image_tag: Option<&str>) -> Option<(u64, u64, u64)> { let tag = image_tag?; let version_str = tag.rsplit(':').next().unwrap_or(tag); @@ -107,7 +108,10 @@ fn parse_image_semver(image_tag: Option<&str>) -> Option<(u64, u64, u64)> { } let major = parts[0].parse::().ok()?; let minor = parts[1].parse::().ok()?; - let patch_str = parts[2].split('-').next().unwrap_or(parts[2]); + let patch_str = parts[2] + .split(|c| c == '-' || c == '+') + .next() + .unwrap_or(parts[2]); let patch = patch_str.parse::().ok()?; Some((major, minor, patch)) } @@ -246,7 +250,9 @@ mod tests { fn supports_cli_flags_handles_prerelease_versions() { assert!(supports_cli_flags(Some("v0.5.0-rc1"))); assert!(supports_cli_flags(Some("v0.5.0-beta"))); + assert!(supports_cli_flags(Some("v0.5.0+build.1"))); assert!(!supports_cli_flags(Some("v0.4.0-rc1"))); + assert!(!supports_cli_flags(Some("v0.4.0+build.1"))); } /// Run `apply_version_compat` over `input` for the given `image_tag` and @@ -294,6 +300,7 @@ mod tests { "v0.6.0", "0.6.0", "v0.6.0-rc1", + "v0.6.0+build.1", ] { let result = compat_flags(Some(tag)); assert!( @@ -315,6 +322,7 @@ mod tests { "v0.6.1", "0.6.1", "v0.6.1-rc1", + "v0.6.1+build.1", "v0.7.0-beta", ] { let result = compat_flags(Some(tag));