Skip to content

Commit

Permalink
fix: honour handleTransparentWorkspaces setting in Yarn/Berry
Browse files Browse the repository at this point in the history
  • Loading branch information
romanofski committed Dec 17, 2024
1 parent ffe5be9 commit 7cb26de
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 5 deletions.
27 changes: 23 additions & 4 deletions crates/turborepo-repository/src/package_graph/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use turborepo_graph_utils as graph;
use turborepo_lockfiles::Lockfile;

use super::{
dep_splitter::DependencySplitter, npmrc::NpmRc, PackageGraph, PackageInfo, PackageName,
PackageNode,
dep_splitter::DependencySplitter, npmrc::NpmRc, yarnrc::YarnRc, PackageGraph, PackageInfo,
PackageName, PackageNode,
};
use crate::{
discovery::{
Expand Down Expand Up @@ -362,6 +362,17 @@ impl<'a, T: PackageDiscovery> BuildState<'a, ResolvedWorkspaces, T> {
}
_ => None,
};
let yarnrc_path = self.repo_root.join_component(".yarnrc.yml");
let yarnrc = match package_manager {
PackageManager::Berry => {
// HOME?
match yarnrc_path.read_existing_to_string().ok().flatten() {
Some(contents) => YarnRc::from_reader(contents.as_bytes()).ok(),
None => None,
}
}
_ => None,
};
let split_deps = self
.workspaces
.iter()
Expand All @@ -375,6 +386,7 @@ impl<'a, T: PackageDiscovery> BuildState<'a, ResolvedWorkspaces, T> {
&self.workspaces,
package_manager,
npmrc.as_ref(),
yarnrc.as_ref(),
entry.package_json.all_dependencies(),
),
)
Expand Down Expand Up @@ -567,6 +579,7 @@ impl Dependencies {
workspaces: &HashMap<PackageName, PackageInfo>,
package_manager: &PackageManager,
npmrc: Option<&NpmRc>,
yarnrc: Option<&YarnRc>,
dependencies: I,
) -> Self {
let resolved_workspace_json_path = repo_root.resolve(workspace_json_path);
Expand All @@ -575,8 +588,14 @@ impl Dependencies {
.expect("package.json path should have parent");
let mut internal = HashSet::new();
let mut external = BTreeMap::new();
let splitter =
DependencySplitter::new(repo_root, workspace_dir, workspaces, package_manager, npmrc);
let splitter = DependencySplitter::new(
repo_root,
workspace_dir,
workspaces,
package_manager,
npmrc,
yarnrc,
);
for (name, version) in dependencies.into_iter() {
if let Some(workspace) = splitter.is_internal(name, version) {
internal.insert(workspace);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use turbopath::{
RelativeUnixPathBuf,
};

use super::{npmrc::NpmRc, PackageInfo, PackageName};
use super::{npmrc::NpmRc, yarnrc::YarnRc, PackageInfo, PackageName};
use crate::package_manager::PackageManager;

pub struct DependencySplitter<'a> {
Expand All @@ -22,13 +22,15 @@ impl<'a> DependencySplitter<'a> {
workspaces: &'a HashMap<PackageName, PackageInfo>,
package_manager: &PackageManager,
npmrc: Option<&'a NpmRc>,
yarnrc: Option<&'a YarnRc>,
) -> Self {
Self {
repo_root,
workspace_dir,
workspaces,
link_workspace_packages: npmrc
.and_then(|npmrc| npmrc.link_workspace_packages)
.or_else(|| yarnrc.map(|yarnrc| yarnrc.enableTransparentWorkspaces))
.unwrap_or(!matches!(package_manager, PackageManager::Pnpm9)),
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/turborepo-repository/src/package_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{
pub mod builder;
mod dep_splitter;
mod npmrc;
mod yarnrc;

pub use builder::{Error, PackageGraphBuilder};

Expand Down
63 changes: 63 additions & 0 deletions crates/turborepo-repository/src/package_graph/yarnrc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::io;

use serde::Deserialize;
use serde_yaml;

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("encountered error parsing yarnrc.yml: {0}")]
SerdeYaml(#[from] serde_yaml::Error),
}

/// A yarnrc.yaml file representing settings affecting the package graph.
#[allow(non_snake_case)]
#[derive(Debug, PartialEq, Eq, Clone, Deserialize)]
pub struct YarnRc {
/// Used by Yarn(Berry) as `enableTransparentWorkspaces`.
/// When true, treats local workspaces that match a package name
/// and semver range as correct match resulting in turbo including
/// the package in the dependency graph
pub enableTransparentWorkspaces: bool,
}

impl Default for YarnRc {
fn default() -> YarnRc {
YarnRc {
enableTransparentWorkspaces: true,
}
}
}

impl YarnRc {
pub fn from_reader(mut reader: impl io::Read) -> Result<Self, Error> {
let config: YarnRc = serde_yaml::from_reader(&mut reader)?;
Ok(config)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_parse_empty_yarnrc() {
let empty = YarnRc::from_reader(b"".as_slice()).unwrap();
assert_eq!(
empty,
YarnRc {
enableTransparentWorkspaces: true
}
);
}

#[test]
fn test_parses_transparent_workspaces() {
let empty = YarnRc::from_reader(b"enableTransparentWorkspaces: false".as_slice()).unwrap();
assert_eq!(
empty,
YarnRc {
enableTransparentWorkspaces: false
}
);
}
}

0 comments on commit 7cb26de

Please sign in to comment.