Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SARIF support #40

Merged
merged 31 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
60e3ac2
add SARIF support
shaopeng-gh Mar 23, 2022
283382b
pretty print the whole json at the end
shaopeng-gh Mar 24, 2022
8627248
SARIF base path uri should end with `/`
shaopeng-gh Mar 28, 2022
8d15b84
Use better sample data in SARIF template
shaopeng-gh Mar 30, 2022
b2e0dce
Add help_uri and description to SARIF output
shaopeng-gh Mar 30, 2022
40cfdd4
update example values in sarif template
shaopeng-gh Apr 4, 2022
d916b98
test workflow
shaopeng-gh Apr 5, 2022
db93036
test puppet-lint-action
shaopeng-gh Apr 6, 2022
6e42257
test workflow
shaopeng-gh Apr 6, 2022
f9555df
test
shaopeng-gh Apr 6, 2022
40c367a
test path
shaopeng-gh Apr 6, 2022
99c91a3
continue-on-error: true
shaopeng-gh Apr 6, 2022
8af4705
use .
shaopeng-gh Apr 6, 2022
427333f
change order
shaopeng-gh Apr 6, 2022
369fadd
Revert "change order"
shaopeng-gh Apr 6, 2022
36e1fbd
change order
shaopeng-gh Apr 6, 2022
747505a
remove warning lines
shaopeng-gh Apr 6, 2022
d145c7f
clean up
shaopeng-gh Apr 6, 2022
0123103
use STDERR.put for warnings
shaopeng-gh Apr 8, 2022
ef1b694
Merge branch 'master' of https://github.com/shaopeng-gh/puppet-lint
shaopeng-gh Apr 8, 2022
16d625d
remove clean step
shaopeng-gh Apr 8, 2022
7fcf324
new line
shaopeng-gh Apr 8, 2022
1b2da02
fix test with stderr
shaopeng-gh Apr 8, 2022
01f8bd8
use Pathname.new
shaopeng-gh Apr 8, 2022
17ad7a8
use delete_if
shaopeng-gh Apr 8, 2022
119f16f
Fix comments
shaopeng-gh Apr 11, 2022
57c7af8
remove not needed strategy matrix
shaopeng-gh Apr 19, 2022
7232414
remove not needed strategy matrix
shaopeng-gh Apr 19, 2022
74b39e6
fix rule index
shaopeng-gh May 10, 2022
9d91452
upgrade to use upload-sarif@v2 instead of upload-sarif@v1
shaopeng-gh May 17, 2022
eca7fe0
removed example scan.yml
shaopeng-gh May 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/puppet-lint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def print_context(message)
# problems - An Array of problem Hashes as returned by
# PuppetLint::Checks#run.
#
# Returns nothing.
# Returns array of problem.
def report(problems)
json = []
problems.each do |message|
Expand All @@ -171,7 +171,7 @@ def report(problems)

next unless message[:kind] == :fixed || [message[:kind], :all].include?(configuration.error_level)

if configuration.json
if configuration.json || configuration.sarif
message['context'] = get_context(message) if configuration.with_context
json << message
else
Expand All @@ -183,6 +183,7 @@ def report(problems)
puts JSON.pretty_generate(json) if configuration.json
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could affect usage via Rake. I don't know if people do this, but there are effectively 2 entry points: the bin file which you already found and Rake:
https://github.com/puppetlabs/puppet-lint/blob/020143b705b023946739eb44e7c7d99fcd087527/lib/puppet-lint/tasks/puppet-lint.rb#L88-L107=

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for all the inputs! I will set the PR as draft for now and look into them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have followed this instruction:
https://github.com/puppetlabs/puppet-lint/blob/master/README.md#testing-with-puppet-lint-as-a-rake-task

then running rake lint seems not having issue and output result normally.
I think running in rake currently only have normal
output does not support json option in the configuration, so the line highlighted will not be run in rake lint command, so should be good.


$stderr.puts 'Try running `puppet parser validate <file>`' if problems.any? { |p| p[:check] == :syntax }
json
end

# Public: Determine if PuppetLint found any errors in the manifest.
Expand Down
51 changes: 50 additions & 1 deletion lib/puppet-lint/bin.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'pathname'
require 'uri'
require 'puppet-lint/optparser'

# Internal: The logic of the puppet-lint bin script, contained in a class for
Expand Down Expand Up @@ -46,6 +48,18 @@ def run

begin
path = @args[0]
full_path = File.expand_path(path, ENV['PWD'])
full_base_path = if File.directory?(full_path)
full_path
else
File.dirname(full_path)
end

full_base_path_uri = if full_base_path.start_with?('/')
'file://' + full_base_path
else
'file:///' + full_base_path
end
path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
path = if File.directory?(path)
Dir.glob("#{path}/**/*.pp")
Expand All @@ -57,14 +71,15 @@ def run

return_val = 0
ignore_paths = PuppetLint.configuration.ignore_paths
all_problems = []

puts '[' if PuppetLint.configuration.json
shaopeng-gh marked this conversation as resolved.
Show resolved Hide resolved
path.each do |f|
next if ignore_paths.any? { |p| File.fnmatch(p, f) }
l = PuppetLint.new
l.file = f
l.run
l.print_problems
all_problems << l.print_problems
puts ',' if f != path.last && PuppetLint.configuration.json
shaopeng-gh marked this conversation as resolved.
Show resolved Hide resolved

