rubocop-minitest 0.15.1 → 0.17.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -9
  3. data/.github/PULL_REQUEST_TEMPLATE.md +3 -4
  4. data/.github/workflows/spell_checking.yml +33 -0
  5. data/.rubocop.yml +2 -3
  6. data/.rubocop_todo.yml +2 -0
  7. data/.yardopts +3 -0
  8. data/CHANGELOG.md +30 -0
  9. data/CONTRIBUTING.md +3 -2
  10. data/Gemfile +4 -1
  11. data/LICENSE.txt +1 -1
  12. data/Rakefile +4 -6
  13. data/codespell.txt +0 -0
  14. data/config/default.yml +13 -2
  15. data/docs/antora.yml +1 -1
  16. data/docs/modules/ROOT/pages/cops_minitest.adoc +99 -4
  17. data/docs/modules/ROOT/pages/installation.adoc +1 -1
  18. data/lib/rubocop/cop/minitest/assert_empty.rb +12 -0
  19. data/lib/rubocop/cop/minitest/assert_empty_literal.rb +1 -1
  20. data/lib/rubocop/cop/minitest/assert_with_expected_argument.rb +3 -2
  21. data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +1 -1
  22. data/lib/rubocop/cop/minitest/global_expectations.rb +109 -38
  23. data/lib/rubocop/cop/minitest/multiple_assertions.rb +1 -1
  24. data/lib/rubocop/cop/minitest/no_assertions.rb +1 -1
  25. data/lib/rubocop/cop/minitest/refute_empty.rb +12 -0
  26. data/lib/rubocop/cop/minitest/unreachable_assertion.rb +2 -4
  27. data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +9 -21
  28. data/lib/rubocop/minitest/assert_offense.rb +183 -0
  29. data/lib/rubocop/minitest/support.rb +10 -0
  30. data/lib/rubocop/minitest/version.rb +1 -1
  31. data/mkdocs.yml +1 -1
  32. data/relnotes/v0.15.2.md +5 -0
  33. data/relnotes/v0.16.0.md +11 -0
  34. data/relnotes/v0.17.0.md +5 -0
  35. data/relnotes/v0.17.1.md +5 -0
  36. data/rubocop-minitest.gemspec +2 -1
  37. data/tasks/changelog.rake +34 -0
  38. data/tasks/changelog.rb +166 -0
  39. data/tasks/cops_documentation.rake +5 -15
  40. data/tasks/cut_release.rake +19 -4
  41. metadata +16 -4
@@ -6,17 +6,83 @@ module RuboCop
6
6
  # This cop checks for deprecated global expectations
7
7
  # and autocorrects them to use expect format.
8
8
  #
9
- # @example
9
+ # @example EnforcedStyle: _
10
10
  # # bad
11
11
  # musts.must_equal expected_musts
12
12
  # wonts.wont_match expected_wonts
13
13
  # musts.must_raise TypeError
14
14
  #
15
+ # expect(musts).must_equal expected_musts
16
+ # expect(wonts).wont_match expected_wonts
17
+ # expect { musts }.must_raise TypeError
18
+ #
19
+ # value(musts).must_equal expected_musts
20
+ # value(wonts).wont_match expected_wonts
21
+ # value { musts }.must_raise TypeError
22
+ #
15
23
  # # good
16
24
  # _(musts).must_equal expected_musts
17
25
  # _(wonts).wont_match expected_wonts
18
26
  # _ { musts }.must_raise TypeError
