Skip to content

Commit

Permalink
fix: Fix node global not being available during dependency installs. (
Browse files Browse the repository at this point in the history
#1089)

* Add tests.

* Add more tests.

* Polish.
  • Loading branch information
milesj authored Oct 1, 2023
1 parent b09a9d1 commit c318505
Show file tree
Hide file tree
Showing 15 changed files with 108 additions and 14 deletions.
9 changes: 9 additions & 0 deletions .yarn/versions/fdfb2523.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
releases:
"@moonrepo/cli": patch
"@moonrepo/core-linux-arm64-gnu": patch
"@moonrepo/core-linux-arm64-musl": patch
"@moonrepo/core-linux-x64-gnu": patch
"@moonrepo/core-linux-x64-musl": patch
"@moonrepo/core-macos-arm64": patch
"@moonrepo/core-macos-x64": patch
"@moonrepo/core-windows-x64-msvc": patch
24 changes: 24 additions & 0 deletions crates/cli/tests/run_node_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,30 @@ fn avoids_postinstall_recursion() {
assert.success();
}

#[test]
fn can_exec_global_bin_as_child_process() {
let sandbox = node_sandbox();

let assert = sandbox.run_moon(|cmd| {
cmd.arg("run").arg("node:execBinSelf");
});

let output = assert.output();

assert!(predicate::str::contains("v18.0.0").eval(&output));
}

#[test]
fn can_exec_global_bin_as_child_process_from_postinstall() {
let sandbox = node_sandbox();

let assert = sandbox.run_moon(|cmd| {
cmd.arg("run").arg("postinstall:noop");
});

assert.success();
}

mod install_deps {
use super::*;

Expand Down
1 change: 1 addition & 0 deletions crates/core/test-utils/src/configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ pub fn get_node_fixture_configs() -> (
projects: Some(PartialWorkspaceProjects::Sources(FxHashMap::from_iter([
("node".into(), "base".to_owned()),
("lifecycles".into(), "lifecycles".to_owned()),
("postinstall".into(), "postinstall".to_owned()),
(
"postinstallRecursion".into(),
"postinstall-recursion".to_owned(),
Expand Down
12 changes: 10 additions & 2 deletions crates/core/tool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ use std::path::Path;
/// other binaries of the same name. Otherwise, tooling like nvm will
/// intercept execution and break our processes. We can work around this
/// by prepending the `PATH` environment variable.
pub fn get_path_env_var(bin_dir: &Path) -> std::ffi::OsString {
pub fn prepend_path_env_var<I, V>(paths: I) -> std::ffi::OsString
where
I: IntoIterator<Item = V>,
V: AsRef<Path>,
{
let path = env::var("PATH").unwrap_or_default();
let mut paths = vec![bin_dir.to_path_buf()];

let mut paths = paths
.into_iter()
.map(|p| p.as_ref().to_path_buf())
.collect::<Vec<_>>();

paths.extend(env::split_paths(&path).collect::<Vec<_>>());

Expand Down
13 changes: 11 additions & 2 deletions crates/node/platform/src/actions/run_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use moon_node_tool::NodeTool;
use moon_process::Command;
use moon_project::Project;
use moon_task::Task;
use moon_tool::{get_path_env_var, DependencyManager, Tool, ToolError};
use moon_tool::{prepend_path_env_var, DependencyManager, Tool, ToolError};
use moon_utils::{get_cache_dir, path, string_vec};
use rustc_hash::FxHashMap;
use starbase_styles::color;
Expand Down Expand Up @@ -163,6 +163,7 @@ pub fn create_target_command(
let node_bin = node.get_bin_path()?;
let node_options = create_node_options(&node.config, context, task)?;
let mut command = Command::new(node.get_shim_path().unwrap_or(node_bin));
let mut is_package_manager = false;

match task.command.as_str() {
"node" | "nodejs" => {
Expand All @@ -172,12 +173,15 @@ pub fn create_target_command(
command = Command::new(node.get_npx_path()?);
}
"npm" => {
is_package_manager = true;
command = node.get_npm()?.create_command(node)?;
}
"pnpm" => {
is_package_manager = true;
command = node.get_pnpm()?.create_command(node)?;
}
"yarn" | "yarnpkg" => {
is_package_manager = true;
command = node.get_yarn()?.create_command(node)?;
}
bin => {
Expand All @@ -189,7 +193,12 @@ pub fn create_target_command(
}
};

command.env("PATH", get_path_env_var(&node.tool.get_tool_dir()));
if !is_package_manager {
command.env(
"PATH",
prepend_path_env_var([node.tool.get_bin_path()?.parent().unwrap()]),
);
}

prepare_target_command(&mut command, context, task, &node.config)?;

Expand Down
7 changes: 5 additions & 2 deletions crates/node/tool/src/node_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use moon_platform_runtime::RuntimeReq;
use moon_process::Command;
use moon_terminal::{print_checkpoint, Checkpoint};
use moon_tool::{
async_trait, get_path_env_var, load_tool_plugin, DependencyManager, Tool, ToolError,
async_trait, load_tool_plugin, prepend_path_env_var, DependencyManager, Tool, ToolError,
};
use proto_core::{Id, ProtoEnvironment, Tool as ProtoTool};
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -78,7 +78,10 @@ impl NodeTool {
let mut cmd = Command::new(self.get_npx_path()?);

if !self.global {
cmd.env("PATH", get_path_env_var(&self.tool.get_tool_dir()));
cmd.env(
"PATH",
prepend_path_env_var([self.tool.get_bin_path()?.parent().unwrap()]),
);
}

cmd.args(exec_args)
Expand Down
10 changes: 8 additions & 2 deletions crates/node/tool/src/npm_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use moon_logger::debug;
use moon_node_lang::{npm, LockfileDependencyVersions, NPM};
use moon_process::Command;
use moon_terminal::{print_checkpoint, Checkpoint};
use moon_tool::{async_trait, get_path_env_var, load_tool_plugin, DependencyManager, Tool};
use moon_tool::{async_trait, load_tool_plugin, prepend_path_env_var, DependencyManager, Tool};
use moon_utils::is_ci;
use proto_core::{Id, ProtoEnvironment, Tool as ProtoTool, UnresolvedVersionSpec};
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -117,7 +117,13 @@ impl DependencyManager<NodeTool> for NpmTool {
};

if !self.global {
cmd.env("PATH", get_path_env_var(&self.tool.get_tool_dir()));
cmd.env(
"PATH",
prepend_path_env_var([
node.get_bin_path()?.parent().unwrap(),
self.tool.get_bin_path()?.parent().unwrap(),
]),
);
}

cmd.env("PROTO_NODE_BIN", node.get_bin_path()?);
Expand Down
10 changes: 8 additions & 2 deletions crates/node/tool/src/pnpm_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use moon_logger::debug;
use moon_node_lang::{pnpm, LockfileDependencyVersions, PNPM};
use moon_process::Command;
use moon_terminal::{print_checkpoint, Checkpoint};
use moon_tool::{async_trait, get_path_env_var, load_tool_plugin, DependencyManager, Tool};
use moon_tool::{async_trait, load_tool_plugin, prepend_path_env_var, DependencyManager, Tool};
use moon_utils::is_ci;
use proto_core::{Id, ProtoEnvironment, Tool as ProtoTool, UnresolvedVersionSpec, VersionReq};
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -123,7 +123,13 @@ impl DependencyManager<NodeTool> for PnpmTool {
};

if !self.global {
cmd.env("PATH", get_path_env_var(&self.tool.get_tool_dir()));
cmd.env(
"PATH",
prepend_path_env_var([
node.get_bin_path()?.parent().unwrap(),
self.tool.get_bin_path()?.parent().unwrap(),
]),
);
}

cmd.env("PROTO_NODE_BIN", node.get_bin_path()?);
Expand Down
10 changes: 8 additions & 2 deletions crates/node/tool/src/yarn_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use moon_node_lang::{yarn, LockfileDependencyVersions, YARN};
use moon_process::Command;
use moon_terminal::{print_checkpoint, Checkpoint};
use moon_tool::{
async_trait, get_path_env_var, load_tool_plugin, DependencyManager, Tool, ToolError,
async_trait, load_tool_plugin, prepend_path_env_var, DependencyManager, Tool, ToolError,
};
use moon_utils::{get_workspace_root, is_ci};
use proto_core::{Id, ProtoEnvironment, Tool as ProtoTool, UnresolvedVersionSpec};
Expand Down Expand Up @@ -179,7 +179,13 @@ impl DependencyManager<NodeTool> for YarnTool {
};

if !self.global {
cmd.env("PATH", get_path_env_var(&self.tool.get_tool_dir()));
cmd.env(
"PATH",
prepend_path_env_var([
node.get_bin_path()?.parent().unwrap(),
self.tool.get_bin_path()?.parent().unwrap(),
]),
);
}

cmd.env("PROTO_NODE_BIN", node.get_bin_path()?);
Expand Down
4 changes: 2 additions & 2 deletions crates/rust/tool/src/rust_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ impl Tool for RustTool {
// When offline and the tool doesn't exist, fallback to the global binary
} else if proto_core::is_offline() {
debug!(
"No internet connection and Rust has not been setup, falling back to global binary in PATH"
);
"No internet connection and Rust has not been setup, falling back to global binary in PATH"
);

self.global = true;

Expand Down
6 changes: 6 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
- More accurately monitors signals (ctrl+c) and shutdowns.
- Tasks can now be configured with a timeout.

## Unreleased

#### 🐞 Fixes

- Fixed some `PATH` inconsistencies when executing npm/pnpm/yarn binaries.

## 1.14.3

#### 🚀 Updates
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/node/base/execBin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { spawnSync } = require('child_process');

spawnSync('node', ['--version'], { stdio: 'inherit' });
3 changes: 3 additions & 0 deletions tests/fixtures/node/base/moon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ tasks:
mjs:
command: node
args: ./mjsFile.mjs
execBinSelf:
command: node
args: ./execBin.js

# Runner cases
exitCodeNonZero:
Expand Down
7 changes: 7 additions & 0 deletions tests/fixtures/node/postinstall/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "test-node-postinstall",
"version": "1.0.0",
"scripts": {
"postinstall": "node ./postinstall.js"
}
}
3 changes: 3 additions & 0 deletions tests/fixtures/node/postinstall/postinstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { spawnSync } = require('child_process');

spawnSync('node', ['--version'], { stdio: 'inherit' });

0 comments on commit c318505

Please sign in to comment.