feat: Add all linux platforms

This commit is contained in:
Gerald Pinder 2025-07-25 10:19:27 -04:00
parent de76312a38
commit 24a5c8d2b5
18 changed files with 185 additions and 78 deletions

View file

@ -188,9 +188,9 @@ impl Driver {
pub fn get_os_version( pub fn get_os_version(
/// The OCI image reference. /// The OCI image reference.
oci_ref: &Reference, oci_ref: &Reference,
/// The platform of the image to pull the version info from. /// The platform of the image to pull the version info from.
#[builder(default)] platform: Option<Platform>,
platform: Platform,
) -> Result<u64> { ) -> Result<u64> {
trace!("Driver::get_os_version({oci_ref:#?})"); trace!("Driver::get_os_version({oci_ref:#?})");
@ -208,7 +208,7 @@ impl Driver {
let os_version = Self::get_metadata( let os_version = Self::get_metadata(
&GetMetadataOpts::builder() &GetMetadataOpts::builder()
.image(oci_ref) .image(oci_ref)
.platform(platform) .maybe_platform(platform)
.build(), .build(),
) )
.and_then(|inspection| { .and_then(|inspection| {

View file

@ -8,7 +8,7 @@ use miette::{Context, IntoDiagnostic, Result, bail, miette};
use serde::Deserialize; use serde::Deserialize;
use tempfile::TempDir; use tempfile::TempDir;
use crate::{drivers::types::Platform, logging::CommandLogging}; use crate::logging::CommandLogging;
use super::{ use super::{
BuildDriver, DriverVersion, BuildDriver, DriverVersion,
@ -60,9 +60,9 @@ impl BuildDriver for BuildahDriver {
"build", "build",
for opts.secrets.args(&temp_dir)?, for opts.secrets.args(&temp_dir)?,
if opts.secrets.ssh() => "--ssh", if opts.secrets.ssh() => "--ssh",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--platform", "--platform",
opts.platform.to_string(), platform.to_string(),
], ],
"--pull=true", "--pull=true",
format!("--layers={}", !opts.squash), format!("--layers={}", !opts.squash),

View file

@ -30,7 +30,7 @@ use crate::{
RunOptsVolume, TagOpts, RunOptsVolume, TagOpts,
}, },
traits::{BuildDriver, DriverVersion, InspectDriver, RunDriver}, traits::{BuildDriver, DriverVersion, InspectDriver, RunDriver},
types::{ContainerId, ImageMetadata, ImageRef, Platform}, types::{ContainerId, ImageMetadata, ImageRef},
}, },
logging::CommandLogging, logging::CommandLogging,
signal_handler::{ContainerRuntime, ContainerSignalId, add_cid, remove_cid}, signal_handler::{ContainerRuntime, ContainerSignalId, add_cid, remove_cid},
@ -207,9 +207,9 @@ impl BuildDriver for DockerDriver {
let c = cmd!( let c = cmd!(
"docker", "docker",
"build", "build",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--platform", "--platform",
opts.platform.to_string(), platform.to_string(),
], ],
"-t", "-t",
opts.image.to_string(), opts.image.to_string(),
@ -456,9 +456,9 @@ fn build_tag_push_cmd(
}).collect() }).collect()
}), }),
"--pull", "--pull",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--platform", "--platform",
opts.platform.to_string(), platform.to_string(),
], ],
"-f", "-f",
&*opts.containerfile, &*opts.containerfile,
@ -507,7 +507,7 @@ impl InspectDriver for DockerDriver {
#[cached( #[cached(
result = true, result = true,
key = "String", key = "String",
convert = r#"{ format!("{}-{}", opts.image, opts.platform)}"#, convert = r#"{ format!("{}-{:?}", opts.image, opts.platform)}"#,
sync_writes = "by_key" sync_writes = "by_key"
)] )]
fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> { fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {

View file

@ -3,7 +3,7 @@ use std::collections::HashMap;
use miette::{Report, bail}; use miette::{Report, bail};
use serde::Deserialize; use serde::Deserialize;
use crate::drivers::types::{ImageMetadata, Platform}; use crate::drivers::types::{ImageMetadata, Platform, PlatformInfo};
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct Metadata { pub struct Metadata {
@ -48,10 +48,10 @@ pub struct Config {
labels: HashMap<String, serde_json::Value>, labels: HashMap<String, serde_json::Value>,
} }
impl TryFrom<(Metadata, Platform)> for ImageMetadata { impl TryFrom<(Metadata, Option<Platform>)> for ImageMetadata {
type Error = Report; type Error = Report;
fn try_from((metadata, platform): (Metadata, Platform)) -> Result<Self, Self::Error> { fn try_from((metadata, platform): (Metadata, Option<Platform>)) -> Result<Self, Self::Error> {
match metadata.image { match metadata.image {
MetadataImage::Single(image) => Ok(Self { MetadataImage::Single(image) => Ok(Self {
labels: image.config.labels, labels: image.config.labels,
@ -59,7 +59,10 @@ impl TryFrom<(Metadata, Platform)> for ImageMetadata {
}), }),
MetadataImage::Multi(mut platforms) => { MetadataImage::Multi(mut platforms) => {
let Some(image) = platforms.remove(&platform.to_string()) else { let Some(image) = platforms.remove(&platform.to_string()) else {
bail!("Image information does not exist for {platform}"); bail!(
"Image information does not exist for {}",
platform.to_string()
);
}; };
let Some(manifest) = metadata let Some(manifest) = metadata
.manifest .manifest
@ -67,7 +70,7 @@ impl TryFrom<(Metadata, Platform)> for ImageMetadata {
.into_iter() .into_iter()
.find(|manifest| manifest.platform.architecture == platform.arch()) .find(|manifest| manifest.platform.architecture == platform.arch())
else { else {
bail!("Manifest does not exist for {platform}"); bail!("Manifest does not exist for {}", platform.to_string());
}; };
Ok(Self { Ok(Self {
labels: image.config.labels, labels: image.config.labels,

View file

@ -41,7 +41,7 @@ impl CiDriver for GithubDriver {
let timestamp = blue_build_utils::get_tag_timestamp(); let timestamp = blue_build_utils::get_tag_timestamp();
let os_version = Driver::get_os_version() let os_version = Driver::get_os_version()
.oci_ref(opts.oci_ref) .oci_ref(opts.oci_ref)
.platform(opts.platform) .maybe_platform(opts.platform)
.call() .call()
.inspect(|v| trace!("os_version={v}"))?; .inspect(|v| trace!("os_version={v}"))?;
let ref_name = get_env_var(GITHUB_REF_NAME) let ref_name = get_env_var(GITHUB_REF_NAME)

View file

@ -49,7 +49,7 @@ impl CiDriver for GitlabDriver {
const MR_EVENT: &str = "merge_request_event"; const MR_EVENT: &str = "merge_request_event";
let os_version = Driver::get_os_version() let os_version = Driver::get_os_version()
.oci_ref(opts.oci_ref) .oci_ref(opts.oci_ref)
.platform(opts.platform) .maybe_platform(opts.platform)
.call()?; .call()?;
let timestamp = blue_build_utils::get_tag_timestamp(); let timestamp = blue_build_utils::get_tag_timestamp();
let short_sha = let short_sha =

View file

@ -26,7 +26,7 @@ impl CiDriver for LocalDriver {
trace!("LocalDriver::generate_tags({opts:?})"); trace!("LocalDriver::generate_tags({opts:?})");
let os_version = Driver::get_os_version() let os_version = Driver::get_os_version()
.oci_ref(opts.oci_ref) .oci_ref(opts.oci_ref)
.platform(opts.platform) .maybe_platform(opts.platform)
.call()?; .call()?;
let timestamp = blue_build_utils::get_tag_timestamp(); let timestamp = blue_build_utils::get_tag_timestamp();
let short_sha = commit_sha(); let short_sha = commit_sha();

View file

@ -20,8 +20,7 @@ pub struct BuildOpts<'scope> {
#[builder(into)] #[builder(into)]
pub containerfile: Cow<'scope, Path>, pub containerfile: Cow<'scope, Path>,
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
#[builder(default)] #[builder(default)]
pub host_network: bool, pub host_network: bool,
@ -102,8 +101,7 @@ pub struct BuildTagPushOpts<'scope> {
pub squash: bool, pub squash: bool,
/// The platform to build the image on. /// The platform to build the image on.
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
/// Runs the build with elevated privileges /// Runs the build with elevated privileges
#[builder(default)] #[builder(default)]

View file

@ -12,8 +12,7 @@ pub struct GenerateTagsOpts<'scope> {
#[builder(into)] #[builder(into)]
pub alt_tags: Option<Vec<Cow<'scope, str>>>, pub alt_tags: Option<Vec<Cow<'scope, str>>>,
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
} }
#[derive(Debug, Clone, Builder)] #[derive(Debug, Clone, Builder)]

View file

@ -9,6 +9,5 @@ pub struct GetMetadataOpts<'scope> {
#[builder(into)] #[builder(into)]
pub image: &'scope Reference, pub image: &'scope Reference,
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
} }

View file

@ -16,8 +16,7 @@ pub struct RechunkOpts<'scope> {
#[builder(into)] #[builder(into)]
pub containerfile: Cow<'scope, Path>, pub containerfile: Cow<'scope, Path>,
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
pub version: Cow<'scope, str>, pub version: Cow<'scope, str>,
pub name: Cow<'scope, str>, pub name: Cow<'scope, str>,
pub description: Cow<'scope, str>, pub description: Cow<'scope, str>,

View file

@ -114,6 +114,5 @@ pub struct SignVerifyOpts<'scope> {
#[builder(default = 1)] #[builder(default = 1)]
pub retry_count: u8, pub retry_count: u8,
#[builder(default)] pub platform: Option<Platform>,
pub platform: Platform,
} }

View file

@ -28,7 +28,7 @@ use crate::{
drivers::{ drivers::{
BuildDriver, DriverVersion, InspectDriver, RunDriver, BuildDriver, DriverVersion, InspectDriver, RunDriver,
opts::{BuildOpts, GetMetadataOpts, PushOpts, RunOpts, RunOptsEnv, RunOptsVolume, TagOpts}, opts::{BuildOpts, GetMetadataOpts, PushOpts, RunOpts, RunOptsEnv, RunOptsVolume, TagOpts},
types::{ImageMetadata, Platform}, types::ImageMetadata,
}, },
logging::{CommandLogging, Logger}, logging::{CommandLogging, Logger},
signal_handler::{ContainerRuntime, ContainerSignalId, add_cid, remove_cid}, signal_handler::{ContainerRuntime, ContainerSignalId, add_cid, remove_cid},
@ -158,9 +158,9 @@ impl BuildDriver for PodmanDriver {
"podman", "podman",
], ],
"build", "build",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--platform", "--platform",
opts.platform.to_string(), platform.to_string(),
], ],
if let Some(cache_from) = opts.cache_from.as_ref() => [ if let Some(cache_from) = opts.cache_from.as_ref() => [
"--cache-from", "--cache-from",
@ -347,7 +347,7 @@ impl InspectDriver for PodmanDriver {
#[cached( #[cached(
result = true, result = true,
key = "String", key = "String",
convert = r#"{ format!("{}-{}", opts.image, opts.platform)}"#, convert = r#"{ format!("{}-{:?}", opts.image, opts.platform)}"#,
sync_writes = "by_key" sync_writes = "by_key"
)] )]
fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> { fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
@ -369,9 +369,9 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
let c = cmd!( let c = cmd!(
"podman", "podman",
"pull", "pull",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--platform", "--platform",
opts.platform.to_string(), platform.to_string(),
], ],
&image_str, &image_str,
); );

View file

@ -23,7 +23,7 @@ impl InspectDriver for SkopeoDriver {
#[cached( #[cached(
result = true, result = true,
key = "String", key = "String",
convert = r#"{ format!("{}-{}", opts.image, opts.platform)}"#, convert = r#"{ format!("{}-{:?}", opts.image, opts.platform)}"#,
sync_writes = "by_key" sync_writes = "by_key"
)] )]
fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> { fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
@ -40,9 +40,13 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
let mut command = cmd!( let mut command = cmd!(
"skopeo", "skopeo",
if !matches!(opts.platform, Platform::Native) => [ if let Some(platform) = opts.platform => [
"--override-arch", "--override-arch",
opts.platform.arch(), platform.arch(),
],
if let Some(variant) = opts.platform.as_ref().and_then(Platform::variant) => [
"--override-variant",
variant,
], ],
"inspect", "inspect",
format!("docker://{image_str}"), format!("docker://{image_str}"),

View file

@ -124,7 +124,7 @@ pub trait BuildDriver: PrivateDriver {
let build_opts = BuildOpts::builder() let build_opts = BuildOpts::builder()
.image(&opts.image) .image(&opts.image)
.containerfile(opts.containerfile.as_ref()) .containerfile(opts.containerfile.as_ref())
.platform(opts.platform) .maybe_platform(opts.platform)
.squash(opts.squash) .squash(opts.squash)
.maybe_cache_from(opts.cache_from) .maybe_cache_from(opts.cache_from)
.maybe_cache_to(opts.cache_to) .maybe_cache_to(opts.cache_to)
@ -286,7 +286,7 @@ pub trait RechunkDriver: RunDriver + BuildDriver + ContainerMountDriver {
&BuildOpts::builder() &BuildOpts::builder()
.image(raw_image) .image(raw_image)
.containerfile(&*opts.containerfile) .containerfile(&*opts.containerfile)
.platform(opts.platform) .maybe_platform(opts.platform)
.privileged(true) .privileged(true)
.squash(true) .squash(true)
.host_network(true) .host_network(true)
@ -562,7 +562,7 @@ pub trait SigningDriver: PrivateDriver {
let image_digest = Driver::get_metadata( let image_digest = Driver::get_metadata(
&GetMetadataOpts::builder() &GetMetadataOpts::builder()
.image(opts.image) .image(opts.image)
.platform(opts.platform) .maybe_platform(opts.platform)
.build(), .build(),
)? )?
.digest; .digest;

View file

@ -8,6 +8,7 @@ use blue_build_utils::{
constants::{GITHUB_ACTIONS, GITLAB_CI, IMAGE_VERSION_LABEL}, constants::{GITHUB_ACTIONS, GITLAB_CI, IMAGE_VERSION_LABEL},
get_env_var, get_env_var,
semver::Version, semver::Version,
string,
}; };
use clap::ValueEnum; use clap::ValueEnum;
use log::{trace, warn}; use log::{trace, warn};
@ -20,6 +21,10 @@ use crate::drivers::{
podman_driver::PodmanDriver, podman_driver::PodmanDriver,
}; };
mod private {
pub trait Private {}
}
pub(super) trait DetermineDriver<T> { pub(super) trait DetermineDriver<T> {
fn determine_driver(&mut self) -> T; fn determine_driver(&mut self) -> T;
} }
@ -178,30 +183,86 @@ impl DetermineDriver<CiDriverType> for Option<CiDriverType> {
} }
} }
#[derive(Debug, Default, Clone, Copy, ValueEnum, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Hash)]
pub enum Platform { pub enum Platform {
#[default]
#[value(name = "native")]
Native,
#[value(name = "linux/amd64")] #[value(name = "linux/amd64")]
LinuxAmd64, LinuxAmd64,
#[value(name = "linux/amd64/v2")]
LinuxAmd64V2,
#[value(name = "linux/arm64")] #[value(name = "linux/arm64")]
LinuxArm64, LinuxArm64,
#[value(name = "linux/arm")]
LinuxArm,
#[value(name = "linux/arm/v6")]
LinuxArmV6,
#[value(name = "linux/arm/v7")]
LinuxArmV7,
#[value(name = "linux/386")]
Linux386,
#[value(name = "linux/loong64")]
LinuxLoong64,
#[value(name = "linux/mips")]
LinuxMips,
#[value(name = "linux/mipsle")]
LinuxMipsle,
#[value(name = "linux/mips64")]
LinuxMips64,
#[value(name = "linux/mips64le")]
LinuxMips64le,
#[value(name = "linux/ppc64")]
LinuxPpc64,
#[value(name = "linux/ppc64le")]
LinuxPpc64le,
#[value(name = "linux/riscv64")]
LinuxRiscv64,
#[value(name = "linux/s390x")]
LinuxS390x,
} }
impl Platform { impl Platform {
/// The architecture of the platform. /// The architecture of the platform.
#[must_use] #[must_use]
pub fn arch(&self) -> &str { pub const fn arch(&self) -> &str {
match *self { match *self {
Self::Native => match std::env::consts::ARCH { Self::LinuxAmd64 | Self::LinuxAmd64V2 => "amd64",
"x86_64" => "amd64",
"aarch64" => "arm64",
arch => unimplemented!("Arch {arch} is unsupported"),
},
Self::LinuxAmd64 => "amd64",
Self::LinuxArm64 => "arm64", Self::LinuxArm64 => "arm64",
Self::LinuxArm | Self::LinuxArmV6 | Self::LinuxArmV7 => "arm",
Self::Linux386 => "386",
Self::LinuxLoong64 => "loong64",
Self::LinuxMips => "mips",
Self::LinuxMipsle => "mipsle",
Self::LinuxMips64 => "mips64",
Self::LinuxMips64le => "mips64le",
Self::LinuxPpc64 => "ppc64",
Self::LinuxPpc64le => "ppc64le",
Self::LinuxRiscv64 => "riscv64",
Self::LinuxS390x => "s390x",
}
}
/// The variant of the platform.
#[must_use]
pub const fn variant(&self) -> Option<&str> {
match *self {
Self::LinuxAmd64V2 => Some("v2"),
Self::LinuxArmV6 => Some("v6"),
Self::LinuxArmV7 => Some("v7"),
_ => None,
} }
} }
} }
@ -212,18 +273,65 @@ impl std::fmt::Display for Platform {
f, f,
"{}", "{}",
match *self { match *self {
Self::Native => match std::env::consts::ARCH {
"x86_64" => "linux/amd64",
"aarch64" => "linux/arm64",
arch => unimplemented!("Arch {arch} is unsupported"),
},
Self::LinuxAmd64 => "linux/amd64", Self::LinuxAmd64 => "linux/amd64",
Self::LinuxAmd64V2 => "linux/amd64/v2",
Self::LinuxArm64 => "linux/arm64", Self::LinuxArm64 => "linux/arm64",
Self::LinuxArm => "linux/arm",
Self::LinuxArmV6 => "linux/arm/v6",
Self::LinuxArmV7 => "linux/arm/v7",
Self::Linux386 => "linux/386",
Self::LinuxLoong64 => "linux/loong64",
Self::LinuxMips => "linux/mips",
Self::LinuxMipsle => "linux/mipsle",
Self::LinuxMips64 => "linux/mips64",
Self::LinuxMips64le => "linux/mips64le",
Self::LinuxPpc64 => "linux/ppc64",
Self::LinuxPpc64le => "linux/ppc64le",
Self::LinuxRiscv64 => "linux/riscv64",
Self::LinuxS390x => "linux/s390x",
} }
) )
} }
} }
impl private::Private for Option<Platform> {}
pub trait PlatformInfo: private::Private {
/// The string representation of the platform.
///
/// If `None`, then the native architecture will be used.
fn to_string(&self) -> String;
/// The string representation of the architecture.
///
/// If `None`, then the native architecture will be used.
fn arch(&self) -> &str;
}
impl PlatformInfo for Option<Platform> {
fn to_string(&self) -> String {
self.map_or_else(
|| match std::env::consts::ARCH {
"x86_64" => string!("linux/amd64"),
"aarch64" => string!("linux/arm64"),
arch => unimplemented!("Arch {arch} is unsupported"),
},
|platform| format!("{platform}"),
)
}
fn arch(&self) -> &str {
self.as_ref().map_or_else(
|| match std::env::consts::ARCH {
"x86_64" => "amd64",
"aarch64" => "arm64",
arch => unimplemented!("Arch {arch} is unsupported"),
},
Platform::arch,
)
}
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub struct ImageMetadata { pub struct ImageMetadata {

View file

@ -57,9 +57,8 @@ pub struct BuildCommand {
/// than your hardware will require installing /// than your hardware will require installing
/// qemu. Build times will be much greater when /// qemu. Build times will be much greater when
/// building for a non-native architecture. /// building for a non-native architecture.
#[arg(long, default_value = "native")] #[arg(long)]
#[builder(default)] platform: Option<Platform>,
platform: Platform,
/// The compression format the images /// The compression format the images
/// will be pushed in. /// will be pushed in.
@ -198,7 +197,7 @@ impl BlueBuildCommand for BuildCommand {
PathBuf::from(CONTAINER_FILE) PathBuf::from(CONTAINER_FILE)
})) }))
.skip_validation(self.skip_validation) .skip_validation(self.skip_validation)
.platform(self.platform) .maybe_platform(self.platform)
.recipe(recipe) .recipe(recipe)
.drivers(self.drivers) .drivers(self.drivers)
.build() .build()
@ -249,7 +248,7 @@ impl BuildCommand {
&GenerateTagsOpts::builder() &GenerateTagsOpts::builder()
.oci_ref(&recipe.base_image_ref()?) .oci_ref(&recipe.base_image_ref()?)
.maybe_alt_tags(recipe.alt_tags.as_ref().map(CowCollecter::collect_cow_vec)) .maybe_alt_tags(recipe.alt_tags.as_ref().map(CowCollecter::collect_cow_vec))
.platform(self.platform) .maybe_platform(self.platform)
.build(), .build(),
)?; )?;
let image_name = self.image_name(&recipe)?; let image_name = self.image_name(&recipe)?;
@ -283,7 +282,7 @@ impl BuildCommand {
BuildTagPushOpts::builder() BuildTagPushOpts::builder()
.image(&image) .image(&image)
.containerfile(containerfile) .containerfile(containerfile)
.platform(self.platform) .maybe_platform(self.platform)
.tags(tags.collect_cow_vec()) .tags(tags.collect_cow_vec())
.push(self.push) .push(self.push)
.retry_push(self.retry_push) .retry_push(self.retry_push)
@ -298,7 +297,7 @@ impl BuildCommand {
|archive_dir| { |archive_dir| {
BuildTagPushOpts::builder() BuildTagPushOpts::builder()
.containerfile(containerfile) .containerfile(containerfile)
.platform(self.platform) .maybe_platform(self.platform)
.image(PathBuf::from(format!( .image(PathBuf::from(format!(
"{}/{}.{ARCHIVE_SUFFIX}", "{}/{}.{ARCHIVE_SUFFIX}",
archive_dir.to_string_lossy().trim_end_matches('/'), archive_dir.to_string_lossy().trim_end_matches('/'),
@ -319,7 +318,7 @@ impl BuildCommand {
.image(&image) .image(&image)
.retry_push(self.retry_push) .retry_push(self.retry_push)
.retry_count(self.retry_count) .retry_count(self.retry_count)
.platform(self.platform) .maybe_platform(self.platform)
.build(), .build(),
)?; )?;
} }
@ -346,14 +345,14 @@ impl BuildCommand {
&RechunkOpts::builder() &RechunkOpts::builder()
.image(image_name) .image(image_name)
.containerfile(containerfile) .containerfile(containerfile)
.platform(self.platform) .maybe_platform(self.platform)
.tags(tags.collect_cow_vec()) .tags(tags.collect_cow_vec())
.push(self.push) .push(self.push)
.version(format!( .version(format!(
"{version}.<date>", "{version}.<date>",
version = Driver::get_os_version() version = Driver::get_os_version()
.oci_ref(&recipe.base_image_ref()?) .oci_ref(&recipe.base_image_ref()?)
.platform(self.platform) .maybe_platform(self.platform)
.call()?, .call()?,
)) ))
.retry_push(self.retry_push) .retry_push(self.retry_push)
@ -363,7 +362,7 @@ impl BuildCommand {
Driver::get_metadata( Driver::get_metadata(
&GetMetadataOpts::builder() &GetMetadataOpts::builder()
.image(&base_image) .image(&base_image)
.platform(self.platform) .maybe_platform(self.platform)
.build(), .build(),
)? )?
.digest, .digest,

View file

@ -73,8 +73,7 @@ pub struct GenerateCommand {
/// Inspect the image for a specific platform /// Inspect the image for a specific platform
/// when retrieving the version. /// when retrieving the version.
#[arg(long, default_value = "native")] #[arg(long, default_value = "native")]
#[builder(default)] platform: Option<Platform>,
platform: Platform,
/// Skips validation of the recipe file. /// Skips validation of the recipe file.
#[arg(long, env = BB_SKIP_VALIDATION)] #[arg(long, env = BB_SKIP_VALIDATION)]
@ -148,7 +147,7 @@ impl GenerateCommand {
.os_version( .os_version(
Driver::get_os_version() Driver::get_os_version()
.oci_ref(&recipe.base_image_ref()?) .oci_ref(&recipe.base_image_ref()?)
.platform(self.platform) .maybe_platform(self.platform)
.call()?, .call()?,
) )
.build_id(Driver::get_build_id()) .build_id(Driver::get_build_id())
@ -161,7 +160,7 @@ impl GenerateCommand {
Driver::get_metadata( Driver::get_metadata(
&GetMetadataOpts::builder() &GetMetadataOpts::builder()
.image(&base_image) .image(&base_image)
.platform(self.platform) .maybe_platform(self.platform)
.build(), .build(),
)? )?
.digest, .digest,
@ -186,14 +185,14 @@ impl GenerateCommand {
#[cached( #[cached(
result = true, result = true,
key = "Platform", key = "Option<Platform>",
convert = r#"{ platform }"#, convert = r#"{ platform }"#,
sync_writes = "by_key" sync_writes = "by_key"
)] )]
fn determine_scripts_tag(platform: Platform) -> Result<Reference> { fn determine_scripts_tag(platform: Option<Platform>) -> Result<Reference> {
trace!("determine_scripts_tag({platform:?})"); trace!("determine_scripts_tag({platform:?})");
let opts = GetMetadataOpts::builder().platform(platform); let opts = GetMetadataOpts::builder().maybe_platform(platform);
format!("{BUILD_SCRIPTS_IMAGE_REF}:{}", shadow::COMMIT_HASH) format!("{BUILD_SCRIPTS_IMAGE_REF}:{}", shadow::COMMIT_HASH)
.parse() .parse()
.into_diagnostic() .into_diagnostic()