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

feat: streamline dfx new output #4073

Merged
merged 10 commits into from
Jan 23, 2025
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
Due to the incompatibility between the APIs on the replica port and the PocketIC port, `dfx info replica-port`
no longer works with PocketIC, and the PocketIC port is provided by a new command, `dfx info pocketic-config-port`.

### feat: streamlined `dfx new` output

### test: adds playwright tests for `dfx new` project frontends

The first of a suite of baseline tests to automate testing starter projects. Makes sure that sveltekit, react, vue, and vanilla frontends are compatible with other dfx or asset canister changes.
Expand Down
71 changes: 44 additions & 27 deletions src/dfx/src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ use dialoguer::{FuzzySelect, MultiSelect};
use fn_error_context::context;
use indicatif::HumanBytes;
use semver::Version;
use slog::{info, trace, warn, Logger};
use slog::{debug, error, info, trace, warn, Logger};
use std::collections::{BTreeMap, HashMap};
use std::io::{self, IsTerminal, Read};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
use std::process::{Command, Output, Stdio};
use std::time::Duration;
use tar::Archive;
use walkdir::WalkDir;
Expand Down Expand Up @@ -200,7 +200,7 @@ pub fn init_git(log: &Logger, project_name: &Path) -> DfxResult {
.status();

if init_status.is_ok() && init_status.unwrap().success() {
info!(log, "Initializing git repository...");
debug!(log, "Initializing git repository...");
std::process::Command::new("git")
.arg("add")
.current_dir(project_name)
Expand Down Expand Up @@ -675,42 +675,62 @@ fn run_post_create_command(
.as_ref()
.map(|msg| env.new_spinner(msg.clone().into()));

let status = cmd
.stderr(Stdio::inherit())
.stdout(Stdio::inherit())
.status()
let child = cmd
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.with_context(|| {
format!(
"Failed to run post-create command '{}' for project template '{}.",
"Failed to spawn post-create command '{}' for project template '{}'.",
&command, &project_template.name
)
});
})?;
let output = child.wait_with_output().with_context(|| {
format!(
"Failed to run post-create command '{}' for project template '{}'.",
&command, &project_template.name
)
});

if let Some(spinner) = spinner {
let message = match status {
Ok(status) if status.success() => "Done.",
_ => "Failed.",
};
spinner.finish_with_message(message.into());
spinner.finish_and_clear();
}

if let Ok(output) = &output {
if !output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);

let msg = format!(
"Post-create ommand '{}' failed.\n--- stdout ---\n{}\n--- stderr ---\n{}",
&command, stdout, stderr
);
if project_template.post_create_failure_warning.is_some() {
warn!(log, "{}", msg);
} else {
error!(log, "{}", msg);
}
}
}

if let Some(warning) = &project_template.post_create_failure_warning {
warn_on_post_create_error(log, status, &command, warning);
warn_on_post_create_error(log, output, &command, warning);
} else {
fail_on_post_create_error(command, status)?;
fail_on_post_create_error(command, output)?;
}
}
Ok(())
}

fn warn_on_post_create_error(
log: &Logger,
status: Result<ExitStatus, Error>,
output: Result<Output, Error>,
command: &str,
warning: &str,
) {
match status {
Ok(status) if status.success() => {}
Ok(status) => match status.code() {
match output {
Ok(output) if output.status.success() => {}
Ok(output) => match output.status.code() {
Some(code) => {
warn!(
log,
Expand All @@ -730,13 +750,10 @@ fn warn_on_post_create_error(
}
}

fn fail_on_post_create_error(
command: String,
status: Result<ExitStatus, Error>,
) -> Result<(), Error> {
let status = status?;
if !status.success() {
match status.code() {
fn fail_on_post_create_error(command: String, output: Result<Output, Error>) -> Result<(), Error> {
let output = output?;
if !output.status.success() {
match output.status.code() {
Some(code) => {
bail!("Post-create command '{command}' failed with exit code {code}.")
}
Expand Down
6 changes: 5 additions & 1 deletion src/dfx/src/config/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ pub fn install_version(v: &str, force: bool) -> Result<PathBuf, InstallCacheErro

if dfx_core::fs::rename(temp_p.as_path(), &p).is_ok() {
if let Some(b) = b {
b.finish_with_message(format!("Installed dfx {} to cache.", v));
if force {
b.finish_with_message(format!("Installed dfx {} to cache.", v));
} else {
b.finish_and_clear();
}
}
} else {
dfx_core::fs::remove_dir_all(temp_p.as_path())?;
Expand Down
1 change: 0 additions & 1 deletion src/dfx/src/lib/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ pub fn get_latest_version(
let manifest_url = url
.join("manifest.json")
.map_err(|e| error_invalid_argument!("invalid manifest URL: {}", e))?;
println!("Fetching manifest {}", manifest_url);

let b = ProgressBar::new_spinner();
b.set_draw_target(ProgressDrawTarget::stderr());
Expand Down
8 changes: 5 additions & 3 deletions src/dfx/src/lib/progress_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ pub struct ProgressBar {
}

macro_rules! forward_fn_impl {
($name: ident) => {
($(#[$meta:meta])* $name: ident) => {
$(#[$meta])*
pub fn $name(&self) {
if let Some(ref progress_bar) = self.bar {
progress_bar.$name();
}
}
};

($name: ident, $( $tname: ident: $t: ty )+) => {
($(#[$meta:meta])* $name: ident, $( $tname: ident: $t: ty )+) => {
$(#[$meta])*
pub fn $name(&self, $($tname: $t,)+) {
if let Some(ref progress_bar) = self.bar {
progress_bar.$name( $($tname,)+ );
Expand All @@ -37,7 +39,7 @@ impl ProgressBar {
}

forward_fn_impl!(finish_and_clear);
forward_fn_impl!(finish_with_message, message: Cow<'static, str>);
forward_fn_impl!(#[allow(dead_code)] finish_with_message, message: Cow<'static, str>);

pub fn discard() -> Self {
ProgressBar { bar: None }
Expand Down
Loading