diff --git a/script/bootstrap b/script/bootstrap index 784d63035..f87a8c8b1 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -1,22 +1,31 @@ -#!/bin/sh +#!/usr/bin/env node +var safeExec = require('./utils/child-process-wrapper.js').safeExec; +var path = require('path'); -# exit on subprocess errors -set -o errexit - -exit_unless_npm_exists() { - if ! hash npm 2> /dev/null; then - echo "ERROR: Atom requires npm" - exit 1 - fi +// Executes an array of commands one by one. +function executeCommands(commands, done, index) { + index = (index == undefined ? 0 : index); + if (index < commands.length) + safeExec(commands[index], executeCommands.bind(this, commands, done, index + 1)); + else + done(null); } -exit_unless_npm_exists +// Join multiple commands into one line. +function joinCommands() { + var commandSeparator = process.platform == 'win32' ? '&' : ';'; + return Array.prototype.slice.call(arguments, 0).join(commandSeparator); +} -git submodule --quiet sync -git submodule --quiet update --recursive --init +var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo'; +var commands = [ + 'git submodule --quiet sync', + 'git submodule --quiet update --recursive --init', + joinCommands('cd vendor/apm', 'npm install --silent .'), + 'npm install --silent vendor/apm', + echoNewLine, + 'node vendor/apm/bin/apm install --silent', +]; -(cd vendor/apm && npm install --silent .) - -npm install --silent vendor/apm -echo "" -./node_modules/.bin/apm install --silent +process.chdir(path.dirname(__dirname)); +executeCommands(commands, process.exit); diff --git a/script/bootstrap.cmd b/script/bootstrap.cmd new file mode 100644 index 000000000..c9cf66238 --- /dev/null +++ b/script/bootstrap.cmd @@ -0,0 +1,6 @@ +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\bootstrap" %* +) ELSE ( + node "%~dp0\bootstrap" %* +) + diff --git a/script/build b/script/build index 4ca3456ca..00cb82e44 100755 --- a/script/build +++ b/script/build @@ -1,8 +1,12 @@ -#!/bin/sh +#!/usr/bin/env node +var cp = require('./utils/child-process-wrapper.js'); +var path = require('path'); -set -e +process.chdir(path.dirname(__dirname)); -cd "$(dirname "$0")/.." - -./script/bootstrap -./node_modules/.bin/grunt "$@" +cp.safeExec('node script/bootstrap', function() { + // ./node_modules/.bin/grunt "$@" + var gruntPath = path.join('node_modules', '.bin', 'grunt'); + var args = [gruntPath].concat(process.argv.slice(2)); + cp.safeSpawn(process.execPath, args, process.exit); +}); diff --git a/script/cibuild b/script/cibuild index 8742fe7c6..9a749de51 100755 --- a/script/cibuild +++ b/script/cibuild @@ -1,18 +1,41 @@ -#!/bin/sh +#!/usr/bin/env node +var cp = require('./utils/child-process-wrapper.js'); +var fs = require('fs'); +var path = require('path'); -set -e +process.chdir(path.dirname(__dirname)); -cd "$(dirname "$0")/.." +if (process.platform != 'darwin') + throw new Error('cibuild can not run on ' + process.platform + ' yet!'); -rm -rf ~/.atom -git clean -dff +var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME; -ATOM_CREDENTIALS_FILE=/var/lib/jenkins/config/atomcredentials -if [ -f $ATOM_CREDENTIALS_FILE ]; then - . $ATOM_CREDENTIALS_FILE - export ATOM_ACCESS_TOKEN=$ATOM_ACCESS_TOKEN # make it visibile to grunt. -fi +function readEnvironmentVariables(callback) { + var credenticalsPath = '/var/lib/jenkins/config/atomcredentials'; + fs.readFile(credenticalsPath, function(error, data) { + if (!error) { + var lines = String(data).trim().split('\n'); + for (i in lines) { + var parts = lines[i].split('='); + var key = parts[0].trim(); + var value = parts[1].trim().substr(1, parts[1].length - 2); + process.env[key] = value; + } + } + // Do not quit when got error. + callback(null); + }); +} -./script/bootstrap -./node_modules/.bin/apm clean -./node_modules/.bin/grunt ci --stack --no-color +cp.safeExec('node script/bootstrap', function() { + var async = require('async'); + async.series([ + readEnvironmentVariables, + require('rimraf').bind(global, path.join(homeDir, '.atom')), + cp.safeExec.bind(global, 'git clean -dff'), + cp.safeExec.bind(global, 'node node_modules/.bin/apm clean'), + cp.safeExec.bind(global, 'node node_modules/.bin/grunt ci --stack --no-color'), + ], function(error) { + process.exit(error ? 1 : 0); + }); +}); diff --git a/script/test b/script/test index deec68c42..708a7b5ec 100755 --- a/script/test +++ b/script/test @@ -1,8 +1,9 @@ -#!/bin/sh +#!/usr/bin/env node +var safeExec = require('./utils/child-process-wrapper.js').safeExec; +var path = require('path'); -set -e +process.chdir(path.dirname(__dirname)); -cd "$(dirname "$0")/.." - -./script/bootstrap -./node_modules/.bin/grunt ci --stack --no-color +safeExec('node script/bootstrap', function() { + safeExec('node node_modules/.bin/grunt ci --stack --no-color', process.exit); +}); diff --git a/script/utils/child-process-wrapper.js b/script/utils/child-process-wrapper.js new file mode 100644 index 000000000..c31f80b10 --- /dev/null +++ b/script/utils/child-process-wrapper.js @@ -0,0 +1,35 @@ +var childProcess = require('child_process'); + +// Exit the process if the command failed and only call the callback if the +// command succeed, output of the command would also be piped. +exports.safeExec = function(command, options, callback) { + if (!callback) { + callback = options; + options = {}; + } + var child = childProcess.exec(command, options, function(error, stdout, stderr) { + if (error) + process.exit(error.code); + else + callback(null); + }); + child.stderr.pipe(process.stderr); + child.stdout.pipe(process.stdout); +} + +// Same with safeExec but call child_process.spawn instead. +exports.safeSpawn = function(command, args, options, callback) { + if (!callback) { + callback = options; + options = {}; + } + var child = childProcess.spawn(command, args, options); + child.stderr.pipe(process.stderr); + child.stdout.pipe(process.stdout); + child.on('exit', function(code) { + if (code != 0) + process.exit(code); + else + callback(null); + }); +}