Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stacked] Finalize bullet_stream output update #769

Open
wants to merge 25 commits into
base: malax/output
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
02c06f3
Refactor CI tasks so guide name is visible
schneems Jan 31, 2025
29c0215
Replace libherokubuildpack::log::log_error
schneems Jan 31, 2025
4f449bf
Replace log_warning
schneems Jan 31, 2025
b9ec8ce
Remove unused "log" feature from Cargo.toml
schneems Jan 31, 2025
78247e3
Trim trailing whitespace
schneems Jan 31, 2025
dfd5504
Update Gradle command execution to use output format
schneems Jan 31, 2025
e75902f
Update Gradle command execution to use output format
schneems Jan 31, 2025
2ab50d1
Remove unused feature
schneems Jan 31, 2025
d712bed
Auto-track timing for non-quiet commands
schneems Jan 31, 2025
65e9168
Auto emit streamed command's name
schneems Jan 31, 2025
185860b
Auto-emit names of "quiet" commands being run
schneems Jan 31, 2025
91becf0
Print total buildpack execution time
schneems Jan 31, 2025
f400282
Remove (nearly) duplicate command running output
schneems Jan 31, 2025
d410b9c
Fix command timing overlap
schneems Jan 31, 2025
cdb3e51
Fix stderr showing up in the build output:
schneems Jan 31, 2025
cb68a2d
Use consistent run interface
schneems Jan 31, 2025
c7c0305
Use H2 for buildpack headers
schneems Jan 31, 2025
6c6c73d
Use consistent command interface
schneems Jan 31, 2025
3e7a3c0
Remove duplicate timing
schneems Jan 31, 2025
62900ad
Add timing to JDK buildpack
schneems Jan 31, 2025
c0f458b
Use consistent Run interface
schneems Jan 31, 2025
2afff3f
Remove duplicate command output
schneems Jan 31, 2025
fbaed89
Update use statements
schneems Jan 31, 2025
824955c
Update tests
schneems Jan 31, 2025
f02864f
Update tests
schneems Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ jobs:
# Runs only tests annotated with the `ignore` attribute (which in this repo, are the integration tests).
run: cargo test --locked -- --ignored --test-threads 16

print-pack-getting-started-output:
runs-on: ${{ matrix.target == 'aarch64-unknown-linux-musl' && 'pub-hk-ubuntu-24.04-arm-medium' || 'ubuntu-24.04' }}
print-guide:
runs-on: 'pub-hk-ubuntu-24.04-arm-medium'
strategy:
matrix:
target: ["aarch64-unknown-linux-musl", "x86_64-unknown-linux-musl"]
guide: ["heroku/java-getting-started", "heroku/gradle-getting-started", "heroku/scala-getting-started"]
guide: ["java-getting-started", "gradle-getting-started", "scala-getting-started"]
fail-fast: false
steps:
- name: Checkout
Expand All @@ -114,7 +113,7 @@ jobs:
- name: Update Rust toolchain
run: rustup update
- name: Install Rust linux-musl target
run: rustup target add ${{ matrix.target }}
run: rustup target add aarch64-unknown-linux-musl
- name: Rust Cache
uses: Swatinem/[email protected]
- name: Install Pack CLI
Expand All @@ -126,31 +125,31 @@ jobs:
- name: Clone getting started guide
uses: actions/checkout@v4
with:
repository: ${{ matrix.guide }}
repository: "heroku/${{ matrix.guide }}"
path: tmp/guide
- name: Install libcnb-cargo for `cargo libcnb package` command
run: cargo install libcnb-cargo
- name: Compile buildpack
run: cargo libcnb package --target ${{ matrix.target }}
run: cargo libcnb package --target aarch64-unknown-linux-musl
- name: "PRINT: Getting started guide output"
run: |
set -euo pipefail

