Skip to content

Commit c1623a4

Browse files
committed
fix: output non-zero code when devenv test fails
1 parent f16bfde commit c1623a4

File tree

5 files changed

+60
-34
lines changed

5 files changed

+60
-34
lines changed

devenv-eval-cache/src/command.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ pub fn supports_eval_caching(cmd: &Command) -> bool {
202202
cmd.get_program().to_string_lossy().ends_with("nix")
203203
}
204204

205+
#[derive(Debug)]
205206
pub struct Output {
206207
/// The status code of the command.
207208
pub status: process::ExitStatus,

devenv-tasks/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ impl Tasks {
613613
}
614614
}
615615

616+
#[derive(Debug)]
616617
pub struct TasksStatus {
617618
lines: Vec<String>,
618619
pub pending: usize,

devenv-tasks/src/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
3333
let config = Config { tasks, roots };
3434

3535
let mut tasks_ui = TasksUi::new(config).await?;
36-
tasks_ui.run().await?;
36+
let (status, _outputs) = tasks_ui.run().await?;
37+
38+
if status.failed + status.dependency_failed > 0 {
39+
std::process::exit(1);
40+
}
3741
}
3842
Command::Export { strings } => {
3943
let output_file =

devenv/src/cnix.rs

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,44 @@ pub struct Nix<'a> {
2929

3030
#[derive(Clone)]
3131
pub struct Options<'a> {
32+
/// Run `exec` to replace the shell with the command.
3233
pub replace_shell: bool,
34+
/// Error out if the command returns a non-zero status code.
35+
pub bail_on_error: bool,
36+
/// Cache the output of the command. This is opt-in per command.
3337
pub cache_output: bool,
38+
/// Enable logging.
3439
pub logging: bool,
40+
/// Log the stdout of the command.
3541
pub logging_stdout: bool,
42+
/// Extra flags to pass to nix commands.
3643
pub nix_flags: &'a [&'a str],
3744
}
3845

46+
impl Default for Options<'_> {
47+
fn default() -> Self {
48+
Self {
49+
replace_shell: false,
50+
bail_on_error: true,
51+
// Individual commands opt into caching
52+
cache_output: false,
53+
logging: true,
54+
logging_stdout: false,
55+
nix_flags: &[
56+
"--show-trace",
57+
"--extra-experimental-features",
58+
"nix-command",
59+
"--extra-experimental-features",
60+
"flakes",
61+
"--option",
62+
"warn-dirty",
63+
"false",
64+
"--keep-going",
65+
],
66+
}
67+
}
68+
}
69+
3970
impl<'a> Nix<'a> {
4071
pub async fn new<P: AsRef<Path>>(
4172
logger: log::Logger,
@@ -54,24 +85,7 @@ impl<'a> Nix<'a> {
5485
let devenv_root = devenv_root.as_ref().to_path_buf();
5586

5687
let cachix_caches = RefCell::new(None);
57-
let options = Options {
58-
replace_shell: false,
59-
// Individual commands opt into caching
60-
cache_output: false,
61-
logging: true,
62-
logging_stdout: false,
63-
nix_flags: &[
64-
"--show-trace",
65-
"--extra-experimental-features",
66-
"nix-command",
67-
"--extra-experimental-features",
68-
"flakes",
69-
"--option",
70-
"warn-dirty",
71-
"false",
72-
"--keep-going",
73-
],
74-
};
88+
let options = Options::default();
7589

7690
let database_url = format!(
7791
"sqlite:{}/nix-eval-cache.db",
@@ -106,6 +120,7 @@ impl<'a> Nix<'a> {
106120
// Cannot cache this because we don't get the derivation back.
107121
// We'd need to switch to print-dev-env and our own `nix develop`.
108122
cache_output: false,
123+
bail_on_error: false,
109124
replace_shell,
110125
..self.options
111126
};
@@ -393,27 +408,32 @@ impl<'a> Nix<'a> {
393408
Some(code) => format!("with exit code {}", code),
394409
None => "without exit code".to_string(),
395410
};
396-
if options.logging {
397-
eprintln!();
398-
self.logger.error(&format!(
399-
"Command produced the following output:\n{}\n{}",
400-
String::from_utf8_lossy(&result.stdout),
401-
String::from_utf8_lossy(&result.stderr),
402-
));
403-
}
411+
404412
if self.global_options.nix_debugger
405413
&& cmd.get_program().to_string_lossy().ends_with("bin/nix")
406414
{
407415
self.logger.info("Starting Nix debugger ...");
408416
cmd.arg("--debugger").exec();
409417
}
410-
bail!(format!(
411-
"Command `{}` failed with {code}",
412-
display_command(&cmd)
413-
))
414-
} else {
415-
Ok(result)
418+
419+
if options.bail_on_error {
420+
if options.logging {
421+
eprintln!();
422+
self.logger.error(&format!(
423+
"Command produced the following output:\n{}\n{}",
424+
String::from_utf8_lossy(&result.stdout),
425+
String::from_utf8_lossy(&result.stderr),
426+
));
427+
}
428+
429+
bail!(format!(
430+
"Command `{}` failed with {code}",
431+
display_command(&cmd)
432+
))
433+
}
416434
}
435+
436+
Ok(result)
417437
}
418438

419439
// We have a separate function to avoid recursion as this needs to call self.prepare_command

devenv/src/devenv.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ impl Devenv {
563563
.iter()
564564
.map(|s| s.as_str())
565565
.collect::<Vec<&str>>(),
566-
false,
566+
false, // replace_shell
567567
)
568568
.await?
569569
};

0 commit comments

Comments
 (0)