coblr
coblr

Reputation: 3038

Why is this gulp task not being run consecutively?

I have three gulp tasks: watch, build, test. I'd like to have my watch running and when a file is saved, it is built and then tested (duh).

What is happening is that despite being set up to run build as a dependency of test, I need to save the file twice in order for the latest build to be the one that is tested.

I can reproduce this by starting the watch, making a change to somewhere in the client JS code (like adding a console log) and then watching the resulting output. The first save will not have any console output. Just saving the file again (no changes made) will cause the test to be re-run and the console output to display.

I have also noticed cases where the first build+test cycle will be the correct build (i.e. will have the console log statement), but after that, it takes two saves to make sure the latest code is the one being tested.

Spec files are immune to this because they are not built and instead used directly (sorta, they're transpiled first).

So, am I going crazy here? These should be run consecutively, right?

The log would suggest that's the case:

[12:05:54] Starting 'build:client:js'...
[12:05:54] Finished 'build:client:js' after 13 ms
[12:05:54] Starting 'test:client'...
19 09 2016 12:05:54.808:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
19 09 2016 12:05:54.808:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
19 09 2016 12:05:54.841:INFO [launcher]: Starting browser PhantomJS
19 09 2016 12:05:55.381:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#Zklau3qmk75NKg2HAAAB with id 61545463
LOG: 'test'
.
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 SUCCESS (0.002 secs / 0.029 secs)
[12:05:55] Finished 'test:client' after 775 ms

Build:

Basic build for AngularJS App, nothing too strange here.

gulp.task('build:client:js', () => {
    gulp.src('app/sections/client/**/!(*.spec|*.e2e).js')
        .pipe(sourceMaps.init())
            .pipe(eslint())
            .pipe(eslint.formatEach())
            .pipe(babel({presets: ['es2015']}))
            .pipe(ngAnnotate())
            .pipe(concat('client.js'))
            .pipe(uglify())
        .pipe(sourceMaps.write())
        .pipe(gulp.dest(paths.build))
});

Test:

This is set up so that, ideally, build runs and completes first.

gulp.task('test:client', ['build:client:js'], (done) => {
    const src = {};
    src['client'] = 'app/sections/client';

    const config = getTestConfig(src);
    new karmaServer(config, done).start();
});

Watch:

This should only need to run test because build is a dependency of test.

gulp.task('watch:client:js', () => {
    gulp.watch('app/sections/client/**/*.js', ['test:client']);
});

Also, to be totally transparent, most of my watch>build>test gulp tasks are being generated dynamically based off a paths file. It basically returns JSON that is then used by functions to create the gulp tasks. The output below is the result of that generation, but I'm not sure that physically writing each task out like this would make any difference.

You can experiment with or see more here.

Upvotes: 0

Views: 52

Answers (1)

kombucha
kombucha

Reputation: 1424

In the task 'build:client:js', you should return the stream so that gulp knows when the task actually ends.

gulp.task('build:client:js', () => {
    return gulp.src('app/sections/client/**/!(*.spec|*.e2e).js')
        .pipe(sourceMaps.init())
            .pipe(eslint())
            .pipe(eslint.formatEach())
            .pipe(babel({presets: ['es2015']}))
            .pipe(ngAnnotate())
            .pipe(concat('client.js'))
            .pipe(uglify())
        .pipe(sourceMaps.write())
        .pipe(gulp.dest(paths.build))
});

Upvotes: 1

Related Questions