Skip to content

Commit

Permalink
Dockerlinter (#4518)
Browse files Browse the repository at this point in the history
* dockerlinter support

* Tests & ShellCheck reference

* sort and align docs
  • Loading branch information
shadowwa authored May 22, 2023
1 parent 5c803fb commit a46121a
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 0 deletions.
69 changes: 69 additions & 0 deletions ale_linters/dockerfile/dockerlinter.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
" Author: Shad
" Description: dockerlinter linter for dockerfile

call ale#Set('dockerfile_dockerlinter_executable', 'dockerlinter')
call ale#Set('dockerfile_dockerlinter_options', '')

function! ale_linters#dockerfile#dockerlinter#GetType(type) abort
if a:type is? 'error'
return 'E'
elseif a:type is? 'warning'
return 'W'
endif

return 'I'
endfunction

function! ale_linters#dockerfile#dockerlinter#Handle(buffer, lines) abort
try
let l:data = json_decode(join(a:lines, ''))
catch
return []
endtry

if empty(l:data)
" Should never happen, but it's better to be on the safe side
return []
endif

let l:messages = []

for l:object in l:data
let l:line = get(l:object, 'lineNumber', -1)
let l:message = l:object['message']
let l:type = l:object['level']
let l:detail = l:message
let l:code = l:object['code']

if l:code =~# '^SC'
let l:link = 'https://www.shellcheck.net/wiki/' . l:code
else
let l:link = 'https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md#' . l:code
endif

let l:detail = l:message . "\n\n" . l:link

call add(l:messages, {
\ 'lnum': l:line,
\ 'code': l:code,
\ 'text': l:message,
\ 'type': ale_linters#dockerfile#dockerlinter#GetType(l:type),
\ 'detail': l:detail,
\})
endfor

return l:messages
endfunction

function! ale_linters#dockerfile#dockerlinter#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'dockerfile_dockerlinter_options'))
\ . ' -j -f'
\ . ' %t'
endfunction

call ale#linter#Define('dockerfile', {
\ 'name': 'dockerlinter',
\ 'executable': {b -> ale#Var(b, 'dockerfile_dockerlinter_executable')},
\ 'command': function('ale_linters#dockerfile#dockerlinter#GetCommand'),
\ 'callback': 'ale_linters#dockerfile#dockerlinter#Handle',
\})
25 changes: 25 additions & 0 deletions doc/ale-dockerfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ g:ale_dockerfile_dockerfile_lint_options
the dockerfile lint invocation - like custom rule file definitions.


===============================================================================
dockerlinter *ale-dockerfile-dockerlinter*

g:ale_dockerfile_dockerlinter_executable
*g:ale_dockerfile_dockerlinter_executable*
*b:ale_dockerfile_dockerlinter_executable*
Type: |String|
Default: `'dockerlinter'`

This variable can be changed to specify the executable used to run
dockerlinter.


g:ale_dockerfile_dockerlinter_options
*g:ale_dockerfile_dockerlinter_options*
*b:ale_dockerfile_dockerlinter_options*
Type: |String|
Default: `''`

This variable can be changed to add additional command-line arguments to
the dockerfile lint invocation - like custom rule file definitions.

dockerlinter


===============================================================================
dprint *ale-dockerfile-dprint*

