Here’s some output from gg-grunt, running `gg-grunt lint:common.id`:
Here’s another screenshot of the same command, but showing an abort after a syntax error:
And finally, success!
gg-grunt also has an auto-update feature. First of all, if you don’t have the util-gg-grunt repo cloned (where all the actual code lives), but you do have the gg-grunt CLI (which lives in another repo, util-eng, which everyone at Gilt already has cloned and in their path), when you run gg-grunt, it will clone the util-gg-grunt repo, and then continue executing.
Also, when you run gg-grunt, and you’re on a tag (which you are by default), it will automatically check for a newer tag, and update if found:
If you’re offline, it won’t make this check:
If you’re on a branch or a tag, it won’t update either. This makes it easy for developers to contribute to gg-grunt itself—they just have to check out master (or a branch), make some changes, and then easily test their changes by running gg-grunt again. When their feature or bug fix is ready for release, all they have to do is create and push a new tag!
Internally we use Grunt, but with our own custom “reporter” (courtesy of Andrew Powell). You can see this reporter in action in all the screenshots above. Instead of dumping the raw output from each of the tasks (jsvalidate, jshint, coffee, etc., not to mention dozens of custom tasks) which don’t have a consistent look and feel, we use a module named “hooker” to “hook” console.*, grunt.log.*, stdout and stderr, and listen for any and all output from these tasks. We then pass the raw output through a set of pattern matchers and generate consistent output: