/ Tech

Jekyll git hook for drafts using branches

After using Jekyll for quite some time now, I was looking for a way to publish to a draft website before publishing to the live website.

As I'm using a git hook to publish my websites (see Why and how I moved from Wordpress to Jekyll: Publishing), I was looking for a way to use git for this. Therefore I've written a new post-receive hook which is able to
differentiate which branch was pushed. Depending on the pushed branch, Jekyll generates the website to a different path, using different configuration files. A new Apache vHost can now point to this different path, serving f.e. a basic authentication secured subdomain like draft.mywebsite.ch.

Using it

Just place the post-receive hook to the git hooks directory on the server and change the constants at the beginning of the script to your environment. Now create a new branch, make changes an push this branch to the same named remote branch. The hook now generates the webpage according to the branch name. If the branch is unknown to the hook, it just does nothing and exits with an error. After finishing the work, merge the draft brancht to the master branch and push it, the update of the website is now live.

Jekyll is able to read more than one configuration file, separated by comma. The later configuration file overwrites the values from the earlier one. So just add the values which are different on the draft page to the second configuration file, f.e. the url parameter.

The code

#!/usr/bin/env ruby

require 'fileutils'

GIT_REPO = '/home/me/mywebsite_ch.git'
TMP_GIT_CLONE = '/tmp/mywebsite_ch_clone'

DOCROOT = { 'master' => ENV['HOME']+'/public_html',
            'draft' => ENV['HOME']+'/public_html_draft' }

JEKYLL_CONFIG = { 'master' => '_config.yml',
                  'draft' => '_config.yml,_config-draft.yml' }

def exit_with_msg(msg)
  puts msg
  exit 1

# detect branch
branch = 'unknown'
$stdin.read.split(' ').each do |param|
  branch = param.split('/')[2] if param.include?('/')

exit_with_msg('branch unknown') if branch == 'unknown'
exit_with_msg('branch not configured') if not DOCROOT.has_key?(branch)
exit_with_msg('jekyll config not configured') if not JEKYLL_CONFIG.has_key?(branch)

puts "INFO: cloning branch '#{branch}' to #{TMP_GIT_CLONE}"
system("git clone -b #{branch} #{GIT_REPO} #{TMP_GIT_CLONE}")
puts "INFO: running jekyll build to '#{DOCROOT[branch]}'"
system("jekyll build -s #{TMP_GIT_CLONE} -d #{DOCROOT[branch]} --config #{JEKYLL_CONFIG[branch]}")
puts "INFO: removing #{TMP_GIT_CLONE}"