gitlab-styles 4.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +18 -0
  3. data/.gitlab-ci.yml +4 -15
  4. data/.gitlab/merge_request_templates/Release.md +4 -4
  5. data/.rubocop.yml +3 -1
  6. data/Gemfile +3 -2
  7. data/README.md +1 -0
  8. data/gitlab-styles.gemspec +5 -4
  9. data/lib/gitlab/styles/rubocop.rb +5 -0
  10. data/lib/gitlab/styles/rubocop/cop/active_record_dependent.rb +1 -1
  11. data/lib/gitlab/styles/rubocop/cop/code_reuse/active_record.rb +131 -0
  12. data/lib/gitlab/styles/rubocop/cop/custom_error_class.rb +6 -3
  13. data/lib/gitlab/styles/rubocop/cop/gem_fetcher.rb +1 -1
  14. data/lib/gitlab/styles/rubocop/cop/line_break_after_guard_clauses.rb +1 -1
  15. data/lib/gitlab/styles/rubocop/cop/line_break_around_conditional_block.rb +132 -0
  16. data/lib/gitlab/styles/rubocop/cop/migration/update_large_table.rb +64 -0
  17. data/lib/gitlab/styles/rubocop/cop/polymorphic_associations.rb +1 -1
  18. data/lib/gitlab/styles/rubocop/cop/rspec/base.rb +18 -0
  19. data/lib/gitlab/styles/rubocop/cop/rspec/empty_line_after_let_block.rb +65 -0
  20. data/lib/gitlab/styles/rubocop/cop/rspec/empty_line_after_shared_example.rb +65 -0
  21. data/lib/gitlab/styles/rubocop/cop/rspec/have_link_parameters.rb +10 -5
  22. data/lib/gitlab/styles/rubocop/cop/rspec/single_line_hook.rb +3 -2
  23. data/lib/gitlab/styles/rubocop/cop/rspec/verbose_include_metadata.rb +10 -13
  24. data/lib/gitlab/styles/rubocop/model_helpers.rb +1 -1
  25. data/lib/gitlab/styles/rubocop/rspec/helpers.rb +17 -0
  26. data/lib/gitlab/styles/version.rb +1 -1
  27. data/rubocop-all.yml +1 -0
  28. data/rubocop-bundler.yml +1 -0
  29. data/rubocop-code_reuse.yml +24 -0
  30. data/rubocop-default.yml +2 -0
  31. data/rubocop-gemspec.yml +1 -0
  32. data/rubocop-layout.yml +6 -0
  33. data/rubocop-lint.yml +63 -5
  34. data/rubocop-metrics.yml +1 -0
  35. data/rubocop-migrations.yml +22 -0
  36. data/rubocop-naming.yml +1 -0
  37. data/rubocop-performance.yml +48 -0
  38. data/rubocop-rails.yml +79 -0
  39. data/rubocop-rspec.yml +14 -0
  40. data/rubocop-security.yml +1 -0
  41. data/rubocop-style.yml +90 -1
  42. metadata +26 -17
  43. data/.rubocop_todo.yml +0 -7
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../../migration_helpers'
3
+
4
+ module Gitlab
5
+ module Styles
6
+ module Rubocop
7
+ module Cop
8
+ module Migration
9
+ # This cop checks for methods that may lead to batch type issues on a table that's been
10
+ # explicitly denied because of its size.
11
+ #
12
+ # Even though though these methods perform functions to avoid
13
+ # downtime, using it with tables with millions of rows still causes a
14
+ # significant delay in the deploy process and is best avoided.
15
+ #
16
+ # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more
17
+ # information.
18
+ class UpdateLargeTable < RuboCop::Cop::Cop
19
+ include MigrationHelpers
20
+
21
+ MSG = 'Using `%s` on the `%s` table will take a long time to ' \
22
+ 'complete, and should be avoided unless absolutely ' \
23
+ 'necessary'
24
+
25
+ def_node_matcher :batch_update?, <<~PATTERN
26
+ (send nil? ${#denied_method?}
27
+ (sym $...)
28
+ ...)
29
+ PATTERN
30
+
31
+ def on_send(node)
32
+ return if denied_tables.empty? || denied_methods.empty?
33
+ return unless in_migration?(node)
34
+
35
+ matches = batch_update?(node)
36
+ return unless matches
37
+
38
+ update_method = matches.first
39
+ table = matches.last.to_a.first
40
+
41
+ return unless denied_tables.include?(table)
42
+
43
+ add_offense(node, message: format(MSG, update_method, table))
44
+ end
45
+
46
+ private
47
+
48
+ def denied_tables
49
+ cop_config['DeniedTables'] || []
50
+ end
51
+
52
+ def denied_method?(method_name)
53
+ denied_methods.include?(method_name)
54
+ end
55
+
56
+ def denied_methods
57
+ cop_config['DeniedMethods'] || []
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -19,7 +19,7 @@ module Gitlab
19
19
  node.children.last.each_node(:pair) do |pair|
20
20
  key_name = pair.children[0].children[0]
21
21
 
22
- add_offense(pair, location: :expression) if key_name == :polymorphic
22
+ add_offense(pair) if key_name == :polymorphic
23
23
  end
24
24
  end
25
25
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop-rspec'
4
+ require_relative '../../rspec/helpers'
5
+
6
+ module Gitlab
7
+ module Styles
8
+ module Rubocop
9
+ module Cop
10
+ module RSpec
11
+ class Base < RuboCop::Cop::RSpec::Base
12
+ include Rubocop::Rspec::Helpers
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop-rspec'
4
+ require_relative 'base'
5
+
6
+ module Gitlab
7
+ module Styles
8
+ module Rubocop
9
+ module Cop
10
+ module RSpec
11
+ # Checks if there is an empty line after let blocks.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # RSpec.describe Foo do
16
+ # let(:something) { 'something' }
17
+ # let(:another_thing) do
18
+ # end
19
+ # let(:something_else) do
20
+ # end
21
+ # let(:last_thing) { 'last thing' }
22
+ # end
23
+ #
24
+ # # good
25
+ # RSpec.describe Foo do
26
+ # let(:something) { 'something' }
27
+ # let(:another_thing) do
28
+ # end
29
+ #
30
+ # let(:something_else) do
31
+ # end
32
+ #
33
+ # let(:last_thing) { 'last thing' }
34
+ # end
35
+ #
36
+ # # good - it's ok to have non-separated without do/end blocks
37
+ # RSpec.describe Foo do
38
+ # let(:something) { 'something' }
39
+ # let(:last_thing) { 'last thing' }
40
+ # end
41
+ #
42
+ class EmptyLineAfterLetBlock < Base
43
+ extend RuboCop::Cop::AutoCorrector
44
+ include RuboCop::RSpec::EmptyLineSeparation
45
+
46
+ MSG = 'Add an empty line after `%<let>s` block.'
47
+
48
+ def_node_matcher :lets, LET.block_pattern
49
+
50
+ def on_block(node)
51
+ lets(node) do
52
+ break if last_child?(node)
53
+ next if node.single_line?
54
+
55
+ missing_separating_line_offense(node) do |method|
56
+ format(MSG, let: method)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop-rspec'
4
+ require_relative 'base'
5
+
6
+ module Gitlab
7
+ module Styles
8
+ module Rubocop
9
+ module Cop
10
+ module RSpec
11
+ # Checks if there is an empty line after shared example blocks.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # RSpec.describe Foo do
16
+ # it_behaves_like 'do this first'
17
+ # it_behaves_like 'does this' do
18
+ # end
19
+ # it_behaves_like 'does that' do
20
+ # end
21
+ # it_behaves_like 'do some more'
22
+ # end
23
+ #
24
+ # # good
25
+ # RSpec.describe Foo do
26
+ # it_behaves_like 'do this first'
27
+ # it_behaves_like 'does this' do
28
+ # end
29
+ #
30
+ # it_behaves_like 'does that' do
31
+ # end
32
+ #
33
+ # it_behaves_like 'do some more'
34
+ # end
35
+ #
36
+ # # fair - it's ok to have non-separated without blocks
37
+ # RSpec.describe Foo do
38
+ # it_behaves_like 'do this first'
39
+ # it_behaves_like 'does this'
40
+ # end
41
+ #
42
+ class EmptyLineAfterSharedExample < Base
43
+ extend RuboCop::Cop::AutoCorrector
44
+ include RuboCop::RSpec::EmptyLineSeparation
45
+
46
+ MSG = 'Add an empty line after `%<example>s` block.'
47
+
48
+ def_node_matcher :shared_examples,
49
+ (SharedGroups::ALL + Includes::ALL).block_pattern
50
+
51
+ def on_block(node)
52
+ shared_examples(node) do
53
+ break if last_child?(node)
54
+
55
+ missing_separating_line_offense(node) do |method|
56
+ format(MSG, example: method)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop-rspec'
4
+ require_relative 'base'
4
5
 
5
6
  module Gitlab
6
7
  module Styles
@@ -17,7 +18,9 @@ module Gitlab
17
18
  # # good
18
19
  # expect(page).to have_link('Link', href: 'https://example.com')
19
20
  # expect(page).to have_link('Example')
20
- class HaveLinkParameters < RuboCop::Cop::RSpec::Cop
21
+ class HaveLinkParameters < Base
22
+ extend RuboCop::Cop::AutoCorrector
23
+
21
24
  MESSAGE = "The second argument to `have_link` should be a Hash."
22
25
 
23
26
  def_node_matcher :unused_parameters?, <<~PATTERN
@@ -29,11 +32,13 @@ module Gitlab
29
32
  def on_send(node)
30
33
  return unless unused_parameters?(node)
31
34
 
32
- location = node.arguments[1..-1]
33
- .map(&:source_range)
34
- .reduce(:join)
35
+ location = node.arguments[1..]
36
+ .map(&:source_range)
37
+ .reduce(:join)
35
38
 
36
- add_offense(node, location: location, message: MESSAGE)
39
+ add_offense(location, message: MESSAGE) do |corrector|
40
+ corrector.insert_after(location.end, "\n")
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop-rspec'
4
+ require_relative 'base'
4
5
 
5
6
  module Gitlab
6
7
  module Styles
@@ -23,7 +24,7 @@ module Gitlab
23
24
  # after(:each) do
24
25
  # undo_something
25
26
  # end
26
- class SingleLineHook < RuboCop::Cop::RSpec::Cop
27
+ class SingleLineHook < Base
27
28
  MESSAGE = "Don't use single-line hook blocks."
28
29
 
29
30
  def_node_search :rspec_hook?, <<~PATTERN
@@ -34,7 +35,7 @@ module Gitlab
34
35
  return unless node.single_line?
35
36
  return unless rspec_hook?(node)
36
37
 
37
- add_offense(node, location: :expression, message: MESSAGE)
38
+ add_offense(node, message: MESSAGE)
38
39
  end
39
40
  end
40
41
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop-rspec'
4
+ require_relative 'base'
4
5
 
5
6
  module Gitlab
6
7
  module Styles
@@ -17,7 +18,9 @@ module Gitlab
17
18
  # # good
18
19
  # describe MyClass, :js do
19
20
  # end
20
- class VerboseIncludeMetadata < RuboCop::Cop::RSpec::Cop
21
+ class VerboseIncludeMetadata < Base
22
+ extend RuboCop::Cop::AutoCorrector
23
+
21
24
  MSG = 'Use `%s` instead of `%s`.'
22
25
 
23
26
  SELECTORS = %i[describe context feature example_group it specify example scenario its].freeze
@@ -37,25 +40,19 @@ module Gitlab
37
40
 
38
41
  def on_send(node)
39
42
  invalid_metadata_matches(node) do |match|
40
- add_offense(node, location: :expression, message: format(MSG, good(match), bad(match)))
41
- end
42
- end
43
-
44
- def autocorrect(node)
45
- lambda do |corrector|
46
- invalid_metadata_matches(node) do |match|
47
- corrector.replace(match.loc.expression, good(match))
43
+ add_offense(node, message: format(MSG, good(match), bad(match))) do |corrector|
44
+ invalid_metadata_matches(node) do |match|
45
+ corrector.replace(match.loc.expression, good(match))
46
+ end
48
47
  end
49
48
  end
50
49
  end
51
50
 
52
51
  private
53
52
 
54
- def invalid_metadata_matches(node)
53
+ def invalid_metadata_matches(node, &block)
55
54
  include_metadata(node) do |matches|
56
- matches.select(&method(:invalid_metadata?)).each do |match|
57
- yield match
58
- end
55
+ matches.select(&method(:invalid_metadata?)).each(&block)
59
56
  end
60
57
  end
61
58
 
@@ -7,7 +7,7 @@ module Gitlab
7
7
  # Returns true if the given node originated from the models directory.
8
8
  def in_model?(node)
9
9
  path = node.location.expression.source_buffer.name
10
- pwd = RuboCop::PathUtil.pwd
10
+ pwd = Dir.pwd
11
11
  models_path = File.join(pwd, 'app', 'models')
12
12
  ee_models_path = File.join(pwd, 'ee', 'app', 'models')
13
13
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop-rspec'
4
+
5
+ module Gitlab
6
+ module Styles
7
+ module Rubocop
8
+ module Rspec
9
+ module Helpers
10
+ include RuboCop::RSpec::Language
11
+
12
+ LET = SelectorSet.new(%i[let_it_be]) + RuboCop::RSpec::Language::Helpers::ALL
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module Styles
5
- VERSION = '4.0.0'
5
+ VERSION = '5.1.0'
6
6
  end
7
7
  end
@@ -1,3 +1,4 @@
1
+ ---
1
2
  AllCops:
2
3
  TargetRubyVersion: 2.6
3
4
  # Cop names are not displayed in offense messages by default. Change behavior
@@ -1,3 +1,4 @@
1
+ ---
1
2
  # Gems in consecutive lines should be alphabetically sorted
2
3
  Bundler/OrderedGems:
3
4
  Enabled: false
@@ -0,0 +1,24 @@
1
+ # Denies the use of ActiveRecord methods outside of configured
2
+ # excluded directories
3
+ # Directories that allow the use of the denied methods.
4
+ # To start we provide a default configuration that matches
5
+ # a standard Rails app and enable.
6
+ # The default configuration can be overridden by
7
+ # providing your own Exclusion list as follows:
8
+ # CodeReuse/ActiveRecord:
9
+ # Enabled: true
10
+ # Exclude:
11
+ # - app/models/**/*.rb
12
+ # - config/**/*.rb
13
+ # - db/**/*.rb
14
+ # - lib/tasks/**/*.rb
15
+ # - spec/**/*.rb
16
+ # - lib/gitlab/**/*.rb
17
+ CodeReuse/ActiveRecord:
18
+ Enabled: true
19
+ Exclude:
20
+ - app/models/**/*.rb
21
+ - config/**/*.rb
22
+ - db/**/*.rb
23
+ - lib/tasks/**/*.rb
24
+ - spec/**/*.rb
@@ -1,3 +1,4 @@
1
+ ---
1
2
  require:
2
3
  - rubocop-gitlab-security
3
4
  - rubocop-performance
@@ -12,6 +13,7 @@ inherit_from:
12
13
  - rubocop-layout.yml
13
14
  - rubocop-lint.yml
14
15
  - rubocop-metrics.yml
16
+ - rubocop-migrations.yml
15
17
  - rubocop-naming.yml
16
18
  - rubocop-performance.yml
17
19
  - rubocop-rails.yml
@@ -1,3 +1,4 @@
1
+ ---
1
2
  # Dependencies in the gemspec should be alphabetically sorted
2
3
  # Configuration parameters: Include, TreatCommentsAsGroupSeparators.
3
4
  Gemspec/OrderedDependencies:
@@ -1,3 +1,4 @@
1
+ ---
1
2
  # Check indentation of private/protected visibility modifiers.
2
3
  Layout/AccessModifierIndentation:
3
4
  Enabled: true
@@ -60,6 +61,11 @@ Layout/EmptyLines:
60
61
  Layout/EmptyLinesAroundAccessModifier:
61
62
  Enabled: true
62
63
 
64
+ # Checks for a newline after an attribute accessor or a group of them
65
+ # https://docs.rubocop.org/rubocop/0.89/cops_layout.html#layoutemptylinesaroundattributeaccessor
66
+ Layout/EmptyLinesAroundAttributeAccessor:
67
+ Enabled: true
68
+
63
69
  # Keeps track of empty lines around block bodies.
64
70
  Layout/EmptyLinesAroundBlockBody:
65
71
  Enabled: true