DEV Community

Eduardo Henrique Gris
Eduardo Henrique Gris

Posted on

Husky and lint-staged for pre-commit in React

Introduction

Who hasn't faced the problem of forgetting to run tests or adjust the code formatting before pushing it, encountering a pipeline failure that validates them? Or having to manually execute routines to follow project standard definition?

The idea of this article is to introduce two libraries that, when used together, allow configuring actions in the pre-commit stage, blocking a commit with failed tests, formatting the code before committing, or performing any other defined action.

Libs

  • husky: It's the library that will allow running pre-commit actions.
  • lint-staged: It's the library that will define the actions to be executed for files that are staged in git.

Libs setup

1- Husky

To add Husky to the application, it's necessary to run the following command:

yarn add --dev husky

To start the configuration, I suggest executing the following command:

npx husky init

It will generate a pre-commit file inside the .husky folder, which will define the execution of pre-commit actions. It will have the following content:



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

npm test


Enter fullscreen mode Exit fullscreen mode

Initially, by default, it's configured to run npm test, but with the addition of lint-staged, we'll update this file.

Also, a script to install Husky will be generated inside package.json.



"scripts": {
  (...)
  "prepare": "husky install"
},


Enter fullscreen mode Exit fullscreen mode

2 - lint-staged

To add lint-staged, it's necessary to run the following command:

yarn add --dev lint-staged

To configure the actions that will be executed pre-commit, add to package.json:



"lint-staged": {
  "*.js": [
  ]
}


Enter fullscreen mode Exit fullscreen mode

*.js is the type of files added in stage where pre-commit actions will be executed (I used this type as an example, but it depends on the type defined in your application). Inside "[ ]" is where the actions to be executed in the pre-commit stage will be placed.

Finally, for the lint-staged usage from Husky, it will be necessary to update the pre-commit file, resulting in the following:



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

npx --no-install lint-staged


Enter fullscreen mode Exit fullscreen mode

To start running Husky to perform pre-commit actions, it's necessary to install it by running: yarn prepare.

Execution example

Now I will present an example of execution with two objectives: formatting the code before committing and validating if the tests are passing to allow the commit to be made.

For this example, it will be considered an app with a component inside App.js and a test file App.test.js, both inside the src folder. App that uses the Jest library to perform tests and prettier for code formatting.

In the package.json, it's presented the following scripts:



"scripts": {
  "test": "jest",
  "format": "prettier --write \"**/src/*.js\"",
  "prepare": "husky install"
  }


Enter fullscreen mode Exit fullscreen mode

The test is responsible for running the tests, and format for formatting the code.

To define what will be executed on pre-commit, define the commands to be executed inside lint-staged in package.json:



"lint-staged": {
  "src/*.js": [
    "yarn format",
    "yarn test --findRelatedTests --bail"
  ]
}


Enter fullscreen mode Exit fullscreen mode

This way, it's defined that for the files staged in git, execute yarn format and yarn test --findRelatedTests --bail pre-commit.

The --findRelatedTests allows that when the App.js component is modified, it runs the associated tests (those presents in App.test.js), and the --bail cancels the commit if any test fails. Those comands are for tests executed with Jest, depending of test lib can be other commands to not allow the commit.

Finally, to test the libraries, it's possible to change the App.js component, stage it with git add, and then commit. Before the commit is made, the actions defined inside lint-staged will be executed. In this example, the modified file will be formatted, and the associated tests will run. If any test fails, the commit will not be completed. If the tests pass, the commit will be completed.

Execution in the terminal:

Image description

In case you want to generate a commit without pre-commit actions, simply add --no-verify at the end of the git commit command, and Husky will not be executed.

Conclusion

Finally, the idea of this article is to introduce two libraries that, together, enable performing pre-commit actions to prevent pipeline failures or allow running processes that are commonly used in the app, for files staged in git. This aims to streamline the development process.

Top comments (2)

Collapse
 
messenja_2w34sdff profile image
messenja

why do we need prepare script, if husky will be installed on npm i command as dev dependency?

Collapse
 
griseduardo profile image
Eduardo Henrique Gris

Hello, thanks for the comment.
To enable git hooks (pre-commit is one type) in the project, it is needed to run husky install. This is necessary to execute husky.
For the first configuration (adding husky to the project), using npx husky init already install it. But other people that clones the project will need to execute the husky install to enable git hooks.
Defining this command in prepare script, when another person clones the project and run npm i, automatically will run the prepare script and allows the person to use husky, without the need to execute husky install manually