quiet_quality 1.5.0 → 1.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ff5a82876936d746842d76e055475ba19e78d0bfff7967b2f179a2262cb5d7e
4
- data.tar.gz: 529ed1d29fdf3c3c6ba381e7ab71cbf006bc44c8d608858e8ec84d67c2efb267
3
+ metadata.gz: f411385dc4547ecadf2e182ca8628a5f95973c43c7340314293b76489b5a5b5a
4
+ data.tar.gz: e414999cb5645c7d64fbcb8b52d02cae9b12be5ec8ea02ae640f2dbd434a5db2
5
5
  SHA512:
6
- metadata.gz: 1b840cfe8d90929c0fcc32fdc1370310924a46464006b39afa5dceff69b8c24254d701002e77f33a845baaa7fe5373243486b5d1422a3beea4fd45a50e65ec8b
7
- data.tar.gz: e3176f406a5de5a027cae5a2edcbd897395a0191dad1a6cb402bf48fb005f9dce3783d8e6778f91e7d05c03b3f12f473ee23438b9235ed5eedd5e4d588a58526
6
+ metadata.gz: de6977b310cc518f46e81ca7404a3913419226c8723faa2554f52aa974759fbe572eab4486b29afe96880d8d5d80a4bc466b14ee85e8a51e2da52a46f2a335c1
7
+ data.tar.gz: 5bacf59ca7abd7004e2910f47e0cfc5fb5e4c8145faa6154b95d308ad73a0cc74a465b8a8a962b0471e4a417de09a486d11aea23f39972399633754c70be0bac
data/.gitignore CHANGED
@@ -4,3 +4,4 @@ Gemfile.lock
4
4
  *.gem
5
5
  coverage/
