diff --git a/README.md b/README.md index 1e280994..849e590b 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ impl Buildpack for HelloWorldBuildpack { // build phase (`bin/build`). fn build(&self, context: BuildContext) -> libcnb::Result { println!("Hello World!"); - println!("The build is running on: {} ({})!", context.target_os, context.target_arch); + println!("The build is running on: {} ({})!", context.target.os, context.target.arch); BuildResultBuilder::new() .launch( diff --git a/examples/basics/src/main.rs b/examples/basics/src/main.rs index b6d99a16..e7287ec1 100644 --- a/examples/basics/src/main.rs +++ b/examples/basics/src/main.rs @@ -17,7 +17,7 @@ impl Buildpack for BasicBuildpack { fn build(&self, context: BuildContext) -> libcnb::Result { println!( "Build runs on: {} ({})!", - context.target_os, context.target_arch + context.target.os, context.target.arch ); BuildResultBuilder::new().build() diff --git a/libcnb/src/build.rs b/libcnb/src/build.rs index c1dc8419..0c14a128 100644 --- a/libcnb/src/build.rs +++ b/libcnb/src/build.rs @@ -8,6 +8,7 @@ use crate::data::{ }; use crate::layer::{HandleLayerErrorOrBuildpackError, Layer, LayerData}; use crate::sbom::Sbom; +use crate::target::ContextTarget; use std::path::PathBuf; /// Context for the build phase execution. @@ -15,40 +16,7 @@ pub struct BuildContext { pub layers_dir: PathBuf, pub app_dir: PathBuf, pub buildpack_dir: PathBuf, - /// The name of the target operating system. - /// - /// The value should conform to [Go's `$GOOS`](https://golang.org/doc/install/source#environment), for example - /// `linux` or `windows`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`os` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - pub target_os: String, - /// The name of the target CPU architecture. - /// - /// The value should conform to [Go's $GOARCH](https://golang.org/doc/install/source#environment), for example - /// `amd64` or `arm64`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`architecture` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - /// `` - pub target_arch: String, - /// The variant of the specified CPU architecture. - /// - /// The value should conform to [OCI image spec platform variants](https://github.com/opencontainers/image-spec/blob/main/image-index.md#platform-variants), for example - /// `v7` or `v8`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`variant` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - pub target_arch_variant: Option, - /// The name of the operating system distribution. Should be empty for windows. - /// - /// For example: `ubuntu` or `arch`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.name` label. - pub target_distro_name: Option, - /// The version of the operating system distribution. - /// - /// For example: `18.02` or `2024.02.01`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.version` label. - pub target_distro_version: Option, + pub target: ContextTarget, pub platform: B::Platform, pub buildpack_plan: BuildpackPlan, pub buildpack_descriptor: ComponentBuildpackDescriptor, diff --git a/libcnb/src/detect.rs b/libcnb/src/detect.rs index c3af7c38..6fa8a452 100644 --- a/libcnb/src/detect.rs +++ b/libcnb/src/detect.rs @@ -1,6 +1,7 @@ //! Provides detect phase specific types and helpers. use crate::buildpack::Buildpack; +use crate::target::ContextTarget; use crate::{data::build_plan::BuildPlan, data::buildpack::ComponentBuildpackDescriptor}; use std::fmt::Debug; use std::path::PathBuf; @@ -9,40 +10,7 @@ use std::path::PathBuf; pub struct DetectContext { pub app_dir: PathBuf, pub buildpack_dir: PathBuf, - /// The name of the target operating system. - /// - /// The value should conform to [Go's `$GOOS`](https://golang.org/doc/install/source#environment), for example - /// `linux` or `windows`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`os` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - pub target_os: String, - /// The name of the target CPU architecture. - /// - /// The value should conform to [Go's $GOARCH](https://golang.org/doc/install/source#environment), for example - /// `amd64` or `arm64`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`architecture` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - /// `` - pub target_arch: String, - /// The variant of the specified CPU architecture. - /// - /// The value should conform to [OCI image spec platform variants](https://github.com/opencontainers/image-spec/blob/main/image-index.md#platform-variants), for example - /// `v7` or `v8`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's [`variant` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). - pub target_arch_variant: Option, - /// The name of the operating system distribution. Should be empty for windows. - /// - /// For example: `ubuntu` or `arch`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.name` label. - pub target_distro_name: Option, - /// The version of the operating system distribution. - /// - /// For example: `18.02` or `2024.02.01`. - /// - /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.version` label. - pub target_distro_version: Option, + pub target: ContextTarget, pub platform: B::Platform, pub buildpack_descriptor: ComponentBuildpackDescriptor, } diff --git a/libcnb/src/layer/tests.rs b/libcnb/src/layer/tests.rs index 85d23ecb..a22da020 100644 --- a/libcnb/src/layer/tests.rs +++ b/libcnb/src/layer/tests.rs @@ -19,6 +19,7 @@ use crate::layer::{ MetadataMigration, }; use crate::layer_env::{LayerEnv, ModificationBehavior, Scope}; +use crate::target::ContextTarget; use crate::{read_toml_file, Buildpack, Env, LIBCNB_SUPPORTED_BUILDPACK_API}; use libcnb_data::buildpack::{BuildpackVersion, ComponentBuildpackDescriptor, Target}; use libcnb_data::buildpack_plan::BuildpackPlan; @@ -901,11 +902,13 @@ fn build_context(temp_dir: &TempDir) -> BuildContext { layers_dir, app_dir, buildpack_dir, - target_os: String::from("linux"), - target_arch: String::from("amd64"), - target_arch_variant: None, - target_distro_name: Some(String::from("ubuntu")), - target_distro_version: Some(String::from("22.04")), + target: ContextTarget { + os: String::from("linux"), + arch: String::from("amd64"), + arch_variant: None, + distro_name: Some(String::from("ubuntu")), + distro_version: Some(String::from("22.04")), + }, platform: GenericPlatform::new(Env::new()), buildpack_plan: BuildpackPlan { entries: Vec::new(), diff --git a/libcnb/src/lib.rs b/libcnb/src/lib.rs index 4488f3ea..f0287f54 100644 --- a/libcnb/src/lib.rs +++ b/libcnb/src/lib.rs @@ -18,6 +18,7 @@ mod error; mod exit_code; mod platform; mod runtime; +mod target; #[cfg(feature = "trace")] mod tracing; mod util; diff --git a/libcnb/src/runtime.rs b/libcnb/src/runtime.rs index d646d0cd..133fc9bf 100644 --- a/libcnb/src/runtime.rs +++ b/libcnb/src/runtime.rs @@ -5,6 +5,7 @@ use crate::detect::{DetectContext, InnerDetectResult}; use crate::error::Error; use crate::platform::Platform; use crate::sbom::cnb_sbom_path; +use crate::target::ContextTarget; #[cfg(feature = "trace")] use crate::tracing::start_trace; use crate::util::is_not_found_error_kind; @@ -138,7 +139,7 @@ pub fn libcnb_runtime_detect( }; #[cfg(not(feature = "trace"))] - let trace_error = |_: &dyn std::error::Error| {}; + let mut trace_error = |_: &dyn std::error::Error| {}; let platform = B::Platform::from_path(&args.platform_dir_path) .map_err(Error::CannotCreatePlatformFromPath) @@ -146,32 +147,12 @@ pub fn libcnb_runtime_detect( let build_plan_path = args.build_plan_path; - let target_os = env::var("CNB_TARGET_OS") - .map_err(Error::CannotDetermineTargetOs) - .map_err(|err| { - trace_error(&err); - err - })?; - - let target_arch = env::var("CNB_TARGET_ARCH") - .map_err(Error::CannotDetermineTargetArch) - .map_err(|err| { - trace_error(&err); - err - })?; - - let target_arch_variant = env::var("CNB_TARGET_ARCH_VARIANT").ok(); - let target_distro_name = env::var("CNB_TARGET_DISTRO_NAME").ok(); - let target_distro_version = env::var("CNB_TARGET_DISTRO_VERSION").ok(); + let target = context_target().inspect_err(|err| trace_error(err))?; let detect_context = DetectContext { app_dir, buildpack_dir, - target_os, - target_arch, - target_arch_variant, - target_distro_name, - target_distro_version, + target, platform, buildpack_descriptor, }; @@ -226,7 +207,7 @@ pub fn libcnb_runtime_build( }; #[cfg(not(feature = "trace"))] - let trace_error = |_: &dyn std::error::Error| {}; + let mut trace_error = |_: &dyn std::error::Error| {}; let platform = Platform::from_path(&args.platform_dir_path) .map_err(Error::CannotCreatePlatformFromPath) @@ -243,33 +224,13 @@ pub fn libcnb_runtime_build( .map_err(Error::CannotReadStore) .inspect_err(|err| trace_error(err))?; - let target_os = env::var("CNB_TARGET_OS") - .map_err(Error::CannotDetermineTargetOs) - .map_err(|err| { - trace_error(&err); - err - })?; - - let target_arch = env::var("CNB_TARGET_ARCH") - .map_err(Error::CannotDetermineTargetArch) - .map_err(|err| { - trace_error(&err); - err - })?; - - let target_arch_variant = env::var("CNB_TARGET_ARCH_VARIANT").ok(); - let target_distro_name = env::var("CNB_TARGET_DISTRO_NAME").ok(); - let target_distro_version = env::var("CNB_TARGET_DISTRO_VERSION").ok(); + let target = context_target().inspect_err(|err| trace_error(err))?; let build_context = BuildContext { layers_dir: layers_dir.clone(), app_dir, platform, - target_os, - target_arch, - target_arch_variant, - target_distro_name, - target_distro_version, + target, buildpack_plan, buildpack_dir, buildpack_descriptor, @@ -396,3 +357,22 @@ fn read_buildpack_descriptor() -> crate::Result< .map_err(Error::CannotReadBuildpackDescriptor) }) } + +fn context_target() -> crate::Result +where + E: Debug, +{ + let os = env::var("CNB_TARGET_OS").map_err(Error::CannotDetermineTargetOs)?; + let arch = env::var("CNB_TARGET_ARCH").map_err(Error::CannotDetermineTargetArch)?; + let arch_variant = env::var("CNB_TARGET_ARCH_VARIANT").ok(); + let distro_name = env::var("CNB_TARGET_DISTRO_NAME").ok(); + let distro_version = env::var("CNB_TARGET_DISTRO_VERSION").ok(); + + Ok(ContextTarget { + os, + arch, + arch_variant, + distro_name, + distro_version, + }) +} diff --git a/libcnb/src/target.rs b/libcnb/src/target.rs new file mode 100644 index 00000000..7ec79a53 --- /dev/null +++ b/libcnb/src/target.rs @@ -0,0 +1,36 @@ +pub struct ContextTarget { + /// The name of the target operating system. + /// + /// The value should conform to [Go's `$GOOS`](https://golang.org/doc/install/source#environment), for example + /// `linux` or `windows`. + /// + /// CNB `lifecycle` sources this value from the build OCI image's [`os` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). + pub os: String, + /// The name of the target CPU architecture. + /// + /// The value should conform to [Go's $GOARCH](https://golang.org/doc/install/source#environment), for example + /// `amd64` or `arm64`. + /// + /// CNB `lifecycle` sources this value from the build OCI image's [`architecture` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). + /// `` + pub arch: String, + /// The variant of the specified CPU architecture. + /// + /// The value should conform to [OCI image spec platform variants](https://github.com/opencontainers/image-spec/blob/main/image-index.md#platform-variants), for example + /// `v7` or `v8`. + /// + /// CNB `lifecycle` sources this value from the build OCI image's [`variant` property](https://github.com/opencontainers/image-spec/blob/main/config.md#properties). + pub arch_variant: Option, + /// The name of the operating system distribution. Should be empty for windows. + /// + /// For example: `ubuntu` or `arch`. + /// + /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.name` label. + pub distro_name: Option, + /// The version of the operating system distribution. + /// + /// For example: `18.02` or `2024.02.01`. + /// + /// CNB `lifecycle` sources this value from the build OCI image's `io.buildpacks.distro.version` label. + pub distro_version: Option, +}