Expand Down
1 change: 1 addition & 0 deletions doc/ale-supported-languages-and-tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ Notes:
* `dhall-lint`
* Dockerfile
* `dockerfile_lint`
* `dockerlinter`
* `dprint`
* `hadolint`
* Elixir
Expand Down
1 change: 1 addition & 0 deletions doc/ale.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,7 @@ documented in additional help files.
dhall-lint............................|ale-dhall-lint|
dockerfile..............................|ale-dockerfile-options|
dockerfile_lint.......................|ale-dockerfile-dockerfile_lint|
dockerlinter..........................|ale-dockerfile-dockerlinter|
dprint................................|ale-dockerfile-dprint|
hadolint..............................|ale-dockerfile-hadolint|
elixir..................................|ale-elixir-options|
Expand Down
1 change: 1 addition & 0 deletions supported-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ formatting.
* [dhall-lint](https://github.com/dhall-lang/dhall-lang)
* Dockerfile
* [dockerfile_lint](https://github.com/projectatomic/dockerfile_lint)
* [dockerlinter](https://github.com/buddy-works/dockerfile-linter)
* [dprint](https://dprint.dev)
* [hadolint](https://github.com/hadolint/hadolint)
* Elixir
Expand Down
77 changes: 77 additions & 0 deletions test/handler/test_dockerlinter_handler.vader
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
Before:
runtime ale_linters/dockerfile/dockerlinter.vim

After:
call ale#linter#Reset()

Execute(The dockerlinter handler should handle broken JSON):
AssertEqual
\ [],
\ ale_linters#dockerfile#dockerlinter#Handle(bufnr(''), ["{asdf"])

Execute(The dockerlinter handler should handle an empty string response):
AssertEqual
\ [],
\ ale_linters#dockerfile#dockerlinter#Handle(bufnr(''), [])

Execute(The dockerlinter handler should handle an empty result, even if it shouldn't happen):
AssertEqual
\ [],
\ ale_linters#dockerfile#dockerlinter#Handle(bufnr(''), ["{}"])

Execute(The dockerlinter handler should handle a normal example):
AssertEqual
\ [
\ {
\ 'lnum': 11,
\ 'type': 'I',
\ 'code': 'ER0002',
\ 'text': "Delete the apt-get lists after installing something",
\ 'detail': "Delete the apt-get lists after installing something\n\nhttps://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md#ER0002",
\ },
\ {
\ 'lnum': 11,
\ 'type': 'I',
\ 'code': 'ER0010',
\ 'text': "Avoid additional packages by specifying --no-install-recommends",
\ 'detail': "Avoid additional packages by specifying --no-install-recommends\n\nhttps://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md#ER0010",
\ },
\ {
\ 'lnum': 11,
\ 'type': 'I',
\ 'code': 'ER0012',
\ 'text': "Pin versions in apt get install",
\ 'detail': "Pin versions in apt get install\n\nhttps://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md#ER0012",
\ },
\ {
\ 'lnum': 30,
\ 'type': 'W',
\ 'code': 'SC2155',
\ 'text': "Declare and assign separately to avoid masking return values.",
\ 'detail': "Declare and assign separately to avoid masking return values.\n\nhttps://www.shellcheck.net/wiki/SC2155",
\ },
\ {
\ 'lnum': 30,
\ 'type': 'W',
\ 'code': 'SC2046',
\ 'text': "Quote this to prevent word splitting.",
\ 'detail': "Quote this to prevent word splitting.\n\nhttps://www.shellcheck.net/wiki/SC2046",
\ },
\ {
\ 'lnum': 30,
\ 'type': 'I',
\ 'code': 'SC2086',
\ 'text': "Double quote to prevent globbing and word splitting.",
\ 'detail': "Double quote to prevent globbing and word splitting.\n\nhttps://www.shellcheck.net/wiki/SC2086",
\ },
\ {
\ 'lnum': 31,
\ 'type': 'W',
\ 'code': 'SC2046',
\ 'text': "Quote this to prevent word splitting.",
\ 'detail': "Quote this to prevent word splitting.\n\nhttps://www.shellcheck.net/wiki/SC2046",
\ },
\ ],
\ ale_linters#dockerfile#dockerlinter#Handle(bufnr(''), [
\ '[{"lineNumber":11,"message":"Delete the apt-get lists after installing something","level":"info","code":"ER0002"},{"lineNumber":11,"message":"Avoid additional packages by specifying --no-install-recommends","level":"info","code":"ER0010"},{"lineNumber":11,"message":"Pin versions in apt get install","level":"info","code":"ER0012"},{"lineNumber":30,"message":"Declare and assign separately to avoid masking return values.","level":"warning","code":"SC2155"},{"lineNumber":30,"message":"Quote this to prevent word splitting.","level":"warning","code":"SC2046"},{"lineNumber":30,"message":"Double quote to prevent globbing and word splitting.","level":"info","code":"SC2086"},{"lineNumber":31,"message":"Quote this to prevent word splitting.","level":"warning","code":"SC2046"}]',
\ ])
19 changes: 19 additions & 0 deletions test/linter/test_dockerlinter.vader
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Before:
call ale#assert#SetUpLinterTest('dockerfile', 'dockerlinter')

After:
call ale#assert#TearDownLinterTest()

Execute(The default command should be correct):
AssertLinter 'dockerlinter', ale#Escape('dockerlinter') . ' -j -f %t'

Execute(The executable should be configurable):
let b:ale_dockerfile_dockerlinter_executable = 'foobar'

AssertLinter 'foobar', ale#Escape('foobar') . ' -j -f %t'

Execute(The options should be configurable):
let b:ale_dockerfile_dockerlinter_options = '-r additional.yaml'

AssertLinter 'dockerlinter', ale#Escape('dockerlinter') . ' -r additional.yaml -j -f %t'

0 comments on commit a46121a

Please sign in to comment.