reviewer 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5df0f3247eb105862f40b5092bb3c3b25fa20e87e155cb283fc2fd278933987
4
- data.tar.gz: 06716646a5f980c5d67f89abc4ab4938977c2dd2691101d8cdd924f4481599cf
3
+ metadata.gz: 64e0b63ddf470414a26b5903508646ace97b1b0ee6e2b0244e7233d9e6717652
4
+ data.tar.gz: 97b9d1d998959319791022b37f00fde7b6424411c728e98fb8109c352078088d
5
5
  SHA512:
6
- metadata.gz: 57ca3df253ec35a5544f9a2145733c535688f8be8f0ed6820973563f758563e08a6f3aa729e8743be49945d931cc63a27a21a75e4512d2f9855f1ecad055a9ac
7
- data.tar.gz: 5b06953f74f63aff8410b27470a37044d764b87b07289554d0ddc3581575d8a6849603a78f656d392273ac6e4d3d358acd91a84cae49a7d49fd427800536d5cb
6
+ metadata.gz: da483ff2104b138d463c1688731c3eb83ecb8778105af38efbe98f6c7597f9aa4a069341580a3fc7bb34833cf83119d64967a56398e0cea4f97ae7bebc2ae5f2
7
+ data.tar.gz: f9f1106bf11209abd1a5af2d3ad151413a1026cbe43a4a5db171414d335df7cae9c7ab8d922e661da0625240163d55906eccf9b8fe03a245869f97b00bc94ce8
@@ -10,7 +10,7 @@ jobs:
10
10
  - name: Set up Ruby
11
11
  uses: ruby/setup-ruby@v1
12
12
  with:
13
- ruby-version: 2.6.6
13
+ ruby-version: 2.7.3
14
14
  bundler-cache: true
15
15
  - name: Run the default task
16
16
  run: bundle exec rake
