script/update-rubocop-config.rb
#!/usr/bin/env ruby
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
Pathname.new(__FILE__).realpath)
require 'rubygems'
require 'bundler/setup'
require 'rubocop'
require 'rubocop-performance'
require 'rubocop-rails'
CONFIG_FILE = File.join(File.dirname(__FILE__), '../.ruby-style.yml')
GEM_VERSIONS = {
'rubocop': RuboCop::Version::STRING,
'rubocop-performance': RuboCop::Performance::Version::STRING,
'rubocop-rails': RuboCop::Rails::Version::STRING
}
print 'Current gem versions: '
p GEM_VERSIONS
def default_config
tmp_dir = File.join(File.dirname(__FILE__), '../tmp')
GEM_VERSIONS.inject({}) do |m, (r, v)|
uri = URI(
"https://raw.githubusercontent.com/rubocop/#{r}/v#{v}/config/default.yml"
)
hash = Digest::MD5.hexdigest(uri.to_s)
tmp_path = File.join(tmp_dir, "rubocop-#{hash}.yml")
File.write(tmp_path, Net::HTTP.get(uri)) unless File.exist?(tmp_path)
if RUBY_VERSION < "3.1"
yaml = YAML.load_file(tmp_path)
else
yaml = YAML.load_file(tmp_path, permitted_classes: [Regexp, Symbol])
end
m.deep_merge!(yaml)
end
end
def current_config
YAML.load_file(CONFIG_FILE)
end
def merge_config(default, current)
config = { 'AllCops' => current['AllCops'] }
non_cops_groupings_from_config(current).each do |g|
config[g] = current[g]
end
cops_from_config(default).each do |cop|
c = current[cop]
if c
config[cop] = c
else
config[cop] = { 'Enabled' => false }
end
end
config
end
def non_cops_groupings_from_config(config)
config.keys.select { |k| k == k.downcase }
end
def cops_from_config(config)
config.keys - non_cops_groupings_from_config(config) - ['AllCops']
end
def groupings_from_config(config)
cops_from_config(config).map { |c| c.split('/').first }.uniq
end
def write_config(config)
yaml = config.sort.to_h.to_yaml
# add lines between cops
yaml.gsub!(/^(?!AllCops)([^ -]+:)$/, "\n\\1")
# increase indent of array items
yaml.gsub!(/^( *- )/, ' \1')
non_cops_groupings_from_config(config).each do |g|
# move non-cop groupings keys to top
yaml.gsub!(/(---\n)(.*)\n^(#{g}:.*)/m, "\\1\\3\n\\2")
end
groupings_from_config(config).each do |g|
# add headers for each grouping
yaml.sub!(g + '/', '#' * 20 + " #{g} " + '#' * 20 + "\n\n#{g}/")
end
File.write(CONFIG_FILE, yaml)
end
write_config(merge_config(default_config, current_config))
puts "RuboCop configuration at #{File.expand_path(CONFIG_FILE)} has been updated"
puts "Please manually check cops which have been renamed"