Let’s consider that we want to write some static webpage (i.e : a blog) using Jekyll to generate the static pages, and we only want to drive it from code using GitLab (this would work with GitHub as well, although the setup described here wouldn’t work).
The setup described will use a git repository to write the Jekyll code in it, some pre-commit validation, and then a branching setup to push the blog either to a GitLab pages, or to a remote server.
We’ll use GitLab CI to perform most of the tasks. Let’s start by creating in a folder which will be our git repository :
mkdir epicfail-jekyll-blog
cd epicfail-jekyll-blog
git init
We’ll add some files in it which are the following :
$ tree -L 1
.
├── 404.html
├── about.markdown
├── \_config.yml
├── Gemfile
├── Gemfile.lock
├── index.html
├── \_posts
├── README.md
└── \_site
_posts will contain the markdown file which will be used to generate the blog articles. _site will contain the generated relevant files to perform the setup on a remote server. The other files are useful for how Jekyll works, you can find more information on that on the Jekyll Website. Those can vary depending on the theme you use.
Once we have generated the files we can now populate the git repository locally by commiting it.
Now let’s start the pre-commit setup. Let’s check that everything works by running the following commands :
$ jekyll serve
Incremental build: disabled. Enable with --incremental
Generating...
Jekyll Feed: Generating feed for posts
done in 0.784 seconds.
Auto-regeneration: enabled for ...
Server address: http://127.0.0.1:4000/
Server running... press ctrl-c to stop.
Check in a browser that it displays as expected, then let’s start the following part which is working on pre-commit. We’re going to check the layout to be accurate to the expectation.
Let us now look at the GitLab-ci setup. We’ll have the following file for automation.
image: ruby:3.0
workflow:
rules:
- if: '$CI_COMMIT_BRANCH'
stages:
- preflight
- build
- test
- deploy
before_script:
- 'which ssh-agent || (apt update && apt-get install -qq openssh-client)'
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
pages:
stage: build
script:
- gem install bundler
- bundle install
- bundle exec jekyll build -d public
artifacts:
paths:
- public
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
tags:
- docker
test:
stage: test
script:
- gem install bundler
- bundle install
- bundle exec jekyll build -d test
artifacts:
paths:
- test
rules:
- if: '$CI_COMMIT_BRANCH != "master"'
tags:
- docker
deploy:
stage: deploy
dependencies:
- pages
script:
- ssh ${USER}@${DESTINATION_HOST} "cd /var/www/${DESTINATION_HOST}/ && mv html html.$(date +%Y-%m-%d-%H-%M).backup && mkdir html"
- scp -r public/* ${USER}@${DESTINATION_HOST}:/var/www/${DESTINATION_HOST}/html/
tags:
- docker
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
It should be noted that this file is not optimal, it’ll be arranged in another post. To break down the steps, we have the following.