Class: RubocopPlus::Commands::Rubo
- Inherits:
-
Cri::CommandRunner
- Object
- Cri::CommandRunner
- RubocopPlus::Commands::Rubo
- Defined in:
- lib/commands/rubo.rb,
lib/commands/rubo/helpers/misc.rb,
lib/commands/rubo/helpers/output.rb,
lib/commands/rubo/helpers/validations.rb
Overview
Helpers for performing validations are grouped in this file.
Instance Method Summary collapse
- #check_if_results_exist! ⇒ Object
- #check_if_rubocop_command_exists! ⇒ Object
-
#check_if_total_violations_count_still_present_and_valid! ⇒ Object
This method is called when the user runs ‘rubo –total-violations`.
- #check_if_violations_count_exists? ⇒ Boolean
- #check_if_yml_has_correct_content! ⇒ Object
- #check_if_yml_present! ⇒ Object
-
#checkstyle_options ⇒ Object
Generates the XML reports necessary to use the Checkstyle Plugin on Jenkins.
-
#delete_rubocop_folder ⇒ Object
While using SublimeText with the SFTP plugin, we noticed the SFTP plugin would not automatically download newer versions of the generated rubocop files at times.
-
#determine_total_violations_count ⇒ Object
Read the total number of violations from the output.
-
#generate_total_violations_file ⇒ Object
This method writes a single integer to a file which represents the total number of violations.
- #initialize_project ⇒ Object
- #installed_version_of_gem ⇒ Object
-
#invoke_rubocop ⇒ Object
Execute rubocop with a tailored set of output files.
-
#is_in_gemfile_dot_lock? ⇒ Boolean
The Gemfile.lock is auto generated when the ‘bundle’ command is run.
- #output_folder_name ⇒ Object
- #rubocop_command_exists? ⇒ Boolean
- #rubocop_version_name ⇒ Object
-
#rubocop_yml_has_correct_content? ⇒ Boolean
Perform some sanity checks to make sure .rubocop.yml has expected content.
- #rubocop_yml_present? ⇒ Boolean
- #run ⇒ Object
- #style_counts_text_file_name ⇒ Object
- #style_issues_html_file_name ⇒ Object
- #style_issues_text_file_name ⇒ Object
-
#total_violations_count ⇒ Object
Return the total violations count from the last rubocop run and remember the result.
- #total_violations_count_text_file_name ⇒ Object
- #validate_post_run! ⇒ Object
-
#validate_pre_run! ⇒ Object
Perform all of the checks to make sure rubo can actually run.
- #write_results_message ⇒ Object
- #write_starting_message ⇒ Object
Instance Method Details
#check_if_results_exist! ⇒ Object
17 18 19 20 21 22 23 24 25 |
# File 'lib/commands/rubo/helpers/validations.rb', line 17 def check_if_results_exist! error = RubocopPlus::Commands::BadOutput check_if_violations_count_exists? raise error, "The '#{output_folder_name}' folder does not exist." unless File.directory?(output_folder_name) raise error, "Missing #{style_issues_text_file_name}" unless File.exist?(style_issues_text_file_name) raise error, "Missing #{style_issues_html_file_name}" unless File.exist?(style_issues_html_file_name) raise error, "Missing #{style_counts_text_file_name}" unless File.exist?(style_counts_text_file_name) end |
#check_if_rubocop_command_exists! ⇒ Object
13 14 15 |
# File 'lib/commands/rubo/helpers/validations.rb', line 13 def check_if_rubocop_command_exists! raise RubocopPlus::Commands::NoRubocopCommand unless rubocop_command_exists? end |
#check_if_total_violations_count_still_present_and_valid! ⇒ Object
This method is called when the user runs ‘rubo –total-violations`. That option is used to open the “total violations counts” file and print the number. However, the user can run `rubo`, wait for a bit, delete his rubocop folder and THEN run `rubo –total-violations`. This is a little different from the other checks where we are IMMEDIATELY checking the results of the rubo command. In those checks, we’re trying to make sure the rubo command worked correctly and was successfully able to write results. In this check, we’re making sure the files are still around before we try and open them.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/commands/rubo/helpers/validations.rb', line 41 def check_if_total_violations_count_still_present_and_valid! error = RubocopPlus::Commands::OutputMissing prefix = "Cannot proceed." raise error, "#{prefix} The '#{output_folder_name}' folder does not exist." unless File.directory?(output_folder_name) file_name = total_violations_count_text_file_name raise error, "#{prefix} The #{file_name} file is missing." unless File.exist?(file_name) violations = File.read(file_name) raise error, "#{prefix} The #{file_name} file is empty." if violations.nil? || violations.strip.empty? violations = violations.strip raise error, "#{prefix} The #{file_name} file contains non-digit characters." unless /^\d*$/.match?(violations) end |
#check_if_violations_count_exists? ⇒ Boolean
27 28 29 30 31 32 33 |
# File 'lib/commands/rubo/helpers/validations.rb', line 27 def check_if_violations_count_exists? error = RubocopPlus::Commands::BadOutput raise error, "Missing #{total_violations_count_text_file_name}" unless File.exist?(total_violations_count_text_file_name) violations = File.read(total_violations_count_text_file_name) raise error, "#{total_violations_count_text_file_name} is empty" if violations.nil? || violations.strip.empty? end |
#check_if_yml_has_correct_content! ⇒ Object
9 10 11 |
# File 'lib/commands/rubo/helpers/validations.rb', line 9 def check_if_yml_has_correct_content! raise RubocopPlus::Commands::IncorrectYml unless rubocop_yml_has_correct_content? end |
#check_if_yml_present! ⇒ Object
5 6 7 |
# File 'lib/commands/rubo/helpers/validations.rb', line 5 def check_if_yml_present! raise RubocopPlus::Commands::MissingYml unless rubocop_yml_present? end |
#checkstyle_options ⇒ Object
Generates the XML reports necessary to use the Checkstyle Plugin on Jenkins. It is only needed for the CI so return an empty string unless the –checkstyle option is present.
65 66 67 68 69 70 71 |
# File 'lib/commands/rubo.rb', line 65 def return "" unless [:checkstyle] cmd = " --require rubocop/formatter/checkstyle_formatter" cmd += " --format RuboCop::Formatter::CheckstyleFormatter" cmd + " --out #{output_folder_name}/checkstyle.xml" end |
#delete_rubocop_folder ⇒ Object
While using SublimeText with the SFTP plugin, we noticed the SFTP plugin would not automatically download newer versions of the generated rubocop files at times. Rubocop should overwrite the files, but we goahead and explicity delete the folder in the hopes that will help resolve the file syncing issues for editors (we’re not 100% sure this helps).
76 77 78 |
# File 'lib/commands/rubo.rb', line 76 def delete_rubocop_folder FileUtils.remove_dir(output_folder_name, true) end |
#determine_total_violations_count ⇒ Object
Read the total number of violations from the output. Unfortunately, rubocop doesn’t have a direct way to generate this number, but it does produce a file with the output burried inside it. We can search the file and figure out the violations count. The file will have a line that looks like this:
1234 Total
19 20 21 22 23 |
# File 'lib/commands/rubo/helpers/output.rb', line 19 def determine_total_violations_count total_line = "" File.readlines(style_counts_text_file_name).each { |line| total_line = line if line.include?("Total") } @total_violations = total_line.empty? ? 0 : total_line.split.first.to_i end |
#generate_total_violations_file ⇒ Object
This method writes a single integer to a file which represents the total number of violations. The value in this file can be used to fail builds on the CI/CD pipeline which have too many violations. Rubocop doesn’t appear to have a formatter that will write the total number of violations to a file. Fortunately, we can pull this information out of some other files and write the output ourselves.
38 39 40 |
# File 'lib/commands/rubo/helpers/output.rb', line 38 def generate_total_violations_file File.open(total_violations_count_text_file_name, 'w') { |f| f.print determine_total_violations_count } end |
#initialize_project ⇒ Object
42 43 44 45 46 47 |
# File 'lib/commands/rubo.rb', line 42 def initialize_project backup_rubocop_yml_if_present template_path = File.('../templates/.rubocop.yml', __dir__) FileUtils.cp(template_path, ".rubocop.yml") puts ".rubocop.yml created" end |
#installed_version_of_gem ⇒ Object
25 26 27 |
# File 'lib/commands/rubo/helpers/misc.rb', line 25 def installed_version_of_gem Gem::Version.new(RubocopPlus::VERSION) end |
#invoke_rubocop ⇒ Object
Execute rubocop with a tailored set of output files. Rails checks are activated in the default config/rubocop.yml file so we do not explicitly activate them there.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/commands/rubo.rb', line 51 def invoke_rubocop cmd = is_in_gemfile_dot_lock? ? "bundle exec rubocop" : "rubocop" # Make sure we always use the specific version of rubocop. Without this line, the latest version of rubocop # will be used if a user installs a version that is newer than what we want to use. cmd += " _#{RubocopPlus::RUBOCOP_VERSION}_" cmd += " --format simple --out #{style_issues_text_file_name}" cmd += " --format html --out #{style_issues_html_file_name}" cmd += " --format offenses --out #{style_counts_text_file_name}" cmd += system cmd end |
#is_in_gemfile_dot_lock? ⇒ Boolean
The Gemfile.lock is auto generated when the ‘bundle’ command is run. It doesn’t contain superfluous comments or any references to a gem unless the gem is being used. However, many terms like ‘rails’ is used in multiple gem name so we need to be smart about checking boundaries. Each gem line in Gemfile.lock always starts with a couple spaces, followed by the gem name, followed by a single space or newline chracter.
13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/commands/rubo/helpers/misc.rb', line 13 def is_in_gemfile_dot_lock? return false unless File.exist?("Gemfile.lock") # Match logic # ^ - match from beginning of string # \s* - match 0-N white space characters # rubocop_plus - match the gem_name exactly once # \s - match one white space character (it will always be a space or a \n) File.foreach("Gemfile.lock") { |line| return true if /^\s*rubocop_plus\s/.match?(line) } false end |
#output_folder_name ⇒ Object
33 34 35 |
# File 'lib/commands/rubo/helpers/misc.rb', line 33 def output_folder_name "rubocop" end |
#rubocop_command_exists? ⇒ Boolean
62 63 64 65 |
# File 'lib/commands/rubo/helpers/misc.rb', line 62 def rubocop_command_exists? path = Which('rubocop') !(path.nil? || path.empty?) end |
#rubocop_version_name ⇒ Object
29 30 31 |
# File 'lib/commands/rubo/helpers/misc.rb', line 29 def rubocop_version_name Gem::Version.new(RubocopPlus::RUBOCOP_VERSION) end |
#rubocop_yml_has_correct_content? ⇒ Boolean
Perform some sanity checks to make sure .rubocop.yml has expected content.
54 55 56 57 58 59 60 |
# File 'lib/commands/rubo/helpers/misc.rb', line 54 def rubocop_yml_has_correct_content? # If we're running from inside the rubocop_plus folder, ignore this check. return true if Dir.pwd.include?("rubocop_plus") text = File.read(".rubocop.yml") text.include?("inherit_gem:") && text.include?("rubocop_plus:") end |
#rubocop_yml_present? ⇒ Boolean
5 6 7 |
# File 'lib/commands/rubo/helpers/misc.rb', line 5 def rubocop_yml_present? File.file?(".rubocop.yml") end |
#run ⇒ Object
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/commands/rubo.rb', line 19 def run validate_pre_run! delete_rubocop_folder invoke_rubocop generate_total_violations_file validate_post_run! end |
#style_counts_text_file_name ⇒ Object
45 46 47 |
# File 'lib/commands/rubo/helpers/misc.rb', line 45 def style_counts_text_file_name "#{output_folder_name}/style-counts.txt" end |
#style_issues_html_file_name ⇒ Object
41 42 43 |
# File 'lib/commands/rubo/helpers/misc.rb', line 41 def style_issues_html_file_name "#{output_folder_name}/style-issues.html" end |
#style_issues_text_file_name ⇒ Object
37 38 39 |
# File 'lib/commands/rubo/helpers/misc.rb', line 37 def style_issues_text_file_name "#{output_folder_name}/style-issues.txt" end |
#total_violations_count ⇒ Object
Return the total violations count from the last rubocop run and remember the result. This result should not do any validation to make sure the file exists, or is correct. That is checked in other parts of the system.
27 28 29 30 31 32 |
# File 'lib/commands/rubo/helpers/output.rb', line 27 def total_violations_count return @total_violations unless @total_violations.nil? first_line = File.read(total_violations_count_text_file_name) @total_violations = first_line.strip.to_i end |
#total_violations_count_text_file_name ⇒ Object
49 50 51 |
# File 'lib/commands/rubo/helpers/misc.rb', line 49 def total_violations_count_text_file_name "#{output_folder_name}/total-violations-count.txt" end |
#validate_post_run! ⇒ Object
38 39 40 |
# File 'lib/commands/rubo.rb', line 38 def validate_post_run! check_if_results_exist! end |
#validate_pre_run! ⇒ Object
Perform all of the checks to make sure rubo can actually run. This method is called by the ‘run’ method when ‘rubo’ is called. It’s also called with ‘rubo –validate’ is called.
32 33 34 35 36 |
# File 'lib/commands/rubo.rb', line 32 def validate_pre_run! check_if_yml_present! check_if_yml_has_correct_content! check_if_rubocop_command_exists! end |
#write_results_message ⇒ Object
5 6 7 8 9 |
# File 'lib/commands/rubo/helpers/output.rb', line 5 def prefix = "#{total_violations_count} issues found, results written to rubocop/" prefix = total_violations_count.zero? ? prefix.rubo_green : prefix.rubo_red puts "#{prefix} (rubocop_plus v#{installed_version_of_gem} / rubocop v#{rubocop_version_name})" end |
#write_starting_message ⇒ Object
11 12 13 |
# File 'lib/commands/rubo/helpers/output.rb', line 11 def print "Running rubocop ... " end |