Goal

As mentioned in my previous post, I deploy my blog as static html with jekyll. Currently I do this by hand (ok, ok, with little helper script but manual). The next step ist to automate this task in a way, that a push to the master branch will update the blog on the public server for me. So I’d like to have a similar process as github pages uses.

Tools

All of the following components (except the external hosting provider) are running as docker container within a rancher cattle environment. The load is distributed over two nodes. The infrastructure would fill more than one blog entry, so we skip it for today. Both services are using let’s encrypt generated certificates and ssl offloading provided by the rancher load balancer configurations.

Gogs

Gogs is a small but powerful git server that provides a basic issue tracking, wiki and repository sharing. The repositories may also be organized in organizations. The following statement is taken from their github page :

The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. With Go, this can be done with an independent binary distribution across ALL platforms that Go supports, including Linux, Mac OS X, Windows and ARM.

Setting it up with rancher was quite an easy solution. They provide a template for the cattle orchestration. So it was a matter of minutes. I just had to add the host to the letsencrypt container config and to the ssl loadbalancer.

CI-CD-Workflow

drone.io

My first idea was to use jenkins. Just because the name is well known and there are a ton of plugins and help available. But even after trying to set it up in rancher, I could not find a way to get used to it. So I looked around and found drone.io. The page has a lot of comming soon and so has the documentation. But the idea of a build system running as docker container and building within a docker container looks promising. So I gave it a try.

The cool thing is, that drone provides integration to all big and (currently) well known code platforms. Gogs is one on the list of the supported source platforms. It directly connects to the source control and uses these credentials. So you don’t have to set up a own user management for drone.

So drone is available for rancher cattle as well. So Configuring it is in fact easy. the difficult part is, that there is not that many information or documentation around.

drone build view

Workflow

The image shouw a schema how the system are connected and what direction the requests go. It is not a full blown diagram.

drone component schema

The following steps show the workflow that I use to deploy the page you’re currently reading:

  • Creating a new feature branch on my local system (one branch for each post)
  • Writing the article and commit it (push to server)
  • Finish feature and merge working branch to master and push to server
  • Hook triggers drone.io
  • Wait for drone to build and publish the page
  • Navigate to the site to check if everything went well (optional, but better safe than sorry)

drone.io pipeline

In drone, there is no fancy web tool like the release management of microsoft’s team services. With drone.io the build and deployment configuration is stored in a yaml file. Below you find the configuration used to build and deploy this page.

pipeline:
  build:
    image: grahamc/jekyll
    commands:
      - gem install bundler
      - bundle install
      - jekyll build --config _config.yml,_config.prod.yml

  deploy:
    image: cschlosser/drone-ftps
    username: webuser
    hostname: webhost.example.com:21
    secrets: [ ftp_password ]
    secure: true
    dest_dir: /html/haefelfinger
    src_dir: /_site
    when:
      branch: master

All steps are executed in an own docker container. All containers have access to the same shared build workspaces. So all steps may access all elements from the previous steps and add more artifacts or do some stuff with them.

build

The image grahamc/jekyll can be found on dockerhub and provides a base image with an base jekyll installation. The commands provided by the list are executed within this container. So the version is always the expected one from the jekyll configuration.

So first, I have to install the latest version of bundler. After that the bundler will install all requirements for this jekyll page. The last step builds the static page content for further usage.

deploy

The image cschlosser/drone-ftps can be found on dockerhub as well. It is an alpine Linux with lftp installed and contains a small script to do an ftp mirror of the given folder. So this step mirrors the content of the folder “/_site” to the content folder “/html/haefelfinger” on the target server.

Because I use gitflow for feature branches to work on more than on article at a time, I only let drone.io run the deploy when the current build is based on the master branch.

Activate pipeline

To activate the build chain, you just log in to drone.io and browse your repositories. Flip the switch on the repository that should get an active build chain. Drone automatically places a webhook to the repository to get a callback. As soon as you push your first change, drone looks for the .drone.yml file and starts executing the pipeline.

Enabling pipeline