Skip to content

Commit 9114f39

Browse files
authored
Merge pull request #777 from fkie-cad/SD2049-rubocop-install-bugfix
fixed bug with rubocop linter installation in older systems
2 parents 47ed1c8 + 1f5276b commit 9114f39

File tree

5 files changed

+59
-44
lines changed

5 files changed

+59
-44
lines changed

src/plugins/analysis/linter/apt-pkgs-runtime.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@ liblua5.3-dev
22
lua5.3
33
luarocks
44
shellcheck
5-
ruby

src/plugins/analysis/linter/dnf-pkgs-runtime.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ lua-devel
33
luarocks
44
nodejs
55
ShellCheck
6-
ruby

src/plugins/analysis/linter/install.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python3
2+
# pylint: disable=ungrouped-imports
23

34
import logging
45
from pathlib import Path
@@ -22,19 +23,18 @@ def install_other_packages(self):
2223
run_cmd_with_logging('sudo luarocks install argparse')
2324
run_cmd_with_logging('sudo luarocks install luacheck')
2425
run_cmd_with_logging('sudo luarocks install luafilesystem')
25-
run_cmd_with_logging('sudo gem install rubocop')
2626

2727
def install_docker_images(self):
2828
run_cmd_with_logging('docker pull crazymax/linguist')
2929
run_cmd_with_logging('docker pull cytopia/eslint')
3030
run_cmd_with_logging('docker pull ghcr.io/phpstan/phpstan')
31+
run_cmd_with_logging('docker pull pipelinecomponents/rubocop')
3132

3233

3334
# Alias for generic use
3435
Installer = LinterInstaller
3536

3637
if __name__ == '__main__':
3738
logging.basicConfig(level=logging.INFO)
38-
distribution = check_distribution()
39-
installer = Installer(distribution)
39+
installer = Installer(distribution=check_distribution())
4040
installer.install()

src/plugins/analysis/linter/internal/linters.py

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import json
22
import logging
3-
import shlex
43
import subprocess
54
from pathlib import Path
6-
from subprocess import DEVNULL, PIPE, STDOUT
5+
from subprocess import PIPE, STDOUT
6+
from typing import List, Tuple
77

88
from docker.types import Mount
99

@@ -35,27 +35,28 @@ def run_eslint(file_path):
3535

3636
def run_shellcheck(file_path):
3737
shellcheck_process = subprocess.run(
38-
'shellcheck --format=json {}'.format(file_path),
38+
f'shellcheck --format=json {file_path}',
3939
shell=True,
4040
stdout=PIPE,
4141
stderr=STDOUT,
42+
check=False,
4243
universal_newlines=True,
4344
)
4445

4546
if shellcheck_process.returncode == 2:
46-
logging.debug('Failed to execute shellcheck:\n{}'.format(shellcheck_process.stdout))
47-
return list()
47+
logging.debug(f'Failed to execute shellcheck:\n{shellcheck_process.stdout}')
48+
return []
4849

4950
try:
5051
shellcheck_json = json.loads(shellcheck_process.stdout)
5152
except json.JSONDecodeError:
52-
return list()
53+
return []
5354

54-
return _shellcheck_extract_relevant_warnings(shellcheck_json)
55+
return _extract_shellcheck_warnings(shellcheck_json)
5556

5657

