I host this blog on a git repo that lives on the same box as the webserver. When I push to it, I want to ensure that deploys happen. Previously, it involved SSHing and doing a bit of a dance. Today, I setup a deploy-on-push script through git’s pre-receive hooks. It was surprisingly difficult to find a good example of this pattern, so I wanted to publish my result.
When the pre-receive hook is invoked, it’s given a line on stdin for each ref
that was pushed. If the branch is master, then invoke the make publish command
in the repo.
GIT_QUARANTINE_PATH is something I couldn’t find tons of information about. It
prevents you from modifying any of the refs during pre-receive. In general, this
sounds like an awesome idea. In practice, it means that you can’t check out the
source files, so we have to unset it.
The GIT_WORK_TREE setup allows you to put the files somewhere as you work on
them, but keep the repo where it is. This was important because when I tried to
git clone , the cloned copy didn’t have a reference to the most recent files.
#!/bin/bash -ex
zero_commit='0000000000000000000000000000000000000000'
while read -r oldrev newrev refname; do
# Branch or tag got deleted, ignore the push
[ "$newrev" = "$zero_commit" ] && continue
# Calculate range for new branch/updated branch
[ "$oldrev" = "$zero_commit" ] && range="$newrev" || range="$oldrev..$newrev"
if [ "$refname" == "refs/heads/master" ]; then
echo "Deploying..."
unset GIT_QUARANTINE_PATH
CO_DIR=`mktemp -d`
GIT_WORK_TREE=$CO_DIR git checkout -f $newrev
GIT_WORK_TREE=$CO_DIR git reset --hard
GIT_WORK_TREE=$CO_DIR git clean -fdx
cd $CO_DIR && make publish
fi
done