Pass Sensitive Information to Grunt Using Command Line Options

September 22nd 2015 Grunt

Before I finally settled with using Web Deploy for deploying my site to Azure, I was also considering using FTP directly from Grunt. I quickly chose grunt-ftp-push as the most promising package for this purpose. A greater challenge was finding a way to keep my FTP credentials out of my gruntfile and source control.

Although Grunt used to have issues with correctly parsing command line options, they are now all fixed. Using grunt.option, the values can easily be read from within the gruntfile:

grunt.option 'ftpUsername'

It's not that easy to use them inside grunt.initConfig method, because it gets evaluated before the task runs and hence before the command line options can be read. The following naive attempt will leave the parameterized values uninitialized even if they are passed from the command line:

grunt.initConfig(
  {
    ftp_push:
      docpad:
        options:
          host: grunt.option 'ftpHost'
          dest: grunt.option 'ftpDest'
          username: grunt.option 'ftpUsername'
          password: grunt.option 'ftpPassword'
        files: [
          {
            expand: true
            cwd: 'out'
            src: '**/*'
          }
        ]
  }

To achieve the desired result another level of indirection will need to be used: grunt.config to change parts of configuration when the task is run. To avoid overriding the complete ftp_push configuration value using grunt.config, we can store the command line options in a temporary options value:

grunt.config.set 'options', {
  ftpHost: grunt.option 'ftpHost'
  ftpDest: grunt.option 'ftpDest'
  ftpUsername: grunt.option 'ftpUsername'
  ftpPassword: grunt.option 'ftpPassword'
}

To use these values inside ftp_push, grunt templates can be used:

ftp_push:
  docpad:
    options:
      host: '<%= options.ftpHost %>'
      dest: '<%= options.ftpDest %>'
      username: '<%= options.ftpUsername %>'
      password: '<%= options.ftpPassword %>'
    files: [
      {
        expand: true
        cwd: 'out'
        src: '**/*'
      }
    ]

The <%= options.ftpHost %> values are templates which get evaluated only when they are retrieved, therefore they will already be initialized because the grunt.config.set will already have happened by then.

With all this in place the values can finally be passed as command line options:

grunt deploy --ftpHost=hostname --ftpDest=/wwwroot/ --ftpUsername=myUsername -ftpPassword=myPassword

Of course deploy task needs to be registered in gruntfile beforehand:

grunt.registerTask('deploy', ['ftp_push'])
Copyright
Creative Commons License