diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c3ff5d8..2fbfc5e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,19 +95,3 @@ jobs: run: pack build my-image --force-color --builder heroku/builder:24 --trust-extra-buildpacks --buildpack heroku/nodejs-engine --buildpack packaged/${{ matrix.target }}/debug/heroku_ruby --path tmp/ruby-getting-started --pull-policy never - name: "PRINT: Cached getting started guide output" run: pack build my-image --force-color --builder heroku/builder:24 --trust-extra-buildpacks --buildpack heroku/nodejs-engine --buildpack packaged/${{ matrix.target }}/debug/heroku_ruby --path tmp/ruby-getting-started --pull-policy never - - print-style-guide: - runs-on: ubuntu-24.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install musl-tools - run: sudo apt-get install musl-tools --no-install-recommends - - name: Update Rust toolchain - run: rustup update - - name: Install Rust linux-musl target - run: rustup target add x86_64-unknown-linux-musl - - name: Rust Cache - uses: Swatinem/rust-cache@v2.7.3 - - name: "PRINT: Style guide" - run: cargo run --quiet --bin print_style_guide diff --git a/buildpacks/ruby/src/install_ruby.rs b/buildpacks/ruby/src/install_ruby.rs index e69de29b..8b137891 100644 --- a/buildpacks/ruby/src/install_ruby.rs +++ b/buildpacks/ruby/src/install_ruby.rs @@ -0,0 +1 @@ + diff --git a/buildpacks/ruby/src/layers/bundle_install_layer.rs b/buildpacks/ruby/src/layers/bundle_install_layer.rs index 7432eb16..90d65e33 100644 --- a/buildpacks/ruby/src/layers/bundle_install_layer.rs +++ b/buildpacks/ruby/src/layers/bundle_install_layer.rs @@ -203,8 +203,6 @@ enum UpdateState { } /// Determines if 'bundle install' should execute on a given call to `BundleInstallLatyer::update` -/// -/// fn update_state(old: &BundleInstallLayerMetadata, now: &BundleInstallLayerMetadata) -> UpdateState { let forced_env = std::env::var_os(HEROKU_SKIP_BUNDLE_DIGEST); let old_key = &old.force_bundle_install_key; diff --git a/buildpacks/ruby/src/layers/ruby_install_layer.rs b/buildpacks/ruby/src/layers/ruby_install_layer.rs index 5ba2b0a9..25c4448e 100644 --- a/buildpacks/ruby/src/layers/ruby_install_layer.rs +++ b/buildpacks/ruby/src/layers/ruby_install_layer.rs @@ -10,8 +10,7 @@ use flate2::read::GzDecoder; use libcnb::build::BuildContext; use libcnb::data::layer_name; use libcnb::layer::{ - CachedLayerDefinition, EmptyLayerCause, IntoAction, InvalidMetadataAction, LayerState, - RestoredLayerAction, + CachedLayerDefinition, EmptyLayerCause, IntoAction, LayerState, RestoredLayerAction, }; use libcnb::layer_env::LayerEnv; use magic_migrate::{try_migrate_deserializer_chain, TryMigrate}; diff --git a/buildpacks/ruby/src/main.rs b/buildpacks/ruby/src/main.rs index ec9b3f1c..eebd0e68 100644 --- a/buildpacks/ruby/src/main.rs +++ b/buildpacks/ruby/src/main.rs @@ -299,9 +299,6 @@ buildpack_main!(RubyBuildpack); struct BundleWithout(String); impl BundleWithout { - fn new(without: impl AsRef) -> Self { - Self(String::from(without.as_ref())) - } fn as_str(&self) -> &str { &self.0 } diff --git a/buildpacks/ruby/src/steps/default_env.rs b/buildpacks/ruby/src/steps/default_env.rs index d4599189..7e68f42e 100644 --- a/buildpacks/ruby/src/steps/default_env.rs +++ b/buildpacks/ruby/src/steps/default_env.rs @@ -1,5 +1,6 @@ use crate::{RubyBuildpack, RubyBuildpackError}; -use commons::layer::DefaultEnvLayer; +use libcnb::layer::UncachedLayerDefinition; +use libcnb::layer_env::{LayerEnv, ModificationBehavior}; use libcnb::{ build::BuildContext, data::{layer_name, store::Store}, @@ -23,25 +24,32 @@ pub(crate) fn default_env( } let (default_secret_key_base, store) = fetch_secret_key_base_from_store(&context.store); + let env_defaults_layer = context.uncached_layer( + layer_name!("env_default"), + UncachedLayerDefinition { + build: true, + launch: true, + }, + )?; - let env_defaults_layer = context // - .handle_layer( - layer_name!("env_defaults"), - DefaultEnvLayer::new( - [ - ("SECRET_KEY_BASE", default_secret_key_base.as_str()), - ("JRUBY_OPTS", "-Xcompile.invokedynamic=false"), - ("RACK_ENV", "production"), - ("RAILS_ENV", "production"), - ("RAILS_SERVE_STATIC_FILES", "enabled"), - ("RAILS_LOG_TO_STDOUT", "enabled"), - ("MALLOC_ARENA_MAX", "2"), - ("DISABLE_SPRING", "1"), - ] - .into_iter(), - ), - )?; - env = env_defaults_layer.env.apply(Scope::Build, &env); + let mut layer_env = LayerEnv::new(); + for (key, value) in [ + ("SECRET_KEY_BASE", default_secret_key_base.as_str()), + ("JRUBY_OPTS", "-Xcompile.invokedynamic=false"), + ("RACK_ENV", "production"), + ("RAILS_ENV", "production"), + ("RAILS_SERVE_STATIC_FILES", "enabled"), + ("RAILS_LOG_TO_STDOUT", "enabled"), + ("MALLOC_ARENA_MAX", "2"), + ("DISABLE_SPRING", "1"), + ] { + layer_env = + layer_env.chainable_insert(Scope::All, ModificationBehavior::Default, key, value); + } + + env_defaults_layer.write_env(&layer_env)?; + + let env = env_defaults_layer.read_env()?.apply(Scope::Build, &env); Ok((env, store)) } diff --git a/buildpacks/ruby/src/user_errors.rs b/buildpacks/ruby/src/user_errors.rs index bf8ffc78..900fdc3b 100644 --- a/buildpacks/ruby/src/user_errors.rs +++ b/buildpacks/ruby/src/user_errors.rs @@ -360,7 +360,7 @@ fn debug_cmd(mut bullet: Print>, command: &mut Command) -> Pri match result { Ok(_) => bullet.done(), - Err(e) => bullet.sub_bullet(&e.to_string()).done(), + Err(e) => bullet.sub_bullet(e.to_string()).done(), } } diff --git a/commons/Cargo.toml b/commons/Cargo.toml index 79a1128c..723a8a6b 100644 --- a/commons/Cargo.toml +++ b/commons/Cargo.toml @@ -4,10 +4,6 @@ edition.workspace = true rust-version.workspace = true version = "1.1.0" -[[bin]] -name = "print_style_guide" -path = "bin/print_style_guide.rs" - [lints] workspace = true diff --git a/commons/bin/print_style_guide.rs b/commons/bin/print_style_guide.rs deleted file mode 100644 index b180b350..00000000 --- a/commons/bin/print_style_guide.rs +++ /dev/null @@ -1,216 +0,0 @@ -// Required due to: https://github.com/rust-lang/rust/issues/95513 -#![allow(unused_crate_dependencies)] - -use ascii_table::AsciiTable; -use commons::output::fmt::{self, DEBUG_INFO, HELP}; -#[allow(clippy::wildcard_imports)] -use commons::output::{ - build_log::*, - section_log::{log_step, log_step_stream, log_step_timed}, -}; -use fun_run::CommandWithName; -use indoc::formatdoc; -use std::io::stdout; -use std::process::Command; - -#[allow(clippy::too_many_lines)] -fn main() { - println!( - "{}", - formatdoc! {" - - Living build output style guide - =============================== - "} - ); - - { - let mut log = BuildLog::new(stdout()).buildpack_name("Section logging features"); - log = log - .section("Section heading example") - .step("step example") - .step("step example two") - .end_section(); - - log = log - .section("Section and step description") - .step( - "A section should be a noun i.e. 'Ruby Version', consider this the section topic.", - ) - .step("A step should be a verb i.e. 'Downloading'") - .step("Related verbs should be nested under a single section") - .step( - formatdoc! {" - Steps can be multiple lines long - However they're best as short, factual, - descriptions of what the program is doing. - "} - .trim(), - ) - .step("Prefer a single line when possible") - .step("Sections and steps are sentence cased with no ending puncuation") - .step(&format!("{HELP} capitalize the first letter")) - .end_section(); - - let mut command = Command::new("bash"); - command.args(["-c", "ps aux | grep cargo"]); - - let mut stream = log.section("Timer steps") - .step("Long running code should execute with a timer printing to the UI, to indicate the progam did not hang.") - .step("Example:") - .step_timed("Background progress timer") - .finish_timed_step() - .step("Output can be streamed. Mostly from commands. Example:") - .step_timed_stream(&format!("Running {}", fmt::command(command.name()))); - - // TODO: Remove usage of unwrap(): https://github.com/heroku/buildpacks-ruby/issues/238 - #[allow(clippy::unwrap_used)] - command.stream_output(stream.io(), stream.io()).unwrap(); - log = stream.finish_timed_stream().end_section(); - drop(log); - } - - { - let mut log = BuildLog::new(stdout()).buildpack_name("Section log functions"); - log = log - .section("Logging inside a layer") - .step( - formatdoc! {" - Layer interfaces are neither mutable nor consuming i.e. - - ``` - fn create( - &self, - _context: &BuildContext, - layer_path: &Path, - ) -> Result, RubyBuildpackError> - ``` - - To allow logging within a layer you can use the `output::section_log` interface. - "} - .trim_end(), - ) - .step("This `section_log` inteface allows you to log without state") - .step("That means you're responsonsible creating a section before calling it") - .step("Here's an example") - .end_section(); - - let section_log = log.section("Example:"); - - log_step("log_step()"); - log_step_timed("log_step_timed()", || { - // do work here - }); - log_step_stream("log_step_stream()", |stream| { - // TODO: Remove usage of unwrap(): https://github.com/heroku/buildpacks-ruby/issues/238 - #[allow(clippy::unwrap_used)] - Command::new("bash") - .args(["-c", "ps aux | grep cargo"]) - .stream_output(stream.io(), stream.io()) - .unwrap() - }); - log_step(formatdoc! {" - If you want to help make sure you're within a section then you can require your layer - takes a reference to `&'a dyn SectionLogger` - "}); - section_log.end_section(); - } - - { - // TODO: Remove usage of unwrap(): https://github.com/heroku/buildpacks-ruby/issues/238 - #[allow(clippy::unwrap_used)] - let cmd_error = Command::new("iDoNotExist").named_output().err().unwrap(); - - let mut log = BuildLog::new(stdout()).buildpack_name("Error and warnings"); - log = log - .section("Debug information") - .step("Should go above errors in section/step format") - .end_section(); - - log = log - .section(DEBUG_INFO) - .step(&cmd_error.to_string()) - .end_section(); - - log.announce() - .warning(&formatdoc! {" - Warning: This is a warning header - - This is a warning body. Warnings are for when we know for a fact a problem exists - but it's not bad enough to abort the build. - "}) - .important(&formatdoc! {" - Important: This is important - - Important is for when there's critical information that needs to be read - however it may or may not be a problem. If we know for a fact that there's - a problem then use a warning instead. - - An example of something that is important but might not be a problem is - that an application owner upgraded to a new stack. - "}) - .error(&formatdoc! {" - Error: This is an error header - - This is the error body. Use an error for when the build cannot continue. - An error should include a header with a short description of why it cannot continue. - - The body should include what error state was observed, why that's a problem, and - what remediation steps an application owner using the buildpack to deploy can - take to solve the issue. - "}); - } - - { - let mut log = BuildLog::new(stdout()).buildpack_name("Formatting helpers"); - - log = log - .section("The fmt module") - .step(&formatdoc! {" - Formatting helpers can be used to enhance log output: - "}) - .end_section(); - - let mut table = AsciiTable::default(); - table.set_max_width(240); - table.column(0).set_header("Example"); - table.column(1).set_header("Code"); - table.column(2).set_header("When to use"); - - let data: Vec> = vec![ - vec![ - fmt::value("2.3.4"), - "fmt::value(\"2.3.f\")".to_string(), - "With versions, file names or other important values worth highlighting".to_string(), - ], - vec![ - fmt::url("https://www.schneems.com"), - "fmt::url(\"https://www.schneems.com\")".to_string(), - "With urls".to_string(), - ], - vec![ - fmt::command("bundle install"), - "fmt::command(command.name())".to_string(), - "With commands (alongside of `fun_run::CommandWithName`)".to_string(), - ], - vec![ - fmt::details("extra information"), - "fmt::details(\"extra information\")".to_string(), - "Add specific information at the end of a line i.e. 'Cache cleared (ruby version changed)'".to_string() - ], - vec![ - fmt::HELP.to_string(), - "fmt::HELP.to_string()".to_string(), - "A help prefix, use it in a step or section title".to_string() - ], - vec![ - fmt::DEBUG_INFO.to_string(), - "fmt::DEBUG_INFO.to_string()".to_string(), - "A debug prefix, use it in a step or section title".to_string() - ] - ]; - - table.print(data); - drop(log); - } -} diff --git a/commons/src/cache.rs b/commons/src/cache.rs index 917e4763..e3f8b559 100644 --- a/commons/src/cache.rs +++ b/commons/src/cache.rs @@ -6,6 +6,8 @@ mod error; pub use self::app_cache::{build, PathState}; pub use self::app_cache::{AppCache, CacheState}; + +#[allow(deprecated)] pub use self::app_cache_collection::AppCacheCollection; pub use self::clean::FilesWithSize; pub use self::config::CacheConfig; diff --git a/commons/src/cache/app_cache_collection.rs b/commons/src/cache/app_cache_collection.rs index afa8799c..2176085d 100644 --- a/commons/src/cache/app_cache_collection.rs +++ b/commons/src/cache/app_cache_collection.rs @@ -20,6 +20,7 @@ pub struct AppCacheCollection<'a> { collection: Vec, } +#[allow(deprecated)] impl<'a> AppCacheCollection<'a> { /// Store multiple application paths in the cache /// @@ -36,7 +37,7 @@ impl<'a> AppCacheCollection<'a> { let caches = config .into_iter() .map(|config| { - AppCache::new_and_load(context, config).map(|store| { + AppCache::new_and_load(context, config).inspect(|store| { let path = store.path().display(); log::log_step(match store.cache_state() { @@ -44,7 +45,6 @@ impl<'a> AppCacheCollection<'a> { CacheState::ExistsEmpty => format!("Loading (empty) cache for {path}"), CacheState::ExistsWithContents => format!("Loading cache for {path}"), }); - store }) }) .collect::, CacheError>>()?; diff --git a/commons/src/layer.rs b/commons/src/layer.rs index d1eee905..74e4e76b 100644 --- a/commons/src/layer.rs +++ b/commons/src/layer.rs @@ -3,7 +3,9 @@ mod default_env_layer; use libcnb::layer::{IntoAction, InvalidMetadataAction}; +#[allow(deprecated)] pub use self::configure_env_layer::ConfigureEnvLayer; +#[allow(deprecated)] pub use self::default_env_layer::DefaultEnvLayer; pub enum MetadataMigrationFYI { diff --git a/commons/src/layer/configure_env_layer.rs b/commons/src/layer/configure_env_layer.rs index bbdd0c51..9565d1de 100644 --- a/commons/src/layer/configure_env_layer.rs +++ b/commons/src/layer/configure_env_layer.rs @@ -1,6 +1,8 @@ use libcnb::build::BuildContext; use libcnb::data::layer_content_metadata::LayerTypes; use libcnb::generic::GenericMetadata; + +#[allow(deprecated)] use libcnb::layer::{Layer, LayerResult, LayerResultBuilder}; use libcnb::layer_env::LayerEnv; use std::marker::PhantomData; @@ -87,6 +89,7 @@ pub struct ConfigureEnvLayer { pub(crate) _buildpack: std::marker::PhantomData, } +#[allow(deprecated)] impl ConfigureEnvLayer where B: libcnb::Buildpack, @@ -100,6 +103,7 @@ where } } +#[allow(deprecated)] impl Layer for ConfigureEnvLayer where B: libcnb::Buildpack, @@ -115,6 +119,7 @@ where } } + #[allow(deprecated)] fn create( &mut self, _context: &BuildContext, diff --git a/commons/src/layer/default_env_layer.rs b/commons/src/layer/default_env_layer.rs index 112bc98c..bc4bf9df 100644 --- a/commons/src/layer/default_env_layer.rs +++ b/commons/src/layer/default_env_layer.rs @@ -2,6 +2,7 @@ use libcnb::layer_env::{LayerEnv, ModificationBehavior, Scope}; use std::ffi::OsString; use std::marker::PhantomData; +#[allow(deprecated)] use super::ConfigureEnvLayer; /// Set default environment variables @@ -65,6 +66,7 @@ use super::ConfigureEnvLayer; #[deprecated(since = "1.1.0", note = "Use the layer Struct API instead")] pub struct DefaultEnvLayer; +#[allow(deprecated)] impl DefaultEnvLayer { #[allow(clippy::new_ret_no_self)] pub fn new(env: E) -> ConfigureEnvLayer diff --git a/commons/src/output/build_log.rs b/commons/src/output/build_log.rs index af8a66b3..2d8cb12d 100644 --- a/commons/src/output/build_log.rs +++ b/commons/src/output/build_log.rs @@ -67,6 +67,7 @@ pub(crate) mod state { pub struct InSection; } +#[allow(deprecated)] impl BuildLog where W: Write + Debug, @@ -80,6 +81,7 @@ where } } +#[allow(deprecated)] impl Logger for BuildLog where W: Write + Send + Sync + Debug + 'static, @@ -103,6 +105,7 @@ where } } +#[allow(deprecated)] impl StartedLogger for BuildLog where W: Write + Send + Sync + Debug + 'static, @@ -133,6 +136,8 @@ where }) } } + +#[allow(deprecated)] impl SectionLogger for BuildLog where W: Write + Send + Sync + Debug + 'static, @@ -291,6 +296,7 @@ where self } + #[allow(deprecated)] fn end_announce(self: Box) -> Box { Box::new(BuildLog { io: self.io, @@ -327,6 +333,7 @@ where self } + #[allow(deprecated)] fn end_announce(self: Box) -> Box { Box::new(BuildLog { io: self.io, @@ -425,6 +432,7 @@ where // // Newline after stream writeln_now(&mut io, ""); + #[allow(deprecated)] let mut section = BuildLog { io, data: self.data, @@ -461,6 +469,7 @@ where writeln_now(&mut io, fmt::details(fmt::time::human(&duration))); + #[allow(deprecated)] Box::new(BuildLog { io, data: self.data, @@ -505,6 +514,7 @@ mod test { let writer = ReadYourWrite::writer(Vec::new()); let reader = writer.reader(); + #[allow(deprecated)] let mut stream = BuildLog::new(writer) .buildpack_name("Heroku Ruby Buildpack") .section("Ruby version `3.1.3` from `Gemfile.lock`") @@ -545,6 +555,7 @@ mod test { let writer = ReadYourWrite::writer(Vec::new()); let reader = writer.reader(); + #[allow(deprecated)] let mut stream = BuildLog::new(writer) .buildpack_name("Streaming buildpack demo") .section("Command streaming") @@ -568,6 +579,7 @@ mod test { let writer = ReadYourWrite::writer(Vec::new()); let reader = writer.reader(); + #[allow(deprecated)] BuildLog::new(writer) .buildpack_name("RCT") .section("Guest thoughs") @@ -603,6 +615,7 @@ mod test { let writer = ReadYourWrite::writer(Vec::new()); let reader = writer.reader(); + #[allow(deprecated)] let logger = BuildLog::new(writer) .buildpack_name("RCT") .section("Guest thoughs") @@ -643,6 +656,8 @@ mod test { let reader = writer.reader(); let warn_later = WarnGuard::new(writer.clone()); + + #[allow(deprecated)] BuildLog::new(writer) .buildpack_name("Walkin' on the Sun") .section("So don't delay, act now, supplies are running out") @@ -683,6 +698,7 @@ mod test { let writer = ReadYourWrite::writer(Vec::new()); let reader = writer.reader(); + #[allow(deprecated)] BuildLog::new(writer) .buildpack_name("Quick and simple") .section("Start") diff --git a/commons/src/output/section_log.rs b/commons/src/output/section_log.rs index 654d9c64..9879aa5b 100644 --- a/commons/src/output/section_log.rs +++ b/commons/src/output/section_log.rs @@ -1,3 +1,4 @@ +#[allow(deprecated)] use crate::output::build_log::{state, BuildData, BuildLog}; #[allow(clippy::wildcard_imports)] pub use crate::output::interface::*; @@ -118,6 +119,7 @@ pub fn log_important(s: impl AsRef) { logger().announce().important(s.as_ref()); } +#[allow(deprecated)] fn logger() -> Box { Box::new(BuildLog:: { io: std::io::stdout(),