quiet_quality 1.0.2 → 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 +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
|