An Idiosyncratic Blog

🐢 Automate linting with Husky

Published on
β€’ 4 minutes read

ESLint and Prettier are used to enforce a consistent style and follow code standards across JavaScript projects. It can be automated with the help of VSCode extensions (and WebStorm config), when saving a file.

The problem I observed was not everyone on my team had ESLint and Prettier extensions installed. Some of them were working with a barebones installation of VSCode. This caused some friction when things were commited and pushed upstream because the PR review comments had "Fix lint here", which in 2021 should not be something we should be spending our time on.

Another problem was with enforcing the conventional commit format.

Enter Husky. You can use it to lint your commit messages, run tests, lint code, etc... when you commit or push. Husky supports all Git hooks.

Perfect! Let's get started

Installing

First step is to install husky to the project:

npm install husky --save-dev

Next to enable Git Hooks,

npx husky install

This creates a .husky/_/husky.sh file in the project. .husky/_/husky.sh file is always git ignored

If someone is cloning the repo for the first time, we can use the prepare script to install husky automatically

npm set-script prepare "husky install"

This would update the package.json file to:

// package.json
{
  "scripts": {
    "prepare": "husky install"
  }
}

Now anytime someone does a npm install, prepare script will take care of calling install from Husky, creating the husky.sh file on local machine.

Configure Hook

Now we can configure pre-commit and commit-msg hooks

npx husky add .husky/pre-commit "npm command"
git add .husky/pre-commit

This will run npm command when we make a commit and will either pass or fail depending on your use-case.

Linting Staged Files

For my use-case, I want the pre-commit hook to lint staged files. lint-staged is the package I chose to do that work for me.

First I updated package.json and included lint-staged config.

// package.json
"lint-staged": {
    "*.{js,jsx}": [
      "eslint --cache --fix"
    ],
    "*.{json,scss}": [
      "prettier --write ."
    ]
  }

Then in .husky/pre-commit

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

And that's it. Now whenever we make a commit, lint-staged will run both eslint and prettier and fix all fixable problems. No more lint comments in PR reviews.

Follow the conventional commit format.

Why Use Conventional Commits?

  • Automatically generating CHANGELOG.
  • Automatically determining a semantic version bump (based on the types of commits landed).
  • Communicating the nature of changes to teammates, the public, and other stakeholders.
  • Triggering build and publish processes.
  • Making it easier for people to contribute to your projects, by allowing them to explore a more structured commit history.

commitlint checks if commit messages meet the conventional commit format.

First install the required packages:

# Install commitlint cli and conventional config
npm install --save-dev @commitlint/{config-conventional,cli}

Next configure commitlint.config.js file to extend from conventional config.

module.exports = { extends: ['@commitlint/config-conventional'] }

Then in .husky/commit-msg

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit "$1"

You can test the hook by simply committing. You should see something like this if everything works.

git commit -m "foo: this will fail"
husky > commit-msg (node v10.1.0)
No staged files match any of provided globs.
β§—   input: foo: this will fail
βœ–   type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]

βœ–   found 1 problems, 0 warnings
β“˜   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky > commit-msg hook failed (add --no-verify to bypass)

Fin

And that's it. Whenever there is a commit, the hooks run and makes sure everything is upto the project guidelines.

Pro-tip: Add a Contributing Guidelines section in your project README.md so that people who plan on contributing aren't thrown off as to why their commits aren't working.

Husky is a great tool to run scripts leveraging Git hooks. And it's not just limited to lint-staged and commitlint, since it is just a bash script, you can run anything from generating automated changelogs to running tests on each commit.

If you want to configure ESLint and Prettier, check out this post where I outline the installation steps, extensions required and the plugins I use on my projects.