57-
def _shellcheck_extract_relevant_warnings(shellcheck_json):
58-
issues = list()
58+
def _extract_shellcheck_warnings(shellcheck_json):
59+
issues = []
5960
for issue in shellcheck_json:
6061
if issue['level'] in ['warning', 'error']:
6162
issues.append({
@@ -72,10 +73,11 @@ def run_luacheck(file_path):
7273
luacheckrc_path = Path(Path(__file__).parent, 'config', 'luacheckrc')
7374

7475
luacheck_process = subprocess.run(
75-
'luacheck -q --ranges --config {} {}'.format(luacheckrc_path, file_path),
76+
f'luacheck -q --ranges --config {luacheckrc_path} {file_path}',
7677
shell=True,
7778
stdout=PIPE,
7879
stderr=STDOUT,
80+
check=False,
7981
universal_newlines=True,
8082
)
8183
return _luacheck_parse_linter_output(luacheck_process.stdout)
@@ -86,11 +88,11 @@ def _luacheck_parse_linter_output(output):
8688
https://luacheck.readthedocs.io/en/stable/warnings.html
8789
ignore_cases = ['(W611)', '(W612)', '(W613)', '(W614)', '(W621)', '(W631)']
8890
'''
89-
issues = list()
91+
issues = []
9092
for line in output.splitlines():
9193
try:
9294
line_number, columns, code_and_message = _luacheck_split_issue_line(line)
93-
code, message = _luacheck_separate_message_and_code(code_and_message)
95+
code, message = _separate_message_and_code(code_and_message)
9496
if not code.startswith('(W6'):
9597
issues.append({
9698
'line': int(line_number),
@@ -100,8 +102,8 @@ def _luacheck_parse_linter_output(output):
100102
})
101103
else:
102104
pass
103-
except (IndexError, ValueError) as e:
104-
logging.warning('Lualinter failed to parse line: {}\n{}'.format(line, e))
105+
except (IndexError, ValueError) as error:
106+
logging.warning(f'Lualinter failed to parse line: {line}\n{error}')
105107

106108
return issues
107109

@@ -111,7 +113,7 @@ def _luacheck_split_issue_line(line):
111113
return split_by_colon[1], split_by_colon[2], ':'.join(split_by_colon[3:]).strip()
112114

113115

114-
def _luacheck_separate_message_and_code(message_string):
116+
def _separate_message_and_code(message_string: str) -> Tuple[str, str]:
115117
return message_string[1:5], message_string[6:].strip()
116118

117119

@@ -120,19 +122,26 @@ def _luacheck_get_first_column(columns):
120122

121123

122124
def run_pylint(file_path):
123-
pylint_process = subprocess.run('pylint --output-format=json {}'.format(file_path), shell=True, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
125+
pylint_process = subprocess.run(
126+
f'pylint --output-format=json {file_path}',
127+
shell=True,
128+
stdout=PIPE,
129+
stderr=STDOUT,
130+
check=False,
131+
universal_newlines=True
132+
)
124133

125134
try:
126135
pylint_json = json.loads(pylint_process.stdout)
127136
except json.JSONDecodeError:
128-
logging.warning('Failed to execute pylint:\n{}'.format(pylint_process.stdout))
129-
return list()
137+
logging.warning(f'Failed to execute pylint:\n{pylint_process.stdout}')
138+
return []
130139

131140
return _pylint_extract_relevant_warnings(pylint_json)
132141

133142

134143
def _pylint_extract_relevant_warnings(pylint_json):
135-
issues = list()
144+
issues = []
136145
for issue in pylint_json:
137146
if issue['type'] in ['error', 'warning']:
138147
for unnecessary_information in ['module', 'obj', 'path', 'message-id']:
@@ -141,27 +150,32 @@ def _pylint_extract_relevant_warnings(pylint_json):
141150
return issues
142151

143152

144-
def run_rubocop(file_path):
145-
rubocop_p = subprocess.run(
146-
shlex.split(f'rubocop --format json {file_path}'),
147-
stdout=PIPE,
148-
stderr=DEVNULL,
149-
check=False,
153+
def run_rubocop(file_path: str) -> List[dict]:
154+
container_path = '/input'
155+
process = run_docker_container(
156+
'pipelinecomponents/rubocop:latest',
157+
combine_stderr_stdout=False,
158+
mounts=[
159+
Mount(container_path, file_path, type='bind', read_only=True),
160+
],
161+
command=f'rubocop --format json -- {container_path}',
150162
)
151-
linter_output = json.loads(rubocop_p.stdout)
152-
153-
issues = []
154-
for offense in linter_output['files'][0]['offenses']:
155-
issues.append(
156-
{
157-
'symbol': offense['cop_name'],
158-
'line': offense['location']['start_line'],
159-
'column': offense['location']['column'],
160-
'message': offense['message'],
161-
}
162-
)
163163

164-
return issues
164+
try:
165+
linter_output = json.loads(process.stdout)
166+
except json.JSONDecodeError:
167+
logging.warning(f'Failed to execute rubocop linter:\n{process.stderr}')
168+
return []
169+
170+
return [
171+
{
172+
'symbol': offense['cop_name'],
173+
'line': offense['location']['start_line'],
174+
'column': offense['location']['column'],
175+
'message': offense['message'],
176+
}
177+
for offense in linter_output['files'][0]['offenses']
178+
]
165179

166180

167181
def run_phpstan(file_path):

src/plugins/analysis/linter/test/test_ruby_linter.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444

4545

4646
def test_do_analysis(monkeypatch):
47-
monkeypatch.setattr('plugins.analysis.linter.internal.linters.subprocess.run', lambda *_, **__: CompletedProcess('args', 0, stdout=MOCK_RESPONSE))
47+
monkeypatch.setattr(
48+
'plugins.analysis.linter.internal.linters.run_docker_container',
49+
lambda *_, **__: CompletedProcess('args', 0, stdout=MOCK_RESPONSE)
50+
)
4851
result = run_rubocop('any/path')
4952

5053
assert len(result) == 1

0 commit comments

Comments
 (0)