-
-
Save cesarandreu/9f6158959493f3565065 to your computer and use it in GitHub Desktop.
Gulpfiles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var gulp = require('gulp'), | |
_ = require('lodash'), | |
path = require('path'), | |
runSequence = require('run-sequence'), | |
mergeStream = require('merge-stream'), | |
streamqueue = require('streamqueue'), | |
// gutil = require('gulp-util'), | |
// debug = require('gulp-debug'), | |
mincss = require('gulp-minify-css'), | |
uglify = require('gulp-uglify'), | |
sourcemaps = require('gulp-sourcemaps'), | |
rev = require('gulp-rev'), | |
revCollector = require('gulp-rev-collector'), | |
autoprefixer = require('gulp-autoprefixer'), | |
image = require('gulp-image'), | |
clone = require('gulp-clone'), | |
concat = require('gulp-concat'), | |
injector = require('gulp-inject'), | |
preprocess = require('gulp-preprocess'), | |
ngannotate = require('gulp-ng-annotate'), | |
htmlmin = require('gulp-htmlmin'), | |
templateCache = require('gulp-angular-templatecache'), | |
rimraf = require('gulp-rimraf'), | |
rename = require('gulp-rename'), | |
jade = require('gulp-jade'), | |
coffee = require('gulp-coffee'), | |
sass = require('gulp-sass'), | |
gulpif = require('gulp-if'), | |
configuration = require('./configuration'), | |
files = require(configuration.files); | |
// Appends './app' to all files | |
var prefixedFiles = {}; | |
_(['scripts', 'application', 'templates', 'styles', 'images', 'fonts', 'others']) | |
.map(function (name) { | |
prefixedFiles[name] = _.map(files[name], function (file) { | |
return path.join(configuration.app, file); | |
}); | |
}); | |
// TASKS START HERE | |
// Removes build folder | |
gulp.task('clean', function () { | |
return gulp | |
.src(configuration.buildDirectory, {read: false}) | |
.pipe(rimraf({force: true})); | |
}); | |
// Removes output folder (../../public) | |
gulp.task('clean-output', function () { | |
return gulp | |
.src(configuration.output, {read: false}) | |
.pipe(rimraf({force: true})); | |
}); | |
// Renders main.html application, injects .js/.css files | |
gulp.task('application', function () { | |
var renamedScripts = gulp.src('../build/scripts/scripts-*.js', {base: configuration.buildDirectory}); | |
var renamedStyles = gulp.src('../build/styles/styles-*.css', {base: configuration.buildDirectory}); | |
// Removes './app' in filepath and returns the script/style tag | |
var scriptTag = _.template('<script src="<%= filepath %>"></script>'); | |
var styleTag = _.template('<link rel="stylesheet" href="<%= filepath %>">'); | |
function transformScript(filepath) { | |
return scriptTag({filepath: filepath.replace(path.resolve(configuration.buildDirectory), '')}); | |
} | |
function transformStyle(filepath) { | |
return styleTag({filepath: filepath.replace(path.resolve(configuration.buildDirectory), '')}); | |
} | |
return gulp | |
.src(prefixedFiles.application, {base: configuration.app}) | |
.pipe(gulpif(/\.jade$/, jade({ | |
pretty: true, | |
doctype: 'html', | |
locals: configuration.locals | |
}))) | |
.pipe(injector(renamedScripts, {transform: transformScript})) | |
.pipe(injector(renamedStyles, {transform: transformStyle})) | |
.pipe(preprocess({ | |
context: configuration.context | |
})) | |
.pipe(gulp.dest(configuration.buildDirectory)); | |
}); | |
gulp.task('assets', function () { | |
// Get all images | |
// Save to /img folder | |
// Rev and save to /img folder | |
// Get the rev manifest | |
var images = gulp | |
.src(prefixedFiles.images, {base: configuration.app}) | |
.pipe(image()) | |
.pipe(gulp.dest(configuration.buildDirectory)) | |
.pipe(rev()) | |
.pipe(gulp.dest(configuration.buildDirectory)) | |
.pipe(rev.manifest()); | |
// Get css styles | |
var css = gulp.src(prefixedFiles.styles.concat('!/**/*.scss'), {base: configuration.app}); | |
// Get sass styles | |
// Compile sass | |
var scss = gulp | |
.src(prefixedFiles.styles.concat('!/**/*.css'), {base: configuration.app}) | |
.pipe(sass({ | |
errLogToConsole: true, | |
includePaths: [path.join(process.cwd(), configuration.app, 'styles/')] | |
})); | |
// Queue sass and css afterward | |
// Apply prefixes for older browsers | |
// Minify styles | |
// Concatenate files | |
var styles = streamqueue({ objectMode: true }, scss, css) | |
.pipe(autoprefixer(['last 2 versions', '> 5%'])) | |
.pipe(mincss()) | |
.pipe(concat('/styles/styles.css')); | |
// Merge styles stream with cloned images-manifest stream | |
// Replace image links in css | |
// Rev and save to /styles folder | |
styles = mergeStream(styles, images.pipe(clone())) | |
.pipe(revCollector()) | |
.pipe(rev()) | |
.pipe(gulp.dest(configuration.buildDirectory)); | |
// Get all templates | |
// Compile jade files | |
// Minify html | |
// Aply preprocessor | |
var templates = gulp | |
.src(prefixedFiles.templates, {base: configuration.app}) | |
.pipe(gulpif(/\.jade$/, jade({ | |
pretty: false, | |
doctype: 'html', | |
locals: configuration.locals | |
}))) | |
.pipe(rename(function () { | |
// DO NOT REMOVE | |
// Removing this breaks template cache url | |
})) | |
.pipe(htmlmin({ | |
removeEmptyAttributes: true, | |
removeRedundantAttributes: true, | |
removeScriptTypeAttributes: true, | |
removeStyleLinkTypeAttributes: true | |
})) | |
.pipe(preprocess({ | |
context: configuration.context | |
})); | |
// Merge templates stream with cloned images-manifest stream | |
// Replace image links in templates | |
// Save templates to /template and /views | |
// Convert all templates into angularjs injectable strings | |
templates = mergeStream(templates, images.pipe(clone())) | |
.pipe(revCollector()) | |
.pipe(gulp.dest(configuration.buildDirectory)) // should also copy over templates | |
.pipe(templateCache({ | |
module: configuration.module | |
})) | |
.pipe(rename(function (file) { | |
// Renames from ./templates.js to ./scripts/templates.js | |
file.dirname = path.join(file.dirname, 'scripts'); | |
return file; | |
})); | |
// Get all scripts | |
var scripts = gulp.src(prefixedFiles.scripts, {base: configuration.app}); | |
// Compile coffeescript | |
// Apply preprocessor | |
// Apply ngannotate | |
// Merge scripts stream with javascript-ified templates | |
// UglifyJS will concatenate and minify everything | |
// Rev (only js files, so it'll ignore source maps) and save to /scripts folder | |
scripts = mergeStream(scripts, templates) | |
.pipe(gulpif(/\.coffee$/, coffee({ | |
bare: true | |
}))) | |
.pipe(gulpif(function (file) { | |
return file.path.indexOf('bower_components') === -1; | |
}, preprocess({ | |
context: configuration.context | |
}))) | |
.pipe(gulpif(function (file) { | |
return file.path.indexOf('bower_components') === -1; | |
}, ngannotate({ | |
add: true, | |
single_quotes: true | |
}))) | |
.pipe(gulp.dest(configuration.buildDirectory)) | |
.pipe(sourcemaps.init()) | |
.pipe(concat('/scripts/scripts.js')) | |
.pipe(uglify()) | |
.pipe(sourcemaps.write('/', {sourceRoot: '/'})) | |
.pipe(gulpif(/\.js$/, rev())) | |
.pipe(gulp.dest(configuration.buildDirectory)); | |
return mergeStream(scripts, styles); | |
}); | |
// Copies other files | |
gulp.task('copy', function () { | |
var fileList = [] | |
.concat(prefixedFiles.fonts) | |
.concat(prefixedFiles.others); | |
return gulp | |
.src(fileList, {base: configuration.app}) | |
.pipe(gulp.dest(configuration.buildDirectory)); | |
}); | |
gulp.task('copy-output', function () { | |
return gulp | |
.src(path.join(configuration.buildDirectory, '/**/*')) | |
.pipe(gulp.dest(configuration.output)); | |
}); | |
gulp.task('build:production', function(cb) { | |
process.env.NODE_ENV = 'production'; | |
runSequence('build', cb); | |
}); | |
gulp.task('build', function (cb) { | |
runSequence( | |
'clean', | |
['assets', 'copy'], | |
'application', | |
'clean-output', | |
'copy-output', | |
cb | |
); | |
}); | |
gulp.task('default', ['build']); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var gulp = require('gulp'), | |
runSequence = require('run-sequence'), | |
gutil = require('gulp-util'), | |
// debug = require('gulp-debug'), | |
livereload = require('gulp-livereload'), | |
express = require('express'), | |
httpProxy = require('http-proxy'), | |
morgan = require('morgan'), | |
path = require('path'), | |
_ = require('lodash'), | |
injector = require('gulp-inject'), | |
autoprefixer = require('gulp-autoprefixer'), | |
preprocess = require('gulp-preprocess'), | |
newer = require('gulp-newer'), | |
rimraf = require('gulp-rimraf'), | |
rename = require('gulp-rename'), | |
jade = require('gulp-jade'), | |
templateCache = require('gulp-angular-templatecache'), | |
coffee = require('gulp-coffee'), | |
sass = require('gulp-sass'), | |
gulpif = require('gulp-if'), | |
openurl = require('openurl'), | |
url = require('url'), | |
configuration = require('./configuration'), | |
files = require(configuration.files); | |
// Appends './app' to all files | |
var prefixedFiles = {}; | |
_(['scripts', 'application', 'templates', 'styles', 'images', 'fonts', 'others']) | |
.map(function (name) { | |
prefixedFiles[name] = _.map(files[name], function (file) { | |
return path.join(configuration.app, file); | |
}); | |
}); | |
// TASKS START HERE | |
// Removes .build folder | |
gulp.task('clean', function () { | |
return gulp | |
.src(configuration.devDirectory, {read: false}) | |
.pipe(rimraf({force: true})); | |
}); | |
// Compiles coffeescript, applies preprocessor | |
gulp.task('scripts', function () { | |
return gulp | |
.src(prefixedFiles.scripts, {base: configuration.app}) | |
.pipe(newer({ | |
dest: configuration.devDirectory, | |
ext: '.js' | |
})) | |
.pipe(gulpif(/\.coffee$/, coffee({ | |
bare: true | |
// sourceMap: true | |
}))) | |
.pipe(gulpif(function (file) { | |
return file.path.indexOf('bower_components') === -1; | |
}, preprocess({ | |
context: configuration.context | |
}))) | |
.pipe(gulp.dest(configuration.devDirectory)); | |
}); | |
// Renders main.html application, injects .js/.css files | |
gulp.task('application', function () { | |
// Renames .coffee files to .js for injector | |
var renamedScripts = gulp | |
.src(prefixedFiles.scripts, {read: false}) | |
.pipe(rename({extname: '.js'})); | |
// Renames .scss/.less files to .css for injector | |
var renamedStyles = gulp | |
.src(prefixedFiles.styles, {read: false}) | |
.pipe(rename({extname: '.css'})); | |
// Removes './app' in filepath and returns the script/style tag | |
var scriptTag = _.template('<script src="<%= filepath %>"></script>'); | |
var styleTag = _.template('<link rel="stylesheet" href="<%= filepath %>">'); | |
function transformScript(filepath) { | |
return scriptTag({filepath: filepath.replace(path.resolve(configuration.app), '')}); | |
} | |
function transformStyle(filepath) { | |
return styleTag({filepath: filepath.replace(path.resolve(configuration.app), '')}); | |
} | |
return gulp | |
.src(prefixedFiles.application, {base: configuration.app}) | |
.pipe(newer({ | |
dest: configuration.devDirectory, | |
ext: '.html' | |
})) | |
.pipe(gulpif(/\.jade$/, jade({ | |
pretty: true, | |
doctype: 'html', | |
locals: configuration.locals | |
}))) | |
.pipe(injector(renamedScripts, {transform: transformScript})) | |
.pipe(injector(renamedStyles, {transform: transformStyle})) | |
.pipe(preprocess({ | |
context: configuration.context | |
})) | |
.pipe(gulp.dest(configuration.devDirectory)); | |
}); | |
// Compiles views and templates jade files | |
gulp.task('templates', function () { | |
return gulp | |
.src(prefixedFiles.templates, {base: configuration.app}) | |
.pipe(newer({ | |
dest: configuration.devDirectory, | |
ext: '.html' | |
})) | |
.pipe(gulpif(/\.jade$/, jade({ | |
pretty: true, | |
doctype: 'html', | |
locals: configuration.locals | |
}))) | |
.pipe(preprocess({ | |
context: configuration.context | |
})) | |
.pipe(gulp.dest(configuration.devDirectory)) | |
.pipe(templateCache({ | |
module: configuration.module | |
})) | |
.pipe(rename(function (file) { | |
// Renames from ./templates.js to ./scripts/templates.js | |
file.dirname = path.join(file.dirname, 'scripts'); | |
return file; | |
})) | |
.pipe(gulp.dest(configuration.devDirectory)); | |
}); | |
// Compiles sass and css files | |
gulp.task('styles', function () { | |
return gulp | |
.src(prefixedFiles.styles, {base: configuration.app}) | |
.pipe(newer({ | |
dest: configuration.devDirectory, | |
ext: '.css' | |
})) | |
.pipe(gulpif(/\.css$/, autoprefixer())) | |
.pipe(gulpif(/\.scss$/, sass({ | |
errLogToConsole: true, | |
sourceComments: 'map' | |
}))) | |
.pipe(gulp.dest(configuration.devDirectory)); | |
}); | |
// Copies other files | |
gulp.task('copy', function () { | |
var fileList = [] | |
.concat(prefixedFiles.images) | |
.concat(prefixedFiles.fonts) | |
.concat(prefixedFiles.others); | |
return gulp | |
.src(fileList, {base: configuration.app}) | |
.pipe(newer({ | |
dest: configuration.devDirectory | |
})) | |
.pipe(gulp.dest(configuration.devDirectory)); | |
}); | |
gulp.task('watch', function () { | |
var copyList = [] | |
.concat(prefixedFiles.images) | |
.concat(prefixedFiles.fonts) | |
.concat(prefixedFiles.others), | |
lr = livereload(); | |
// watchStyles = [] | |
// .concat(prefixedFiles.styles) | |
// .concat(_.map(configuration.watch.styles, function (file) { | |
// return path.join(configuration.app, file); | |
// })); | |
gulp.watch(prefixedFiles.scripts, ['scripts']); | |
gulp.watch(prefixedFiles.templates, ['templates']); | |
gulp.watch(prefixedFiles.styles, ['styles']); | |
gulp.watch(prefixedFiles.application, ['application']); | |
gulp.watch(copyList, ['copy']); | |
gulp.watch([ | |
configuration.devDirectory + '/{,**/}*.{html,css,js}', | |
'!' + configuration.devDirectory + '/bower_components/{,**/}*', | |
'!' + configuration.devDirectory + '/scripts/viewer/*', | |
'!' + configuration.devDirectory + '/img/{,**/}*' | |
]) | |
.on('change', function (file) { | |
lr.changed(file.path); | |
}); | |
}); | |
gulp.task('server', function (done) { | |
var app = express(), | |
proxy = httpProxy.createProxyServer({}); | |
proxy.on('error', function (e) { | |
gutil.log(gutil.colors.red('Proxy error:'), e); | |
}); | |
app.use(morgan('dev')); | |
app.use(require('connect-livereload')()); | |
app.use(express.static(path.resolve(__dirname, configuration.devDirectory))); | |
app.use(express.static(path.resolve(__dirname, configuration.reqDirectory))); | |
app.use(function (req, res, next) { | |
if (configuration.server.proxy.regex.test(req.url)) { | |
// this gets ignored | |
// res.setHeader('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); | |
// res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); | |
// res.header('Pragma', 'no-cache'); | |
// res.header('Expires', 0); | |
proxy.web(req, res, {target: configuration.server.proxy.url}); | |
} else { | |
next(); | |
} | |
}); | |
app.use(function (req, res) { | |
gutil.log('Responding with', gutil.colors.cyan(configuration.main)); | |
res.sendfile(path.resolve(__dirname, configuration.devDirectory, configuration.main)); | |
}); | |
app.listen(configuration.server.port, function () { | |
// Lets gulp know the task is done | |
done(); | |
}); | |
}); | |
gulp.task('open', function () { | |
openurl.open(url.format({ | |
protocol: 'http', | |
hostname: 'localhost', | |
port: configuration.server.port | |
})); | |
}); | |
gulp.task('serve', function (cb) { | |
runSequence( | |
'clean', | |
['scripts', 'templates', 'styles', 'application', 'copy'], | |
'server', | |
'watch', | |
'open', | |
cb | |
); | |
}); | |
gulp.task('default', ['serve']); | |
// Ran this to rename .js.coffee to .cofee | |
// rename 's/.js.coffee$/.coffee/' *.js.coffee |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var gulp = require('gulp'), | |
request = require('request'), | |
runSequence = require('run-sequence'), | |
karma = require('karma').server, | |
batch = require('gulp-batch'), | |
spawn = require('child_process').spawn, | |
exec = require('child_process').exec, | |
_ = require('lodash'), | |
protractor = require('gulp-protractor').protractor, | |
glob = require('glob'), | |
webdriverUpdate = require('gulp-protractor').webdriver_update; | |
// bundle exec rake integration:prepare | |
gulp.task('rails:prepare', function (done) { | |
var child = exec('bundle exec rake integration:prepare', { | |
pwd: '../..' | |
}); | |
child.stdout.on('data', function (data) { | |
console.log('prepare:', data.replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
child.stderr.on('data', function (data) { | |
console.log('prepare:', data.replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
child.on('close', function (code) { | |
done(code); | |
}); | |
}); | |
// bundle exec rake integration:run | |
gulp.task('rails:run', function (done) { | |
var child = spawn('bundle', ['exec', 'rake', 'integration:run'], { | |
pwd: '../..' | |
}); | |
child.stderr.on('data', function (data) { | |
console.log('server:', data.toString().replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
child.stdout.on('data', function (data) { | |
console.log('server:', data.toString().replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
process.on('exit', function () { | |
child.kill('SIGINT'); | |
}); | |
process.on('SIGINT', function () { | |
process.exit(2); | |
}); | |
function isReady (count) { | |
request('http://localhost:4000/', function (err, res) { | |
if (count > 100) { | |
done(count); | |
} else if (!err && res.statusCode === 200) { | |
done(); | |
} else { | |
setTimeout(function () { | |
isReady(++count); | |
}, 250); | |
} | |
}); | |
} | |
console.log('Trying to start rails server on port 4000...'); | |
isReady(0); | |
}); | |
gulp.task('rails', function (done) { | |
runSequence( | |
'rails:prepare', | |
'rails:run', | |
done | |
); | |
}); | |
gulp.task('protractor:full', function () { | |
return gulp.src('../test/e2e/**/*_spec.*') | |
.pipe(protractor({ | |
configFile: '../protractor.full.conf.js' | |
})); | |
}); | |
gulp.task('protractor:circle', function () { | |
var CIRCLE_TOTAL = _.parseInt(process.env.CIRCLE_NODE_TOTAL) || 1, | |
CIRCLE_INDEX = _.parseInt(process.env.CIRCLE_NODE_INDEX) || 0; | |
var files = _.chain(glob.sync('../test/e2e/**/*_spec.*')) | |
.sortBy(function (name) { | |
return name; | |
}) | |
.filter(function (file, idx) { | |
return idx % CIRCLE_TOTAL === CIRCLE_INDEX; | |
}) | |
.value(); | |
console.log('Files:', files); | |
return gulp.src(files) | |
.pipe(protractor({ | |
configFile: '../protractor.circle.conf.js' | |
})); | |
}); | |
gulp.task('protractor:live', function () { | |
gulp.watch('../test/e2e/**/*_spec.*', batch(function (events, done) { | |
events | |
.pipe(protractor({ | |
args: process.env.DEBUG === 'true' ? ['debug'] : [], | |
configFile: '../protractor.live.conf.js' | |
})).on('error', function () { | |
done(); | |
}).on('end', function () { | |
done(); | |
}); | |
})); | |
}); | |
gulp.task('webdriver:update', webdriverUpdate); | |
gulp.task('webdriver:start', function () { | |
var child = spawn('../node_modules/.bin/webdriver-manager', ['start']); | |
child.stderr.on('data', function (data) { | |
console.log('webdriver:', data.toString().replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
child.stdout.on('data', function (data) { | |
console.log('webdriver:', data.toString().replace(/(\r\n|\n|\r)/gm,'')); | |
}); | |
process.on('exit', function () { | |
child.kill('SIGINT'); | |
}); | |
process.on('SIGINT', function () { | |
process.exit(2); | |
}); | |
}); | |
gulp.task('webdriver:live', function () { | |
var child = spawn('../node_modules/.bin/webdriver-manager', ['start']); | |
process.on('exit', function () { | |
child.kill('SIGINT'); | |
}); | |
process.on('SIGINT', function () { | |
process.exit(2); | |
}); | |
}); | |
gulp.task('e2e:full', ['webdriver:start', 'protractor:full']); | |
gulp.task('e2e:live', ['webdriver:live', 'protractor:live']); | |
gulp.task('e2e:circle', ['protractor:circle']); | |
gulp.task('karma:live', function (done) { | |
// Paths are all relative to this file's location | |
var files = _.map(require('../app/files.js').scripts, function (file) { | |
return '../devbuild' + file; | |
}); | |
files.push('../app/bower_components/angular-mocks/angular-mocks.js'); | |
files.push('../test/unit/**/*.js'); | |
console.log('FILES', files); | |
var config = require('../karma.conf.js')(); | |
config.reporters = ['progress']; | |
config.singleRun = false; | |
config.files = files; | |
config.basePath = ''; | |
karma.start(config, function (exitCode) { | |
done(exitCode); | |
process.exit(exitCode); | |
}); | |
}); | |
gulp.task('karma:full', function (done) { | |
// Paths are all relative to this file's location | |
var files = _.map(require('../app/files.js').scripts, function (file) { | |
return '../build' + file; | |
}); | |
files.push('../app/bower_components/angular-mocks/angular-mocks.js'); | |
files.push('../test/unit/**/*.js'); | |
console.log('FILES', files); | |
var config = require('../karma.conf.js')(); | |
config.reporters = ['progress']; | |
config.singleRun = true; | |
config.files = files; | |
config.basePath = ''; | |
karma.start(config, function (exitCode) { | |
done(exitCode); | |
process.exit(exitCode); | |
}); | |
}); | |
gulp.task('karma:circle', function (done) { | |
var CIRCLE_TOTAL = _.parseInt(process.env.CIRCLE_NODE_TOTAL); | |
var CIRCLE_INDEX = _.parseInt(process.env.CIRCLE_NODE_INDEX); | |
// Paths are all relative to this file's location | |
var files = _.map(require('../app/files.js').scripts, function (file) { | |
return '../build' + file; | |
}); | |
files.push('../app/bower_components/angular-mocks/angular-mocks.js'); | |
files = files.concat( | |
_.chain(glob.sync('../test/unit/**/*.js')) | |
.sortBy(function (name) { | |
return name; | |
}) | |
.filter(function (file, idx) { | |
return idx % CIRCLE_TOTAL === CIRCLE_INDEX; | |
}) | |
.value() | |
); | |
console.log('FILES', files); | |
var config = require('../karma.conf.js')(); | |
config.reporters = ['dots']; | |
config.singleRun = true; | |
config.files = files; | |
config.basePath = ''; | |
karma.start(config, function (exitCode) { | |
done(exitCode); | |
process.exit(exitCode); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment