Ansible-lint autodetect and git CI

Hello,
I have a problem with ansible-lint and its mode to discover paths.

In my develop environment all it’s working fine. I enter the role or collection path, I run ansible-lint and I see the results of the role or the collection checks.

It’s exciting and I decided to add ansible-lint to my CI environment too :slightly_smiling_face: Ie:

[...]
test_job:
  stage: test
  script:
    - ansible-playbook -i /etc/ansible/hosts/main_docker.yml tests/test.yml --syntax-check
    - ansible-lint
    - ansible-playbook -i /etc/ansible/hosts/main_docker.yml tests/test.yml

Here when I run ansible-lint I see a lot of errors because the paths are not well detected.
If I run the lint on a role inside a collection, the role is threated as a standalone role, and all collections and roles are checked.

So I run ansible-lint in verbose mode and I noticed that the problem is:

# ansible-lint -v
INFO     Identified / as project root due file system root.

Even if I add a path, the project root is always “/”:

# cd ..
# ansible-lint -v mycollection/
INFO     Identified / as project root due file system root.

Ps: the ansible-lint docs says

positional arguments:
 lintables             One or more files or paths. When missing it will enable auto-detection mode.

but it seems that it’s not really true, or I don’t understand something, because the discovering path process starts even if I specify a path.

In my develop environment the difference is that the collection is a git project (internal roles are git submodules), so all is working as expected:

# cd <my collection path>
# ansible-lint -v
INFO     Identified /root/.ansible/collections/ansible_collections/<namespace>/<name> as project root due .git directory.

In my CI environment with gitlab pipelines I don’t have the .git directories and ansible-lint always starts checking from “/”.

I’m a little confused about this behaviour. I wonder how to avoid this problem, or I wonder what the best workaround to solve this would be.

Do you have any hints?

The ansible-lint version is the last:

ansible-lint 24.2.0 using ansible-core:2.16.2 ansible-compat:4.1.11 ruamel-yaml:0.18.5 ruamel-yaml-clib:0.2.8

Thank you very much
Kind Regards

Marco

This probably doesn’t help as I’m only using GitLab CI with roles and not collections but I have found that using pre-commit to run ansible-lint works quite well, for example in .gitlab-ci.yml:


---
variables:
  PRE_COMMIT_COLOR: always
  PY_COLORS: "1"
stages:
  - lint
lint:
  script:
    - pre-commit install
    - pre-commit run --all-files
...

In .pre-commit-config.yaml I use something like this:

---
repos:
  # https://github.com/adrienverge/yamllint/tags
  - repo: https://github.com/adrienverge/yamllint.git
    rev: v1.34.0
    hooks:
      - id: yamllint
        name: YAML Lint
  # https://github.com/aristanetworks/j2lint/releases
  - repo: https://github.com/aristanetworks/j2lint.git
    rev: v1.1.0
    hooks:
      - id: j2lint
        name: Jinja2-Linter
        args:
          - templates
  # https://github.com/jackdewinter/pymarkdown/releases
  - repo: https://github.com/jackdewinter/pymarkdown.git
    rev: 0.9.16
    hooks:
      - id: pymarkdown
        name: Markdown Lint
        args:
          - scan
          - README.md
          - VARIABLES.md
  # https://github.com/ansible/ansible-lint/releases
  - repo: https://github.com/ansible/ansible-lint.git
    rev: v24.2.0
    hooks:
      - id: ansible-lint
        name: Ansible Lint
        language: python
        additional_dependencies:
          # https://github.com/kellyjonbrazil/jc/releases
          - jc==1.25.0
          # https://github.com/jmespath/jmespath.py/tags
          - jmespath==1.0.1
...
1 Like

Hello Chris,

thank you for sharing this and for this hint.
I already use pre-commit with ansible-lint in git.
My hope is to have the pre-commit result aligned with the ansible-lint result in CI.

Why?

