rules_nodejs icon indicating copy to clipboard operation
rules_nodejs copied to clipboard

npm_install requires external build tools for installing native modules

Open guytt opened this issue 7 years ago • 19 comments

šŸž bug report

Affected Rule

The issue is caused by the rule: npm_install

Is this a regression?

Not that I have noticed.

Description

When I use npm_install on a package.json that includes, in its list of dependencies, a native node module, the run of the rule attempts to use build tools external to bazel (e.g. **make**) and fails when such build tools are not present in the linux environment where bazel is being run.

After installing the required tools (i.e. running apt-get install build-essential), running the rule succeeds. This violates bazel's proclaimed hermeticity to some extent.

šŸ”¬ Minimal Reproduction

Partial content of WORKSPACE file:

load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "npm_install")

node_repositories(
    package_json = ["//:package.json"],
    node_version = "10.13.0",
)

npm_install(
    name = "node_modules",
    package_json = "//:package.json",
)

Content of pacakge.json:

{
  "name": "mymodule",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "native-module": "^0.11.3"
  }
}

šŸ”„ Exception or Error


gyp ERR! build error
gyp ERR! stack Error: not found: make
gyp ERR! stack     at getNotFoundError (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:13:12)
gyp ERR! stack     at F (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:68:19)
gyp ERR! stack     at E (/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:80:29)
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/which/which.js:89:16
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/isexe/index.js:42:5
gyp ERR! stack     at /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/isexe/mode.js:8:5
gyp ERR! stack     at FSReqWrap.oncomplete (fs.js:154:21)
gyp ERR! System Linux 4.9.125-linuxkit
gyp ERR! command "/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/bin/node" "/bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/nodejs/bin/nodejs/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /bazel-smb-share/outputs/9f616bba2eedecf392b1070e3c256f4e/external/cloud-host-worker-deps/node_modules/native-module
gyp ERR! node -v v10.13.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm WARN @wix/[email protected] requires a peer of newrelic@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @wix/[email protected] No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/bazel/.npm/_logs/2019-01-18T19_55_56_115Z-debug.log

šŸŒ Your Environment

Operating System:

  
4.9.125-linuxkit
  

Output of bazel version:

  
Build label: 0.20.0
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Fri Nov 30 14:39:01 2018 (1543588741)
Build timestamp: 1543588741
Build timestamp as int: 1543588741
  

Rules version (SHA):

  
0.16.4 (d6fcfaf1380e81ace932b534c4ea99166008f0b6)
  

Encountered as part of using Bazel at Wix.com @ittaiz

guytt avatar Jan 18 '19 20:01 guytt

Do you hit this issue by running npm outside of Bazel? I suppose no?

I understand that this violates the hermeticity but it might be a reasonable compromise so that we do not couple rules_nodejs with the external tooling involved in building native node modules.

cc @alexeagle @gregmagolan

mgechev avatar Jan 18 '19 21:01 mgechev

What do you suggest? That we have every developer install make and various other tools needed (we stumbled on to two more IIRC)? I’m not asking sarcastically (though am a bit worried).

Have you encountered this in the past? What did you do? I’d be surprised if @alexeagle never faced this dilemma On Fri, 18 Jan 2019 at 23:42 Minko Gechev [email protected] wrote:

Do you hit this issue by running npm outside of Bazel? I suppose no?

I understand that this violates the hermeticity but it might be a reasonable compromise so that we do not couple rules_nodejs with the external tooling involved in building native node modules.

cc @alexeagle https://github.com/alexeagle @gregmagolan https://github.com/gregmagolan

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bazelbuild/rules_nodejs/issues/506#issuecomment-455696929, or mute the thread https://github.com/notifications/unsubscribe-auth/ABUIF3b45WEA-dundMFR1tY4DQNIbNmNks5vEj-7gaJpZM4aIk_c .

ittaiz avatar Jan 19 '19 05:01 ittaiz

@mgechev I hit this issue whenever running npm install in an environment where this external tooling is not installed. As most installations of node/npm install this additional tooling, I don't hit the issue.

guytt avatar Jan 20 '19 09:01 guytt

@gregmagolan can you update about the toolchain approach we discussed? Thanks!

ittaiz avatar Jan 27 '19 18:01 ittaiz

Yes. @ittaiz @alexeagle and I discussed this at the bazel rules summit last week. The thinking is that we should be able to resolve this with bazel toolchains. We're planning to migrate nodejs to bazel toolchains in the next month so we'll look at this at that point.

gregmagolan avatar Jan 28 '19 17:01 gregmagolan

