quiet_quality 1.2.2 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.quiet_quality.ci.yml +1 -0
- data/.quiet_quality.yml +1 -0
- data/CHANGELOG.md +14 -0
- data/README.md +7 -1
- data/lib/quiet_quality/annotators.rb +6 -2
- data/lib/quiet_quality/cli/arg_parser.rb +19 -5
- data/lib/quiet_quality/cli/entrypoint.rb +13 -9
- data/lib/quiet_quality/cli/presenter.rb +26 -13
- data/lib/quiet_quality/colorize.rb +19 -0
- data/lib/quiet_quality/config/builder.rb +1 -0
- data/lib/quiet_quality/config/options.rb +39 -2
- data/lib/quiet_quality/config/parsed_options.rb +1 -0
- data/lib/quiet_quality/config/parser.rb +2 -1
- data/lib/quiet_quality/config/tool_options.rb +9 -0
- data/lib/quiet_quality/executors/pipeline.rb +27 -5
- data/lib/quiet_quality/logger.rb +54 -6
- data/lib/quiet_quality/logging.rb +21 -0
- data/lib/quiet_quality/tools/base_runner.rb +9 -0
- data/lib/quiet_quality/tools/relevant_runner.rb +1 -0
- data/lib/quiet_quality/version.rb +1 -1
- data/lib/quiet_quality.rb +6 -0
- data/quiet_quality.gemspec +2 -1
- metadata +22 -7
- data/lib/quiet_quality/config/logging.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7049c44ac27b14f8f599dfcb080dcd7d6aadceed0cee69f0d9f460ccb23bd66c
|
4
|
+
data.tar.gz: 6ec55838027c9bd81659109807e27e50199b5c54e1e17d04b2b0727819851d89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cac5b2196f3409ab37252830b115cf7ec54b0cc21e2e5a25062cb4cd79615f7378a6ac4bd2d4fd39a0c1ff6882948fa2e6e1f7029dd88b1b9989fb8910aa0b6
|
7
|
+
data.tar.gz: e48380c23c35946e11c011bb1bdb694f6731d93828fa06a4d725a9d9a9c347e3f8ee5a8687904593905da9be74c5d8903b09f72c815f2dbdcb5fdedcc5f8e69f
|
data/.quiet_quality.ci.yml
CHANGED
data/.quiet_quality.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Release 1.3.1
|
4
|
+
|
5
|
+
* Fix a bug around the logging of nil commands when runners are skipped (#104
|
6
|
+
resolves #103)
|
7
|
+
|
8
|
+
## Release 1.3.0
|
9
|
+
|
10
|
+
* Support (and enable by default) colorizing the console stderr output from
|
11
|
+
`bin/qq` - disable with the `--no-colorize` flag or the `colorize: false`
|
12
|
+
configuration entry. (#94, resolved #36)
|
13
|
+
* Introduce a Logging facility, and add the `--verbose/-v` flag - supply it
|
14
|
+
either once or twice to enable (colorized) logging in either `info` or `debug`
|
15
|
+
level, providing much more detail about what's going on during execution.
|
16
|
+
|
3
17
|
## Release 1.2.2
|
4
18
|
|
5
19
|
* Add some code to the Rspec::Parser that _cleans_ the json of certain text that
|
data/README.md
CHANGED
@@ -148,6 +148,9 @@ The configuration file supports the following _global_ options (top-level keys):
|
|
148
148
|
prints a aggregated result (e.g. "3 tools executed: 1 passed, 2 failed
|
149
149
|
(rubocop, standardrb)"). The `quiet` option will only return a status code,
|
150
150
|
printing nothing.
|
151
|
+
* `colorize`: by default, `bin/qq` will include color codes in its output, to
|
152
|
+
make failing tools easier to spot, and messages easier to read. But you can
|
153
|
+
supply `colorize: false` to tell it not to do that if you don't want them.
|
151
154
|
|
152
155
|
And then each tool can have an entry, within which `changed_files` and
|
153
156
|
`filter_messages` can be specified - the tool-specific settings override the
|
@@ -196,7 +199,10 @@ Usage: qq [TOOLS] [GLOBAL_OPTIONS] [TOOL_OPTIONS]
|
|
196
199
|
-B, --comparison-branch BRANCH Specify the branch to compare against
|
197
200
|
-f, --filter-messages [tool] Filter messages from tool(s) based on changed lines
|
198
201
|
-u, --unfiltered [tool] Don't filter messages from tool(s)
|
202
|
+
--[no-]colorize Colorize the logging output
|
203
|
+
-n, --normal Print outcomes and messages
|
199
204
|
-l, --light Print aggregated results only
|
200
205
|
-q, --quiet Don't print results, only return a status code
|
201
|
-
-L, --logging LEVEL Specify logging mode
|
206
|
+
-L, --logging LEVEL Specify logging mode (from light/quiet/normal)
|
207
|
+
-v, --verbose Log more verbosely - multiple times is more verbose
|
202
208
|
```
|
@@ -1,10 +1,14 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
module Annotators
|
3
|
+
Unrecognized = Class.new(Error)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
glob = File.expand_path("../annotators/*.rb", __FILE__)
|
2
8
|
Dir.glob(glob).sort.each { |f| require(f) }
|
3
9
|
|
4
10
|
module QuietQuality
|
5
11
|
module Annotators
|
6
|
-
Unrecognized = Class.new(Error)
|
7
|
-
|
8
12
|
ANNOTATOR_TYPES = {
|
9
13
|
github_stdout: Annotators::GithubStdout
|
10
14
|
}.freeze
|
@@ -65,7 +65,9 @@ module QuietQuality
|
|
65
65
|
setup_annotation_options(parser)
|
66
66
|
setup_file_target_options(parser)
|
67
67
|
setup_filter_messages_options(parser)
|
68
|
+
setup_colorization_options(parser)
|
68
69
|
setup_logging_options(parser)
|
70
|
+
setup_verbosity_options(parser)
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
@@ -136,24 +138,36 @@ module QuietQuality
|
|
136
138
|
end
|
137
139
|
end
|
138
140
|
|
141
|
+
def setup_colorization_options(parser)
|
142
|
+
parser.on("--[no-]colorize", "Colorize the logging output") do |value|
|
143
|
+
set_global_option(:colorize, value)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
139
147
|
def setup_logging_options(parser)
|
140
148
|
parser.on("-n", "--normal", "Print outcomes and messages") do
|
141
|
-
set_global_option(:logging,
|
149
|
+
set_global_option(:logging, :normal)
|
142
150
|
end
|
143
151
|
|
144
152
|
parser.on("-l", "--light", "Print aggregated results only") do
|
145
|
-
set_global_option(:logging,
|
153
|
+
set_global_option(:logging, :light)
|
146
154
|
end
|
147
155
|
|
148
156
|
parser.on("-q", "--quiet", "Don't print results, only return a status code") do
|
149
|
-
set_global_option(:logging,
|
157
|
+
set_global_option(:logging, :quiet)
|
150
158
|
end
|
151
159
|
|
152
|
-
parser.on("-L", "--logging LEVEL", "Specify logging mode
|
153
|
-
validate_value_from("logging level", level, Config::
|
160
|
+
parser.on("-L", "--logging LEVEL", "Specify logging mode (from normal/light/quiet)") do |level|
|
161
|
+
validate_value_from("logging level", level.to_sym, Config::Options::LOGGING_LEVELS)
|
154
162
|
set_global_option(:logging, level.to_sym)
|
155
163
|
end
|
156
164
|
end
|
165
|
+
|
166
|
+
def setup_verbosity_options(parser)
|
167
|
+
parser.on("-v", "--verbose", "Log more verbosely - multiple times is more verbose") do
|
168
|
+
QuietQuality.logger.increase_level!
|
169
|
+
end
|
170
|
+
end
|
157
171
|
end
|
158
172
|
end
|
159
173
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Cli
|
3
3
|
class Entrypoint
|
4
|
+
include Logging
|
5
|
+
|
4
6
|
def initialize(argv:, output_stream: $stdout, error_stream: $stderr)
|
5
7
|
@argv = argv
|
6
8
|
@output_stream = output_stream
|
@@ -15,6 +17,7 @@ module QuietQuality
|
|
15
17
|
elsif no_tools?
|
16
18
|
log_no_tools_text
|
17
19
|
else
|
20
|
+
log_options
|
18
21
|
executed
|
19
22
|
log_results
|
20
23
|
annotate_messages
|
@@ -33,19 +36,19 @@ module QuietQuality
|
|
33
36
|
|
34
37
|
attr_reader :argv, :output_stream, :error_stream
|
35
38
|
|
36
|
-
def logger
|
37
|
-
@_logger ||= QuietQuality::Logger.new(stream: error_stream, logging: options.logging)
|
38
|
-
end
|
39
|
-
|
40
39
|
def presenter
|
41
40
|
@_presenter ||= Presenter.new(
|
42
|
-
|
43
|
-
|
41
|
+
stream: error_stream,
|
42
|
+
options: options,
|
44
43
|
outcomes: executor.outcomes,
|
45
44
|
messages: executor.messages
|
46
45
|
)
|
47
46
|
end
|
48
47
|
|
48
|
+
def log_options
|
49
|
+
debug("Complete Options object:", data: options.to_h)
|
50
|
+
end
|
51
|
+
|
49
52
|
def log_results
|
50
53
|
presenter.log_results
|
51
54
|
end
|
@@ -71,15 +74,15 @@ module QuietQuality
|
|
71
74
|
end
|
72
75
|
|
73
76
|
def log_help_text
|
74
|
-
|
77
|
+
error_stream.puts(arg_parser.help_text)
|
75
78
|
end
|
76
79
|
|
77
80
|
def log_version_text
|
78
|
-
|
81
|
+
error_stream.puts(QuietQuality::VERSION)
|
79
82
|
end
|
80
83
|
|
81
84
|
def log_no_tools_text
|
82
|
-
|
85
|
+
error_stream.puts(<<~TEXT)
|
83
86
|
You must specify one or more tools to run, either on the command-line or in the
|
84
87
|
default_tools key in a configuration file.
|
85
88
|
TEXT
|
@@ -113,6 +116,7 @@ module QuietQuality
|
|
113
116
|
|
114
117
|
def annotate_messages
|
115
118
|
return unless options.annotator
|
119
|
+
info("Annotating with #{options.annotator}")
|
116
120
|
annotator = options.annotator.new(output_stream: output_stream)
|
117
121
|
annotator.annotate!(executed.messages)
|
118
122
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Cli
|
3
3
|
class Presenter
|
4
|
-
def initialize(
|
5
|
-
@
|
6
|
-
@
|
4
|
+
def initialize(stream:, options:, outcomes:, messages:)
|
5
|
+
@stream = stream
|
6
|
+
@options = options
|
7
7
|
@outcomes = outcomes
|
8
8
|
@messages = messages
|
9
9
|
end
|
10
10
|
|
11
11
|
def log_results
|
12
|
-
return if
|
12
|
+
return if options.quiet?
|
13
13
|
|
14
|
-
if
|
14
|
+
if options.light?
|
15
15
|
log_light_outcomes
|
16
16
|
else
|
17
17
|
log_outcomes
|
@@ -21,7 +21,7 @@ module QuietQuality
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
attr_reader :
|
24
|
+
attr_reader :stream, :options, :outcomes, :messages
|
25
25
|
|
26
26
|
def failed_outcomes
|
27
27
|
@_failed_outcomes ||= outcomes.select(&:failure?)
|
@@ -31,26 +31,38 @@ module QuietQuality
|
|
31
31
|
@_successful_outcomes ||= outcomes.select(&:success?)
|
32
32
|
end
|
33
33
|
|
34
|
+
def colorize(color_name, s)
|
35
|
+
return s unless options.colorize?
|
36
|
+
Colorize.colorize(s, color: color_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def failed_tools_text
|
40
|
+
colorize(:red, " (#{failed_outcomes.map(&:tool).join(", ")})")
|
41
|
+
end
|
42
|
+
|
34
43
|
def log_light_outcomes
|
35
44
|
line = "%d tools executed: %d passed, %d failed" % [
|
36
45
|
outcomes.count,
|
37
46
|
successful_outcomes.count,
|
38
47
|
failed_outcomes.count
|
39
48
|
]
|
40
|
-
line +=
|
41
|
-
|
49
|
+
line += failed_tools_text if failed_outcomes.any?
|
50
|
+
stream.puts line
|
42
51
|
end
|
43
52
|
|
44
53
|
def log_outcomes
|
45
54
|
outcomes.each do |outcome|
|
46
|
-
|
47
|
-
|
55
|
+
if outcome.success?
|
56
|
+
stream.puts "--- " + colorize(:green, "Passed: #{outcome.tool}")
|
57
|
+
else
|
58
|
+
stream.puts "--- " + colorize(:red, "Failed: #{outcome.tool}")
|
59
|
+
end
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
51
63
|
def log_messages
|
52
64
|
return unless messages.any?
|
53
|
-
|
65
|
+
stream.puts "\n\n#{messages.count} messages:"
|
54
66
|
messages.each { |msg| log_message(msg) }
|
55
67
|
end
|
56
68
|
|
@@ -67,10 +79,11 @@ module QuietQuality
|
|
67
79
|
end
|
68
80
|
|
69
81
|
def log_message(msg)
|
82
|
+
tool = colorize(:yellow, msg.tool_name)
|
70
83
|
line_range = line_range_for(msg)
|
71
|
-
rule_string = msg.rule ? " [#{msg.rule}]" : ""
|
84
|
+
rule_string = msg.rule ? " [#{colorize(:yellow, msg.rule)}]" : ""
|
72
85
|
truncated_body = reduce_text(msg.body, 120)
|
73
|
-
|
86
|
+
stream.puts "#{tool} #{msg.path}:#{line_range}#{rule_string} #{truncated_body}"
|
74
87
|
end
|
75
88
|
end
|
76
89
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
module Colorize
|
3
|
+
CODES = {
|
4
|
+
red: "\e[31m",
|
5
|
+
green: "\e[32m",
|
6
|
+
yellow: "\e[33m",
|
7
|
+
light_blue: "\e[94m",
|
8
|
+
light_cyan: "\e[96m"
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
RESET_CODE = "\e[0m"
|
12
|
+
|
13
|
+
def self.colorize(s, color:)
|
14
|
+
fail(ArgumentError, "Unrecognized color '#{color}'") unless CODES.include?(color.to_sym)
|
15
|
+
color_code = CODES.fetch(color.to_sym)
|
16
|
+
"#{color_code}#{s}#{RESET_CODE}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -106,6 +106,7 @@ module QuietQuality
|
|
106
106
|
|
107
107
|
def update_logging
|
108
108
|
set_unless_nil(options, :logging, apply.global_option(:logging))
|
109
|
+
set_unless_nil(options, :colorize, apply.global_option(:colorize))
|
109
110
|
end
|
110
111
|
|
111
112
|
# ---- update the tool options (apply global forms first) -------
|
@@ -1,19 +1,56 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Config
|
3
3
|
class Options
|
4
|
+
LOGGING_LEVELS = [:quiet, :light, :normal].freeze
|
5
|
+
|
4
6
|
def initialize
|
5
7
|
@annotator = nil
|
6
8
|
@executor = Executors::ConcurrentExecutor
|
7
9
|
@tools = nil
|
8
10
|
@comparison_branch = nil
|
9
|
-
@
|
11
|
+
@colorize = true
|
12
|
+
@logging = :normal
|
10
13
|
end
|
11
14
|
|
12
15
|
attr_accessor :tools, :comparison_branch, :annotator, :executor
|
13
16
|
attr_reader :logging
|
17
|
+
attr_writer :colorize
|
14
18
|
|
15
19
|
def logging=(level)
|
16
|
-
|
20
|
+
fail(ArgumentError, "Unrecognized logging level '#{level}'") unless LOGGING_LEVELS.include?(level.to_sym)
|
21
|
+
@logging = level.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def colorize?
|
25
|
+
!!@colorize
|
26
|
+
end
|
27
|
+
|
28
|
+
def quiet?
|
29
|
+
logging == :quiet
|
30
|
+
end
|
31
|
+
|
32
|
+
def light?
|
33
|
+
logging == :light
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_h
|
37
|
+
{
|
38
|
+
annotator: annotator,
|
39
|
+
executor: executor.name,
|
40
|
+
comparison_branch: comparison_branch,
|
41
|
+
colorize: colorize?,
|
42
|
+
logging: logging,
|
43
|
+
tools: tool_hashes_by_name
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def tool_hashes_by_name
|
50
|
+
return {} unless tools
|
51
|
+
tools
|
52
|
+
.map { |tool_option| [tool_option.tool_name, tool_option.to_h] }
|
53
|
+
.to_h
|
17
54
|
end
|
18
55
|
end
|
19
56
|
end
|
@@ -46,7 +46,8 @@ module QuietQuality
|
|
46
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, :
|
49
|
+
read_global_option(opts, :colorize, :colorize, as: :boolean)
|
50
|
+
read_global_option(opts, :logging, :logging, as: :symbol, validate_from: Options::LOGGING_LEVELS)
|
50
51
|
end
|
51
52
|
|
52
53
|
def store_tool_options(opts)
|
@@ -35,6 +35,15 @@ module QuietQuality
|
|
35
35
|
return nil if @file_filter.nil?
|
36
36
|
Regexp.new(@file_filter)
|
37
37
|
end
|
38
|
+
|
39
|
+
def to_h
|
40
|
+
{
|
41
|
+
tool_name: tool_name,
|
42
|
+
limit_targets: limit_targets?,
|
43
|
+
filter_messages: filter_messages?,
|
44
|
+
file_filter: file_filter&.to_s
|
45
|
+
}
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
40
49
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Executors
|
3
3
|
class Pipeline
|
4
|
+
include Logging
|
5
|
+
|
4
6
|
def initialize(tool_options:, changed_files: nil)
|
5
7
|
@tool_options = tool_options
|
6
8
|
@changed_files = changed_files
|
@@ -25,10 +27,7 @@ module QuietQuality
|
|
25
27
|
|
26
28
|
def messages
|
27
29
|
return @_messages if defined?(@_messages)
|
28
|
-
@_messages = parser.messages
|
29
|
-
@_messages = relevance_filter.filter(@_messages) if filter_messages? && changed_files
|
30
|
-
@_messages.each { |m| locator.update!(m) } if changed_files
|
31
|
-
@_messages
|
30
|
+
@_messages = relocated(filtered(parser.messages))
|
32
31
|
end
|
33
32
|
|
34
33
|
private
|
@@ -51,7 +50,13 @@ module QuietQuality
|
|
51
50
|
@_runner ||= tool_options.runner_class.new(
|
52
51
|
changed_files: limit_targets? ? changed_files : nil,
|
53
52
|
file_filter: tool_options.file_filter
|
54
|
-
)
|
53
|
+
).tap { |r| log_runner(r) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_runner(r)
|
57
|
+
command_string = r.command ? "`#{r.command.join(" ")}`" : "(skipped)"
|
58
|
+
info("Runner #{r.tool_name} command: #{command_string}")
|
59
|
+
debug("Full command for #{r.tool_name}", data: r.command)
|
55
60
|
end
|
56
61
|
|
57
62
|
def parser
|
@@ -65,6 +70,23 @@ module QuietQuality
|
|
65
70
|
def locator
|
66
71
|
@_locator ||= AnnotationLocator.new(changed_files: changed_files)
|
67
72
|
end
|
73
|
+
|
74
|
+
def filtered(messages_object)
|
75
|
+
return messages_object unless filter_messages? && changed_files
|
76
|
+
|
77
|
+
original_count = messages_object.count
|
78
|
+
relevance_filter.filter(messages_object).tap do |filtered|
|
79
|
+
info("Messages for #{tool_name} filtered from #{original_count} to #{filtered.count}")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def relocated(messages_object)
|
84
|
+
if changed_files && !messages_object.empty?
|
85
|
+
messages_object.each { |m| locator.update!(m) }
|
86
|
+
info("Messages for #{tool_name} positioned into the diff for annotation purposes")
|
87
|
+
end
|
88
|
+
messages_object
|
89
|
+
end
|
68
90
|
end
|
69
91
|
end
|
70
92
|
end
|
data/lib/quiet_quality/logger.rb
CHANGED
@@ -1,17 +1,65 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
class Logger
|
3
|
-
|
3
|
+
LEVEL_UPS = {none: :warn, warn: :info, info: :debug}.freeze
|
4
|
+
LEVELS = {none: 0, warn: 1, info: 2, debug: 3}.freeze
|
5
|
+
COLORS = {warn: :yellow, info: :light_blue, debug: :light_cyan}.freeze
|
6
|
+
|
7
|
+
def initialize(level: :warn, stream: $stderr)
|
8
|
+
@level = level
|
4
9
|
@stream = stream
|
5
|
-
@logging = logging
|
6
10
|
end
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
attr_reader :level
|
13
|
+
|
14
|
+
def increase_level!
|
15
|
+
next_level = LEVEL_UPS.fetch(level, nil)
|
16
|
+
self.level = next_level if next_level
|
17
|
+
end
|
18
|
+
|
19
|
+
def show?(message_level)
|
20
|
+
LEVELS[message_level] <= LEVELS[level]
|
21
|
+
end
|
22
|
+
|
23
|
+
def level=(name)
|
24
|
+
fail(ArgumentError, "Unrecognized Logger level '#{name}'") unless LEVELS.include?(name.to_sym)
|
25
|
+
@level = name.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def warn(message, data: nil)
|
29
|
+
log_message(message, data, :warn)
|
30
|
+
end
|
31
|
+
|
32
|
+
def info(message, data: nil)
|
33
|
+
log_message(message, data, :info)
|
34
|
+
end
|
35
|
+
|
36
|
+
def debug(message, data: nil)
|
37
|
+
log_message(message, data, :debug)
|
11
38
|
end
|
12
39
|
|
13
40
|
private
|
14
41
|
|
15
|
-
attr_reader :stream
|
42
|
+
attr_reader :stream
|
43
|
+
|
44
|
+
def log_message(message, data, message_level)
|
45
|
+
return unless show?(message_level)
|
46
|
+
stream.puts formatted_message(message, data, message_level)
|
47
|
+
stream.flush
|
48
|
+
end
|
49
|
+
|
50
|
+
def formatted_message(message, data, message_level)
|
51
|
+
prefix = message_level.to_s.upcase.rjust(5)
|
52
|
+
if data
|
53
|
+
data_text = JSON.pretty_generate(data)
|
54
|
+
message = message + "\n" + data_text
|
55
|
+
end
|
56
|
+
prefixed_message = message.split("\n").map { |line| "[#{prefix}] #{line}" }.join("\n")
|
57
|
+
colorize(prefixed_message, message_level)
|
58
|
+
end
|
59
|
+
|
60
|
+
def colorize(s, message_level)
|
61
|
+
color = COLORS.fetch(message_level)
|
62
|
+
Colorize.colorize(s, color: color)
|
63
|
+
end
|
16
64
|
end
|
17
65
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module QuietQuality
|
2
|
+
module Logging
|
3
|
+
def warn(message, data: nil)
|
4
|
+
logger.warn(message, data: data)
|
5
|
+
end
|
6
|
+
|
7
|
+
def info(message, data: nil)
|
8
|
+
logger.info(message, data: data)
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug(message, data: nil)
|
12
|
+
logger.debug(message, data: data)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def logger
|
18
|
+
QuietQuality.logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module QuietQuality
|
2
2
|
module Tools
|
3
3
|
class BaseRunner
|
4
|
+
include Logging
|
5
|
+
|
4
6
|
# In general, we don't want to supply a huge number of arguments to a command-line tool.
|
5
7
|
MAX_FILES = 100
|
6
8
|
|
@@ -36,6 +38,8 @@ module QuietQuality
|
|
36
38
|
|
37
39
|
def performed_outcome
|
38
40
|
out, err, stat = Open3.capture3(*command)
|
41
|
+
log_performance(err, stat)
|
42
|
+
|
39
43
|
if success_status?(stat)
|
40
44
|
Outcome.new(tool: tool_name, output: out, logging: err)
|
41
45
|
elsif failure_status?(stat)
|
@@ -44,6 +48,11 @@ module QuietQuality
|
|
44
48
|
fail(ExecutionError, "Execution of #{tool_name} failed with #{stat.exitstatus}")
|
45
49
|
end
|
46
50
|
end
|
51
|
+
|
52
|
+
def log_performance(err, stat)
|
53
|
+
info("Runner #{tool_name} exited with #{stat.exitstatus}")
|
54
|
+
debug("Runner logs from #{tool_name}:", data: err&.split("\n"))
|
55
|
+
end
|
47
56
|
end
|
48
57
|
end
|
49
58
|
end
|
data/lib/quiet_quality.rb
CHANGED
@@ -10,7 +10,13 @@ require "set" # rubocop:disable Lint/RedundantRequireStatement
|
|
10
10
|
|
11
11
|
module QuietQuality
|
12
12
|
Error = Class.new(StandardError)
|
13
|
+
|
14
|
+
def self.logger
|
15
|
+
@_logger ||= QuietQuality::Logger.new
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
19
|
+
require_relative "./quiet_quality/logger"
|
20
|
+
require_relative "./quiet_quality/logging"
|
15
21
|
glob = File.expand_path("../quiet_quality/*.rb", __FILE__)
|
16
22
|
Dir.glob(glob).sort.each { |f| require f }
|
data/quiet_quality.gemspec
CHANGED
@@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency "pry", "~> 0.14"
|
41
41
|
spec.add_development_dependency "standard", "~> 1.28"
|
42
42
|
spec.add_development_dependency "rubocop", "~> 1.50"
|
43
|
-
spec.add_development_dependency "debug"
|
43
|
+
spec.add_development_dependency "debug", "~> 1.7"
|
44
44
|
spec.add_development_dependency "mdl", "~> 0.12"
|
45
|
+
spec.add_development_dependency "rspec-cover_it", "~> 0.1.0"
|
45
46
|
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.
|
4
|
+
version: 1.3.1
|
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-06-
|
11
|
+
date: 2023-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
@@ -126,16 +126,16 @@ dependencies:
|
|
126
126
|
name: debug
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '1.7'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '1.7'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: mdl
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0.12'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rspec-cover_it
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.1.0
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.1.0
|
153
167
|
description: |
|
154
168
|
Allow your CI to notice and/or annotate new quality issues, despite the presences of
|
155
169
|
many pre-existing issues in your codebase.
|
@@ -186,10 +200,10 @@ files:
|
|
186
200
|
- lib/quiet_quality/cli/arg_parser.rb
|
187
201
|
- lib/quiet_quality/cli/entrypoint.rb
|
188
202
|
- lib/quiet_quality/cli/presenter.rb
|
203
|
+
- lib/quiet_quality/colorize.rb
|
189
204
|
- lib/quiet_quality/config.rb
|
190
205
|
- lib/quiet_quality/config/builder.rb
|
191
206
|
- lib/quiet_quality/config/finder.rb
|
192
|
-
- lib/quiet_quality/config/logging.rb
|
193
207
|
- lib/quiet_quality/config/options.rb
|
194
208
|
- lib/quiet_quality/config/parsed_options.rb
|
195
209
|
- lib/quiet_quality/config/parser.rb
|
@@ -200,6 +214,7 @@ files:
|
|
200
214
|
- lib/quiet_quality/executors/pipeline.rb
|
201
215
|
- lib/quiet_quality/executors/serial_executor.rb
|
202
216
|
- lib/quiet_quality/logger.rb
|
217
|
+
- lib/quiet_quality/logging.rb
|
203
218
|
- lib/quiet_quality/message.rb
|
204
219
|
- lib/quiet_quality/message_filter.rb
|
205
220
|
- lib/quiet_quality/messages.rb
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module QuietQuality
|
2
|
-
module Config
|
3
|
-
class Logging
|
4
|
-
LIGHT = :light
|
5
|
-
QUIET = :quiet
|
6
|
-
NORMAL = :normal
|
7
|
-
LEVELS = [LIGHT, QUIET, NORMAL].freeze
|
8
|
-
|
9
|
-
attr_accessor :level
|
10
|
-
|
11
|
-
def initialize(level: NORMAL)
|
12
|
-
@level = level
|
13
|
-
end
|
14
|
-
|
15
|
-
def light?
|
16
|
-
@level == LIGHT
|
17
|
-
end
|
18
|
-
|
19
|
-
def quiet?
|
20
|
-
@level == QUIET
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|