quiet_quality 1.1.0 → 1.2.1
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/dogfood.yml +1 -1
- data/.github/workflows/rspec.yml +1 -1
- data/.quiet_quality.ci.yml +6 -0
- data/.quiet_quality.yml +2 -1
- data/CHANGELOG.md +63 -0
- data/README.md +43 -13
- data/lib/quiet_quality/cli/arg_parser.rb +23 -7
- data/lib/quiet_quality/cli/entrypoint.rb +21 -30
- data/lib/quiet_quality/cli/presenter.rb +77 -0
- data/lib/quiet_quality/config/builder.rb +5 -0
- data/lib/quiet_quality/config/finder.rb +0 -4
- data/lib/quiet_quality/config/logging.rb +23 -0
- data/lib/quiet_quality/config/options.rb +6 -0
- data/lib/quiet_quality/config/parsed_options.rb +36 -0
- data/lib/quiet_quality/config/parser.rb +5 -8
- data/lib/quiet_quality/executors/base_executor.rb +9 -11
- data/lib/quiet_quality/logger.rb +17 -0
- data/lib/quiet_quality/tools/base_runner.rb +49 -0
- data/lib/quiet_quality/tools/brakeman/runner.rb +7 -26
- data/lib/quiet_quality/tools/brakeman.rb +0 -2
- data/lib/quiet_quality/tools/haml_lint/runner.rb +15 -50
- data/lib/quiet_quality/tools/haml_lint.rb +0 -2
- data/lib/quiet_quality/tools/markdown_lint/parser.rb +34 -0
- data/lib/quiet_quality/tools/markdown_lint/runner.rb +28 -0
- data/lib/quiet_quality/tools/markdown_lint.rb +9 -0
- data/lib/quiet_quality/tools/relevant_runner.rb +55 -0
- data/lib/quiet_quality/tools/rspec/runner.rb +9 -46
- data/lib/quiet_quality/tools/rspec.rb +0 -2
- data/lib/quiet_quality/tools/rubocop/runner.rb +9 -56
- data/lib/quiet_quality/tools/rubocop.rb +0 -2
- data/lib/quiet_quality/tools/standardrb/runner.rb +15 -3
- data/lib/quiet_quality/tools/standardrb.rb +0 -2
- data/lib/quiet_quality/tools.rb +6 -0
- data/lib/quiet_quality/version.rb +1 -1
- data/lib/quiet_quality/version_control_systems/git.rb +2 -11
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3847a8d0b996b19f34c32ac587dd1b9e51a2bedbea8e777e6b888294b16b5c0
|
4
|
+
data.tar.gz: 742080e4b9193d0d99606f00c68077229ffba805c5b93ffa75c09705e0101b18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b61e91968e6bdd4943809a336d60cf6a7feee9ab58db225a33f8268bd02efc911c3fa812e45491be1cc9f6d461a6db71308e790f1d912fac011c82cf4864e8d7
|
7
|
+
data.tar.gz: ace3273fb13dfcd04ae2432ed0cd488195789c75a27251617fc6be851bf865e4c4b689f9c3e3e83203ffb2b1ecd2be11c258405b10a3720c186b79b5e150fe3b
|
data/.github/workflows/rspec.yml
CHANGED
data/.quiet_quality.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## Release 1.2.1
|
4
|
+
|
5
|
+
* Fix the handling of the various ways to specify whether tools should limit
|
6
|
+
their targets to changed files or run against the entire repository. The
|
7
|
+
configuration systems had disagreements on what to call the options in
|
8
|
+
question, which resulted in some configuration entries being ignored. We
|
9
|
+
enforce a set of validations on reads and writes now to avoid such a problem
|
10
|
+
in the future (#89, resolves #88)
|
11
|
+
* Add coverage-checking, and then improve test coverage and remove unreferenced
|
12
|
+
code as a result. (#87)
|
13
|
+
|
14
|
+
## Release 1.2.0
|
15
|
+
|
16
|
+
* Support `--light`, `--quiet`, and `--logging LEVEL` arguments for less output
|
17
|
+
(#78, resolves #37)
|
18
|
+
* Support the [markdownlint](https://github.com/markdownlint/markdownlint) tool
|
19
|
+
(#79, resolves #58)
|
20
|
+
* Extract BaseRunner (#82) and RelevantRunner (#83) parent classes from the tool
|
21
|
+
runners, to allow new tools to be more easily implemented. (Resolves #81)
|
22
|
+
* Extract a Cli::Presenter from the Entrypoint, to simplify pending work on cli
|
23
|
+
presentation (#84, resolves #42)
|
24
|
+
* Update the docs a bit, and add a changelog (hi!)
|
25
|
+
|
26
|
+
## Release 1.1.0
|
27
|
+
|
28
|
+
* Support a `file_filter` config entry per-tool (without a cli option), to limit
|
29
|
+
what file paths a runner might supply to its tool based on a regex
|
30
|
+
(#74, resolves #68)
|
31
|
+
* When what tools to execute is not specified (by cli or by config file), abort
|
32
|
+
`bin/qq` and explain, rather than assuming "all of them" (#79, resolves #58)
|
33
|
+
* Update the config parser to handle keys named to match the cli options
|
34
|
+
alongside the ones that were (mistakenly) named differently. This is a
|
35
|
+
backwards-compatible change; if we eventually deprecate and simplify some of
|
36
|
+
these option names, you'll have plenty of warning (#77, resolves #75)
|
37
|
+
* Support `--version/-V` flag (#73, resolves #69)
|
38
|
+
|
39
|
+
## Release 1.0.3
|
40
|
+
|
41
|
+
* Fix the printed _output_ for the case where there were some warnings from a
|
42
|
+
tool, but all of them were filtered out (because they targetted lines that
|
43
|
+
were not changed, for example). This situation should tell you that nothing
|
44
|
+
is wrong with your PR, not that there is a problem (#71)
|
45
|
+
|
46
|
+
## Release 1.0.2
|
47
|
+
|
48
|
+
* Fix the _exit status_ for the case where there were some warnings from a
|
49
|
+
tool, but all of them were filtered out (because they targetted lines that
|
50
|
+
were not changed, for example). This situation should produce a successful
|
51
|
+
result, and not fail a CI pipeline (#67)
|
52
|
+
|
53
|
+
## Release 1.0.1
|
54
|
+
|
55
|
+
* Fix the calculation of `changed_files` for the executor - in the migration
|
56
|
+
to Entrypoint, the actual git call to get a ChangedFiles object to pass into
|
57
|
+
other service classes was lost, which had the result that the entire system
|
58
|
+
behaved (outside of tests) as if you were always running with `--all-files`
|
59
|
+
(#65).
|
60
|
+
|
61
|
+
## Release 1.0.0
|
62
|
+
|
63
|
+
Initial functional public release.
|
data/README.md
CHANGED
@@ -14,11 +14,13 @@ that too.
|
|
14
14
|
|
15
15
|
So far, we have support for the following tools:
|
16
16
|
|
17
|
-
* rubocop
|
18
|
-
* standardrb
|
19
|
-
* rspec
|
20
|
-
* haml-lint
|
21
|
-
*
|
17
|
+
* [rubocop](https://github.com/rubocop/rubocop)
|
18
|
+
* [standardrb](https://github.com/standardrb/standard)
|
19
|
+
* [rspec](https://rspec.info/)
|
20
|
+
* [haml-lint](https://github.com/sds/haml-lint)
|
21
|
+
* [markdownlint](https://github.com/markdownlint/markdownlint)
|
22
|
+
* [brakeman](https://brakemanscanner.org/) (though there's no way to run this
|
23
|
+
against only changed files)
|
22
24
|
|
23
25
|
Supporting more tools is relatively straightforward - they're implemented by
|
24
26
|
wrapping cli invocations and parsing output files (which overall seem to be much
|
@@ -126,6 +128,9 @@ And then run `qq -C config/quiet_quality/linters_workflow.yml`
|
|
126
128
|
|
127
129
|
The configuration file supports the following _global_ options (top-level keys):
|
128
130
|
|
131
|
+
* `default_tools`: Which tools should be run when you `qq` without specifying?
|
132
|
+
Valid values are: `rubocop`, `rspec`, `standardrb`, `haml_lint`, `brakeman`,
|
133
|
+
and `markdown_lint`.
|
129
134
|
* `executor`: 'serial' or 'concurrent' (the latter is the default)
|
130
135
|
* `annotator`: none set by default, and `github_stdout` is the only supported
|
131
136
|
value so far.
|
@@ -139,6 +144,10 @@ The configuration file supports the following _global_ options (top-level keys):
|
|
139
144
|
* `filter_messages`: defaults to false - should the resulting messages that do
|
140
145
|
not refer to lines that were changed or added relative to the comparison
|
141
146
|
branch be skipped? Also possible to set for each tool.
|
147
|
+
* `logging`: defaults to full messages printed. The `light` option
|
148
|
+
prints a aggregated result (e.g. "3 tools executed: 1 passed, 2 failed
|
149
|
+
(rubocop, standardrb)"). The `quiet` option will only return a status code,
|
150
|
+
printing nothing.
|
142
151
|
|
143
152
|
And then each tool can have an entry, within which `changed_files` and
|
144
153
|
`filter_messages` can be specified - the tool-specific settings override the
|
@@ -162,11 +171,32 @@ rspec:
|
|
162
171
|
|
163
172
|
### CLI Options
|
164
173
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
174
|
+
To specify which _tools_ to run (and if any are specified, the `default_tools`
|
175
|
+
from the configuration file will be ignored), you supply them as positional
|
176
|
+
arguments: `qq rubocop rspec --all-files -L` will run the `rubocop` and `rspec`
|
177
|
+
tools, for example.
|
178
|
+
|
179
|
+
Run `qq --help` for a detailed list of the CLI options, they largely agree with
|
180
|
+
those in the configuration file, but there are some differences. There's no way
|
181
|
+
to specify a `file_filter` for a tool on the command-line, and there are some
|
182
|
+
additional options available focused on managing the interactions with
|
183
|
+
configuration files.
|
184
|
+
|
185
|
+
```text
|
186
|
+
Usage: qq [TOOLS] [GLOBAL_OPTIONS] [TOOL_OPTIONS]
|
187
|
+
-h, --help Prints this help
|
188
|
+
-V, --version Print the current version of the gem
|
189
|
+
-C, --config PATH Load a config file from this path
|
190
|
+
-N, --no-config Do not load a config file, even if present
|
191
|
+
-E, --executor EXECUTOR Which executor to use
|
192
|
+
-A, --annotate ANNOTATOR Annotate with this annotator
|
193
|
+
-G, --annotate-github-stdout Annotate with GitHub Workflow commands
|
194
|
+
-a, --all-files [tool] Use the tool(s) on all files
|
195
|
+
-c, --changed-files [tool] Use the tool(s) only on changed files
|
196
|
+
-B, --comparison-branch BRANCH Specify the branch to compare against
|
197
|
+
-f, --filter-messages [tool] Filter messages from tool(s) based on changed lines
|
198
|
+
-u, --unfiltered [tool] Don't filter messages from tool(s)
|
199
|
+
-l, --light Print aggregated results only
|
200
|
+
-q, --quiet Don't print results, only return a status code
|
201
|
+
-L, --logging LEVEL Specify logging mode that results will be returned in. Valid options: light, quiet
|
202
|
+
```
|
@@ -45,12 +45,12 @@ module QuietQuality
|
|
45
45
|
# options; if they don't, they are global options. (optparse allows an optional argument
|
46
46
|
# to a flag if the string representing it is not a 'string in all caps'. So `[FOO]` or `foo`
|
47
47
|
# would be optional, but `FOO` would be required. This helper simplifies handling those.
|
48
|
-
def read_tool_or_global_option(name
|
48
|
+
def read_tool_or_global_option(name:, into:, tool:, value:)
|
49
49
|
if tool
|
50
50
|
validate_value_from("tool", tool, Tools::AVAILABLE)
|
51
|
-
set_tool_option(tool,
|
51
|
+
set_tool_option(tool, into, value)
|
52
52
|
else
|
53
|
-
set_global_option(
|
53
|
+
set_global_option(into, value)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -65,6 +65,7 @@ module QuietQuality
|
|
65
65
|
setup_annotation_options(parser)
|
66
66
|
setup_file_target_options(parser)
|
67
67
|
setup_filter_messages_options(parser)
|
68
|
+
setup_logging_options(parser)
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
@@ -113,11 +114,11 @@ module QuietQuality
|
|
113
114
|
|
114
115
|
def setup_file_target_options(parser)
|
115
116
|
parser.on("-a", "--all-files [tool]", "Use the tool(s) on all files") do |tool|
|
116
|
-
read_tool_or_global_option(:all_files, tool,
|
117
|
+
read_tool_or_global_option(name: :all_files, into: :limit_targets, tool: tool, value: false)
|
117
118
|
end
|
118
119
|
|
119
120
|
parser.on("-c", "--changed-files [tool]", "Use the tool(s) only on changed files") do |tool|
|
120
|
-
read_tool_or_global_option(:all_files, tool,
|
121
|
+
read_tool_or_global_option(name: :all_files, into: :limit_targets, tool: tool, value: true)
|
121
122
|
end
|
122
123
|
|
123
124
|
parser.on("-B", "--comparison-branch BRANCH", "Specify the branch to compare against") do |branch|
|
@@ -127,11 +128,26 @@ module QuietQuality
|
|
127
128
|
|
128
129
|
def setup_filter_messages_options(parser)
|
129
130
|
parser.on("-f", "--filter-messages [tool]", "Filter messages from tool(s) based on changed lines") do |tool|
|
130
|
-
read_tool_or_global_option(:filter_messages, tool, true)
|
131
|
+
read_tool_or_global_option(name: :filter_messages, into: :filter_messages, tool: tool, value: true)
|
131
132
|
end
|
132
133
|
|
133
134
|
parser.on("-u", "--unfiltered [tool]", "Don't filter messages from tool(s)") do |tool|
|
134
|
-
read_tool_or_global_option(:filter_messages, tool, false)
|
135
|
+
read_tool_or_global_option(name: :filter_messages, into: :filter_messages, tool: tool, value: false)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def setup_logging_options(parser)
|
140
|
+
parser.on("-l", "--light", "Print aggregated results only") do
|
141
|
+
set_global_option(:logging, Config::Logging::LIGHT)
|
142
|
+
end
|
143
|
+
|
144
|
+
parser.on("-q", "--quiet", "Don't print results, only return a status code") do
|
145
|
+
set_global_option(:logging, Config::Logging::QUIET)
|
146
|
+
end
|
147
|
+
|
148
|
+
parser.on("-L", "--logging LEVEL", "Specify logging mode that results will be returned in. Valid options: light, quiet") do |level|
|
149
|
+
validate_value_from("logging level", level, Config::Logging::LEVELS)
|
150
|
+
set_global_option(:logging, level.to_sym)
|
135
151
|
end
|
136
152
|
end
|
137
153
|
end
|
@@ -16,8 +16,7 @@ module QuietQuality
|
|
16
16
|
log_no_tools_text
|
17
17
|
else
|
18
18
|
executed
|
19
|
-
|
20
|
-
log_messages
|
19
|
+
log_results
|
21
20
|
annotate_messages
|
22
21
|
end
|
23
22
|
|
@@ -34,6 +33,23 @@ module QuietQuality
|
|
34
33
|
|
35
34
|
attr_reader :argv, :output_stream, :error_stream
|
36
35
|
|
36
|
+
def logger
|
37
|
+
@_logger ||= QuietQuality::Logger.new(stream: error_stream, logging: options.logging)
|
38
|
+
end
|
39
|
+
|
40
|
+
def presenter
|
41
|
+
@_presenter ||= Presenter.new(
|
42
|
+
logger: logger,
|
43
|
+
logging: options.logging,
|
44
|
+
outcomes: executor.outcomes,
|
45
|
+
messages: executor.messages
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def log_results
|
50
|
+
presenter.log_results
|
51
|
+
end
|
52
|
+
|
37
53
|
def arg_parser
|
38
54
|
@_arg_parser ||= ArgParser.new(argv.dup)
|
39
55
|
end
|
@@ -55,15 +71,15 @@ module QuietQuality
|
|
55
71
|
end
|
56
72
|
|
57
73
|
def log_help_text
|
58
|
-
|
74
|
+
logger.puts(arg_parser.help_text)
|
59
75
|
end
|
60
76
|
|
61
77
|
def log_version_text
|
62
|
-
|
78
|
+
logger.puts(QuietQuality::VERSION)
|
63
79
|
end
|
64
80
|
|
65
81
|
def log_no_tools_text
|
66
|
-
|
82
|
+
logger.puts(<<~TEXT)
|
67
83
|
You must specify one or more tools to run, either on the command-line or in the
|
68
84
|
default_tools key in a configuration file.
|
69
85
|
TEXT
|
@@ -95,31 +111,6 @@ module QuietQuality
|
|
95
111
|
@_executed = executor
|
96
112
|
end
|
97
113
|
|
98
|
-
def log_outcomes
|
99
|
-
executed.outcomes.each do |outcome|
|
100
|
-
result = outcome.success? ? "Passed" : "Failed"
|
101
|
-
error_stream.puts "--- #{result}: #{outcome.tool}"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def log_message(msg)
|
106
|
-
line_range =
|
107
|
-
if msg.start_line == msg.stop_line
|
108
|
-
msg.start_line.to_s
|
109
|
-
else
|
110
|
-
"#{msg.start_line}-#{msg.stop_line}"
|
111
|
-
end
|
112
|
-
rule_string = msg.rule ? " [#{msg.rule}]" : ""
|
113
|
-
truncated_body = msg.body.gsub(/ *\n */, "\\n").slice(0, 120)
|
114
|
-
error_stream.puts " #{msg.path}:#{line_range}#{rule_string} #{truncated_body}"
|
115
|
-
end
|
116
|
-
|
117
|
-
def log_messages
|
118
|
-
return unless executed.messages.any?
|
119
|
-
error_stream.puts "\n\n#{executed.messages.count} messages:"
|
120
|
-
executed.messages.each { |msg| log_message(msg) }
|
121
|
-
end
|
122
|
-
|
123
114
|
def annotate_messages
|
124
115
|
return unless options.annotator
|
125
116
|
annotator = options.annotator.new(output_stream: output_stream)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
module Cli
|
3
|
+
class Presenter
|
4
|
+
def initialize(logger:, logging:, outcomes:, messages:)
|
5
|
+
@logger = logger
|
6
|
+
@logging = logging
|
7
|
+
@outcomes = outcomes
|
8
|
+
@messages = messages
|
9
|
+
end
|
10
|
+
|
11
|
+
def log_results
|
12
|
+
return if logging.quiet?
|
13
|
+
|
14
|
+
if logging.light?
|
15
|
+
log_light_outcomes
|
16
|
+
else
|
17
|
+
log_outcomes
|
18
|
+
log_messages
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :logger, :logging, :outcomes, :messages
|
25
|
+
|
26
|
+
def failed_outcomes
|
27
|
+
@_failed_outcomes ||= outcomes.select(&:failure?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def successful_outcomes
|
31
|
+
@_successful_outcomes ||= outcomes.select(&:success?)
|
32
|
+
end
|
33
|
+
|
34
|
+
def log_light_outcomes
|
35
|
+
line = "%d tools executed: %d passed, %d failed" % [
|
36
|
+
outcomes.count,
|
37
|
+
successful_outcomes.count,
|
38
|
+
failed_outcomes.count
|
39
|
+
]
|
40
|
+
line += " (#{failed_outcomes.map(&:tool).join(", ")})" if failed_outcomes.any?
|
41
|
+
logger.puts line
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_outcomes
|
45
|
+
outcomes.each do |outcome|
|
46
|
+
result = outcome.success? ? "Passed" : "Failed"
|
47
|
+
logger.puts "--- #{result}: #{outcome.tool}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def log_messages
|
52
|
+
return unless messages.any?
|
53
|
+
logger.puts "\n\n#{messages.count} messages:"
|
54
|
+
messages.each { |msg| log_message(msg) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def line_range_for(msg)
|
58
|
+
if msg.start_line == msg.stop_line
|
59
|
+
msg.start_line.to_s
|
60
|
+
else
|
61
|
+
"#{msg.start_line}-#{msg.stop_line}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def reduce_text(s, length)
|
66
|
+
s.gsub(/ *\n */, "\\n").slice(0, length)
|
67
|
+
end
|
68
|
+
|
69
|
+
def log_message(msg)
|
70
|
+
line_range = line_range_for(msg)
|
71
|
+
rule_string = msg.rule ? " [#{msg.rule}]" : ""
|
72
|
+
truncated_body = reduce_text(msg.body, 120)
|
73
|
+
logger.puts " #{msg.path}:#{line_range}#{rule_string} #{truncated_body}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -85,6 +85,7 @@ module QuietQuality
|
|
85
85
|
update_annotator
|
86
86
|
update_executor
|
87
87
|
update_comparison_branch
|
88
|
+
update_logging
|
88
89
|
end
|
89
90
|
|
90
91
|
def update_annotator
|
@@ -103,6 +104,10 @@ module QuietQuality
|
|
103
104
|
set_unless_nil(options, :comparison_branch, apply.global_option(:comparison_branch))
|
104
105
|
end
|
105
106
|
|
107
|
+
def update_logging
|
108
|
+
set_unless_nil(options, :logging, apply.global_option(:logging))
|
109
|
+
end
|
110
|
+
|
106
111
|
# ---- update the tool options (apply global forms first) -------
|
107
112
|
|
108
113
|
def update_tools
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
module Config
|
3
|
+
class Logging
|
4
|
+
LIGHT = :light
|
5
|
+
QUIET = :quiet
|
6
|
+
LEVELS = [LIGHT, QUIET].freeze
|
7
|
+
|
8
|
+
attr_accessor :level
|
9
|
+
|
10
|
+
def initialize(level: nil)
|
11
|
+
@level = level
|
12
|
+
end
|
13
|
+
|
14
|
+
def light?
|
15
|
+
@level == LIGHT
|
16
|
+
end
|
17
|
+
|
18
|
+
def quiet?
|
19
|
+
@level == QUIET
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -6,9 +6,15 @@ module QuietQuality
|
|
6
6
|
@executor = Executors::ConcurrentExecutor
|
7
7
|
@tools = nil
|
8
8
|
@comparison_branch = nil
|
9
|
+
@logging = Logging.new
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_accessor :tools, :comparison_branch, :annotator, :executor
|
13
|
+
attr_reader :logging
|
14
|
+
|
15
|
+
def logging=(level)
|
16
|
+
@logging.level = level
|
17
|
+
end
|
12
18
|
end
|
13
19
|
end
|
14
20
|
end
|
@@ -1,6 +1,26 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Config
|
3
3
|
class ParsedOptions
|
4
|
+
InvalidOptionName = Class.new(Error)
|
5
|
+
|
6
|
+
GLOBAL_OPTIONS = [
|
7
|
+
:no_config,
|
8
|
+
:config_path,
|
9
|
+
:annotator,
|
10
|
+
:executor,
|
11
|
+
:comparison_branch,
|
12
|
+
:logging,
|
13
|
+
:limit_targets,
|
14
|
+
:filter_messages,
|
15
|
+
:file_filter
|
16
|
+
].to_set
|
17
|
+
|
18
|
+
TOOL_OPTIONS = [
|
19
|
+
:limit_targets,
|
20
|
+
:filter_messages,
|
21
|
+
:file_filter
|
22
|
+
].to_set
|
23
|
+
|
4
24
|
def initialize
|
5
25
|
@tools = []
|
6
26
|
@tool_options = {}
|
@@ -20,21 +40,37 @@ module QuietQuality
|
|
20
40
|
end
|
21
41
|
|
22
42
|
def set_global_option(name, value)
|
43
|
+
validate_global_option(name)
|
23
44
|
@global_options[name.to_sym] = value
|
24
45
|
end
|
25
46
|
|
26
47
|
def global_option(name)
|
48
|
+
validate_global_option(name)
|
27
49
|
@global_options.fetch(name.to_sym, nil)
|
28
50
|
end
|
29
51
|
|
30
52
|
def set_tool_option(tool, name, value)
|
53
|
+
validate_tool_option(name)
|
31
54
|
@tool_options[tool.to_sym] ||= {}
|
32
55
|
@tool_options[tool.to_sym][name.to_sym] = value
|
33
56
|
end
|
34
57
|
|
35
58
|
def tool_option(tool, name)
|
59
|
+
validate_tool_option(name)
|
36
60
|
@tool_options.dig(tool.to_sym, name.to_sym)
|
37
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def validate_global_option(name)
|
66
|
+
return if GLOBAL_OPTIONS.include?(name.to_sym)
|
67
|
+
fail(InvalidOptionName, "Option name #{name} is not a recognized global ParsedOption")
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_tool_option(name)
|
71
|
+
return if TOOL_OPTIONS.include?(name.to_sym)
|
72
|
+
fail(InvalidOptionName, "Option name #{name} is not a recognized tool ParsedOption")
|
73
|
+
end
|
38
74
|
end
|
39
75
|
end
|
40
76
|
end
|
@@ -42,10 +42,11 @@ module QuietQuality
|
|
42
42
|
read_global_option(opts, :annotator, :annotator, as: :symbol, validate_from: Annotators::ANNOTATOR_TYPES)
|
43
43
|
read_global_option(opts, :annotate, :annotator, as: :symbol, validate_from: Annotators::ANNOTATOR_TYPES)
|
44
44
|
read_global_option(opts, :comparison_branch, :comparison_branch, as: :string)
|
45
|
-
read_global_option(opts, :changed_files, :
|
46
|
-
read_global_option(opts, :all_files, :
|
45
|
+
read_global_option(opts, :changed_files, :limit_targets, as: :boolean)
|
46
|
+
read_global_option(opts, :all_files, :limit_targets, as: :reversed_boolean)
|
47
47
|
read_global_option(opts, :filter_messages, :filter_messages, as: :boolean)
|
48
48
|
read_global_option(opts, :unfiltered, :filter_messages, as: :reversed_boolean)
|
49
|
+
read_global_option(opts, :logging, :logging, as: :symbol, validate_from: Logging::LEVELS)
|
49
50
|
end
|
50
51
|
|
51
52
|
def store_tool_options(opts)
|
@@ -60,8 +61,8 @@ module QuietQuality
|
|
60
61
|
|
61
62
|
read_tool_option(opts, tool_name, :filter_messages, :filter_messages, as: :boolean)
|
62
63
|
read_tool_option(opts, tool_name, :unfiltered, :filter_messages, as: :reversed_boolean)
|
63
|
-
read_tool_option(opts, tool_name, :changed_files, :
|
64
|
-
read_tool_option(opts, tool_name, :all_files, :
|
64
|
+
read_tool_option(opts, tool_name, :changed_files, :limit_targets, as: :boolean)
|
65
|
+
read_tool_option(opts, tool_name, :all_files, :limit_targets, as: :reversed_boolean)
|
65
66
|
read_tool_option(opts, tool_name, :file_filter, :file_filter, as: :string)
|
66
67
|
end
|
67
68
|
|
@@ -101,8 +102,6 @@ module QuietQuality
|
|
101
102
|
when :reversed_boolean then validate_boolean(name, value)
|
102
103
|
when :symbol then validate_symbol(name, value, from: from)
|
103
104
|
when :string then validate_string(name, value)
|
104
|
-
else
|
105
|
-
fail ArgumentError, "validate_value does not handle type #{as}"
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
@@ -134,8 +133,6 @@ module QuietQuality
|
|
134
133
|
when :reversed_boolean then !value
|
135
134
|
when :string then value.to_s
|
136
135
|
when :symbol then value.to_sym
|
137
|
-
else
|
138
|
-
fail ArgumentError, "coerce_value does not handle type #{as}"
|
139
136
|
end
|
140
137
|
end
|
141
138
|
end
|
@@ -7,7 +7,7 @@ module QuietQuality
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def execute!
|
10
|
-
|
10
|
+
pipelines.none?(&:failure?)
|
11
11
|
end
|
12
12
|
|
13
13
|
def outcomes
|
@@ -22,6 +22,14 @@ module QuietQuality
|
|
22
22
|
pipelines.any?(&:failure?)
|
23
23
|
end
|
24
24
|
|
25
|
+
def successful_outcomes
|
26
|
+
@_successful_outcomes ||= outcomes.select(&:success?)
|
27
|
+
end
|
28
|
+
|
29
|
+
def failed_outcomes
|
30
|
+
@_failed_outcomes ||= outcomes.select(&:failure?)
|
31
|
+
end
|
32
|
+
|
25
33
|
private
|
26
34
|
|
27
35
|
attr_reader :tools, :changed_files
|
@@ -31,16 +39,6 @@ module QuietQuality
|
|
31
39
|
Pipeline.new(tool_options: topts, changed_files: changed_files)
|
32
40
|
end
|
33
41
|
end
|
34
|
-
|
35
|
-
def pipeline_by_tool
|
36
|
-
@_pipeline_by_tool ||= pipelines
|
37
|
-
.map { |p| [p.tool_name, p] }
|
38
|
-
.to_h
|
39
|
-
end
|
40
|
-
|
41
|
-
def pipeline_for(tool)
|
42
|
-
pipeline_by_tool.fetch(tool.to_sym)
|
43
|
-
end
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
class Logger
|
3
|
+
def initialize(stream:, logging:)
|
4
|
+
@stream = stream
|
5
|
+
@logging = logging
|
6
|
+
end
|
7
|
+
|
8
|
+
def puts(s)
|
9
|
+
return if logging.quiet?
|
10
|
+
stream.puts(s)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :stream, :logging
|
16
|
+
end
|
17
|
+
end
|