`npm ls` does not provide the same output after `npm ci` as it does for `npm i` when there are git dependencies

What I Wanted to Do

We want to begin validating that our package-lock.json files are well-formatted by running npm ci during CI/CD and validating that npm ls exits with code 0, indicating that all peer dependencies are met, there aren’t any extraneous dependencies, etc. We expected that if npm ls exited with code 0 after npm i, that npm ls would also exit with code 0 after npm ci.

What Happened Instead

This worked as expected if there were only dependencies from the public npm registry. Once we started running the process described above on packages with dependencies from our GitHub Enterprise instance, we observed that npm ls would exit with code 0 after an npm i, but npm ls would complain about unmet dependencies and exit with a nonzero code after an npm ci. However, the packages still functioned properly…

Reproduction Steps

To reproduce, clone this repository: https://github.com/millerick/example_package_2
Run the following:

npm i
npm ls

Observe the following output from npm ls:

example_package_2@1.0.0 /src/example_package_2
β”œβ”€β”¬ async@2.6.1
β”‚ └── lodash@4.17.11
└─┬ example_package_1@1.5.0 (git+ssh://git@github.com/millerick/example_package_1.git#903df064912d1ecb2d0e557379c0b0ff72509480)
  └─┬ async@2.6.2
    └── lodash@4.17.11 deduped

Run the following:

npm ci
npm ls

Observe the following output from npm ls:

example_package_2@1.0.0 /src/example_package_2
β”œβ”€β”¬ async@2.6.1
β”‚ └── lodash@4.17.11
└─┬ UNMET DEPENDENCY example_package_1@git+ssh://git@github.com/millerick/example_package_1.git#903df064912d1ecb2d0e557379c0b0ff72509480
  └─┬ UNMET DEPENDENCY async@2.6.2
    └── lodash@4.17.11 deduped

npm ERR! missing: example_package_1@git+ssh://git@github.com/millerick/example_package_1.git#v1.5.0, required by example_package_2@1.0.0
npm ERR! missing: async@2.6.2, required by example_package_1@git+ssh://git@github.com/millerick/example_package_1.git#903df064912d1ecb2d0e557379c0b0ff72509480

Note that the output between the two is different, and the latter process exits with a nonzero code. I believe the output of the two should be identical.


I believe the information above is sufficient to reproduce, but let me know if you need more information.

Platform Info

Node 10.15.3
Npm 6.4.1

$ npm --versions
{ npm: '6.4.1',
  ares: '1.15.0',
  cldr: '33.1',
  http_parser: '2.8.0',
  icu: '62.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.34.0',
  node: '10.15.3',
  openssl: '1.1.0j',
  tz: '2018e',
  unicode: '11.0',
  uv: '1.23.2',
  v8: '',
  zlib: '1.2.11' }
$ node -p process.platform

Reproduced following steps with npm 6.4.1 and 6.10.0. (Also on Mac.)

I’ve also reproduced on Node 10.15.3 NPM 6.4.1 on linux Ubuntu 16.04