Maxime Demolin

Build and deploy your middleman application with gitlab

In order to build and deploy your application, you will need two things:

  1. .gitlab-ci.yml: the file describing which steps will be executed by CI.
  2. Dockerfile: for building an image that will be used inside .gitlab-ci.yml.

.gitlab-ci.yml

We will start with a simple example. For more information on what you can do, take a look at configuration of your jobs with .gitlab-ci.yml.

# .gitlab-ci.yml

image: gitlab.host/group/project/image:latest

# Build project and store artifacts
build_site:
  stage: build
  script: bundle install && yarn && middleman build
  artifacts:
    paths:
    - build/

# Deploy artifacts to production
deploy_to_ftp:
  stage: deploy
  script:
    - lftp ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST -e "mirror -R -p build/ $FTP_ROOT ; quit"
  only:
  - master

Let's tackle it down:

  • first we specify the image the use. We'll cover that more in details in Dockerfile section.
  • our first job is build_site< which will build the project with the command middleman build and store the artifacts we'll deploy. bundle install && yarn are required to fetch project dependencies (yarn can be optional though).
  • finally the job deploy_to_ftp will send your artifacts to your ftp, only if job ran on branch master. Environment variables can be set inside your project's settings, under "CI/CD Pipelines".

You can also ask for deploy to be manual, so that your application won't be deployed unless you explicitly click on a button:

# previous instructions
deploy_to_ftp:
  stage: deploy
  script:
    - lftp ftp://$FTP_USER:$FTP_PASSWORD@$FTP_HOST -e "mirror -R -p build/ $FTP_ROOT ; quit"
  when: manual     # won't be automatically executed
  only:
  - master

If your application is hosted on something else than a ftp server, you will have to adapt script. For instance, if you use surge, it will look like this:

deploy_to_surge:
  stage: deploy
  script:
    - yarn && yarn surge --project ./build --domain $SURGE_DOMAIN

Dockerfile

The Dockerfile will contain instructions on what is needed to build your middleman project. It can be fairly simple:

# Dockerfile

FROM ruby:2.4.1-alpine

# Base packages
RUN apk update
RUN apk add --no-cache build-base nodejs

# Install bundler
RUN gem install bundler

If you need to deploy to ftp, also add lftp to the list of base packages.

In case you use yarn, you'll have to pass an additional layer because ruby:alpine does not use the latest version of alpine where yarn has been added to repositories.

# After Base packages

# Yarn
RUN echo -e 'http://dl-cdn.alpinelinux.org/alpine/edge/main\nhttp://dl-cdn.alpinelinux.org/alpine/edge/community\nhttp://dl-cdn.alpinelinux.org/alpine/edge/testing' > /etc/apk/repositories && \
  apk add --no-cache yarn

Now all you need is to build your Dockerfile and push it to a registry. I usualy use the one provided by gitlab.

# Build and push image to registry
docker build -t gitlab.host/group/project/image .
docker push gitlab.host/group/project/image

And voila! Your next builds will be able to deploy artifacts to your production server.