@@ -0,0 +1,47 @@
1
+ # Quick overview of the options configuration for command-line tools.
2
+ #
3
+ # <command_key>: // ex. 'rubocop', 'bundler-audit', etc.
4
+ # disabled: true // Optional. Tools are enabled by default
5
+ # name: // Optional. Will use the `command_key` if name isn't provided.
6
+ # description: // Optional. Serves as a handy reminder for the purpose of the command.
7
+ # tags: [ruby, dependencies] // Optional. Lets you run commands tagged with the same word.
8
+ # links:
9
+ # home: // Optional. A link to the home page for the tool.
10
+ # install: // Optional. A link to the installation instructions for the tool.
11
+ # ignore_syntax: // Optional. A link to the syntax for ignoring/disabling some rules for the tool.
12
+ # commands:
13
+ # install: // Optional. Command to run to install the tool.
14
+ # prepare: // Optional. Command to run prior to the review phase. ex. 'bundle exec bundle-audit update'
15
+ # review: // Required. The only truly required field because this is the whole point.
16
+ # format: // Optional. Command to auto-update rule violations when possible.
17
+ # quiet_option: // Optional, but strongly suggested. Helps keep output under control when running multiple tools.
18
+ # max_exit_status: // Optional, defaults to 0. Some tools like Yarn Audit essentially won't return less than a 3. This specifies the threshold that's still considered passing.
19
+ # env: // Optional. A way to specify necessary environment variables for the tools commands. The key is the variable name, and the value is, well, the value.
20
+ # example_one: value // - The names will automatically be capitalized, so you can freely use lower-case here.
21
+ # example_one: value // - Reviewer is smart enough to handle string values with spaces and automatically quote them.
22
+ # flags: // Optional. A way to specify flags *only for the review command*. The key is the flag name, and the value is, well, the value.
23
+ # example_one: value // - Reviewer is smart enough to handle single-letter (-f) and multi-letter (--format) flags.
24
+ # example_two: value // - It's highly-recommended to use the longer-name format for flags when possible to serve as self-documentation.
25
+
26
+ # This is an example for a YAML block for a command-line tool:
27
+ #
28
+ # tool-name-key:
29
+ # disabled: true
30
+ # name: Tool
31
+ # description: A tool that finds issues and fixes code.
32
+ # tags: [syntax, security]
33
+ # links:
34
+ # home: https://example.com
35
+ # install: https://example.com/install
36
+ # ignore_syntax: https://example.com/ignore
37
+ # commands:
38
+ # install: 'bundle install tool'
39
+ # prepare: 'bundle exec tool update'
40
+ # review: 'bundle exec tool'
41
+ # format: 'bundle exec tool --format'
42
+ # quiet_option: '--quiet'
43
+ # max_exit_status: 1
44
+ # env:
45
+ # report: false
46
+ # flags:
47
+ # format: json
data/.reviewer.yml ADDED
@@ -0,0 +1,36 @@
1
+ bundler_audit:
2
+ tags: [critical, dependencies, ruby]
3
+ name: Bundler Audit
4
+ description: Audit Gem Dependencies for Security Issues
5
+ links:
6
+ home: https://github.com/rubysec/bundler-audit
7
+ install: https://github.com/rubysec/bundler-audit#install
8
+ commands:
9
+ install: 'bundle exec gem install bundler-audit'
10
+ prepare: 'bundle exec bundle-audit update'
11
+ review: 'bundle exec bundle-audit check --no-update'
12
+ quiet_option: '--quiet'
13
+
14
+ tests:
15
+ name: Minitest
16
+ description: Unit Tests
17
+ tags: [ruby, tests]
18
+ links:
19
+ home:
20
+ commands:
21
+ review: "bundle exec rake TESTOPTS='--seed=$SEED'"
22
+ quiet_option: '--silent'
23
+
24
+ rubocop:
25
+ tags: [ruby, syntax]
26
+ description: Review Ruby syntax/formatting for consistency
27
+ links:
28
+ home: https://rubocop.org
29
+ install: https://docs.rubocop.org/rubocop/1.13/installation.html
30
+ ignore_syntax: https://docs.rubocop.org/rubocop/configuration.html#ignoredmethods
31
+ disable_syntax: https://docs.rubocop.org/rubocop/configuration.html#disabling-cops-within-source-code
32
+ commands:
33
+ install: 'bundle exec gem install rubocop'
34
+ review: 'bundle exec rubocop --parallel'
35
+ format: 'bundle exec rubocop --auto-correct'
36
+ quiet_option: '--format q'
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ Exclude:
4
+ - 'bin/**/*'
5
+
6
+ # Let's aim for 80, but we don't need to be nagged if we judiciously go over.
7
+ Layout/LineLength:
8
+ Enabled: false
9
+
10
+ # One case statement in a single method isn't complex.
11
+ Metrics/CyclomaticComplexity:
12
+ IgnoredMethods: ['case']
13
+
14
+ # 10 is a good goal but a little draconian
15
+ Metrics/MethodLength:
16
+ CountAsOne: ['array', 'hash', 'heredoc']
17
+ Max: 15
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.3
data/Gemfile CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in reviewer.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
8
+ gem 'rake', '~> 13.0'
9
9
 
10
- gem "minitest", "~> 5.0"
10
+ gem 'minitest', '~> 5.0'
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- reviewer (0.1.1)
4
+ reviewer (0.1.2)
5
5
  activesupport
6
+ colorize
6
7
  slop
7
8
 
8
9
  GEM
@@ -14,23 +15,58 @@ GEM
14
15
  minitest (>= 5.1)
15
16
  tzinfo (~> 2.0)
16
17
  zeitwerk (~> 2.3)
18
+ ast (2.4.2)
19
+ bundler-audit (0.8.0)
20
+ bundler (>= 1.2.0, < 3)
21
+ thor (~> 1.0)
22
+ colorize (0.8.1)
17
23
  concurrent-ruby (1.1.8)
18
24
  i18n (1.8.10)
19
25
  concurrent-ruby (~> 1.0)
20
26
  minitest (5.14.4)
27
+ parallel (1.20.1)
28
+ parser (3.0.1.0)
29
+ ast (~> 2.4.1)
30
+ rainbow (3.0.0)
21
31
  rake (13.0.3)
