Skip to content

Instantly share code, notes, and snippets.

@lowjoel
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lowjoel/f6092d9271d716a1e8a9 to your computer and use it in GitHub Desktop.
Save lowjoel/f6092d9271d716a1e8a9 to your computer and use it in GitHub Desktop.
Running Rubocop from the Command Line, generating a JUnit report
#!/usr/bin/env ruby2.1
# Modified from
# https://github.com/clintoncwolfe/chef-ci-tools/blob/master/bin/rubocop-junit-tee.rb
require 'fileutils'
# This first part runs Rubocop proper
puts "Executing within: #{Dir.pwd}"
RUBOCOP_XML = ARGV.shift
RUBOCOP_JSON = "#{RUBOCOP_XML}.json"
RUBOCOP = 'rubocop -R'
FileUtils.mkpath(File.dirname(RUBOCOP_XML))
`#{RUBOCOP} -f json -o #{RUBOCOP_JSON}`
require 'json'
FileUtils.rm_f RUBOCOP_XML
cbname = File.basename(Dir.pwd)
puts "------ rubocop checks: #{cbname} ------"
#==================================================#
# Obtain list of enabled Cops from rubocop, using config passed in.
#==================================================#
cops = {}
current_type = nil
current_cop = nil
current_desc = nil
`#{RUBOCOP} --show-cops`.each_line do |line|
if md = line.match(/^# Type '(?<type>.+)'/) then
current_type = md[:type]
next
end
if md = line.match(/^(?<cop>\S+):/) then
current_cop = md[:cop]
next
end
if md = line.match(/^(:\s{4}-\s|\s{2})Description:\s(?<desc>.+)$/) then
current_desc = md[:desc]
end
if md = line.match(/^(:\s{4}-\s|\s{2})Enabled:\s(?<enabled>true|false)/) then
if md[:enabled] == 'true' then
cops[current_cop] = {
:desc => current_desc,
:type => current_type,
:offences => [],
}
end
end
end
#------------------------------------------------------------#
# Parse RC Output
#------------------------------------------------------------#
json_string = nil
open(RUBOCOP_JSON) do |f|
json_string = f.read
end
cop_data = ::JSON.parse(json_string)
cop_data["files"].each do |file_info|
# make file path relative
path = file_info["path"].sub(Dir.pwd + '/', '')
(file_info["offences"] || file_info["offenses"]).each do |offence|
# Produce a line like -f emacs, it's simple
tee_line = path
tee_line += ':' + offence["location"]["line"].to_s
tee_line += ':' + offence["location"]["column"].to_s
tee_line += ': ' + offence["severity"][0].upcase
tee_line += ': ' + offence["message"]
puts tee_line
# Record the offense per-cop
(cops[offence["cop_name"]][:offences] || cops[offence["cop_name"]][:offenses]).
push offence.merge("path" => path)
end
end
#------------------------------------------------------------#
# Output JUNIT XML
#------------------------------------------------------------#
require 'rexml/text'
def escape(text)
REXML::Text.new(text, false, nil, false).to_s
end
File.open(RUBOCOP_XML, 'w') do |out|
out.print <<-EOX
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="#{cbname}" timestamp="">
EOX
cops.each do |name, info|
out.puts '<testcase classname="rubocop.' + escape(name) + '" name="' + escape(info[:desc]) + '">'
info[:offences].each do |offence|
out.print '<failure type="' + escape(name) + '" message="' + escape(offence['message']) + '">'
out.puts '%s, line %s, col %s' % [
escape(offence['path']),
offence['location']['line'].to_s,
offence['location']['column'].to_s
]
out.puts '', '</failure>'
end
out.puts '</testcase>'
end
out.puts ' </testsuite>'
out.puts '</testsuites>'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment