From 23d2e16dbf4bb51f2a71cffed254a9fa292b6deb Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 10 Jul 2024 17:02:16 -0700 Subject: [PATCH 1/7] feat: add config option for disabling package manager requirement --- crates/turborepo-lib/src/cli/mod.rs | 20 ++ crates/turborepo-lib/src/commands/mod.rs | 5 + crates/turborepo-lib/src/config.rs | 45 ++- crates/turborepo-lib/src/turbo_json/mod.rs | 5 + turborepo-tests/integration/tests/no-args.t | 53 ++-- .../integration/tests/turbo-help.t | 288 ++++++++++++------ 6 files changed, 303 insertions(+), 113 deletions(-) diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index de97156366bb7..8642d3ad0e358 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -217,6 +217,12 @@ pub struct Args { pub check_for_update: bool, #[clap(long = "__test-run", global = true, hide = true)] pub test_run: bool, + /// Allow for missing `packageManager` in `package.json`. + /// + /// `turbo` will use hints from codebase to guess which package manager + /// should be used. + #[clap(long, global = true)] + pub dangerously_allow_no_package_manager: bool, #[clap(flatten, next_help_heading = "Run Arguments")] pub run_args: Option, // This should be inside `RunArgs` but clap currently has a bug @@ -2531,4 +2537,18 @@ mod test { assert!(!LogOrder::Stream.compatible_with_tui()); assert!(!LogOrder::Grouped.compatible_with_tui()); } + + #[test] + fn test_dangerously_allow_no_package_manager() { + assert!( + !Args::try_parse_from(["turbo", "build",]) + .unwrap() + .dangerously_allow_no_package_manager + ); + assert!( + Args::try_parse_from(["turbo", "build", "--dangerously-allow-no-package-manager"]) + .unwrap() + .dangerously_allow_no_package_manager + ); + } } diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/src/commands/mod.rs index 2420ff93cbc34..a051a58182a0e 100644 --- a/crates/turborepo-lib/src/commands/mod.rs +++ b/crates/turborepo-lib/src/commands/mod.rs @@ -79,6 +79,11 @@ impl CommandBase { } }) })) + .with_allow_no_package_manager( + self.args + .dangerously_allow_no_package_manager + .then_some(true), + ) .build() } diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index 772c49f156011..72d262023745a 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -208,6 +208,8 @@ pub struct ConfigurationOptions { pub(crate) spaces_id: Option, #[serde(rename = "ui")] pub(crate) ui: Option, + #[serde(rename = "dangerouslyAllowNoPackageManager")] + pub(crate) allow_no_package_manager: Option, } #[derive(Default)] @@ -281,6 +283,14 @@ fn non_empty_str(s: Option<&str>) -> Option<&str> { s.filter(|s| !s.is_empty()) } +fn truth_env_var(s: &str) -> Option { + match s { + "true" | "1" => Some(true), + "false" | "0" => Some(false), + _ => None, + } +} + trait ResolvedConfigurationOptions { fn get_configuration_options(self) -> Result; } @@ -331,6 +341,10 @@ fn get_env_var_config( "upload_timeout", ); turbo_mapping.insert(OsString::from("turbo_ui"), "ui"); + turbo_mapping.insert( + OsString::from("turbo_dangerously_allow_no_package_manager"), + "allow_no_package_manager", + ); turbo_mapping.insert(OsString::from("turbo_preflight"), "preflight"); // We do not enable new config sources: @@ -412,11 +426,15 @@ fn get_env_var_config( }; // Process experimentalUI - let ui = output_map.get("ui").and_then(|val| match val.as_str() { - "true" | "1" => Some(true), - "false" | "0" => Some(false), - _ => None, - }); + let ui = output_map + .get("ui") + .map(|s| s.as_str()) + .and_then(truth_env_var); + + let allow_no_package_manager = output_map + .get("allow_no_package_manager") + .map(|s| s.as_str()) + .and_then(truth_env_var); // 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 @@ -435,6 +453,7 @@ fn get_env_var_config( preflight, enabled, ui, + allow_no_package_manager, // Processed numbers timeout, @@ -498,6 +517,7 @@ fn get_override_env_var_config( timeout: None, upload_timeout: None, spaces_id: None, + allow_no_package_manager: None, }; Ok(output) @@ -633,6 +653,11 @@ impl TurborepoConfigBuilder { create_builder!(with_preflight, preflight, Option); create_builder!(with_timeout, timeout, Option); create_builder!(with_ui, ui, Option); + create_builder!( + with_allow_no_package_manager, + allow_no_package_manager, + Option + ); pub fn build(&self) -> Result { // Priority, from least significant to most significant: @@ -710,6 +735,11 @@ impl TurborepoConfigBuilder { if let Some(ui) = current_source_config.ui { acc.ui = Some(ui); } + if let Some(allow_no_package_manager) = + current_source_config.allow_no_package_manager + { + acc.allow_no_package_manager = Some(allow_no_package_manager); + } acc }) @@ -766,6 +796,10 @@ mod test { turbo_remote_cache_timeout.to_string().into(), ); env.insert("turbo_ui".into(), "true".into()); + env.insert( + "turbo_dangerously_allow_no_package_manager".into(), + "true".into(), + ); env.insert("turbo_preflight".into(), "true".into()); let config = get_env_var_config(&env).unwrap(); @@ -777,6 +811,7 @@ mod test { assert_eq!(turbo_token, config.token.unwrap()); assert_eq!(turbo_remote_cache_timeout, config.timeout.unwrap()); assert_eq!(Some(true), config.ui); + assert_eq!(Some(true), config.allow_no_package_manager); } #[test] diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/src/turbo_json/mod.rs index edd6edb6df374..ba085dad5cc5d 100644 --- a/crates/turborepo-lib/src/turbo_json/mod.rs +++ b/crates/turborepo-lib/src/turbo_json/mod.rs @@ -126,6 +126,11 @@ pub struct RawTurboJson { pub(crate) remote_cache: Option, #[serde(skip_serializing_if = "Option::is_none", rename = "ui")] pub ui: Option, + #[serde( + skip_serializing_if = "Option::is_none", + rename = "dangerouslyAllowNoPackageManager" + )] + pub allow_no_package_manager: Option, #[deserializable(rename = "//")] #[serde(skip)] diff --git a/turborepo-tests/integration/tests/no-args.t b/turborepo-tests/integration/tests/no-args.t index 647b6982d1919..7f46dee3aa459 100644 --- a/turborepo-tests/integration/tests/no-args.t +++ b/turborepo-tests/integration/tests/no-args.t @@ -23,23 +23,42 @@ Make sure exit code is 2 when no args are passed unlink Unlink the current directory from your Vercel organization and disable Remote Caching Options: - --version - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --version + + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') Run Arguments: --cache-workers diff --git a/turborepo-tests/integration/tests/turbo-help.t b/turborepo-tests/integration/tests/turbo-help.t index d6d43e7530a7f..9d8fcc03772c9 100644 --- a/turborepo-tests/integration/tests/turbo-help.t +++ b/turborepo-tests/integration/tests/turbo-help.t @@ -23,23 +23,42 @@ Test help flag unlink Unlink the current directory from your Vercel organization and disable Remote Caching Options: - --version - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --version + + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') Run Arguments: --cache-workers @@ -169,6 +188,11 @@ Test help flag --verbosity Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json`. + + `turbo` will use hints from codebase to guess which package manager should be used. + -h, --help Print help (see a summary with '-h') @@ -285,25 +309,46 @@ Test help flag for link command Usage: turbo(\.exe)? link \[OPTIONS\] (re) Options: - --no-gitignore Do not create or modify .gitignore (default false) - --version - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --target Specify what should be linked (default "remote cache") [default: remote-cache] [possible values: remote-cache, spaces] - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --no-gitignore + Do not create or modify .gitignore (default false) + --version + + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --target + Specify what should be linked (default "remote cache") [default: remote-cache] [possible values: remote-cache, spaces] + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') Test help flag for unlink command $ ${TURBO} unlink -h @@ -312,24 +357,44 @@ Test help flag for unlink command Usage: turbo(\.exe)? unlink \[OPTIONS\] (re) Options: - --target Specify what should be unlinked (default "remote cache") [default: remote-cache] [possible values: remote-cache, spaces] - --version - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --target + Specify what should be unlinked (default "remote cache") [default: remote-cache] [possible values: remote-cache, spaces] + --version + + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') Test help flag for login command $ ${TURBO} login -h @@ -338,25 +403,46 @@ Test help flag for login command Usage: turbo(\.exe)? login \[OPTIONS\] (re) Options: - --sso-team - --version - -f, --force Force a login to receive a new token. Will overwrite any existing tokens for the given login url - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --sso-team + + --version + + -f, --force + Force a login to receive a new token. Will overwrite any existing tokens for the given login url + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') Test help flag for logout command $ ${TURBO} logout -h @@ -365,21 +451,41 @@ Test help flag for logout command Usage: turbo(\.exe)? logout \[OPTIONS\] (re) Options: - --invalidate Invalidate the token on the server - --version - --skip-infer Skip any attempts to infer which version of Turbo the project is configured to use - --no-update-notifier Disable the turbo update notification - --api Override the endpoint for API calls - --color Force color usage in the terminal - --cwd The directory in which to run turbo - --heap Specify a file to save a pprof heap profile - --ui Specify whether to use the streaming UI or TUI [possible values: tui, stream] - --login Override the login endpoint - --no-color Suppress color usage in the terminal - --preflight When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization - --remote-cache-timeout Set a timeout for all HTTP requests - --team Set the team slug for API calls - --token Set the auth token for API calls - --trace Specify a file to save a pprof trace - --verbosity Verbosity level - -h, --help Print help (see more with '--help') + --invalidate + Invalidate the token on the server + --version + + --skip-infer + Skip any attempts to infer which version of Turbo the project is configured to use + --no-update-notifier + Disable the turbo update notification + --api + Override the endpoint for API calls + --color + Force color usage in the terminal + --cwd + The directory in which to run turbo + --heap + Specify a file to save a pprof heap profile + --ui + Specify whether to use the streaming UI or TUI [possible values: tui, stream] + --login + Override the login endpoint + --no-color + Suppress color usage in the terminal + --preflight + When enabled, turbo will precede HTTP requests with an OPTIONS request for authorization + --remote-cache-timeout + Set a timeout for all HTTP requests + --team + Set the team slug for API calls + --token + Set the auth token for API calls + --trace + Specify a file to save a pprof trace + --verbosity + Verbosity level + --dangerously-allow-no-package-manager + Allow for missing `packageManager` in `package.json` + -h, --help + Print help (see more with '--help') From 198bd01b18202fc3ed1326564e1aa059258332d7 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 Jul 2024 07:34:01 -0700 Subject: [PATCH 2/7] chore: add back package manager detection logic --- .../src/package_manager/bun.rs | 62 +++++++++++++++++++ .../src/package_manager/mod.rs | 24 +++++++ .../src/package_manager/npm.rs | 62 +++++++++++++++++++ .../src/package_manager/pnpm.rs | 48 ++++++++++++-- .../src/package_manager/yarn.rs | 52 +++++++++++++++- 5 files changed, 240 insertions(+), 8 deletions(-) diff --git a/crates/turborepo-repository/src/package_manager/bun.rs b/crates/turborepo-repository/src/package_manager/bun.rs index ab6c654664117..4ed64cb207d46 100644 --- a/crates/turborepo-repository/src/package_manager/bun.rs +++ b/crates/turborepo-repository/src/package_manager/bun.rs @@ -1 +1,63 @@ +use turbopath::AbsoluteSystemPath; + +use crate::package_manager::{Error, PackageManager}; + pub const LOCKFILE: &str = "bun.lockb"; + +pub struct BunDetector<'a> { + repo_root: &'a AbsoluteSystemPath, + found: bool, +} + +impl<'a> BunDetector<'a> { + pub fn new(repo_root: &'a AbsoluteSystemPath) -> Self { + Self { + repo_root, + found: false, + } + } +} + +impl<'a> Iterator for BunDetector<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.found { + return None; + } + + self.found = true; + let package_json = self.repo_root.join_component(LOCKFILE); + + if package_json.exists() { + Some(Ok(PackageManager::Bun)) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + use std::fs::File; + + use anyhow::Result; + use tempfile::tempdir; + use turbopath::AbsoluteSystemPathBuf; + + use super::LOCKFILE; + use crate::package_manager::PackageManager; + + #[test] + fn test_detect_bun() -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + + let lockfile_path = repo_root.path().join(LOCKFILE); + File::create(lockfile_path)?; + let package_manager = PackageManager::detect_package_manager(&repo_root_path)?; + assert_eq!(package_manager, PackageManager::Bun); + + Ok(()) + } +} diff --git a/crates/turborepo-repository/src/package_manager/mod.rs b/crates/turborepo-repository/src/package_manager/mod.rs index f22490083e667..f4bf6aabd3caf 100644 --- a/crates/turborepo-repository/src/package_manager/mod.rs +++ b/crates/turborepo-repository/src/package_manager/mod.rs @@ -11,9 +11,11 @@ use std::{ str::FromStr, }; +use bun::BunDetector; use globwalk::{fix_glob_pattern, ValidatedGlob}; use itertools::{Either, Itertools}; use lazy_regex::{lazy_regex, Lazy}; +use npm::NpmDetector; use regex::Regex; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -454,6 +456,28 @@ impl PackageManager { } } + /// Detect package manager based on configuration files and binaries + /// installed on the system. + pub fn detect_package_manager(repo_root: &AbsoluteSystemPath) -> Result { + let detected_package_managers = PnpmDetector::new(repo_root) + .chain(NpmDetector::new(repo_root)) + .chain(YarnDetector::new(repo_root)) + .chain(BunDetector::new(repo_root)) + .collect::, Error>>()?; + + match detected_package_managers.as_slice() { + [] => Err(NoPackageManager.into()), + [package_manager] => Ok(*package_manager), + _ => { + let managers = detected_package_managers + .iter() + .map(|mgr| mgr.to_string()) + .collect(); + Err(Error::MultiplePackageManagers { managers }) + } + } + } + pub(crate) fn parse_package_manager_string(manager: &str) -> Result<(&str, &str), Error> { if let Some(captures) = PACKAGE_MANAGER_PATTERN.captures(manager) { let manager = captures.name("manager").unwrap().as_str(); diff --git a/crates/turborepo-repository/src/package_manager/npm.rs b/crates/turborepo-repository/src/package_manager/npm.rs index 73a0f58646ce9..969e2dd3cb820 100644 --- a/crates/turborepo-repository/src/package_manager/npm.rs +++ b/crates/turborepo-repository/src/package_manager/npm.rs @@ -1 +1,63 @@ +use turbopath::AbsoluteSystemPath; + +use crate::package_manager::{Error, PackageManager}; + pub const LOCKFILE: &str = "package-lock.json"; + +pub struct NpmDetector<'a> { + repo_root: &'a AbsoluteSystemPath, + found: bool, +} + +impl<'a> NpmDetector<'a> { + pub fn new(repo_root: &'a AbsoluteSystemPath) -> Self { + Self { + repo_root, + found: false, + } + } +} + +impl<'a> Iterator for NpmDetector<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.found { + return None; + } + + self.found = true; + let package_json = self.repo_root.join_component(LOCKFILE); + + if package_json.exists() { + Some(Ok(PackageManager::Npm)) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + use std::fs::File; + + use anyhow::Result; + use tempfile::tempdir; + use turbopath::AbsoluteSystemPathBuf; + + use super::LOCKFILE; + use crate::package_manager::PackageManager; + + #[test] + fn test_detect_npm() -> Result<()> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + + let lockfile_path = repo_root.path().join(LOCKFILE); + File::create(lockfile_path)?; + let package_manager = PackageManager::detect_package_manager(&repo_root_path)?; + assert_eq!(package_manager, PackageManager::Npm); + + Ok(()) + } +} diff --git a/crates/turborepo-repository/src/package_manager/pnpm.rs b/crates/turborepo-repository/src/package_manager/pnpm.rs index 1bafa8e46b1f8..6a51288d230a5 100644 --- a/crates/turborepo-repository/src/package_manager/pnpm.rs +++ b/crates/turborepo-repository/src/package_manager/pnpm.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use node_semver::{Range, Version}; -use turbopath::RelativeUnixPath; +use turbopath::{AbsoluteSystemPath, RelativeUnixPath}; use crate::{ package_json::PackageJson, @@ -10,9 +10,19 @@ use crate::{ pub const LOCKFILE: &str = "pnpm-lock.yaml"; -pub struct PnpmDetector; +pub struct PnpmDetector<'a> { + found: bool, + repo_root: &'a AbsoluteSystemPath, +} + +impl<'a> PnpmDetector<'a> { + pub fn new(repo_root: &'a AbsoluteSystemPath) -> Self { + Self { + repo_root, + found: false, + } + } -impl PnpmDetector { pub fn detect_pnpm6_or_pnpm(version: &Version) -> Result { let pnpm6_constraint: Range = "<7.0.0".parse()?; let pnpm9_constraint: Range = ">=9.0.0-alpha.0".parse()?; @@ -26,6 +36,21 @@ impl PnpmDetector { } } +impl<'a> Iterator for PnpmDetector<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.found { + return None; + } + self.found = true; + + let pnpm_lockfile = self.repo_root.join_component(LOCKFILE); + + pnpm_lockfile.exists().then(|| Ok(PackageManager::Pnpm)) + } +} + pub(crate) fn prune_patches>( package_json: &PackageJson, patches: &[R], @@ -46,14 +71,27 @@ pub(crate) fn prune_patches>( #[cfg(test)] mod test { - use std::collections::BTreeMap; + use std::{collections::BTreeMap, fs::File}; use serde_json::json; + use tempfile::tempdir; use test_case::test_case; - use turbopath::RelativeUnixPathBuf; + use turbopath::{AbsoluteSystemPathBuf, RelativeUnixPathBuf}; use super::*; + #[test] + fn test_detect_pnpm() -> Result<(), Error> { + let repo_root = tempdir()?; + let repo_root_path = AbsoluteSystemPathBuf::try_from(repo_root.path())?; + let lockfile_path = repo_root.path().join(LOCKFILE); + File::create(lockfile_path)?; + let package_manager = PackageManager::detect_package_manager(&repo_root_path)?; + assert_eq!(package_manager, PackageManager::Pnpm); + + Ok(()) + } + #[test] fn test_patch_pruning() { let package_json: PackageJson = PackageJson::from_value(json!({ diff --git a/crates/turborepo-repository/src/package_manager/yarn.rs b/crates/turborepo-repository/src/package_manager/yarn.rs index 25d5bb3dae46d..cf4b27e75b12e 100644 --- a/crates/turborepo-repository/src/package_manager/yarn.rs +++ b/crates/turborepo-repository/src/package_manager/yarn.rs @@ -1,5 +1,8 @@ +use std::process::Command; + use node_semver::{Range, Version}; -use turbopath::RelativeUnixPath; +use turbopath::{AbsoluteSystemPath, RelativeUnixPath}; +use which::which; use crate::{ package_json::PackageJson, @@ -8,9 +11,30 @@ use crate::{ pub const LOCKFILE: &str = "yarn.lock"; -pub struct YarnDetector; +pub struct YarnDetector<'a> { + repo_root: &'a AbsoluteSystemPath, + found: bool, +} + +impl<'a> YarnDetector<'a> { + pub fn new(repo_root: &'a AbsoluteSystemPath) -> Self { + Self { + repo_root, + found: false, + } + } + + fn get_yarn_version(&self) -> Result { + let binary = "yarn"; + let yarn_binary = which(binary).map_err(|e| Error::Which(e, binary.to_string()))?; + let output = Command::new(yarn_binary) + .arg("--version") + .current_dir(self.repo_root) + .output()?; + let yarn_version_output = String::from_utf8(output.stdout)?; + Ok(yarn_version_output.trim().parse()?) + } -impl YarnDetector { pub fn detect_berry_or_yarn(version: &Version) -> Result { let berry_constraint: Range = ">=2.0.0-0".parse()?; if berry_constraint.satisfies(version) { @@ -43,6 +67,28 @@ pub(crate) fn prune_patches>( pruned_json } +impl<'a> Iterator for YarnDetector<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.found { + return None; + } + self.found = true; + + let yarn_lockfile = self.repo_root.join_component(LOCKFILE); + + if yarn_lockfile.exists() { + Some( + self.get_yarn_version() + .and_then(|version| Self::detect_berry_or_yarn(&version)), + ) + } else { + None + } + } +} + #[cfg(test)] mod tests { use std::collections::BTreeMap; From 911292b67f759fe05762e05921ee0a327332a61f Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 Jul 2024 10:29:37 -0700 Subject: [PATCH 3/7] chore: add telemetry for allow missing package manager --- crates/turborepo-lib/src/commands/prune.rs | 11 ++++++++++- crates/turborepo-lib/src/config.rs | 4 ++++ crates/turborepo-lib/src/run/builder.rs | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/turborepo-lib/src/commands/prune.rs b/crates/turborepo-lib/src/commands/prune.rs index b44c0ce86953a..3ea5c617ff4fe 100644 --- a/crates/turborepo-lib/src/commands/prune.rs +++ b/crates/turborepo-lib/src/commands/prune.rs @@ -49,6 +49,8 @@ pub enum Error { MissingLockfile, #[error("Prune is not supported for Bun")] BunUnsupported, + #[error("Unable to read config: {0}")] + Config(#[from] crate::config::Error), } // Files that should be copied from root and if they're required for install @@ -96,7 +98,7 @@ pub async fn prune( telemetry.track_arg_usage("docker", docker); telemetry.track_arg_usage("out-dir", output_dir != DEFAULT_OUTPUT_DIR); - let prune = Prune::new(base, scope, docker, output_dir).await?; + let prune = Prune::new(base, scope, docker, output_dir, telemetry).await?; if matches!( prune.package_graph.package_manager(), @@ -259,7 +261,14 @@ impl<'a> Prune<'a> { scope: &'a [String], docker: bool, output_dir: &str, + telemetry: CommandEventBuilder, ) -> Result { + let allow_missing_package_manager = base.config()?.allow_no_package_manager(); + telemetry.track_arg_usage( + "dangerously-allow-missing-package-manager", + allow_missing_package_manager, + ); + if scope.is_empty() { return Err(Error::NoWorkspaceSpecified); } diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index 72d262023745a..c15546400a12a 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -276,6 +276,10 @@ impl ConfigurationOptions { pub fn ui(&self) -> bool { self.ui.unwrap_or(false) && atty::is(atty::Stream::Stdout) } + + pub fn allow_no_package_manager(&self) -> bool { + self.allow_no_package_manager.unwrap_or_default() + } } // Maps Some("") to None to emulate how Go handles empty strings diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index 0d67fd258b30e..a97b33a1d6229 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -64,6 +64,7 @@ pub struct RunBuilder { // this package. entrypoint_packages: Option>, should_print_prelude_override: Option, + allow_missing_package_manager: bool, } impl RunBuilder { @@ -73,6 +74,8 @@ impl RunBuilder { let mut opts: Opts = base.args().try_into()?; let config = base.config()?; + let allow_missing_package_manager = config.allow_no_package_manager(); + let is_linked = turborepo_api_client::is_linked(&api_auth); if !is_linked { opts.cache_opts.skip_remote = true; @@ -116,6 +119,7 @@ impl RunBuilder { analytics_sender: None, entrypoint_packages: None, should_print_prelude_override: None, + allow_missing_package_manager, }) } @@ -187,6 +191,10 @@ impl RunBuilder { // Pulled from initAnalyticsClient in run.go let is_linked = turborepo_api_client::is_linked(&self.api_auth); run_telemetry.track_is_linked(is_linked); + run_telemetry.track_arg_usage( + "dangerously_allow_missing_package_manager", + self.allow_missing_package_manager, + ); // we only track the remote cache if we're linked because this defaults to // Vercel if is_linked { From 3c1875d3345b3f5d3d4bc710970934173854e72f Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 Jul 2024 11:13:54 -0700 Subject: [PATCH 4/7] chore: remove conditional compilation of daemon package discovery --- crates/turborepo-lib/src/run/builder.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index a97b33a1d6229..80ec1f2b0fdc8 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -214,8 +214,7 @@ impl RunBuilder { run_telemetry.track_ci(turborepo_ci::Vendor::get_name()); // Remove allow when daemon is flagged back on - #[allow(unused_mut)] - let mut daemon = match (is_ci_or_not_tty, self.opts.run_opts.daemon) { + let daemon = match (is_ci_or_not_tty, self.opts.run_opts.daemon) { (true, None) => { run_telemetry.track_daemon_init(DaemonInitStatus::Skipped); debug!("skipping turbod since we appear to be in a non-interactive context"); @@ -256,8 +255,7 @@ impl RunBuilder { let builder = PackageGraph::builder(&self.repo_root, root_package_json.clone()) .with_single_package_mode(self.opts.run_opts.single_package); - #[cfg(feature = "daemon-package-discovery")] - let graph = { + let graph = if cfg!(feature = "daemon-package-discovery") { match (&daemon, self.opts.run_opts.daemon) { (None, Some(true)) => { // We've asked for the daemon, but it's not available. This is an error @@ -299,9 +297,9 @@ impl RunBuilder { .await } } + } else { + builder.build().await }; - #[cfg(not(feature = "daemon-package-discovery"))] - let graph = builder.build().await; match graph { Ok(graph) => graph, From 066ec396e2e70cdc1a71af8f182e6d9e4a51e06b Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 11 Jul 2024 17:25:22 -0700 Subject: [PATCH 5/7] feat: allow missing packageManager in package.json --- crates/turborepo-lib/src/commands/prune.rs | 1 + crates/turborepo-lib/src/config.rs | 1 + crates/turborepo-lib/src/run/builder.rs | 8 ++++++-- crates/turborepo-repository/src/discovery.rs | 12 +++++++++++- crates/turborepo-repository/src/inference.rs | 3 ++- .../src/package_graph/builder.rs | 6 ++++++ .../src/package_manager/mod.rs | 18 +++++++++++------- 7 files changed, 38 insertions(+), 11 deletions(-) diff --git a/crates/turborepo-lib/src/commands/prune.rs b/crates/turborepo-lib/src/commands/prune.rs index 3ea5c617ff4fe..9459164233b7b 100644 --- a/crates/turborepo-lib/src/commands/prune.rs +++ b/crates/turborepo-lib/src/commands/prune.rs @@ -277,6 +277,7 @@ impl<'a> Prune<'a> { let root_package_json = PackageJson::load(&root_package_json_path)?; let package_graph = PackageGraph::builder(&base.repo_root, root_package_json) + .with_allow_no_package_manager(allow_missing_package_manager) .build() .await?; diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index c15546400a12a..ca62e3add0c58 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -313,6 +313,7 @@ impl ResolvedConfigurationOptions for RawTurboJson { .and_then(|spaces| spaces.id) .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; Ok(opts) } } diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index 80ec1f2b0fdc8..3bc96d3a5543c 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -253,9 +253,13 @@ impl RunBuilder { let mut pkg_dep_graph = { let builder = PackageGraph::builder(&self.repo_root, root_package_json.clone()) - .with_single_package_mode(self.opts.run_opts.single_package); + .with_single_package_mode(self.opts.run_opts.single_package) + .with_allow_no_package_manager(self.allow_missing_package_manager); - let graph = if cfg!(feature = "daemon-package-discovery") { + // Daemon package discovery depends on packageManager existing in package.json + let graph = if cfg!(feature = "daemon-package-discovery") + && !self.allow_missing_package_manager + { match (&daemon, self.opts.run_opts.daemon) { (None, Some(true)) => { // We've asked for the daemon, but it's not available. This is an error diff --git a/crates/turborepo-repository/src/discovery.rs b/crates/turborepo-repository/src/discovery.rs index 7a984666167ea..ec2128e41c379 100644 --- a/crates/turborepo-repository/src/discovery.rs +++ b/crates/turborepo-repository/src/discovery.rs @@ -84,6 +84,7 @@ pub struct LocalPackageDiscoveryBuilder { repo_root: AbsoluteSystemPathBuf, package_manager: Option, package_json: Option, + allow_missing_package_manager: bool, } impl LocalPackageDiscoveryBuilder { @@ -96,8 +97,13 @@ impl LocalPackageDiscoveryBuilder { repo_root, package_manager, package_json, + allow_missing_package_manager: false, } } + + pub fn with_allow_no_package_manager(&mut self, allow_missing_package_manager: bool) { + self.allow_missing_package_manager = allow_missing_package_manager; + } } impl PackageDiscoveryBuilder for LocalPackageDiscoveryBuilder { @@ -111,7 +117,11 @@ impl PackageDiscoveryBuilder for LocalPackageDiscoveryBuilder { let package_json = self.package_json.map(Ok).unwrap_or_else(|| { PackageJson::load(&self.repo_root.join_component("package.json")) })?; - PackageManager::get_package_manager(&package_json)? + if self.allow_missing_package_manager { + PackageManager::read_or_detect_package_manager(&package_json, &self.repo_root)? + } else { + PackageManager::get_package_manager(&package_json)? + } } }; diff --git a/crates/turborepo-repository/src/inference.rs b/crates/turborepo-repository/src/inference.rs index cd2fbc9cb8187..917ef283d6365 100644 --- a/crates/turborepo-repository/src/inference.rs +++ b/crates/turborepo-repository/src/inference.rs @@ -80,7 +80,8 @@ impl RepoState { .ok() .map(|package_json| { // FIXME: We should save this package manager that we detected - let package_manager = PackageManager::get_package_manager(&package_json); + let package_manager = + PackageManager::read_or_detect_package_manager(&package_json, path); let workspace_globs = package_manager .as_ref() .ok() diff --git a/crates/turborepo-repository/src/package_graph/builder.rs b/crates/turborepo-repository/src/package_graph/builder.rs index d4cc22839ed29..68d8fa4a90446 100644 --- a/crates/turborepo-repository/src/package_graph/builder.rs +++ b/crates/turborepo-repository/src/package_graph/builder.rs @@ -78,6 +78,12 @@ impl<'a> PackageGraphBuilder<'a, LocalPackageDiscoveryBuilder> { lockfile: None, } } + + pub fn with_allow_no_package_manager(mut self, allow_no_package_manager: bool) -> Self { + self.package_discovery + .with_allow_no_package_manager(allow_no_package_manager); + self + } } impl<'a, P> PackageGraphBuilder<'a, P> { diff --git a/crates/turborepo-repository/src/package_manager/mod.rs b/crates/turborepo-repository/src/package_manager/mod.rs index f4bf6aabd3caf..2f04c99de57ec 100644 --- a/crates/turborepo-repository/src/package_manager/mod.rs +++ b/crates/turborepo-repository/src/package_manager/mod.rs @@ -429,12 +429,7 @@ impl PackageManager { ) } - /// Try to detect the package manager by inspecting the repository. - /// This method does not read the package.json, instead looking for - /// lockfiles and other files that indicate the package manager. - /// - /// TODO: consider if this method should not need an Option, and possibly be - /// a method on PackageJSON + /// Try to extract the package manager from package.json. pub fn get_package_manager(package_json: &PackageJson) -> Result { Self::read_package_manager(package_json) } @@ -456,7 +451,7 @@ impl PackageManager { } } - /// Detect package manager based on configuration files and binaries + /// Try to detect package manager based on configuration files and binaries /// installed on the system. pub fn detect_package_manager(repo_root: &AbsoluteSystemPath) -> Result { let detected_package_managers = PnpmDetector::new(repo_root) @@ -478,6 +473,15 @@ impl PackageManager { } } + /// Try to extract package manager from package.json, otherwise detect based + /// on configuration files and binaries installed on the system + pub fn read_or_detect_package_manager( + package_json: &PackageJson, + repo_root: &AbsoluteSystemPath, + ) -> Result { + Self::get_package_manager(package_json).or_else(|_| Self::detect_package_manager(repo_root)) + } + pub(crate) fn parse_package_manager_string(manager: &str) -> Result<(&str, &str), Error> { if let Some(captures) = PACKAGE_MANAGER_PATTERN.captures(manager) { let manager = captures.name("manager").unwrap().as_str(); From 318fbb586dc43f645f502962af372054ce8cc07f Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 12 Jul 2024 11:34:37 -0700 Subject: [PATCH 6/7] chore: add tests for new functionality --- crates/turborepo-lib/src/config.rs | 1 + crates/turborepo-lib/src/turbo_json/mod.rs | 10 +++++ crates/turborepo-repository/src/inference.rs | 40 ++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index ca62e3add0c58..fd5a7df9a13c0 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -778,6 +778,7 @@ mod test { assert!(!defaults.preflight()); assert_eq!(defaults.timeout(), DEFAULT_TIMEOUT); assert_eq!(defaults.spaces_id(), None); + assert!(!defaults.allow_no_package_manager()); } #[test] diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/src/turbo_json/mod.rs index ba085dad5cc5d..c045b8245cff9 100644 --- a/crates/turborepo-lib/src/turbo_json/mod.rs +++ b/crates/turborepo-lib/src/turbo_json/mod.rs @@ -1090,4 +1090,14 @@ mod tests { let actual = serde_json::to_string(&parsed).unwrap(); assert_eq!(actual, expected); } + + #[test_case(r#"{"dangerouslyAllowNoPackageManager":true}"#, Some(true) ; "t")] + #[test_case(r#"{"dangerouslyAllowNoPackageManager":false}"#, Some(false) ; "f")] + #[test_case(r#"{}"#, None ; "missing")] + fn test_allow_no_package_manager_serde(json_str: &str, expected: Option) { + let json = RawTurboJson::parse(json_str, AnchoredSystemPath::new("").unwrap()).unwrap(); + assert_eq!(json.allow_no_package_manager, expected); + let serialized = serde_json::to_string(&json).unwrap(); + assert_eq!(serialized, json_str); + } } diff --git a/crates/turborepo-repository/src/inference.rs b/crates/turborepo-repository/src/inference.rs index 917ef283d6365..cb47fe2ee2e02 100644 --- a/crates/turborepo-repository/src/inference.rs +++ b/crates/turborepo-repository/src/inference.rs @@ -307,4 +307,44 @@ mod test { } } } + + #[test] + fn test_allows_missing_package_manager() { + let (_tmp, tmp_dir) = tmp_dir(); + + let monorepo_root = tmp_dir.join_component("monorepo_root"); + let monorepo_pkg_json = monorepo_root.join_component("package.json"); + let monorepo_contents = "{\"workspaces\": [\"packages/*\"]}"; + monorepo_pkg_json.ensure_dir().unwrap(); + monorepo_pkg_json + .create_with_contents(monorepo_contents) + .unwrap(); + monorepo_root + .join_component("package-lock.json") + .create_with_contents("") + .unwrap(); + + let app_1 = monorepo_root.join_components(&["packages", "app-1"]); + let app_1_pkg_json = app_1.join_component("package.json"); + app_1_pkg_json.ensure_dir().unwrap(); + app_1_pkg_json + .create_with_contents("{\"name\": \"app_1\"}") + .unwrap(); + + let repo_state_from_root = RepoState::infer(&monorepo_root).unwrap(); + let repo_state_from_app = RepoState::infer(&app_1).unwrap(); + + assert_eq!(&repo_state_from_root.root, &monorepo_root); + assert_eq!(&repo_state_from_app.root, &monorepo_root); + assert_eq!(repo_state_from_root.mode, RepoMode::MultiPackage); + assert_eq!(repo_state_from_app.mode, RepoMode::MultiPackage); + assert_eq!( + repo_state_from_root.package_manager.unwrap(), + PackageManager::Npm + ); + assert_eq!( + repo_state_from_app.package_manager.unwrap(), + PackageManager::Npm + ); + } } From 89b4e3ac2354c37b10d4cc23f1209c16aa60b709 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 12 Jul 2024 12:12:28 -0700 Subject: [PATCH 7/7] chore: pr feedback rename config --- crates/turborepo-lib/src/cli/mod.rs | 14 +++++++++----- crates/turborepo-lib/src/commands/mod.rs | 2 +- crates/turborepo-lib/src/config.rs | 6 +++--- crates/turborepo-lib/src/turbo_json/mod.rs | 6 +++--- turborepo-tests/integration/tests/no-args.t | 2 +- turborepo-tests/integration/tests/turbo-help.t | 12 ++++++------ 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 8642d3ad0e358..7f54a52368df1 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -222,7 +222,7 @@ pub struct Args { /// `turbo` will use hints from codebase to guess which package manager /// should be used. #[clap(long, global = true)] - pub dangerously_allow_no_package_manager: bool, + pub dangerously_disable_package_manager_check: bool, #[clap(flatten, next_help_heading = "Run Arguments")] pub run_args: Option, // This should be inside `RunArgs` but clap currently has a bug @@ -2543,12 +2543,16 @@ mod test { assert!( !Args::try_parse_from(["turbo", "build",]) .unwrap() - .dangerously_allow_no_package_manager + .dangerously_disable_package_manager_check ); assert!( - Args::try_parse_from(["turbo", "build", "--dangerously-allow-no-package-manager"]) - .unwrap() - .dangerously_allow_no_package_manager + Args::try_parse_from([ + "turbo", + "build", + "--dangerously-disable-package-manager-check" + ]) + .unwrap() + .dangerously_disable_package_manager_check ); } } diff --git a/crates/turborepo-lib/src/commands/mod.rs b/crates/turborepo-lib/src/commands/mod.rs index a051a58182a0e..57eafed677f0f 100644 --- a/crates/turborepo-lib/src/commands/mod.rs +++ b/crates/turborepo-lib/src/commands/mod.rs @@ -81,7 +81,7 @@ impl CommandBase { })) .with_allow_no_package_manager( self.args - .dangerously_allow_no_package_manager + .dangerously_disable_package_manager_check .then_some(true), ) .build() diff --git a/crates/turborepo-lib/src/config.rs b/crates/turborepo-lib/src/config.rs index fd5a7df9a13c0..242ba830bdec8 100644 --- a/crates/turborepo-lib/src/config.rs +++ b/crates/turborepo-lib/src/config.rs @@ -208,7 +208,7 @@ pub struct ConfigurationOptions { pub(crate) spaces_id: Option, #[serde(rename = "ui")] pub(crate) ui: Option, - #[serde(rename = "dangerouslyAllowNoPackageManager")] + #[serde(rename = "dangerouslyDisablePackageManagerCheck")] pub(crate) allow_no_package_manager: Option, } @@ -347,7 +347,7 @@ fn get_env_var_config( ); turbo_mapping.insert(OsString::from("turbo_ui"), "ui"); turbo_mapping.insert( - OsString::from("turbo_dangerously_allow_no_package_manager"), + OsString::from("turbo_dangerously_disable_package_manager_check"), "allow_no_package_manager", ); turbo_mapping.insert(OsString::from("turbo_preflight"), "preflight"); @@ -803,7 +803,7 @@ mod test { ); env.insert("turbo_ui".into(), "true".into()); env.insert( - "turbo_dangerously_allow_no_package_manager".into(), + "turbo_dangerously_disable_package_manager_check".into(), "true".into(), ); env.insert("turbo_preflight".into(), "true".into()); diff --git a/crates/turborepo-lib/src/turbo_json/mod.rs b/crates/turborepo-lib/src/turbo_json/mod.rs index c045b8245cff9..eb4c483298b3c 100644 --- a/crates/turborepo-lib/src/turbo_json/mod.rs +++ b/crates/turborepo-lib/src/turbo_json/mod.rs @@ -128,7 +128,7 @@ pub struct RawTurboJson { pub ui: Option, #[serde( skip_serializing_if = "Option::is_none", - rename = "dangerouslyAllowNoPackageManager" + rename = "dangerouslyDisablePackageManagerCheck" )] pub allow_no_package_manager: Option, @@ -1091,8 +1091,8 @@ mod tests { assert_eq!(actual, expected); } - #[test_case(r#"{"dangerouslyAllowNoPackageManager":true}"#, Some(true) ; "t")] - #[test_case(r#"{"dangerouslyAllowNoPackageManager":false}"#, Some(false) ; "f")] + #[test_case(r#"{"dangerouslyDisablePackageManagerCheck":true}"#, Some(true) ; "t")] + #[test_case(r#"{"dangerouslyDisablePackageManagerCheck":false}"#, Some(false) ; "f")] #[test_case(r#"{}"#, None ; "missing")] fn test_allow_no_package_manager_serde(json_str: &str, expected: Option) { let json = RawTurboJson::parse(json_str, AnchoredSystemPath::new("").unwrap()).unwrap(); diff --git a/turborepo-tests/integration/tests/no-args.t b/turborepo-tests/integration/tests/no-args.t index 7f46dee3aa459..8c74321153b0c 100644 --- a/turborepo-tests/integration/tests/no-args.t +++ b/turborepo-tests/integration/tests/no-args.t @@ -55,7 +55,7 @@ Make sure exit code is 2 when no args are passed Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help') diff --git a/turborepo-tests/integration/tests/turbo-help.t b/turborepo-tests/integration/tests/turbo-help.t index 9d8fcc03772c9..1ec3f0c34c423 100644 --- a/turborepo-tests/integration/tests/turbo-help.t +++ b/turborepo-tests/integration/tests/turbo-help.t @@ -55,7 +55,7 @@ Test help flag Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help') @@ -188,7 +188,7 @@ Test help flag --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json`. `turbo` will use hints from codebase to guess which package manager should be used. @@ -345,7 +345,7 @@ Test help flag for link command Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help') @@ -391,7 +391,7 @@ Test help flag for unlink command Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help') @@ -439,7 +439,7 @@ Test help flag for login command Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help') @@ -485,7 +485,7 @@ Test help flag for logout command Specify a file to save a pprof trace --verbosity Verbosity level - --dangerously-allow-no-package-manager + --dangerously-disable-package-manager-check Allow for missing `packageManager` in `package.json` -h, --help Print help (see more with '--help')