32
+ regexp_parser (2.1.1)
33
+ rexml (3.2.5)
34
+ rubocop (1.13.0)
35
+ parallel (~> 1.10)
36
+ parser (>= 3.0.0.0)
37
+ rainbow (>= 2.2.2, < 4.0)
38
+ regexp_parser (>= 1.8, < 3.0)
39
+ rexml
40
+ rubocop-ast (>= 1.2.0, < 2.0)
41
+ ruby-progressbar (~> 1.7)
42
+ unicode-display_width (>= 1.4.0, < 3.0)
43
+ rubocop-ast (1.4.1)
44
+ parser (>= 2.7.1.5)
45
+ rubocop-minitest (0.11.1)
46
+ rubocop (>= 0.90, < 2.0)
47
+ rubocop-rake (0.5.1)
48
+ rubocop
49
+ ruby-progressbar (1.11.0)
22
50
  slop (4.8.2)
51
+ thor (1.1.0)
23
52
  tzinfo (2.0.4)
24
53
  concurrent-ruby (~> 1.0)
54
+ unicode-display_width (2.0.0)
25
55
  zeitwerk (2.4.2)
26
56
 
27
57
  PLATFORMS
58
+ ruby
28
59
  x86_64-darwin-19
60
+ x86_64-linux
29
61
 
30
62
  DEPENDENCIES
63
+ bundler-audit
31
64
  minitest (~> 5.0)
32
65
  rake (~> 13.0)
33
66
  reviewer!
67
+ rubocop
68
+ rubocop-minitest
69
+ rubocop-rake
34
70
 
35
71
  BUNDLED WITH
36
72
  2.2.16
data/README.md CHANGED
@@ -1,8 +1,28 @@
1
+ **Note:** As of May 4th, 2021, Reviewer is a work in progress and does not actually do anything just yet. Hopefully soon.
2
+
1
3
  # Reviewer
