mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-06 12:44:23 +08:00
add: support project-local ansible-lint (#5015)
Add support for project-local `ansible-lint` (via `uv`, `poetry`, and `pipenv`) when using the system-wide installed one is not possible or not desirable.
This commit is contained in:
@@ -2,11 +2,44 @@
|
|||||||
" Description: ansible-lint for ansible-yaml files
|
" Description: ansible-lint for ansible-yaml files
|
||||||
|
|
||||||
call ale#Set('ansible_ansible_lint_executable', 'ansible-lint')
|
call ale#Set('ansible_ansible_lint_executable', 'ansible-lint')
|
||||||
|
call ale#Set('ansible_ansible_lint_auto_pipenv', 0)
|
||||||
|
call ale#Set('ansible_ansible_lint_auto_poetry', 0)
|
||||||
|
call ale#Set('ansible_ansible_lint_auto_uv', 0)
|
||||||
|
call ale#Set('ansible_ansible_lint_change_directory', 1)
|
||||||
|
|
||||||
function! ale_linters#ansible#ansible_lint#GetExecutable(buffer) abort
|
function! ale_linters#ansible#ansible_lint#GetExecutable(buffer) abort
|
||||||
|
if (ale#Var(a:buffer, 'python_auto_pipenv')
|
||||||
|
\ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_pipenv'))
|
||||||
|
\ && ale#python#PipenvPresent(a:buffer)
|
||||||
|
return 'pipenv'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (ale#Var(a:buffer, 'python_auto_poetry')
|
||||||
|
\ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_poetry'))
|
||||||
|
\ && ale#python#PoetryPresent(a:buffer)
|
||||||
|
return 'poetry'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (ale#Var(a:buffer, 'python_auto_uv')
|
||||||
|
\ || ale#Var(a:buffer, 'ansible_ansible_lint_auto_uv'))
|
||||||
|
\ && ale#python#UvPresent(a:buffer)
|
||||||
|
return 'uv'
|
||||||
|
endif
|
||||||
|
|
||||||
return ale#Var(a:buffer, 'ansible_ansible_lint_executable')
|
return ale#Var(a:buffer, 'ansible_ansible_lint_executable')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! ale_linters#ansible#ansible_lint#GetCwd(buffer) abort
|
||||||
|
if ale#Var(a:buffer, 'ansible_ansible_lint_change_directory')
|
||||||
|
" Run from project root if found, else from buffer dir.
|
||||||
|
let l:project_root = ale#python#FindProjectRoot(a:buffer)
|
||||||
|
|
||||||
|
return !empty(l:project_root) ? l:project_root : '%s:h'
|
||||||
|
endif
|
||||||
|
|
||||||
|
return ''
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
|
function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
|
||||||
for l:line in a:lines[:10]
|
for l:line in a:lines[:10]
|
||||||
if match(l:line, '^Traceback') >= 0
|
if match(l:line, '^Traceback') >= 0
|
||||||
@@ -103,28 +136,50 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort
|
function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort
|
||||||
let l:commands = {
|
let l:executable = ale_linters#ansible#ansible_lint#GetExecutable(a:buffer)
|
||||||
\ '>=6.0.0': '%e --nocolor -f json -x yaml %s',
|
|
||||||
\ '>=5.0.0': '%e --nocolor --parseable-severity -x yaml %s',
|
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
|
||||||
\ '<5.0.0': '%e --nocolor -p %t'
|
\ ? ' run ansible-lint'
|
||||||
|
\ : ''
|
||||||
|
|
||||||
|
let l:opts_map = {
|
||||||
|
\ '>=6.0.0': ' --nocolor -f json -x yaml %s',
|
||||||
|
\ '>=5.0.0': ' --nocolor --parseable-severity -x yaml %s',
|
||||||
|
\ '<5.0.0': ' --nocolor -p %t'
|
||||||
\}
|
\}
|
||||||
let l:command = ale#semver#GTE(a:version, [6, 0]) ? l:commands['>=6.0.0'] :
|
|
||||||
\ ale#semver#GTE(a:version, [5, 0]) ? l:commands['>=5.0.0'] :
|
let l:cmd_opts = ale#semver#GTE(a:version, [6, 0]) ? l:opts_map['>=6.0.0'] :
|
||||||
\ l:commands['<5.0.0']
|
\ ale#semver#GTE(a:version, [5, 0]) ? l:opts_map['>=5.0.0'] :
|
||||||
|
\ l:opts_map['<5.0.0']
|
||||||
|
|
||||||
|
let l:command = ale#Escape(l:executable) . l:exec_args . l:cmd_opts
|
||||||
|
|
||||||
return l:command
|
return l:command
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! ale_linters#ansible#ansible_lint#RunWithVersionCheck(buffer) abort
|
||||||
|
let l:executable = ale_linters#ansible#ansible_lint#GetExecutable(a:buffer)
|
||||||
|
|
||||||
|
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
|
||||||
|
\ ? ' run ansible-lint'
|
||||||
|
\ : ''
|
||||||
|
|
||||||
|
let l:command = ale#Escape(l:executable) . l:exec_args . ' --version'
|
||||||
|
|
||||||
|
return ale#semver#RunWithVersionCheck(
|
||||||
|
\ a:buffer,
|
||||||
|
\ l:executable,
|
||||||
|
\ l:command,
|
||||||
|
\ function('ale_linters#ansible#ansible_lint#GetCommand'),
|
||||||
|
\)
|
||||||
|
endfunction
|
||||||
|
|
||||||
call ale#linter#Define('ansible', {
|
call ale#linter#Define('ansible', {
|
||||||
\ 'name': 'ansible_lint',
|
\ 'name': 'ansible_lint',
|
||||||
\ 'aliases': ['ansible', 'ansible-lint'],
|
\ 'aliases': ['ansible', 'ansible-lint'],
|
||||||
\ 'executable': function('ale_linters#ansible#ansible_lint#GetExecutable'),
|
\ 'executable': function('ale_linters#ansible#ansible_lint#GetExecutable'),
|
||||||
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
|
\ 'cwd': function('ale_linters#ansible#ansible_lint#GetCwd'),
|
||||||
\ buffer,
|
\ 'command': function('ale_linters#ansible#ansible_lint#RunWithVersionCheck'),
|
||||||
\ ale_linters#ansible#ansible_lint#GetExecutable(buffer),
|
|
||||||
\ '%e --version',
|
|
||||||
\ function('ale_linters#ansible#ansible_lint#GetCommand'),
|
|
||||||
\ )},
|
|
||||||
\ 'lint_file': 1,
|
\ 'lint_file': 1,
|
||||||
\ 'callback': {buffer, lines -> ale#semver#RunWithVersionCheck(
|
\ 'callback': {buffer, lines -> ale#semver#RunWithVersionCheck(
|
||||||
\ buffer,
|
\ buffer,
|
||||||
|
|||||||
@@ -44,5 +44,39 @@ g:ale_ansible_ansible_lint_executable
|
|||||||
This variable can be changed to modify the executable used for ansible-lint.
|
This variable can be changed to modify the executable used for ansible-lint.
|
||||||
|
|
||||||
|
|
||||||
|
*ale-options.ansible_ansible_lint_auto_pipenv*
|
||||||
|
*g:ale_ansible_ansible_lint_auto_pipenv*
|
||||||
|
*b:ale_ansible_ansible_lint_auto_pipenv*
|
||||||
|
ansible_ansible_lint_auto_pipenv
|
||||||
|
g:ale_ansible_ansible_lint_auto_pipenv
|
||||||
|
Type: |Number|
|
||||||
|
Default: `0`
|
||||||
|
|
||||||
|
Detect whether the file is inside a pipenv, and set the executable to `pipenv`
|
||||||
|
if true. This is overridden by a manually-set executable.
|
||||||
|
|
||||||
|
*ale-options.ansible_ansible_lint_auto_poetry*
|
||||||
|
*g:ale_ansible_ansible_lint_auto_poetry*
|
||||||
|
*b:ale_ansible_ansible_lint_auto_poetry*
|
||||||
|
ansible_ansible_lint_auto_poetry
|
||||||
|
g:ale_ansible_ansible_lint_auto_poetry
|
||||||
|
Type: |Number|
|
||||||
|
Default: `0`
|
||||||
|
|
||||||
|
Detect whether the file is inside a poetry, and set the executable to `poetry`
|
||||||
|
if true. This is overridden by a manually-set executable.
|
||||||
|
|
||||||
|
*ale-options.ansible_ansible_lint_auto_uv*
|
||||||
|
*g:ale_ansible_ansible_lint_auto_uv*
|
||||||
|
*b:ale_ansible_ansible_lint_auto_uv*
|
||||||
|
ansible_ansible_lint_auto_uv
|
||||||
|
g:ale_ansible_ansible_lint_auto_uv
|
||||||
|
Type: |Number|
|
||||||
|
Default: `0`
|
||||||
|
|
||||||
|
Set the executable to `uv` if true. This is overridden by a manually-set
|
||||||
|
executable.
|
||||||
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||||
|
|||||||
@@ -24,3 +24,28 @@ Execute(The ansible_lint executable should be configurable):
|
|||||||
GivenCommandOutput ['v4.1.2']
|
GivenCommandOutput ['v4.1.2']
|
||||||
AssertLinter '~/.local/bin/ansible-lint',
|
AssertLinter '~/.local/bin/ansible-lint',
|
||||||
\ ale#Escape('~/.local/bin/ansible-lint') . ' --nocolor -p %t'
|
\ ale#Escape('~/.local/bin/ansible-lint') . ' --nocolor -p %t'
|
||||||
|
|
||||||
|
Execute(pipenv is detected when ansible_ansible_lint_auto_pipenv is set):
|
||||||
|
let g:ale_ansible_ansible_lint_auto_pipenv = 1
|
||||||
|
call ale#test#SetFilename('../test-files/ansible/pipenv/script.yml')
|
||||||
|
|
||||||
|
GivenCommandOutput ['v25.6.1']
|
||||||
|
AssertLinterCwd expand('%:p:h')
|
||||||
|
AssertLinter 'pipenv', ale#Escape('pipenv') . ' run ansible-lint --nocolor -f json -x yaml %s'
|
||||||
|
|
||||||
|
Execute(poetry is detected when ansible_ansible_lint_auto_poetry is set):
|
||||||
|
let g:ale_ansible_ansible_lint_auto_poetry = 1
|
||||||
|
call ale#test#SetFilename('../test-files/ansible/poetry/script.yml')
|
||||||
|
|
||||||
|
GivenCommandOutput ['v25.6.1']
|
||||||
|
AssertLinterCwd expand('%:p:h')
|
||||||
|
AssertLinter 'poetry', ale#Escape('poetry') . ' run ansible-lint --nocolor -f json -x yaml %s'
|
||||||
|
|
||||||
|
Execute(uv is detected when ansible_ansible_lint_auto_uv is set):
|
||||||
|
let g:ale_ansible_ansible_lint_auto_uv = 1
|
||||||
|
call ale#test#SetFilename('../test-files/ansible/uv/script.yml')
|
||||||
|
|
||||||
|
GivenCommandOutput ['v25.6.1']
|
||||||
|
AssertLinterCwd expand('%:p:h')
|
||||||
|
AssertLinter 'uv', ale#Escape('uv') . ' run ansible-lint --nocolor -f json -x yaml %s'
|
||||||
|
|
||||||
|
|||||||
0
test/test-files/ansible/pipenv/Pipfile.lock
generated
Normal file
0
test/test-files/ansible/pipenv/Pipfile.lock
generated
Normal file
0
test/test-files/ansible/poetry/poetry.lock
generated
Normal file
0
test/test-files/ansible/poetry/poetry.lock
generated
Normal file
0
test/test-files/ansible/uv/uv.lock
generated
Normal file
0
test/test-files/ansible/uv/uv.lock
generated
Normal file
Reference in New Issue
Block a user