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.