2
4
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/reviewer`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ Reviewer reduces the friction of using automated tools for dependency audits, static analysis, linting, testing, and more by providing a standardized way to configure and run them in different contexts with less friction.
6
+
7
+ So, instead of...
8
+ ```
9
+ yarn audit --level moderate
10
+ bundle exec bundle-audit check --no-update
11
+ bundle exec rubocop --parallel
12
+ bundle exec erblint --lint-all --enable-all-linters
13
+ yarn stylelint .
14
+ yarn eslint .
15
+ bundle exec rake notes
16
+ ```
17
+
18
+ You run...
19
+ ```
20
+ ./bin/rvw
21
+ ```
22
+
23
+ Having a simpler command is just the beginning through. It also cleans up the output and lets you run subsets of commands.
4
24
 
5
- TODO: Delete this and the text above, and describe your gem
25
+ For more detailed information, take a look at the [Overview](https://github.com/garrettdimon/reviewer/wiki/Overview) and [Usage](https://github.com/garrettdimon/reviewer/wiki/Usage) pages in the wiki.
6
26
 
7
27
  ## Installation
8
28
 
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rake/testtask"
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
5
 
6
6
  Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
9
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
10
  end
11
11
 
12
12
  task default: :test
data/bin/console CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "reviewer"
4
+ require 'bundler/setup'
5
+ require 'reviewer'
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
9
9
 
10
10
  # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
11
+ # require 'pry'
12
12
  # Pry.start
13
13
 
14
- require "irb"
14
+ require 'irb'
15
15
  IRB.start(__FILE__)
data/bin/fmt ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/reviewer'
4
+
5
+ Reviewer.format
data/bin/{review → rvw} RENAMED
File without changes
data/lib/reviewer.rb CHANGED
@@ -1,31 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "reviewer/arguments"
4
- require_relative "reviewer/configuration"
5
- require_relative "reviewer/loader"
6
- require_relative "reviewer/tool"
7
- require_relative "reviewer/tools"
8
- require_relative "reviewer/version"
9
-
3
+ require 'active_support/core_ext/string'
4
+ require 'benchmark'
5
+
6
+ require_relative 'reviewer/configuration'
7
+ require_relative 'reviewer/arguments'
8
+ require_relative 'reviewer/loader'
9
+ require_relative 'reviewer/logger'
10
+ require_relative 'reviewer/runner'
11
+ require_relative 'reviewer/tool'
12
+ require_relative 'reviewer/tools'
13
+ require_relative 'reviewer/version'
14
+
15
+ # Primary interface for the reviewer tools
10
16
  module Reviewer
11
17
  class Error < StandardError; end
12
18
 
13
19
  class << self
14
- attr_writer :configuration
20
+ attr_writer :configuration, :logger
15
21
  end
16
22
 
17
23
  def self.review
18
- options = Arguments.new
19
- # TODO: Make it actually run the tools.
20
- puts "Running with the following options:"
21
- pp options
24
+ elapsed_time = Benchmark.realtime do
25
+ Tools.all.each do |tool|
26
+ next if tool.disabled?
27
+
28
+ exit_status = Runner.new(tool, :review).run
29
+
30
+ break unless exit_status <= tool.max_exit_status
31
+ end
32
+ end
33
+ puts "\n➤ Total Time: #{elapsed_time.round(3)}s\n"
22
34
  end
23
35
 
24
36
  def self.format
25
- options = Arguments.new
26
- # TODO: Make it actually run the tools.
27
- puts "Running with the following options:"
28
- pp options
37
+ # options = Arguments.new
38
+ Tools.all.each do |tool|
39
+ Runner.run(tool, :format)
40
+ end
29
41
  end
30
42
 
31
43
  def self.configuration
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'slop'
4
4
 
5
- # Handles option parsing for bin/review
6
5
  module Reviewer
6
+ # Handles option parsing for bin/review
7
7
  class Arguments
8
8
  attr_accessor :options
9
9
 
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reviewer
4
+ # Configuration for Reviewer
4
5
  class Configuration
5
6
  DEFAULT_CONFIGURATION_PATH = Dir.pwd.freeze
6
- DEFAULT_CONFIGURATION_FILE = '.reviewer.yml'.freeze
7
+ DEFAULT_CONFIGURATION_FILE = '.reviewer.yml'
7
8
 
8
9
  attr_accessor :file
9
10
 
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
- require "active_support/core_ext/hash/indifferent_access"
3
+ require 'yaml'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
5
 
6
- # Provides a collection of the configured tools
7
6
  module Reviewer
7
+ # Provides a collection of the configured tools
8
8
  class Loader
9
9
  class MissingConfigurationError < StandardError; end
10
+
10
11
  class InvalidConfigurationError < StandardError; end
11
12
 
12
13
  attr_reader :configuration
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+
5
+ module Reviewer
6
+ # Clean formatter for logging to $stdout
7
+ class StandardOutFormatter < ::Logger::Formatter
8
+ def call(_severity, _time, _progname, message)
9
+ "#{message}\n"
10
+ end
11
+ end
12
+
13
+ # Logger for $stdout
14
+ class Logger < ::Logger
15
+ SUCCESS = 'Success'
16
+ FAILURE = 'Failure ·'
17
+ PROMPT = '$'
18
+
19
+ def initialize(formatter = StandardOutFormatter.new)
20
+ super($stdout)
21
+ @formatter = formatter
22
+ end
23
+
24
+ def running(tool)
25
+ info "\n#{tool.name}".bold + ' · '.light_black + tool.description
26
+ end
27
+
28
+ def command(cmd)
29
+ info "#{PROMPT} #{cmd}".light_black
30
+ end
31
+
32
+ def rerunning(tool)
33
+ info "\n\nRe-running #{tool.name} verbosely:"
34
+ end
35
+
36
+ def success(elapsed_time)
37
+ info SUCCESS.green.bold + " (#{elapsed_time.round(3)}s)".green
38
+ end
39
+
40
+ def failure(message)
41
+ info "#{FAILURE} #{message}".red.bold
42
+ end
43
+
44
+ def guidance(summary, details)
45
+ info " #{summary}" if summary
46
+ info " #{details}".light_black if details
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module Reviewer
6
+ # Handles running, benchmarking, and printing output for a command
7
+ class Runner
8
+ COMMAND_NOT_FOUND_EXIT_STATUS_CODE = 127
9
+
10
+ attr_accessor :tool, :command
11
+
12
+ attr_reader :elapsed_time, :stdout, :stderr, :status, :exit_status, :logger
13
+
14
+ def initialize(tool, command, logger: Logger.new)
15
+ @tool = tool
16
+ @command = command
17
+ @logger = logger
18
+ end
19
+
20
+ def run
21
+ logger.running(tool)
22
+
23
+ @elapsed_time = Benchmark.realtime do
24
+ prepare
25
+ review
26
+ end
27
+
28
+ print_result
29
+ exit_status
30
+ end
31
+
32
+ private
33
+
34
+ def shell_out(cmd)
35
+ @stdout, @stderr, @status = Open3.capture3(cmd)
36
+ @exit_status = status.exitstatus
37
+
38
+ logger.command(cmd) unless status.success?
39
+ end
40
+
41
+ def prepare
42
+ shell_out(tool.preparation_command) if tool.prepare_command?
43
+ end
44
+
45
+ def review
46
+ shell_out(tool.review_command(seed: seed))
47
+ end
48
+
49
+ def format
50
+ shell_out(tool.format_command) if tool.format_command?
51
+ end
52
+
53
+ def review_verbosely
54
+ cmd = tool.review_command(:no_silence, seed: seed)
55
+ logger.rerunning(tool)
56
+ logger.command(cmd)
57
+ system(cmd)
58
+ end
59
+
60
+ def print_result
61
+ if status.success?
62
+ # Outputs success details
63
+ logger.success(elapsed_time)
64
+ else
65
+ recovery_guidance
66
+ end
67
+ end
68
+
69
+ def recovery_guidance
70
+ logger.failure(error_message)
71
+ if missing_executable?
72
+ missing_executable_guidance
73
+ else
74
+ review_verbosely
75
+ end
76
+ end
77
+
78
+ def error_message
79
+ if missing_executable?
80
+ "Missing executable for '#{tool}'"
81
+ else
82
+ "Exit Status #{exit_status}"
83
+ end
84
+ end
85
+
86
+ def missing_executable_guidance
87
+ logger.guidance('Installation Command:', tool.installation_command) if tool.install_command?
88
+ logger.guidance('Installation Help:', tool.settings.links[:install]) if tool.install_link?
89
+ end
90
+
91
+ def missing_executable?
92
+ (@exit_status == COMMAND_NOT_FOUND_EXIT_STATUS_CODE) ||
93
+ stderr.include?("can't find executable")
94
+ end
95
+
96
+ def seed
97
+ # Keep the same seed for each instance so re-running generates the same results as the failure.
98
+ # Otherwise, re-running after the failure will change the seed and show different results.
99
+ @seed ||= Random.rand(100_000)
100
+ end
101
+ end
102
+ end
data/lib/reviewer/tool.rb CHANGED
@@ -1,38 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/string"
4
- require_relative "tool/command"
5
- require_relative "tool/env"
6
- require_relative "tool/flags"
7
- require_relative "tool/settings"
8
- require_relative "tool/verbosity"
9
-
10
- # Provides an instance of a specific tool
3
+ require_relative 'tool/command'
4
+ require_relative 'tool/env'
5
+ require_relative 'tool/flags'
6
+ require_relative 'tool/settings'
7
+ require_relative 'tool/verbosity'
8
+
11
9
  module Reviewer
10
+ # Provides an instance of a specific tool
12
11
  class Tool
13
12
  attr_reader :settings
14
13
 
14
+ delegate :name,
15
+ :description,
16
+ :enabled?,
17
+ :disabled?,
18
+ :max_exit_status,
19
+ :prepare_command?,
20
+ :install_command?,
21
+ :format_command?,
22
+ :install_link?,
23
+ to: :settings
24
+
15
25
  def initialize(tool)
16
26
  @settings = Settings.new(tool)
17
27
  end
18
28
 
29
+ def to_s
30
+ name
31
+ end
32
+
19
33
  def installation_command(verbosity_level = :no_silence)
20
34
  command_string(:install, verbosity_level: verbosity_level)
21
35
  end
22
36
 
23
- def preparation_command(verbosity_level = :no_silence)
24
- command_string(:prepare, verbosity_level: verbosity_level)
37
+ def preparation_command(verbosity_level = :total_silence)
38
+ command_string(:prepare, verbosity_level: verbosity_level)
25
39
  end
26
40
 
27
- def review_command(verbosity_level = :total_silence)
28
- command_string(:review, verbosity_level: verbosity_level)
41
+ def review_command(verbosity_level = :total_silence, seed: nil)
42
+ command_string(:review, verbosity_level: verbosity_level).gsub('$SEED', seed.to_s)
29
43
  end
30
44
 
31
45
  def format_command(verbosity_level = :no_silence)
32
46
  command_string(:format, verbosity_level: verbosity_level)
33
47
  end
34
48
 
35
-
36
49
  private
37
50
 
38
51
  def command_string(command_type, verbosity_level: :no_silence)
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Assembles tool tool_settings into a usable command string
4
3
  module Reviewer
5
4
  class Tool
5
+ # Assembles tool tool_settings into a usable command string
6
6
  class Command
7
7
  class InvalidTypeError < StandardError; end
8
+
8
9
  class NotConfiguredError < StandardError; end
9
10
 
10
11
  TYPES = %i[install prepare review format].freeze
@@ -21,9 +22,9 @@ module Reviewer
21
22
 
22
23
  def to_s
23
24
  to_a
24
- .map(&:strip)
25
- .join(' ')
26
- .strip
25
+ .map(&:strip) # Remove extra spaces on the components
26
+ .join(' ') # Merge the components
27
+ .strip # Strip extra spaces from the end result
27
28
  end
28
29
 
29
30
  def to_a
@@ -44,17 +45,18 @@ module Reviewer
44
45
  end
45
46
 
46
47
  def flags
47
- # :review commands are the only commands that use flags (except the :quiet_flag)
48
- return nil unless review?
48
+ # :review commands are the only commands that use flags
49
+ # And if no flags are configured, this won't do much
50
+ # Flags for 'quiet' are handled separately by design and excluded from this check.
51
+ return nil unless review? && tool_settings.flags.any?
49
52
 
50
53
  Flags.new(tool_settings.flags).to_s
51
54
  end
52
55
 
53
56
  def verbosity
54
- Verbosity.new(tool_settings.quiet_flag, level: verbosity_level).to_s
57
+ Verbosity.new(tool_settings.quiet_option, level: verbosity_level).to_s
55
58
  end
56
59
 
57
-
58
60
  private
59
61
 
60
62
  def review?
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Assembles tool environment variables into a single string or array
4
3
  module Reviewer
5
4
  class Tool
5
+ # Assembles tool environment variables into a single string or array
6
6
  class Env
7
7
  attr_reader :env_pairs
8
8
 
@@ -20,7 +20,6 @@ module Reviewer
20
20
  env
21
21
  end
22
22
 
23
-
24
23
  private
25
24
 
26
25
  def env(key, value)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Assembles tool flag settings into a single string or array
4
3
  module Reviewer
5
4
  class Tool
5
+ # Assembles tool flag settings into a single string or array
6
6
  class Flags
7
7
  attr_reader :flag_pairs
8
8
 
@@ -20,7 +20,6 @@ module Reviewer
20
20
  flags
21
21
  end
22
22
 
23
-
24
23
  private
25
24
 
26
25
  def flag(key, value)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Converts/casts tool configuration values and provides default values if not set
4
3
  module Reviewer
5
4
  class Tool
5
+ # Converts/casts tool configuration values and provides default values if not set
6
6
  class Settings
7
7
  class MissingReviewCommandError < StandardError; end
8
8
 
@@ -14,17 +14,33 @@ module Reviewer
14
14
 
15
15
  # Ideally, folks would fill out everything, but realistically, the 'review' command is the only required value.
16
16
  # If the key is missing, or maybe there was a typo, fail right away.
17
- raise MissingReviewCommandError, "'#{name}' does not have a 'review' key under 'commands' in your tools configuration" unless commands.key?(:review)
17
+ raise MissingReviewCommandError, "'#{key}' does not have a 'review' key under 'commands' in `#{Reviewer.configuration.file}`" unless commands.key?(:review)
18
18
  end
