build(npm): add tools/npm/reshrinkwrap script and update docs

This commit is contained in:
Igor Minar 2016-01-02 21:47:09 -08:00 committed by Igor Minar
parent 625474c4e2
commit a0d25db4a5
4 changed files with 33 additions and 29 deletions

View File

@ -3,16 +3,11 @@ All of our npm dependencies are locked via the `npm-shrinkwrap.json` file for th
- our project has lots of dependencies which update at unpredictable times, so it's important that - our project has lots of dependencies which update at unpredictable times, so it's important that
we update them explicitly once in a while rather than implicitly when any of us runs npm install we update them explicitly once in a while rather than implicitly when any of us runs npm install
- locked dependencies allow us to do reuse npm cache on travis, significantly speeding up our builds - locked dependencies allow us to do reuse npm cache on travis, significantly speeding up our builds
(by 5min or more) (by 5 minutes or more)
- locked dependencies allow us to detect when node_modules folder is out of date after a branch switch - locked dependencies allow us to detect when node_modules folder is out of date after a branch switch
which allows us to build the project with the correct dependencies every time which allows us to build the project with the correct dependencies every time
However npm's shrinkwrap is known to be buggy, so we need to take some extra steps to deal with this. We also generate `npm-shrinkwrap.clean.js` file which is used during code reviews or debugging to easily review what has actually changed without extra noise.
The most important step is generating the npm-shrinkwrap.clean.js which is used during code reviews
or debugging to easily review what has actually changed.
See https://github.com/npm/npm/issues/3581 for related npm issue. A common symptom is that the `from`
property of various dependencies in `npm-shrinkwrap.json` "arbitrarily" changes depending on when and
where the shrinkwrap command was run.
To add a new dependency do the following: To add a new dependency do the following:
@ -20,14 +15,11 @@ To add a new dependency do the following:
installation. This is due to an optional `fsevents` dependency that is really required on MacOS installation. This is due to an optional `fsevents` dependency that is really required on MacOS
to get good performance from file watching. to get good performance from file watching.
2. make sure you are in sync with `upstream/master` 2. make sure you are in sync with `upstream/master`
3. ensure that your `node_modules` directory is not stale or poisoned by doing a clean install with 3. ensure that your `node_modules` directory is not stale by running `npm install`
`rm -rf node_modules && npm install`
4. add a new dependency via `npm install --save-dev <packagename>` 4. add a new dependency via `npm install --save-dev <packagename>`
5. update npm-shrinkwrap.json with `npm shrinkwrap --dev` 5. run `./tools/npm/reshrinkwrap`
6. run `./tools/npm/clean-shrinkwrap.js` 6. these steps should change 3 files: `package.json`, `npm-shrinkwrap.json` and `npm-shrinkwrap.clean.json`
7. these steps should change 3 files: `package.json`, `npm-shrinkwrap.json` and 7. commit changes to these three files and you are done
`npm-shrinkwrap.clean.json`
8. commit changes to these three files and you are done
To update existing dependency do the following: To update existing dependency do the following:
@ -36,16 +28,14 @@ To update existing dependency do the following:
installation. This is due to an optional `fsevents` dependency that is really required on MacOS installation. This is due to an optional `fsevents` dependency that is really required on MacOS
to get good performance from file watching. to get good performance from file watching.
2. make sure you are in sync with `upstream/master`: `git fetch upstream && git rebase upstream/master` 2. make sure you are in sync with `upstream/master`: `git fetch upstream && git rebase upstream/master`
3. ensure that your `node_modules` directory is not stale or poisoned by doing a clean install with 3. ensure that your `node_modules` directory is not stale by running `npm install`
`rm -rf node_modules && npm install`
4. run `npm install --save-dev <packagename>@<version|latest>` or `npm update <packagename>` to 4. run `npm install --save-dev <packagename>@<version|latest>` or `npm update <packagename>` to
update to the latest version that matches version constraint in `package.json` update to the latest version that matches version constraint in `package.json`
5. relock the dependencies with `npm shrinkwrap --dev` 5. run `./tools/npm/reshrinkwrap`
6. clean up the shrinkwrap file for review with `./tools/npm/clean-shrinkwrap.js` 6. these steps should change 2 files: `npm-shrinkwrap.json` and `npm-shrinkwrap.clean.json`.
7. these steps should change 2 files: `npm-shrinkwrap.json` and `npm-shrinkwrap.clean.json`.
Optionally if you used `npm install ...` in the first step, `package.json` might be modified as Optionally if you used `npm install ...` in the first step, `package.json` might be modified as
well. well.
8. commit changes to these three files and you are done 7. commit changes to these three files and you are done
To Remove an existing dependency do the following: To Remove an existing dependency do the following:
@ -54,10 +44,8 @@ To Remove an existing dependency do the following:
installation. This is due to an optional `fsevents` dependency that is really required on MacOS installation. This is due to an optional `fsevents` dependency that is really required on MacOS
to get good performance from file watching. to get good performance from file watching.
2. make sure you are in sync with `upstream/master`: `git fetch upstream && git rebase upstream/master` 2. make sure you are in sync with `upstream/master`: `git fetch upstream && git rebase upstream/master`
3. ensure that your `node_modules` directory is not stale or poisoned by doing a clean install with 3. ensure that your `node_modules` directory is not stale by running `npm install`
`rm -rf node_modules && npm install`
4. run `npm uninstall --save-dev <packagename>@<version|latest>` 4. run `npm uninstall --save-dev <packagename>@<version|latest>`
5. relock the dependencies with `npm shrinkwrap --dev` 5. run `./tools/npm/reshrinkwrap`
6. clean up the shrinkwrap file for review with `./tools/npm/clean-shrinkwrap.js` 6. these steps should change 3 files: `npm-shrinkwrap.json` and `npm-shrinkwrap.clean.json`.
7. these steps should change 3 files: `npm-shrinkwrap.json` and `npm-shrinkwrap.clean.json`. 7. commit changes to these three files and you are done
8. commit changes to these three files and you are done

