Skip to Content

Under the hood: GitLab CI/CD

With my Pelican container I can now easily write blog posts and review them locally.

Now I need to get my files to my server.

Pelican provides a ‘make’ command to do this which I’ve used for years. ‘make rsync’ will get things updated. But again it’s 2019 and that is boring.

We’re essentially going to do the same things we did with Docker within the GitLab environment. We’ll build a Pelican environment, run Pelican and generate my content. Then we will build another environment with rsync and push my content to my server.

I created a .gitlab-ci.yml file and placed that within the root of my blog.

# ----------------------------------------------------------------------------------------
# build file for thecrumb.com
# will generate html files and rsync to host
# ----------------------------------------------------------------------------------------

variables:
  OUTPUTDIR: output
  SSH_HOST: foo.bar.com
  SSH_USER: foobar
  SSH_TARGET_DIR: public_html/
  GIT_SUBMODULE_STRATEGY: recursive

# Define two stages, if the site fails to build it will not be deployed
stages:
  - build
  - deploy

build:
  stage: build
  image: osones/pelican  # pelican docker image
  artifacts:  # artifacts are files that will be passed to the next CI stage and can be downloaded from the GitLab web
    paths:
      - output  # This is the directory we want to save and pass to the next stage
    expire_in: 1 week  # Keep it around for a week in case we need to roll back
  script:  
    - pip3 install --upgrade pip
    - pip3 install -r requirements.txt
    - pelican content -o output -s pelicanconf.py  
    - ls -lart output
  only:
    refs:
      - master  # Only run this step on the master branch and if we've updated content
    changes:
      - content/*


deploy-prod:
  stage: deploy
  image: instrumentisto/rsync-ssh  # alpine image with rsync and ssh

  script:
    # setup ssh and move keys where they need to go
    - echo ----------------------------------
    - mkdir "$HOME/.ssh"
    - echo "$KNOWN_HOSTS" > "$HOME/.ssh/known_hosts"
    - echo "$SSH_PRIVATE_KEY" > "$HOME/.ssh/gitlab-ci"
    - chmod 700 $HOME/.ssh/
    - chmod 644 $HOME/.ssh/known_hosts
    - chmod 600 $HOME/.ssh/gitlab-ci

    # rsync files
    - rsync -e "ssh -i $HOME/.ssh/gitlab-ci" -rvzc --exclude test --delete $OUTPUTDIR/ $SSH_USER@$SSH_HOST:$SSH_TARGET_DIR/ --cvs-exclude

  environment: 
    name: master-prod
  only:
    - master

I have two ‘stages’

  1. build - Run Pelican and generate my static content into an ‘output’ directory
  2. deploy - if the build is successful I will move the code in ‘output’ to my server via rsync

This is a simple process. In real life we’d be linting, running tests and compiling things.

So now when I ‘git push’ to master GitLab will build and deploy my blog to my server.

My last issue is since this is all static I have no convenient way to schedule a post in the future like you can with a dynamic system like WordPress. But I am working on cobbling together something with cron. Once I get that working I’ll add a post to this series.