19
19
 
20
20
  def disabled?
21
- config.fetch(:disabled) { false }
21
+ config.fetch(:disabled, false)
22
22
  end
23
23
 
24
24
  def enabled?
25
25
  !disabled?
26
26
  end
27
27
 
28
+ def prepare_command?
29
+ commands.key?(:prepare) && commands[:prepare].present?
30
+ end
31
+
32
+ def install_command?
33
+ commands.key?(:install) && commands[:install].present?
34
+ end
35
+
36
+ def format_command?
37
+ commands.key?(:format) && commands[:format].present?
38
+ end
39
+
40
+ def install_link?
41
+ links.key?(:install) && links[:install].present?
42
+ end
43
+
28
44
  def key
29
45
  tool.to_sym
30
46
  end
@@ -58,11 +74,11 @@ module Reviewer
58
74
  end
59
75
 
60
76
  def max_exit_status
61
- commands.fetch(:max_exit_status) { 0 }
77
+ commands.fetch(:max_exit_status, 0)
62
78
  end
63
79
 
64
- def quiet_flag
65
- commands.fetch(:quiet_flag) { '' }
80
+ def quiet_option
81
+ commands.fetch(:quiet_option, '')
66
82
  end
67
83
  end
68
84
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Assembles tool settings and provided context for silencing output
4
3
  module Reviewer
