reviewer 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df101aff2f6774a051ec434d758d2a1b9f81366a5c6747ba524dfb711ada5d46
4
- data.tar.gz: 76646cdd12c3ee0c280cbf1dec32745555a18f4a892fc8f10322f6795cf9a22b
3
+ metadata.gz: a5df0f3247eb105862f40b5092bb3c3b25fa20e87e155cb283fc2fd278933987
4
+ data.tar.gz: 06716646a5f980c5d67f89abc4ab4938977c2dd2691101d8cdd924f4481599cf
5
5
  SHA512:
6
- metadata.gz: 28dbb56742a1ddee23e17ff5792bf66bd53cb38d9ebf8e3d00c9a343b92ee6ace22ff19568e123bc01e865d16126dbf4004d12826c0e3b28754a7541e909c3d1
7
- data.tar.gz: b4ee814b4c07a1501000193ba593ca5a5ee06d41954b7bb397174947da26b01c22a45edc56482229b325ff7396ec29ce9c9e8759edf4caaa5dca0405ce16e959
6
+ metadata.gz: 57ca3df253ec35a5544f9a2145733c535688f8be8f0ed6820973563f758563e08a6f3aa729e8743be49945d931cc63a27a21a75e4512d2f9855f1ecad055a9ac
7
+ data.tar.gz: 5b06953f74f63aff8410b27470a37044d764b87b07289554d0ddc3581575d8a6849603a78f656d392273ac6e4d3d358acd91a84cae49a7d49fd427800536d5cb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ - TODO: Add Runner to handle timing, logging, and exit status
4
+ - TODO: Add Targets to handle targeting specific files
5
+ - TODO: Add support for Targets in Tool/Command generator
6
+
7
+ ## [0.1.1] - 2021-04-17
8
+
9
+ It doesn't work just yet, but it's filling out. Primarily, this enables it to parse the configuration file and turn each tool's settings into a runnable command string for install, prepare, review, and format.
10
+
11
+ - Added Configuration Management
12
+ - Added command-line framework with option parsing
13
+ - Created configuration loading bits
14
+ - Built pieces to generate complete command strings
15
+
3
16
  ## [0.1.0] - 2021-04-16
4
17
 
5
18
  - Initial release
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ reviewer (0.1.1)
5
+ activesupport
6
+ slop
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (6.1.3.1)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
16
+ zeitwerk (~> 2.3)
17
+ concurrent-ruby (1.1.8)
18
+ i18n (1.8.10)
19
+ concurrent-ruby (~> 1.0)
20
+ minitest (5.14.4)
21
+ rake (13.0.3)
22
+ slop (4.8.2)
23
+ tzinfo (2.0.4)
24
+ concurrent-ruby (~> 1.0)
25
+ zeitwerk (2.4.2)
26
+
27
+ PLATFORMS
28
+ x86_64-darwin-19
29
+
30
+ DEPENDENCIES
31
+ minitest (~> 5.0)
32
+ rake (~> 13.0)
33
+ reviewer!
34
+
35
+ BUNDLED WITH
36
+ 2.2.16
data/bin/review ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/reviewer'
4
+
5
+ Reviewer.review
data/lib/reviewer.rb CHANGED
@@ -1,8 +1,42 @@
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"
3
8
  require_relative "reviewer/version"
4
9
 
5
10
  module Reviewer
6
11
  class Error < StandardError; end