if l.errors? || (l.warnings? && PuppetLint.configuration.fail_on_warnings)
Expand All @@ -78,11 +93,45 @@ def run
end
puts ']' if PuppetLint.configuration.json
shaopeng-gh marked this conversation as resolved.
Show resolved Hide resolved

report_sarif(all_problems, full_base_path, full_base_path_uri) if PuppetLint.configuration.sarif

return return_val
rescue PuppetLint::NoCodeError
puts 'puppet-lint: no file specified or specified file does not exist'
puts "puppet-lint: try 'puppet-lint --help' for more information"
return 1
end
end

# Internal: Print the reported problems in SARIF format to stdout.
#
# problems - An Array of problem Hashes as returned by
# PuppetLint::Checks#run.
#
# Returns nothing.
def report_sarif(problems, base_path, base_path_uri)
sarif_file = File.read(File.join(File.dirname(File.expand_path(__FILE__)), 'report/sarif.json'))
shaopeng-gh marked this conversation as resolved.
Show resolved Hide resolved
sarif = JSON.parse(sarif_file)
sarif['runs'][0]['originalUriBaseIds']['ROOTPATH']['uri'] = base_path_uri
rules = sarif['runs'][0]['tool']['driver']['rules'] = []
results = sarif['runs'][0]['results'] = []
problems.each do |messages|
messages.each do |message|
relative_path = Pathname.new(message[:fullpath]).relative_path_from(base_path)
rules = sarif['runs'][0]['tool']['driver']['rules']
rule_exists = rules.any? { |r| r['id'] == message[:check] }
rules << { 'id' => message[:check] } unless rule_exists
rule_index = rules.count - 1
result = {
'ruleId' => message[:check],
'ruleIndex' => rule_index,
'message' => { 'text' => message[:message] },
'locations' => [{ 'physicalLocation' => { 'artifactLocation' => { 'uri' => relative_path, 'uriBaseId' => 'ROOTPATH' }, 'region' => { 'startLine' => message[:line], 'startColumn' => message[:column] } } }],
}
result['level'] = message[:KIND].downcase if %w[error warning].include?(message[:KIND].downcase)
results << result
end
end
puts JSON.pretty_generate(sarif)
end
end
1 change: 1 addition & 0 deletions lib/puppet-lint/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ def defaults
self.with_context = false
self.fix = false
self.json = false
self.sarif = false
self.show_ignored = false
self.ignore_paths = ['vendor/**/*.pp']
self.github_actions = ENV.key?('GITHUB_ACTION')
Expand Down
4 changes: 4 additions & 0 deletions lib/puppet-lint/optparser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ def self.build(args = [])
PuppetLint.configuration.json = true
end

opts.on('--sarif', 'Log output as SARIF') do
PuppetLint.configuration.sarif = true
end

opts.on('--list-checks', 'List available check names.') do
PuppetLint.configuration.list_checks = true
end
Expand Down
60 changes: 60 additions & 0 deletions lib/puppet-lint/report/sarif.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"$schema":"https://www.schemastore.org/schemas/json/sarif-2.1.0-rtm.5.json",
"version":"2.1.0",
"runs":[
{
"tool":{
"driver":{
"name":"Puppet Lint",
"informationUri":"https://github.com/puppetlabs/puppet-lint",
"version":"0.15.0",
"rules":[
{
"id":"",
"name":"",
"shortDescription":{
"text":""
},
"fullDescription":{
"text":""
},
"help":{
"text":""
}
}
]
}
},
"results":[
{
"ruleId":"",
"ruleIndex":0,
"level":"error",
"message":{
"text":""
},
"locations":[
{
"physicalLocation":{
"artifactLocation":{
"uri":"file:///foo.txt",
"uriBaseId":"ROOTPATH"
},
"region":{
"startLine":1,
"startColumn":1
}
}
}
]
}
],
"columnKind":"utf16CodeUnits",
"originalUriBaseIds":{
"ROOTPATH":{
"uri":"/"
}
}
}
]
}
35 changes: 35 additions & 0 deletions spec/puppet-lint/bin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,41 @@ def initialize(args)
end
end

context 'when displaying results as SARIF' do
let(:args) do
[
'--sarif',
'spec/fixtures/test/manifests/warning.pp',
]
end

its(:exitstatus) { is_expected.to eq(0) }

its(:stdout) do
is_expected.to match(%r{"ruleId": "parameter_order"})
is_expected.to match(%r{"uri": "warning.pp"})
end
end

context 'when displaying results for multiple targets as SARIF' do
let(:args) do
[
'--sarif',
'spec/fixtures/test/manifests/fail.pp',
'spec/fixtures/test/manifests/warning.pp',
]
end

its(:exitstatus) { is_expected.to eq(1) }

its(:stdout) do
is_expected.to match(%r{"ruleId": "autoloader_layout"})
is_expected.to match(%r{"uri": "fail.pp"})
is_expected.to match(%r{"ruleId": "parameter_order"})
is_expected.to match(%r{"uri": "warning.pp"})
end
end

context 'when hiding ignored problems' do
let(:args) do
[
Expand Down
1 change: 1 addition & 0 deletions spec/puppet-lint/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
'fail_on_warnings' => false,
'error_level' => :all,
'log_format' => '',
'sarif' => false,
'with_context' => false,
'fix' => false,
'github_actions' => false,
Expand Down