Continuous Integration pipelines are a fantastic tools to leverage in application testing and fortunately Gitlab comes with built-in Continuous Integration support. Unfortunately, tests don’t always run the same locally as they do in CI builds, and a failed test in a CI pipeline can be difficult to debug when you’re seeing different results locally. Instead of making incremental changes to your code and praying the next CI build passes, you can leverage Gitlab runners to run CI builds locally and speed up the debugging process.
This article assumes you already have Gitlab CI set up for your project. If not, take a look at the getting started guide, or look at this guide for more information on what Gitlab CI is and how it works.
To execute CI jobs, Gitlab uses Runners. You can think of Gitlab Runners as individual computers that execute the jobs in your .gitlab-ci.yml file. It’s assumed in this guide that you already have a dedicated Runner set up and connected with your project. Instead we’ll be installing a Gitlab Runner on your local machine in order to debug CI problems locally. I’ve highlighted the steps for installing a Runner on a Mac or Linux machine below, but feel free to refer back to the official guide which contains some additional details that aren’t necessary for our setup.
Installing a Gitlab Runner on MacOS
$ sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64 $ sudo chmod +x /usr/local/bin/gitlab-runner
Installing a Gitlab Runner on Linux
$curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash $sudo apt-get install gitlab-runner
Installing a Gitlab Runner on Windows
The setup process is a bit more detailed for Windows users, but can be found here.
Make sure Gitlab Runner is working
depending if the runner was installed on a Linux or Mac/Windows system.
You should see output like this:
NAME: gitlab-ci-multi-runner - a GitLab Runner USAGE: gitlab-ci-multi-runner [global options] command [command options] [arguments...] VERSION: 9.5.0 (413da38) AUTHOR(S): GitLab Inc. <email@example.com> COMMANDS: exec execute a build locally ... GLOBAL OPTIONS: --debug debug mode [$DEBUG] ...
Using gitlab-runner to run a job locally
Assuming you already have a
.gitlab-ci.yml file that looks something like this:
image: node:latest Build: stage: build script: - docker build . Unit-Tests: stage: test script: - npm install - npm test
You can run the Unit-Tests job with:
$ cd path/to/project $ gitlab-runner exec docker Unit-Tests
Things to know
- Your local changes must be committed to git or they won’t be available to gitlab-runner. Because of this, I find it useful to use
$ git reset — soft HEAD~1which will unstage the last commit(s) made when debugging CI issues until the issue is resolved.
- You may need to use
dockerif running on MacOS or Windows. In that case, our command would be
gitlab-runner exec shell Unit-Testsfor this example.
- You can run any of the jobs defined in your
.gitlab-ci.ymlfile locally but not all at one, you’ll have to specify which job to run each time. For example, you can run either the Build or Unit-Tests stage but the gitlab-runner won’t run them both in one command.
- The cache and artifacts in your
.gitlab-ci.ymlwon’t work with the gitlab-runner exec docker command.
- I recommend running gitlab-runner locally any time you’re setting up a new .gitlab-ci.yml or making any modifications to it. It can save hours in debugging time when it comes to catching errors in your shell scripts and finding discrepancies between your local testing environment and the one on the Gitlab Runner.