Best practice setup for "Git-Hook" and "EsLint" for teams and also mono repositories
If you are setting up a mono-repo consist of Javascript/Typescript projects and you want to work on it with your team then you need to setup es-lint in a proper way. There are already tools like husky and lint-staged that you can utilise to setup es-lint on git-hooks but when it comes to mono-repositories, those will not work properly in sub-directories. This is a quick tutorial on how to setup Git-Hooks in a mono-repo and also in control of the team, because you want everyone in your team have the consistent experience with es-lint. Things we are going to do in bullets:
-
setup es-lint in each Typescript/Javascript project
-
setup git-hook script
-
create an init script which every developer for the first time will use
-
make script files executable
-
push everything to remote and happiness begins :)
Here is a structure of our code base which consist of different Typescript/Javascript projects. backend frontend shared-libraries, etc…
We create in each of these projects a .eslintrc.js file which includes our configuration for es-lint and in package.json we would have a script that runs es-lint against that project or sub-directory.
https://github.com/sunnystatue/githook-monorepo-example/blob/master/frontend/.eslintrc.js
https://github.com/sunnystatue/githook-monorepo-example/blob/master/frontend/package.jsonBy
adding that lint script in package.json we enable our git-hook pre commit script to run the es-lint with the local project specs and uses each project's node_modules independently.
The purpose of the whole thing is when developers in team decided to add file to stage and then commit them, before commit process we run the es-lint to make sure everyone is committing good quality code. There is a concept of hooks in git repositories if you open .git/hooks folder you would see list of different samples on different type of hooks. .git/hooksWe create a separate folder and change the default hooks folder in our code base named git-hooks to keep the hooks in a way that we can share it with the team. Then we create the pre-commit which will keep our logic on commits. Here is the backend section code which is pretty sam as frontend.
https://github.com/sunnystatue/githook-monorepo-example/blob/master/git-hooks/pre-commitWhat
what we do:
- list files that are in backend/src folder that are staged and they are one of the (js|jsx|tsx|ts)
- remove the backend/src prefix and fix the path strings
- run backend eslint against those files with --fix option
- try to stage them again for those which are fixed
- if eslint result is fail to fix all errors we exit the commit with out committing and print a message to tell developers they need to fix some stuff.
- It's pretty same for the frontend.
Then we need a init script which will act as a initial trigger to setup everything, this script file only contains one line:
git config core.hooksPath ./git-hooks
This tells the git to look for ./git-hooks for hooks. That's it, Isn't it wonderful?! :D
Now the only thing is left is to make pre-commit and init files executable other wise it won't work. to do that we run below commands:
chmod +x git-hooks/pre-commit
chmod +x git-hooks/init
git add .
# make these files executable in git
update-index --chmod=+x git-hooks/pre-commit
update-index --chmod=+x git-hooks/init
git commit -m"make init and pre-commit executable"
At this stage everything is setup and if you pull from another directory or machine the only thing to do is run ./git-hooks/init and then every time a developer make a change in (js|jsx|tsx|ts) files and tries to commit the eslint runs against that file. To get the initial sample repository use this Github link.