6/2/2017 - 3:06 PM

3 undocumented breaking changes we encountered while upgarding npm to v5.0.1 in homebrew

3 undocumented breaking changes we encountered while upgarding npm to v5.0.1 in homebrew

I'm opening this issue because:

  • npm is crashing.
  • npm is producing an incorrect install.
  • npm is doing something I don't understand.
  • Other (see below for feature requests):

supporting information:

  • npm -v prints: 5.0.1
  • node -v prints: v8.0.0
  • npm config get registry prints: https://registry.npmjs.org/
  • Windows, OS X/macOS, or Linux?: macOS
  • Network issues: no

While upgrading npm from npm@4 to npm@5 in the node Homebrew formula over at https://github.com/Homebrew/homebrew-core/pull/14085 we encountered 3 undocumented breaking changes in npm@5 of which the last 2 are more or less in a grey area. I decided to report them here anyway, so that you could make your own assessment if they are considered to be real bugs or just an unsupported usage of npm. I would completely understand if you label them as a wontfix.

1. installing a package with broken file system permission fails.

This issue was already reported in https://github.com/npm/npm/issues/16896 and I joined the discussion over there with more details.

(npm install easy-table@0.0.1 will fail with EACCES becasue npm@5 doesn't normalize permissions anymore and the 0.0.1 tarball is lacking +x on its lib folder)

2. make install can't be used to install npm to a prefix anymore

Refs: https://github.com/Homebrew/homebrew-core/pull/14085#discussion_r119396602

Until now (for npm <=4) we installed npm by the the hacky way of doing a configure --prefix=libexec/npm followed by a make install. Because make install is only an alias for node bin/npm-cli.js install -g -f ${NPMOPTS} and the breaking npm install <folder> change in npm@5, make install would now only create a symlink to our temporary build path (which gets removed by brew automatically after installation) instead of copying npm over to the specified prefix as npm@4 used to do. This has broken the way we had installed npm until now, and yes we know what we did was never a recommended way of installing npm. Nonetheless, the npm@5 make install behaviour doesn't match what you would expect from a typical make install call in the unix world anymore (which could be problematic, because the make targets aren't documented and this could confuse someone trying to package npm). It would be nice to have the original make install behavior available in some form (as a different make target?). For now we have worked around this by using a temporary version of npm extracted from the npm registry tarball to install said registry tarball to our prefix in libexec.

3. npm@5 destroys node_modules folder installed by yarn

Refs: https://github.com/Homebrew/homebrew-core/pull/14125

By mistake, the grafana formula previously executed npm install grunt-cli after a complete installation of all its dependencies with yarn install (grunt-cli was already installed by yarn, but the issue also reproduces if you install something new using npm). While using npm@4 the redundant npm install grunt-cli command just did nothing as expected, but when run with npm@5, npm@5 removes all other dependencies from node_modules except grunt-cli and its dependencies breaking the previously (with yarn) installed modules completely.

How to reproduce:

  1. Install yarn: npm install -g yarn
  2. Download and extract grafana from https://github.com/grafana/grafana/archive/v4.3.0.tar.gz somewhere
  3. Install all dependencies with yarn install
  4. Install grunt-cli using npm@5: npm install grunt-cli -ddd

Output of 4.: https://gist.github.com/chrmoritz/650993b1756c0ecbce76422809c5787f

Expected result: all dependencies installed with yarn are still there inside node_modules

Actual result: all dependencies installed with yarn were removed and replaced by the grunt-cli only installation

This was fixed in https://github.com/Homebrew/homebrew-core/pull/14125 by dropping the redundant npm install grunt-cli call.

See also the following brew logs containing the full verbose npm log: