Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Large] Add support for inheriting platforms (monorepos) #755

Merged
merged 13 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/volta-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ dunce = "1.0.0"
ci_info = "0.10.0"
hyperx = "1.0.0"
attohttpc = { version = "0.13.0", features = ["json"] }
chain-map = "0.1.0"
indexmap = "1.3.2"

[target.'cfg(windows)'.dependencies]
winreg = "0.6.0"
9 changes: 9 additions & 0 deletions crates/volta-core/fixtures/cycle-1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "cycle-1-project",
"version": "0.0.1",
"description": "Testing that project correctly detects a cycle between this and volta.json",
"license": "To Kill",
"volta": {
"extends": "./volta.json"
}
}
5 changes: 5 additions & 0 deletions crates/volta-core/fixtures/cycle-1/volta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"volta": {
"extends": "./package.json"
}
}
9 changes: 9 additions & 0 deletions crates/volta-core/fixtures/cycle-2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "cycle-2-project",
"version": "0.0.1",
"description": "Testing that project correctly detects a cycle between workspace-1.json and workspace-2.json",
"license": "To Kill",
"volta": {
"extends": "./workspace-1.json"
}
}
5 changes: 5 additions & 0 deletions crates/volta-core/fixtures/cycle-2/workspace-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"volta": {
"extends": "./workspace-2.json"
}
}
5 changes: 5 additions & 0 deletions crates/volta-core/fixtures/cycle-2/workspace-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"volta": {
"extends": "./workspace-1.json"
}
}
3 changes: 3 additions & 0 deletions crates/volta-core/fixtures/nested/node_modules/.bin/eslint

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions crates/volta-core/fixtures/nested/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "nested-project",
"version": "0.0.1",
"description": "Testing that project correctly detects a nested workspace",
"license": "To Kill",
"dependencies": {
"lodash": "*"
},
"devDependencies": {
"eslint": "*"
},
"volta": {
"yarn": "1.11.0",
"npm": "6.12.1",
"node": "12.14.0"
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "inner-project",
"version": "0.0.1",
"description": "Testing that project correctly detects a nested workspace",
"license": "To Kill",
"dependencies": {
"express": "*"
},
"devDependencies": {
"typescript": "*"
},
"volta": {
"yarn": "1.22.4",
"extends": "../package.json"
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions crates/volta-core/fixtures/nested/subproject/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "subproject",
"version": "0.0.1",
"description": "Testing that project correctly detects a nested workspace",
"license": "To Kill",
"dependencies": {
"rsvp": "*"
},
"devDependencies": {
"glob": "*"
},
"volta": {
"yarn": "1.17.0",
"npm": "6.9.0",
"extends": "../package.json"
}
}
57 changes: 56 additions & 1 deletion crates/volta-core/src/error/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ pub enum ErrorKind {
command: String,
},

/// Thrown when `volta.extends` keys result in an infinite cycle
ExtensionCycleError {
paths: Vec<PathBuf>,
duplicate: PathBuf,
},
Comment on lines +125 to +128
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍


/// Thrown when determining the path to an extension manifest fails
ExtensionPathError {
path: PathBuf,
},

/// Thrown when a hook command returns a non-zero exit code
HookCommandFailed {
command: String,
Expand Down Expand Up @@ -200,6 +211,9 @@ pub enum ErrorKind {
/// Thrown when the platform (Node version) could not be determined
NoPlatform,

/// Thrown when parsing the project manifest and there is a `"volta"` key without Node
NoProjectNodeInManifest,

/// Thrown when Yarn is not set in a project
NoProjectYarn,

Expand Down Expand Up @@ -685,6 +699,38 @@ Please verify your internet connection and ensure the correct version is specifi
Please ensure that the correct command is specified.",
command
),
ErrorKind::ExtensionCycleError { paths, duplicate } => {
// Detected infinite loop in project workspace:
//
// --> /home/user/workspace/project/package.json
// /home/user/workspace/package.json
// --> /home/user/workspace/project/package.json
//
// Please ensure that project workspaces do not depend on each other.
Comment on lines +703 to +709
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More 😍!

f.write_str("Detected infinite loop in project workspace:\n\n")?;

for path in paths {
if path == duplicate {
f.write_str("--> ")?;
} else {
f.write_str(" ")?;
}

writeln!(f, "{}", path.display())?;
}

writeln!(f, "--> {}", duplicate.display())?;
writeln!(f)?;

f.write_str("Please ensure that project workspaces do not depend on each other.")
}
ErrorKind::ExtensionPathError { path } => write!(
f,
"Could not determine path to project workspace: '{}'

Please ensure that the file exists and is accessible.",
path.display(),
),
ErrorKind::HookCommandFailed { command } => write!(
f,
"Hook command '{}' indicated a failure.
Expand Down Expand Up @@ -849,6 +895,12 @@ Use `volta pin node` to pin Node first, then pin a {0} version.",
"Node is not available.

To run any Node command, first set a default version using `volta install node`"
),
ErrorKind::NoProjectNodeInManifest => write!(
f,
"No Node version found in this project.

Use `volta pin node` to select a version (see `volta help pin` for more info)."
),
ErrorKind::NoProjectYarn => write!(
f,
Expand Down Expand Up @@ -1068,7 +1120,7 @@ Please ensure you have correct permissions to access the file.",
),
ErrorKind::ProjectLocalBinaryNotFound { command } => write!(
f,
"Could not execute `{}`, the file does not exist.
"Could not locate executable `{}` in your project.

Please ensure that all project dependencies are installed with `npm install` or `yarn install`",
command
Expand Down Expand Up @@ -1403,6 +1455,8 @@ impl ErrorKind {
ErrorKind::ExecutablePathError { .. } => ExitCode::UnknownError,
ErrorKind::ExecutablePermissionsError { .. } => ExitCode::FileSystemError,
ErrorKind::ExecuteHookError { .. } => ExitCode::ExecutionFailure,
ErrorKind::ExtensionCycleError { .. } => ExitCode::ConfigurationError,
ErrorKind::ExtensionPathError { .. } => ExitCode::FileSystemError,
ErrorKind::HookCommandFailed { .. } => ExitCode::ConfigurationError,
ErrorKind::HookMultipleFieldsSpecified => ExitCode::ConfigurationError,
ErrorKind::HookNoFieldsSpecified => ExitCode::ConfigurationError,
Expand All @@ -1422,6 +1476,7 @@ impl ErrorKind {
ErrorKind::NoPackageExecutables { .. } => ExitCode::InvalidArguments,
ErrorKind::NoPinnedNodeVersion { .. } => ExitCode::ConfigurationError,
ErrorKind::NoPlatform => ExitCode::ConfigurationError,
ErrorKind::NoProjectNodeInManifest => ExitCode::ConfigurationError,
ErrorKind::NoProjectYarn => ExitCode::ConfigurationError,
ErrorKind::NoShellProfile { .. } => ExitCode::EnvironmentError,
ErrorKind::NotInPackage => ExitCode::ConfigurationError,
Expand Down
11 changes: 7 additions & 4 deletions crates/volta-core/src/hook/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,19 @@ impl HookConfig {
fn current(project: Option<&Project>) -> Fallible<Self> {
let default_hooks_file = volta_home()?.default_hooks_file();

// Since `from_paths` expects the paths to be sorted in descending precedence order, we include project hooks first
// Since `from_paths` expects the paths to be sorted in descending precedence order, we
// include all project hooks first (workspace_roots is already sorted in descending
// precedence order)
// See the per-project configuration RFC for more details on the configuration precedence:
// https://github.com/volta-cli/rfcs/blob/master/text/0033-per-project-config.md#configuration-precedence
let paths = project
.map(|p| {
let mut path = p.project_root().join(".volta");
.into_iter()
.flat_map(Project::workspace_roots)
.map(|root| {
let mut path = root.join(".volta");
path.push("hooks.json");
Cow::Owned(path)
})
.into_iter()
.chain(once(Cow::Borrowed(default_hooks_file)));

Self::from_paths(paths)
Expand Down
Loading