Integrate inspec check with cookstyle

Signed-off-by: Nikita Mathur <nikita.mathur@chef.io>
This commit is contained in:
Nikita Mathur 2021-08-16 15:47:22 +05:30
parent e5b7bcf4b9
commit bedde88849
5 changed files with 79 additions and 5 deletions

View file

@ -20,6 +20,8 @@ end
# but our runtime dep is still 3.9+
gem "rspec", ">= 3.10"
gem "cookstyle"
group :omnibus do
gem "rb-readline"
gem "appbundler"

View file

@ -122,8 +122,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
end
puts
if result[:errors].empty? && result[:warnings].empty?
ui.plain_line("No errors or warnings")
if result[:errors].empty? && result[:warnings].empty? && result[:offenses].empty?
ui.plain_line("No errors or warnings or offenses")
else
item_msg = lambda { |item|
pos = [item[:file], item[:line], item[:column]].compact.join(":")
@ -135,11 +135,18 @@ class Inspec::InspecCLI < Inspec::BaseCLI
puts
unless result[:offenses].empty?
puts "Offenses:\n"
result[:offenses].each { |item| ui.cyan(" #{Inspec::UI::GLYPHS[:script_x]} #{item_msg.call(item)}\n\n") }
end
offenses = ui.cyan("#{result[:offenses].length} offenses", print: false)
errors = ui.red("#{result[:errors].length} errors", print: false)
warnings = ui.yellow("#{result[:warnings].length} warnings", print: false)
ui.plain_line("Summary: #{errors}, #{warnings}")
ui.plain_line("Summary: #{errors}, #{warnings}, #{offenses}")
end
end
ui.exit Inspec::UI::EXIT_USAGE_ERROR unless result[:summary][:valid]
rescue StandardError => e
pretty_handle_exception(e)

View file

@ -386,6 +386,34 @@ module Inspec
res
end
def cookstyle_linting_check
msgs = []
output = cookstyle_rake_output.split("Offenses:").last
msgs = output.split("\n").select { |x| (x.include? "R:") || (x.include? "C:") } unless output.nil?
msgs
end
# Cookstyle linting rake run output
def cookstyle_rake_output
require "cookstyle"
require "rubocop/rake_task"
begin
RuboCop::RakeTask.new(:cookstyle_lint) do |spec|
spec.options += ["--display-cop-names", "--parallel"]
spec.patterns += Dir.glob("#{@target}/**/*").reject { |f| File.directory?(f) || (f.include? "inspec.lock") }
spec.fail_on_error = false
end
rescue LoadError
puts "Rubocop is not available. Install the rubocop gem to run the lint tests."
end
stdout = StringIO.new
$stdout = stdout
Rake::Task["cookstyle_lint"].invoke
$stdout = STDOUT
Rake.application["cookstyle_lint"].reenable
stdout.string
end
# Check if the profile is internally well-structured. The logger will be
# used to print information on errors and warnings which are found.
#
@ -402,6 +430,7 @@ module Inspec
},
errors: [],
warnings: [],
offenses: [],
}
entry = lambda { |file, line, column, control, msg|
@ -424,6 +453,10 @@ module Inspec
result[:errors].push(entry.call(file, line, column, control, msg))
}
offense = lambda { |file, line, column, control, msg|
result[:offenses].push(entry.call(file, line, column, control, msg))
}
@logger.info "Checking profile in #{@target}"
meta_path = @source_reader.target.abs_path(@source_reader.metadata.ref)
@ -486,8 +519,15 @@ module Inspec
warn.call(sfile, sline, nil, id, "Control #{id} has no tests defined") if control[:checks].nil? || control[:checks].empty?
end
# profile is valid if we could not find any error
result[:summary][:valid] = result[:errors].empty?
# Running cookstyle to check for code offenses
cookstyle_linting_check.each do |lint_output|
data = lint_output.split(":")
msg = "#{data[-2]}:#{data[-1]}"
offense.call(data[0], data[1], data[2], nil, msg)
end
# profile is valid if we could not find any error & offenses
result[:summary][:valid] = result[:errors].empty? && result[:offenses].empty?
@logger.info "Control definitions OK." if result[:warnings].empty?
result

View file

@ -117,4 +117,18 @@ describe "inspec check" do
assert_exit_code 1, out
end
end
describe "inspec check also check for cookstyle offenses" do
it "finds no offenses in a complete profile" do
out = inspec("check #{profile_path}/complete-profile")
_(out.stdout).must_match(/No errors or warnings or offenses/)
assert_exit_code 0, out
end
it "fails and returns offenses in a profile" do
out = inspec("check #{profile_path}/control-tags")
_(out.stdout).must_match(/29 offenses/)
assert_exit_code 1, out
end
end
end

View file

@ -124,6 +124,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors].length).must_equal 1
_(result[:warnings].length).must_equal 5
_(result[:offenses]).must_be_empty
end
end
@ -148,6 +149,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors]).must_be_empty
_(result[:warnings].length).must_equal 1
_(result[:offenses]).must_be_empty
end
end
@ -171,6 +173,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 1
_(result[:errors]).must_be_empty
_(result[:warnings]).must_be_empty
_(result[:offenses]).must_be_empty
end
end
@ -196,6 +199,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 1
_(result[:errors]).must_be_empty
_(result[:warnings]).must_be_empty
_(result[:offenses]).must_be_empty
end
end
@ -221,6 +225,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 1
_(result[:errors]).must_be_empty
_(result[:warnings]).must_be_empty
_(result[:offenses]).must_be_empty
end
end
@ -246,6 +251,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 1
_(result[:errors]).must_be_empty
_(result[:warnings]).must_be_empty
_(result[:offenses]).must_be_empty
end
end
@ -272,6 +278,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors].length).must_equal 1
_(result[:warnings].length).must_equal 1
_(result[:offenses]).must_be_empty
end
end
@ -289,6 +296,7 @@ describe Inspec::Profile do
logger.verify
_(result[:warnings]).must_be_empty
_(result[:errors].length).must_equal 1
_(result[:offenses]).must_be_empty
end
end
@ -316,6 +324,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors]).must_be_empty
_(result[:warnings].length).must_equal 2
_(result[:offenses]).must_be_empty
end
describe "shows no warning if license is spdx" do
@ -341,6 +350,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors]).must_be_empty
_(result[:warnings].length).must_equal 1
_(result[:offenses]).must_be_empty
end
end
@ -367,6 +377,7 @@ describe Inspec::Profile do
_(result[:summary][:controls]).must_equal 0
_(result[:errors]).must_be_empty
_(result[:warnings].length).must_equal 1
_(result[:offenses]).must_be_empty
end
end