diff --git a/.travis.yml b/.travis.yml index 86f95f0b90..655bbd3b4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,8 +44,8 @@ install: - npm --version # Check the size of caches - du -sh ./node_modules || true - # Install npm dependecies and ensure that npm cache is not stale - - tools/npm/install-dependencies.sh + # Install npm dependecies + - npm install before_script: - mkdir -p $LOGS_DIR diff --git a/gulpfile.js b/gulpfile.js index 08461bb365..388db5a1d3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -15,7 +15,7 @@ var madge = require('madge'); var merge = require('merge'); var merge2 = require('merge2'); var path = require('path'); -var semver = require('semver'); + var watch = require('./tools/build/watch'); var transpile = require('./tools/build/transpile'); @@ -36,6 +36,11 @@ var replace = require('gulp-replace'); var insert = require('gulp-insert'); var shouldLog = require('./tools/build/logging'); +require('./tools/check-environment')({ + requiredNpmVersion: '>=2.9.0', + requiredNodeVersion: '>=0.12.2' +}); + // Make it easy to quiet down portions of the build. // --logs=all -> log everything (This is the default) // --logs=quiet -> log nothing @@ -63,35 +68,6 @@ var angularBuilder = { } }; -(function checkNodeAndNpmVersions() { - var requiredNpmVersion = '>=2.9.0'; - var requiredNodeVersion = '>=0.12.2'; - - exec('npm --version', function(e, stdout) { - var foundNpmVersion = semver.clean(stdout); - var foundNodeVersion = process.version; - var issues = []; - - - if (!semver.satisfies(foundNodeVersion, requiredNodeVersion)) { - issues.push('You are running unsupported node version. Found: ' + foundNodeVersion + - ' Expected: ' + requiredNodeVersion); - } - - if (!semver.satisfies(foundNpmVersion, requiredNpmVersion)) { - issues.push('You are running unsupported npm version. Found: ' + foundNpmVersion + - ' Expected: ' + requiredNpmVersion); - } - - if (issues.length) { - // TODO: in the future we should error, but let's just display the warning for a few days first - console.warn(Array(80).join('!')); - console.warn('Your environment is not in a good shape. Following issues were found:'); - issues.forEach(function(issue) {console.warn(' - ' + issue)}); - console.warn(Array(80).join('!')); - } - }); -}()); function sequenceComplete(done) { return function (err) { diff --git a/package.json b/package.json index b2b0b73047..33d5e77132 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "url": "https://github.com/angular/angular.git" }, "scripts": { - "postinstall": "node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --config modules/angular2/tsd.json && tsd reinstall --config tools/tsd.json", + "preinstall": "node tools/npm/check-node-modules --purge", + "postinstall": "node tools/npm/copy-npm-shrinkwrap && node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --config modules/angular2/tsd.json && tsd reinstall --config tools/tsd.json", "test": "gulp test.all.js && gulp test.all.dart" }, "dependencies": { diff --git a/tools/check-environment.js b/tools/check-environment.js new file mode 100644 index 0000000000..16c473370d --- /dev/null +++ b/tools/check-environment.js @@ -0,0 +1,39 @@ +var exec = require('child_process').exec; +var semver = require('semver'); + +var checkNodeModules = require('./npm/check-node-modules.js'); + + +function checkEnvironment(reqs) { + + exec('npm --version', function(e, stdout) { + var foundNpmVersion = semver.clean(stdout); + var foundNodeVersion = process.version; + var issues = []; + + + if (!semver.satisfies(foundNodeVersion, reqs.requiredNodeVersion)) { + issues.push('You are running unsupported node version. Found: ' + foundNodeVersion + + ' Expected: ' + reqs.requiredNodeVersion + '. Use nvm to update your node version.'); + } + + if (!semver.satisfies(foundNpmVersion, reqs.requiredNpmVersion)) { + issues.push('You are running unsupported npm version. Found: ' + foundNpmVersion + + ' Expected: ' + reqs.requiredNpmVersion + '. Run: npm update -g npm'); + } + + if (!checkNodeModules()) { + issues.push('Your node_modules directory is stale or out of sync with npm-shrinkwrap.json. Run: npm install'); + } + + if (issues.length) { + console.warn(Array(80).join('!')); + console.warn('Your environment is not in a good shape. Following issues were found:'); + issues.forEach(function(issue) {console.warn(' - ' + issue)}); + console.warn(Array(80).join('!')); + } + }); +} + + +module.exports = checkEnvironment; diff --git a/tools/npm/check-node-modules b/tools/npm/check-node-modules new file mode 100755 index 0000000000..09a1462892 --- /dev/null +++ b/tools/npm/check-node-modules @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var checkNpm = require('./check-node-modules.js'); + +var purgeIfStale = (process.argv.indexOf('--purge') !== -1) + +checkNpm(true, purgeIfStale); diff --git a/tools/npm/check-node-modules.js b/tools/npm/check-node-modules.js new file mode 100755 index 0000000000..bd4cbd9074 --- /dev/null +++ b/tools/npm/check-node-modules.js @@ -0,0 +1,50 @@ +"use strict"; + +var fs = require('fs'); +var path = require('path'); + +var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json'; +var NPM_SHRINKWRAP_CACHED_FILE = 'node_modules/npm-shrinkwrap.cached.json'; +var FS_OPTS = {encoding: 'utf-8'}; +var PROJECT_ROOT = path.join(__dirname, '../../'); + + +function checkNodeModules(logOutput, purgeIfStale) { + var nodeModulesOK = _checkCache(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE); + + if (nodeModulesOK) { + if (logOutput) console.log(':-) npm dependencies are looking good!'); + } else { + if (logOutput) console.error(':-( npm dependencies are stale or in an in unknown state!'); + if (purgeIfStale) { + if (logOutput) console.log(' purging...'); + + var nodeModulesPath = path.join(PROJECT_ROOT, 'node_modules'); + + if (fs.existsSync(nodeModulesPath)) { + // lazy-load fs-extra + var fse = require('fs-extra'); + fse.removeSync(nodeModulesPath); + } + } + } + + return nodeModulesOK; +} + + +function _checkCache(markerFile, cacheMarkerFile) { + var absoluteMarkerFilePath = path.join(PROJECT_ROOT, markerFile); + var absoluteCacheMarkerFilePath = path.join(PROJECT_ROOT, cacheMarkerFile); + + + if (!fs.existsSync(absoluteCacheMarkerFilePath)) return false; + + var markerContent = fs.readFileSync(absoluteMarkerFilePath, FS_OPTS); + var cacheMarkerContent = fs.readFileSync(absoluteCacheMarkerFilePath, FS_OPTS); + + return markerContent == cacheMarkerContent; +} + + +module.exports = checkNodeModules; diff --git a/tools/npm/copy-npm-shrinkwrap b/tools/npm/copy-npm-shrinkwrap new file mode 100755 index 0000000000..ad1fea788e --- /dev/null +++ b/tools/npm/copy-npm-shrinkwrap @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +var fse = require('fs-extra'); +var path = require('path'); + +var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json'; +var NPM_SHRINKWRAP_CACHED_FILE = 'node_modules/npm-shrinkwrap.cached.json'; +var PROJECT_ROOT = path.join(__dirname, '../../'); + +process.chdir(PROJECT_ROOT); + +fse.copySync(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE); diff --git a/tools/npm/install-dependencies.sh b/tools/npm/install-dependencies.sh deleted file mode 100755 index b4a828a00b..0000000000 --- a/tools/npm/install-dependencies.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e - -SHRINKWRAP_FILE=npm-shrinkwrap.json -SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json - -if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then - echo 'No shrinkwrap changes detected. npm install will be skipped...'; - echo 'Running npm postinstall' - npm run postinstall -else - echo 'Blowing away node_modules and reinstalling npm dependencies...' - rm -rf node_modules - npm install - cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE - echo 'npm install successful!' -fi