quiet_quality 1.0.2 → 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/.github/workflows/linters.yml +3 -0
- data/.mdl_rules.rb +2 -0
- data/.mdlrc +2 -0
- data/README.md +163 -25
- data/docs/example-config.yml +9 -0
- 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 +16 -5
- 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
- data/quiet_quality.gemspec +1 -0
- metadata +20 -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/.mdl_rules.rb
ADDED
data/.mdlrc
ADDED
data/README.md
CHANGED
@@ -1,34 +1,172 @@
|
|
1
1
|
# QuietQuality
|
2
2
|
|
3
|
-
|
3
|
+
There are a lot of different tools that you need to run as you work - possibly
|
4
|
+
before you commit, or before you make a pull request, or after you make changes
|
5
|
+
to a class.. style checkers, tests, complexity metrics, static analyzers, etc.
|
6
|
+
QuietQuality can make that simpler and faster!
|
4
7
|
|
5
|
-
|
8
|
+
Or you may have a huge existing project, that's not _fully_ in compliance with
|
9
|
+
your style guides, but you want to avoid introducing _new_ issues, without
|
10
|
+
having to first resolve all of the existing ones. QuietQuality can help with
|
11
|
+
that too.
|
6
12
|
|
7
|
-
|
8
|
-
files locally (the files that have changed locally relative to the default branch)
|
9
|
-
2. Let you run those tools in CI (probably github actions) and annotate any issues found
|
10
|
-
with _new or modified_ code, without bothering you about existing issues that you didn't
|
11
|
-
touch.
|
13
|
+
## Tool Support
|
12
14
|
|
15
|
+
So far, we have support for the following tools:
|
13
16
|
|
14
|
-
|
17
|
+
* rubocop
|
18
|
+
* standardrb
|
19
|
+
* rspec
|
20
|
+
* haml-lint
|
21
|
+
* brakeman (though there's no way to run this against only changed files)
|
15
22
|
|
23
|
+
Supporting more tools is relatively straightforward - they're implemented by
|
24
|
+
wrapping cli invocations and parsing output files (which overall seem to be much
|
25
|
+
more stable interfaces than the code interfaces to the various tools), and each
|
26
|
+
tool's support is built orthogonally to the others, in a
|
27
|
+
`QuietQuality::Tools::[Something]` namespace, with a `Runner` and a `Parser`.
|
28
|
+
|
29
|
+
## Local Usage Examples
|
30
|
+
|
31
|
+
Working locally, you'll generally want to commit a `.quiet_quality.yml`
|
32
|
+
configuration file into the root of your repository - it'll specify which tools
|
33
|
+
to run by default, and how to run them (whether you want to only run each tool
|
34
|
+
against the _changed files_, whether to _filter_ the resulting _messages_ down
|
35
|
+
to only those targeting lines that have been changed), and allows you to specify
|
36
|
+
the _comparison branch_, so you don't have to make a request to your origin
|
37
|
+
server every time you run the tool to see whether you're comparing against
|
38
|
+
`master` or `main` in this project.
|
39
|
+
|
40
|
+
If you have a configuration set up like that, you might have details specified
|
41
|
+
for `rubocop`, `rspec`, `standardrb`, and `brakeman`, but have only `rubocop`,
|
42
|
+
`standardrb`, and `rspec` set to run by default. That configuration file would
|
43
|
+
look like this (you can copy it from [here](docs/example-config.yml)):
|
44
|
+
|
45
|
+
```yaml
|
46
|
+
---
|
47
|
+
default_tools: ["standardrb", "rubocop", "rspec"]
|
48
|
+
executor: concurrent
|
49
|
+
comparison_branch: main
|
50
|
+
changed_files: true
|
51
|
+
filter_messages: true
|
52
|
+
brakeman:
|
53
|
+
changed_files: false
|
54
|
+
filter_messages: true
|
55
|
+
```
|
56
|
+
|
57
|
+
Then if you invoke `qq`, you'll see output like this:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
❯ qq
|
61
|
+
--- Passed: standardrb
|
62
|
+
--- Passed: rubocop
|
63
|
+
--- Passed: rspec
|
64
|
+
```
|
65
|
+
|
66
|
+
But if you want to run brakeman, you could call `qq brakeman`:
|
67
|
+
|
68
|
+
```bash
|
69
|
+
❯ qq brakeman
|
70
|
+
--- Failed: brakeman
|
71
|
+
|
72
|
+
|
73
|
+
2 messages:
|
74
|
+
app/controllers/articles_controller.rb:3 [SQL Injection] Possible SQL injection
|
75
|
+
app/controllers/articles_controller.rb:11 [Remote Code Execution] `YAML.load` called with parameter value
|
76
|
+
|
77
|
+
```
|
78
|
+
|
79
|
+
## CI Usage Examples
|
80
|
+
|
81
|
+
Currently, QuietQuality is most useful from GitHub Actions - in that context, it's
|
82
|
+
possible to generate nice annotations for the analyzed commit (using Workflow
|
83
|
+
Actions). But it can be used from other CI systems as well, you just won't get
|
84
|
+
nice annotations out of it (yet).
|
85
|
+
|
86
|
+
For CI systems, you can either configure your execution entirely through
|
87
|
+
command-line arguments, or you can create additional configuration files and
|
88
|
+
specify them on the command-line.
|
89
|
+
|
90
|
+
Here is an invocation that executes rubocop and standardrb, expecting the full
|
91
|
+
repository to pass the latter, but not the former:
|
92
|
+
|
93
|
+
```bash
|
94
|
+
qq rubocop standardrb \
|
95
|
+
--all-files --changed-files rubocop \
|
96
|
+
--unfiltered --filter-messages rubocop \
|
97
|
+
--comparison-branch main \
|
98
|
+
--no-config \
|
99
|
+
--executor serial \
|
100
|
+
--annotate-github-stdout
|
16
101
|
```
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
102
|
+
|
103
|
+
Note the use of `--no-config`, to cause it to _not_ automatically load the
|
104
|
+
`.quiet_quality.yml` config included in the repository.
|
105
|
+
|
106
|
+
Alternatively, we could have put all of that configuration into a config file
|
107
|
+
like this:
|
108
|
+
|
109
|
+
```yaml
|
110
|
+
# config/quiet_quality/linters_workflow.yml
|
111
|
+
---
|
112
|
+
default_tools: ["standardrb", "rubocop"]
|
113
|
+
executor: serial
|
114
|
+
comparison_branch: main
|
115
|
+
changed_files: false
|
116
|
+
filter_messages: false
|
117
|
+
|
118
|
+
rubocop:
|
119
|
+
changed_files: true
|
120
|
+
filter_messages: true
|
34
121
|
```
|
122
|
+
|
123
|
+
And then run `qq -C config/quiet_quality/linters_workflow.yml`
|
124
|
+
|
125
|
+
## Available Options
|
126
|
+
|
127
|
+
The configuration file supports the following _global_ options (top-level keys):
|
128
|
+
|
129
|
+
* `executor`: 'serial' or 'concurrent' (the latter is the default)
|
130
|
+
* `annotator`: none set by default, and `github_stdout` is the only supported
|
131
|
+
value so far.
|
132
|
+
* `comparison_branch`: by default, this will be _fetched_ from git, but that
|
133
|
+
does require a remote request. You should set this, it saves about half a
|
134
|
+
second. This is normally 'main' or 'master', but it could be 'trunk', or
|
135
|
+
'develop' - it is the branch that PR diffs are _against_.
|
136
|
+
* `changed_files`: defaults to false - should tools be run against only the
|
137
|
+
files that have changed, or against the entire repository? This is the global
|
138
|
+
setting, but it is also settable per tool.
|
139
|
+
* `filter_messages`: defaults to false - should the resulting messages that do
|
140
|
+
not refer to lines that were changed or added relative to the comparison
|
141
|
+
branch be skipped? Also possible to set for each tool.
|
142
|
+
|
143
|
+
And then each tool can have an entry, within which `changed_files` and
|
144
|
+
`filter_messages` can be specified - the tool-specific settings override the
|
145
|
+
global ones.
|
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
|
+
|
163
|
+
### CLI Options
|
164
|
+
|
165
|
+
The same options are all available on the CLI, plus some additional ones - run
|
166
|
+
`qq --help` for a detailed list of the options, but the notable additions are:
|
167
|
+
|
168
|
+
* `--help/-H`: See a list of the options
|
169
|
+
* `--no-config/-N`: Do _not_ load a config file, even if present.
|
170
|
+
* `--config/-C`: load the supplied config file (instead of the detected one, if
|
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
|
@@ -11,11 +11,16 @@ module QuietQuality
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def outcome
|
14
|
-
@_outcome ||=
|
14
|
+
@_outcome ||= Tools::Outcome.new(
|
15
|
+
tool: runner_outcome.tool,
|
16
|
+
output: runner_outcome.output,
|
17
|
+
logging: runner_outcome.logging,
|
18
|
+
failure: messages.any?
|
19
|
+
)
|
15
20
|
end
|
16
21
|
|
17
22
|
def failure?
|
18
|
-
|
23
|
+
outcome.failure?
|
19
24
|
end
|
20
25
|
|
21
26
|
def messages
|
@@ -30,6 +35,10 @@ module QuietQuality
|
|
30
35
|
|
31
36
|
attr_reader :changed_files, :tool_options
|
32
37
|
|
38
|
+
def runner_outcome
|
39
|
+
@_runner_outcome ||= runner.invoke!
|
40
|
+
end
|
41
|
+
|
33
42
|
def limit_targets?
|
34
43
|
tool_options.limit_targets?
|
35
44
|
end
|
@@ -39,12 +48,14 @@ module QuietQuality
|
|
39
48
|
end
|
40
49
|
|
41
50
|
def runner
|
42
|
-
@_runner ||= tool_options.runner_class
|
43
|
-
|
51
|
+
@_runner ||= tool_options.runner_class.new(
|
52
|
+
changed_files: limit_targets? ? changed_files : nil,
|
53
|
+
file_filter: tool_options.file_filter
|
54
|
+
)
|
44
55
|
end
|
45
56
|
|
46
57
|
def parser
|
47
|
-
@_parser ||= tool_options.parser_class.new(
|
58
|
+
@_parser ||= tool_options.parser_class.new(runner_outcome.output)
|
48
59
|
end
|
49
60
|
|
50
61
|
def relevance_filter
|
@@ -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
|
data/quiet_quality.gemspec
CHANGED
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
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: mdl
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.12'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.12'
|
139
153
|
description: |
|
140
154
|
Allow your CI to notice and/or annotate new quality issues, despite the presences of
|
141
155
|
many pre-existing issues in your codebase.
|
@@ -150,6 +164,8 @@ files:
|
|
150
164
|
- ".github/workflows/linters.yml"
|
151
165
|
- ".github/workflows/rspec.yml"
|
152
166
|
- ".gitignore"
|
167
|
+
- ".mdl_rules.rb"
|
168
|
+
- ".mdlrc"
|
153
169
|
- ".quiet_quality.yml"
|
154
170
|
- ".rspec"
|
155
171
|
- ".rubocop.yml"
|
@@ -157,6 +173,7 @@ files:
|
|
157
173
|
- LICENSE
|
158
174
|
- README.md
|
159
175
|
- bin/qq
|
176
|
+
- docs/example-config.yml
|
160
177
|
- lib/quiet_quality.rb
|
161
178
|
- lib/quiet_quality/annotation_locator.rb
|
162
179
|
- lib/quiet_quality/annotators.rb
|
@@ -224,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
241
|
- !ruby/object:Gem::Version
|
225
242
|
version: '0'
|
226
243
|
requirements: []
|
227
|
-
rubygems_version: 3.
|
244
|
+
rubygems_version: 3.3.7
|
228
245
|
signing_key:
|
229
246
|
specification_version: 4
|
230
247
|
summary: A system for comparing quality tool outputs against the forward diffs
|