6
6
  tmp/*
7
+ .DS_Store
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## Release 1.5.2
4
+
5
+ * Support command/exec-command overrides (yaml-only) (#127)
6
+ * Support ruby-git 2.x (#130 resolves #129)
7
+
8
+ ## Release 1.5.1
9
+
10
+ * Refactor ConfigParser to just parse the config into ParsedOptions, separating
11
+ the file-filter/excludes handling properly (#114)
12
+ * Update the standard/rubocop constraints (dev-only)
13
+ * Fail the pipeline when rspec encounters non-spec failures (#120 resolves #119)
14
+ * Expose error messages when brakeman encounters errors (#122 resolves #115)
15
+
3
16
  ## Release 1.5.0
4
17
 
5
18
  * Update to comply with current standardrb rules, and use checkout@v4
@@ -84,7 +84,7 @@ module QuietQuality
84
84
 
85
85
  def set_unless_nil(object, method, value)
86
86
  return if value.nil?
87
- object.send("#{method}=", value)
87
+ object.send(:"#{method}=", value)
88
88
  end
89
89
 
90
90
  # ---- update the global options -------------
@@ -129,15 +129,24 @@ module QuietQuality
129
129
  options.tools.each do |tool_options|
130
130
  update_tool_option(tool_options, :limit_targets)
131
131
  update_tool_option(tool_options, :filter_messages)
132
- update_tool_option(tool_options, :file_filter)
132
+ update_tool_option(tool_options, :command, global: false)
133
+ update_tool_option(tool_options, :exec_command, global: false)
134
+ set_unless_nil(tool_options, :file_filter, build_file_filter(tool_options.tool_name))
133
135
  end
134
136
  end
135
137
 
136
- def update_tool_option(tool_options, option_name)
138
+ def update_tool_option(tool_options, option_name, global: true)
137
139
  tool_name = tool_options.tool_name
138
- set_unless_nil(tool_options, option_name, apply.global_option(option_name))
140
+ set_unless_nil(tool_options, option_name, apply.global_option(option_name)) if global
139
141
  set_unless_nil(tool_options, option_name, apply.tool_option(tool_name, option_name))
140
142
  end
143
+
144
+ def build_file_filter(tool_name)
145
+ filter_string = apply.tool_option(tool_name, :file_filter)
146
+ excludes_strings = apply.tool_option(tool_name, :excludes)
147
+ return nil if filter_string.nil? && (excludes_strings.nil? || excludes_strings.empty?)
148
+ Config::FileFilter.new(regex: filter_string, excludes: excludes_strings)
149
+ end
141
150
  end
142
151
  end
143
152
  end
@@ -8,6 +8,8 @@ module QuietQuality
8
8
  @excludes_strings = excludes
9
9
  end
10
10
 
11
+ attr_reader :regex_string, :excludes_strings
12
+
11
13
  def regex
12
14
  return nil if @regex_string.nil?
13
15
  @_regex ||= Regexp.new(@regex_string)
@@ -33,6 +35,10 @@ module QuietQuality
33
35
  regex_match?(s) && !excludes_match?(s)
34
36
  end
35
37
 
38
+ def ==(other)
39
+ regex_string == other.regex_string && excludes_strings.sort == other.excludes_strings.sort
40
+ end
41
+
36
42
  private
37
43
 
38
44
  # The regex is an allow-match - if it's not supplied, treat everything as matching.
@@ -21,7 +21,10 @@ module QuietQuality
21
21
  TOOL_OPTIONS = [
22
22
  :limit_targets,
23
23
  :filter_messages,
24
- :file_filter
24
+ :file_filter,
25
+ :excludes,
26
+ :command,
27
+ :exec_command
25
28
  ].to_set
26
29
 
27
30
  def initialize
@@ -65,7 +65,10 @@ module QuietQuality
65
65
  read_tool_option(opts, tool_name, :unfiltered, :filter_messages, as: :reversed_boolean)
66
66
  read_tool_option(opts, tool_name, :changed_files, :limit_targets, as: :boolean)
67
67
  read_tool_option(opts, tool_name, :all_files, :limit_targets, as: :reversed_boolean)
68
- read_file_filter(opts, tool_name)
68
+ read_tool_option(opts, tool_name, :file_filter, :file_filter, as: :string)
69
+ read_tool_option(opts, tool_name, :excludes, :excludes, as: :strings)
70
+ read_tool_option(opts, tool_name, :command, :command, as: :strings)
71
+ read_tool_option(opts, tool_name, :exec_command, :exec_command, as: :strings)
69
72
  end
70
73
 
71
74
  def invalid!(message)
@@ -98,21 +101,13 @@ module QuietQuality
98
101
  opts.set_tool_option(tool, into, coerced_value)
99
102
  end
100
103
 
101
- def read_file_filter(opts, tool)
102
- parsed_regex = data.dig(tool.to_sym, :file_filter)
103
- parsed_excludes = data.dig(tool.to_sym, :excludes)
104
- if parsed_regex || parsed_excludes
105
- filter = Config::FileFilter.new(regex: parsed_regex, excludes: parsed_excludes)
106
- opts.set_tool_option(tool, :file_filter, filter)
107
- end
108
- end
109
-
110
104
  def validate_value(name, value, as:, from: nil)
111
105
  case as
112
106
  when :boolean then validate_boolean(name, value)
113
107
  when :reversed_boolean then validate_boolean(name, value)
114
108
  when :symbol then validate_symbol(name, value, from: from)
115
109
  when :string then validate_string(name, value)
110
+ when :strings then validate_strings(name, value)
116
111
  end
117
112
  end
118
113
 
@@ -138,11 +133,17 @@ module QuietQuality
138
133
  invalid!("option #{name} must not be empty") if value.empty?
139
134
  end
140
135
 
136
+ def validate_strings(name, value)
137
+ invalid!("option #{name} must be an array") unless value.is_a?(Array)
138
+ value.each_with_index { |item, n| validate_string("#{name}[#{n}]", item) }
139
+ end
140
+
141
141
  def coerce_value(value, as:)
142
142
  case as
143
143
  when :boolean then !!value
144
144
  when :reversed_boolean then !value
145
145
  when :string then value.to_s
146
+ when :strings then value.map(&:to_s)
146
147
  when :symbol then value.to_sym
147
148
  end
148
149
  end
@@ -1,14 +1,16 @@
1
1
  module QuietQuality
2
2
  module Config
3
3
  class ToolOptions
4
- def initialize(tool, limit_targets: true, filter_messages: true, file_filter: nil)
4
+ def initialize(tool, **options)
5
5
  @tool_name = tool.to_sym
6
- @limit_targets = limit_targets
7
- @filter_messages = filter_messages
8
- @file_filter = file_filter
6
+ @limit_targets = options.fetch(:limit_targets, true)
7
+ @filter_messages = options.fetch(:filter_messages, true)
8
+ @file_filter = options.fetch(:file_filter, nil)
9
+ @command = options.fetch(:command, nil)
10
+ @exec_command = options.fetch(:exec_command, nil)
9
11
  end
10
12
 
11
- attr_accessor :file_filter
13
+ attr_accessor :file_filter, :command, :exec_command
12
14
  attr_reader :tool_name
13
15
  attr_writer :limit_targets, :filter_messages
14
16
 
@@ -38,6 +40,8 @@ module QuietQuality
38
40
  limit_targets: limit_targets?,
39
41
  filter_messages: filter_messages?,
40
42
  file_filter: file_filter&.regex&.to_s,
43
+ command: command,
44
+ exec_command: exec_command,
41
45
  excludes: file_filter&.excludes&.map(&:to_s)
42
46
  }
43
47
  end
@@ -32,7 +32,9 @@ module QuietQuality
32
32
  def runner
33
33
  @_runner ||= tool_options.runner_class.new(
34
34
  changed_files: limit_targets? ? changed_files : nil,
35
- file_filter: tool_options.file_filter
35
+ file_filter: tool_options.file_filter,
36
+ command_override: tool_options.command,
37
+ exec_override: tool_options.exec_command
36
38
  ).tap { |r| log_runner(r) }
37
39
  end
38
40
 
@@ -49,7 +49,9 @@ module QuietQuality
49
49
  def runner
50
50
  @_runner ||= tool_options.runner_class.new(
51
51
  changed_files: limit_targets? ? changed_files : nil,
52
- file_filter: tool_options.file_filter
52
+ file_filter: tool_options.file_filter,
53
+ command_override: tool_options.command,
54
+ exec_override: tool_options.exec_command
53
55
  ).tap { |r| log_runner(r) }
54
56
  end
55
57
 
@@ -53,8 +53,10 @@ module QuietQuality
53
53
  data_text = JSON.pretty_generate(data)
54
54
  message = message + "\n" + data_text
55
55
  end
56
- prefixed_message = message.split("\n").map { |line| "[#{prefix}] #{line}" }.join("\n")
57
- colorize(prefixed_message, message_level)
56
+ message.split("\n")
57
+ .map { |line| "[#{prefix}] #{line}" }
58
+ .map { |prefixed_line| colorize(prefixed_line, message_level) }
59
+ .join("\n")
58
60
  end
59
61
 
60
62
  def colorize(s, message_level)
@@ -6,9 +6,11 @@ module QuietQuality
6
6
  # In general, we don't want to supply a huge number of arguments to a command-line tool.
7
7
  MAX_FILES = 100
8
8
 
9
- def initialize(changed_files: nil, file_filter: nil)
9
+ def initialize(changed_files: nil, file_filter: nil, command_override: nil, exec_override: nil)
10
10
  @changed_files = changed_files
11
11
  @file_filter = file_filter
12
+ @command_override = command_override
13
+ @exec_override = exec_override
12
14
  end
13
15
 
14
16
  def invoke!
@@ -38,7 +40,7 @@ module QuietQuality
38
40
 
39
41
  private
40
42
 
41
- attr_reader :changed_files, :file_filter
43
+ attr_reader :changed_files, :file_filter, :command_override, :exec_override
42
44
 
43
45
  def performed_outcome
44
46
  out, err, stat = Open3.capture3(*command)
@@ -2,6 +2,8 @@ module QuietQuality
2
2
  module Tools
3
3
  module Brakeman
4
4
  class Parser
5
+ include Logging
6
+
5
7
  def initialize(text)
6
8
  @text = text
7
9
  end
@@ -24,6 +26,8 @@ module QuietQuality
24
26
  def check_errors!
25
27
  errors = data[:errors]
26
28
  return if errors.nil? || errors.empty?
29
+ warn "Brakeman errors:"
30
+ errors.each { |error| warn " #{error}" }
27
31
  fail(ParsingError, "Found #{errors.length} errors in brakeman output")
28
32
  end
29
33
 
@@ -7,11 +7,11 @@ module QuietQuality
7
7
  end
8
8
 
9
9
  def command
10
- ["brakeman", "-f", "json"]
10
+ command_override || ["brakeman", "-f", "json"]
11
11
  end
12
12
 
13
13
  def exec_command
14
- ["brakeman"]
14
+ exec_override || ["brakeman"]
15
15
  end
16
16
 
17
17
  # These are specified in constants at the top of brakeman.rb:
@@ -12,22 +12,27 @@ module QuietQuality
12
12
 
13
13
  def command(json: true)
14
14
  return nil if skip_execution?
15
- base_command = ["mdl"]
16
- base_command << "--json" if json
17
- if target_files.any?
18
- base_command + target_files.sort
19
- else
20
- base_command + ["."]
21
- end
15
+ (command_override || ["mdl", "--json"]) + command_targets
22
16
  end
23
17
 
24
18
  def exec_command
25
- command(json: false)
19
+ return nil if skip_execution?
20
+ (exec_override || ["mdl"]) + command_targets
26
21
  end
27
22
 
28
23
  def relevant_path?(path)
29
24
  path.end_with?(".md")
30
25
  end
26
+
27
+ private
28
+
29
+ def command_targets
30
+ if target_files.any?
31
+ target_files.sort
32
+ else
33
+ ["."]
34
+ end
35
+ end
31
36
  end
32
37
  end
33
38
  end
@@ -13,12 +13,12 @@ module QuietQuality
13
13
 
14
14
  def command
15
15
  return nil if skip_execution?
16
- base_command + target_files.sort
16
+ (command_override || base_command) + target_files.sort
17
17
  end
18
18
 
19
19
  def exec_command
20
20
  return nil if skip_execution?
21
- base_exec_command + target_files.sort
21
+ (exec_override || base_exec_command) + target_files.sort
22
22
  end
23
23
 
24
24
  def relevant_path?(path)
@@ -2,6 +2,8 @@ module QuietQuality
2
2
  module Tools
3
3
  module Rspec
4
4
  class Parser
5
+ include Logging
6
+
5
7
  def initialize(text)
6
8
  @text = text
7
9
  end
@@ -39,7 +41,9 @@ module QuietQuality
39
41
  end
40
42
 
41
43
  def examples
42
- @_examples ||= content.fetch(:examples)
44
+ return @_examples if defined?(@_examples)
45
+ raise_if_errors_outside_of_examples!
46
+ @_examples = content.fetch(:examples)
43
47
  end
44
48
 
45
49
  def failed_examples
@@ -63,6 +67,25 @@ module QuietQuality
63
67
  tool_name: TOOL_NAME
64
68
  )
65
69
  end
70
+
71
+ def errors_count
72
+ @_errors_count ||= content.dig(:summary, :errors_outside_of_examples_count) || 0
73
+ end
74
+
75
+ def error_messages
76
+ @_error_messages ||= content.fetch(:messages, [])
77
+ end
78
+
79
+ def raise_if_errors_outside_of_examples!
80
+ return if errors_count < 1
81
+ warn "RSpec errors:"
82
+ warn "-" * 80
83
+ error_messages.each do |msg|
84
+ warn msg
85
+ warn "-" * 80
86
+ end
87
+ fail Rspec::Error, "Rspec encountered #{errors_count} errors outside of examples"
88
+ end
66
89
  end
67
90
  end
68
91
  end
@@ -2,6 +2,8 @@ module QuietQuality
2
2
  module Tools
3
3
  module Rspec
4
4
  TOOL_NAME = :rspec
5
+
6
+ Error = Class.new(Tools::Error)
5
7
  end
6
8
  end
7
9
  end
@@ -1,3 +1,3 @@
1
1
  module QuietQuality
2
- VERSION = "1.5.0"
2
+ VERSION = "1.5.2"
3
3
  end
@@ -31,15 +31,15 @@ Gem::Specification.new do |spec|
31
31
  .map { |path| path.sub(/^bin\//, "") }
32
32
  end
33
33
 
34
- spec.add_dependency "git", "~> 1.18"
34
+ spec.add_dependency "git", ">= 1.18"
35
35
  spec.add_dependency "git_diff_parser", "~> 4"
36
36
 
37
- spec.add_development_dependency "rspec", "~> 3.10"
37
+ spec.add_development_dependency "rspec", "~> 3.13"
38
38
  spec.add_development_dependency "rspec-its", "~> 1.3"
39
39
  spec.add_development_dependency "simplecov", "~> 0.22.0"
40
40
  spec.add_development_dependency "pry", "~> 0.14"
41
- spec.add_development_dependency "standard", "~> 1.28"
42
- spec.add_development_dependency "rubocop", "~> 1.50"
41
+ spec.add_development_dependency "standard", ">= 1.35.1"
42
+ spec.add_development_dependency "rubocop", ">= 1.62"
43
43
  spec.add_development_dependency "debug", "~> 1.7"
44
44
  spec.add_development_dependency "mdl", "~> 0.12"
45
45
  spec.add_development_dependency "rspec-cover_it", "~> 0.1.0"
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quiet_quality
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.2
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-11-15 00:00:00.000000000 Z
11
+ date: 2024-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.18'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.18'
27
27
  - !ruby/object:Gem::Dependency
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.10'
47
+ version: '3.13'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.10'
54
+ version: '3.13'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec-its
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -98,30 +98,30 @@ dependencies:
98
98
  name: standard
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '1.28'
103
+ version: 1.35.1
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '1.28'
110
+ version: 1.35.1
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '1.50'
117
+ version: '1.62'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '1.50'
124
+ version: '1.62'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: debug
127
127
  requirement: !ruby/object:Gem::Requirement