GitHub Pages vs GitLab Pages - Improving CI/CD for Static Sites
GitHub Pages is a really easy way to get a static site up and running with a static site generator like Jekyll, Hugo, Gatsby, etc. This site is built using Hugo. My first iteration was deployed via Travis CI to GitHub Pages using a builder bot. It is totally functional and deploys easily enough.
The main issue I have with the current deployment using Travis CI is builds take 7-8 minutes for each pull request or merge to master. This takes up quite a bit of time. Because of the fact that there is a build for both PR and merge to master, each change to the site will take at minimum 15 minutes. I have been thinking of ways to use new tools to streamline this. I have had both GitLab and GitHub accounts for a while, but I have primarily used GitHub (there isn’t any particular reason why that’s the case.) Both services have been fine for what I need to do, but I have a lot more hands on experience with GitHub.
Why GitLab?
GitLab was one of the first repository management platforms that offered DevOps tools. I have heard that as a result, their CI/CD platform is very mature and robust compared to some others. I wanted to see what all the buzz is about. GitHub now has GitHub Actions, but I wanted to get out of my comfort zone to use some new platforms and tools (perhaps I will test using GitHub Actions at a later date).
Another reason I chose GitLab to test is I wanted to see how reliable GitLab’s offerings are. I have heard good things about GitLab. Meanwhile, I’ve personally experienced a small handful of issues with things like GitHub webhooks failing to send/trigger builds due to outages (it isn’t common, but it has happened occasionally due with GitHub reporting issues on their end). While I don’t personally use GitHub Actions, I do see frequent notifications from GitHub reporting issues. I can’t really speak on how minor or major these issues actually are, but I do see the notifications about that service.
Initial Prep
Prior to starting this I had already created a .gitlab-ci.yml
and it was already added to the project. When researching what would be needed for this file, I noticed Hugo had a guide for deploying on GitLab. Looking at the configuration for this, I realized that I wouldn’t really have to change anything from the base config, which is the following:
image: monachus/hugo
variables:
GIT_SUBMODULE_STRATEGY: recursive
pages:
script:
- hugo
artifacts:
paths:
- public
only:
- master
My site was already uploaded to my GitHub account. Using GitLab’s import functionality, I imported my repo from GitHub to GitLab. From there I just ran the pipeline and waited for it to complete. I noticed that the builds were immediately faster.
Difficulties and Differences
Getting Started
After running the first pipeline, the site did deploy successfully but the CSS was not displaying properly and the site was not visually acceptable. Using Hugo to build the site both on my local PC and via Travis CI, there were no issues. To get it working on GitLab pages a little bit of modifying needed to be done to the config.toml
. It appears that this can occur because the URL that is used for GitLab pages is a bit different. GitHub Pages would use al-haras.github.io
for the project and locally it is just localhost
. When using GitLab Pages to host the site the base URL is al-haras.gitlab.io/alex-haras-hugo
. Thus, adjustments are needed for the baseurl
value.
If you are migrating from GitHub, you may need to modify your config.toml
. This is the diff for the adjustments I made:
All and all, it was a minimal change and wouldn’t deter me.
Builds
Using GitLab to deploy my site, my build and deployment times dropped substantially. The builds went from 7-9 minutes to 46 seconds. That is an unbelievable amount of time saved. In additon, I did not need or want to create a bot account to deploy my site. I also did not need to add and mask credentials for the builds. It just runs and deploys your code.
GitLab CI - 47 seconds
Travis CI - 7 minutes 34 seconds
Something else that isn’t needed for GitLab is seperate repos for Hugo files, and the website files that Hugo generates. The CI tool just runs and deploys the public directory. It is very simple to setup.
SSL Certificates
Both GitHub Pages and GitLab Pages offer the ability to use SSL certs and automatically redirect http requests to https. Both also have the ability to automatically create SSL certs via LetsEncrypt. A difference is that GitLab allows you to upload and use your own SSL certs rather than using the LetsEncrypt certs. It is nice to see that offered. At the time of writing this, with GitHub Pages this is not available and the only option is to use the GitHub provided LetsEncrypt certs.
DNS - Custom Domains
I will say that GitHub Pages is a bit easier to setup DNS for custom domains. You just need to create A and CNAME records for your. GitLab requires that you additionally verify your domain ownership via a TXT record. Not that this is terribly difficult, but it is a difference.
Site Performance
I will just say it right off the bat. The GitHub Pages site loads faster. The GitLab Pages site is absolutely usable, but it is very difficult to see any difference in performance between the GitHub Pages site and using Hugo to serve the site locally (cache was cleared before testing). Both text and picture content load great with GitHub Pages. It is noticably slower on GitLab Pages which is disappointing. Site performance is one of my most important requirements for this project.
Will I Move to GitLab?
I would love to move to GitLab based on the build times. GitLab is a great platform and the CI/CD tools were really easy to work with. However, after looking at the performance of both sites side by side, it is hard for me to get over the difference. GitHub Pages just seems to be the better performer between the two. I think that rather than fully migrating to GitLab it would be best to first revisit the Travis CI builds and see if they can be improved.
A part of why my Travis CI builds take so long is both Go and Hugo are downloaded during the build. The container image recommended by Hugo for GitLab is monachus/hugo which has Hugo already installed. I thought about it and decided to refactor my Travis CI pipeline as I could very well see similar build times. Ideally, I’d be able to achieve this without sacrificing site performance.
Refactoring Existing CI/CD - GitHub Pages and Travis CI
Looking at the Travis CI documentation, Travis CI supports snaps (including Hugo) which I had not realized before. Just installing Hugo via snap
would save quite a bit of time for the current builds due to not needing to install both Go and Hugo. I modified my .travis.yml
accordingly:
---
dist: bionic
addons:
snaps:
- hugo
script:
- hugo
branches:
only:
- master
deploy:
local_dir: public
repo: $SITE_REPO
target_branch: master
provider: pages
skip_cleanup: true
github_token: $GITHUB_TOKEN
email: $GITHUB_EMAIL
name: $GITHUB_USERNAME
on:
branch: master
On the next build, I got exactly what I was looking for.
Travis CI - 30 seconds
My build times for PRs dropped from 7-9 minutes to 30 seconds. My deploy builds now take about 55 seconds. Build times are nearly tenfold less overall. I was able to achieve the same result benefit as I was on GitLab while keeping the same site performance by adjusting the existing process slightly.
Wrapping Up
After working on this project with GitLab there are a lot of features that GitHub simply lacks. GitLab is an incredible platform and has a lot of features that I didn’t realize it had. I am incredibly interested in working with it to work on other projects. While the performance of GitLab Pages didn’t wow me, the CI/CD and other tools did and I look forward to using it in the future.
If the site performance was the same, I would really consider moving from GitHub to GitLab as I feel like GitLab has more features.
All and all, this was a great experiment to do. I was able to learn a bit more about GitLab and reflect on the current CI/CD pipeline and implement some improvements.