2

I'm running a number of grunt tasks on a project. One of which sets a number of grunt.options grunt.option(key, value) which I need to access in a subsequent task var option = grunt.option(key). These options are returning undefined when I try to access them in the latter task.

If I log the variable at the head of the latter task, it is shown before that task is run and I am unable to access the previously set value in the tasks config.

Is there something I need to do between setting the grunt.option and using it in another task to notify grunt of the change? Am I doing something inherently wrong here? Or is there a better way to do this with a global variable of sorts (my research pointed me to using grunt.option)

My Gruntfile.js

grunt.log.writeln('loading tasks');
grunt.loadTasks('grunttasks');
grunt.log.writeln('tasks loaded');

grunt.registerTask(
    'jenkins',[
        'clean', //clears out any existing build folders
        'curl', //gets build config file from remote server
        'set-env', //sets the grunt.options based on the build config file
        'string-replace:config', //attempts to access the new grunt.options
        ....
        ....
        ....
        ....
    ]
);

In my set-env task, I set some environment variables based on the contents of a text file returned in the curl task. This works fine and I can log all the grunt.options immediately after setting them so I know they are being set correctly.

set-env-task

module.exports = function(grunt) {

    grunt.registerTask('set-env', 'set-env', function() {
        ......
        ......
        for (var i = 0; i < propFile.length; i++) {
            if (propFile[i] !== '') {
                ......
                ......
                keyValues[propName] = propValue;
                grunt.option(propName, propValue);
                console.log("FROM GRUNT.OPTION " + grunt.option(propName));
                ......
                ......
            }
        }
        ......
        ......
    });

};

When I try and access the grunt.options set in the above task from my string-replace (or any other subsequent) task undefined is returned. If I set test values to these grunt.options at the start of my Gruntfile.js I can access them with no issue:

module.exports = function(grunt) {
    grunt.config('string-replace', {
        ..........
        ..........
        config:{
            files: configFiles,
            options: {
                replacements: [
                    ..........
                    ..........
                    {
                        pattern: /var _OPTION_KEY = \"(.*?)\"\;/ig,
                        replacement: 'var _OPTION_KEY = "'+grunt.option('_OPTION_KEY')+'";' //grunt.option('_OPTION_KEY') here is undefined
                    }
                    ..........
                    ..........
                ]
            }
        }
        ..........
        ..........
    });
    grunt.loadNpmTasks('grunt-string-replace');
}

(I have double, triple and quadruple checked that I'm using the correct option keys)

Fraser
  • 14,036
  • 22
  • 73
  • 118

1 Answers1

1

The problem is that you're accessing the variables from the grunt option set during the "config stage" of the task, which runs one time, before you set the options in your set-env task. Evaluating the custom option key at that point in the code indeed should yield undefined. (Note that this is practically the equivalent of using the initConfig block)

What you an do instead is instead of reading the option values from the options object, modify the config object of the task directly, using grunt.config.set, which would enable you to do what you've been trying.

So basically, instead of

grunt.option(propName, propValue);

use something like

grunt.config.set('mytask.replacements', options.replacements);

(Of course, this will require a sizable reworking of your code, I don't get into that.)


edit: probably there's an even cleaner solution using the templating functionality of grunt, see this stackoverflow answer, and the grunt api docs on templating:

Template strings can be processed manually using the provided template functions. In addition, the config.get method (used by many tasks) automatically expands <% %> style template strings specified as config data inside the Gruntfile.

The point being that these are evaluated not when the config block is parsed, but only when the task reads the values using config.get.


Your pattern of using the options object to share values between tasks works better if it's between two custom tasks of yours - you can set it in one task, read it in the other, not in the configuration, but as an actual step of running the tasks.

In general, although it seems doable, I'd say this is not the workflow grunt has in mind - if you know which environment you're running grunt in, it's easier to pass in the environment parameters through the options command-line flag directly when you run a grunt task, which would already take effect in any task configuration you're doing.

Community
  • 1
  • 1
doldt
  • 4,466
  • 3
  • 21
  • 36