mirror of
https://github.com/inspec/inspec
synced 2024-11-10 23:24:18 +00:00
Integrate inspec check with cookstyle
Signed-off-by: Nikita Mathur <nikita.mathur@chef.io>
This commit is contained in:
parent
e5b7bcf4b9
commit
bedde88849
5 changed files with 79 additions and 5 deletions
2
Gemfile
2
Gemfile
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue