Grunt made easy for large and distributed projects


Grunt made easy for large projects. It's like One Ring to rule them all, but for Grunt

Disclaimer: Croak is still an initial version, but it's ready-to-use in relaxed environments

Grunt is an awesome task runner and build automation tool largely adopted for node.js

Croak is just a simple, but featured wrapper for Grunt that aims to help you to manage and orchestrate Grunt tasks configuration (aka Gruntfile) in large and distributed projects, helping you to avoid redundancy, saving time and reducing dramatically changes impact during the project life-cycle and development workflow

  • Allows you to centralize your Gruntfile in one place and use it from many places
  • Easily manages and orchestrates different configuration for multiple projects
  • Avoid redundant Grunt configuration over multiple repositories
  • Abstracts and provides more control for Grunt tasks configuration
  • Support to use and discover global node packages as Grunt configuration package
  • Extends or overwrites global Gruntfile from local configuration
  • Provides the same Grunt API and very similar CLI (things won’t change too much)
  • Customizes Grunt execution options from a config file (future .gruntrc)
  • You don’t need to have Grunt NPM task locally installed in order to run tasks

It is recommended that you install Croak as global package:

$ npm install croak -g

Then, create the configuration file:

$ croak init -g

The above command will create a .croakrc file in your user home directory, as global configuration.

Still confused? Please, take some minutes to read the detailed documentation below

Croak arises from the need to create a specific solution to abstract all the automation configuration stuff. It allows you to delegate responsibilities properly in your project to the developers, without losing the desired level of control and centralization.

Because a design principle, node.js (and consequently Grunt) packages and its dependencies are locally installed, and that is fantastic. However, this is not always the best choice for some scenarios. As you probably already know, dependencies globalization in node.js can be considered an anti-pattern, but globalization can be an ideal choice if you are in a big and distributed project.

When a project have a considerable number of repositories, by inertia you probably tend to use the local packages and configuration across each different repository, but these configurations are usually equal or very similar for each different repository.

The above project scenario is really hard to maintain when you need to apply changes massively in your project, like automation, building or deployment configuration changes that is completely usual during the project evolution

Croak is created to supply this need. It aims to provide a specific solution to easily centralize and orchestrate Grunt configuration, so that you can rapidly apply massive changes in your project.

Croak has basically two main goals:

  • Reduces the Grunt configuration changes impact during your project life-cycle
  • Gives configuration control and provides abstraction to developers, without hurting their feelings
  • When you have only one or two repositories in your project
  • When you have an ultra specific grunt config on each project repository
  • When you or your team don’t want to spend time updating/synchronizing build configuration
  • When you don’t need to centralize and (consequently) don’t need to take the control
  • When you have a lot of free time and you enjoy doing redundant and not very interesting tasks
  • When developers of your project... (at least one):
    • are ultra skilled and responsible guys
    • have a lot of time to maintain their own automation tasks configuration
    • need to take full control of the automation tasks configuration
  • When you want to centralize and take control of the project building and automation configuration
  • When you want to reduce the configuration change time and impact in your project
  • When your project have a considerable number of repositories (more than 3)
  • When your project configuration is equal or very similar in different repositories
  • When you want to keep clean each repository of Grunt tasks
  • When you do NOT want to spend time doing redundant and not very funny stuff
  • When you do not want to spend much time providing support to developers about configuration stuff
  • Or whatever is not on the 'When do I not need' list...

In a few words, Croak allows you to have a multiple Gruntfile in global locations and runs them using a simple project identifier (like a linker). It also allows you to define pre-configured options to pass to Grunt in a simple configuration file

Moreover, Croak allows you to extend or overwrite Gruntfile configurations, so you can provide a way to customize tasks configuration from local configuration (see the Croakfile section)

A representative scenario could be, for example, that your project has a relevant number of repositories. Each repository needs its automation configuration for development, testing or building stuff.

Usually, this configuration tends to grow when your repository has a certain amount of different tasks and it also tends to be very similar or redundant in different repositories in your project

For example you could need the same tasks in your project to run tests, generate documentation, statically analyze the code, generate a coverage report or measure the code complexibility

Continuous changes and improvements are a permanent feature in any software project, and Croak just helps with that

You can see a complete example project structure using Croak here

Abstraction is not always the best choice and some people can hate it. Basically, an abstraction in software development tries to reduce notably the complexity, underlines details and gives more control

With Croak you can provide an ideal level of abstraction to developers without losing control and, additionally, give them freedom if they want to customize or extend Grunt configuration allowing them to adapt it to their needs

If you want to make less impact to the developers, take a look to the Croak Grunt faker

Croak is an initial ready-to-use version, though it’s under active development process and important changes can be done in a near future version

Croak supports Grunt ~0.4.0

Croak uses disk files to store persistently the configuration. The Croak configuration file must be called .croakrc

Croak supports two types of configuration files

A global file can store your project configuration and this configuration will be used in each Croak execution

