diff --git a/crates/turborepo-lib/src/package_changes_watcher.rs b/crates/turborepo-lib/src/package_changes_watcher.rs index dbd5298f77c7f..e9d38998f993d 100644 --- a/crates/turborepo-lib/src/package_changes_watcher.rs +++ b/crates/turborepo-lib/src/package_changes_watcher.rs @@ -23,7 +23,7 @@ use turborepo_repository::{ }; use turborepo_scm::GitHashes; -use crate::turbo_json::{TurboJson, TurboJsonLoader, CONFIG_FILE}; +use crate::turbo_json::{TurboJson, TurboJsonLoader, CONFIG_FILE, CONFIG_FILE_JSONC}; #[derive(Clone)] pub enum PackageChangeEvent { @@ -171,9 +171,30 @@ impl Subscriber { return None; }; + let turbo_json_path = self.repo_root.join_component(CONFIG_FILE); + let turbo_jsonc_path = self.repo_root.join_component(CONFIG_FILE_JSONC); + + let turbo_json_exists = turbo_json_path.exists(); + let turbo_jsonc_exists = turbo_jsonc_path.exists(); + + // TODO: Dedupe places where we search for turbo.json and turbo.jsonc + // There are now several places where we do this in the codebase + let config_path = match (turbo_json_exists, turbo_jsonc_exists) { + (true, true) => { + tracing::warn!( + "Found both turbo.json and turbo.jsonc in {}. Using turbo.json for watching.", + self.repo_root + ); + turbo_json_path + } + (true, false) => turbo_json_path, + (false, true) => turbo_jsonc_path, + (false, false) => turbo_json_path, // Default to turbo.json + }; + let root_turbo_json = TurboJsonLoader::workspace( self.repo_root.clone(), - self.repo_root.join_component(CONFIG_FILE), + config_path, pkg_dep_graph.packages(), ) .load(&PackageName::Root) @@ -327,6 +348,39 @@ impl Subscriber { root_gitignore = new_root_gitignore; } + // Check for changes to turbo.json or turbo.jsonc, and trigger rediscovery if + // either changed + let turbo_json_path = self.repo_root.join_component(CONFIG_FILE); + let turbo_jsonc_path = self.repo_root.join_component(CONFIG_FILE_JSONC); + + if trie.get(turbo_json_path.as_str()).is_some() + || trie.get(turbo_jsonc_path.as_str()).is_some() + { + tracing::info!( + "Detected change to turbo configuration file. Triggering rediscovery." + ); + let _ = self + .package_change_events_tx + .send(PackageChangeEvent::Rediscover); + + match self.initialize_repo_state().await { + Some((new_repo_state, new_gitignore)) => { + repo_state = new_repo_state; + root_gitignore = new_gitignore; + change_mapper = match repo_state.get_change_mapper() { + Some(change_mapper) => change_mapper, + None => { + break; + } + }; + } + None => { + break; + } + } + continue; + } + let changed_files: HashSet<_> = trie .keys() .filter_map(|p| { diff --git a/crates/turborepo-lib/src/run/watch.rs b/crates/turborepo-lib/src/run/watch.rs index c4d06dcb925d6..8376dbe734488 100644 --- a/crates/turborepo-lib/src/run/watch.rs +++ b/crates/turborepo-lib/src/run/watch.rs @@ -19,7 +19,7 @@ use crate::{ daemon::{proto, DaemonConnectorError, DaemonError}, get_version, opts, run::{self, builder::RunBuilder, scope::target_selector::InvalidSelectorError, Run}, - turbo_json::CONFIG_FILE, + turbo_json::{CONFIG_FILE, CONFIG_FILE_JSONC}, DaemonConnector, DaemonPaths, }; @@ -103,7 +103,7 @@ pub enum Error { UI(#[from] turborepo_ui::Error), #[error("Could not connect to UI thread: {0}")] UISend(String), - #[error("Cannot use root turbo.json at {0} with Watch Mode.")] + #[error("Cannot use non-standard turbo configuration at {0} with Watch Mode.")] NonStandardTurboJsonPath(String), #[error("Invalid config: {0}")] Config(#[from] crate::config::Error), @@ -120,9 +120,14 @@ impl WatchClient { let signal = get_signal()?; let handler = SignalHandler::new(signal); - // Check if the turbo.json path is the standard one - let standard_path = base.repo_root.join_component(CONFIG_FILE); - if base.opts.repo_opts.root_turbo_json_path != standard_path { + // Check if the turbo.json path is the standard one (either turbo.json or + // turbo.jsonc) + let standard_path_json = base.repo_root.join_component(CONFIG_FILE); + let standard_path_jsonc = base.repo_root.join_component(CONFIG_FILE_JSONC); + + if base.opts.repo_opts.root_turbo_json_path != standard_path_json + && base.opts.repo_opts.root_turbo_json_path != standard_path_jsonc + { return Err(Error::NonStandardTurboJsonPath( base.opts.repo_opts.root_turbo_json_path.to_string(), ));