Automatic deployment of pelican blog with ansible and gitlab

Intro

I want to be able to edit my blog post from gitlab interface and then have changes automatically deployed to my blog. For that I will setup a gitlab runner on my existing web server and create a CI job to execute on that runner.

I will use 'website' tag to mach a runner to the ci configuration.

Ansible dependencies

I've been using riemers.gitlab-runner playbook for installing gitlab runner, and the latest version 1.5.3 works quite well.

I also use avanov.pyenv playbook to install python versions on a target machine, python development dependencies should be installed on the target machine.

My requirements.yml file looks like the following

- src: avanov.pyenv
- src: riemers.gitlab-runner
  version: v1.5.3

Installing ansible requirements:

ansible-galaxy install -r requirements.yml

Installing gitlab-runner

Use the following settings in gitlab-runner role, webserver host is defined in hosts file with tag 'website' identifying the runner that has capabilities to run pelican deployment jobs (this will come in handy in CI definition).

- hosts: webserver
  roles:
    - role: riemers.gitlab-runner
      gitlab_runner_coordinator_url: https://gitlab.server
      gitlab_runner_registration_token: --secret--
      gitlab_runner_package_name: gitlab-runner
      gitlab_runner_concurrent: 1
      gitlab_runner_runners:
        - name: webserver
          concurrent_specific: 1
          tags: [website]
          run_untagged: false
          locked: true
      become: true

Then set up required python version along with a virtualenv for the CI job. In this case virtualenv is called 'pelican'.

- hosts: webserver
   roles:
   - role: avanov.pyenv
    pyenv_path: "/home/gitlab-runner/pyenv"
    pyenv_owner: "gitlab-runner"
    pyenv_update_git_install: no
    pyenv_enable_autocompletion: no
    pyenv_python_versions:
      - "3.6.5"
    pyenv_virtualenvs:
      - venv_name: "pelican"
        py_version: "3.6.5"

To set permissions on a target folder to be owned by gitlab-runner. A file task for that can be defined as part of a role.

- name: ownership for static site dir is set
  file:
    path: /srv/flamy_ca
    state: directory
    recurse: yes
    owner: gitlab-runner
    group: gitlab-runner

Defining CI script

I added the following to my .gitlab-ci.yml at the root of the project folder. It is basically development deployment, with the addition of the first two commands activating virtual environment, and installing all pelican dependencies.

Instead of 'make html' to generate static site, use 'make publish' which imports production settings from publishconf.py instead of pelicanconf.py.

stages:
  - deploy
prod deploy:
  stage: deploy
  script:
    - source /home/gitlab-runner/pyenv/.pyenvrc
    - pyenv activate pelican
    - pip install -r requirements.txt
    - make clean
    - make publish
    - rsync --archive --delete --progress output/* /srv/flamy_ca
  tags:
    - website
  only:
    - master

This script only runs on master branch and only in a runner that has 'website' tag defined.

Pitfalls

There is an issue with debian system where you might get 'No Such file or directory' when running a running the deploy. It appears there is a bug in .bash_logout file.

Deleting the file solves the issue, for more details see this stackoverflow question.