27
+ #
28
+ # @example EnforcedStyle: any (default)
29
+ # # bad
30
+ # musts.must_equal expected_musts
31
+ # wonts.wont_match expected_wonts
32
+ # musts.must_raise TypeError
33
+ #
34
+ # # good
35
+ # _(musts).must_equal expected_musts
36
+ # _(wonts).wont_match expected_wonts
37
+ # _ { musts }.must_raise TypeError
38
+ #
39
+ # expect(musts).must_equal expected_musts
40
+ # expect(wonts).wont_match expected_wonts
41
+ # expect { musts }.must_raise TypeError
42
+ #
43
+ # value(musts).must_equal expected_musts
44
+ # value(wonts).wont_match expected_wonts
45
+ # value { musts }.must_raise TypeError
46
+ #
47
+ # @example EnforcedStyle: expect
48
+ # # bad
49
+ # musts.must_equal expected_musts
50
+ # wonts.wont_match expected_wonts
51
+ # musts.must_raise TypeError
52
+ #
53
+ # _(musts).must_equal expected_musts
54
+ # _(wonts).wont_match expected_wonts
55
+ # _ { musts }.must_raise TypeError
56
+ #
57
+ # value(musts).must_equal expected_musts
58
+ # value(wonts).wont_match expected_wonts
59
+ # value { musts }.must_raise TypeError
60
+ #
61
+ # # good
62
+ # expect(musts).must_equal expected_musts
63
+ # expect(wonts).wont_match expected_wonts
64
+ # expect { musts }.must_raise TypeError
65
+ #
66
+ # @example EnforcedStyle: value
67
+ # # bad
68
+ # musts.must_equal expected_musts
69
+ # wonts.wont_match expected_wonts
70
+ # musts.must_raise TypeError
71
+ #
72
+ # _(musts).must_equal expected_musts
73
+ # _(wonts).wont_match expected_wonts
74
+ # _ { musts }.must_raise TypeError
75
+ #
76
+ # expect(musts).must_equal expected_musts
77
+ # expect(wonts).wont_match expected_wonts
78
+ # expect { musts }.must_raise TypeError
79
+ #
80
+ # # good
81
+ # value(musts).must_equal expected_musts
82
+ # value(wonts).wont_match expected_wonts
83
+ # value { musts }.must_raise TypeError
19
84
  class GlobalExpectations < Base
85
+ include ConfigurableEnforcedStyle
20
86
  extend AutoCorrector
21
87
 
22
88
  MSG = 'Use `%<preferred>s` instead.'
@@ -34,58 +100,63 @@ module RuboCop
34
100
 
35
101
  RESTRICT_ON_SEND = VALUE_MATCHERS + BLOCK_MATCHERS
36
102
 
37
- VALUE_MATCHERS_STR = VALUE_MATCHERS.map do |m|
38
- ":#{m}"
39
- end.join(' ').freeze
103
+ # There are aliases for the `_` method - `expect` and `value`
104
+ DSL_METHODS = %i[_ expect value].freeze
40
105
 
41
- BLOCK_MATCHERS_STR = BLOCK_MATCHERS.map do |m|
42
- ":#{m}"
43
- end.join(' ').freeze
106
+ def on_send(node)
107
+ receiver = node.receiver
108
+ return unless receiver
44
109
 
45
- # There are aliases for the `_` method - `expect` and `value`
46
- DSL_METHODS_LIST = %w[_ value expect].map do |n|
47
- ":#{n}"
48
- end.join(' ').freeze
110
+ method = block_receiver?(receiver) || value_receiver?(receiver)
111
+ return if method == preferred_method || (method && style == :any)
112
+
113
+ register_offense(node, method)
114
+ end
49
115
 
