Skip to content

Commit

Permalink
fix(plan): stdout logic for valid output files (#1249)
Browse files Browse the repository at this point in the history
* feat: cleanup build plan logic and stdout

Don't let build plans generate anything other than the build plan
itself. If an error or warning should be generated, it should be
outputted to stderr. That way consumers can be pretty confident that the
output is only ever in valid TOML/JSON format.

* docs: add expected output behavior of -- plan

* chore: fix linting error

---------

Co-authored-by: Jake Runzer <jakerunzer@gmail.com>
  • Loading branch information
CoderJoshDK and coffee-cup authored Jan 6, 2025
1 parent 7653b2f commit 1c61eb9
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/pages/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ nixpacks plan examples/node
```

By default, the plan is output in JSON format. You can output in TOML format with the `--format toml` option.
The generated plan will be outputted to stdout, while some providers expose recoverable errors to stderr.

View all plan options with

Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ struct Args {
#[allow(clippy::large_enum_variant)]
#[derive(Subcommand)]
enum Commands {
/// Generate a build plan for an app
/// Generate a build plan for an app.
/// Generated plan will be outputted to stdout, while warnings might be outputted to stderr.
Plan {
/// App source
path: String,
Expand Down
2 changes: 1 addition & 1 deletion src/providers/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ fn version_number_to_pkg(version: u32) -> String {
fn parse_node_version_into_pkg(node_version: &str) -> String {
let default_node_pkg_name = version_number_to_pkg(DEFAULT_NODE_VERSION);
let range: Range = node_version.parse().unwrap_or_else(|_| {
println!("Warning: node version {node_version} is not valid, using default node version {default_node_pkg_name}");
eprintln!("Warning: node version {node_version} is not valid, using default node version {default_node_pkg_name}");
Range::parse(DEFAULT_NODE_VERSION.to_string()).unwrap()
});
let mut available_node_versions = AVAILABLE_NODE_VERSIONS.to_vec();
Expand Down
2 changes: 1 addition & 1 deletion src/providers/node/turborepo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Turborepo {
format!("{pkg_manager} --workspace {name} run start")
}));
}
println!("Warning: Turborepo app `{name}` not found");
eprintln!("Warning: Turborepo app `{name}` not found");
}
if let Some(start_pipeline) = Turborepo::get_start_cmd(&turbo_cfg) {
return Ok(Some(start_pipeline));
Expand Down
4 changes: 2 additions & 2 deletions src/providers/php/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,13 @@ impl PhpProvider {
} else if v.contains("7.4") {
"7.4".to_string()
} else {
println!(
eprintln!(
"Warning: PHP version {v} is not available, using PHP {DEFAULT_PHP_VERSION}"
);
DEFAULT_PHP_VERSION.to_string()
}
} else {
println!("Warning: No PHP version specified, using PHP {DEFAULT_PHP_VERSION}; see https://getcomposer.org/doc/04-schema.md#package-links for how to specify a PHP version.");
eprintln!("Warning: No PHP version specified, using PHP {DEFAULT_PHP_VERSION}; see https://getcomposer.org/doc/04-schema.md#package-links for how to specify a PHP version.");
DEFAULT_PHP_VERSION.to_string()
};

Expand Down
11 changes: 4 additions & 7 deletions src/providers/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,13 +377,10 @@ impl PythonProvider {
Ok(asdf_versions.get("python").map(|s| {
let parts: Vec<&str> = s.split('.').collect();

if parts.len() == 3 {
// this is the expected result, but will be unexpected to users
println!("Patch python version detected in .tool-versions, but not supported in nixpkgs.");
} else if parts.len() == 2 {
println!("Expected a python version string in the format x.y.z from .tool-versions");
} else {
println!("Could not find a python version string in the format x.y.z or x.y from .tool-versions");
// We expect there to be 3 or 2 parts (x.y.z) however, only x.y can be parsed.
// So we accept strip x.y.z -> x.y and warn that all other formats are invalid
if parts.len() != 3 && parts.len() != 2 {
eprintln!("Could not find a python version string in the format x.y.z or x.y from .tool-versions. Found {}. Skipping", parts.join("."));
}

format!("{}.{}", parts[0], parts[1])
Expand Down

0 comments on commit 1c61eb9

Please sign in to comment.