Skip to content

Commit

Permalink
fix: gracefully handle error during npm install
Browse files Browse the repository at this point in the history
PR-URL: #1009
Credit: @danielleadams
Close: #1009
Reviewed-by: @claudiahdz
  • Loading branch information
Danielle Adams authored and claudiahdz committed Jul 20, 2020
1 parent 1961c93 commit 8788889
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 3 deletions.
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ We often want to know if the bug we've fixed for the feature we've added has any
1. Make a pull-request against this repository
2. Add the following comment to the pull-request: "`test this please ✅`"

This will trigger the [benmark suite](https://github.com/npm/benchmarks) to run against your pull-request, and when it's finished running it will post a comment on your pull-request just like bellow. You'll be able to see the results from the suite inline in your pull-request.
This will trigger the [benchmark suite](https://github.com/npm/benchmarks) to run against your pull-request, and when it's finished running it will post a comment on your pull-request just like below. You'll be able to see the results from the suite inline in your pull-request.

> You'll notice that the bot-user will also add a 🚀 reaction to your comment to
let you know that it's sent the request to start the benchmark suite.
Expand Down Expand Up @@ -186,7 +186,6 @@ You'll need a few things installed in order to update and test the CLI project d

> Package vendoring is commonly referred to as the case where dependent packages are stored in the same place as your project. That usually means you dependencies are checked into your source management system, such as Git.
The CLI project vendors it's dependencies in the `node_modules/` folder. Meaning all the dependencies that the CLI project uses are contained withing the project itself. This is represented by the `bundledDependencies` section in the root level `package.json` file. The main reason for this is because the `npm` CLI project is distributed with the NodeJS runtime and needs to work out of the box, which means all dependencies need to be available after the runtime is installed.
The CLI project vendors its dependencies in the `node_modules/` folder. Meaning all the dependencies that the CLI project uses are contained within the project itself. This is represented by the `bundledDependencies` section in the root level `package.json` file. The main reason for this is because the `npm` CLI project is distributed with the NodeJS runtime and needs to work out of the box, which means all dependencies need to be available after the runtime is installed.

There are a couple scripts created to help manage this process in the `scripts/` folder.

8 changes: 8 additions & 0 deletions lib/install/inflate-shrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ function inflateShrinkwrap (topPath, tree, swdeps, opts) {
const sw = swdeps[name]
const dependencies = sw.dependencies || {}
const requested = realizeShrinkwrapSpecifier(name, sw, topPath)

if (Object.keys(sw).length === 0) {
let message = `Object for dependency "${name}" is empty.\n`
message += 'Something went wrong. Regenerate the package-lock.json with "npm install".\n'
message += 'If using a shrinkwrap, regenerate with "npm shrinkwrap".'
return Promise.reject(new Error(message))
}

return inflatableChild(
onDisk[name], name, topPath, tree, sw, requested, opts
).then((child) => {
Expand Down
68 changes: 68 additions & 0 deletions test/tap/lockfile-empty-dep-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict'

const common = require('../common-tap.js')
const path = require('path')
const test = require('tap').test

const Tacks = require('tacks')
const File = Tacks.File
const Dir = Tacks.Dir

const basedir = common.pkg
const testdir = path.join(basedir, 'testdir')

const fixture = new Tacks(Dir({
cache: Dir(),
global: Dir(),
tmp: Dir(),
testdir: Dir({
'package-lock.json': File({
name: 'http-locks',
version: '1.0.0',
lockfileVersion: 1,
requires: true,
dependencies: {
minimist: {}
}
}),
'package.json': File({
name: 'http-locks',
version: '1.0.0',
dependencies: {
minimist: common.registry + '/minimist/-/minimist-0.0.5.tgz'
}
})
})
}))

function setup () {
cleanup()
fixture.create(basedir)
}

function cleanup () {
fixture.remove(basedir)
}

test('setup', function (t) {
setup()
t.done()
})

test('raises error to regenerate the lock file', function (t) {
common.npm(['install'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.match(
stderr,
'npm ERR! Something went wrong. Regenerate the package-lock.json with "npm install".',
'returns message to regenerate package-lock'
)

t.done()
})
})

test('cleanup', function (t) {
cleanup()
t.done()
})
66 changes: 66 additions & 0 deletions test/tap/shrinkwrap-empty-dep-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict'

const common = require('../common-tap.js')
const path = require('path')
const test = require('tap').test

const Tacks = require('tacks')
const File = Tacks.File
const Dir = Tacks.Dir

const basedir = common.pkg
const testdir = path.join(basedir, 'testdir')

const fixture = new Tacks(Dir({
cache: Dir(),
global: Dir(),
tmp: Dir(),
testdir: Dir({
'npm-shrinkwrap.json': File({
name: 'http-locks',
version: '0.0.0',
dependencies: {
minimist: {}
}
}),
'package.json': File({
name: 'http-locks',
version: '1.0.0',
dependencies: {
minimist: common.registry + '/minimist/-/minimist-0.0.5.tgz'
}
})
})
}))

function setup () {
cleanup()
fixture.create(basedir)
}

function cleanup () {
fixture.remove(basedir)
}

test('setup', function (t) {
setup()
t.done()
})

test('raises error to regenerate the shrinkwrap', function (t) {
common.npm(['install'], {cwd: testdir}, function (err, code, stdout, stderr) {
if (err) throw err
t.match(
stderr,
'npm ERR! If using a shrinkwrap, regenerate with "npm shrinkwrap".',
'returns message to regenerate shrinkwrap'
)

t.done()
})
})

test('cleanup', function (t) {
cleanup()
t.done()
})

0 comments on commit 8788889

Please sign in to comment.