Never break master by accident

Run unit tests on every commit using git hook.

Run sanity check before committing

Developers are good people, striving to do the best job possible. We write good clean modules, well designed and thoroughly tested. When we work on the code locally, we try to commit early and often.

Sometimes the real life intrudes at the very last second. A small change at the last second, maybe very innocuous (an update to README or some json config) before the push or merge to master.

The code goes to the main repository, and suddenly an email arrives: your push broke the continuous build on the server. You spend a couple of minutes looking through the logs, just to discover style errors that break the build. You run the local build and they pop up. You forgot to run the full build after the tiny change.

Without any statistics to back this up, I would say 25% of the broken builds I cause are jshint related. They loom large in my mind, because as opposed real problems, they should be easy to spot locally. It is just very hard to always rerun the build even if you do not remember touching any JavaScript.

Check NPM modules on pre-commit

I am using pre-commit in my projects, which installs a small hook file .git/hooks/pre-commit. It is just a JavaScript file that executes npm tasks one by one:

1
2
3
4
5
var npm = child.spawn('npm', ['run', task], {
cwd: root, // Make sure that we spawn it in the root of repo.
env: process.env, // Give them the same ENV variables.
stdio: [0, 1, 2] // Pipe all the things.
});

This hook is executed by default every time you try to run git commit. You can disable the pre-commit hook using git commit -n.

Define what to check on pre-commit

By default, the pre-commit executes npm test command. You can define what to run inside the package.json by first defining the commands inside the scripts object, then adding them to the pre-commit list:

package.json
1
2
3
4
5
6
7
8
9
"scripts": {
"test": "grunt",
"deps-ok": "grunt deps-ok",
"jshint": "grunt jshint"
},
"pre-commit": [
"deps-ok",
"jshint"
]

Selecting the things to check

As often, there are trade-offs: more things to check cause a delay before pushing. Running grunt on every commit might be a time-waisting overkill. I suggest looking back at the things that break most often for your project and just checking those things: jshint is the task I check. One can easily see how long each grunt task takes by including time-grunt in your Gruntfile.js.