5
4
  class Tool
5
+ # Assembles tool settings and provided context for silencing output
6
6
  class Verbosity
7
7
  class InvalidLevelError < StandardError; end
8
8
  # :total_silence = Use the quiet flag and send everything to dev/null.
@@ -11,20 +11,20 @@ module Reviewer
11
11
  # :tool_silence = Just the quiet flag
12
12
  # :no_silence = Let the output scroll for eternity
13
13
  LEVELS = %i[total_silence tool_silence no_silence].freeze
14
- SEND_TO_DEV_NULL = "> /dev/null".freeze
14
+ SEND_TO_DEV_NULL = '> /dev/null'
15
15
 
16
16
  attr_reader :flag, :level
17
17
 
18
- def initialize(flag, level: :total_silence)
18
+ def initialize(flag, level: :tool_silence)
19
19
  @flag = flag
20
20
 
21
- raise InvalidLevelError, "Invalid Verbosity Level: '#{level}'" unless LEVELS.include?(level)
21
+ raise InvalidLevelError, "Invalid Verbosity Level: '#{level}'" unless LEVELS.include?(level)
22
22
 
23
23
  @level = level
24
24
  end
25
25
 
26
26
  def to_s
27
- to_a.join(' ').strip
27
+ to_a.map(&:strip).join(' ').strip
28
28
  end
