3

I want to define a tree of shell commands in my Gruntfile.js, using grunt-exec to write shell commands.

I can do this for a single command, but I can't figure out the syntax for writing multiple sets of commands, and being able to call them one-by-one, or in groups.

Could someone please provide a fully fleshed out example Gruntfile.js with the following task structure?

test: `npm test`
lint:
  jshint: `jshint .`
  csslint: `csslint .`

I'm coming from the world of make, so I really want to shove this workflow into my Node.js projects, damn the Node community conventions.

I want grunt to default to npm test

I want grunt lint to perform both jshint . and csslint .

I want grunt jshint to perform only jshint .

mcandre
  • 22,868
  • 20
  • 88
  • 147

2 Answers2

6

A grunt multi-task supports multiple targets, but they can't be nested. But you can register tasks that run other tasks.

Gruntfile.js:

module.exports = function(grunt) {
  grunt.initConfig({
        exec: {
            test: "npm test",
            jshint: "jshint .",
            csslint: "csslint ."
        }
  });

  grunt.loadNpmTasks("grunt-exec");

  grunt.registerTask("default", ["exec:test"]);
  grunt.registerTask("test", ["exec:test"]);
  grunt.registerTask("lint", ["exec:jshint", "exec:csslint"]);
};

Note that there are already a lot of grunt tasks available, like grunt-contrib-jshint, which make things much simpler.

mcandre
  • 22,868
  • 20
  • 88
  • 147
jgillich
  • 71,459
  • 6
  • 57
  • 85
  • The trick is to list each subtask out (grunt/grunt-exec does not seem to allow writing them nested). Then register them back into a hierarchy. – mcandre Jul 30 '14 at 14:30
1

Grunt lets you register tasks by name, and tasks of tasks. Easily done via arrays of string literal task names, e.g.:

grunt.registerTask('default', ['test']);
grunt.registerTask('lint', ['jshint', 'csslint']);

jshint should already be registered if you've defined it as jshint inside your grunt.initConfig. Keep in mind that, unusual for a node program, everything is highly synchronous. The tasks will run in the order you give them.

edit: in case you need it later, you can also registerTask a function instead of an array of task names. This is how you could go about writing a task that does async work, or if you have very strict ordering requirements that may use control flow logic. Try to stick with just registering based on task name if you can.

Josh from Qaribou
  • 6,776
  • 2
  • 23
  • 21