Automating Code Checks and Tests with Git Hooks

Author

Engineering Manager leading the Frontend Development Team. Passionate about Tech and Dubstep Dance, Musicophile.

Automating Code Checks and Tests with Git Hooks

June 10, 2021

gitdev-tools

Automating Code Checks and Tests with Git Hooks

Motivation:

The most common way to add checks to your codebase is to use husky and lint-staged. I have used husky many times to add git hooks to the code base it’s one of the easiest ways to integrate any hooks. Recently I wanted to introduce a pre-commit hook to one of our projects. And my go-to approach was to integrate Husky and lint-staged. When I tried to integrate my project, The pre-commit hooks were not working as expected. After some digging, I realised that the newer version of Husky has some changes in the integration process. Husky(> V5) make use of Git’s(V 2.9) core.hooksPath feature. Basically, it lets you tell Git to not use .git/hooks/ but any other directory. This made me think if there is a way to do this natively?

Dive into the example code here

Native solution:

Git Hooks are the scripts you can place in a hooks directory to trigger any actions at certain points in Git’s execution process. These scripts can be invoked at any given points like pre-commit, post-commit, pre-push, pre-rebase etc, You can find all the available hooks here.

By default, the hooks directory is at .git/hooks/. If you open any of your project which is initialised by git, You can check all the sample hooks.

All the git hooks

Implementation :

Let’s create a workflow where every time someone tries to commit something, we will run some checks like Linter, Prettier and Tests. And to be more efficient we will run these steps only for the files which are staged. We can implement this pre-commit hook in 4 steps.

Step 1 :

Create a file called .git-hooks at the root level, Inside this folder, create any of the hook files, In our case, it will be .git-hooks/pre-commit with no extensions, it will be a bash file.

Step 2 :

Open .git-hooks/pre-commit file and paste below code.

#!/bin/sh
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')

# run linter on staged files
echo "Running Linter..⚒️⚒️⚒️"
./node_modules/.bin/eslint $STAGED_FILES --quiet --fix
LINTER_EXIT_CODE=$?

# run Prettier on staged files
echo "Running Prettier..✨✨✨"
./node_modules/.bin/prettier $STAGED_FILES --ignore-unknown --write

# add files auto-fixed by the linter and prettier
git add -f $STAGED_FILES

# check linter exit code
if [ $LINTER_EXIT_CODE -ne 0 ]; then
    echo "No, no, no! fix those lint errors first..😠"
    exit 1
else
    echo "lint all good..👍"
fi

# run tests related to staged files
echo "Running Tests"
./node_modules/.bin/jest --bail --findRelatedTests $STAGED_FILES --passWithNoTests
JEST_EXIT_CODE=$?

# check jest exit code
if [ $JEST_EXIT_CODE -ne 0 ]; then
    echo "Please you can do better than this..🙏🙏🙏"
    exit 1
else
    echo "test all good..👍"
fi

# return 0-exit code
echo "🎉 you are a rockstar..🔥🔥🔥"
exit 0

Before we go further, Let’s understand some important commands from above script.

  • git diff --cached --name-only : Get all the staged file names.
  • --diff-filter=ACMR : Filter only A Added, C Copied, M Modified and R Renamed files.
  • sed 's| |\\ |g' : This will match the regex and gives the file names in the correct format.
  • $?: This gives the exit status of the last executed command, By convention an exit status of 0 means success, and non-zero return status means failure.
  • git add -f $STAGED_FILES: Add All files back if there are any modifications done by eslint auto-fix or prettier. We will use the -f flag to force git add in case if there are any empty files.
  • If everything goes well, we will print appropriate message and exit from the execution.

If you are not much aware of bash then this cheat sheet will help

Step 3 :

Now that our script is ready, We need to tell Git to point our folder( .git-hooks ) instead of its default folder (.git/hooks ), whenever the git execution process starts.

To do that, we need to run the below command.

git config core.hooksPath ./.git-hooks

you can read more about git-config here.

Step 4:

Our git workflow is ready to use by now, Whenever there is a commit, our pre-commit hook will kick in and runs all the checks as mentioned in the script. But every time someone clones our repository they need to make sure that they run the config command as mentioned in step 3. We can automate this process by adding this command to our package.json file as below.

"scripts" : {
			....
			"postinstall": "git config core.hooksPath ./.git-hooks"
			....
			}

Now whenever npm install command is run, It will also configure git-hooks.

Note: Sometimes we might want to skip all the checks from git hooks, We can use--no-verify command which will bypass any git hooks and commit-msg. git add . git commit -m "skip git hooks" —-no-verify

References :

Antstack Blog Post
Antstack Blog Post

Are you planning to go to serverless? AntStack is a cloud computing service and consulting company primarily focusing on Serverless Computing. We help companies get up and running with serverless, and we’ll make sure that there are no limits.

Keep track of our socials and connect with us - LinkedIn

event bannerevent bannerevent banner