December 11, 2018
Using git hooks to keep your codebase clean
Problem
Let’s be honest – developers tend to be lazy. Whenever you start a new project you’re probably saying to yourself that you want to do everything better this time but often times your new project becomes the same mess as your previous one. I want to introduce a neat little trick that might help your codebase to stay clean from the beginning. We’re only taking a look at how you can force all of your developers to use the same codestyle across your new angular project that was created using the angular-cli.
tl;dr;
install husky
1 |
npm i husky --save-dev |
trigger the linter whenever the git postcommit hook is called
1 2 3 4 |
"scripts": { "lint": "ng lint", "precommit": "npm run lint" } |
Now you’re not able to commit when your code contains linting errors.
Goal
In bigger projects with a team size larger than 2-3 people you will typically encounter situations where developers have different opinions about how the applications code should look like. This is why linters became popular and are almost a standard in web application development. The angular-cli comes with a bundled linter that you can configure through the auto-generated tslint.json.
I discovered that even though there are global linting rules people tend to forget about them until the build server tries to build the application, fails and sends you an email about the failure. I stumbled across the husky package and figured it might solve the issues we had. In the following setup I’ll show you how exactly you can integrate this workflow into you project.
Setup
install the npm package husky. This package allows you to trigger scripts in your package.json whenever git hooks are executed.
1 |
npm i husky --save-dev |
add the following to the scripts section of your package.json
1 2 3 4 |
"scripts": { "lint": "ng lint", "precommit": "npm run lint" } |
now whenever you’re performing a git commit either through the commandline or via your IDE the precommit hook will trigger and execute whatever script you defined. In our case we want to tell our linter to lint the whole codebase and search for violations of our linting rules. Since we’re dealing with an angular application that is set up using the angular-cli the command we want to run is ng lint.
Whenever your code contains a linting error the ng lint command will finish with a non zero exit code and will therefore fail the git commit command and present an error message to you.
Advanced Setup
If linting the codebase is not enough for you, you’ll might want to add a prepush hook that executes unit tests and only allows the developer to push the changes if all the unit tests execute just fine. This of course requires the tests to run fast (hint: jest could you with that).
1 2 3 4 5 6 |
"scripts": { "test": "ng test", "lint": "ng lint", "precommit": "npm run lint", "prepush": "npm run test" } |
To avoid the package.json to get bloated with tons of entries husky lets you use a separate config file. You can copy-paste all the hooks you defined in the script section of your package.json into a new file called .huskyrc
1 2 3 4 5 6 |
// .huskyrc { "hooks": { "precommit": "npm test" } } |
There might be situations where you don’t want to run those hooks. You can easily bypass them using the –no-verify flag when using git commit from the commandline or ticking the designated checkbox in your IDE (IntelliJ in my case) to do that.