A git pre-push hook to run tests on a particular branch when you push
I’ve been working on a project with a couple of others and we needed something to test our build before it was pushed to the main branch.
Succinctly, the idea was that when someone pushed to branch X, I wanted a test script to be run. If it passed, it allowed the push through, otherwise it should tell you to fix the issue.
So, instinctively, I knew this was a job for a git hook. Conceptually, I understand what git hooks do. For the uninitiated, they are files that lives in the ./git/hooks
folder of your project.
I made a stab at it, but when things started error-ing I felt the oh-so-familiar feeling of a gap between my optimism and actual knowledge and talent 🙂
So, I asked on Stack Overflow and after the usual virtual ‘hand slaps’ for not phrasing the question correctly and other things, the folks there kindly corrected what I had to this:
#!/bin/zsh
current_branch=$(git symbolic-ref --short head)
cmd="npm run testbuild"
if [[ $current_branch = "YOURBRANCH" ]]; then
echo "you are on $current_branch, running build test"
eval $cmd
result=$?
if ! eval "$cmd"; then
echo "failed $cmd" >&2
exit 1
fi
fi
exit 0
Let me do my best to explain what’s going on for both of our benefit. This is a shell script, so first thing is the bang and shell. We are all on mac where zsh is the default shell, but #!/bin/bash
would likely work just as well.
Then we get the current branch as a string with the git command $(git...)
.
Next I am defining the command I want to run if we are on the relevant branch. I hadn’t realised that the part in the square brackets is whitespace sensitive. You DO want that space around the square brackets.
Then we have our first if/fi
which we only enter if we are on the branch in question. We then echo out a line of text, run the cmd (eval
runs the string above as an actual thing).
Then in the nested if/fi
if that script isn’t happy, we exit with 1. With shell scripts, 1 means not good. 0 means good!
Now, once you have this working on your own system, you need to get it into everyone else’s system. I read this https://dev.to/akdevcraft/git-pre-hook-pre-commit-hook-with-npm-project-44p2 on the subject and amended the part where you use the package.json
to get the script copied from one place to the other.
So, I copied my script into scripts/pre-push
in my local project and then added this to my package.json
:
"postinstall": "cp scripts/pre-push .git/hooks/ && chmod +x .git/hooks/pre-push && echo 'hook copied'"
This means that once I had committed these changes, all I needed to do was get each person to run an npm i
and the script would be copied across on their machine, to the correct location.
Now, when they push, if they are pushing to the branch in question, it runs the tests first to prevent not working code making it to our main branch.
Leave a Reply