View File

@ -27,12 +27,12 @@ function cleanModule(moduleRecord, name) {
} }
console.log('Reading npm-shrinkwrap.json'); //console.log('Reading npm-shrinkwrap.json');
var shrinkwrap = require('../../npm-shrinkwrap.json'); var shrinkwrap = require('../../npm-shrinkwrap.json');
console.log('Cleaning shrinkwrap object'); //console.log('Cleaning shrinkwrap object');
cleanModule(shrinkwrap, shrinkwrap.name); cleanModule(shrinkwrap, shrinkwrap.name);
var cleanShrinkwrapPath = path.join(__dirname, '..', '..', 'npm-shrinkwrap.clean.json'); var cleanShrinkwrapPath = path.join(__dirname, '..', '..', 'npm-shrinkwrap.clean.json');
console.log('Writing cleaned to', cleanShrinkwrapPath); console.log('writing npm-shrinkwrap.clean.json');
fs.writeFileSync(cleanShrinkwrapPath, JSON.stringify(sorted(shrinkwrap), null, 2) + "\n"); fs.writeFileSync(cleanShrinkwrapPath, JSON.stringify(sorted(shrinkwrap), null, 2) + "\n");

View File

@ -11,6 +11,7 @@ var PROJECT_ROOT = path.join(__dirname, '../../');
process.chdir(PROJECT_ROOT); process.chdir(PROJECT_ROOT);
if (fs.existsSync(NPM_SHRINKWRAP_FILE)) { if (fs.existsSync(NPM_SHRINKWRAP_FILE)) {
console.log('copying shrinkwrap fingerprint to', NPM_SHRINKWRAP_CACHED_FILE);
fse.copySync(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE); fse.copySync(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
} else { } else {
console.warn(`${NPM_SHRINKWRAP_FILE} not found. Copy operation will be skipped.`); console.warn(`${NPM_SHRINKWRAP_FILE} not found. Copy operation will be skipped.`);

15
tools/npm/reshrinkwrap Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env node
'use strict';
let childProcess = require('child_process');
childProcess.spawn('npm', ['shrinkwrap', '--dev'], {stdio: 'inherit'}).on('exit', (exitCode) => {
if (exitCode !== 0) return;
childProcess.fork('./tools/npm/clean-shrinkwrap.js').on('exit', (exitCode) => {
if (exitCode !== 0) return;
childProcess.fork('./tools/npm/copy-npm-shrinkwrap');
});
});