quiet_quality 1.0.3 → 1.1.0

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: d7372d3c4b395adb2890c54270426bf92b9a2a9e2669ef27d5145eda776d1072
4
- data.tar.gz: 5877277009b82e9685e62f8f8a1f17aec823faaad93c3c8e40dcb7f2640d0e7c
3
+ metadata.gz: b6aea488d2026da63fdf9483d1df9bd4e2363270d7b441cbca384cd803cab803
4
+ data.tar.gz: 0536d6eb0b8cdd1c4678f49058be4d37017b7ff6156d363afa71df8a979d30aa
5
5
  SHA512:
6
- metadata.gz: 4c860d24410fd6a03390e726fdc699113f3d0c21b722e12ccf564c666b5708690d8ed90a092448f3942496a47331e10b3d3bb7580ba2e0feeafbf74ea60bdb03
7
- data.tar.gz: 67b89da10e8fc43370d586d9282776c2f1f23a0fa4fcfbea5bfd596ab6520cca7c9319731fd960c63dc04e36ab7021b83e27497d52f2e10b8cdd9ef8a39ad394
6
+ metadata.gz: 766f24f8211b83610c05e57b0f81d77bbf2d4bf8c206cc5e9af1d4e302adc9fee6425c506b344850a1421b7a30f18b6dfa6a23132aaa64dc3e6fbeb5e59c4c0b
7
+ data.tar.gz: 7b72dcf22a6696b2ff88a5efb08fb0338d2d4f0b43f506f147a2d5cb0ed7186328157ff4b8ded7198fff3785f6636b32d8b1ecd1102cd462b341f28c57dfd429
data/README.md CHANGED
@@ -144,6 +144,22 @@ And then each tool can have an entry, within which `changed_files` and
144
144
  `filter_messages` can be specified - the tool-specific settings override the
145
145
  global ones.
146
146
 
147
+ The tools have one additional setting that is not available at a global level:
148
+ `file_filter`. This is a string that will be turned into a _ruby regex_, and
149
+ used to limit what file paths are passed to the tool. For example, if you are
150
+ working in a rails engine `engines/foo/`, and you touch one of the rspec tests
151
+ there, you would not want `qq` in the root of the repository to run
152
+ `rspec engines/foo/spec/foo/thing_spec.rb` - that probably won't work, as your
153
+ engine will have its own test setup code and Gemfile. This setting is mostly
154
+ intended to be used like this:
155
+
156
+ ```yaml
157
+ rspec:
158
+ changed_files: true
159
+ filter_messages: false
160
+ file_filter: "^spec/"
161
+ ```
162
+
147
163
  ### CLI Options
148
164
 
149
165
  The same options are all available on the CLI, plus some additional ones - run
@@ -151,5 +167,6 @@ The same options are all available on the CLI, plus some additional ones - run
151
167
 
152
168
  * `--help/-H`: See a list of the options
153
169
  * `--no-config/-N`: Do _not_ load a config file, even if present.
