Jekyll automation with GitLab
Post

Jekyll automation with GitLab

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.