quiet_quality 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/lib/quiet_quality/cli/arg_parser.rb +4 -0
- data/lib/quiet_quality/cli/entrypoint.rb +26 -1
- data/lib/quiet_quality/config/builder.rb +2 -1
- data/lib/quiet_quality/config/parsed_options.rb +6 -2
- data/lib/quiet_quality/config/parser.rb +20 -11
- data/lib/quiet_quality/config/tool_options.rb +8 -2
- data/lib/quiet_quality/executors/pipeline.rb +4 -2
- data/lib/quiet_quality/tools/brakeman/runner.rb +5 -1
- data/lib/quiet_quality/tools/haml_lint/runner.rb +6 -3
- data/lib/quiet_quality/tools/rspec/runner.rb +6 -3
- data/lib/quiet_quality/tools/rubocop/runner.rb +6 -3
- data/lib/quiet_quality/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6aea488d2026da63fdf9483d1df9bd4e2363270d7b441cbca384cd803cab803
|
4
|
+
data.tar.gz: 0536d6eb0b8cdd1c4678f49058be4d37017b7ff6156d363afa71df8a979d30aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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? ||
|
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
|
-
|
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, :
|
44
|
-
read_global_option(opts, :
|
45
|
-
read_global_option(opts, :
|
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
|
-
|
58
|
-
read_tool_option(opts, tool_name, :
|
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(
|
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,
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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-
|
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.
|
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
|