Automate GitHub Pages publishing with Jekyll and Travis CI
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.
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: "./build.sh" # execute this script on each commit
branches:
only:
- jekyll # only take into account `jekyll' branch
rvm:
- 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 env.global
The command above should add following lines to your .travis.yml
.
env:
global:
secure: HERE GOES ENCRYPTED STUFF
Build script
And finally the build script.
#!/bin/bash
# only proceed script when started not by pull request (PR)
if [ $TRAVIS_PULL_REQUEST == "true" ]; then
echo "this is PR, exiting"
exit 0
fi
# enable error reporting to the console
set -e
# build site with jekyll, by default to `_site' folder
jekyll build
# cleanup
rm -rf ../eshepelyuk.github.io.master
#clone `master' branch of the repository using encrypted GH_TOKEN for authentification
git clone https://${GH_TOKEN}@github.com/eshepelyuk/eshepelyuk.github.io.git ../eshepelyuk.github.io.master
# copy generated HTML site to `master' branch
cp -R _site/* ../eshepelyuk.github.io.master
# commit and push generated content to `master' branch
# since repository was cloned in write mode with token auth - we can push there
cd ../eshepelyuk.github.io.master
git config user.email "eshepelyuk@gmail.com"
git config user.name "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.
P.S.
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.
Credits
The actual setup and this post was inspired by Dan Allen reply to my tweet and the code from this project