Add support for SARIF format

Signed-off-by: Mathieu Rul <mathroule@gmail.com>
pull/579/head
Mathieu Rul 2 years ago
parent ea560f0fb4
commit 73e8798369
No known key found for this signature in database
GPG Key ID: 80FEB484670CEF0E

@ -22,7 +22,7 @@ import sys
from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
from yamllint import linter from yamllint import linter
from yamllint.config import YamlLintConfig, YamlLintConfigError from yamllint.config import YamlLintConfig, YamlLintConfigError
from yamllint.formatters import colored, github, parsable, standard from yamllint.formatters import colored, github, parsable, sarif, standard
from yamllint.linter import PROBLEM_LEVELS from yamllint.linter import PROBLEM_LEVELS
@ -59,6 +59,8 @@ def show_results(results, args_format, no_warn):
return parsable.format_results(results, no_warn) return parsable.format_results(results, no_warn)
elif args_format == 'github': elif args_format == 'github':
return github.format_results(results, no_warn) return github.format_results(results, no_warn)
elif args_format == 'sarif':
return sarif.format_results(results, no_warn)
elif args_format == 'colored': elif args_format == 'colored':
return colored.format_results(results, no_warn) return colored.format_results(results, no_warn)
else: else:
@ -98,7 +100,7 @@ def run(argv=None):
help='list files to lint and exit') help='list files to lint and exit')
parser.add_argument('-f', '--format', parser.add_argument('-f', '--format',
choices=('parsable', 'standard', 'colored', 'github', choices=('parsable', 'standard', 'colored', 'github',
'auto'), 'sarif', 'auto'),
default='auto', help='format for parsing output') default='auto', help='format for parsing output')
parser.add_argument('-s', '--strict', parser.add_argument('-s', '--strict',
action='store_true', action='store_true',

@ -0,0 +1,113 @@
# Copyright (C) 2016 Adrien Vergé
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
from yamllint import APP_VERSION
from yamllint.linter import PROBLEM_LEVELS
def format_results(results, no_warn):
max_level = 0
sarif = {
'$schema': 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
'version': '2.1.0',
'runs': [
{
'tool': {
'driver': {
'name': 'yamllint',
'version': APP_VERSION,
'informationUri': 'https://yamllint.readthedocs.io',
'rules': []
},
},
'results': []
}
]
}
rules = {}
max_rule_index = 0
for file in results:
for problem in results[file]:
max_level = max(max_level, PROBLEM_LEVELS[problem.level])
if problem.rule in rules:
rule_index = rules[problem.rule]
else:
rule_index = max_rule_index
rules[problem.rule] = max_rule_index
sarif['runs'][0]['tool']['driver']['rules'].append(format_rule(problem))
max_rule_index += 1
sarif['runs'][0]['results'].append(format_result(rule_index, problem, file))
print(json.dumps(sarif))
return max_level
def format_rule(problem):
uri = 'https://yamllint.readthedocs.io/en/v{}/rules.html#module-yamllint.rules.{}'.format(APP_VERSION, problem.rule)
return {
'id': problem.rule,
'name': ''.join([word.capitalize() for word in problem.rule.split('-')]),
'defaultConfiguration': {
'level': problem.level
},
'properties': {
'description': problem.desc,
'tags': [],
'queryUri': uri,
},
'shortDescription': {
'text': problem.desc
},
'fullDescription': {
'text': problem.desc
},
'helpUri': uri,
'help': {
'text': 'More info: {}'.format(uri),
'markdown': '[More info]({})'.format(uri)
}
}
def format_result(rule_index, problem, filename):
return {
'ruleId': problem.rule,
'ruleIndex': rule_index,
'message': {
'text': problem.message
},
'locations': [
{
'physicalLocation': {
'artifactLocation': {
'uri': filename,
'uriBaseId': '%SRCROOT%'
},
'region': {
'startLine': problem.line,
'startColumn': problem.column
}
}
}
]
}
Loading…
Cancel
Save