Content is a KING. Neither fancy CMS nor online WYSYWIG editors are, but content is. That’s why Jekyll powered GitHub Pages got such a popularity. Just push HTML, Liquid, Markdown etc, then files got processed by Jekyll and the whole site becomes available online in a minute. However, if you’d like to use extra Jekyll features, for instance AsciiDoctor, you should manage site generation yourself. This quite boring activity could be simplified by leveraging Travis CI continuous integration project.

Setting up Jekyll

The only precondition is that you have Jekyll site already configured using Bundler and you can run it locally with

bundle exec jekyll serve

Setting up Travis CI

The whole idea was to make publishing experience of highly customized Jekyll project to GitHub Pages exactly the same as publishing of standard Jekyll site. You just push your changes to git, wait couple of minutes and refresh the page with new content.

I’m using User Pages approach as described here so I have two branches for my setup

  • master for generated static content

  • jekyll for markup sources and configuration

The goal is to configure Travis CI job to listen for commits on jekyll branch, then run jekyll build for process markup sources and then push generated content to master branch.

Enable Hooks

To make Travis CI listen for commits and do actual work - we have to enable hooks.

Enable Travis CI hook

Travis CI configuration

Then let’s limit commit trigger to jekyll branch only and explicitly configure the script that will be executed after commit detection. For this we have to put file .travis.yml to the root of jekyll branch with following content.

language: ruby
script: "./" # execute this script on each commit
  - jekyll # only take into account `jekyll' branch
- 2.1.2 # version of `ruby'

Generate and encrypt GitHub token for Travis Ci

Since we’d need to commit and push our changes to other (master) branch from within the build script it’s mandatory to checkout this branch either using HTTPS or SSH protocol, as described HERE Easiest way for us is to clone using HTTPS protocol and use personal access token for authentication.

Generate GitHub token
Copy generated token somewhere to be used in the next step.

Putting clear text tokens into script isn’t good idea, but thanks to travis command line tool we can encrypt any name=value pair and later expose them as environment variables to the build job.

Execute following code in the working directory where jekyll branch is cloned to.

gem install travis
travis encrypt GH_TOKEN=<token> --add

The command above should add following lines to your .travis.yml.


Build script

And finally the build script.

# only proceed script when started not by pull request (PR)
if [ $TRAVIS_PULL_REQUEST == "true" ]; then
  echo "this is PR, exiting"
  exit 0

# enable error reporting to the console
set -e

# build site with jekyll, by default to `_site' folder
jekyll build

# cleanup
rm -rf ../

#clone `master' branch of the repository using encrypted GH_TOKEN for authentification
git clone https://${GH_TOKEN} ../

# copy generated HTML site to `master' branch
cp -R _site/* ../

# commit and push generated content to `master' branch
# since repository was cloned in write mode with token auth - we can push there
cd ../
git config ""
git config "Evgeny Shepelyuk"
git add -A .
git commit -a -m "Travis #$TRAVIS_BUILD_NUMBER"
git push --quiet origin master > /dev/null 2>&1 (1)
1 Hiding all the output from git push command, to prevent token leak.

Run everything

After doing all those steps all you need is to commit and push your jekyll branch and then navigate to Travis CI build section of your project to monitor your build progress.


I hope this tutorial help you setup own Jekyll with less pain. Supposedly described steps could be applied to other static site generators like Middleman, Awestruct etc.


The actual setup and this post was inspired by Dan Allen reply to my tweet and the code from this project