Gulp returns 0 when tasks fail

21,655

Solution 1

A fix has been introduced in this commit.

It works something like this:

gulp.src("src/**/*.js")
  .pipe(jshint())
  .pipe(jshint.reporter("default"))
  .pipe(jshint.reporter("fail"));

I have been using it on circleci and it works a treat!

Solution 2

You need to 'return gulp.src(...' so that the task waits for the returned stream.

EDIT

Gulp tasks are asynchronous by nature. The actual task is not executed yet at the time of 'gulp.src(...).pipe(...);'. In your example, the gulp tasks mark their results as success before the actual tasks are executed.

There are some ways to make gulp to wait for your actual task. Use a callback or return a stream or promise.

https://github.com/gulpjs/gulp/blob/master/docs/API.md#async-task-support

The easiest way is just returning the stream of 'gulp.src(...).pipe(...)'. If gulp task gets a stream, it will listen to 'end' event and 'error' event. They corresponds to return code 0 and 1. So, a full example for your 'lint' task would be:

gulp.task('lint', function () {
    return gulp.src('./*.js')
               .pipe(jshint('jshintrc.json'))
               .pipe(jshint.reporter('jshint-stylish'));
});

A bonus is that now you can measure the actual time spent on your tasks.

Solution 3

@robrich is right, you have to keep track of exit codes yourself, but there's no need for a forceful approach. The process global is an EventEmitter which you can bind your exit function to.

var exitCode = 0

gulp.task('test', function (done) {
  return require('child_process')
    .spawn('npm', ['test'], {stdio: 'pipe'})
    .on('close', function (code, signal) {
      if (code) exitCode = code
      done()
    })
})

gulp.on('err', function (err) {
  process.emit('exit') // or throw err
})

process.on('exit', function () {
  process.nextTick(function () {
    process.exit(exitCode)
  })
})

Solution 4

gulp-jshint has been struggling with how to fail the build on jshint fail. On the one hand, we can crash the build inside jshint, but then you never get to the reporter. On the other hand, requiring the reporter to fail the build isn't part of the default reporters. I generally hook up my own reporter that keeps track of fails, and .on('end', function () { will process.exit(1). It's quite brute force, but it works like a charm. See https://github.com/wearefractal/gulp-jshint/issues/10

Solution 5

Similar to Andy Piper answer above, I have found this module stream-combiner2 to be useful when running a sequence of tasks to ensure and exit code is emitted if there is an error somewhere. Can be used something like this

var combiner = require('stream-combiner2');

var tasks = combiner.obj([
    gulp.src(files),
    task1(options),
    task2(options),
    gulp.dest('path/to/dest')
]);

tasks.on('error', function () {
    process.exit(1)
});
Share:
21,655
Roberto Bonvallet
Author by

Roberto Bonvallet

(Dλs)functional programmer. Personal website: Una mez.cl/a de cosas.

Updated on March 31, 2020

Comments

  • Roberto Bonvallet
    Roberto Bonvallet about 4 years

    I'm using Gulp in my small project in order to run tests and lint my code. When any of those tasks fail, Gulp always exits with return code 0. If I run jshint by hand, it exits with non-zero code as it should.

    Here's my very simple gulpfile.

    Do I need to somehow explicitly tell Gulp to return a meaningful value? Is this Gulp's fault, or maybe the gulp-jshint and gulp-jasmine plugins are to blame?

  • Roberto Bonvallet
    Roberto Bonvallet over 10 years
    Hi Shuhei, I tried returning the stream and it doesn't work either. Thanks for the link, I'll take a deeper look at it.
  • Shuhei Kagawa
    Shuhei Kagawa over 10 years
    Hi Roberto, you may need fail reporter to make your task fail.
  • Roberto Bonvallet
    Roberto Bonvallet about 10 years
    Hi robrich, thanks for the reference. While I understand that there may be some need for discussion on how to fail and how to report, I think returning nonzero is simply common Unix courtesy, so it should be the default behavior. I'll try your workaround.
  • Tiddo
    Tiddo over 9 years
    Why do you emit the exit event in the gulp error handler instead of just calling process.exit directly?
  • Colton McCormack
    Colton McCormack over 9 years
    Tiddo, the code above does not emit an exit event, but rather listens for one. Whenever an exit event is encountered, it queues up process.exit(exitCode) to run on the next tick.
  • Roberto Bonvallet
    Roberto Bonvallet about 9 years
    Thanks, this is what I was expecting to eventually happen.
  • Roberto Bonvallet
    Roberto Bonvallet about 9 years
    Do you know if there is a similar fix for Jasmine?
  • nicolas
    nicolas over 8 years
    that is so hilarious