From c1623a46c4b6b7e17f610039ab2c6157f88e989c Mon Sep 17 00:00:00 2001 From: Sander Date: Tue, 8 Oct 2024 21:26:40 +0400 Subject: [PATCH 1/3] fix: output non-zero code when `devenv test` fails --- devenv-eval-cache/src/command.rs | 1 + devenv-tasks/src/lib.rs | 1 + devenv-tasks/src/main.rs | 6 ++- devenv/src/cnix.rs | 84 ++++++++++++++++++++------------ devenv/src/devenv.rs | 2 +- 5 files changed, 60 insertions(+), 34 deletions(-) diff --git a/devenv-eval-cache/src/command.rs b/devenv-eval-cache/src/command.rs index 155c1c5aa..e8811423e 100644 --- a/devenv-eval-cache/src/command.rs +++ b/devenv-eval-cache/src/command.rs @@ -202,6 +202,7 @@ pub fn supports_eval_caching(cmd: &Command) -> bool { cmd.get_program().to_string_lossy().ends_with("nix") } +#[derive(Debug)] pub struct Output { /// The status code of the command. pub status: process::ExitStatus, diff --git a/devenv-tasks/src/lib.rs b/devenv-tasks/src/lib.rs index 4ab09fe6b..5016bd119 100644 --- a/devenv-tasks/src/lib.rs +++ b/devenv-tasks/src/lib.rs @@ -613,6 +613,7 @@ impl Tasks { } } +#[derive(Debug)] pub struct TasksStatus { lines: Vec, pub pending: usize, diff --git a/devenv-tasks/src/main.rs b/devenv-tasks/src/main.rs index 8b1fc9fad..34ec4fcba 100644 --- a/devenv-tasks/src/main.rs +++ b/devenv-tasks/src/main.rs @@ -33,7 +33,11 @@ async fn main() -> Result<(), Box> { let config = Config { tasks, roots }; let mut tasks_ui = TasksUi::new(config).await?; - tasks_ui.run().await?; + let (status, _outputs) = tasks_ui.run().await?; + + if status.failed + status.dependency_failed > 0 { + std::process::exit(1); + } } Command::Export { strings } => { let output_file = diff --git a/devenv/src/cnix.rs b/devenv/src/cnix.rs index 18881966f..f92a37e2f 100644 --- a/devenv/src/cnix.rs +++ b/devenv/src/cnix.rs @@ -29,13 +29,44 @@ pub struct Nix<'a> { #[derive(Clone)] pub struct Options<'a> { + /// Run `exec` to replace the shell with the command. pub replace_shell: bool, + /// Error out if the command returns a non-zero status code. + pub bail_on_error: bool, + /// Cache the output of the command. This is opt-in per command. pub cache_output: bool, + /// Enable logging. pub logging: bool, + /// Log the stdout of the command. pub logging_stdout: bool, + /// Extra flags to pass to nix commands. pub nix_flags: &'a [&'a str], } +impl Default for Options<'_> { + fn default() -> Self { + Self { + replace_shell: false, + bail_on_error: true, + // Individual commands opt into caching + cache_output: false, + logging: true, + logging_stdout: false, + nix_flags: &[ + "--show-trace", + "--extra-experimental-features", + "nix-command", + "--extra-experimental-features", + "flakes", + "--option", + "warn-dirty", + "false", + "--keep-going", + ], + } + } +} + impl<'a> Nix<'a> { pub async fn new>( logger: log::Logger, @@ -54,24 +85,7 @@ impl<'a> Nix<'a> { let devenv_root = devenv_root.as_ref().to_path_buf(); let cachix_caches = RefCell::new(None); - let options = Options { - replace_shell: false, - // Individual commands opt into caching - cache_output: false, - logging: true, - logging_stdout: false, - nix_flags: &[ - "--show-trace", - "--extra-experimental-features", - "nix-command", - "--extra-experimental-features", - "flakes", - "--option", - "warn-dirty", - "false", - "--keep-going", - ], - }; + let options = Options::default(); let database_url = format!( "sqlite:{}/nix-eval-cache.db", @@ -106,6 +120,7 @@ impl<'a> Nix<'a> { // Cannot cache this because we don't get the derivation back. // We'd need to switch to print-dev-env and our own `nix develop`. cache_output: false, + bail_on_error: false, replace_shell, ..self.options }; @@ -393,27 +408,32 @@ impl<'a> Nix<'a> { Some(code) => format!("with exit code {}", code), None => "without exit code".to_string(), }; - if options.logging { - eprintln!(); - self.logger.error(&format!( - "Command produced the following output:\n{}\n{}", - String::from_utf8_lossy(&result.stdout), - String::from_utf8_lossy(&result.stderr), - )); - } + if self.global_options.nix_debugger && cmd.get_program().to_string_lossy().ends_with("bin/nix") { self.logger.info("Starting Nix debugger ..."); cmd.arg("--debugger").exec(); } - bail!(format!( - "Command `{}` failed with {code}", - display_command(&cmd) - )) - } else { - Ok(result) + + if options.bail_on_error { + if options.logging { + eprintln!(); + self.logger.error(&format!( + "Command produced the following output:\n{}\n{}", + String::from_utf8_lossy(&result.stdout), + String::from_utf8_lossy(&result.stderr), + )); + } + + bail!(format!( + "Command `{}` failed with {code}", + display_command(&cmd) + )) + } } + + Ok(result) } // We have a separate function to avoid recursion as this needs to call self.prepare_command diff --git a/devenv/src/devenv.rs b/devenv/src/devenv.rs index eaa8f78b1..08dca14e9 100644 --- a/devenv/src/devenv.rs +++ b/devenv/src/devenv.rs @@ -563,7 +563,7 @@ impl Devenv { .iter() .map(|s| s.as_str()) .collect::>(), - false, + false, // replace_shell ) .await? }; From 24903d2012ebf8121068a18ff2599fc8cac98d75 Mon Sep 17 00:00:00 2001 From: Sander Date: Tue, 8 Oct 2024 22:53:49 +0400 Subject: [PATCH 2/3] chore: lint --- src/modules/languages/rust.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/languages/rust.nix b/src/modules/languages/rust.nix index 60be70fd3..48ba73bc2 100644 --- a/src/modules/languages/rust.nix +++ b/src/modules/languages/rust.nix @@ -137,7 +137,7 @@ in if cfg.toolchain ? rust-src then "${cfg.toolchain.rust-src}/lib/rustlib/src/rust/library" else pkgs.rustPlatform.rustLibSrc; - RUSTFLAGS = optionalEnv (moldFlags != "" || cfg.rustflags != "") (lib.concatStringsSep " " (lib.filter (x: x != "") [moldFlags cfg.rustflags])); + RUSTFLAGS = optionalEnv (moldFlags != "" || cfg.rustflags != "") (lib.concatStringsSep " " (lib.filter (x: x != "") [ moldFlags cfg.rustflags ])); RUSTDOCFLAGS = optionalEnv (moldFlags != "") moldFlags; CFLAGS = lib.optionalString pkgs.stdenv.isDarwin "-iframework ${config.devenv.profile}/Library/Frameworks"; }; From 497332c0104ff9477737e4d1be32ed802290465f Mon Sep 17 00:00:00 2001 From: Sander Date: Tue, 8 Oct 2024 23:57:30 +0400 Subject: [PATCH 3/3] javascript: ensure node build includes npm if `npm.enable` --- src/modules/languages/javascript.nix | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/languages/javascript.nix b/src/modules/languages/javascript.nix index 6bd864c8d..06938b7d3 100644 --- a/src/modules/languages/javascript.nix +++ b/src/modules/languages/javascript.nix @@ -171,7 +171,9 @@ in enable = lib.mkEnableOption "install npm"; package = lib.mkOption { type = lib.types.package; - default = cfg.package; + default = cfg.package.override { + enableNpm = true; + }; defaultText = lib.literalExpression "languages.javascript.package"; description = "The Node.js package to use."; }; @@ -217,14 +219,14 @@ in }; config = lib.mkIf cfg.enable { - packages = [ - cfg.package - ] - ++ lib.optional cfg.npm.enable (cfg.npm.package) - ++ lib.optional cfg.pnpm.enable (cfg.pnpm.package) - ++ lib.optional cfg.yarn.enable (cfg.yarn.package.override { nodejs = cfg.package; }) - ++ lib.optional cfg.bun.enable (cfg.bun.package) - ++ lib.optional cfg.corepack.enable (pkgs.runCommand "corepack-enable" { } '' + packages + # Node ships with npm. If npm is enabled, use its package instead. + = lib.optional (!cfg.npm.enable) cfg.package + ++ lib.optional cfg.npm.enable (cfg.npm.package) + ++ lib.optional cfg.pnpm.enable (cfg.pnpm.package) + ++ lib.optional cfg.yarn.enable (cfg.yarn.package.override { nodejs = cfg.package; }) + ++ lib.optional cfg.bun.enable (cfg.bun.package) + ++ lib.optional cfg.corepack.enable (pkgs.runCommand "corepack-enable" { } '' mkdir -p $out/bin ${cfg.package}/bin/corepack enable --install-directory $out/bin '');