# Run task only on gulp --production

**URL:** https://discourse.roots.io/t/run-task-only-on-gulp-production/4726
**Category:** sage
**Tags:** gulp
**Created:** 2015-09-10T15:07:50Z
**Posts:** 15

## Post 1 by @Twansparant — 2015-09-10T15:07:51Z

Hi there,

Following up on this [thread](https://discourse.roots.io/t/deploy-to-production-server-on-shared-hosting-with-gulp-with-ftp/4435/5), is it possible to run a gulp task only on `gulp --production`?  
Since I don’t have SSH access to my remote server, I have to upload my changed files with a gulp task using [vinyl-ftp](https://github.com/morris/vinyl-ftp):

```
// ### Vinyl FTP
gulp.task( 'upload', ['rmdirs'], function ( cb ) {
  var conn = ftp.create( ftppass );
  var globs = [
    '*',
    '*.php',
    'dist/**',
    'lang/**',
    'templates/*.php',
    'lib/*.php',
    '!.ftppass.json',
    '!.git',
    '!*.json',
    '!*.md',
    '!*.xml',
    '!assets',
    '!bower_components',
    '!gulpfile.js',
    '!node_modules',
    '!node_modules/**',
  ];
  // using base = '.' will transfer everything to /public_html correctly
  // turn off buffering in gulp.src for best performance
  return gulp.src( globs, { base: '.', buffer: false } )
    .pipe( conn.newer( '/public_html/web/app/themes/sage/' ) ) // only upload newer files
    .pipe( conn.dest( '/public_html/web/app/themes/sage/' ) );
});

// Remove directories
gulp.task( 'rmdirs', ['rmdirScripts', 'rmdirStyles'] );

// Remove dist/scripts directory
gulp.task( 'rmdirScripts', function ( cb ) {
  var conn = ftp.create( ftppass );
  conn.rmdir( '/public_html/web/app/themes/sage/dist/scripts', cb );
});

// Remove dist/styles directory
gulp.task( 'rmdirStyles', function ( cb ) {
  var conn = ftp.create( ftppass );
  conn.rmdir( '/public_html/web/app/themes/sage/dist/styles', cb );
});
```

Since it doesn’t automatically delete older minified production scripts and styles, I have to run a **gulp sequence** which will delete the **dist/scripts** and **dist/styles** directories first remotely before uploading the new ones.

This works perfect, however when running `gulp`, the `upload` task also runs which causes non-production files to get uploaded and deleting the production files in **dist/scripts** and **dist/styles**.

So to completely solve my problem, I have to run the upload task only with the `--production` flag.  
How do I achieve this?

Thanks!

---

## Post 2 by @austin — 2015-09-10T16:26:32Z

In your glob array you definitely want to be whitelisting files instead of blacklisting.

---

## Post 3 by @Twansparant — 2015-09-11T07:25:59Z

> [@austin](#):
>
> In your glob array you definitely want to be whitelisting files instead of blacklisting

Ok thanks, but how does that help me with this issue?  
I’m trying to comprehend what tasks I need to add in order to run only on `gulp --production`?  
Cheers!

---

## Post 4 by @Twansparant — 2015-09-11T09:59:57Z

I can’t grasp my head around how this works in Gulp…  
Right now, I added the following in my **gulpfile.js** :

```
// ## Globals    
var vinylftp = require('vinyl-ftp');
var ftppass = require('./.ftppass.json');
        
// Set production flag
var isProduction = false;
if (argv.production === true) {
  isProduction = true;
}
        
// ### FTP tasks
var ftpTasks = function() {
  return lazypipe()
    .pipe(function(cb) {
      var conn = vinylftp.create(ftppass);
      conn.rmdir( '/public_html/web/app/themes/sage/dist/scripts', function(err) {
        if (err) { console.log(err); }
      });
    })
    .pipe(function(cb) {
      var conn = vinylftp.create(ftppass);
      conn.rmdir( '/public_html/web/app/themes/sage/dist/styles', function(err) {
        if (err) { console.log(err); }
      });
    })
    .pipe(function() {
      var conn = vinylftp.create(ftppass);
      var globs = [
        '*',
        '*.php',
        'dist/**',
        'lang/**',
        'templates/*.php',
        'lib/*.php',
        '!.ftppass.json',
        '!.git',
        '!*.json',
        '!*.md',
        '!*.xml',
        '!assets',
        '!bower_components',
        '!dist/scripts/jquery.js',
        '!dist/scripts/jquery.js.map',
        '!dist/scripts/main.js',
        '!dist/scripts/main.js.map',
        '!dist/scripts/modernizr.js',
        '!dist/scripts/modernizr.js.map',
        '!dist/styles/editor-style.css',
        '!dist/styles/editor-style.css.map',
        '!dist/styles/main.css',
        '!dist/styles/main.css.map',
        '!gulpfile.js',
        '!node_modules',
        '!node_modules/**',
      ];
      // using base = '.' will transfer everything to /public_html correctly
      // turn off buffering in gulp.src for best performance
      return gulp.src( globs, { base: '.', buffer: false } )
        .pipe( conn.newer( '/public_html/web/app/themes/sage' ) ) // only upload newer files
        .pipe( conn.dest( '/public_html/web/app/themes/sage' ) ),
        function() {
          console.log(chalk.green('✔ All done!'));
        };
    })();
};
        
// ### Upload
gulp.task('upload', function() {
  console.log(isProduction);
  // gulp.src('.') // same error
  return gulp.src('.')
    .pipe( gulpif(isProduction, ftpTasks() ) );
});
        
// ### Build
gulp.task('build', function(callback) {
  runSequence('styles',
              'scripts',
              ['fonts', 'images', 'svg'],
              'upload',
              callback);
});
```

When I run `gulp` or `gulp --production` I’m getting these errors:

```
[11:55:38] Starting 'upload'...
true
[11:55:38] 'upload' errored after 11 ms
[11:55:38] TypeError: undefined is not a function
    at proxyStream (/pathto/site/web/app/themes/sage/node_modules/lazypipe/node_modules/stream-combiner/node_modules/duplexer/index.js:65:16)
    at Array.forEach (native)
    at forEach (/pathto/site/web/app/themes/sage/node_modules/lazypipe/node_modules/stream-combiner/node_modules/duplexer/index.js:11:20)
    at duplex (/pathto/site/web/app/themes/sage/node_modules/lazypipe/node_modules/stream-combiner/node_modules/duplexer/index.js:27:5)
    at module.exports (/pathto/site/web/app/themes/sage/node_modules/lazypipe/node_modules/stream-combiner/index.js:20:17)
    at build (/pathto/site/web/app/themes/sage/node_modules/lazypipe/index.js:26:20)
    at ftpTasks (/pathto/site/web/app/themes/sage/gulpfile.js:233:7)
    at Gulp.<anonymous> (/pathto/site/web/app/themes/sage/gulpfile.js:367:33)
    at module.exports (/pathto/site/web/app/themes/sage/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7)
    at Gulp.Orchestrator._runTask (/pathto/site/web/app/themes/sage/node_modules/gulp/node_modules/orchestrator/index.js:273:3)
```

Any idea what I’m doing wrong here?  
Thanks!

---

## Post 5 by @jakus — 2015-09-15T02:08:08Z

Hi Austin, appreciate the response… But could you please elaborate on this a bit?

---

## Post 6 by @Twansparant — 2015-09-16T08:49:21Z

Is there really no one who could help us with an example on how to add a **gulp task** with **gulp-if** condition for the **–production** flag?  
Can’t find any examples out there that work n this workflow…  
Any help is appreciated! Thanks

---

## Post 7 by @Twansparant — 2015-09-16T11:59:41Z

@jakus I finally worked it out!

First create a **.ftppass.json** file in your theme root with your FTP credentials:

```
{
  "host": "ftp.mydomain.com",
  "user": "username",
  "password": "password"
}
```

Then add these 2 globals at he top of your **gulpfile.js** :

```
var vinylftp = require('vinyl-ftp');
var ftppass = require('./.ftppass.json');
```

Then in your **upload** task, check if the `--production` flag is set and if so, run a sequence of tasks:

```
// ### Upload
gulp.task('upload', function(callback) {
  if (argv.production === true) {
    runSequence('rmdirdist', ['ftpupload'], callback);
  }  
});
```

First remove the remote **dist** folder with the **rmdirdist** task:

```
// ### Remove remote dist directory
gulp.task( 'rmdirdist', function (cb) {
  var conn = vinylftp.create( ftppass );
  conn.rmdir( '/public_html/web/app/themes/sage/dist', cb );
});
```

After that, upload only new files (including the freshly created dist directory) with the **ftpupload** task:

```
// ### Upload Vinyl FTP
gulp.task('ftpupload', function (callback) {
  var conn = vinylftp.create({
    host: ftppass.host,
    user: ftppass.user,
    password: ftppass.password,
    log: gutil.log
  });
  var globs = [
    '*',
    '*.php',
    'dist/**',
    'lang/**',
    'templates/*.php',
    'lib/*.php',
    '!*.json',
    '!*.md',
    '!*.xml',
    '!assets',
    '!bower_components',
    '!node_modules',
  ];
  // using base = '.' will transfer everything to /public_html correctly
  // turn off buffering in gulp.src for best performance
  return gulp.src( globs, { base: '.', buffer: false } )
    .pipe( conn.newer( '/public_html/web/app/themes/sage' ) ) // only upload newer files
    .pipe( conn.dest( '/public_html/web/app/themes/sage' ) );
});
```

Finally, add the **upload** task to the **build** sequence task:

```
// ### Build
gulp.task('build', function(callback) {
  runSequence('styles',
              'scripts',
              ['fonts', 'images', 'svg'],
              'upload',
              callback);
});
```

This should work now!  
Happy :smile:

---

## Post 8 by @jakus — 2015-09-17T05:19:01Z

Amazing man! Thank you very much…

I’ll give it a shot now.

---

## Post 9 by @jakus — 2015-09-17T05:23:48Z

Sorry just have a stupid noobish question - just to confirm do I run gulp upload?

Or can I just run gulp --production and this will run the upload/rmdist tasks automatically?

Thanks again mate.

---

## Post 10 by @austin — 2015-09-17T05:28:16Z

A little late to the party, but a couple comments:

## flag usage

I define flags [here](https://github.com/roots/sage/blob/2aafd22584795b9a7e17d9d548156e4a007d6cf8/gulpfile.js#L53-L65) that tell the rest of the gulpfile what should be enabled/disabled. [Here](https://github.com/roots/sage/blob/2aafd22584795b9a7e17d9d548156e4a007d6cf8/gulpfile.js#L114-L116) is an example of me using one of the flags. I suppose you could also do something like `if (enabled.rev) { /*whatever*/ }`. The way you are doing it is fine though, just wanted to elaborate on how I am parsing the flags.

## do not blacklist things

I cannot really think of a situation where you would want to create a blacklist for your globs. You should generally always be whitelisting stuff unless you have a good reason to blacklist.

```
var globs = [
    '*.php',
    'dist/**',
    'lang/**',
    'templates/*.php',
    'lib/*.php'
  ];
```

This way no secret stuff makes it’s way to the public web.

## How to conditionally run the upload task

The way you are doing it works I’m sure, but it has some limitations. You cannot run `gulp uploads` on it’s own without specifying `--production`. Here is how I would do it:

```
// ### Build
gulp.task('build', function(callback) {
  var tasks = [
    'styles',
    'scripts', ['fonts', 'images', 'svg']
  ];

  if (argv.production) {
    // only add upload to task list if `--production`
    tasks = tasks.concat(['upload']);
  }

  runSequence.apply(
    this,
    tasks.concat([callback])
  );
});
```

And then remove the `if (argv.production)` inside your uploads task. This way you can run the uploads task on it’s own with `gulp uploads` without specifying `--production`

```
// ### Upload
gulp.task('upload', function(callback) {
    runSequence('rmdirdist', 'ftpupload', callback);
});
```

---

## Post 11 by @jakus — 2015-09-17T05:50:53Z

Thanks Austin, this is awesome feedback and helps greatly…

---

## Post 12 by @Twansparant — 2015-09-17T08:03:17Z

Thanks for your reply Austin!

> [@austin](#):
>
> I define flags here that tell the rest of the gulpfile what should be enabled/disabled. Here is an example of me using one of the flags.

Yeah, that’s the first thing I tried, adding this to the enabled array:

```
// FTP Upload when `--production`
upload: argv.production
```

But then I get an error:

```
upload: argv.production
  ^^^^^^^^
SyntaxError: Unexpected identifier
```

I don’t understand exactly what the difference is between functions declared like this:

```
var upload = function() {}
```

and tasks or how you call such a function within a task?  
How exactly would that work in this case?

> [@austin](#):
>
> I cannot really think of a situation where you would want to create a blacklist for your globs. You should generally always be whitelisting stuff unless you have a good reason to blacklist.

Thanks, I tried that too actually, but all my **bower\_components** and **node\_modules** got uploaded too because this line was still in my globs : `'*'`  
I removed it, and it works now!

> [@austin](#):
>
> Here is how I would do it:

Great, much better indeed!  
Thanks for your help, glad I got this workflow working now!

---

## Post 13 by @austin — 2015-09-17T15:33:08Z

> [@Twansparant](#):
>
> But then I get an error:

This is a syntax error. Check your commas and stuff.

---

## Post 14 by @jakus — 2015-09-17T23:06:03Z

FYI: Austin’s steps/code are working fine for me… The tasks are not uploading any of the node\_modules or bower\_components and I can run the gulp upload task on its own…

Maybe follow Austin’s code Twansparant :smile:

---

## Post 15 by @Twansparant — 2015-09-18T07:42:30Z

it is working fine for me too @jakus, just not when defining the flag in the **CLI options**.  
Doesn’t matter anyway, because my problem is solved!
