Skip to content

Commit bb8f81e

Browse files
chore(config): move all uses of clap(env) to config (#9113)
### Description In an effort to get us where we're able to identify if there are multiple copies of run args* present this PR moves uses of `clap(env)` to `config/env.rs`. This also prepares us if we want to add some of these options to `turbo.json`. Each commit of this PR should be reviewed on it's own. The first chunk of this PR is some refactors to the config setup to reduce the copy-pasta of adding more env vars. **Explanation of `clap(env)` issue** Env vars being parsed at the CLI level results in problems for us as `TURBO_LOG_ORDER=grouped turbo run build --log-order stream` is totally valid command where we should stream logs, but it will result in `args.execution_args.log_order = LogOrder::Grouped` and `args.command.execution_args.log_order = LogOrder::Stream` and we can't tell if this is from env var usage or if the user typed `turbo --log-order=grouped run build --log-order=stream`. ### Testing Instructions Existing unit tests. Manually checking all of the changed flags/env vars e.g. ``` turbo build --filter=@turbo/types --flag FLAG=true turbo build --filter=@turbo/types ```
1 parent b7a00d3 commit bb8f81e

File tree

8 files changed

+249
-197
lines changed

8 files changed

+249
-197
lines changed

crates/turborepo-lib/src/cli/mod.rs

+53-24
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl From<OutputLogsMode> for turborepo_ui::tui::event::OutputLogs {
8787
}
8888
}
8989

90-
#[derive(Copy, Clone, Debug, PartialEq, Serialize, ValueEnum)]
90+
#[derive(Copy, Clone, Debug, PartialEq, Serialize, ValueEnum, Deserialize, Eq)]
9191
pub enum LogOrder {
9292
#[serde(rename = "auto")]
9393
Auto,
@@ -233,7 +233,9 @@ pub struct Args {
233233
// This should be inside `RunArgs` but clap currently has a bug
234234
// around nested flattened optional args: https://github.com/clap-rs/clap/issues/4697
235235
#[clap(flatten)]
236-
pub execution_args: Option<ExecutionArgs>,
236+
// DO NOT MAKE THIS VISIBLE
237+
// Instead use the getter method execution_args()
238+
execution_args: Option<ExecutionArgs>,
237239
#[clap(subcommand)]
238240
pub command: Option<Command>,
239241
}
@@ -474,6 +476,15 @@ impl Args {
474476
self.run_args.as_ref()
475477
}
476478
}
479+
480+
/// Fetch the execution args supplied to the command
481+
pub fn execution_args(&self) -> Option<&ExecutionArgs> {
482+
if let Some(Command::Run { execution_args, .. }) = &self.command {
483+
Some(execution_args)
484+
} else {
485+
self.execution_args.as_ref()
486+
}
487+
}
477488
}
478489