PACK_CMD="pack build my-image --force-color --builder heroku/builder:24 --trust-extra-buildpacks --path tmp/guide --pull-policy never "
case "${{ matrix.guide }}" in
"heroku/java-getting-started")
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_java "
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_maven "
"java-getting-started")
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_java "
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_maven "
;;
"heroku/gradle-getting-started")
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_gradle "
"gradle-getting-started")
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_gradle "
;;
"heroku/scala-getting-started")
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_sbt "
PACK_CMD+=" --buildpack packaged/${{ matrix.target }}/debug/heroku_scala "
"scala-getting-started")
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_jvm "
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_sbt "
PACK_CMD+=" --buildpack packaged/aarch64-unknown-linux-musl/debug/heroku_scala "
;;
*)
echo "Unknown guide: ${{ matrix.guide }}"
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion buildpacks/gradle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ workspace = true
buildpacks-jvm-shared.workspace = true
indoc = "2"
libcnb = "=0.26.0"
libherokubuildpack = { version = "=0.26.0", default-features = false, features = ["command", "error", "log"] }
libherokubuildpack = { version = "=0.26.0", default-features = false, features = ["error"] }
nom = "7"
serde = { version = "1", features = ["derive"] }

Expand Down
13 changes: 8 additions & 5 deletions buildpacks/gradle/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use crate::GradleBuildpackError;
use buildpacks_jvm_shared::log::{
log_build_tool_io_error, log_build_tool_unexpected_exit_code_error, log_please_try_again_error,
use buildpacks_jvm_shared::{
log::{
log_build_tool_io_error, log_build_tool_unexpected_exit_code_error,
log_please_try_again_error,
},
output::print_error,
};
use indoc::indoc;
use libherokubuildpack::log::log_error;

#[allow(clippy::too_many_lines, clippy::needless_pass_by_value)]
pub(crate) fn on_error_gradle_buildpack(error: GradleBuildpackError) {
match error {
GradleBuildpackError::GradleWrapperNotFound => {
log_error(
print_error(
"Missing Gradle Wrapper",
indoc! {"
This buildpack leverages Gradle Wrapper to install the correct Gradle version to build your application.
Expand Down Expand Up @@ -59,7 +62,7 @@ pub(crate) fn on_error_gradle_buildpack(error: GradleBuildpackError) {
"The Gradle daemon for this build could not be started.",
error,
),
GradleBuildpackError::BuildTaskUnknown => log_error(
GradleBuildpackError::BuildTaskUnknown => print_error(
"Failed to determine build task",
indoc! {"
It looks like your project does not contain a 'stage' task, which Heroku needs in order
Expand Down
38 changes: 19 additions & 19 deletions buildpacks/gradle/src/gradle_command/daemon.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
use crate::gradle_command::GradleCommandError;
use crate::GRADLE_TASK_NAME_HEROKU_START_DAEMON;
use buildpacks_jvm_shared::output;
use libcnb::Env;
use libherokubuildpack::command::CommandExt;
use std::io::{stderr, stdout};
use std::path::Path;
use std::process::Command;

pub(crate) fn start(
gradle_wrapper_executable_path: &Path,
gradle_env: &Env,
) -> Result<(), GradleCommandError<()>> {
let output = Command::new(gradle_wrapper_executable_path)
let mut command = Command::new(gradle_wrapper_executable_path);
command
.args([
// Fixes an issue when running under Apple Rosetta emulation
"-Djdk.lang.Process.launchMechanism=vfork",
"--daemon",
GRADLE_TASK_NAME_HEROKU_START_DAEMON,
])
.envs(gradle_env)
.output_and_write_streams(stdout(), stderr())
.map_err(GradleCommandError::Io)?;
.envs(gradle_env);

if output.status.success() {
Ok(())
} else {
Err(GradleCommandError::UnexpectedExitStatus {
output::run_command(command, false, GradleCommandError::Io, |output| {
GradleCommandError::UnexpectedExitStatus {
status: output.status,
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
})
}
}
})
.map(|_| ())
}

pub(crate) fn stop(
gradle_wrapper_executable_path: &Path,
gradle_env: &Env,
) -> Result<(), GradleCommandError<()>> {
Command::new(gradle_wrapper_executable_path)
.args(["-q", "--stop"])
.envs(gradle_env)
.spawn()
.and_then(|mut child| child.wait())
.map_err(GradleCommandError::Io)?;
let mut command = Command::new(gradle_wrapper_executable_path);
command.args(["-q", "--stop"]).envs(gradle_env);

Ok(())
output::run_command(command, true, GradleCommandError::Io, |output| {
GradleCommandError::UnexpectedExitStatus {
status: output.status,
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
}
})
.map(|_| ())
}
31 changes: 14 additions & 17 deletions buildpacks/gradle/src/gradle_command/dependency_report.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::gradle_command::GradleCommandError;
use buildpacks_jvm_shared::output::run_command;
use libcnb::Env;
use std::collections::BTreeMap;
use std::path::Path;
Expand All @@ -8,27 +9,23 @@ pub(crate) fn dependency_report(
app_dir: &Path,
env: &Env,
) -> Result<GradleDependencyReport, GradleCommandError<()>> {
let output = Command::new(app_dir.join("gradlew"))
let mut command = Command::new(app_dir.join("gradlew"));
command
.current_dir(app_dir)
.envs(env)
.args(["--quiet", "dependencies"])
.output()
.map_err(GradleCommandError::Io)?;
.args(["--quiet", "dependencies"]);

let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

if output.status.success() {
parser::dependency_report(&stdout)
.map_err(|_| GradleCommandError::Parse(()))
.map(|(_, dependency_report)| dependency_report)
} else {
Err(GradleCommandError::UnexpectedExitStatus {
let output = run_command(command, true, GradleCommandError::Io, |output| {
GradleCommandError::UnexpectedExitStatus {
status: output.status,
stdout: stdout.into_owned(),
stderr: stderr.into_owned(),
})
}
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
}
})?;

parser::dependency_report(&String::from_utf8_lossy(&output.stdout))
.map_err(|_| GradleCommandError::Parse(()))
.map(|(_, dependency_report)| dependency_report)
}

#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down
22 changes: 0 additions & 22 deletions buildpacks/gradle/src/gradle_command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ pub(crate) use daemon::stop as stop_daemon;
pub(crate) use dependency_report::{dependency_report, GradleDependencyReport};
pub(crate) use tasks::tasks;

use std::process::Command;

#[derive(Debug)]
pub(crate) enum GradleCommandError<P> {
Io(std::io::Error),
Expand Down Expand Up @@ -40,23 +38,3 @@ impl<P> GradleCommandError<P> {
}
}
}

fn run_gradle_command<T, F, P>(command: &mut Command, parser: F) -> Result<T, GradleCommandError<P>>
where
F: FnOnce(&str, &str) -> Result<T, P>,
{
let output = command.output().map_err(GradleCommandError::Io)?;

let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();

if output.status.success() {
parser(&stdout, &stderr).map_err(GradleCommandError::Parse)
} else {
Err(GradleCommandError::UnexpectedExitStatus {
status: output.status,
stdout,
stderr,
})
}
}
38 changes: 23 additions & 15 deletions buildpacks/gradle/src/gradle_command/tasks.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::gradle_command::{run_gradle_command, GradleCommandError};
use crate::gradle_command::GradleCommandError;
use buildpacks_jvm_shared::output::run_command;
use libcnb::Env;
use std::path::Path;
use std::process::Command;
Expand All @@ -7,20 +8,27 @@ pub(crate) fn tasks(
current_dir: &Path,
env: &Env,
) -> Result<Tasks, GradleCommandError<nom::error::Error<String>>> {
run_gradle_command(
Command::new(current_dir.join("gradlew"))
.current_dir(current_dir)
.envs(env)
.args(["--quiet", "tasks"]),
|stdout, _stderr| {
parser::parse(stdout)
.map(|groups| Tasks { groups })
.map_err(|error| nom::error::Error {
input: error.input.to_string(),
code: error.code,
})
},
)
let mut command = Command::new(current_dir.join("gradlew"));
command
.current_dir(current_dir)
.envs(env)
.args(["--quiet", "tasks"]);

let output = run_command(command, true, GradleCommandError::Io, |output| {
GradleCommandError::UnexpectedExitStatus {
status: output.status,
stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
}
})?;

parser::parse(&String::from_utf8_lossy(&output.stdout))
.map(|groups| Tasks { groups })
.map_err(|error| nom::error::Error {
input: error.input.to_string(),
code: error.code,
})
.map_err(GradleCommandError::Parse)
}

#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down
Loading