Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute shell script in gruntfile and assign result to variable

I am using grunt to manage a suite of mocha-run tests. One of the things required in the mocha test suite is that certain environment variables be set so that the tests are executed properly based on the environment of the developer running the tests. One of these environment variables will have a different value on every developer's machine, so we execute a bash script to return that value for the environment variable we are setting.

I am using grunt.util.spawn to run the script and assign its result to a variable defined in my gruntfile, and then grunt-env to set the environment variable with that value. Below is an example of my gruntfile (in coffeescript):

module.exports = (grunt) ->
  envvar = ''

  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    env:
      dev:
        ENV_VAR: envvar

    simplemocha:
      options:
        timeout: 30000
        reporter: 'spec'
        compilers: 'coffee:coffee-script'
      all:
        src: ['Tests/**/*.coffee']

  grunt.registerTask 'init', ->
    done = this.async
    command =
      cmd: './bin/get_envvar.sh'
    grunt.util.spawn command, (error, result, code) ->
      envvar = result
      console.log 'envvar: ' + envvar
      done

  grunt.registerTask 'test', ['init', 'env', 'simplemocha']

To execute this, I call...

/path/to/grunt test

Unfortunately, although init runs, the callback therein doesn't seem to get executed, so envvar never gets set. Oddly, if I disable logging in my tests, the callback DOES get called, but only after my env and simplemocha tasks have been kicked off. My understanding of grunt tasks is that they are blocking, so I would expect the init task to have to completed (even with the async function therein) before moving on to the next task.

Any ideas?

like image 213
Clandestine Avatar asked Aug 21 '13 22:08

Clandestine


1 Answers

Although I'm still unclear on why the method above is not working, and welcome any feedback, after a bit of research, I found shelljs, which I was able to use to solve my problem. Since shelljs can exec shell commands synchronously, I don't have to work with callbacks when I really want things to block:

module.exports = (grunt) ->
  shell = require 'shelljs'
  envvar = shell.exec('./bin/get_envvar.sh', {'silent':true}).output

  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')

    env:
      dev:
        ENV_VAR: envvar

    simplemocha:
      options:
        timeout: 30000
        reporter: 'spec'
        compilers: 'coffee:coffee-script'
      all:
        src: ['Tests/**/*.coffee']

  grunt.registerTask 'test', ['env', 'simplemocha']

A lot cleaner, too!

References:

  • How can I perform an asynchronous operation before grunt.initConfig()?
  • http://jaketrent.com/post/impressions-of-grunt/
like image 172
Clandestine Avatar answered Nov 19 '22 01:11

Clandestine