CI could be a redundant check, I know. But there are also some circumstances where the CI test could capture untested contributions. Such as pull request. I can’t be sure that all developers use pre-commit, in a scenario with many developers or multiple development environments.

Thank you
Kind Regards
Marco

2 Likes

I’ve found a workaround, but I don’t understand where is the problem.

Resume: I want to lint a role inside a collection. In develop ansible-lint knows that it’s a role inside a collection:

# cd /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename
# ansible-lint -v
INFO     Identified /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename as project root due .git directory.
INFO     Set ANSIBLE_LIBRARY=/root/.cache/ansible-compat/124193/modules:/root/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/root/.cache/ansible-compat/124193/collections:/root/.ansible/collections:/usr/share/ansible/collections:/usr/local/lib/python3.11/site-packages
INFO     Set ANSIBLE_ROLES_PATH=/root/.cache/ansible-compat/124193/roles:/root/.ansible/roles
INFO     Running from /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename : ansible-galaxy collection install -vvv --force ../..
INFO     Excluded: .git

In CI the workaround is the following. I install the collection and I add a fake .git folder:

before_script:
  - ansible-galaxy collection install namespace.name
  - rm -rf /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename
  - cp -pr ../rolename  /root/.ansible/collections/ansible_collections/namespace/name/roles/
  # Add fake .git folder:
  - mkdir /root/.ansible/collections/ansible_collections/namespace/name/.git

In this way ansible-lint doesn’t fail the whole collection lint, but it still fails if it runs inside the folder role:

# cd /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename
# ansible-lint -v
INFO     Identified /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename as project root due .git directory.
INFO     Set ANSIBLE_LIBRARY=/root/.cache/ansible-compat/124193/modules:/root/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/root/.cache/ansible-compat/124193/collections:/root/.ansible/collections:/usr/share/ansible/collections:/usr/local/lib/python3.11/site-packages
INFO     Set ANSIBLE_ROLES_PATH=/root/.cache/ansible-compat/124193/roles:/root/.ansible/roles
ERROR    Computed fully qualified role name of rolename does not follow current galaxy requirements.
Please edit meta/main.yml and assure we can correctly determine full role name:

galaxy_info:
role_name: my_name  # if absent directory name hosting role is used instead
namespace: my_galaxy_namespace  # if absent, author is used instead

It’s missing the line

INFO     Running from /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename : ansible-galaxy collection install -vvv --force ../..

I have to do this in order to work:

# cd  /root/.ansible/collections/ansible_collections/namespace/name/roles
# ansible-lint -v rolename
INFO     Identified /root/.ansible/collections/ansible_collections/namespace/name/roles/rolename as project root due .git directory.
INFO     Set ANSIBLE_LIBRARY=/root/.cache/ansible-compat/66cf55/modules:/root/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/root/.cache/ansible-compat/66cf55/collections:/root/.ansible/collections:/usr/share/ansible/collections:/usr/local/lib/python3.11/site-packages
INFO     Set ANSIBLE_ROLES_PATH=/root/.cache/ansible-compat/66cf55/roles:/root/.ansible/roles
INFO     Excluded: rolename/.git
INFO     Set ANSIBLE_LIBRARY=/root/.cache/ansible-compat/66cf55/modules:/root/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/root/.cache/ansible-compat/66cf55/collections:/root/.ansible/collections:/usr/share/ansible/collections:/usr/local/lib/python3.11/site-packages
INFO     Set ANSIBLE_ROLES_PATH=/root/.cache/ansible-compat/66cf55/roles:/root/.ansible/roles
INFO     Executing syntax check on role rolename (0.64s)
INFO     Executing syntax check on playbook rolename/tests/test.yml (0.72s)

Passed: 0 failure(s), 0 warning(s) on 52 files. Last profile that met the validation criteria was 'production'.

I don’t know if the problem could be somewhere here, where ansible notices if the role is inside a collection.

Warm Regards
Marco

2 Likes