We use Jekyll to statically build this blog, and have integrated it with GitHub Pages, which takes care of hosting and the CI/CD pipeline. The Jekyll/GitHub Pages solution involves using the github-pages gem in the project, and configuring the GitHub Pages settings for the repository. To build and deploy, all that’s required is to push a commit to the master
branch, and the GitHub hosted blog is live in a matter of minutes.
We have been using Jekyll for 5 or 6 years now, and it has made writing our blog easy. We have our own theme and layout which was fairly easy to create, and adding a blog post is as simple as writing a new markdown file. However, we have been stuck on an old version, 3, for some time now, and with a rebrand of the blog, it seemed like a perfect opportunity to address this and migrate to Jekyll 4. The problem is that the GitHub Pages gem doesn’t support Jekyll 4, and doesn’t look like it will anytime soon.
How does the GitHub Pages gem work anyway?
To start with, Jekyll has built-in support for GitHub Pages via the github-pages gem. When a repository is configured to use GitHub Pages, and it is a Jekyll site with the gem applied to it, it will first build the site before deploying the build artifacts. But if all things remain the same, except the gem is not applied to the site, then the entire repository will be deployed. That’s key. The GitHub Pages gem is the CI part of the CI/CD pipeline:
CI/CD pipeline with the gem
CI | CD |
---|---|
GitHub Pages gem | GitHub Pages |
So, is that it? Are we stuck with Jekyll 3?
As it turns out, there is a very simple alternative to using the gem for CI, and that is using the Jekyll Actions GitHub Action instead, which is the recommended approach from the guys at Jekyll. And the nice thing about this approach is that it keeps everything in GitHub, just like the gem, but without the restrictions.
There is very simple configuration file, plus a requirement of a Personal Access Token with repository permissions. And given this is a company blog, the token belongs to a machine user.
CI/CD pipeline with GitHub Actions
CI | CD |
---|---|
Jekyll GitHub Action | GitHub Pages |
Okay, but do we really need to migrate to Jekyll 4?
Some of the key features of version 4 for us were:
- Keeping our software up-to-date with the latest versions
- Making use of the new gems
The first one shouldn’t be considered unimportant. Old software can hinder developers:
- New features cannot be taken advantage of
- Best practices change and these may not be easy to keep up with when using stale software
- Security holes may not be fixed
- Documentation for the old version may be difficult to find, especially necessary when things have changed significantly
Perhaps I’m labouring the point. But neither am I advocating living on the bleeding edge, which too has it’s down sides. It’s just much better for everyone to be up-to-date.
So, what exactly are the steps we identified?
- 2 Perform the actual migration
-
3 Update internal documentation to include the new build step
-
4 Write a blog post describing our experience (yes, this one!)
- 5 Analysing the impact with GTM reports
1 Perform a dry run, just to ensure the process is understood beforehand, and identify any complications
To ensure the process be well understood beforehand, and to identify any complications, the repository can be duplicated/forked for a trial run. In fact, the following migration steps were refined through doing just that. This built confidence is the migration process and helped distinguish between things that were part of the migration to Jekyll 4 and those that were part of the re-branding/re-theming exercise.
2 Perform the actual migration
2.1 Create a secret from a Personal Access Token with full repo permissions to the repository
A Personal Access Token can be created at https://github.com/settings/tokens, using instructions from authenticating-to-github/creating-a-personal-access-token in GitHub docs. (We already had with full repo
permissions to the repository for a machine user.)
With the token at hand, head to the following location within the project repository /settings/secrets/actions/new
to create the new secret:
Name | Value |
---|---|
FMP_GITHUB_TOKEN |
{Personal Access Token with repo permissions} |
Then click Add secret.
2.2 Add a new GitHub Action workflow file to the repository
The GitHub Action workflow file will be configured to trigger on changes to the master
branch, and will then checkout the repository, and build it, using the Jekyll Actions GitHub Action with the Personal Access Token setup earlier (referred to as secrets.FMP_GITHUB_TOKEN
).
The env: PAGES_PAGES_HOSTNAME: xxx
is only used if you have a custom domain setup.
NB. The last step copies the build artefacts to the gh-pages
branch.
.github/workflows/github-pages.yml
:
name: Build and deploy Jekyll site to GitHub Pages
on:
push:
branches:
- master
jobs:
github-pages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: helaili/jekyll-action@2.1.0
with:
token: $
env:
PAGES_PAGES_HOSTNAME: https://custom-domain
In order for the action to correctly set site.repository
(used by things like site.baseurl
), while still using the github-pages
gem, you will need to add the following to your _config.yml
:
+ repository: username/repo-name
This change can now be pushed, even with GitHub Pages continuing to build and deploy off the master
branch. The action doesn’t interfere with this, as it only makes changes to the gh-pages
branch and this is not what is deployed, yet.
2.3 Configure GitHub Pages to use gh-pages branch
With the GitHub Action successfully setup and running on the repository (which can be checked by both reviewing the Actions
tab in the repository, or simply the contents of the gh-pages
branch), it’s time to wire this up to GitHub Pages.
Go to the Settings
tab in the repository, scroll to the GitHub Pages section, and set the following:
- Source
- Branch
gh-pages
- Folder
/ (root)
- Branch
- Custom domain (Set by the
CNAME
file within the repository, when using a custom domain)
2.4 Upgrade to Jekyll 4 and remove the GitHub Pages gem requirement from the Gemfile
Update the Gemfile
by removing the github-pages
gem and including the Jekyll 4.2.0 gem:
- ruby '~> 2.3'
+ ruby '~> 2.4'
- gem 'github-pages', group: :jekyll_plugins
+ gem "jekyll", "~> 4.2.0"
+
+group :jekyll_plugins do
+ gem "jekyll-seo-tag", "~> 2.7.1"
+end
Then run the following to make sure the Gemfile.lock
is updated correctly:
bundle install
And check everything is still working okay (hopefully so 🙏) by running the site and viewing it:
bundle exec jekyll serve
Update the .gitignore
with the following cache directories generated by Jekyll 4 builds:
+ .jekyll-cache/
+ .sass-cache/
3 Update internal documentation to include the new build step
Add a description of the CI/CD pipeline, how it works and how it can be modified. Some of this blog post and the document’s pipeline section share similar, content, but for differing purposes.
While this appears as a task after the migration, it was completed beforehand.
4 Write a blog post describing our experience (yes, this one!)
As with the internal documentation, it was written out in full before the actual migration was performed (with the exception of the final thoughts 😉), again providing another opportunity to think through the migration in detail and understand it inside out.
5 Analysing the impact with GTM reports
The Google Analytics reports for the blog were reviewed to identify what needed keeping an eye on and ensure no negative impact from the upgrade.
Final thoughts
TBC post-migration!