ansible-lint on gitlab-ci

February 24, 2021

As ansible-lint checks playbooks and roles for common problems and possible improvements we will explore how to run the linter on top of Gitlab CI.

I prefer containers as CI tasks should produce idempotent results. This way one can use different linting runtimes on many projects while offering great flexibility without modifying the base OS. As ansible-lint is written in Python we need a python-runtime. The resulting linter image can be reused and therefore the build time decreases drastically. The gitlab docs describe the runner installation and registration process in depth.

A first approach

By using the python3 slim base image one can define a basic gitlab CI-configuration like this:

.gitlab-ci.yml – draft, do not use

image: python:3-slim

  - pip install ansible-lint
  - ansible-lint --version

  - ansible-lint

  stage: ansible-lint
    - ansible-lint site.yml

Not bad, but this approach has two problems:
As the version of ansible-lint is still unconfigured package updates could cause issues you do not want to deal with regularly. The base image is updated very frequently. So by not configuring any base image version this would create a lot of different images wasting precious disk space.

Creating a custom docker image

I’ve based my docker image on the popular python3 slim image available on docker hub (running debian buster under the hood). So let’s create a docker image.


FROM python:3-slim


RUN pip install ansible-lint==$ANSIBLE_LINT_VERSION ansible==$ANSIBLE_VERSION

As you can see both versions are configured by environment variables while I keep the ansible version always in sync with my locally used version. I’m using a private docker registry so whenever this Dockerfile changes it’s rebuilt by the CI and pushed again.

docker image .gitlab-ci.yml

  stage: deploy
    - shell
    - export BUILD_VERSION=$(date +%s)
    - docker build -t$BUILD_VERSION .
    - docker tag$BUILD_VERSION
    - docker push$BUILD_VERSION
    - docker push

The image is always tagged twice, by a timestamp and as latest version. The final gitlab-CI configuration I ended up looks like this:



  - ansible-lint

  stage: ansible-lint
    - ansible-lint -L
    - ansible-lint -r ./ site.yml

ansible-lint -L is executed first to list all available rules.

Photo by Sam Moqadam on Unsplash

Leave a comment