50
- def_node_matcher :value_global_expectation?, <<~PATTERN
51
- (send !(send nil? {#{DSL_METHODS_LIST}} _) {#{VALUE_MATCHERS_STR}} ...)
116
+ private
117
+
118
+ def_node_matcher :block_receiver?, <<~PATTERN
119
+ (block (send nil? $#method_allowed?) _ _)
52
120
  PATTERN
53
121
 
54
- def_node_matcher :block_global_expectation?, <<~PATTERN
55
- (send
56
- [
57
- !(send nil? {#{DSL_METHODS_LIST}} _)
58
- !(block (send nil? {#{DSL_METHODS_LIST}}) _ _)
59
- ]
60
- {#{BLOCK_MATCHERS_STR}}
61
- _
62
- )
122
+ def_node_matcher :value_receiver?, <<~PATTERN
123
+ (send nil? $#method_allowed? _)
63
124
  PATTERN
64
125
 
65
- def on_send(node)
66
- return unless value_global_expectation?(node) || block_global_expectation?(node)
126
+ def method_allowed?(method)
127
+ DSL_METHODS.include?(method)
128
+ end
67
129
 
68
- message = format(MSG, preferred: preferred_receiver(node))
130
+ def preferred_method
131
+ style == :any ? :_ : style
132
+ end
69
133
 
70
- add_offense(node.receiver.source_range, message: message) do |corrector|
71
- receiver = node.receiver.source_range
134
+ def preferred_receiver(node)
135
+ receiver = node.receiver
72
136
 
73
- if BLOCK_MATCHERS.include?(node.method_name)
74
- corrector.wrap(receiver, '_ { ', ' }')
75
- else
76
- corrector.wrap(receiver, '_(', ')')
77
- end
137
+ if BLOCK_MATCHERS.include?(node.method_name)
138
+ body = receiver.lambda? ? receiver.body : receiver
139
+ "#{preferred_method} { #{body.source} }"
140
+ else
141
+ "#{preferred_method}(#{receiver.source})"
78
142
  end
79
143
  end
80
144
 
81
- private
145
+ def register_offense(node, method)
146
+ receiver = node.receiver
82
147
 
83
- def preferred_receiver(node)
84
- source = node.receiver.source
85
- if BLOCK_MATCHERS.include?(node.method_name)
86
- "_ { #{source} }"
148
+ if method
149
+ preferred = preferred_method
150
+ replacement = receiver.source.sub(method.to_s, preferred_method.to_s)
87
151
  else
88
- "_(#{source})"
152
+ preferred = preferred_receiver(node)
153
+ replacement = preferred
154
+ end
155
+
156
+ message = format(MSG, preferred: preferred)
157
+
158
+ add_offense(receiver, message: message) do |corrector|
159
+ corrector.replace(receiver, replacement)
89
160
  end
90
161
  end
91
162
  end
@@ -50,7 +50,7 @@ module RuboCop
50
50
  private
51
51
 
52
52
  def assertions_count(node)
53
- base = assertion?(node) ? 1 : 0
53
+ base = assertion_method?(node) ? 1 : 0
54
54
  base + node.each_child_node.sum { |c| assertions_count(c) }
55
55
  end
56
56
 
@@ -39,7 +39,7 @@ module RuboCop
39
39
  private
40
40
 
41
41
  def assertions_count(node)
42
- base = assertion?(node) ? 1 : 0
42
+ base = assertion_method?(node) ? 1 : 0
43
43
  base + node.each_child_node.sum { |c| assertions_count(c) }
44
44
  end
45
45
  end
@@ -19,6 +19,18 @@ module RuboCop
19
19
  extend MinitestCopRule
20
20
 
21
21
  define_rule :refute, target_method: :empty?
22
+
23
+ remove_method :on_send
24
+ def on_send(node)
25
+ return unless node.method?(:refute)
26
+ return unless (arguments = peel_redundant_parentheses_from(node.arguments))
27
+ return unless arguments.first.respond_to?(:method?) && arguments.first.method?(:empty?)
28
+ return unless arguments.first.arguments.empty?
29
+
30
+ add_offense(node, message: offense_message(arguments)) do |corrector|
31
+ autocorrect(corrector, node, arguments)
32
+ end
33
+ end
22
34
  end
23
35
  end
24
36
  end
@@ -30,11 +30,9 @@ module RuboCop
30
30
 
31
31
  last_node = body.begin_type? ? body.children.last : body
32
32
  return unless last_node.send_type?
33
+ return unless assertion_method?(last_node)
33
34
 
34
- method_name = last_node.method_name
35
- return unless assertion_method?(method_name)
36
-
37
- add_offense(last_node, message: format(MSG, assertion_method: method_name))
35
+ add_offense(last_node, message: format(MSG, assertion_method: last_node.method_name))
38
36
  end
39
37
  end
40
38
  end
@@ -10,17 +10,6 @@ module RuboCop
10
10
 
11
11
  ASSERTION_PREFIXES = %w[assert refute].freeze
12
12
 
13
- ASSERTION_METHODS = %i[
14
- assert assert_empty assert_equal assert_in_delta assert_in_epsilon assert_includes assert_instance_of
15
- assert_kind_of assert_match assert_nil assert_operator assert_output assert_path_exists assert_predicate
16
- assert_raises assert_respond_to assert_same assert_send assert_silent assert_throws
17
- refute refute_empty refute_equal refute_in_delta refute_in_epsilon refute_includes refute_instance_of
18
- refute_kind_of refute_match refute_nil refute_operator refute_path_exists refute_predicate
19
- refute_respond_to refute_same
20
- ].freeze
21
-
22
- FLUNK = 'flunk'
23
-
24
13
  LIFECYCLE_HOOK_METHODS = %i[
25
14
  before_setup
26
15
  setup
@@ -84,19 +73,18 @@ module RuboCop
84
73
  method_def.each_child_node(:send)
85
74
  end
86
75
 
87
- send_nodes.select { |send_node| assertion?(send_node) }
76
+ send_nodes.select { |send_node| assertion_method?(send_node) }
88
77
  end
89
78
 
90
- def assertion?(node)
91
- node.send_type? &&
92
- ASSERTION_PREFIXES.any? do |prefix|
93
- method_name = node.method_name.to_s
94
- method_name == FLUNK || method_name.start_with?(prefix)
95
- end
96
- end
79
+ def assertion_method?(node)
80
+ return false unless node.send_type?
81
+
82
+ ASSERTION_PREFIXES.any? do |prefix|
83
+ method_name = node.method_name
97
84
 
98
- def assertion_method?(method_name)
99
- method_name == FLUNK || ASSERTION_METHODS.include?(method_name)
85
+ # TODO: Remove the fllowing `to_s` since Ruby 2.7 that supports `Symbol#start_with?`.
86
+ method_name.to_s.start_with?(prefix) || node.method?(:flunk)
87
+ end
100
88
  end
101
89
 
102
90
  def lifecycle_hook_method?(node)
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Laziness copied from rubocop source code
4
+ require 'rubocop/rspec/expect_offense'
5
+ require 'rubocop/cop/legacy/corrector'
6
+
7
+ module RuboCop
8
+ module Minitest
9
+ # Mixin for `assert_offense` and `assert_no_offenses`
10
+ #
11
+ # This mixin makes it easier to specify strict offense assertions
12
+ # in a declarative and visual fashion. Just type out the code that
13
+ # should generate a offense, annotate code by writing '^'s
14
+ # underneath each character that should be highlighted, and follow
15
+ # the carets with a string (separated by a space) that is the
16
+ # message of the offense. You can include multiple offenses in
17
+ # one code snippet.
18
+ #
19
+ # @example Usage
20
+ #
21
+ # assert_offense(<<~RUBY)
22
+ # class FooTest < Minitest::Test
23
+ # def test_do_something
24
+ # assert_equal(nil, somestuff)
25
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_nil(somestuff)` over `assert_equal(nil, somestuff)`.
26
+ # end
27
+ # end
28
+ # RUBY
29
+ #
30
+ # Auto-correction can be tested using `assert_correction` after
31
+ # `assert_offense`.
32
+ #
33
+ # @example `assert_offense` and `assert_correction`
34
+ #
35
+ # assert_offense(<<~RUBY)
36
+ # class FooTest < Minitest::Test
37
+ # def test_do_something
38
+ # assert_equal(nil, somestuff)
39
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_nil(somestuff)` over `assert_equal(nil, somestuff)`.
40
+ # end
41
+ # end
42
+ # RUBY
43
+ #
44
+ # assert_correction(<<~RUBY)
45
+ # class FooTest < Minitest::Test
46
+ # def test_do_something
47
+ # assert_nil(somestuff)
48
+ # end
49
+ # end
50
+ # RUBY
51
+ #
52
+ # If you do not want to specify an offense then use the
53
+ # companion method `assert_no_offenses`. This method is a much
54
+ # simpler assertion since it just inspects the source and checks
55
+ # that there were no offenses. The `assert_offense` method has
56
+ # to do more work by parsing out lines that contain carets.
57
+ #
58
+ # If the code produces an offense that could not be auto-corrected, you can
59
+ # use `assert_no_corrections` after `assert_offense`.
60
+ #
61
+ # @example `assert_offense` and `assert_no_corrections`
62
+ #
63
+ # assert_offense(<<~RUBY)
64
+ # class FooTest < Minitest::Test
65
+ # def test_do_something
66
+ # assert_equal(nil, somestuff)
67
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_nil(somestuff)` over `assert_equal(nil, somestuff)`.
68
+ # end
69
+ # end
70
+ # RUBY
71
+ #
72
+ # assert_no_corrections
73
+ module AssertOffense
74
+ private
75
+
76
+ def setup
77
+ cop_name = self.class.to_s.delete_suffix('Test')
78
+
79
+ @cop = RuboCop::Cop::Minitest.const_get(cop_name).new
80
+ end
81
+
82
+ def assert_no_offenses(source, file = nil)
83
+ setup_assertion
84
+
85
+ offenses = inspect_source(source, @cop, file)
86
+
87
+ expected_annotations = RuboCop::RSpec::ExpectOffense::AnnotatedSource.parse(source)
88
+ actual_annotations = expected_annotations.with_offense_annotations(offenses)
89
+
90
+ assert_equal(source, actual_annotations.to_s)
91
+ end
92
+
93
+ def assert_offense(source, file = nil)
94
+ setup_assertion
95
+
96
+ @cop.instance_variable_get(:@options)[:auto_correct] = true
97
+
98
+ expected_annotations = RuboCop::RSpec::ExpectOffense::AnnotatedSource.parse(source)
99
+ if expected_annotations.plain_source == source
100
+ raise 'Use `assert_no_offenses` to assert that no offenses are found'
101
+ end
102
+
103
+ @processed_source = parse_source!(expected_annotations.plain_source, file)
104
+
105
+ offenses = _investigate(@cop, @processed_source)
106
+
107
+ actual_annotations = expected_annotations.with_offense_annotations(offenses)
108
+
109
+ assert_equal(expected_annotations.to_s, actual_annotations.to_s)
110
+ end
111
+
112
+ def _investigate(cop, processed_source)
113
+ team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
114
+ report = team.investigate(processed_source)
115
+ @last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
116
+ report.offenses
117
+ end
118
+
119
+ def assert_correction(correction, loop: true)
120
+ raise '`assert_correction` must follow `assert_offense`' unless @processed_source
121
+
122
+ iteration = 0
123
+ new_source = loop do
124
+ iteration += 1
125
+
126
+ corrected_source = @last_corrector.rewrite
127
+
128
+ break corrected_source unless loop
129
+ break corrected_source if @last_corrector.empty? || corrected_source == @processed_source.buffer.source
130
+
131
+ if iteration > RuboCop::Runner::MAX_ITERATIONS
132
+ raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
133
+ end
134
+
135
+ # Prepare for next loop
136
+ @processed_source = parse_source!(corrected_source, @processed_source.path)
137
+
138
+ _investigate(@cop, @processed_source)
139
+ end
140
+
141
+ assert_equal(correction, new_source)
142
+ end
143
+
144
+ def setup_assertion
145
+ RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
146
+ RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
147
+ end
148
+
149
+ def inspect_source(source, cop, file = nil)
150
+ processed_source = parse_source!(source, file)
151
+ raise 'Error parsing example code' unless processed_source.valid_syntax?
152
+
153
+ _investigate(cop, processed_source)
154
+ end
155
+
156
+ def investigate(cop, processed_source)
157
+ needed = Hash.new { |h, k| h[k] = [] }
158
+ Array(cop.class.joining_forces).each { |force| needed[force] << cop }
159
+ forces = needed.map do |force_class, joining_cops|
160
+ force_class.new(joining_cops)
161
+ end
162
+
163
+ commissioner = RuboCop::Cop::Commissioner.new([cop], forces, raise_error: true)
164
+ commissioner.investigate(processed_source)
165
+ commissioner
166
+ end
167
+
168
+ def parse_source!(source, file = nil)
169
+ if file.respond_to?(:write)
170
+ file.write(source)
171
+ file.rewind
172
+ file = file.path
173
+ end
174
+
175
+ RuboCop::ProcessedSource.new(source, ruby_version, file)
176
+ end
177
+
178
+ def ruby_version
179
+ 2.5
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Require this file to load code that supports testing using Minitest.
4
+
5
+ require 'rubocop'
6
+ require 'minitest/autorun'
7
+ require 'minitest/pride'
8
+ require_relative 'assert_offense'
9
+
10
+ Minitest::Test.include RuboCop::Minitest::AssertOffense
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Minitest
5
5
  # This module holds the RuboCop Minitest version information.
6
6
  module Version
7
- STRING = '0.15.1'
7
+ STRING = '0.17.1'
8
8
 
9
9
  def self.document_version
10
10
  STRING.match('\d+\.\d+').to_s
data/mkdocs.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  site_name: "A RuboCop extension focused on enforcing Minitest best practices and coding conventions."
2
2
  repo_url: https://github.com/rubocop/rubocop-minitest
3
3
  edit_uri: edit/master/legacy-docs/
4
- copyright: "Copyright &copy; 2021 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO, and RuboCop contributors"
4
+ copyright: "Copyright &copy; 2022 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO, and RuboCop contributors"
5
5
  docs_dir: legacy-docs
6
6
  pages:
7
7
  - Home: index.md
@@ -0,0 +1,5 @@
1
+ ### Bug fixes
2
+
3
+ * [#145](https://github.com/rubocop/rubocop-minitest/pull/145): Mark `Minitest/AssertEmptyLiteral` as safe auto-correction. ([@koic][])
4
+
5
+ [@koic]: https://github.com/koic
@@ -0,0 +1,11 @@
1
+ ### New features
2
+
3
+ * [#147](https://github.com/rubocop/rubocop-minitest/issues/147): Add `EnforcedStyle` config parameter for `Minitest/GlobalExpectations`. ([@gi][])
4
+
5
+ ### Bug fixes
6
+
7
+ * [#142](https://github.com/rubocop/rubocop-minitest/issues/142): Fix `Minitest/GlobalExpectations` autocorrect when receiver is lambda. ([@gi][])
8
+ * [#150](https://github.com/rubocop/rubocop-minitest/issues/150): Fix a false positive for `Minitest/AssertEmpty` and `RefuteEmpty` cops when using `empty` method with any arguments. ([@koic][])
9
+
10
+ [@gi]: https://github.com/gi
11
+ [@koic]: https://github.com/koic
@@ -0,0 +1,5 @@
1
+ ### New features
2
+
3
+ * [#155](https://github.com/rubocop/rubocop-minitest/issues/155): Provide `assert_offense`, `assert_correction`, and `assert_no_offenses` testing APIs for custom Minitest cop development. ([@koic][])
4
+
5
+ [@koic]: https://github.com/koic
@@ -0,0 +1,5 @@
1
+ ### Changes
2
+
3
+ * [#158](https://github.com/rubocop/rubocop-minitest/pull/158): Make `Minitest/UnreachableAssertion` aware of `assert` and `refute` prefix methods. ([@koic][])
4
+
5
+ [@koic]: https://github.com/koic
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
22
22
  'changelog_uri' => 'https://github.com/rubocop/rubocop-minitest/blob/master/CHANGELOG.md',
23
23
  'source_code_uri' => 'https://github.com/rubocop/rubocop-minitest',
24
24
  'documentation_uri' => "https://docs.rubocop.org/rubocop-minitest/#{RuboCop::Minitest::Version.document_version}",
25
- 'bug_tracker_uri' => 'https://github.com/rubocop/rubocop-minitest/issues'
25
+ 'bug_tracker_uri' => 'https://github.com/rubocop/rubocop-minitest/issues',
26
+ 'rubygems_mfa_required' => 'true'
26
27
  }
27
28
 
28
29
  # Specify which files should be added to the gem when it is released.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ autoload :Changelog, "#{__dir__}/changelog"
4
+
5
+ namespace :changelog do
6
+ %i[new fix change].each do |type|
7
+ desc "Create a Changelog entry (#{type})"
8
+ task type, [:id] do |_task, args|
9
+ ref_type = :pull if args[:id]
10
+ path = Changelog::Entry.new(type: type, ref_id: args[:id], ref_type: ref_type).write
11
+ cmd = "git add #{path}"
12
+ system cmd
13
+ puts "Entry '#{path}' created and added to git index"
14
+ end
15
+ end
16
+
17
+ desc 'Merge entries and delete them'
18
+ task :merge do
19
+ raise 'No entries!' unless Changelog.pending?
20
+
21
+ Changelog.new.merge!.and_delete!
22
+ cmd = "git commit -a -m 'Update Changelog'"
23
+ puts cmd
24
+ system cmd
25
+ end
26
+
27
+ task :check_clean do
28
+ next unless Changelog.pending?
29
+
30
+ puts '*** Pending changelog entries!'
31
+ puts 'Do `bundle exec rake changelog:merge`'
32
+ exit(1)
33
+ end
34
+ end