GitLab Continuous Integration always intimidated me. It used to be a separate server, which also seemed to required other separate servers. I’ve had GitLab running for about a year, but was always terrified of how much more server management trying to implement CI looked like. These days (post ver 8), the CI server is baked into the omnibus installation of GitLab. I was still hesitant because there were all these “runners” to worry about. All of the documentation just said “set up a runner and go!” but it didn’t make sense. What is a runner? Does it need it’s own dedicated server? It sounds like a lot more extra management.

I finally dove into it yesterday, and guess what — it’s stupid easy.

What’s up with CI?

CI in Gitlab is enabled through 3 main components:

  • CI Coordinator (now integrated with GitLab)
  • CI Runner (A simple binary file that GitLab can ping on a remote server to run some stuff)
  • CI Project Configuration (.gitlab-ci.yml)

CI Coordinator

The CI Coordinator runs on GitLab and is the main brain of continuous integration. It maintains the various registered remote connections to use for testing/integration, and coordinates the executions.

It can be activated in a project simply by including a CI Config file (.gitlab-ci.yml)

When this file is included, GitLab will parse it for relevant jobs based on the commit and tags. More at CI Configuration.

CI Runner

The CI Runner is a simple Go app binary that sits on whatever computer you want to integrate with GitLab. It doesn’t have to be a server, and can even be installed on your local dev desktop if you wished.

  1. Download the GitLab CI Multi Runner
    • It’s a single app that is compiled against all of the main platforms, written in Go.
    • Windows place the binary wherever it’s appropriate. The directory it’s created in will suck down your repositories and execute from that location with your user account.
    • Linux it’s a simple package that installs a new user for running, and adds appropriate PATH.
  2. Register a runner
    • gitlab-ci-multi-runner register (executable name varies slightly on each platform)
    • The app will ask you a few questions:
    • GitLab Coordinator URL: https://git.thegeck.com/ci
    • GitLab-CI Token: This comes from GitLab depending on the context you are registering this runner
      • Shared Runners are system wide – separate API key from…
      • Project Specific Runners are reserved exclusively for your project’s usage
    • Description: name for the runner
    • Tags: A series of comma separated tags that describe the environment.
      • ruby, rails, linux, x32, python
      • windows, clr, aspnet, csharp, iis, rails, test
    • Executor: What environment runs the code?
      • shell is most straightforward and least magical - it just means “execute command line stuff”
      • You can also use docker, and a few other tricks
        • I don’t know how to use Docker yet, but it looks easy and awesome and magical.
          • If you’re on Windows, you’ll also need to assign the service to your user account so it can run in the background.
    • The documentation says gitlab-ci-multirunner install --password {PASSWORD} but it didn’t work for me. I had to open the services menu and manually change the user account.
    • Make sure the service is started after making this change.

CI Configuration

To configure your project to use CI, simply include a .gitlab-ci.yml file. You’ll also need to provide runners. You can either enable system-wide shared runners, or register a project specific runner. When you first publish a project with a config that doesn’t have a runner, GitLab holds your hand to get you hooked up. Find out details of creating a config file here: http://doc.gitlab.com/ci/yaml/README.html

When you make a commit, the engine parses the config file to check if there is work to be done for commits against this branch. Each branch can have it’s own separated jobs if desired:

  • master
  • testing
  • production
  • development
  • whatever

Once runners are turned on, the CI engine parses the file for each job to execute, and the associated tags. This enabled different types of tests to happen on different types of platforms. For instance:

  • Unit Testing in the native code environment
    • Windows .net c#?
  • Integration Testing (ui testing) might be a totally different environment
    • ruby capybara from outside the network?
  • Other types of tests (code coverage tests, etc)

See more information on configuring this file at: http://doc.gitlab.com/ci/yaml/README.html Take note! You can’t have \t tabs! Convert them to spaces. Otherwise you have problems. You can use the Gitlab Linter to check your file before submitting it. It’s basically like this:

# run before each script
before_script:
  - dnvm use 1.0.0-beta8 -r coreclr -a x64
  - dnu restore

stages:
  - test
  - deploy # more stages as needed

XUnit tests:
  stage: test
  script:
    - dnx test
  tags:
    - csharp
    - coreclr
  only:
    - master

integration tests:
  stage: test
  script:
    - capybara test # whatever
  tags:
    - capybara
  only:
    - master

deploy:
  stage: deploy
  script:
    - c:\this\is\just\CMD
    - # ftp somewhere?
    - # http git hook? whatever you want!