diff --git a/crates/turborepo-lib/src/commands/config.rs b/crates/turborepo-lib/src/commands/config.rs index f3d3d04dbaa68..d1730ce6e79b0 100644 --- a/crates/turborepo-lib/src/commands/config.rs +++ b/crates/turborepo-lib/src/commands/config.rs @@ -20,6 +20,7 @@ struct ConfigOutput<'a> { spaces_id: Option<&'a str>, ui: bool, package_manager: PackageManager, + daemon: Option, } pub async fn run(base: CommandBase) -> Result<(), cli::Error> { @@ -47,6 +48,7 @@ pub async fn run(base: CommandBase) -> Result<(), cli::Error> { spaces_id: config.spaces_id(), ui: config.ui(), package_manager: *package_manager, + daemon: config.daemon, })? ); Ok(()) diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/src/commands/mod.rs index bd0d980bebab1..f7bc1062bdc3f 100644 --- a/crates/turborepo-lib/src/commands/mod.rs +++ b/crates/turborepo-lib/src/commands/mod.rs @@ -85,6 +85,7 @@ impl CommandBase { .dangerously_disable_package_manager_check .then_some(true), ) + .with_daemon(self.args.run_args.as_ref().and_then(|args| args.daemon())) .build() } diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index 242ba830bdec8..4787db55c96b8 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -210,6 +210,7 @@ pub struct ConfigurationOptions { pub(crate) ui: Option, #[serde(rename = "dangerouslyDisablePackageManagerCheck")] pub(crate) allow_no_package_manager: Option, + pub(crate) daemon: Option, } #[derive(Default)] @@ -280,6 +281,10 @@ impl ConfigurationOptions { pub fn allow_no_package_manager(&self) -> bool { self.allow_no_package_manager.unwrap_or_default() } + + pub fn daemon(&self) -> Option { + self.daemon + } } // Maps Some("") to None to emulate how Go handles empty strings @@ -314,6 +319,7 @@ impl ResolvedConfigurationOptions for RawTurboJson { .map(|spaces_id| spaces_id.into()); opts.ui = self.ui.map(|ui| ui.use_tui()); opts.allow_no_package_manager = self.allow_no_package_manager; + opts.daemon = self.daemon.map(|daemon| *daemon.as_inner()); Ok(opts) } } @@ -350,6 +356,7 @@ fn get_env_var_config( OsString::from("turbo_dangerously_disable_package_manager_check"), "allow_no_package_manager", ); + turbo_mapping.insert(OsString::from("turbo_daemon"), "daemon"); turbo_mapping.insert(OsString::from("turbo_preflight"), "preflight"); // We do not enable new config sources: @@ -441,6 +448,13 @@ fn get_env_var_config( .map(|s| s.as_str()) .and_then(truth_env_var); + // Process daemon + let daemon = output_map.get("daemon").and_then(|val| match val.as_str() { + "1" | "true" => Some(true), + "0" | "false" => Some(false), + _ => None, + }); + // We currently don't pick up a Spaces ID via env var, we likely won't // continue using the Spaces name, we can add an env var when we have the // name we want to stick with. @@ -459,6 +473,7 @@ fn get_env_var_config( enabled, ui, allow_no_package_manager, + daemon, // Processed numbers timeout, @@ -519,6 +534,7 @@ fn get_override_env_var_config( preflight: None, enabled: None, ui, + daemon: None, timeout: None, upload_timeout: None, spaces_id: None, @@ -663,6 +679,7 @@ impl TurborepoConfigBuilder { allow_no_package_manager, Option ); + create_builder!(with_daemon, daemon, Option); pub fn build(&self) -> Result { // Priority, from least significant to most significant: @@ -745,6 +762,9 @@ impl TurborepoConfigBuilder { { acc.allow_no_package_manager = Some(allow_no_package_manager); } + if let Some(daemon) = current_source_config.daemon { + acc.daemon = Some(daemon); + } acc }) @@ -806,6 +826,7 @@ mod test { "turbo_dangerously_disable_package_manager_check".into(), "true".into(), ); + env.insert("turbo_daemon".into(), "true".into()); env.insert("turbo_preflight".into(), "true".into()); let config = get_env_var_config(&env).unwrap(); @@ -818,6 +839,7 @@ mod test { assert_eq!(turbo_remote_cache_timeout, config.timeout.unwrap()); assert_eq!(Some(true), config.ui); assert_eq!(Some(true), config.allow_no_package_manager); + assert_eq!(Some(true), config.daemon); } #[test] @@ -829,6 +851,7 @@ mod test { env.insert("turbo_teamid".into(), "".into()); env.insert("turbo_token".into(), "".into()); env.insert("turbo_ui".into(), "".into()); + env.insert("turbo_daemon".into(), "".into()); env.insert("turbo_preflight".into(), "".into()); let config = get_env_var_config(&env).unwrap(); @@ -838,6 +861,7 @@ mod test { assert_eq!(config.team_id(), None); assert_eq!(config.token(), None); assert_eq!(config.ui, None); + assert_eq!(config.daemon, None); assert!(!config.preflight()); } diff --git a/crates/turborepo-lib/src/opts.rs b/crates/turborepo-lib/src/opts.rs index 1e31ead1b7279..faf630fc0d721 100644 --- a/crates/turborepo-lib/src/opts.rs +++ b/crates/turborepo-lib/src/opts.rs @@ -254,7 +254,7 @@ impl<'a> TryFrom> for RunOpts { continue_on_error: inputs.execution_args.continue_execution, pass_through_args: inputs.execution_args.pass_through_args.clone(), only: inputs.execution_args.only, - daemon: inputs.run_args.daemon(), + daemon: inputs.config.daemon(), single_package: inputs.execution_args.single_package, graph, dry_run: inputs.run_args.dry_run, @@ -465,13 +465,13 @@ mod test { only: opts_input.only, dry_run: opts_input.dry_run, graph: None, - daemon: None, single_package: false, log_prefix: crate::opts::ResolvedLogPrefix::Task, log_order: crate::opts::ResolvedLogOrder::Stream, summarize: None, experimental_space_id: None, is_github_actions: false, + daemon: None, }; let cache_opts = CacheOpts::default(); let runcache_opts = RunCacheOpts::default(); diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/src/turbo_json/mod.rs index db4045ba741e7..ca3bc2bea25e2 100644 --- a/crates/turborepo-lib/src/turbo_json/mod.rs +++ b/crates/turborepo-lib/src/turbo_json/mod.rs @@ -131,6 +131,8 @@ pub struct RawTurboJson { rename = "dangerouslyDisablePackageManagerCheck" )] pub allow_no_package_manager: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub daemon: Option>, #[deserializable(rename = "//")] #[serde(skip)] @@ -1083,6 +1085,14 @@ mod tests { assert_eq!(json.ui, expected); } + #[test_case(r#"{ "daemon": true }"#, r#"{"daemon":true}"# ; "daemon_on")] + #[test_case(r#"{ "daemon": false }"#, r#"{"daemon":false}"# ; "daemon_off")] + fn test_daemon(json: &str, expected: &str) { + let parsed = RawTurboJson::parse(json, AnchoredSystemPath::new("").unwrap()).unwrap(); + let actual = serde_json::to_string(&parsed).unwrap(); + assert_eq!(actual, expected); + } + #[test_case(r#"{ "ui": "tui" }"#, r#"{"ui":"tui"}"# ; "tui")] #[test_case(r#"{ "ui": "stream" }"#, r#"{"ui":"stream"}"# ; "stream")] fn test_ui_serialization(input: &str, expected: &str) { diff --git a/turborepo-tests/integration/tests/config.t b/turborepo-tests/integration/tests/config.t index 5428994f5a87e..c15c12f589802 100644 --- a/turborepo-tests/integration/tests/config.t +++ b/turborepo-tests/integration/tests/config.t @@ -15,7 +15,8 @@ Run test run "enabled": true, "spacesId": null, "ui": false, - "packageManager": "npm" + "packageManager": "npm", + "daemon": null } Run test run with api overloaded @@ -56,3 +57,22 @@ Run build with invalid env var [1] +Confirm that the daemon is not configured + $ ${TURBO} config | jq .daemon + null + +Add env var: `TURBO_DAEMON=true` + $ TURBO_DAEMON=true ${TURBO} config | jq .daemon + true + +Add env var: `TURBO_DAEMON=false` + $ TURBO_DAEMON=false ${TURBO} config | jq .daemon + false + +Add flag: `--daemon` + $ ${TURBO} --daemon config | jq .daemon + true + +Add flag: `--no-daemon` + $ ${TURBO} --no-daemon config | jq .daemon + false