It will be located in the user home directories by default.

If you want to define a global cross-user shared configuration, you can define CROAKRC environment variable in order to specify a custom global file location, instead of the current user home directory

Local file can be located in any path, but it’s recommended that you create it in your project or repository root folder

Usually, a local file should have only one project configured. Any local configuration has priority and will overwrite global configuration (for example, if you configure the same project in both files)

Croak implements a similar file discovery algorithm like the one Grunt uses to discover the Gruntfile

$defaultstringundefinedProject to use by default when no project is defined. Useful to use in local configuration and avoiding to pass the --project flag via CLI
packagestringundefinedNode package which contains the Gruntfile. It will be resolved as local and global package. This is a recommended alternative to the gruntfile option
extendbooleanfalseEnable extend existing tasks from Croakfile
overwritebooleanfalseEnable overwrite existing tasks from Croakfile
register_tasksbooleanfalseEnable register/create new tasks from Croakfile

The following options will be (probably) available in Grunt in future versions, inside a file called .gruntrc, however, Croak already supports it

gruntfilestringundefinedPath to your Gruntfile. It can be a relative path. You should define this option in all of your projects. If you define the package option, Gruntfile path will be relative to the package root directory. By default, Croak tries to find it in the package root folder or inside the grunt directory. You only need to use this option with package if your Gruntfile exist in a custom directory
basestringundefinedSpecify an alternate base path. By default, all file paths are relative to the Gruntfile
no_colorbooleanfalseDisable colored output
debugbooleanfalseEnable debugging mode for tasks that support it
stackbooleanfalsePrint a stack trace when exiting with a warning or fatal error
forcebooleanfalseA way to force your way past warnings. Don’t use this option, fix your code
tasksstringundefinedAdditional directory paths to scan for task and "extra" files
npmstringundefinedNpm-installed grunt plugins to scan for task and "extra" files
no_writebooleanfalseDisable writing files (dry run)
verbosebooleanfalseVerbose mode. A lot more information output

You can use any of the config options also as a command line flag. See the Grunt CLI documentation

A multi-project .croakrc configuration file

$default = my-project
extend = true
gruntfile = ${HOME}/projects/super-project/build/
debug = true
stack = true
extend = true
overwrite = true
register_tasks = true
; resolve an node package in the system locally and globally installed 
; then Croak will try to discover the Gruntfile inside the package directory 
package = my-project-builder
; grunt-specific 
base = ${HOME}/projects/my-project/my-package/
no_color = false
no_write = false
debug = false
verbose = false
force = true
stack = true
tasks = ../custom-tasks/
npm = mytask

You can use any existing environment variables in config values, using the ${VARIABLE_NAME} notation

In order to use the same config values across diferent OS, Croak will transparently translate common environment variables to the specific running OS

For example, if your use ${HOME}, Croak will translate it into %USERPROFILE% under Windows and viceversa. The same case is applied for ${PWD}, ${TMPDIR}, %HOMEDRIVE%, translating this last one into / under Unix-like OS

Additionally, Croak introduces support for an easy way to use relative paths from Croak-specific files locations, like the .croakrc config file path

CROAKRC_PATHAbsolute path to the .croakrc local file. If it doesn’t exist, $PWD will be used instead

Croak will automatically expose the croak object in Gruntfile, so you can use this configuration like template values in your tasks config

This is really useful because, in much cases, you need to use absolute paths in your Gruntfiles

Croak grunt object

The following properties will be available as Croak task in Grunt. You can use it as Grunt templating in tasks configuration. If you don't use the base option, you should use one of the following options to configure your tasks in order to use absolute paths

cwdAbsolute path to the current user working directory from where Croak was called
rootAbsolute path to the existing Croakfile or .croakrc directory. If both files don’t exists, cwd will be used instead
configAbsolute path to the local .croakrc file directory. If it doesn’t exist, it will be null
baseConfigured base path. If the base options doesn’t exist, cwd will be used
gruntfileAbsolute path to the current used Gruntfile
croakfileAbsolute path to the current used Croakfile, if it exists
versionCurrent Croak version
npmGrunt npm load packages
tasksGrunt tasks load path
optionsCroak current config options object

The above properties will be also available from grunt.croak object

Example Gruntfile

module.exports = function (grunt) {
  if (grunt.croak) {
    grunt.log.writeln('Running Grunt from Croak (v.' + grunt.croak.version + ')');
    clean: {
      options: {
        force: true
      views: '<%= croak.cwd %>/tmpl/'
      tmp: '<%= croak.root %>/.tmp/'
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      all: [
        '<%= croak.base %>/src/scripts/{,*/}*.js'
        '<%= croak.config %>/demo/{,*/}*.js'
        '!<%= croak.root %>/src/scripts/vendor/*.js'
    connect: {
      server: {
        options: {
          port: 9001,
          base: '<%= croak.root %>'

The Croak Grunt task is still in progress