479490
/// 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),
710721
])]
711722
pub struct ExecutionArgs {
712723
/// Override the filesystem cache directory.
713-
#[clap(long, value_parser = path_non_empty, env = "TURBO_CACHE_DIR")]
724+
#[clap(long, value_parser = path_non_empty)]
714725
pub cache_dir: Option<Utf8PathBuf>,
715726
/// Limit the concurrency of task execution. Use 1 for serial (i.e.
716727
/// one-at-a-time) execution.
@@ -724,7 +735,7 @@ pub struct ExecutionArgs {
724735
#[clap(long)]
725736
pub single_package: bool,
726737
/// Ignore the existing cache (to force execution)
727-
#[clap(long, env = "TURBO_FORCE", default_missing_value = "true")]
738+
#[clap(long, default_missing_value = "true")]
728739
pub force: Option<Option<bool>>,
729740
/// Specify whether or not to do framework inference for tasks
730741
#[clap(long, value_name = "BOOL", action = ArgAction::Set, default_value = "true", default_missing_value = "true", num_args = 0..=1)]
@@ -761,17 +772,17 @@ pub struct ExecutionArgs {
761772
/// output as soon as it is available. Use "grouped" to
762773
/// show output when a command has finished execution. Use "auto" to let
763774
/// turbo decide based on its own heuristics. (default auto)
764-
#[clap(long, env = "TURBO_LOG_ORDER", value_enum, default_value_t = LogOrder::Auto)]
765-
pub log_order: LogOrder,
775+
#[clap(long, value_enum)]
776+
pub log_order: Option<LogOrder>,
766777
/// Only executes the tasks specified, does not execute parent tasks.
767778
#[clap(long)]
768779
pub only: bool,
769780
#[clap(long, hide = true)]
770781
pub pkg_inference_root: Option<String>,
771782
/// Ignore the local filesystem cache for all tasks. Only
772783
/// allow reading and caching artifacts using the remote cache.
773-
#[clap(long, env = "TURBO_REMOTE_ONLY", value_name = "BOOL", action = ArgAction::Set, default_value = "false", default_missing_value = "true", num_args = 0..=1)]
774-
pub remote_only: bool,
784+
#[clap(long, default_missing_value = "true")]
785+
pub remote_only: Option<Option<bool>>,
775786
/// Use "none" to remove prefixes from task logs. Use "task" to get task id
776787
/// prefixing. Use "auto" to let turbo decide how to prefix the logs
777788
/// based on the execution environment. In most cases this will be the same
@@ -790,14 +801,19 @@ pub struct ExecutionArgs {
790801
}
791802

792803
impl ExecutionArgs {
804+
pub fn remote_only(&self) -> Option<bool> {
805+
let remote_only = self.remote_only?;
806+
Some(remote_only.unwrap_or(true))
807+
}
808+
793809
fn track(&self, telemetry: &CommandEventBuilder) {
794810
// default to false
795811
track_usage!(telemetry, self.framework_inference, |val: bool| !val);
796812

797813
track_usage!(telemetry, self.continue_execution, |val| val);
798814
track_usage!(telemetry, self.single_package, |val| val);
799815
track_usage!(telemetry, self.only, |val| val);
800-
track_usage!(telemetry, self.remote_only, |val| val);
816+
track_usage!(telemetry, self.remote_only().unwrap_or_default(), |val| val);
801817
track_usage!(telemetry, &self.cache_dir, Option::is_some);
802818
track_usage!(telemetry, &self.force, Option::is_some);
803819
track_usage!(telemetry, &self.pkg_inference_root, Option::is_some);
@@ -822,8 +838,8 @@ impl ExecutionArgs {
822838
telemetry.track_arg_value("output-logs", output_logs, EventType::NonSensitive);
823839
}
824840

825-
if self.log_order != LogOrder::default() {
826-
telemetry.track_arg_value("log-order", self.log_order, EventType::NonSensitive);
841+
if let Some(log_order) = self.log_order {
842+
telemetry.track_arg_value("log-order", log_order, EventType::NonSensitive);
827843
}
828844

829845
if self.log_prefix != LogPrefix::default() {
@@ -882,10 +898,10 @@ pub struct RunArgs {
882898
#[clap(long, value_parser=NonEmptyStringValueParser::new(), conflicts_with = "profile")]
883899
pub anon_profile: Option<String>,
884900
/// Treat remote cache as read only
885-
#[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)]
886-
pub remote_cache_read_only: bool,
901+
#[clap(long, default_missing_value = "true")]
902+
pub remote_cache_read_only: Option<Option<bool>>,
887903
/// Generate a summary of the turbo run
888-
#[clap(long, env = "TURBO_RUN_SUMMARY", default_missing_value = "true")]
904+
#[clap(long, default_missing_value = "true")]
889905
pub summarize: Option<Option<bool>>,
890906

891907
// Pass a string to enable posting Run Summaries to Vercel
@@ -908,7 +924,7 @@ impl Default for RunArgs {
908924
no_daemon: false,
909925
profile: None,
910926
anon_profile: None,
911-
remote_cache_read_only: false,
927+
remote_cache_read_only: None,
912928
summarize: None,
913929
experimental_space_id: None,
914930
parallel: false,
@@ -938,13 +954,27 @@ impl RunArgs {
938954
}
939955
}
940956

957+
pub fn remote_cache_read_only(&self) -> Option<bool> {
958+
let remote_cache_read_only = self.remote_cache_read_only?;
959+
Some(remote_cache_read_only.unwrap_or(true))
960+
}
961+
962+
pub fn summarize(&self) -> Option<bool> {
963+
let summarize = self.summarize?;
964+
Some(summarize.unwrap_or(true))
965+
}
966+
941967
pub fn track(&self, telemetry: &CommandEventBuilder) {
942968
// default to true
943969
track_usage!(telemetry, self.no_cache, |val| val);
944970
track_usage!(telemetry, self.daemon, |val| val);
945971
track_usage!(telemetry, self.no_daemon, |val| val);
946972
track_usage!(telemetry, self.parallel, |val| val);
947-
track_usage!(telemetry, self.remote_cache_read_only, |val| val);
973+
track_usage!(
974+
telemetry,
975+
self.remote_cache_read_only().unwrap_or_default(),
976+
|val| val
977+
);
948978

949979
// default to None
950980
track_usage!(telemetry, &self.profile, Option::is_some);
@@ -1412,7 +1442,7 @@ mod test {
14121442
fn get_default_execution_args() -> ExecutionArgs {
14131443
ExecutionArgs {
14141444
output_logs: None,
1415-
remote_only: false,
1445+
remote_only: None,
14161446
framework_inference: true,
14171447
..ExecutionArgs::default()
14181448
}
@@ -1923,7 +1953,7 @@ mod test {
19231953
command: Some(Command::Run {
19241954
execution_args: Box::new(ExecutionArgs {
19251955
tasks: vec!["build".to_string()],
1926-
log_order: LogOrder::Stream,
1956+
log_order: Some(LogOrder::Stream),
19271957
..get_default_execution_args()
19281958
}),
19291959
run_args: Box::new(get_default_run_args())
@@ -1938,7 +1968,7 @@ mod test {
19381968
command: Some(Command::Run {
19391969
execution_args: Box::new(ExecutionArgs {
19401970
tasks: vec!["build".to_string()],
1941-
log_order: LogOrder::Grouped,
1971+
log_order: Some(LogOrder::Grouped),
19421972
..get_default_execution_args()
19431973
}),
19441974
run_args: Box::new(get_default_run_args())
@@ -1998,7 +2028,6 @@ mod test {
19982028
command: Some(Command::Run {
19992029
execution_args: Box::new(ExecutionArgs {
20002030
tasks: vec!["build".to_string()],
2001-
log_order: LogOrder::Auto,
20022031
..get_default_execution_args()
20032032
}),
20042033
run_args: Box::new(get_default_run_args())
@@ -2048,7 +2077,7 @@ mod test {
20482077
command: Some(Command::Run {
20492078
execution_args: Box::new(ExecutionArgs {
20502079
tasks: vec!["build".to_string()],
2051-
remote_only: false,
2080+
remote_only: None,
20522081
..get_default_execution_args()
20532082
}),
20542083
run_args: Box::new(get_default_run_args())
@@ -2063,7 +2092,7 @@ mod test {
20632092
command: Some(Command::Run {
20642093
execution_args: Box::new(ExecutionArgs {
20652094
tasks: vec!["build".to_string()],
2066-
remote_only: true,
2095+
remote_only: Some(Some(true)),
20672096
..get_default_execution_args()
20682097
}),
20692098
run_args: Box::new(get_default_run_args())
@@ -2078,7 +2107,7 @@ mod test {
20782107
command: Some(Command::Run {
20792108
execution_args: Box::new(ExecutionArgs {
20802109
tasks: vec!["build".to_string()],
2081-
remote_only: true,
2110+
remote_only: Some(Some(true)),
20822111
..get_default_execution_args()
20832112
}),
20842113
run_args: Box::new(get_default_run_args())
@@ -2093,7 +2122,7 @@ mod test {
20932122
command: Some(Command::Run {
20942123
execution_args: Box::new(ExecutionArgs {
20952124
tasks: vec!["build".to_string()],
2096-
remote_only: false,
2125+
remote_only: Some(Some(false)),
20972126
..get_default_execution_args()
20982127
}),
20992128
run_args: Box::new(get_default_run_args())

crates/turborepo-lib/src/commands/mod.rs

+22-37
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use turborepo_dirs::config_dir;
77
use turborepo_ui::ColorConfig;
88

99
use crate::{
10-
cli::Command,
1110
config::{ConfigurationOptions, Error as ConfigError, TurborepoConfigBuilder},
12-
turbo_json::UIMode,
1311
Args,
1412
};
1513

@@ -69,17 +67,7 @@ impl CommandBase {
6967
.with_token(self.args.token.clone())
7068
.with_timeout(self.args.remote_cache_timeout)
7169
.with_preflight(self.args.preflight.then_some(true))
72-
.with_ui(self.args.ui.or_else(|| {
73-
self.args.execution_args.as_ref().and_then(|args| {
74-
if !args.log_order.compatible_with_tui() {
75-
Some(UIMode::Stream)
76-
} else {
77-
// If the argument is compatible with the TUI this does not mean we should
78-
// override other configs
79-
None
80-
}
81-
})
82-
}))
70+
.with_ui(self.args.ui)
8371
.with_allow_no_package_manager(
8472
self.args
8573
.dangerously_disable_package_manager_check
@@ -88,33 +76,13 @@ impl CommandBase {
8876
.with_daemon(self.args.run_args().and_then(|args| args.daemon()))
8977
.with_env_mode(
9078
self.args
91-
.command
92-
.as_ref()
93-
.and_then(|c| match c {
94-
Command::Run { execution_args, .. } => execution_args.env_mode,
95-
_ => None,
96-
})
97-
.or_else(|| {
98-
self.args
99-
.execution_args
100-
.as_ref()
101-
.and_then(|args| args.env_mode)
102-
}),
79+
.execution_args()
80+
.and_then(|execution_args| execution_args.env_mode),
10381
)
10482
.with_cache_dir(
10583
self.args
106-
.command
107-
.as_ref()
108-
.and_then(|c| match c {
109-
Command::Run { execution_args, .. } => execution_args.cache_dir.clone(),
110-
_ => None,
111-
})
112-
.or_else(|| {
113-
self.args
114-
.execution_args
115-
.as_ref()
116-
.and_then(|args| args.cache_dir.clone())
117-
}),
84+
.execution_args()
85+
.and_then(|execution_args| execution_args.cache_dir.clone()),
11886
)
11987
.with_root_turbo_json_path(
12088
self.args
@@ -123,6 +91,23 @@ impl CommandBase {
12391
.map(AbsoluteSystemPathBuf::from_cwd)
12492
.transpose()?,
12593
)
94+
.with_force(
95+
self.args
96+
.execution_args()
97+
.and_then(|args| args.force.map(|value| value.unwrap_or(true))),
98+
)
99+
.with_log_order(self.args.execution_args().and_then(|args| args.log_order))
100+
.with_remote_only(
101+
self.args
102+
.execution_args()
103+
.and_then(|args| args.remote_only()),
104+
)
105+
.with_remote_cache_read_only(
106+
self.args
107+
.run_args()
108+
.and_then(|args| args.remote_cache_read_only()),
109+
)
110+
.with_run_summary(self.args.run_args().and_then(|args| args.summarize()))
126111
.build()
127112
}
128113

0 commit comments

Comments
 (0)