Doesn't this break determinism as well? The npm process for building native modules seems to break caching for me.

rohansingh avatar Mar 03 '19 03:03 rohansingh

Greg, Any chance you have an update? On Sun, 3 Mar 2019 at 5:57 Rohan Singh [email protected] wrote:

Doesn't this break determinism as well? The npm process for building native modules isn't deterministic or hermetic, and breaks caching.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bazelbuild/rules_nodejs/issues/506#issuecomment-468985618, or mute the thread https://github.com/notifications/unsubscribe-auth/ABUIFyQj9zcaSOSASoUQG8iYYQGr3vRkks5vS0gNgaJpZM4aIk_c .

ittaiz avatar Mar 03 '19 04:03 ittaiz

Flyby comment: I think the long term solution for this one is getting projects that publish native code to instead publish WASM

Toxicable avatar Sep 08 '20 20:09 Toxicable

Is there any planned next-steps on this? Or is it just a big question-mark still?

We have similar issues where we can't use npm_install due to failures with modules installing themselves via node-gyp. We live in a weird mixed world at the moment (we have hacked around to get the BUILD file generation but leave module installation outside of bazel), but we'd much prefer to get to the standard patterns expected by the library.

vpanta avatar May 04 '21 18:05 vpanta

*clarification, our issue with node modules and node-gyp is explicitly when executing in our Linux docker container on CI, however it works fine on our local MacOS machines.

vpanta avatar May 04 '21 23:05 vpanta

@vpanta did you manage to find a solution?

xvzf avatar May 03 '22 14:05 xvzf

@xvzf No, although we're diving back into looking more at it now.

vpanta avatar May 10 '22 18:05 vpanta

for now, I think we've found a workaround with using npm_command = "install", as it's only when bazel runs npm ci in these environments that it seems to fail to install node-gyp-build appropriately (?)

*edit: that only worked due to symlink_node_modules being set to True, however we'll probably want to use the default once we can update rules_nodejs (now False). That sets us back to the same issue as before :/

vpanta avatar May 10 '22 21:05 vpanta

Ok, so our issue isn't purely with node-gyp-build but rather that, when it executes, it can't find node-gyp. Which shouldn't be a thing seeing that node-gyp is a pack-in with npm itself.

So, if I get onto the machine and use npm outside of bazel to globally install node-gyp (shouldn't be needed, as node-gyp is a pack-in with node), then we get past this as bazel is finding that secondary installed node-gyp.

Poking deeper, I patched our version of the _npm.sh generated here to include a call npm ls -g node-gyp immediately before the call to npm ci. It returned:

`-- [email protected]
  +-- @npmcli/[email protected]
  | `-- [email protected] deduped
  `-- [email protected]

yet still failed on the very next line with:

npm ERR! command failed
npm ERR! command sh -c node-gyp-build
npm ERR! node:events:368
npm ERR!       throw er; // Unhandled 'error' event
npm ERR!       ^
npm ERR! 
npm ERR! Error: spawn node-gyp ENOENT
npm ERR!     at Process.ChildProcess._handle.onexit (node:internal/child_process:282:19)

which has me extra flummoxed...

vpanta avatar May 12 '22 20:05 vpanta

I was hoping this was maybe due to something with symlinked paths, assuming it was executing the node-gyp from within utf-8-validate's build (that's who's using node-gyp-build), and during that install the cwd is a different place, but various attempts to get --preserve-symlinks for node and/or --scripts-prepend-node-path=true for npm into the command line have also failed to produce any results.

At the moment, we're solving this with a forced global install of node-gyp (i.e. npm i -g node-gyp), so that when the other modules get installed it can find node-gyp without issue. This isn't great though.

vpanta avatar May 13 '22 18:05 vpanta

Ok, one last update: this isn't Linux specific. We're seeing the same issue on our MacOS containers as well.

vpanta avatar May 13 '22 18:05 vpanta

phooey, the "globally install" trick isn't working on our MacOS containers :/

vpanta avatar May 13 '22 19:05 vpanta

@vpanta what was the solution?

Shusanta avatar Mar 04 '24 01:03 Shusanta

We never found a solution under the old versions of rules_nodejs. We now use the latest version of rules_nodejs along with aspect-build/rules_js and don't have this specific issue.

We did however recently run into an issue with node-gyp-build, which was solved by apnpm.packageExtensions block in our package.json (forcing node-gyp as a dependency of packages which depended on node-gyp-build).

vpanta avatar Mar 04 '24 13:03 vpanta