Skip to content

Commit

Permalink
Use global print output (#395)
Browse files Browse the repository at this point in the history
* Use global writer state

This preserves newlines between when the printer is dropped and then recovered.

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Make Print interfaces generic

* Update example to not need print state in signature

* Remove unused import

* Update integration tests

Stdout -> Stderr
  • Loading branch information
schneems authored Feb 12, 2025
1 parent 16c9983 commit ef4af81
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 87 deletions.
9 changes: 5 additions & 4 deletions buildpacks/ruby/src/gem_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use fun_run::CmdError;
use regex::Regex;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::io::Stdout;
use std::io::Write;
use std::process::Command;

/// ## Gets list of an application's dependencies
Expand All @@ -21,11 +21,12 @@ pub(crate) struct GemList {
/// # Errors
///
/// Errors if the command `bundle list` is unsuccessful.
pub(crate) fn bundle_list<T, K, V>(
mut bullet: Print<SubBullet<Stdout>>,
pub(crate) fn bundle_list<W, T, K, V>(
mut bullet: Print<SubBullet<W>>,
envs: T,
) -> Result<(Print<SubBullet<Stdout>>, GemList), CmdError>
) -> Result<(Print<SubBullet<W>>, GemList), CmdError>
where
W: Write + Send + Sync + 'static,
T: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
Expand Down
20 changes: 13 additions & 7 deletions buildpacks/ruby/src/layers/bundle_download_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@ use libcnb::layer_env::{LayerEnv, ModificationBehavior, Scope};
use libcnb::Env;
use magic_migrate::TryMigrate;
use serde::{Deserialize, Serialize};
use std::io::Stdout;
use std::io::Write;
use std::path::Path;
use std::process::Command;

pub(crate) fn handle(
pub(crate) fn handle<W>(
context: &libcnb::build::BuildContext<RubyBuildpack>,
env: &Env,
mut bullet: Print<SubBullet<Stdout>>,
mut bullet: Print<SubBullet<W>>,
metadata: &Metadata,
) -> libcnb::Result<(Print<SubBullet<Stdout>>, LayerEnv), RubyBuildpackError> {
) -> libcnb::Result<(Print<SubBullet<W>>, LayerEnv), RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let layer_ref = DiffMigrateLayer {
build: true,
launch: true,
Expand Down Expand Up @@ -79,12 +82,15 @@ pub(crate) struct MetadataV1 {
pub(crate) version: ResolvedBundlerVersion,
}

fn download_bundler(
mut bullet: Print<SubBullet<Stdout>>,
fn download_bundler<W>(
mut bullet: Print<SubBullet<W>>,
env: &Env,
metadata: &Metadata,
gem_path: &Path,
) -> Result<Print<SubBullet<Stdout>>, RubyBuildpackError> {
) -> Result<Print<SubBullet<W>>, RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let bin_dir = gem_path.join("bin");

let mut cmd = Command::new("gem");
Expand Down
11 changes: 7 additions & 4 deletions buildpacks/ruby/src/layers/bundle_install_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use libcnb::{
};
use magic_migrate::TryMigrate;
use serde::{Deserialize, Serialize};
use std::io::Stdout;
use std::io::Write;
use std::{path::Path, process::Command};

/// When this environment variable is set, the `bundle install` command will always
Expand All @@ -44,13 +44,16 @@ const SKIP_DIGEST_ENV_KEY: &str = "HEROKU_SKIP_BUNDLE_DIGEST";
/// on the next build.
pub(crate) const FORCE_BUNDLE_INSTALL_CACHE_KEY: &str = "v1";

pub(crate) fn handle(
pub(crate) fn handle<W>(
context: &libcnb::build::BuildContext<RubyBuildpack>,
env: &Env,
mut bullet: Print<SubBullet<Stdout>>,
mut bullet: Print<SubBullet<W>>,
metadata: &Metadata,
without: &BundleWithout,
) -> libcnb::Result<(Print<SubBullet<Stdout>>, LayerEnv), RubyBuildpackError> {
) -> libcnb::Result<(Print<SubBullet<W>>, LayerEnv), RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let layer_ref = DiffMigrateLayer {
build: true,
launch: true,
Expand Down
11 changes: 7 additions & 4 deletions buildpacks/ruby/src/layers/metrics_agent_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use libcnb::layer::{
};
use libherokubuildpack::digest::sha256;
use serde::{Deserialize, Serialize};
use std::io::Stdout;
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
use tar::Archive;
Expand Down Expand Up @@ -60,10 +60,13 @@ pub(crate) enum MetricsAgentInstallError {
ChecksumFailed(String),
}

pub(crate) fn handle_metrics_agent_layer(
pub(crate) fn handle_metrics_agent_layer<W>(
context: &libcnb::build::BuildContext<RubyBuildpack>,
mut bullet: Print<SubBullet<Stdout>>,
) -> libcnb::Result<Print<SubBullet<Stdout>>, RubyBuildpackError> {
mut bullet: Print<SubBullet<W>>,
) -> libcnb::Result<Print<SubBullet<W>>, RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let metadata = Metadata {
download_url: DOWNLOAD_URL.to_string(),
};
Expand Down
13 changes: 8 additions & 5 deletions buildpacks/ruby/src/layers/ruby_install_layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ use libcnb::layer::{EmptyLayerCause, LayerState};
use libcnb::layer_env::LayerEnv;
use magic_migrate::TryMigrate;
use serde::{Deserialize, Serialize};
use std::io::{self, Stdout};
use std::io::Write;
use std::path::Path;
use tar::Archive;
use tempfile::NamedTempFile;
use url::Url;

pub(crate) fn handle(
pub(crate) fn handle<W>(
context: &libcnb::build::BuildContext<RubyBuildpack>,
mut bullet: Print<SubBullet<Stdout>>,
mut bullet: Print<SubBullet<W>>,
metadata: &Metadata,
) -> libcnb::Result<(Print<SubBullet<Stdout>>, LayerEnv), RubyBuildpackError> {
) -> libcnb::Result<(Print<SubBullet<W>>, LayerEnv), RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let layer_ref = DiffMigrateLayer {
build: true,
launch: true,
Expand Down Expand Up @@ -198,7 +201,7 @@ pub(crate) fn download(
let mut destination_file = fs_err::File::create(destination.as_ref())
.map_err(RubyInstallError::CouldNotCreateDestinationFile)?;

io::copy(&mut response_reader, &mut destination_file)
std::io::copy(&mut response_reader, &mut destination_file)
.map_err(RubyInstallError::CouldNotWriteDestinationFile)?;

Ok(())
Expand Down
3 changes: 1 addition & 2 deletions buildpacks/ruby/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use libcnb::layer::UncachedLayerDefinition;
use libcnb::layer_env::{LayerEnv, ModificationBehavior, Scope};
use libcnb::Platform;
use libcnb::{buildpack_main, Buildpack};
use std::io::stdout;

mod gem_list;
mod layers;
Expand Down Expand Up @@ -115,7 +114,7 @@ impl Buildpack for RubyBuildpack {

#[allow(clippy::too_many_lines)]
fn build(&self, context: BuildContext<Self>) -> libcnb::Result<BuildResult, Self::Error> {
let mut build_output = Print::new(stdout()).h2("Heroku Ruby Buildpack");
let mut build_output = Print::global().h2("Heroku Ruby Buildpack");

// ## Set default environment
let (mut env, store) =
Expand Down
14 changes: 10 additions & 4 deletions buildpacks/ruby/src/rake_task_detect.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bullet_stream::{state::SubBullet, Print};
use core::str::FromStr;
use fun_run::CmdError;
use std::io::Stdout;
use std::io::Write;
use std::{ffi::OsStr, process::Command};

/// Run `rake -P` and parse output to show what rake tasks an application has
Expand All @@ -21,11 +21,17 @@ pub(crate) struct RakeDetect {
/// # Errors
///
/// Will return `Err` if `bundle exec rake -p` command cannot be invoked by the operating system.
pub(crate) fn call<T: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>>(
mut bullet: Print<SubBullet<Stdout>>,
pub(crate) fn call<W, T, K, V>(
mut bullet: Print<SubBullet<W>>,
envs: T,
error_on_failure: bool,
) -> Result<(Print<SubBullet<Stdout>>, RakeDetect), CmdError> {
) -> Result<(Print<SubBullet<W>>, RakeDetect), CmdError>
where
W: Write + Send + Sync + 'static,
T: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
let mut cmd = Command::new("rake");
cmd.args(["-P", "--trace"]).env_clear().envs(envs);

Expand Down
11 changes: 7 additions & 4 deletions buildpacks/ruby/src/steps/detect_rake_tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ use bullet_stream::state::SubBullet;
use bullet_stream::{style, Print};
use libcnb::build::BuildContext;
use libcnb::Env;
use std::io::Stdout;
use std::io::Write;

pub(crate) fn detect_rake_tasks(
bullet: Print<SubBullet<Stdout>>,
pub(crate) fn detect_rake_tasks<W>(
bullet: Print<SubBullet<W>>,
gem_list: &GemList,
context: &BuildContext<RubyBuildpack>,
env: &Env,
) -> Result<(Print<SubBullet<Stdout>>, Option<RakeDetect>), RubyBuildpackError> {
) -> Result<(Print<SubBullet<W>>, Option<RakeDetect>), RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let help = style::important("HELP");
let rake = style::value("rake");
let gemfile = style::value("Gemfile");
Expand Down
11 changes: 7 additions & 4 deletions buildpacks/ruby/src/steps/get_default_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ use libcnb::build::BuildContext;
use libcnb::data::launch::Process;
use libcnb::data::launch::ProcessBuilder;
use libcnb::data::process_type;
use std::io::Stdout;
use std::io::Write;
use std::path::Path;

pub(crate) fn get_default_process(
bullet: Print<SubBullet<Stdout>>,
pub(crate) fn get_default_process<W>(
bullet: Print<SubBullet<W>>,
context: &BuildContext<RubyBuildpack>,
gem_list: &GemList,
) -> (Print<SubBullet<Stdout>>, Option<Process>) {
) -> (Print<SubBullet<W>>, Option<Process>)
where
W: Write + Send + Sync + 'static,
{
let config_ru = style::value("config.ru");
let rails = style::value("rails");
let rack = style::value("rack");
Expand Down
11 changes: 7 additions & 4 deletions buildpacks/ruby/src/steps/rake_assets_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ use bullet_stream::{style, Print};
use commons::cache::{mib, AppCache, CacheConfig, CacheError, CacheState, KeepPath, PathState};
use libcnb::build::BuildContext;
use libcnb::Env;
use std::io::Stdout;
use std::io::Write;
use std::process::Command;

pub(crate) fn rake_assets_install(
mut bullet: Print<SubBullet<Stdout>>,
pub(crate) fn rake_assets_install<W>(
mut bullet: Print<SubBullet<W>>,
context: &BuildContext<RubyBuildpack>,
env: &Env,
rake_detect: &RakeDetect,
) -> Result<Print<SubBullet<Stdout>>, RubyBuildpackError> {
) -> Result<Print<SubBullet<W>>, RubyBuildpackError>
where
W: Write + Send + Sync + 'static,
{
let help = style::important("HELP");
let cases = asset_cases(rake_detect);
let rake_assets_precompile = style::value("rake assets:precompile");
Expand Down
14 changes: 10 additions & 4 deletions buildpacks/ruby/src/user_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use crate::{DetectError, RubyBuildpackError};
use bullet_stream::{state::Bullet, state::SubBullet, style, Print};
use fun_run::CmdError;
use indoc::formatdoc;
use std::io::Stdout;
use std::io::Write;
use std::process::Command;
const DEBUG_INFO_STR: &str = "Debug info";

pub(crate) fn on_error(err: libcnb::Error<RubyBuildpackError>) {
let output = Print::new(std::io::stdout()).without_header();
let output = Print::global().without_header();
let debug_info = style::important(DEBUG_INFO_STR);
match cause(err) {
Cause::OurError(error) => log_our_error(output, error),
Expand All @@ -34,7 +34,10 @@ pub(crate) fn on_error(err: libcnb::Error<RubyBuildpackError>) {
}

#[allow(clippy::too_many_lines)]
fn log_our_error(mut output: Print<Bullet<Stdout>>, error: RubyBuildpackError) {
fn log_our_error<W: Write + Send + Sync + 'static>(
mut output: Print<Bullet<W>>,
error: RubyBuildpackError,
) {
let git_branch_url =
style::url("https://devcenter.heroku.com/articles/git#deploy-from-a-branch-besides-main");
let ruby_versions_url =
Expand Down Expand Up @@ -340,7 +343,10 @@ fn replace_app_path_with_relative(contents: impl AsRef<str>) -> String {
app_path_re.replace_all(contents.as_ref(), "./").to_string()
}

fn debug_cmd(mut log: Print<SubBullet<Stdout>>, command: &mut Command) -> Print<Bullet<Stdout>> {
fn debug_cmd<W: Write + Send + Sync + 'static>(
mut log: Print<SubBullet<W>>,
command: &mut Command,
) -> Print<Bullet<W>> {
match log.stream_cmd(command) {
Ok(_) => log.done(),
Err(e) => log.sub_bullet(e.to_string()).done(),
Expand Down
Loading

0 comments on commit ef4af81

Please sign in to comment.