7
- # Your code goes here...
12
+
13
+ class << self
14
+ attr_writer :configuration
15
+ end
16
+
17
+ 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
22
+ end
23
+
24
+ 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
29
+ end
30
+
31
+ def self.configuration
32
+ @configuration ||= Configuration.new
33
+ end
34
+
35
+ def self.reset
36
+ @configuration = Configuration.new
37
+ end
38
+
39
+ def self.configure
40
+ yield(configuration)
41
+ end
8
42
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slop'
4
+
5
+ # Handles option parsing for bin/review
6
+ module Reviewer
7
+ class Arguments
8
+ attr_accessor :options
9
+
10
+ def initialize(options = ARGV)
11
+ @options = Slop.parse options do |opts|
12
+ opts.array '-f', '--files', 'a list of comma-separated files or paths', delimiter: ',', default: []
13
+ opts.array '-t', '--tags', 'a list of comma-separated tags', delimiter: ',', default: []
14
+
15
+ opts.on '-v', '--version', 'print the version' do
16
+ puts VERSION
17
+ exit
18
+ end
19
+
20
+ opts.on '-h', '--help', 'print the help' do
21
+ puts opts
22
+ exit
23
+ end
24
+ end
25
+ end
26
+
27
+ def files
28
+ options[:files]
29
+ end
30
+
31
+ def tags
32
+ options[:tags]
33
+ end
34
+
35
+ def arguments
36
+ options.arguments
37
+ end
38
+
39
+ def keywords
40
+ # TODO: Filter arguments to only for allowed keywords to be defined later.
41
+ arguments
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reviewer
4
+ class Configuration
5
+ DEFAULT_CONFIGURATION_PATH = Dir.pwd.freeze
6
+ DEFAULT_CONFIGURATION_FILE = '.reviewer.yml'.freeze
7
+
8
+ attr_accessor :file
9
+
10
+ def initialize
11
+ @file = "#{DEFAULT_CONFIGURATION_PATH}/#{DEFAULT_CONFIGURATION_FILE}"
12
+ end
13
+
14
+ def tools
15
+ @tools ||= Loader.new.to_h
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "active_support/core_ext/hash/indifferent_access"
5
+
6
+ # Provides a collection of the configured tools
7
+ module Reviewer
8
+ class Loader
9
+ class MissingConfigurationError < StandardError; end
10
+ class InvalidConfigurationError < StandardError; end
11
+
12
+ attr_reader :configuration
13
+
14
+ def initialize
15
+ @configuration = HashWithIndifferentAccess.new(configuration_hash)
16
+ end
17
+
18
+ def to_h
19
+ configuration
20
+ end
21
+
22
+ private
23
+
24
+ def configuration_hash
25
+ @configuration_hash ||= YAML.load_file(Reviewer.configuration.file)
26
+ rescue Errno::ENOENT
27
+ raise MissingConfigurationError, "Tools configuration file couldn't be found - #{Reviewer.configuration.file}"
28
+ rescue Psych::SyntaxError => e
29
+ raise InvalidConfigurationError, "Tools configuration file has a syntax error - #{e.message}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
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
11
+ module Reviewer
12
+ class Tool
13
+ attr_reader :settings
14
+
15
+ def initialize(tool)
16
+ @settings = Settings.new(tool)
17
+ end
18
+
19
+ def installation_command(verbosity_level = :no_silence)
20
+ command_string(:install, verbosity_level: verbosity_level)
21
+ end
22
+
23
+ def preparation_command(verbosity_level = :no_silence)
24
+ command_string(:prepare, verbosity_level: verbosity_level)
25
+ end
26
+
27
+ def review_command(verbosity_level = :total_silence)
28
+ command_string(:review, verbosity_level: verbosity_level)
29
+ end
30
+
31
+ def format_command(verbosity_level = :no_silence)
32
+ command_string(:format, verbosity_level: verbosity_level)
33
+ end
34
+
35
+
36
+ private
37
+
38
+ def command_string(command_type, verbosity_level: :no_silence)
39
+ cmd = Command.new(command_type, tool_settings: settings, verbosity_level: verbosity_level)
40
+
41
+ cmd.to_s
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Assembles tool tool_settings into a usable command string
4
+ module Reviewer
5
+ class Tool
6
+ class Command
7
+ class InvalidTypeError < StandardError; end
8
+ class NotConfiguredError < StandardError; end
9
+
10
+ TYPES = %i[install prepare review format].freeze
11
+
12
+ attr_reader :command_type, :tool_settings, :verbosity_level
13
+
14
+ def initialize(command_type, tool_settings:, verbosity_level: nil)
15
+ @command_type = command_type
16
+ @tool_settings = tool_settings
17
+ @verbosity_level = verbosity_level
18
+
19
+ verify_command_type!
20
+ end
21
+
22
+ def to_s
23
+ to_a
24
+ .map(&:strip)
25
+ .join(' ')
26
+ .strip
27
+ end
28
+
29
+ def to_a
30
+ [
31
+ env,
32
+ body,
33
+ flags,
34
+ verbosity
35
+ ].compact
36
+ end
37
+
38
+ def env
39
+ Env.new(tool_settings.env).to_s
40
+ end
41
+
42
+ def body
43
+ tool_settings.commands.fetch(command_type)
44
+ end
45
+
46
+ def flags
47
+ # :review commands are the only commands that use flags (except the :quiet_flag)
48
+ return nil unless review?
49
+
50
+ Flags.new(tool_settings.flags).to_s
51
+ end
52
+
53
+ def verbosity
54
+ Verbosity.new(tool_settings.quiet_flag, level: verbosity_level).to_s
55
+ end
56
+
57
+
58
+ private
59
+
60
+ def review?
61
+ command_type == :review
62
+ end
63
+
64
+ def valid_command?
65
+ TYPES.include?(command_type)
66
+ end
67
+
68
+ def command_defined?
69
+ tool_settings.commands.key?(command_type)
70
+ end
71
+
72
+ def verify_command_type!
73
+ raise InvalidTypeError, "'#{body}' is not a supported command type. (Make sure it's not a typo.)" unless valid_command?
74
+ raise NotConfiguredError, "The '#{body}' command is not configured for #{tool_settings.name}. (Make sure it's not a typo.)" unless command_defined?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Assembles tool environment variables into a single string or array
4
+ module Reviewer
5
+ class Tool
6
+ class Env
7
+ attr_reader :env_pairs
8
+
9
+ def initialize(env_pairs)
10
+ @env_pairs = env_pairs
11
+ end
12
+
13
+ def to_s
14
+ to_a.compact.join(' ')
15
+ end
16
+
17
+ def to_a
18
+ env = []
19
+ env_pairs.each { |key, value| env << env(key, value) }
20
+ env
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def env(key, value)
27
+ return nil if key.to_s.blank? || value.to_s.blank?
28
+
29
+ value = needs_quotes?(value) ? "'#{value}'" : value
30
+
31
+ "#{key.to_s.strip.upcase}=#{value.to_s.strip};"
32
+ end
33
+
34
+ def needs_quotes?(value)
35
+ value.is_a?(String) && value.include?(' ')
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Assembles tool flag settings into a single string or array
4
+ module Reviewer
5
+ class Tool
6
+ class Flags
7
+ attr_reader :flag_pairs
8
+
9
+ def initialize(flag_pairs)
10
+ @flag_pairs = flag_pairs
11
+ end
12
+
13
+ def to_s
14
+ to_a.join(' ')
15
+ end
16
+
17
+ def to_a
18
+ flags = []
19
+ flag_pairs.each { |key, value| flags << flag(key, value) }
20
+ flags
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def flag(key, value)
27
+ dash = key.to_s.size == 1 ? '-' : '--'
28
+
29
+ value = needs_quotes?(value) ? "'#{value}'" : value
30
+
31
+ "#{dash}#{key} #{value}".strip
32
+ end
33
+
34
+ def needs_quotes?(value)
35
+ value.is_a?(String) && value.include?(' ')
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Converts/casts tool configuration values and provides default values if not set
4
+ module Reviewer
5
+ class Tool
6
+ class Settings
7
+ class MissingReviewCommandError < StandardError; end
8
+
9
+ attr_reader :tool, :config
10
+
11
+ def initialize(tool, config: nil)
12
+ @tool = tool
13
+ @config = config || Reviewer.configuration.tools.fetch(tool.to_sym) { {} }
14
+
15
+ # Ideally, folks would fill out everything, but realistically, the 'review' command is the only required value.
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)
18
+ end
19
+
20
+ def disabled?
21
+ config.fetch(:disabled) { false }
22
+ end
23
+
24
+ def enabled?
25
+ !disabled?
26
+ end
27
+
28
+ def key
29
+ tool.to_sym
30
+ end
31
+
32
+ def name
33
+ config.fetch(:name) { tool.to_s.titleize }
34
+ end
35
+
36
+ def description
37
+ config.fetch(:description) { "(No description provided for '#{name}')" }
38
+ end
39
+
40
+ def tags
41
+ config.fetch(:tags) { [] }
42
+ end
43
+
44
+ def links
45
+ config.fetch(:links) { {} }
46
+ end
47
+
48
+ def env
49
+ config.fetch(:env) { {} }
50
+ end
51
+
52
+ def flags
53
+ config.fetch(:flags) { {} }
54
+ end
55
+
56
+ def commands
57
+ config.fetch(:commands) { {} }
58
+ end
59
+
60
+ def max_exit_status
61
+ commands.fetch(:max_exit_status) { 0 }
62
+ end
63
+
64
+ def quiet_flag
65
+ commands.fetch(:quiet_flag) { '' }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Assembles tool settings and provided context for silencing output
4
+ module Reviewer
5
+ class Tool
6
+ class Verbosity
7
+ class InvalidLevelError < StandardError; end
8
+ # :total_silence = Use the quiet flag and send everything to dev/null.
9
+ # For some tools "quiet" means "less noisy" rather than truly silent.
10
+ # So in those cases, dev/null handles lingering noise.
11
+ # :tool_silence = Just the quiet flag
12
+ # :no_silence = Let the output scroll for eternity
13
+ LEVELS = %i[total_silence tool_silence no_silence].freeze
14
+ SEND_TO_DEV_NULL = "> /dev/null".freeze
15
+
16
+ attr_reader :flag, :level
17
+
18
+ def initialize(flag, level: :total_silence)
19
+ @flag = flag
20
+
21
+ raise InvalidLevelError, "Invalid Verbosity Level: '#{level}'" unless LEVELS.include?(level)
22
+
23
+ @level = level
24
+ end
25
+
26
+ def to_s
27
+ to_a.join(' ').strip
28
+ end
29
+
30
+ def to_a
31
+ case level
32
+ when :total_silence then [flag, SEND_TO_DEV_NULL].compact
33
+ when :tool_silence then [flag].compact
34
+ when :no_silence then []
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides a collection of the configured tools
4
+ module Reviewer
5
+ module Tools
6
+ def self.all
7
+ []
8
+ end
9
+
10
+ def self.enabled
11
+ []
12
+ end
13
+
14
+ def self.disabled
15
+ []
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reviewer
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/reviewer.gemspec CHANGED
@@ -28,7 +28,8 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  # Uncomment to register a new dependency of your gem
31
- # spec.add_dependency "example-gem", "~> 1.0"
31
+ spec.add_dependency "activesupport"
32
+ spec.add_dependency "slop"
32
33
 