154
- * `--config/-C` load the supplied config file (instead of the detected one, if
170
+ * `--config/-C`: load the supplied config file (instead of the detected one, if
155
171
  found)
172
+ * `--version/-V`: what version of the gem are you using?
@@ -76,6 +76,10 @@ module QuietQuality
76
76
  parser.on("-h", "--help", "Prints this help") do
77
77
  @parsed_options.helping = true
78
78
  end
79
+
80
+ parser.on("-V", "--version", "Print the current version of the gem") do
81
+ @parsed_options.printing_version = true
82
+ end
79
83
  end
80
84
 
81
85
  def setup_config_options(parser)
@@ -10,6 +10,10 @@ module QuietQuality
10
10
  def execute
11
11
  if helping?
12
12
  log_help_text
13
+ elsif printing_version?
14
+ log_version_text
15
+ elsif no_tools?
16
+ log_no_tools_text
13
17
  else
14
18
  executed
15
19
  log_outcomes
@@ -21,7 +25,9 @@ module QuietQuality
21
25
  end
22
26
 
23
27
  def successful?
24
- helping? || !executed.any_failure?
28
+ return true if helping? || printing_version?
29
+ return false if no_tools?
30
+ !executed.any_failure?
25
31
  end
26
32
 
27
33
  private
@@ -40,10 +46,29 @@ module QuietQuality
40
46
  parsed_options.helping?
41
47
  end
42
48
 
49
+ def printing_version?
50
+ parsed_options.printing_version?
51
+ end
52
+
53
+ def no_tools?
54
+ options.tools.empty?
55
+ end
56
+
43
57
  def log_help_text
44
58
  error_stream.puts(arg_parser.help_text)
45
59
  end
46
60
 
61
+ def log_version_text
62
+ error_stream.puts(QuietQuality::VERSION)
63
+ end
64
+
65
+ def log_no_tools_text
66
+ error_stream.puts(<<~TEXT)
67
+ You must specify one or more tools to run, either on the command-line or in the
68
+ default_tools key in a configuration file.
69
+ TEXT
70
+ end
71
+
47
72
  def options
48
73
  return @_options if defined?(@_options)
49
74
  builder = Config::Builder.new(parsed_cli_options: parsed_options)
@@ -28,7 +28,7 @@ module QuietQuality
28
28
  elsif config_file&.tools&.any?
29
29
  config_file.tools
30
30
  else
31
- Tools::AVAILABLE.keys
31
+ []
32
32
  end
33
33
  end
34
34
 
@@ -109,6 +109,7 @@ module QuietQuality
109
109
  options.tools.each do |tool_options|
110
110
  update_tool_option(tool_options, :limit_targets)
111
111
  update_tool_option(tool_options, :filter_messages)
112
+ update_tool_option(tool_options, :file_filter)
112
113
  end
113
114
  end
114
115
 
@@ -5,16 +5,20 @@ module QuietQuality
5
5
  @tools = []
6
6
  @tool_options = {}
7
7
  @global_options = {}
8
- @helping = false
8
+ @helping = @printing_version = false
9
9
  end
10
10
 
11
11
  attr_accessor :tools
12
- attr_writer :helping
12
+ attr_writer :helping, :printing_version
13
13
 
14
14
  def helping?
15
15
  @helping
16
16
  end
17
17
 
18
+ def printing_version?
19
+ @printing_version
20
+ end
21
+
18
22
  def set_global_option(name, value)
19
23
  @global_options[name.to_sym] = value
20
24
  end
@@ -38,11 +38,14 @@ module QuietQuality
38
38
  end
39
39
 
40
40
  def store_global_options(opts)
41
- read_global_option(opts, :executor, as: :symbol, validate_from: Executors::AVAILABLE)
42
- read_global_option(opts, :annotator, as: :symbol, validate_from: Annotators::ANNOTATOR_TYPES)
43
- read_global_option(opts, :comparison_branch, as: :string)
44
- read_global_option(opts, :changed_files, as: :boolean)
45
- read_global_option(opts, :filter_messages, as: :boolean)
41
+ read_global_option(opts, :executor, :executor, as: :symbol, validate_from: Executors::AVAILABLE)
42
+ read_global_option(opts, :annotator, :annotator, as: :symbol, validate_from: Annotators::ANNOTATOR_TYPES)
43
+ read_global_option(opts, :annotate, :annotator, as: :symbol, validate_from: Annotators::ANNOTATOR_TYPES)
44
+ read_global_option(opts, :comparison_branch, :comparison_branch, as: :string)
45
+ read_global_option(opts, :changed_files, :changed_files, as: :boolean)
46
+ read_global_option(opts, :all_files, :changed_files, as: :reversed_boolean)
47
+ read_global_option(opts, :filter_messages, :filter_messages, as: :boolean)
48
+ read_global_option(opts, :unfiltered, :filter_messages, as: :reversed_boolean)
46
49
  end
47
50
 
48
51
  def store_tool_options(opts)
@@ -54,8 +57,12 @@ module QuietQuality
54
57
  def store_tool_options_for(opts, tool_name)
55
58
  entries = data.fetch(tool_name, nil)
56
59
  return if entries.nil?
57
- read_tool_option(opts, tool_name, :filter_messages, as: :boolean)
58
- read_tool_option(opts, tool_name, :changed_files, as: :boolean)
60
+
61
+ read_tool_option(opts, tool_name, :filter_messages, :filter_messages, as: :boolean)
62
+ read_tool_option(opts, tool_name, :unfiltered, :filter_messages, as: :reversed_boolean)
63
+ read_tool_option(opts, tool_name, :changed_files, :changed_files, as: :boolean)
64
+ read_tool_option(opts, tool_name, :all_files, :changed_files, as: :reversed_boolean)
65
+ read_tool_option(opts, tool_name, :file_filter, :file_filter, as: :string)
59
66
  end
60
67
 
61
68
  def invalid!(message)
@@ -70,27 +77,28 @@ module QuietQuality
70
77
  [true, false].include?(value)
71
78
  end
72
79
 
73
- def read_global_option(opts, name, as:, validate_from: nil)
80
+ def read_global_option(opts, name, into, as:, validate_from: nil)
74
81
  parsed_value = data.fetch(name.to_sym, nil)
75
82
  return if parsed_value.nil?
76
83
 
77
84
  validate_value(name, parsed_value, as: as, from: validate_from)
78
85
  coerced_value = coerce_value(parsed_value, as: as)
79
- opts.set_global_option(name, coerced_value)
86
+ opts.set_global_option(into, coerced_value)
80
87
  end
81
88
 
82
- def read_tool_option(opts, tool, name, as:)
89
+ def read_tool_option(opts, tool, name, into, as:)
83
90
  parsed_value = data.dig(tool.to_sym, name.to_sym)
84
91
  return if parsed_value.nil?
85
92
 
86
93
  validate_value("#{tool}.#{name}", parsed_value, as: as)
87
94
  coerced_value = coerce_value(parsed_value, as: as)
88
- opts.set_tool_option(tool, name, coerced_value)
95
+ opts.set_tool_option(tool, into, coerced_value)
89
96
  end
90
97
 
91
98
  def validate_value(name, value, as:, from: nil)
92
99
  case as
93
100
  when :boolean then validate_boolean(name, value)
101
+ when :reversed_boolean then validate_boolean(name, value)
94
102
  when :symbol then validate_symbol(name, value, from: from)
95
103
  when :string then validate_string(name, value)
96
104
  else
@@ -123,6 +131,7 @@ module QuietQuality
123
131
  def coerce_value(value, as:)
124
132
  case as
125
133
  when :boolean then !!value
134
+ when :reversed_boolean then !value
126
135
  when :string then value.to_s
127
136
  when :symbol then value.to_sym
128
137
  else
@@ -1,14 +1,15 @@
1
1
  module QuietQuality
2
2
  module Config
3
3
  class ToolOptions
4
- def initialize(tool, limit_targets: true, filter_messages: true)
4
+ def initialize(tool, limit_targets: true, filter_messages: true, file_filter: nil)
5
5
  @tool_name = tool.to_sym
6
6
  @limit_targets = limit_targets
7
7
  @filter_messages = filter_messages
8
+ @file_filter = file_filter
8
9
  end
9
10
 
10
11
  attr_reader :tool_name
11
- attr_writer :limit_targets, :filter_messages
12
+ attr_writer :limit_targets, :filter_messages, :file_filter
12
13
 
13
14
  def limit_targets?
14
15
  @limit_targets
@@ -29,6 +30,11 @@ module QuietQuality
29
30
  def parser_class
30
31
  tool_namespace::Parser
31
32
  end
33
+
34
+ def file_filter
35
+ return nil if @file_filter.nil?
36
+ Regexp.new(@file_filter)
37
+ end
32
38
  end
33
39
  end
34
40
  end
@@ -48,8 +48,10 @@ module QuietQuality
48
48
  end
49
49
 
50
50
  def runner
51
- @_runner ||= tool_options.runner_class
52
- .new(changed_files: limit_targets? ? changed_files : nil)
51
+ @_runner ||= tool_options.runner_class.new(
52
+ changed_files: limit_targets? ? changed_files : nil,
53
+ file_filter: tool_options.file_filter
54
+ )
53
55
  end
54
56
 
55
57
  def parser
@@ -6,8 +6,12 @@ module QuietQuality
6
6
  # https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman.rb#L6-L25
7
7
  KNOWN_EXIT_STATUSES = [3, 4, 5, 6, 7, 8].to_set
8
8
 
9
- def initialize(changed_files: nil)
9
+ # brakeman does not support being run against a portion of the project, so neither
10
+ # changed_files nor file_filter is actually used. But they are accepted here because
11
+ # that is what Runner initializers are required to accept.
12
+ def initialize(changed_files: nil, file_filter: nil)
10
13
  @changed_files = changed_files
14
+ @file_filter = file_filter
11
15
  end
12
16
 
13
17
  def invoke!
@@ -11,8 +11,9 @@ module QuietQuality
11
11
  # encountered"
12
12
  FAILURE_STATUS = 65
13
13
 
14
- def initialize(changed_files: nil)
14
+ def initialize(changed_files: nil, file_filter: nil)
15
15
  @changed_files = changed_files
16
+ @file_filter = file_filter
16
17
  end
17
18
 
18
19
  def invoke!
@@ -21,7 +22,7 @@ module QuietQuality
21
22
 
22
23
  private
23
24
 
24
- attr_reader :changed_files
25
+ attr_reader :changed_files, :file_filter
25
26
 
26
27
  def skip_execution?
27
28
  changed_files && relevant_files.empty?
@@ -29,7 +30,9 @@ module QuietQuality
29
30
 
30
31
  def relevant_files
31
32
  return nil if changed_files.nil?
32
- changed_files.paths.select { |path| path.end_with?(".haml") }
33
+ changed_files.paths
34
+ .select { |path| path.end_with?(".haml") }
35
+ .select { |path| file_filter.nil? || file_filter.match?(path) }
33
36
  end
34
37
 
35
38
  def target_files
@@ -5,8 +5,9 @@ module QuietQuality
5
5
  MAX_FILES = 100
6
6
  NO_FILES_OUTPUT = '{"examples": [], "summary": {"failure_count": 0}}'
7
7
 
8
- def initialize(changed_files: nil)
8
+ def initialize(changed_files: nil, file_filter: nil)
9
9
  @changed_files = changed_files
10
+ @file_filter = file_filter
10
11
  end
11
12
 
12
13
  def invoke!
@@ -15,7 +16,7 @@ module QuietQuality
15
16
 
16
17
  private
17
18
 
18
- attr_reader :changed_files
19
+ attr_reader :changed_files, :file_filter
19
20
 
20
21
  def skip_execution?
21
22
  changed_files && relevant_files.empty?
@@ -23,7 +24,9 @@ module QuietQuality
23
24
 
24
25
  def relevant_files
25
26
  return nil if changed_files.nil?
26
- changed_files.paths.select { |path| path.end_with?("_spec.rb") }
27
+ changed_files.paths
28
+ .select { |path| path.end_with?("_spec.rb") }
29
+ .select { |path| file_filter.nil? || file_filter.match?(path) }
27
30
  end
28
31
 
29
32
  def target_files
@@ -10,8 +10,9 @@ module QuietQuality
10
10
  end
11
11
 
12
12
  # Supplying changed_files: nil means "run against all files".
13
- def initialize(changed_files: nil)
13
+ def initialize(changed_files: nil, file_filter: nil)
14
14
  @changed_files = changed_files
15
+ @file_filter = file_filter
15
16
  end
16
17
 
17
18
  def invoke!
@@ -20,7 +21,7 @@ module QuietQuality
20
21
 
21
22
  private
22
23
 
23
- attr_reader :changed_files
24
+ attr_reader :changed_files, :file_filter
24
25
 
25
26
  # If we were told that _no files changed_ (which is distinct from not being told that
26
27
  # any files changed - a [] instead of a nil), then we shouldn't run rubocop at all.
@@ -38,7 +39,9 @@ module QuietQuality
38
39
 
39
40
  def relevant_files
40
41
  return nil if changed_files.nil?
41
- changed_files.paths.select { |path| path.end_with?(".rb") }
42
+ changed_files.paths
43
+ .select { |path| path.end_with?(".rb") }
44
+ .select { |path| file_filter.nil? || file_filter.match?(path) }
42
45
  end
43
46
 
44
47
  def target_files
@@ -1,3 +1,3 @@
1
1
  module QuietQuality
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quiet_quality
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
11
+ date: 2023-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -241,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
241
  - !ruby/object:Gem::Version
242
242
  version: '0'
243
243
  requirements: []
244
- rubygems_version: 3.1.6
244
+ rubygems_version: 3.3.7
245
245
  signing_key:
246
246
  specification_version: 4
247
247
  summary: A system for comparing quality tool outputs against the forward diffs