From 05188dad45cca6a946531e7fd398a493f5438a21 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Tue, 2 Apr 2024 17:53:10 -0400 Subject: [PATCH 1/4] Creating a watch walker for more granular re-running of tasks --- crates/turborepo-lib/src/cli/mod.rs | 10 ++-- crates/turborepo-lib/src/engine/execute.rs | 2 +- crates/turborepo-lib/src/engine/mod.rs | 69 ++++++++++++++++++++++ crates/turborepo-lib/src/run/builder.rs | 31 +++++++++- crates/turborepo-lib/src/run/mod.rs | 3 +- crates/turborepo-lib/src/run/task_id.rs | 9 +++ crates/turborepo-lib/src/run/watch.rs | 22 ++++--- crates/turborepo-lib/src/turbo_json/mod.rs | 16 +++++ 8 files changed, 145 insertions(+), 17 deletions(-) diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 2a3ceabdc7062..dbf3438c82dde 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -1346,17 +1346,17 @@ fn warn_all_deprecated_flags(args: &Args) { warn_flag_removal("--cpuprofile"); } - if let Some(Command::Run(run_args)) = args.command.as_ref() { - if run_args.since.is_some() { + if let Some(Command::Run { execution_args, .. }) = args.command.as_ref() { + if execution_args.since.is_some() { warn_flag_removal("--since"); } - if !run_args.scope.is_empty() { + if !execution_args.scope.is_empty() { warn_flag_removal("--scope"); } - if run_args.include_dependencies { + if execution_args.include_dependencies { warn_flag_removal("--include-dependencies"); } - if run_args.no_deps { + if execution_args.no_deps { warn_flag_removal("--no-deps"); } } diff --git a/crates/turborepo-lib/src/engine/execute.rs b/crates/turborepo-lib/src/engine/execute.rs index 699319444bb2f..067c263e71130 100644 --- a/crates/turborepo-lib/src/engine/execute.rs +++ b/crates/turborepo-lib/src/engine/execute.rs @@ -55,7 +55,7 @@ pub struct StopExecution; impl Engine { /// Execute a task graph by sending task ids to the visitor /// while respecting concurrency limits. - /// The visitor is expected to handle any error handling on it's end. + /// The visitor is expected to handle any error handling on its end. /// We enforce this by only allowing the returning of a sentinel error /// type which will stop any further execution of tasks. /// This will not stop any task which is currently running, simply it will diff --git a/crates/turborepo-lib/src/engine/mod.rs b/crates/turborepo-lib/src/engine/mod.rs index f65f504c3b72e..d2486068cc9b5 100644 --- a/crates/turborepo-lib/src/engine/mod.rs +++ b/crates/turborepo-lib/src/engine/mod.rs @@ -45,6 +45,7 @@ pub struct Engine { task_lookup: HashMap, petgraph::graph::NodeIndex>, task_definitions: HashMap, TaskDefinition>, task_locations: HashMap, Spanned<()>>, + package_tasks: HashMap>, } impl Engine { @@ -58,6 +59,7 @@ impl Engine { task_lookup: HashMap::default(), task_definitions: HashMap::default(), task_locations: HashMap::default(), + package_tasks: HashMap::default(), } } @@ -65,6 +67,11 @@ impl Engine { self.task_lookup.get(task_id).copied().unwrap_or_else(|| { let index = self.task_graph.add_node(TaskNode::Task(task_id.clone())); self.task_lookup.insert(task_id.clone(), index); + self.package_tasks + .entry(PackageName::from(task_id.package())) + .or_default() + .push(index); + index }) } @@ -103,6 +110,7 @@ impl Engine { root_index, task_definitions, task_locations, + package_tasks, .. } = self; Engine { @@ -112,6 +120,7 @@ impl Engine { root_index, task_definitions, task_locations, + package_tasks, } } } @@ -123,6 +132,66 @@ impl Default for Engine { } impl Engine { + /// Creates an instance of `Engine` that only contains tasks that depend on + /// tasks from a given package. This is useful for watch mode, where we + /// need to re-run only a portion of the task graph. + pub fn create_engine_for_subgraph( + &self, + changed_package: &PackageName, + ) -> Result, BuilderError> { + let entrypoint_indices: &[petgraph::graph::NodeIndex] = self + .package_tasks + .get(changed_package) + .map_or(&[], |v| &v[..]); + + // We reverse the graph because we want the *dependents* of entrypoint tasks + let mut reversed_graph = self.task_graph.clone(); + reversed_graph.reverse(); + + // This is `O(V^3)`, so in theory a bottleneck. Running dijkstra's + // algorithm for each entrypoint task could potentially be faster. + let node_distances = petgraph::algo::floyd_warshall::floyd_warshall(&reversed_graph, |_| 1) + .expect("no negative cycles"); + + let new_graph = self.task_graph.filter_map( + |node_idx, node| { + // If the node is reachable from any of the entrypoint tasks, we include it + entrypoint_indices + .iter() + .any(|idx| { + node_distances + .get(&(*idx, node_idx)) + .map_or(false, |dist| *dist != i32::MAX) + }) + .then_some(node.clone()) + }, + |_, _| Some(()), + ); + + let task_lookup: HashMap<_, _> = new_graph + .node_indices() + .filter_map(|index| { + let task = new_graph + .node_weight(index) + .expect("node index should be present"); + match task { + TaskNode::Root => None, + TaskNode::Task(task) => Some((task.clone(), index)), + } + }) + .collect(); + + Ok(Engine { + marker: std::marker::PhantomData, + root_index: self.root_index, + task_graph: new_graph, + task_lookup, + task_definitions: self.task_definitions.clone(), + task_locations: self.task_locations.clone(), + package_tasks: self.package_tasks.clone(), + }) + } + pub fn dependencies(&self, task_id: &TaskId) -> Option> { self.neighbors(task_id, petgraph::Direction::Outgoing) } diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index be13ddfc79b8b..761de1548e652 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -59,6 +59,11 @@ pub struct RunBuilder { experimental_ui: bool, api_client: APIClient, analytics_sender: Option, + // In watch mode, we can have a changed package that we want to serve as an entrypoint. + // We will then prune away any tasks that do not depend on tasks inside + // this package. + entrypoint_package: Option, + should_print_prelude_override: Option, } impl RunBuilder { @@ -98,6 +103,7 @@ impl RunBuilder { (!cfg!(windows) || experimental_ui), ); let CommandBase { repo_root, ui, .. } = base; + Ok(Self { processes, opts, @@ -108,9 +114,21 @@ impl RunBuilder { version, experimental_ui, analytics_sender: None, + entrypoint_package: None, + should_print_prelude_override: None, }) } + pub fn with_entrypoint_package(mut self, entrypoint_package: PackageName) -> Self { + self.entrypoint_package = Some(entrypoint_package); + self + } + + pub fn hide_prelude(mut self) -> Self { + self.should_print_prelude_override = Some(false); + self + } + fn connect_process_manager(&self, signal_subscriber: SignalSubscriber) { let manager = self.processes.clone(); tokio::spawn(async move { @@ -377,6 +395,10 @@ impl RunBuilder { self.opts.run_opts.env_mode = EnvMode::Strict; } + let should_print_prelude = self.should_print_prelude_override.unwrap_or_else(|| { + self.opts.run_opts.dry_run.is_none() && self.opts.run_opts.graph.is_none() + }); + Ok(Run { version: self.version, ui: self.ui, @@ -397,6 +419,7 @@ impl RunBuilder { engine: Arc::new(engine), run_cache, signal_handler: signal_handler.clone(), + should_print_prelude, }) } @@ -406,7 +429,7 @@ impl RunBuilder { root_turbo_json: &TurboJson, filtered_pkgs: &HashSet, ) -> Result { - let engine = EngineBuilder::new( + let mut engine = EngineBuilder::new( &self.repo_root, pkg_dep_graph, self.opts.run_opts.single_package, @@ -425,6 +448,12 @@ impl RunBuilder { })) .build()?; + // If we have an initial task, we prune out the engine to only + // tasks that are reachable from that initial task. + if let Some(entrypoint_package) = &self.entrypoint_package { + engine = engine.create_engine_for_subgraph(entrypoint_package)?; + } + if !self.opts.run_opts.parallel { engine .validate( diff --git a/crates/turborepo-lib/src/run/mod.rs b/crates/turborepo-lib/src/run/mod.rs index f47cec91d43dc..2e4ce5b4cc986 100644 --- a/crates/turborepo-lib/src/run/mod.rs +++ b/crates/turborepo-lib/src/run/mod.rs @@ -60,6 +60,7 @@ pub struct Run { signal_handler: SignalHandler, engine: Arc, task_access: TaskAccess, + should_print_prelude: bool, } impl Run { @@ -95,7 +96,7 @@ impl Run { } pub async fn run(&self) -> Result { - if self.opts.run_opts.dry_run.is_none() && self.opts.run_opts.graph.is_none() { + if self.should_print_prelude { self.print_run_prelude(); } if let Some(subscriber) = self.signal_handler.subscribe() { diff --git a/crates/turborepo-lib/src/run/task_id.rs b/crates/turborepo-lib/src/run/task_id.rs index ed18580837e33..b56e32d91b8b6 100644 --- a/crates/turborepo-lib/src/run/task_id.rs +++ b/crates/turborepo-lib/src/run/task_id.rs @@ -43,6 +43,15 @@ impl<'a> From> for String { } } +impl TaskId<'static> { + pub fn from_static(package: String, task: String) -> Self { + TaskId { + package: package.into(), + task: task.into(), + } + } +} + impl<'a> TaskId<'a> { pub fn new(package: &'a str, task: &'a str) -> Self { TaskId::try_from(task).unwrap_or_else(|_| Self { diff --git a/crates/turborepo-lib/src/run/watch.rs b/crates/turborepo-lib/src/run/watch.rs index 98dffa80936a1..dfe665da629ca 100644 --- a/crates/turborepo-lib/src/run/watch.rs +++ b/crates/turborepo-lib/src/run/watch.rs @@ -68,7 +68,7 @@ impl WatchClient { let mut new_base = base.clone(); new_base.args_mut().command = Some(Command::Run { - run_args: Box::new(RunArgs::default()), + run_args: Box::default(), execution_args: execution_args.clone(), }); @@ -79,6 +79,8 @@ impl WatchClient { .build(&handler, telemetry.clone()) .await?; + run.print_run_prelude(); + let connector = DaemonConnector { can_start_server: true, can_kill_server: true, @@ -143,10 +145,7 @@ impl WatchClient { args.command = args.command.map(|c| { if let Command::Watch(execution_args) = c { Command::Run { - execution_args: Box::new(ExecutionArgs { - filter: vec![format!("...{}", package_name)], - ..*execution_args - }), + execution_args: Box::new(ExecutionArgs { ..*execution_args }), run_args: Box::new(RunArgs { no_cache: true, daemon: true, @@ -166,14 +165,18 @@ impl WatchClient { run.abort(); } + let signal_handler = handler.clone(); let telemetry = telemetry.clone(); - let handler = handler.clone(); + current_runs.insert( - package_name, + package_name.clone(), tokio::spawn(async move { - let mut run = RunBuilder::new(new_base)? - .build(&handler, telemetry) + let run = RunBuilder::new(new_base)? + .with_entrypoint_package(package_name) + .hide_prelude() + .build(&signal_handler, telemetry) .await?; + run.run().await }), ); @@ -204,6 +207,7 @@ impl WatchClient { // rebuild run struct *run = RunBuilder::new(base.clone())? + .hide_prelude() .build(handler, telemetry.clone()) .await?; diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/src/turbo_json/mod.rs index 2de4b4533a046..14d292e0b02d9 100644 --- a/crates/turborepo-lib/src/turbo_json/mod.rs +++ b/crates/turborepo-lib/src/turbo_json/mod.rs @@ -604,6 +604,22 @@ impl TurboJson { } }; + if repo_root.join_component("Cargo.toml").exists() { + turbo_json.pipeline.insert( + TaskName::from("build").into_root_task(), + Spanned::new(RawTaskDefinition { + cache: Some(Spanned::new(true)), + inputs: Some(vec![ + Spanned::new("Cargo.toml".into()), + Spanned::new("Cargo.lock".into()), + Spanned::new("**/*.rs".into()), + ]), + outputs: Some(vec![Spanned::new("target".into())]), + ..RawTaskDefinition::default() + }), + ); + } + // TODO: Add location info from package.json for script_name in root_package_json.scripts.keys() { let task_name = TaskName::from(script_name.as_str()); From b809909e7028ea1710a83866fdc11c8e3a8608e9 Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Mon, 15 Apr 2024 16:17:59 -0400 Subject: [PATCH 2/4] Small clean up --- crates/turborepo-lib/src/engine/mod.rs | 9 +++------ crates/turborepo-lib/src/run/builder.rs | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/turborepo-lib/src/engine/mod.rs b/crates/turborepo-lib/src/engine/mod.rs index d2486068cc9b5..92347529b805e 100644 --- a/crates/turborepo-lib/src/engine/mod.rs +++ b/crates/turborepo-lib/src/engine/mod.rs @@ -135,10 +135,7 @@ impl Engine { /// Creates an instance of `Engine` that only contains tasks that depend on /// tasks from a given package. This is useful for watch mode, where we /// need to re-run only a portion of the task graph. - pub fn create_engine_for_subgraph( - &self, - changed_package: &PackageName, - ) -> Result, BuilderError> { + pub fn create_engine_for_subgraph(&self, changed_package: &PackageName) -> Engine { let entrypoint_indices: &[petgraph::graph::NodeIndex] = self .package_tasks .get(changed_package) @@ -181,7 +178,7 @@ impl Engine { }) .collect(); - Ok(Engine { + Engine { marker: std::marker::PhantomData, root_index: self.root_index, task_graph: new_graph, @@ -189,7 +186,7 @@ impl Engine { task_definitions: self.task_definitions.clone(), task_locations: self.task_locations.clone(), package_tasks: self.package_tasks.clone(), - }) + } } pub fn dependencies(&self, task_id: &TaskId) -> Option> { diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index 761de1548e652..922dced85b1e2 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -451,7 +451,7 @@ impl RunBuilder { // If we have an initial task, we prune out the engine to only // tasks that are reachable from that initial task. if let Some(entrypoint_package) = &self.entrypoint_package { - engine = engine.create_engine_for_subgraph(entrypoint_package)?; + engine = engine.create_engine_for_subgraph(entrypoint_package); } if !self.opts.run_opts.parallel { From 6d76103692d21717234e396a321df57055ee178a Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 17 Apr 2024 11:31:45 -0400 Subject: [PATCH 3/4] Fixed windows --- crates/turborepo-lib/src/commands/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/turborepo-lib/src/commands/run.rs b/crates/turborepo-lib/src/commands/run.rs index b18372d77ad32..e7a05aef88c5f 100644 --- a/crates/turborepo-lib/src/commands/run.rs +++ b/crates/turborepo-lib/src/commands/run.rs @@ -5,7 +5,7 @@ use turborepo_telemetry::events::command::CommandEventBuilder; use crate::{commands::CommandBase, run, run::builder::RunBuilder, signal::SignalHandler}; #[cfg(windows)] -pub async fn get_signal() -> Result>, run::Error> { +pub fn get_signal() -> Result>, run::Error> { let mut ctrl_c = tokio::signal::windows::ctrl_c().map_err(run::Error::SignalHandler)?; Ok(async move { ctrl_c.recv().await }) } From df46f8a517e08b18efa90cd0b500d5814469f18c Mon Sep 17 00:00:00 2001 From: nicholaslyang Date: Wed, 17 Apr 2024 12:41:51 -0400 Subject: [PATCH 4/4] Fix tests --- .../integration/tests/conflicting-flags.t | 4 +- turborepo-tests/integration/tests/no-args.t | 43 +++++----- .../integration/tests/turbo-help.t | 86 +++++++++---------- 3 files changed, 65 insertions(+), 68 deletions(-) diff --git a/turborepo-tests/integration/tests/conflicting-flags.t b/turborepo-tests/integration/tests/conflicting-flags.t index e293c65f8d198..0e0b278aa4809 100644 --- a/turborepo-tests/integration/tests/conflicting-flags.t +++ b/turborepo-tests/integration/tests/conflicting-flags.t @@ -1,9 +1,9 @@ Setup $ . ${TESTDIR}/../../helpers/setup_integration_test.sh $ ${TURBO} run build --daemon --no-daemon - ERROR the argument '--daemon' cannot be used with '--no-daemon' + ERROR the argument '--[no-]daemon' cannot be used with '--no-daemon' - Usage: turbo(\.exe)? run --daemon (re) + Usage: turbo(\.exe)? run --\[no-\]daemon (re) For more information, try '--help'. diff --git a/turborepo-tests/integration/tests/no-args.t b/turborepo-tests/integration/tests/no-args.t index 152ac332f9d78..c5f0d94e7266f 100644 --- a/turborepo-tests/integration/tests/no-args.t +++ b/turborepo-tests/integration/tests/no-args.t @@ -19,6 +19,7 @@ Make sure exit code is 2 when no args are passed logout Logout to your Vercel account prune Prepare a subset of your monorepo run Run tasks across projects in your monorepo + watch Arguments used in run and watch unlink Unlink the current directory from your Vercel organization and disable Remote Caching Options: @@ -41,16 +42,32 @@ Make sure exit code is 2 when no args are passed -h, --help Print help Run Arguments: - --cache-dir - Override the filesystem cache directory [env: TURBO_CACHE_DIR=] --cache-workers Set the number of concurrent cache operations (default 10) [default: 10] + --dry-run [] + [possible values: text, json] + --graph [] + Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided + --no-cache + Avoid saving task results to the cache. Useful for development/watch tasks + --[no-]daemon + Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic + --profile + 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] + --summarize [] + Generate a summary of the turbo run [env: TURBO_RUN_SUMMARY=] [possible values: true, false] + --parallel + Execute all tasks in parallel + --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 --continue Continue execution even if a task exits with an error or non-zero exit code. The default behavior is to bail - --dry-run [] - [possible values: text, json] --single-package Run turbo in single-package mode --force [] @@ -59,8 +76,6 @@ Make sure exit code is 2 when no args are passed Specify whether or not to do framework inference for tasks [default: true] [possible values: true, false] --global-deps Specify glob of global filesystem dependencies to be hashed. Useful for .env and files - --graph [] - Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided --env-mode [] Environment variable mode. Use "loose" to pass the entire existing environment. Use "strict" to use an allowlist specified in turbo.json. Use "infer" to defer to existence of "passThroughEnv" or "globalPassThroughEnv" in turbo.json. (default infer) [default: infer] [possible values: infer, loose, strict] -F, --filter @@ -75,30 +90,14 @@ Make sure exit code is 2 when no args are passed DEPRECATED: Include the dependencies of tasks in execution --no-deps DEPRECATED: Exclude dependent task consumers from execution - --no-cache - Avoid saving task results to the cache. Useful for development/watch tasks - --daemon - - --no-daemon - Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic --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] --only Only executes the tasks specified, does not execute parent tasks - --parallel - Execute all tasks in parallel - --profile - 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-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-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] --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] diff --git a/turborepo-tests/integration/tests/turbo-help.t b/turborepo-tests/integration/tests/turbo-help.t index 3619cf9a271fb..2757b18eb130d 100644 --- a/turborepo-tests/integration/tests/turbo-help.t +++ b/turborepo-tests/integration/tests/turbo-help.t @@ -19,6 +19,7 @@ Test help flag logout Logout to your Vercel account prune Prepare a subset of your monorepo run Run tasks across projects in your monorepo + watch Arguments used in run and watch unlink Unlink the current directory from your Vercel organization and disable Remote Caching Options: @@ -41,16 +42,32 @@ Test help flag -h, --help Print help Run Arguments: - --cache-dir - Override the filesystem cache directory [env: TURBO_CACHE_DIR=] --cache-workers Set the number of concurrent cache operations (default 10) [default: 10] + --dry-run [] + [possible values: text, json] + --graph [] + Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided + --no-cache + Avoid saving task results to the cache. Useful for development/watch tasks + --[no-]daemon + Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic + --profile + 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] + --summarize [] + Generate a summary of the turbo run [env: TURBO_RUN_SUMMARY=] [possible values: true, false] + --parallel + Execute all tasks in parallel + --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 --continue Continue execution even if a task exits with an error or non-zero exit code. The default behavior is to bail - --dry-run [] - [possible values: text, json] --single-package Run turbo in single-package mode --force [] @@ -59,8 +76,6 @@ Test help flag Specify whether or not to do framework inference for tasks [default: true] [possible values: true, false] --global-deps Specify glob of global filesystem dependencies to be hashed. Useful for .env and files - --graph [] - Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided --env-mode [] Environment variable mode. Use "loose" to pass the entire existing environment. Use "strict" to use an allowlist specified in turbo.json. Use "infer" to defer to existence of "passThroughEnv" or "globalPassThroughEnv" in turbo.json. (default infer) [default: infer] [possible values: infer, loose, strict] -F, --filter @@ -75,30 +90,14 @@ Test help flag DEPRECATED: Include the dependencies of tasks in execution --no-deps DEPRECATED: Exclude dependent task consumers from execution - --no-cache - Avoid saving task results to the cache. Useful for development/watch tasks - --daemon - - --no-daemon - Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic --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] --only Only executes the tasks specified, does not execute parent tasks - --parallel - Execute all tasks in parallel - --profile - 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-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-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] --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] @@ -124,6 +123,7 @@ Test help flag logout Logout to your Vercel account prune Prepare a subset of your monorepo run Run tasks across projects in your monorepo + watch Arguments used in run and watch unlink Unlink the current directory from your Vercel organization and disable Remote Caching Options: @@ -146,16 +146,32 @@ Test help flag -h, --help Print help Run Arguments: - --cache-dir - Override the filesystem cache directory [env: TURBO_CACHE_DIR=] --cache-workers Set the number of concurrent cache operations (default 10) [default: 10] + --dry-run [] + [possible values: text, json] + --graph [] + Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided + --no-cache + Avoid saving task results to the cache. Useful for development/watch tasks + --[no-]daemon + Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic + --profile + 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] + --summarize [] + Generate a summary of the turbo run [env: TURBO_RUN_SUMMARY=] [possible values: true, false] + --parallel + Execute all tasks in parallel + --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 --continue Continue execution even if a task exits with an error or non-zero exit code. The default behavior is to bail - --dry-run [] - [possible values: text, json] --single-package Run turbo in single-package mode --force [] @@ -164,8 +180,6 @@ Test help flag Specify whether or not to do framework inference for tasks [default: true] [possible values: true, false] --global-deps Specify glob of global filesystem dependencies to be hashed. Useful for .env and files - --graph [] - Generate a graph of the task execution and output to a file when a filename is specified (.svg, .png, .jpg, .pdf, .json, .html, .mermaid, .dot). Outputs dot graph to stdout when if no filename is provided --env-mode [] Environment variable mode. Use "loose" to pass the entire existing environment. Use "strict" to use an allowlist specified in turbo.json. Use "infer" to defer to existence of "passThroughEnv" or "globalPassThroughEnv" in turbo.json. (default infer) [default: infer] [possible values: infer, loose, strict] -F, --filter @@ -180,30 +194,14 @@ Test help flag DEPRECATED: Include the dependencies of tasks in execution --no-deps DEPRECATED: Exclude dependent task consumers from execution - --no-cache - Avoid saving task results to the cache. Useful for development/watch tasks - --daemon - - --no-daemon - Force turbo to either use or not use the local daemon. If unset turbo will use the default detection logic --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] --only Only executes the tasks specified, does not execute parent tasks - --parallel - Execute all tasks in parallel - --profile - 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-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-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] --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]