Ansible linting pre-commit

What is Linting?


What is a linter and why your team should use it? – SourceLevel

Linting is the process of automated checking of source code for programmatic, styling errors or any other unwanted form of ‘bad’ coding. As a good practice you should keep your code as tidy as possible and in a version system such as Git. Git has ‘hooks’. These hooks can be programmed to trigger scripts at certain actions such as pushing, pulling, or committing code. We will be focusing on the pre-commit hook. By using the pre-commit hook in a git repository that contains Ansible code, we can lint code before committing this. It will decline code by default when this does not pass this linting.

Installing pre-commit and Ansible pre-commit yaml.


The pre-commit software can be installed with apt, dnf or any other package system your Linux distro is using. This document will be using Debian.

$ sudo apt install pre-commit

Go to your Ansible git repository and type:

$ pre-commit install 

The result will be:

pre-commit installed at .git/hooks/pre-commit


Pre-commit is used for all kind of languages, so we need to configure two specific scripts and place them in the Ansible git repository to lint Ansible code. There are two files to be created: .pre-commit-config.yaml and .ansible-config.yaml. Don’t just take version v.5.1.3 for granted. Find the latest at https://github.com/ansible-community/ansible-lint/releases/ and configure this!

.pre-commit.config.yaml:

- repo: https://github.com/ansible-community/ansible-lint.git
  rev: v5.1.3  # put latest release tag from https://github.com/ansible-community/ansible-lint/releases/
  hooks:
    - id: ansible-lint
      files: \.(yaml|yml)$

.ansible-config:
This is a boilerplate script from https://ansible-lint.readthedocs.io/en/latest/configuring.html#pre-commit-setup

# .ansible-lint
exclude_paths:
  - .cache/  # implicit unless exclude_paths is defined in config
  - .github/
# parseable: true
# quiet: true
# verbosity: 1

# Mock modules or roles in order to pass ansible-playbook --syntax-check
mock_modules:
  - zuul_return
  # note the foo.bar is invalid as being neither a module or a collection
  - fake_namespace.fake_collection.fake_module
  - fake_namespace.fake_collection.fake_module.fake_submodule
mock_roles:
  - mocked_role
  - author.role_name  # old standalone galaxy role
  - fake_namespace.fake_collection.fake_role  # role within a collection

# Enable checking of loop variable prefixes in roles
loop_var_prefix: "{role}_"

# Enforce variable names to follow pattern below, in addition to Ansible own
# requirements, like avoiding python identifiers. To disable add `var-naming`
# to skip_list.
# var_naming_pattern: "^[a-z_][a-z0-9_]*$"

use_default_rules: true
# Load custom rules from this specific folder
# rulesdir:
#   - ./rule/directory/

# This makes linter to fully ignore rules/tags listed below
skip_list:
  - skip_this_tag
  - git-latest

# Any rule that has the 'opt-in' tag will not be loaded unless its 'id' is
# mentioned in the enable_list:
enable_list:
  - fqcn-builtins  # opt-in
  - no-log-password  # opt-in
  - no-same-owner  # opt-in
  # add yaml here if you want to avoid ignoring yaml checks when yamllint
  # library is missing. Normally its absence just skips using that rule.
  - yaml
# Report only a subset of tags and fully ignore any others
# tags:
#   - var-spacing

# This makes the linter display but not fail for rules/tags listed below:
warn_list:
  - skip_this_tag
  - git-latest
  - experimental  # experimental is included in the implicit list
  # - role-name

# Offline mode disables installation of requirements.yml
offline: false

# Define required Ansible's variables to satisfy syntax check
extra_vars:
  foo: bar
  multiline_string_variable: |
    line1
    line2
  complex_variable: ":{;\t$()"

Commit the two config files and let the linting begin!

git add .ansible-lint
git add .pre-commit-config.yaml
git commit -m "Let the linting begin"

Some notes

Linting an existing repository can be an overwhelming process. Best is to start from nothing or to fork the repository and work your way from there. If you decide that linting isn’t for you the process to remove linting and the pre-commit hook is as followed:

pre-commit uninstall
rm .ansible-lint
rm .pre-commit-config.yaml