How To Set up Lefthook to handle git hooks in react applications
Tags: react, unittest, githooks, javascript
Published: 2024-06-29 03:55:54

## First of all, why Lefthook?

I will point some reasons to you choose lefthook when you need to decide a git hooks manager.
<br/>

### 1. Configuration

Lefthook is very straightforward and has a smooth setup, that can be worthy if you want to test if it's what you are looking for. We need a yaml file only, with a bunch of possibilities like docker support, flexible list of files and glob/regexp filters.

### 2. Velocity

As Lefhook is written in go, and we can run commands in parallel, that grant for us a faster execution, not being possible in some others git hooks managers.

### 3. Environment agnostic

Lefthook is a go binary with wrappers to other languages. So, it gives you the possibility to share your config with teams using different programming languages, from front end to back end for instance.

I hope that you are already convinced. If are not, take a look how simple is the setup.
<br/>

## Setup<br/><br/>


### **Installation**

```md
npm install lefthook --save-dev
```

Once installed, a new file named lefthook.yml will be on your project root. You can now add the needed configuration to git hooks.<br/><br/>

### Editing config file (lefthook.yml)

Git has a bunch of hooks that you can handle with the lefthook. Here we have a [list with all](https://git-scm.com/docs/githooks), so feel free to get exactly what you want. This article will handle the `pre-commit` and `pre-push` ones, presenting a real example.
<br/><br/>

#### **Pre-commit**<br/>

In the lefthook.yml, we can add the git hook name, followed by the commands that will run:

```yaml
pre-commit:
  parallel: true
  commands:
    eslint:
      stage_fixed: true
      glob: "*.{ts,tsx}"
      run: yarn lint --fix {staged_files} --quiet # See "yarn lint" as eslint --ext ts,tsx
    test:
      run: vitest related {staged_files} --run --silent
```
<br/>

##### **Step by step**

- **Parallel**

This property will do all commands run in parallel (really?), saving time, mainly in big projects. This is great as in CI/CD as local.

- **Commands**

Here we can name all commands needed for the hook. In the example we have the eslint to ensure the code consistency, and test to ensure quality over the app.

- **Inside eslint**
  - **stage_fixed:** This is related to run git add after fix the files when the command has finished.
  - **glob:** Filter the files that will be on {staged\_files} using the extension in this case.
  - **run:** The command.
  - {staged\_files}: All files being modified at the moment (in the staging area). Note that even the command running with selected extensions (`--ext` flag), we still need the glob pattern because we are setting the files directly with staged\_files. Eslint command will ignore the flag in this case.
- **Inside test command**

We have added the run property only, and we already know what it is, but I want to mention the `related` flag from vitest. This allow us to run all tests that import a file (in this case a list of).

e.g.


```js

// checkout.test.ts
import {Checkout} from ../Checkout

describe('Checkout', () => ...)

```

In this case, if we change the `Checkout` component, it will be on our {staged\_files} list, and even not changing tests, vitest will look for all tests importing the component and will run each one, like the `checkout.test.js` .

> see docs: [vitest related](https://vitest.dev/guide/cli.html#vitest-related)



<br/><br/>


#### **Pre-push**<br/>

```yaml
pre-push:
  parallel: true
  commands:
    lint:
      run: yarn lint . --quiet
    test:
      run: vitest --run --silent
```

Well, nothing new here. We are now running all tests before push, and also running the eslint in all files. It is useful for companies that cannot pay for infrastructure to run tests on CI/CD, but still want to have some quality assurance.

> It's important notice that if you have something in your staging area that makes the test pass before the push, the tests will run without errors even if the code being pushed is with an error.

<br/><br/>

### Registering hooks


<br/>


After the config file is done, we can run:

```md
lefthook install
```

It  will do the hooks be registered and run when it's time. Remember to run it whenever you change the lefhook.yml file, or change something related the commands, for instance remove a command from package json that is being used by your hooks.

After this, it's time to commit and forget it (at least until need to change again).

<br/><br/>

#### References

- [Lefthook docs](https://github.com/evilmartians/lefthook)