29
29
 
30
30
  def to_a
@@ -1,18 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Provides a collection of the configured tools
4
3
  module Reviewer
4
+ # Provides a collection of the configured tools
5
5
  module Tools
6
6
  def self.all
7
- []
8
- end
9
-
10
- def self.enabled
11
- []
12
- end
13
-
14
- def self.disabled
15
- []
7
+ tools = []
8
+ Reviewer.configuration.tools.each_key do |key|
9
+ tools << Tool.new(key)
10
+ end
11
+ tools
16
12
  end
17
13
  end
18
14
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reviewer
4
- VERSION = "0.1.1"
4
+ VERSION = '0.1.2'
5
5
  end
data/reviewer.gemspec CHANGED
@@ -1,36 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/reviewer/version"
3
+ require_relative 'lib/reviewer/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "reviewer"
6
+ spec.name = 'reviewer'
7
7
  spec.version = Reviewer::VERSION
8
- spec.authors = ["Garrett Dimon"]
9
- spec.email = ["email@garrettdimon.com"]
8
+ spec.authors = ['Garrett Dimon']
9
+ spec.email = ['email@garrettdimon.com']
10
10
 
11
- spec.summary = "Provides a unified approach to managing automated code quality tools."
12
- spec.description = "Provides a unified approach to managing automated code quality tools."
13
- spec.homepage = "https://github.com/garrettdimon/reviewer"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
11
+ spec.summary = 'Provides a unified approach to managing automated code quality tools.'
12
+ spec.description = 'Provides a unified approach to managing automated code quality tools.'
13
+ spec.homepage = 'https://github.com/garrettdimon/reviewer'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.3')
16
16
 
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/garrettdimon/reviewer"
19
- spec.metadata["changelog_uri"] = "https://github.com/garrettdimon/reviewer/CHANGELOG.md"
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/garrettdimon/reviewer'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/garrettdimon/reviewer/CHANGELOG.md'
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
23
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
25
25
  end
