diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index d7a501acf3b8d..3d8a4fa1735b8 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -87,7 +87,7 @@ impl From for turborepo_ui::tui::event::OutputLogs { } } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, ValueEnum)] +#[derive(Copy, Clone, Debug, PartialEq, Serialize, ValueEnum, Deserialize, Eq)] pub enum LogOrder { #[serde(rename = "auto")] Auto, @@ -233,7 +233,9 @@ pub struct Args { // This should be inside `RunArgs` but clap currently has a bug // around nested flattened optional args: https://github.com/clap-rs/clap/issues/4697 #[clap(flatten)] - pub execution_args: Option, + // DO NOT MAKE THIS VISIBLE + // Instead use the getter method execution_args() + execution_args: Option, #[clap(subcommand)] pub command: Option, } @@ -474,6 +476,15 @@ impl Args { self.run_args.as_ref() } } + + /// Fetch the execution args supplied to the command + pub fn execution_args(&self) -> Option<&ExecutionArgs> { + if let Some(Command::Run { execution_args, .. }) = &self.command { + Some(execution_args) + } else { + self.execution_args.as_ref() + } + } } /// Defines the subcommands for CLI. NOTE: If we change the commands in Go, @@ -710,7 +721,7 @@ ArgGroup::new("scope-filter-group").multiple(true).required(false), ])] pub struct ExecutionArgs { /// Override the filesystem cache directory. - #[clap(long, value_parser = path_non_empty, env = "TURBO_CACHE_DIR")] + #[clap(long, value_parser = path_non_empty)] pub cache_dir: Option, /// Limit the concurrency of task execution. Use 1 for serial (i.e. /// one-at-a-time) execution. @@ -724,7 +735,7 @@ pub struct ExecutionArgs { #[clap(long)] pub single_package: bool, /// Ignore the existing cache (to force execution) - #[clap(long, env = "TURBO_FORCE", default_missing_value = "true")] + #[clap(long, default_missing_value = "true")] pub force: Option>, /// Specify whether or not to do framework inference for tasks #[clap(long, value_name = "BOOL", action = ArgAction::Set, default_value = "true", default_missing_value = "true", num_args = 0..=1)] @@ -761,8 +772,8 @@ pub struct ExecutionArgs { /// output as soon as it is available. Use "grouped" to /// show output when a command has finished execution. Use "auto" to let /// turbo decide based on its own heuristics. (default auto) - #[clap(long, env = "TURBO_LOG_ORDER", value_enum, default_value_t = LogOrder::Auto)] - pub log_order: LogOrder, + #[clap(long, value_enum)] + pub log_order: Option, /// Only executes the tasks specified, does not execute parent tasks. #[clap(long)] pub only: bool, @@ -770,8 +781,8 @@ pub struct ExecutionArgs { pub pkg_inference_root: Option, /// Ignore the local filesystem cache for all tasks. Only /// allow reading and caching artifacts using the remote cache. - #[clap(long, env = "TURBO_REMOTE_ONLY", value_name = "BOOL", action = ArgAction::Set, default_value = "false", default_missing_value = "true", num_args = 0..=1)] - pub remote_only: bool, + #[clap(long, default_missing_value = "true")] + pub remote_only: Option>, /// Use "none" to remove prefixes from task logs. Use "task" to get task id /// prefixing. Use "auto" to let turbo decide how to prefix the logs /// based on the execution environment. In most cases this will be the same @@ -790,6 +801,11 @@ pub struct ExecutionArgs { } impl ExecutionArgs { + pub fn remote_only(&self) -> Option { + let remote_only = self.remote_only?; + Some(remote_only.unwrap_or(true)) + } + fn track(&self, telemetry: &CommandEventBuilder) { // default to false track_usage!(telemetry, self.framework_inference, |val: bool| !val); @@ -797,7 +813,7 @@ impl ExecutionArgs { track_usage!(telemetry, self.continue_execution, |val| val); track_usage!(telemetry, self.single_package, |val| val); track_usage!(telemetry, self.only, |val| val); - track_usage!(telemetry, self.remote_only, |val| val); + track_usage!(telemetry, self.remote_only().unwrap_or_default(), |val| val); track_usage!(telemetry, &self.cache_dir, Option::is_some); track_usage!(telemetry, &self.force, Option::is_some); track_usage!(telemetry, &self.pkg_inference_root, Option::is_some); @@ -822,8 +838,8 @@ impl ExecutionArgs { telemetry.track_arg_value("output-logs", output_logs, EventType::NonSensitive); } - if self.log_order != LogOrder::default() { - telemetry.track_arg_value("log-order", self.log_order, EventType::NonSensitive); + if let Some(log_order) = self.log_order { + telemetry.track_arg_value("log-order", log_order, EventType::NonSensitive); } if self.log_prefix != LogPrefix::default() { @@ -882,10 +898,10 @@ pub struct RunArgs { #[clap(long, value_parser=NonEmptyStringValueParser::new(), conflicts_with = "profile")] pub anon_profile: Option, /// Treat remote cache as read only - #[clap(long, env = "TURBO_REMOTE_CACHE_READ_ONLY", value_name = "BOOL", action = ArgAction::Set, default_value = "false", default_missing_value = "true", num_args = 0..=1)] - pub remote_cache_read_only: bool, + #[clap(long, default_missing_value = "true")] + pub remote_cache_read_only: Option>, /// Generate a summary of the turbo run - #[clap(long, env = "TURBO_RUN_SUMMARY", default_missing_value = "true")] + #[clap(long, default_missing_value = "true")] pub summarize: Option>, // Pass a string to enable posting Run Summaries to Vercel @@ -908,7 +924,7 @@ impl Default for RunArgs { no_daemon: false, profile: None, anon_profile: None, - remote_cache_read_only: false, + remote_cache_read_only: None, summarize: None, experimental_space_id: None, parallel: false, @@ -938,13 +954,27 @@ impl RunArgs { } } + pub fn remote_cache_read_only(&self) -> Option { + let remote_cache_read_only = self.remote_cache_read_only?; + Some(remote_cache_read_only.unwrap_or(true)) + } + + pub fn summarize(&self) -> Option { + let summarize = self.summarize?; + Some(summarize.unwrap_or(true)) + } + pub fn track(&self, telemetry: &CommandEventBuilder) { // default to true track_usage!(telemetry, self.no_cache, |val| val); track_usage!(telemetry, self.daemon, |val| val); track_usage!(telemetry, self.no_daemon, |val| val); track_usage!(telemetry, self.parallel, |val| val); - track_usage!(telemetry, self.remote_cache_read_only, |val| val); + track_usage!( + telemetry, + self.remote_cache_read_only().unwrap_or_default(), + |val| val + ); // default to None track_usage!(telemetry, &self.profile, Option::is_some); @@ -1412,7 +1442,7 @@ mod test { fn get_default_execution_args() -> ExecutionArgs { ExecutionArgs { output_logs: None, - remote_only: false, + remote_only: None, framework_inference: true, ..ExecutionArgs::default() } @@ -1923,7 +1953,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - log_order: LogOrder::Stream, + log_order: Some(LogOrder::Stream), ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -1938,7 +1968,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - log_order: LogOrder::Grouped, + log_order: Some(LogOrder::Grouped), ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -1998,7 +2028,6 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - log_order: LogOrder::Auto, ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -2048,7 +2077,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - remote_only: false, + remote_only: None, ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -2063,7 +2092,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - remote_only: true, + remote_only: Some(Some(true)), ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -2078,7 +2107,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - remote_only: true, + remote_only: Some(Some(true)), ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) @@ -2093,7 +2122,7 @@ mod test { command: Some(Command::Run { execution_args: Box::new(ExecutionArgs { tasks: vec!["build".to_string()], - remote_only: false, + remote_only: Some(Some(false)), ..get_default_execution_args() }), run_args: Box::new(get_default_run_args()) diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/src/commands/mod.rs index 8136839d7fa34..857f5e31b111b 100644 --- a/crates/turborepo-lib/src/commands/mod.rs +++ b/crates/turborepo-lib/src/commands/mod.rs @@ -7,9 +7,7 @@ use turborepo_dirs::config_dir; use turborepo_ui::ColorConfig; use crate::{ - cli::Command, config::{ConfigurationOptions, Error as ConfigError, TurborepoConfigBuilder}, - turbo_json::UIMode, Args, }; @@ -69,17 +67,7 @@ impl CommandBase { .with_token(self.args.token.clone()) .with_timeout(self.args.remote_cache_timeout) .with_preflight(self.args.preflight.then_some(true)) - .with_ui(self.args.ui.or_else(|| { - self.args.execution_args.as_ref().and_then(|args| { - if !args.log_order.compatible_with_tui() { - Some(UIMode::Stream) - } else { - // If the argument is compatible with the TUI this does not mean we should - // override other configs - None - } - }) - })) + .with_ui(self.args.ui) .with_allow_no_package_manager( self.args .dangerously_disable_package_manager_check @@ -88,33 +76,13 @@ impl CommandBase { .with_daemon(self.args.run_args().and_then(|args| args.daemon())) .with_env_mode( self.args - .command - .as_ref() - .and_then(|c| match c { - Command::Run { execution_args, .. } => execution_args.env_mode, - _ => None, - }) - .or_else(|| { - self.args - .execution_args - .as_ref() - .and_then(|args| args.env_mode) - }), + .execution_args() + .and_then(|execution_args| execution_args.env_mode), ) .with_cache_dir( self.args - .command - .as_ref() - .and_then(|c| match c { - Command::Run { execution_args, .. } => execution_args.cache_dir.clone(), - _ => None, - }) - .or_else(|| { - self.args - .execution_args - .as_ref() - .and_then(|args| args.cache_dir.clone()) - }), + .execution_args() + .and_then(|execution_args| execution_args.cache_dir.clone()), ) .with_root_turbo_json_path( self.args @@ -123,6 +91,23 @@ impl CommandBase { .map(AbsoluteSystemPathBuf::from_cwd) .transpose()?, ) + .with_force( + self.args + .execution_args() + .and_then(|args| args.force.map(|value| value.unwrap_or(true))), + ) + .with_log_order(self.args.execution_args().and_then(|args| args.log_order)) + .with_remote_only( + self.args + .execution_args() + .and_then(|args| args.remote_only()), + ) + .with_remote_cache_read_only( + self.args + .run_args() + .and_then(|args| args.remote_cache_read_only()), + ) + .with_run_summary(self.args.run_args().and_then(|args| args.summarize())) .build() } diff --git a/crates/turborepo-lib/src/config/env.rs b/crates/turborepo-lib/src/config/env.rs index 0e982c1d2a9a0..f70987712b9fd 100644 --- a/crates/turborepo-lib/src/config/env.rs +++ b/crates/turborepo-lib/src/config/env.rs @@ -3,10 +3,15 @@ use std::{ ffi::{OsStr, OsString}, }; +use clap::ValueEnum; +use itertools::Itertools; use turbopath::AbsoluteSystemPathBuf; use super::{ConfigurationOptions, Error, ResolvedConfigurationOptions}; -use crate::{cli::EnvMode, turbo_json::UIMode}; +use crate::{ + cli::{EnvMode, LogOrder}, + turbo_json::UIMode, +}; const TURBO_MAPPING: &[(&str, &str)] = [ ("turbo_api", "api_url"), @@ -28,6 +33,11 @@ const TURBO_MAPPING: &[(&str, &str)] = [ ("turbo_scm_base", "scm_base"), ("turbo_scm_head", "scm_head"), ("turbo_root_turbo_json", "root_turbo_json_path"), + ("turbo_force", "force"), + ("turbo_log_order", "log_order"), + ("turbo_remote_only", "remote_only"), + ("turbo_remote_cache_read_only", "remote_cache_read_only"), + ("turbo_run_summary", "run_summary"), ] .as_slice(); @@ -41,6 +51,12 @@ impl EnvVars { let output_map = map_environment(turbo_mapping, environment)?; Ok(Self { output_map }) } + + fn truthy_value(&self, key: &str) -> Option> { + Some(truth_env_var( + self.output_map.get(key).filter(|s| !s.is_empty())?, + )) + } } impl ResolvedConfigurationOptions for EnvVars { @@ -49,83 +65,53 @@ impl ResolvedConfigurationOptions for EnvVars { _existing_config: &ConfigurationOptions, ) -> Result { // Process signature - let signature = if let Some(signature) = self.output_map.get("signature") { - match signature.as_str() { - "0" => Some(false), - "1" => Some(true), - _ => return Err(Error::InvalidSignature), - } - } else { - None - }; + let signature = self + .truthy_value("signature") + .map(|value| value.ok_or_else(|| Error::InvalidSignature)) + .transpose()?; // Process preflight - let preflight = if let Some(preflight) = self.output_map.get("preflight") { - match preflight.as_str() { - "0" | "false" => Some(false), - "1" | "true" => Some(true), - "" => None, - _ => return Err(Error::InvalidPreflight), - } - } else { - None - }; + let preflight = self + .truthy_value("preflight") + .map(|value| value.ok_or_else(|| Error::InvalidPreflight)) + .transpose()?; // Process enabled - let enabled = if let Some(enabled) = self.output_map.get("enabled") { - match enabled.as_str() { - "0" => Some(false), - "1" => Some(true), - _ => return Err(Error::InvalidRemoteCacheEnabled), - } - } else { - None - }; + let enabled = self + .truthy_value("enabled") + .map(|value| value.ok_or_else(|| Error::InvalidRemoteCacheEnabled)) + .transpose()?; + + let force = self.truthy_value("force").flatten(); + let remote_only = self.truthy_value("remote_only").flatten(); + let remote_cache_read_only = self.truthy_value("remote_cache_read_only").flatten(); + let run_summary = self.truthy_value("run_summary").flatten(); // Process timeout - let timeout = if let Some(timeout) = self.output_map.get("timeout") { - Some( - timeout - .parse::() - .map_err(Error::InvalidRemoteCacheTimeout)?, - ) - } else { - None - }; + let timeout = self + .output_map + .get("timeout") + .map(|s| s.parse()) + .transpose() + .map_err(Error::InvalidRemoteCacheTimeout)?; - let upload_timeout = if let Some(upload_timeout) = self.output_map.get("upload_timeout") { - Some( - upload_timeout - .parse::() - .map_err(Error::InvalidUploadTimeout)?, - ) - } else { - None - }; + let upload_timeout = self + .output_map + .get("upload_timeout") + .map(|s| s.parse()) + .transpose() + .map_err(Error::InvalidUploadTimeout)?; // Process experimentalUI - let ui = self - .output_map - .get("ui") - .map(|s| s.as_str()) - .and_then(truth_env_var) - .map(|ui| if ui { UIMode::Tui } else { UIMode::Stream }); + let ui = + self.truthy_value("ui") + .flatten() + .map(|ui| if ui { UIMode::Tui } else { UIMode::Stream }); - let allow_no_package_manager = self - .output_map - .get("allow_no_package_manager") - .map(|s| s.as_str()) - .and_then(truth_env_var); + let allow_no_package_manager = self.truthy_value("allow_no_package_manager").flatten(); // Process daemon - let daemon = self - .output_map - .get("daemon") - .and_then(|val| match val.as_str() { - "1" | "true" => Some(true), - "0" | "false" => Some(false), - _ => None, - }); + let daemon = self.truthy_value("daemon").flatten(); let env_mode = self .output_map @@ -146,6 +132,21 @@ impl ResolvedConfigurationOptions for EnvVars { .map(AbsoluteSystemPathBuf::from_cwd) .transpose()?; + let log_order = self + .output_map + .get("log_order") + .filter(|s| !s.is_empty()) + .map(|s| LogOrder::from_str(s, true)) + .transpose() + .map_err(|_| { + Error::InvalidLogOrder( + LogOrder::value_variants() + .iter() + .map(|v| v.to_string()) + .join(", "), + ) + })?; + // 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. @@ -166,6 +167,10 @@ impl ResolvedConfigurationOptions for EnvVars { ui, allow_no_package_manager, daemon, + force, + remote_only, + remote_cache_read_only, + run_summary, // Processed numbers timeout, @@ -174,6 +179,7 @@ impl ResolvedConfigurationOptions for EnvVars { env_mode, cache_dir, root_turbo_json_path, + log_order, }; Ok(output) @@ -202,6 +208,17 @@ impl<'a> OverrideEnvVars<'a> { output_map, }) } + + fn ui(&self) -> Option { + let value = self + .environment + .get(OsStr::new("ci")) + .or_else(|| self.environment.get(OsStr::new("no_color")))?; + match truth_env_var(value.to_str()?)? { + true => Some(UIMode::Stream), + false => None, + } + } } impl<'a> ResolvedConfigurationOptions for OverrideEnvVars<'a> { @@ -209,40 +226,13 @@ impl<'a> ResolvedConfigurationOptions for OverrideEnvVars<'a> { &self, _existing_config: &ConfigurationOptions, ) -> Result { - let ui = self - .environment - .get(OsStr::new("ci")) - .or_else(|| self.environment.get(OsStr::new("no_color"))) - .and_then(|value| { - // If either of these are truthy, then we disable the TUI - if value == "true" || value == "1" { - Some(UIMode::Stream) - } else { - None - } - }); - + let ui = self.ui(); let output = ConfigurationOptions { - api_url: None, - login_url: None, - team_slug: None, team_id: self.output_map.get("team_id").cloned(), token: self.output_map.get("token").cloned(), - scm_base: None, - scm_head: None, - - signature: None, - preflight: None, - enabled: None, + api_url: None, ui, - daemon: None, - timeout: None, - upload_timeout: None, - spaces_id: None, - allow_no_package_manager: None, - env_mode: None, - cache_dir: None, - root_turbo_json_path: None, + ..Default::default() }; Ok(output) @@ -281,7 +271,10 @@ mod test { use camino::Utf8PathBuf; use super::*; - use crate::config::{DEFAULT_API_URL, DEFAULT_LOGIN_URL}; + use crate::{ + cli::LogOrder, + config::{DEFAULT_API_URL, DEFAULT_LOGIN_URL}, + }; #[test] fn test_env_setting() { @@ -319,12 +312,22 @@ mod test { env.insert("turbo_env_mode".into(), "strict".into()); env.insert("turbo_cache_dir".into(), cache_dir.clone().into()); env.insert("turbo_root_turbo_json".into(), root_turbo_json.into()); + env.insert("turbo_force".into(), "1".into()); + env.insert("turbo_log_order".into(), "grouped".into()); + env.insert("turbo_remote_only".into(), "1".into()); + env.insert("turbo_remote_cache_read_only".into(), "1".into()); + env.insert("turbo_run_summary".into(), "true".into()); let config = EnvVars::new(&env) .unwrap() .get_configuration_options(&ConfigurationOptions::default()) .unwrap(); assert!(config.preflight()); + assert!(config.force()); + assert_eq!(config.log_order(), LogOrder::Grouped); + assert!(config.remote_only()); + assert!(config.remote_cache_read_only()); + assert!(config.run_summary()); assert_eq!(turbo_api, config.api_url.unwrap()); assert_eq!(turbo_login, config.login_url.unwrap()); assert_eq!(turbo_team, config.team_slug.unwrap()); @@ -357,6 +360,11 @@ mod test { env.insert("turbo_scm_head".into(), "".into()); env.insert("turbo_scm_base".into(), "".into()); env.insert("turbo_root_turbo_json".into(), "".into()); + env.insert("turbo_force".into(), "".into()); + env.insert("turbo_log_order".into(), "".into()); + env.insert("turbo_remote_only".into(), "".into()); + env.insert("turbo_remote_cache_read_only".into(), "".into()); + env.insert("turbo_run_summary".into(), "".into()); let config = EnvVars::new(&env) .unwrap() @@ -374,6 +382,11 @@ mod test { assert_eq!(config.scm_base(), None); assert_eq!(config.scm_head(), "HEAD"); assert_eq!(config.root_turbo_json_path, None); + assert!(!config.force()); + assert_eq!(config.log_order(), LogOrder::Auto); + assert!(!config.remote_only()); + assert!(!config.remote_cache_read_only()); + assert!(!config.run_summary()); } #[test] diff --git a/crates/turborepo-lib/src/config/mod.rs b/crates/turborepo-lib/src/config/mod.rs index 6fefa2d435e69..c059333421446 100644 --- a/crates/turborepo-lib/src/config/mod.rs +++ b/crates/turborepo-lib/src/config/mod.rs @@ -19,7 +19,11 @@ use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; use turborepo_errors::TURBO_SITE; pub use crate::turbo_json::{RawTurboJson, UIMode}; -use crate::{cli::EnvMode, commands::CommandBase, turbo_json::CONFIG_FILE}; +use crate::{ + cli::{EnvMode, LogOrder}, + commands::CommandBase, + turbo_json::CONFIG_FILE, +}; #[derive(Debug, Error, Diagnostic)] #[error("Environment variables should not be prefixed with \"{env_pipeline_delimiter}\"")] @@ -162,6 +166,8 @@ pub enum Error { InvalidUploadTimeout(#[source] std::num::ParseIntError), #[error("TURBO_PREFLIGHT should be either 1 or 0.")] InvalidPreflight, + #[error("TURBO_LOG_ORDER should be one of: {0}")] + InvalidLogOrder(String), #[error(transparent)] #[diagnostic(transparent)] TurboJsonParseError(#[from] crate::turbo_json::parser::Error), @@ -228,6 +234,11 @@ pub struct ConfigurationOptions { // This is skipped as we never want this to be stored in a file #[serde(skip)] pub(crate) root_turbo_json_path: Option, + pub(crate) force: Option, + pub(crate) log_order: Option, + pub(crate) remote_only: Option, + pub(crate) remote_cache_read_only: Option, + pub(crate) run_summary: Option, } #[derive(Default)] @@ -294,7 +305,11 @@ impl ConfigurationOptions { return UIMode::Stream; } - self.ui.unwrap_or(UIMode::Stream) + self.log_order() + .compatible_with_tui() + .then_some(self.ui) + .flatten() + .unwrap_or(UIMode::Stream) } pub fn scm_base(&self) -> Option<&str> { @@ -327,6 +342,26 @@ impl ConfigurationOptions { }) } + pub fn force(&self) -> bool { + self.force.unwrap_or_default() + } + + pub fn log_order(&self) -> LogOrder { + self.log_order.unwrap_or_default() + } + + pub fn remote_only(&self) -> bool { + self.remote_only.unwrap_or_default() + } + + pub fn remote_cache_read_only(&self) -> bool { + self.remote_cache_read_only.unwrap_or_default() + } + + pub fn run_summary(&self) -> bool { + self.run_summary.unwrap_or_default() + } + pub fn root_turbo_json_path(&self, repo_root: &AbsoluteSystemPath) -> AbsoluteSystemPathBuf { self.root_turbo_json_path .clone() diff --git a/crates/turborepo-lib/src/opts.rs b/crates/turborepo-lib/src/opts.rs index 77726b0f1080b..fdd20aa088be4 100644 --- a/crates/turborepo-lib/src/opts.rs +++ b/crates/turborepo-lib/src/opts.rs @@ -138,7 +138,7 @@ pub struct RunCacheOpts { impl<'a> From> for RunCacheOpts { fn from(inputs: OptsInputs<'a>) -> Self { RunCacheOpts { - skip_reads: inputs.execution_args.force.flatten().is_some_and(|f| f), + skip_reads: inputs.config.force(), skip_writes: inputs.run_args.no_cache, task_output_logs_override: inputs.execution_args.output_logs, } @@ -164,7 +164,7 @@ pub struct RunOpts { pub(crate) single_package: bool, pub log_prefix: ResolvedLogPrefix, pub log_order: ResolvedLogOrder, - pub summarize: Option>, + pub summarize: bool, pub(crate) experimental_space_id: Option, pub is_github_actions: bool, pub ui_mode: UIMode, @@ -222,7 +222,7 @@ impl<'a> TryFrom> for RunOpts { f => GraphOpts::File(f.to_string()), }); - let (is_github_actions, log_order, log_prefix) = match inputs.execution_args.log_order { + let (is_github_actions, log_order, log_prefix) = match inputs.config.log_order() { LogOrder::Auto if turborepo_ci::Vendor::get_constant() == Some("GITHUB_ACTIONS") => ( true, ResolvedLogOrder::Grouped, @@ -249,7 +249,7 @@ impl<'a> TryFrom> for RunOpts { tasks: inputs.execution_args.tasks.clone(), log_prefix, log_order, - summarize: inputs.run_args.summarize, + summarize: inputs.config.run_summary(), experimental_space_id: inputs .run_args .experimental_space_id @@ -365,8 +365,8 @@ impl<'a> From> for CacheOpts { CacheOpts { cache_dir: inputs.config.cache_dir().into(), - skip_filesystem: inputs.execution_args.remote_only, - remote_cache_read_only: inputs.run_args.remote_cache_read_only, + skip_filesystem: inputs.config.remote_only(), + remote_cache_read_only: inputs.config.remote_cache_read_only(), workers: inputs.run_args.cache_workers, skip_remote, remote_cache_opts, @@ -507,7 +507,7 @@ mod test { single_package: false, log_prefix: crate::opts::ResolvedLogPrefix::Task, log_order: crate::opts::ResolvedLogOrder::Stream, - summarize: None, + summarize: false, experimental_space_id: None, is_github_actions: false, daemon: None, diff --git a/crates/turborepo-lib/src/run/summary/mod.rs b/crates/turborepo-lib/src/run/summary/mod.rs index 5fc65ba7aa54a..cb67963c7d72a 100644 --- a/crates/turborepo-lib/src/run/summary/mod.rs +++ b/crates/turborepo-lib/src/run/summary/mod.rs @@ -188,7 +188,7 @@ impl RunTracker { task_factory: TaskSummaryFactory<'a>, ) -> Result, Error> { let single_package = run_opts.single_package; - let should_save = run_opts.summarize.flatten().is_some_and(|s| s); + let should_save = run_opts.summarize; let run_type = match run_opts.dry_run { None => RunType::Real, diff --git a/turborepo-tests/integration/tests/no-args.t b/turborepo-tests/integration/tests/no-args.t index 88405d0e2aaa3..b76576b838c1d 100644 --- a/turborepo-tests/integration/tests/no-args.t +++ b/turborepo-tests/integration/tests/no-args.t @@ -80,14 +80,14 @@ Make sure exit code is 2 when no args are passed File to write turbo's performance profile output into. You can load the file up in chrome://tracing to see which parts of your build were slow --anon-profile File to write turbo's performance profile output into. All identifying data omitted from the profile - --remote-cache-read-only [] - Treat remote cache as read only [env: TURBO_REMOTE_CACHE_READ_ONLY=] [default: false] [possible values: true, false] + --remote-cache-read-only [] + Treat remote cache as read only [possible values: true, false] --summarize [] - Generate a summary of the turbo run [env: TURBO_RUN_SUMMARY=] [possible values: true, false] + Generate a summary of the turbo run [possible values: true, false] --parallel Execute all tasks in parallel --cache-dir - Override the filesystem cache directory [env: TURBO_CACHE_DIR=] + Override the filesystem cache directory --concurrency Limit the concurrency of task execution. Use 1 for serial (i.e. one-at-a-time) execution --continue @@ -95,7 +95,7 @@ Make sure exit code is 2 when no args are passed --single-package Run turbo in single-package mode --force [] - Ignore the existing cache (to force execution) [env: TURBO_FORCE=] [possible values: true, false] + Ignore the existing cache (to force execution) [possible values: true, false] --framework-inference [] Specify whether or not to do framework inference for tasks [default: true] [possible values: true, false] --global-deps @@ -109,11 +109,11 @@ Make sure exit code is 2 when no args are passed --output-logs Set type of process output logging. Use "full" to show all output. Use "hash-only" to show only turbo-computed task hashes. Use "new-only" to show only new output with only hashes for cached tasks. Use "none" to hide process output. (default full) [possible values: full, none, hash-only, new-only, errors-only] --log-order - Set type of task output order. Use "stream" to show output as soon as it is available. Use "grouped" to show output when a command has finished execution. Use "auto" to let turbo decide based on its own heuristics. (default auto) [env: TURBO_LOG_ORDER=] [default: auto] [possible values: auto, stream, grouped] + Set type of task output order. Use "stream" to show output as soon as it is available. Use "grouped" to show output when a command has finished execution. Use "auto" to let turbo decide based on its own heuristics. (default auto) [possible values: auto, stream, grouped] --only Only executes the tasks specified, does not execute parent tasks - --remote-only [] - Ignore the local filesystem cache for all tasks. Only allow reading and caching artifacts using the remote cache [env: TURBO_REMOTE_ONLY=] [default: false] [possible values: true, false] + --remote-only [] + Ignore the local filesystem cache for all tasks. Only allow reading and caching artifacts using the remote cache [possible values: true, false] --log-prefix Use "none" to remove prefixes from task logs. Use "task" to get task id prefixing. Use "auto" to let turbo decide how to prefix the logs based on the execution environment. In most cases this will be the same as "task". Note that tasks running in parallel interleave their logs, so removing prefixes can make it difficult to associate logs with tasks. Use --log-order=grouped to prevent interleaving. (default auto) [default: auto] [possible values: auto, none, task] [1] @@ -141,7 +141,7 @@ Run again with a filter and get only the packages that match Run again with an environment variable that corresponds to a run argument and assert that we get the full help output. - $ TURBO_LOG_ORDER=stream ${TURBO} 2>&1 > out.txt + $ TURBO_LOG_ORDER=stream ${TURBO} 2> out.txt [1] $ cat out.txt | head -n1 The build system that makes ship happen diff --git a/turborepo-tests/integration/tests/turbo-help.t b/turborepo-tests/integration/tests/turbo-help.t index 05ca151029722..0ea98403d9752 100644 --- a/turborepo-tests/integration/tests/turbo-help.t +++ b/turborepo-tests/integration/tests/turbo-help.t @@ -80,14 +80,14 @@ Test help flag File to write turbo's performance profile output into. You can load the file up in chrome://tracing to see which parts of your build were slow --anon-profile File to write turbo's performance profile output into. All identifying data omitted from the profile - --remote-cache-read-only [] - Treat remote cache as read only [env: TURBO_REMOTE_CACHE_READ_ONLY=] [default: false] [possible values: true, false] + --remote-cache-read-only [] + Treat remote cache as read only [possible values: true, false] --summarize [] - Generate a summary of the turbo run [env: TURBO_RUN_SUMMARY=] [possible values: true, false] + Generate a summary of the turbo run [possible values: true, false] --parallel Execute all tasks in parallel --cache-dir - Override the filesystem cache directory [env: TURBO_CACHE_DIR=] + Override the filesystem cache directory --concurrency Limit the concurrency of task execution. Use 1 for serial (i.e. one-at-a-time) execution --continue @@ -95,7 +95,7 @@ Test help flag --single-package Run turbo in single-package mode --force [] - Ignore the existing cache (to force execution) [env: TURBO_FORCE=] [possible values: true, false] + Ignore the existing cache (to force execution) [possible values: true, false] --framework-inference [] Specify whether or not to do framework inference for tasks [default: true] [possible values: true, false] --global-deps @@ -109,11 +109,11 @@ Test help flag --output-logs Set type of process output logging. Use "full" to show all output. Use "hash-only" to show only turbo-computed task hashes. Use "new-only" to show only new output with only hashes for cached tasks. Use "none" to hide process output. (default full) [possible values: full, none, hash-only, new-only, errors-only] --log-order - Set type of task output order. Use "stream" to show output as soon as it is available. Use "grouped" to show output when a command has finished execution. Use "auto" to let turbo decide based on its own heuristics. (default auto) [env: TURBO_LOG_ORDER=] [default: auto] [possible values: auto, stream, grouped] + Set type of task output order. Use "stream" to show output as soon as it is available. Use "grouped" to show output when a command has finished execution. Use "auto" to let turbo decide based on its own heuristics. (default auto) [possible values: auto, stream, grouped] --only Only executes the tasks specified, does not execute parent tasks - --remote-only [] - Ignore the local filesystem cache for all tasks. Only allow reading and caching artifacts using the remote cache [env: TURBO_REMOTE_ONLY=] [default: false] [possible values: true, false] + --remote-only [] + Ignore the local filesystem cache for all tasks. Only allow reading and caching artifacts using the remote cache [possible values: true, false] --log-prefix Use "none" to remove prefixes from task logs. Use "task" to get task id prefixing. Use "auto" to let turbo decide how to prefix the logs based on the execution environment. In most cases this will be the same as "task". Note that tasks running in parallel interleave their logs, so removing prefixes can make it difficult to associate logs with tasks. Use --log-order=grouped to prevent interleaving. (default auto) [default: auto] [possible values: auto, none, task] @@ -235,17 +235,14 @@ Test help flag --anon-profile File to write turbo's performance profile output into. All identifying data omitted from the profile - --remote-cache-read-only [] + --remote-cache-read-only [] Treat remote cache as read only - [env: TURBO_REMOTE_CACHE_READ_ONLY=] - [default: false] [possible values: true, false] --summarize [] Generate a summary of the turbo run - [env: TURBO_RUN_SUMMARY=] [possible values: true, false] --parallel @@ -253,8 +250,6 @@ Test help flag --cache-dir Override the filesystem cache directory - - [env: TURBO_CACHE_DIR=] --concurrency Limit the concurrency of task execution. Use 1 for serial (i.e. one-at-a-time) execution @@ -268,7 +263,6 @@ Test help flag --force [] Ignore the existing cache (to force execution) - [env: TURBO_FORCE=] [possible values: true, false] --framework-inference [] @@ -299,18 +293,14 @@ Test help flag --log-order Set type of task output order. Use "stream" to show output as soon as it is available. Use "grouped" to show output when a command has finished execution. Use "auto" to let turbo decide based on its own heuristics. (default auto) - [env: TURBO_LOG_ORDER=] - [default: auto] [possible values: auto, stream, grouped] --only Only executes the tasks specified, does not execute parent tasks - --remote-only [] + --remote-only [] Ignore the local filesystem cache for all tasks. Only allow reading and caching artifacts using the remote cache - [env: TURBO_REMOTE_ONLY=] - [default: false] [possible values: true, false] --log-prefix