Jekyll + Github Pages + Travis CI

🗓️ 23 March 2020
🍿 8 mins read time
🏷️ Tags: Web

Introduction

Have you ever heard of static sites? Well, if your answer is no, stick with me and you will learn the basics of them.

As defined on Wikipedia, a flat page is a web page that is delivered to the user’s web browser exactly as stored, such that this page displays the same information for all users. Actually, “exactly as stored” would be too restrictive to produce a decent website with minimal effort, and here is where Jekyll comes into play.

What is Jekyll?

Jekyll is a tool used to generate simple, blog-aware, static websites. Let’s analyze those words:

Jekyll uses the so-called Liquid template engine, developed by Shopify, which we can exploit to inject some logic into our static files. Liquid is based upon two types of markup:

Jekyll has an extensive theme system, which we can leverage to build good-looking websites effortlessly. My personal favorite Github-hosted theme is PortfolYOU, which is the one I am using right now on the website you’re on.

Jekyll sites can also be enriched by plugins. You can browse for some good ones here. My personal favorites are the following ones:

If you want to create a local Jekyll project you can open a command-line window and do the following:

  1. Make sure you have Ruby installed on your system
  2. Run gem install bundler jekyll
  3. Run jekyll new my-site && cd my-site
  4. Run bundle exec jekyll serve

This will run your my-site locally at http://localhost:4000, so that you can open a browser and see what’s happening.

That’s pretty much all you have to know to work with Jekyll. Next up, we have to host our website on a specific provider to make it accessible on the internet, and here is where Github pages comes in handy.

What is Github pages?

Github pages is a free hosting service provided by the Github organization. With it, you can create one personal website with just a few clicks, which will be live at the URL <username>.github.io. To start, you have to do the following:

  1. Create a public repository and name it <username>.github.io, where <username> is your lowercase Github username (e.g. my Github username is Wadaboa and my Github pages repo is named wadaboa.github.io)
  2. Head over to the new repo settings and flag “Enforce HTTPS” if it is unflagged. Then, optionally write a custom domain, other than <username>.github.io, inside the “Custom domain” field (note that this will require to modify some DNS settings on your custom domain provider)

You are good to go. Now, all you have to do is download a Jekyll theme, or build a Jekyll website from scratch, as described above, and upload those files to the master branch of your Github pages repo.

So, why is Travis CI needed if the entire deployment is already done by Github pages? We shall see where a Continuos Integration pipeline turns out useful in the next section.

What is Travis CI?

Travis CI is a tool used to automate some repetitive programming tasks, which fall under the category known as DevOps.

In our example, how could Travis CI help us? Well, if you are using a Jekyll Github-hosted remote theme and you want to extend it with new functionalities, such as new plugins, you may want to locally build your Jekyll project and then directly push the generated static files to Github pages, in order to let it serve those files without the need to perform build operations. This operation is actually needed when you want to work with non-safe plugins, i.e. plugins which are not supported by the build process of Github pages. Examples of such plugins are jekyll-analytics and jekyll-sitemap.

In order to work with Travis CI, we need to follow some simple steps:

Now, you need to create a .travis.yml file in the root of your <username>.github.io repository, with the following content:

language: ruby
rvm:
  - 2.6.3

before_install:
  - gem install bundler

install:
  - bundle install

before_script:
  - chmod +x ./scripts/build

script: ./scripts/build

branches:
  only:
    - release

sudo: required

cache: bundler

deploy:
  provider: pages
  skip_cleanup: true
  keep-history: true
  local_dir: _site/
  target_branch: master
  github_token: $GITHUB_API_KEY
  on:
    branch: release

notifications:
  email:
    on_success: never
    on_failure: always

You will also need to create a build script inside a new scripts folder, with the following content:

#!/usr/bin/env bash

set -e
JEKYLL_ENV=production bundle exec jekyll build --destination _site
touch ./_site/.nojekyll

In order to make everything work, you will also need to create two new branches:

When you will perform a push on the release branch, Travis CI will be triggered and your build will start. If anything goes wrong, you will receive a notification on your Github-associated email, otherwise you will see a push on the master branch, made by traviscibot, and your updated website will be live.

Remember that the master branch is where Travis CI will copy the static files associated with your Jekyll website. These static files are generated inside the _site folder in the root of your project when you perform a bundle exec jekyll build operation and they should not be present in your release branch, hence you should always add _site/ to your .gitignore file.

NOTE: If you were using the jekyll-github-metadata before using Travis CI, you will find out that this plugin no longer works after performing the described steps. To fix it, you have to do the following:

  1. On Github, click on your profile picture in the top right → Settings → Developer settings → Personal access tokens → Generate new token, then add a Jekyll entry with the repo scopes and copy the corresponding token
  2. On Travis CI, click on Dashboard → <username>.github.io under Active repositories → More options → Settings → Environment Variables and set the variable JEKYLL_GITHUB_TOKEN with value the Github generated token