26
- spec.bindir = "exe"
26
+ spec.bindir = 'exe'
27
27
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
28
+ spec.require_paths = ['lib']
29
29
 
30
- # Uncomment to register a new dependency of your gem
31
- spec.add_dependency "activesupport"
32
- spec.add_dependency "slop"
30
+ spec.add_dependency 'activesupport'
31
+ spec.add_dependency 'colorize'
32
+ spec.add_dependency 'slop'
33
33
 
34
- # For more information and examples about making a new gem, checkout our
35
- # guide at: https://bundler.io/guides/creating_gem.html
34
+ spec.add_development_dependency 'bundler-audit'
35
+ spec.add_development_dependency 'rubocop'
36
+ spec.add_development_dependency 'rubocop-minitest'
37
+ spec.add_development_dependency 'rubocop-rake'
36
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reviewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett Dimon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-18 00:00:00.000000000 Z
11
+ date: 2021-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: slop
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,62 @@ dependencies:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler-audit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
41
111
  description: Provides a unified approach to managing automated code quality tools.
42
112
  email:
43
113
  - email@garrettdimon.com
@@ -47,6 +117,10 @@ extra_rdoc_files: []
47
117
  files:
48
118
  - ".github/workflows/main.yml"
49
119
  - ".gitignore"
120
+ - ".reviewer.example.yml"
121
+ - ".reviewer.yml"
122
+ - ".rubocop.yml"
123
+ - ".ruby-version"
50
124
  - CHANGELOG.md
51
125
  - CODE_OF_CONDUCT.md
52
126
  - Gemfile
@@ -55,12 +129,15 @@ files:
55
129
  - README.md
56
130
  - Rakefile
57
131
  - bin/console
58
- - bin/review
132
+ - bin/fmt
133
+ - bin/rvw
59
134
  - bin/setup
60
135
  - lib/reviewer.rb
61
136
  - lib/reviewer/arguments.rb
62
137
  - lib/reviewer/configuration.rb
63
138
  - lib/reviewer/loader.rb
139
+ - lib/reviewer/logger.rb
140
+ - lib/reviewer/runner.rb
64
141
  - lib/reviewer/tool.rb
65
142
  - lib/reviewer/tool/command.rb
66
143
  - lib/reviewer/tool/env.rb
@@ -85,14 +162,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
162
  requirements:
86
163
  - - ">="
87
164
  - !ruby/object:Gem::Version
88
- version: 2.4.0
165
+ version: 2.7.3
89
166
  required_rubygems_version: !ruby/object:Gem::Requirement
90
167
  requirements:
91
168
  - - ">="
92
169
  - !ruby/object:Gem::Version
93
170
  version: '0'
94
171
  requirements: []
95
- rubygems_version: 3.2.16
172
+ rubygems_version: 3.1.6
96
173
  signing_key:
97
174
  specification_version: 4
98
175
  summary: Provides a unified approach to managing automated code quality tools.