One reason for [migrating to static site generation][migrate-to-jekyll] is that the site becomes more straightforward to keep in version control systems such as git. And I do like version control; I naturally ran git init
before I ran jekyll new
!
In my workflow, once I have made and committed changes locally, I push the changes remotely. But now I need to build and deploy the new version of the site. What if I could get that to happen automatically?
To do this, I set up my web server to accept git commands; this is a topic unto itself which I might write about some time.
I then create a bare repo:
git init --bare blog.git
After setting permissions as appropriate, I can now push my git repo to the web server:
git remote add origin https://user@your.website.tld/git/blog.git
git push -u origin master
I then modified [an example git-hook][jekyll-deploy-hook] I found on the Jekyll website to be more robust and meet my needs. There are a few things to take note of here:
- I switched from using the
git-receive
hook as per Jekyll’s recommendation topost-receive
. This is because the level of infogit-receive
, ahem, receives seems a bit overkill —post-update
provides the names of the modified branches, and that’s all we need. DEPLOY_REF_REGEX
is a regex that matches git-refs, such as branches. The value in my script means that it’ll only deploy the website when changes are pushed tomaster
. This means you are free to experiment on non-master
branches. I haven’t gone so far as to deploy different branches different places!GIT_REPO
is the path to your site’s git repo. Ensure it can be read by the webserver.PUBLIC_WWW
is where the website needs to be deployed to be visible on the web. Ensure it is writable by the webserver.
To use this hook, create a file called post-update
in your remote bare repo’s hooks
directory. Ensure it is executable by your webserver!
#!/bin/bash
# Builds and deploys blog when new commits are pushed to the specified branches (default master).
#
# Despite the Jekyll site recommending to use the post-receive hook, we do not
# need the level of information that post-receive gets. post-update receives
# each ref that was updated as an argument, and so is sufficient for this
# script's needs.
#
# The script also adds the commit ID of the deployed commit to the site, so you are able
# to tell exactly what is live by visiting /deployed_commit.
#
# Originally taken from: http://jekyllrb.com/docs/deployment-methods/#git-post-receive-hook
#
DEPLOY_REF_REGEX=refs/heads/master
GIT_REPO=/shared/code/git/blog.git
PUBLIC_WWW=/var/www/blog
DEPLOY=
for ref in "$@"; do
if [[ $ref =~ $DEPLOY_REF_REGEX ]]; then
DEPLOY=true
break
fi
done
if [ $DEPLOY ]; then
TMP_GIT_CLONE=$(mktemp -d)
git clone "$GIT_REPO" "$TMP_GIT_CLONE"
echo $(GIT_DIR=.git git -C "$TMP_GIT_CLONE" rev-parse HEAD) > "$TMP_GIT_CLONE/deployed_commit"
jekyll build -s "$TMP_GIT_CLONE" -d "$PUBLIC_WWW"
rm -Rf "$TMP_GIT_CLONE"
else
echo "Updated refs did not match; not deploying."
fi
exit
You’ll get output like the following:
$ git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 3.15 KiB | 0 bytes/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Cloning into '/tmp/tmp.TkcxSnfVnb'...
remote: done.
remote: Configuration file: /tmp/tmp.TkcxSnfVnb/_config.yml
remote: Source: /tmp/tmp.TkcxSnfVnb
remote: Destination: /var/www/blog
remote: Generating...
remote: done.
remote: Auto-regeneration: disabled. Use --watch to enable.
To https://user@your.website.tld/git/blog.git
df05e56..ce42b80 master -> master
If the deploy succeeds, then website should be available on the internet and you are done! If the deploy fails, the push will be cancelled and you’ll need to investigate why that might be. I would first check the permissions on all of the directories mentioned above.
Finally, as a little bonus, the script creates a deployed_commit
file which contains the commit SHA of the commit the build was based on; useful if something goes wrong or you just want to check what you last deployed. You can even check my site’s deployed commit (update: now defunct)!
[migrate-to-jekyll]: {% post_url 2015-10-04-migrating-from-wordpress-to-jekyll %} [jekyll-deploy-hook]: http://jekyllrb.com/docs/deployment-methods/#git-post-receive-hook