33
34
  # For more information and examples about making a new gem, checkout our
34
35
  # guide at: https://bundler.io/guides/creating_gem.html
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reviewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
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-16 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slop
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'
13
41
  description: Provides a unified approach to managing automated code quality tools.
14
42
  email:
15
43
  - email@garrettdimon.com
@@ -22,12 +50,24 @@ files:
22
50
  - CHANGELOG.md
23
51
  - CODE_OF_CONDUCT.md
24
52
  - Gemfile
53
+ - Gemfile.lock
25
54
  - LICENSE.txt
26
55
  - README.md
27
56
  - Rakefile
28
57
  - bin/console
58
+ - bin/review
29
59
  - bin/setup
30
60
  - lib/reviewer.rb
61
+ - lib/reviewer/arguments.rb
62
+ - lib/reviewer/configuration.rb
63
+ - lib/reviewer/loader.rb
64
+ - lib/reviewer/tool.rb
65
+ - lib/reviewer/tool/command.rb
66
+ - lib/reviewer/tool/env.rb
67
+ - lib/reviewer/tool/flags.rb
68
+ - lib/reviewer/tool/settings.rb
69
+ - lib/reviewer/tool/verbosity.rb
70
+ - lib/reviewer/tools.rb
31
71
  - lib/reviewer/version.rb
32
72
  - reviewer.gemspec
33
73
  homepage: https://github.com/garrettdimon/reviewer