gitlab-styles 8.0.0 → 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +7 -1
  3. data/.rubocop.yml +11 -0
  4. data/Gemfile +7 -3
  5. data/README.md +25 -5
  6. data/bin/console +1 -0
  7. data/gitlab-styles.gemspec +6 -6
  8. data/lefthook.yml +16 -0
  9. data/lib/gitlab/styles/version.rb +1 -1
  10. data/lib/rubocop/cop/active_record_dependent.rb +2 -2
  11. data/lib/rubocop/cop/active_record_serialize.rb +2 -2
  12. data/lib/rubocop/cop/avoid_return_from_blocks.rb +3 -1
  13. data/lib/rubocop/cop/code_reuse/active_record.rb +3 -3
  14. data/lib/rubocop/cop/custom_error_class.rb +8 -10
  15. data/lib/rubocop/cop/gem_fetcher.rb +3 -3
  16. data/lib/rubocop/cop/in_batches.rb +2 -2
  17. data/lib/rubocop/cop/internal_affairs/deprecate_cop_helper.rb +4 -1
  18. data/lib/rubocop/cop/line_break_after_guard_clauses.rb +2 -1
  19. data/lib/rubocop/cop/line_break_around_conditional_block.rb +6 -7
  20. data/lib/rubocop/cop/migration/update_large_table.rb +5 -4
  21. data/lib/rubocop/cop/performance/rubyzip.rb +3 -2
  22. data/lib/rubocop/cop/polymorphic_associations.rb +1 -1
  23. data/lib/rubocop/cop/rails/include_url_helper.rb +2 -1
  24. data/lib/rubocop/cop/redirect_with_status.rb +3 -3
  25. data/lib/rubocop/cop/rspec/base.rb +0 -2
  26. data/lib/rubocop/cop/rspec/empty_line_after_let_block.rb +7 -7
  27. data/lib/rubocop/cop/rspec/empty_line_after_shared_example.rb +4 -2
  28. data/lib/rubocop/cop/rspec/example_starting_character.rb +2 -0
  29. data/lib/rubocop/cop/rspec/have_link_parameters.rb +2 -1
  30. data/lib/rubocop/cop/rspec/single_line_hook.rb +3 -1
  31. data/lib/rubocop/cop/rspec/verbose_include_metadata.rb +2 -0
  32. data/lib/rubocop/cop/style/hash_transformation.rb +10 -12
  33. data/lib/rubocop/cop/style/open_struct_use.rb +3 -2
  34. data/lib/rubocop/cop/without_reactive_cache.rb +2 -2
  35. data/rubocop-layout.yml +1 -1
  36. data/rubocop-rspec.yml +27 -5
  37. data/rubocop-security.yml +4 -0
  38. metadata +13 -20
  39. data/lib/gitlab/styles/rubocop/rspec/helpers.rb +0 -18
  40. data/lib/rubocop/cop/rspec/empty_line_after_final_let_it_be.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b56e4d8be26ddd4c64b078c7ba35ee9cde92ee9aa8510303fc8e56f55d76b4c
4
- data.tar.gz: 9e3aae79876619f3f189ad51133ad0e5b6c9f2b50a9d08fcaa1d37275bfe4ccc
3
+ metadata.gz: 50eab9da6dd93cfbda3c8a8877e6ac2f8ce8274d6f92116973e6c9c1ee590d5f
4
+ data.tar.gz: f7e187d901c89bb4d4ba4a40d72523b10c5148ef965d60b243e8c09c9bc21642
5
5
  SHA512:
6
- metadata.gz: 7bf2ad47042480c6e187b5643c963e8e2560c8f7d38ed9431308902b0074aca0a52f740790fc2cd82e59611e50156b7dc18d89a562b17c1c8cce2c1db3ebe50b
7
- data.tar.gz: b97431178490c4344cf1eaec23c1bf2596b7e44a2a8182ea2295add370e7e0c67da6bfa5fc4b213540306a681534e62272736669549e2949168b09bc4b1ddf8d
6
+ metadata.gz: a9d90f34b3a3e6d97c6a791c5f91a26318b956751a77b2827f5370e15f8717bdf30cf30ddad0c63afd1f2335707d76dd948d1c7898c0d762f9b19389dea55d49
7
+ data.tar.gz: 9634b21fcc052557e12ebd277279089e4cfd325b88860c45a5250da554b0f14e378b7cdf8c9648d019649cd1396b327fc7cf10d48462622f00f1af888cd61b31
data/.gitlab-ci.yml CHANGED
@@ -3,7 +3,7 @@ stages:
3
3
  - deploy
4
4
 
5
5
  default:
6
- image: ruby:2.7
6
+ image: "ruby:${RUBY_VERSION}"
7
7
  tags:
8
8
  - gitlab-org
9
9
  before_script:
@@ -23,11 +23,17 @@ styles:
23
23
  stage: test
24
24
  script:
25
25
  - bundle exec rubocop --debug --parallel
26
+ parallel:
27
+ matrix:
28
+ - RUBY_VERSION: ['2.7', '3.0']
26
29
 
27
30
  specs:
28
31
  stage: test
29
32
  script:
30
33
  - bundle exec rspec
34
+ parallel:
35
+ matrix:
36
+ - RUBY_VERSION: ['2.7', '3.0']
31
37
 
32
38
  include:
33
39
  - project: 'gitlab-org/quality/pipeline-common'
data/.rubocop.yml CHANGED
@@ -4,7 +4,18 @@ inherit_from:
4
4
  require:
5
5
  - rubocop/cop/internal_affairs
6
6
 
7
+ AllCops:
8
+ NewCops: disable # https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/issues/40
9
+ SuggestExtensions: false # https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/issues/39
10
+
7
11
  InternalAffairs/DeprecateCopHelper:
8
12
  Enabled: true
9
13
  Include:
10
14
  - spec/**/*.rb
15
+
16
+ # This only makes sense for cops that are included with RuboCop. We could add
17
+ # our own config/default.yml and do something like
18
+ # https://github.com/rubocop/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb,
19
+ # but realistically this is OK here.
20
+ InternalAffairs/UndefinedConfig:
21
+ Enabled: false
data/Gemfile CHANGED
@@ -5,9 +5,13 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in gitlab-rubocop.gemspec
6
6
  gemspec
7
7
 
8
+ group :development do
9
+ gem "lefthook", require: false
10
+ end
11
+
8
12
  group :test do
9
13
  # Pin these dependencies, otherwise a new rule could break the CI pipelines
10
- gem 'rubocop', '0.91.1'
11
- gem 'rubocop-rspec', '1.44.1'
12
- gem 'rspec-parameterized', '0.4.2', require: false
14
+ gem 'rubocop', '1.38.0'
15
+ gem 'rubocop-rspec', '2.15.0'
16
+ gem 'rspec-parameterized', '0.5.2', require: false
13
17
  end
data/README.md CHANGED
@@ -66,10 +66,19 @@ After checking out the repo, run `bin/setup` to install dependencies.
66
66
  Then, run `rake spec` to run the tests. You can also run `bin/console` for an
67
67
  interactive prompt that will allow you to experiment.
68
68
 
69
- To install this gem onto your local machine, run `bundle exec rake install`. To
70
- release a new version, update the version number in `version.rb`, and then run
71
- `bundle exec rake release`, which will create a git tag for the version, push
72
- git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
69
+ To test some rules locally, there is a test application [in the playground folder](./playground/). It is a vanilla Rails 6 application with your local `gitlab-styles` included, and it is used to test RuboCop rules. You can add code in it (preferably RuboCop offenses) and run the following command to test the RuboCop policy we setup:
70
+
71
+ ```shell
72
+ cd playground
73
+ bundle install
74
+ bundle exec rubocop -c .rubocop.yml
75
+ ```
76
+
77
+ ### Activate lefthook locally
78
+
79
+ ```shell
80
+ lefthook install
81
+ ```
73
82
 
74
83
  ## Contributing
75
84
 
@@ -80,7 +89,18 @@ to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
80
89
 
81
90
  ## Release Process
82
91
 
83
- Please refer to the [Release Process](docs/release_process.md).
92
+ We release `gitlab-styles` on an ad-hoc basis. There is no regularity to when
93
+ we release, we just release when we make a change - no matter the size of the
94
+ change.
95
+
96
+ To release a new version:
97
+
98
+ 1. Create a Merge Request.
99
+ 1. Use Merge Request template [Release.md](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/blob/master/.gitlab/merge_request_templates/Release.md).
100
+ 1. Follow the instructions.
101
+ 1. A new gem version is [published automatically](https://gitlab.com/gitlab-org/quality/pipeline-common/-/blob/master/ci/gem-release.yml) after the Merge Request has been merged.
102
+
103
+ See [!123](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/merge_requests/123) as an example.
84
104
 
85
105
  ## License
86
106
 
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "bundler/setup"
4
5
  require "gitlab/styles"
@@ -16,18 +16,18 @@ Gem::Specification.new do |spec|
16
16
  spec.license = 'MIT'
17
17
 
18
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
- f.match(%r{^(docs|test|spec|features)/})
19
+ f.match(%r{^(docs|test|spec|features|playground)/})
20
20
  end
21
21
  spec.bindir = 'exe'
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
- spec.add_dependency 'rubocop', '~> 0.91', '>= 0.91.1'
25
+ spec.add_dependency 'rubocop', '~> 1.38.0'
26
26
  spec.add_dependency 'rubocop-gitlab-security', '~> 0.1.1'
27
- spec.add_dependency 'rubocop-graphql', '~> 0.10'
28
- spec.add_dependency 'rubocop-performance', '~> 1.9.2'
29
- spec.add_dependency 'rubocop-rails', '~> 2.9'
30
- spec.add_dependency 'rubocop-rspec', '~> 1.44'
27
+ spec.add_dependency 'rubocop-graphql', '~> 0.14'
28
+ spec.add_dependency 'rubocop-performance', '~> 1.14'
29
+ spec.add_dependency 'rubocop-rails', '~> 2.15'
30
+ spec.add_dependency 'rubocop-rspec', '~> 2.15'
31
31
 
32
32
  spec.add_development_dependency 'bundler', '~> 2.1'
33
33
  spec.add_development_dependency 'gitlab-dangerfiles', '~> 2.11.0'
data/lefthook.yml ADDED
@@ -0,0 +1,16 @@
1
+ # Lefthook configuration. For more information, see:
2
+ # https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md
3
+
4
+ pre-push:
5
+ parallel: true
6
+ commands:
7
+ # Run ruby linting
8
+ rubocop:
9
+ files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
10
+ glob: '*.{rb,rake}'
11
+ run: bundle exec rubocop --parallel --force-exclusion {files}
12
+
13
+ # Run all tests (warn if there are any missing tools required for tests).
14
+ rspec:
15
+ run: bundle exec rspec -f progress
16
+ glob: '*.rb'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module Styles
5
- VERSION = '8.0.0'
5
+ VERSION = '9.1.0'
6
6
  end
7
7
  end
@@ -5,11 +5,11 @@ require_relative '../../gitlab/styles/rubocop/model_helpers'
5
5
  module Rubocop
6
6
  module Cop
7
7
  # Cop that prevents the use of `dependent: ...` in ActiveRecord models.
8
- class ActiveRecordDependent < RuboCop::Cop::Cop
8
+ class ActiveRecordDependent < RuboCop::Cop::Base
9
9
  include Gitlab::Styles::Rubocop::ModelHelpers
10
10
 
11
11
  MSG = 'Do not use `dependent:` to remove associated data, ' \
12
- 'use foreign keys with cascading deletes instead.'
12
+ 'use foreign keys with cascading deletes instead.'
13
13
 
14
14
  METHOD_NAMES = [:has_many, :has_one, :belongs_to].freeze
15
15
  ALLOWED_OPTIONS = [:restrict_with_error].freeze
@@ -5,7 +5,7 @@ require_relative '../../gitlab/styles/rubocop/model_helpers'
5
5
  module Rubocop
6
6
  module Cop
7
7
  # Cop that prevents the use of `serialize` in ActiveRecord models.
8
- class ActiveRecordSerialize < RuboCop::Cop::Cop
8
+ class ActiveRecordSerialize < RuboCop::Cop::Base
9
9
  include Gitlab::Styles::Rubocop::ModelHelpers
10
10
 
11
11
  MSG = 'Do not store serialized data in the database, use separate columns and/or tables instead'
@@ -13,7 +13,7 @@ module Rubocop
13
13
  def on_send(node)
14
14
  return unless in_model?(node)
15
15
 
16
- add_offense(node, location: :selector) if node.children[1] == :serialize
16
+ add_offense(node.loc.selector) if node.children[1] == :serialize
17
17
  end
18
18
  end
19
19
  end
@@ -20,7 +20,7 @@ module Rubocop
20
20
  # do_something_else
21
21
  # end
22
22
  #
23
- class AvoidReturnFromBlocks < RuboCop::Cop::Cop
23
+ class AvoidReturnFromBlocks < RuboCop::Cop::Base
24
24
  MSG = 'Do not return from a block, use next or break instead.'
25
25
  DEF_METHODS = %i[define_method lambda].freeze
26
26
  WHITELISTED_METHODS = %i[each each_filename times loop].freeze
@@ -38,6 +38,8 @@ module Rubocop
38
38
  end
39
39
  end
40
40
 
41
+ alias_method :on_numblock, :on_block
42
+
41
43
  private
42
44
 
43
45
  def top_block?(node)
@@ -4,9 +4,9 @@ module Rubocop
4
4
  module Cop
5
5
  module CodeReuse
6
6
  # Cop that denies the use of ActiveRecord methods outside of models.
7
- class ActiveRecord < RuboCop::Cop::Cop
7
+ class ActiveRecord < RuboCop::Cop::Base
8
8
  MSG = 'This method can only be used inside an ActiveRecord model: ' \
9
- 'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
9
+ 'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
10
10
 
11
11
  # Various methods from ActiveRecord::Querying that are denied. We
12
12
  # exclude some generic ones such as `any?` and `first`, as these may
@@ -72,7 +72,7 @@ module Rubocop
72
72
  # `Project.group(:name)`.
73
73
  return if NOT_ALLOWED[send_name] && !first_arg
74
74
 
75
- add_offense(node, location: :selector)
75
+ add_offense(node.loc.selector)
76
76
  end
77
77
  end
78
78
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- # This cop makes sure that custom error classes, when empty, are declared
5
+ # Makes sure that custom error classes, when empty, are declared
6
6
  # with Class.new.
7
7
  #
8
8
  # @example
@@ -15,7 +15,9 @@ module Rubocop
15
15
  #
16
16
  # # good
17
17
  # FooError = Class.new(StandardError)
18
- class CustomErrorClass < RuboCop::Cop::Cop
18
+ class CustomErrorClass < RuboCop::Cop::Base
19
+ extend RuboCop::Cop::AutoCorrector
20
+
19
21
  MSG = 'Use `Class.new(SuperClass)` to define an empty custom error class.'
20
22
 
21
23
  def on_class(node)
@@ -28,16 +30,12 @@ module Rubocop
28
30
 
29
31
  return unless parent_klass&.to_s&.end_with?('Error')
30
32
 
31
- add_offense(node)
32
- end
33
-
34
- def autocorrect(node)
35
- klass = node.identifier
36
- parent = node.parent_class
33
+ add_offense(node) do |corrector|
34
+ klass = node.identifier
35
+ parent = node.parent_class
37
36
 
38
- replacement = "#{class_name_from_node(klass)} = Class.new(#{class_name_from_node(parent)})"
37
+ replacement = "#{class_name_from_node(klass)} = Class.new(#{class_name_from_node(parent)})"
39
38
 
40
- lambda do |corrector|
41
39
  corrector.replace(node.source_range, replacement)
42
40
  end
43
41
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- # This cop prevents usage of the `git` and `github` arguments to `gem` in a
5
+ # Prevents usage of the `git` and `github` arguments to `gem` in a
6
6
  # `Gemfile` in order to avoid additional points of failure beyond
7
7
  # rubygems.org.
8
- class GemFetcher < RuboCop::Cop::Cop
8
+ class GemFetcher < RuboCop::Cop::Base
9
9
  MSG = 'Do not use gems from git repositories, only use gems from RubyGems.'
10
10
 
11
11
  GIT_KEYS = [:git, :github].freeze
@@ -18,7 +18,7 @@ module Rubocop
18
18
 
19
19
  node.children.last.each_node(:pair) do |pair|
20
20
  key_name = pair.children[0].children[0].to_sym
21
- add_offense(node, location: pair.source_range) if GIT_KEYS.include?(key_name)
21
+ add_offense(pair.source_range) if GIT_KEYS.include?(key_name)
22
22
  end
23
23
  end
24
24
 
@@ -5,13 +5,13 @@ require_relative '../../gitlab/styles/rubocop/model_helpers'
5
5
  module Rubocop
6
6
  module Cop
7
7
  # Cop that prevents the use of `in_batches`
8
- class InBatches < RuboCop::Cop::Cop
8
+ class InBatches < RuboCop::Cop::Base
9
9
  MSG = 'Do not use `in_batches`, use `each_batch` from the EachBatch module instead'
10
10
 
11
11
  def on_send(node)
12
12
  return unless node.children[1] == :in_batches
13
13
 
14
- add_offense(node, location: :selector)
14
+ add_offense(node.loc.selector)
15
15
  end
16
16
  end
17
17
  end
@@ -4,18 +4,21 @@ module Rubocop
4
4
  module Cop
5
5
  module InternalAffairs
6
6
  # Cop that denies the use of CopHelper.
7
- class DeprecateCopHelper < RuboCop::Cop::Cop
7
+ class DeprecateCopHelper < RuboCop::Cop::Base
8
8
  MSG = 'Do not use `CopHelper` or methods from it, use improved patterns described in https://www.rubydoc.info/gems/rubocop/RuboCop/RSpec/ExpectOffense'
9
9
 
10
+ # @!method cop_helper(node)
10
11
  def_node_matcher :cop_helper, <<~PATTERN
11
12
  (send nil? ${:include :extend :prepend}
12
13
  (const _ {:CopHelper}))
13
14
  PATTERN
14
15
 
16
+ # @!method cop_helper_method(node)
15
17
  def_node_search :cop_helper_method, <<~PATTERN
16
18
  (send nil? {:inspect_source :inspect_source_file :parse_source :autocorrect_source_file :autocorrect_source :_investigate} ...)
17
19
  PATTERN
18
20
 
21
+ # @!method cop_helper_method_on_instance(node)
19
22
  def_node_search :cop_helper_method_on_instance, <<~PATTERN
20
23
  (send (send nil? _) {:messages :highlights :offenses} ...)
21
24
  PATTERN
@@ -55,9 +55,10 @@ module Rubocop
55
55
  # end
56
56
  #
57
57
  # do_something_more
58
- class LineBreakAfterGuardClauses < RuboCop::Cop::Cop
58
+ class LineBreakAfterGuardClauses < RuboCop::Cop::Base
59
59
  MSG = 'Add a line break after guard clauses'
60
60
 
61
+ # @!method guard_clause_node?(node)
61
62
  def_node_matcher :guard_clause_node?, <<-PATTERN
62
63
  [{(send nil? {:raise :fail :throw} ...) return break next} single_line?]
63
64
  PATTERN
@@ -42,7 +42,8 @@ module Rubocop
42
42
  # do_something
43
43
  # end
44
44
  # end
45
- class LineBreakAroundConditionalBlock < RuboCop::Cop::Cop
45
+ class LineBreakAroundConditionalBlock < RuboCop::Cop::Base
46
+ extend RuboCop::Cop::AutoCorrector
46
47
  include RuboCop::Cop::RangeHelp
47
48
 
48
49
  MSG = 'Add a line break around conditional blocks'
@@ -53,17 +54,15 @@ module Rubocop
53
54
  return if node.single_line?
54
55
  return unless node.if? || node.unless?
55
56
 
56
- add_offense(node) unless previous_line_valid?(node)
57
- add_offense(node) unless last_line_valid?(node)
58
- end
59
-
60
- def autocorrect(node)
61
- lambda do |corrector|
57
+ corrector_block = lambda do |corrector|
62
58
  line = range_by_whole_lines(node.source_range)
63
59
 
64
60
  corrector.insert_before(line, "\n") unless previous_line_valid?(node)
65
61
  corrector.insert_after(line, "\n") unless last_line_valid?(node)
66
62
  end
63
+
64
+ add_offense(node, &corrector_block) unless previous_line_valid?(node)
65
+ add_offense(node, &corrector_block) unless last_line_valid?(node)
67
66
  end
68
67
 
69
68
  private
@@ -4,7 +4,7 @@ require_relative '../../../gitlab/styles/rubocop/migration_helpers'
4
4
  module Rubocop
5
5
  module Cop
6
6
  module Migration
7
- # This cop checks for methods that may lead to batch type issues on a table that's been
7
+ # Checks for methods that may lead to batch type issues on a table that's been
8
8
  # explicitly denied because of its size.
9
9
  #
10
10
  # Even though though these methods perform functions to avoid
@@ -13,13 +13,14 @@ module Rubocop
13
13
  #
14
14
  # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more
15
15
  # information.
16
- class UpdateLargeTable < RuboCop::Cop::Cop
16
+ class UpdateLargeTable < RuboCop::Cop::Base
17
17
  include Gitlab::Styles::Rubocop::MigrationHelpers
18
18
 
19
19
  MSG = 'Using `%s` on the `%s` table will take a long time to ' \
20
- 'complete, and should be avoided unless absolutely ' \
21
- 'necessary'
20
+ 'complete, and should be avoided unless absolutely ' \
21
+ 'necessary'
22
22
 
23
+ # @!method batch_update?(node)
23
24
  def_node_matcher :batch_update?, <<~PATTERN
24
25
  (send nil? ${#denied_method?}
25
26
  (sym $...)
@@ -3,7 +3,7 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Performance
6
- # This cop flags inefficient uses of rubyzip's Zip::File, since when instantiated
6
+ # Flags inefficient uses of rubyzip's Zip::File, since when instantiated
7
7
  # it reads the file's Central Directory into memory entirely. For zips with many
8
8
  # files and directories, this can be very expensive even when the archive's size
9
9
  # in bytes is small.
@@ -11,13 +11,14 @@ module Rubocop
11
11
  # See also:
12
12
  # - https://github.com/rubyzip/rubyzip/issues/506
13
13
  # - https://github.com/rubyzip/rubyzip#notes-on-zipinputstream
14
- class Rubyzip < RuboCop::Cop::Cop
14
+ class Rubyzip < RuboCop::Cop::Base
15
15
  MSG = 'Be careful when opening or iterating zip files via Zip::File. ' \
16
16
  'Zip archives may contain many entries, and their file index is ' \
17
17
  'read into memory upon construction, which can lead to ' \
18
18
  'high memory use and poor performance. ' \
19
19
  'Consider iterating archive entries via Zip::InputStream instead.'
20
20
 
21
+ # @!method reads_central_directory?(node)
21
22
  def_node_matcher :reads_central_directory?, <<-PATTERN
22
23
  (send
23
24
  (const
@@ -5,7 +5,7 @@ require_relative '../../gitlab/styles/rubocop/model_helpers'
5
5
  module Rubocop
6
6
  module Cop
7
7
  # Cop that prevents the use of polymorphic associations
8
- class PolymorphicAssociations < RuboCop::Cop::Cop
8
+ class PolymorphicAssociations < RuboCop::Cop::Base
9
9
  include Gitlab::Styles::Rubocop::ModelHelpers
10
10
 
11
11
  MSG = 'Do not use polymorphic associations, use separate tables instead'
@@ -5,7 +5,7 @@ require_relative '../../../gitlab/styles/rubocop/model_helpers'
5
5
  module Rubocop
6
6
  module Cop
7
7
  module Rails
8
- class IncludeUrlHelper < RuboCop::Cop::Cop
8
+ class IncludeUrlHelper < RuboCop::Cop::Base
9
9
  MSG = <<~MSG
10
10
  Avoid including `ActionView::Helpers::UrlHelper`.
11
11
  It adds/overrides ~40 methods while usually only one is needed.
@@ -14,6 +14,7 @@ module Rubocop
14
14
  See https://gitlab.com/gitlab-org/gitlab/-/issues/340567.
15
15
  MSG
16
16
 
17
+ # @!method include_url_helpers_node?(node)
17
18
  def_node_matcher :include_url_helpers_node?, <<~PATTERN
18
19
  (send nil? :include (const (const (const {nil? cbase} :ActionView) :Helpers) :UrlHelper))
19
20
  PATTERN
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Rubocop
4
4
  module Cop
5
- # This cop prevents usage of 'redirect_to' in actions 'destroy' without specifying 'status'.
5
+ # Prevents usage of 'redirect_to' in actions 'destroy' without specifying 'status'.
6
6
  # See https://gitlab.com/gitlab-org/gitlab-ce/issues/31840
7
- class RedirectWithStatus < RuboCop::Cop::Cop
7
+ class RedirectWithStatus < RuboCop::Cop::Base
8
8
  MSG = 'Do not use "redirect_to" without "status" in "destroy" action'
9
9
 
10
10
  def on_def(node)
@@ -20,7 +20,7 @@ module Rubocop
20
20
  methods << pair.children.first.children.first
21
21
  end
22
22
 
23
- add_offense(def_node, location: :selector) unless methods.include?(:status)
23
+ add_offense(def_node.loc.selector) unless methods.include?(:status)
24
24
  end
25
25
  end
26
26
 
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop-rspec'
4
- require_relative '../../../gitlab/styles/rubocop/rspec/helpers'
5
4
 
6
5
  module Rubocop
7
6
  module Cop
8
7
  module RSpec
9
8
  class Base < RuboCop::Cop::RSpec::Base
10
- include Gitlab::Styles::Rubocop::Rspec::Helpers
11
9
  end
12
10
  end
13
11
  end
@@ -39,22 +39,22 @@ module Rubocop
39
39
  #
40
40
  class EmptyLineAfterLetBlock < Base
41
41
  extend RuboCop::Cop::AutoCorrector
42
- include RuboCop::RSpec::EmptyLineSeparation
42
+ include RuboCop::Cop::RSpec::EmptyLineSeparation
43
43
 
44
44
  MSG = 'Add an empty line after `%<let>s` block.'
45
45
 
46
- def_node_matcher :lets, LET.block_pattern
47
-
48
46
  def on_block(node)
49
- lets(node) do
50
- break if last_child?(node)
51
- next if node.single_line?
47
+ RuboCop::RSpec::ExampleGroup.new(node).lets.each do |let|
48
+ break if last_child?(let)
49
+ next if let.single_line?
52
50
 
53
- missing_separating_line_offense(node) do |method|
51
+ missing_separating_line_offense(let) do |method|
52
+ format(MSG, let: method)
54
53
  format(MSG, let: method)
55
54
  end
56
55
  end
57
56
  end
57
+ alias_method :on_numblock, :on_block
58
58
  end
59
59
  end
60
60
  end
@@ -39,12 +39,13 @@ module Rubocop
39
39
  #
40
40
  class EmptyLineAfterSharedExample < Base
41
41
  extend RuboCop::Cop::AutoCorrector
42
- include RuboCop::RSpec::EmptyLineSeparation
42
+ include RuboCop::Cop::RSpec::EmptyLineSeparation
43
43
 
44
44
  MSG = 'Add an empty line after `%<example>s` block.'
45
45
 
46
+ # @!method shared_examples(node)
46
47
  def_node_matcher :shared_examples,
47
- (SharedGroups::ALL + Includes::ALL).block_pattern
48
+ block_pattern('{#SharedGroups.all #Includes.all}')
48
49
 
49
50
  def on_block(node)
50
51
  shared_examples(node) do
@@ -55,6 +56,7 @@ module Rubocop
55
56
  end
56
57
  end
57
58
  end
59
+ alias_method :on_numblock, :on_block
58
60
  end
59
61
  end
60
62
  end
@@ -52,6 +52,7 @@ module Rubocop
52
52
 
53
53
  MSG = 'Only start words with lowercase alpha with no leading/trailing spaces when describing your tests.'
54
54
 
55
+ # @!method it_description(node)
55
56
  def_node_matcher :it_description, <<-PATTERN
56
57
  (block (send _ :it ${
57
58
  (str $_)
@@ -64,6 +65,7 @@ module Rubocop
64
65
  add_wording_offense(description_node, MSG) if invalid_description?(text(description_node))
65
66
  end
66
67
  end
68
+ alias_method :on_numblock, :on_block
67
69
 
68
70
  private
69
71
 
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  module Rubocop
7
7
  module Cop
8
8
  module RSpec
9
- # This cop checks for unused parameters to the `have_link` matcher.
9
+ # Checks for unused parameters to the `have_link` matcher.
10
10
  #
11
11
  # @example
12
12
  #
@@ -21,6 +21,7 @@ module Rubocop
21
21
 
22
22
  MESSAGE = "The second argument to `have_link` should be a Hash."
23
23
 
24
+ # @!method unused_parameters?(node)
24
25
  def_node_matcher :unused_parameters?, <<~PATTERN
25
26
  (send nil? :have_link
26
27
  _ !{hash nil}
@@ -6,7 +6,7 @@ require_relative 'base'
6
6
  module Rubocop
7
7
  module Cop
8
8
  module RSpec
9
- # This cop checks for single-line hook blocks
9
+ # Checks for single-line hook blocks
10
10
  #
11
11
  # @example
12
12
  #
@@ -25,6 +25,7 @@ module Rubocop
25
25
  class SingleLineHook < Base
26
26
  MESSAGE = "Don't use single-line hook blocks."
27
27
 
28
+ # @!method rspec_hook?(node)
28
29
  def_node_search :rspec_hook?, <<~PATTERN
29
30
  (send nil? {:after :around :before} ...)
30
31
  PATTERN
@@ -35,6 +36,7 @@ module Rubocop
35
36
 
36
37
  add_offense(node, message: MESSAGE)
37
38
  end
39
+ alias_method :on_numblock, :on_block
38
40
  end
39
41
  end
40
42
  end
@@ -23,6 +23,7 @@ module Rubocop
23
23
 
24
24
  SELECTORS = %i[describe context feature example_group it specify example scenario its].freeze
25
25
 
26
+ # @!method include_metadata(node)
26
27
  def_node_matcher :include_metadata, <<-PATTERN
27
28
  (send {(const nil? :RSpec) nil?} {#{SELECTORS.map(&:inspect).join(' ')}}
28
29
  !const
@@ -30,6 +31,7 @@ module Rubocop
30
31
  (hash $...))
31
32
  PATTERN
32
33
 
34
+ # @!method invalid_metadata?(node)
33
35
  def_node_matcher :invalid_metadata?, <<-PATTERN
34
36
  (pair
35
37
  (sym $...)
@@ -3,7 +3,7 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Style
6
- # This cop identifies places where `map { ... }.to_h` or
6
+ # Identifies places where `map { ... }.to_h` or
7
7
  # `Hash[map { ... }]` can be replaced with `to_h { ... }`,
8
8
  # saving an intermediate array allocation.
9
9
  #
@@ -20,11 +20,13 @@ module Rubocop
20
20
  # array.to_h { |x| [x, x + 1] }
21
21
  #
22
22
  # Full credit: https://github.com/eugeneius/rubocop-performance/blob/hash_transformation/lib/rubocop/cop/performance/hash_transformation.rb
23
- class HashTransformation < RuboCop::Cop::Cop
23
+ class HashTransformation < RuboCop::Cop::Base
24
+ extend RuboCop::Cop::AutoCorrector
24
25
  include RuboCop::Cop::RangeHelp
25
26
 
26
27
  MSG = 'Use `to_h { ... }` instead of `%<current>s`.'
27
28
 
29
+ # @!method to_h_candidate?(node)
28
30
  def_node_matcher :to_h_candidate?, <<~PATTERN
29
31
  {
30
32
  [(send
@@ -38,17 +40,13 @@ module Rubocop
38
40
  to_h_candidate?(node) do |_block, call|
39
41
  range = offense_range(node, call)
40
42
  message = message(node, call)
41
- add_offense(node, location: range, message: message)
42
- end
43
- end
44
-
45
- def autocorrect(node)
46
- block, call = to_h_candidate?(node)
43
+ add_offense(range, message: message) do |corrector|
44
+ block, call = to_h_candidate?(node)
47
45
 
48
- lambda do |corrector|
49
- corrector.remove(after_block(node, block))
50
- corrector.replace(call.loc.selector, 'to_h')
51
- corrector.remove(before_block(node, block))
46
+ corrector.remove(after_block(node, block))
47
+ corrector.replace(call.loc.selector, 'to_h')
48
+ corrector.remove(before_block(node, block))
49
+ end
52
50
  end
53
51
  end
54
52
 
@@ -3,18 +3,19 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Style
6
- # This cop flags uses of OpenStruct, as it is now officially discouraged
6
+ # Flags uses of OpenStruct, as it is now officially discouraged
7
7
  # to be used for performance, version compatibility, and potential security issues.
8
8
  #
9
9
  # See also:
10
10
  # - https://rubyreferences.github.io/rubychanges/3.0.html#standard-library
11
11
  # - https://docs.ruby-lang.org/en/3.0.0/OpenStruct.html#class-OpenStruct-label-Caveats
12
12
  # - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67855
13
- class OpenStructUse < RuboCop::Cop::Cop
13
+ class OpenStructUse < RuboCop::Cop::Base
14
14
  MSG = 'Avoid using `OpenStruct`. It is officially discouraged. ' \
15
15
  'Replace it with `Struct`, `Hash`, or RSpec doubles. ' \
16
16
  'See https://docs.ruby-lang.org/en/3.0.0/OpenStruct.html#class-OpenStruct-label-Caveats'
17
17
 
18
+ # @!method uses_open_struct?(node)
18
19
  def_node_matcher :uses_open_struct?, <<-PATTERN
19
20
  (const {nil? (cbase)} :OpenStruct)
20
21
  PATTERN
@@ -3,13 +3,13 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  # Cop that prevents the use of `without_reactive_cache`
6
- class WithoutReactiveCache < RuboCop::Cop::Cop
6
+ class WithoutReactiveCache < RuboCop::Cop::Base
7
7
  MSG = 'without_reactive_cache is for debugging purposes only. Please use with_reactive_cache.'
8
8
 
9
9
  def on_send(node)
10
10
  return unless node.children[1] == :without_reactive_cache
11
11
 
12
- add_offense(node, location: :selector)
12
+ add_offense(node.loc.selector)
13
13
  end
14
14
  end
15
15
  end
data/rubocop-layout.yml CHANGED
@@ -135,7 +135,7 @@ Layout/LeadingCommentSpace:
135
135
  Layout/LineLength:
136
136
  Enabled: true
137
137
  Max: 120
138
- IgnoredPatterns: ['\s#\srubocop']
138
+ AllowedPatterns: ['\s#\srubocop']
139
139
 
140
140
  # Checks that the closing brace in an array literal is either on the same line
141
141
  # as the last array element, or a new line.
data/rubocop-rspec.yml CHANGED
@@ -14,6 +14,16 @@ RSpec/BeEql:
14
14
  RSpec/BeforeAfterAll:
15
15
  Enabled: false
16
16
 
17
+ # Checks if there is a more specific finder offered by Capybara.
18
+ # https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/merge_requests/131#note_1141024624
19
+ RSpec/Capybara/SpecificFinders:
20
+ Enabled: false
21
+
22
+ # Enforces consistent use of be_a or be_kind_of.
23
+ # https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/merge_requests/131#note_1141022718
24
+ RSpec/ClassCheck:
25
+ Enabled: false
26
+
17
27
  # Check that the first argument to the top level describe is the tested class or
18
28
  # module.
19
29
  RSpec/DescribeClass:
@@ -34,11 +44,6 @@ RSpec/DescribedClass:
34
44
  # Checks if an example group does not include any tests.
35
45
  RSpec/EmptyExampleGroup:
36
46
  Enabled: true
37
- CustomIncludeMethods:
38
- - run_permission_checks
39
- - run_group_permission_checks
40
- - it_should_email!
41
- - it_should_not_email!
42
47
 
43
48
  # Checks if there is an empty line after let blocks.
44
49
  RSpec/EmptyLineAfterLetBlock:
@@ -66,6 +71,12 @@ RSpec/ExampleWording:
66
71
  RSpec/ExpectActual:
67
72
  Enabled: true
68
73
 
74
+ # Checks for `expect {...}.to change {...}` using a block.
75
+ # See https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/merge_requests/122#note_1089192391
76
+ RSpec/ExpectChange:
77
+ Enabled: true
78
+ EnforcedStyle: block
79
+
69
80
  # Checks for opportunities to use `expect { … }.to output`.
70
81
  RSpec/ExpectOutput:
71
82
  Enabled: true
@@ -136,6 +147,10 @@ RSpec/NotToNot:
136
147
  EnforcedStyle: not_to
137
148
  Enabled: true
138
149
 
150
+ # See https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/merge_requests/122#note_1089202045
151
+ RSpec/PredicateMatcher:
152
+ Enabled: false
153
+
139
154
  # Check for repeated description strings in example groups.
140
155
  RSpec/RepeatedDescription:
141
156
  Enabled: false
@@ -159,3 +174,10 @@ RSpec/SubjectStub:
159
174
  # Prefer using verifying doubles over normal doubles.
160
175
  RSpec/VerifiedDoubles:
161
176
  Enabled: true
177
+
178
+ RSpec:
179
+ Language:
180
+ Helpers:
181
+ - let_it_be
182
+ - let_it_be_with_refind
183
+ - let_it_be_with_reload
data/rubocop-security.yml CHANGED
@@ -11,6 +11,10 @@ Security/JSONLoad:
11
11
  Security/Eval:
12
12
  Enabled: true
13
13
 
14
+ # Checks for the first argument to IO.read, IO.binread, IO.write, IO.binwrite, IO.foreach, and IO.readlines
15
+ Security/IoMethods:
16
+ Enabled: true
17
+
14
18
  GitlabSecurity/DeepMunge:
15
19
  Enabled: true
16
20
  Exclude:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-styles
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0
4
+ version: 9.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-02 00:00:00.000000000 Z
11
+ date: 2022-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -16,20 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.91'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 0.91.1
19
+ version: 1.38.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '0.91'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 0.91.1
26
+ version: 1.38.0
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: rubocop-gitlab-security
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -50,56 +44,56 @@ dependencies:
50
44
  requirements:
51
45
  - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: '0.10'
47
+ version: '0.14'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
51
  requirements:
58
52
  - - "~>"
59
53
  - !ruby/object:Gem::Version
60
- version: '0.10'
54
+ version: '0.14'
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: rubocop-performance
63
57
  requirement: !ruby/object:Gem::Requirement
64
58
  requirements:
65
59
  - - "~>"
66
60
  - !ruby/object:Gem::Version
67
- version: 1.9.2
61
+ version: '1.14'
68
62
  type: :runtime
69
63
  prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
66
  - - "~>"
73
67
  - !ruby/object:Gem::Version
74
- version: 1.9.2
68
+ version: '1.14'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: rubocop-rails
77
71
  requirement: !ruby/object:Gem::Requirement
78
72
  requirements:
79
73
  - - "~>"
80
74
  - !ruby/object:Gem::Version
81
- version: '2.9'
75
+ version: '2.15'
82
76
  type: :runtime
83
77
  prerelease: false
84
78
  version_requirements: !ruby/object:Gem::Requirement
85
79
  requirements:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
- version: '2.9'
82
+ version: '2.15'
89
83
  - !ruby/object:Gem::Dependency
90
84
  name: rubocop-rspec
91
85
  requirement: !ruby/object:Gem::Requirement
92
86
  requirements:
93
87
  - - "~>"
94
88
  - !ruby/object:Gem::Version
95
- version: '1.44'
89
+ version: '2.15'
96
90
  type: :runtime
97
91
  prerelease: false
98
92
  version_requirements: !ruby/object:Gem::Requirement
99
93
  requirements:
100
94
  - - "~>"
101
95
  - !ruby/object:Gem::Version
102
- version: '1.44'
96
+ version: '2.15'
103
97
  - !ruby/object:Gem::Dependency
104
98
  name: bundler
105
99
  requirement: !ruby/object:Gem::Requirement
@@ -181,12 +175,12 @@ files:
181
175
  - bin/console
182
176
  - bin/setup
183
177
  - gitlab-styles.gemspec
178
+ - lefthook.yml
184
179
  - lib/gitlab/styles.rb
185
180
  - lib/gitlab/styles/common/banned_constants.rb
186
181
  - lib/gitlab/styles/rubocop.rb
187
182
  - lib/gitlab/styles/rubocop/migration_helpers.rb
188
183
  - lib/gitlab/styles/rubocop/model_helpers.rb
189
- - lib/gitlab/styles/rubocop/rspec/helpers.rb
190
184
  - lib/gitlab/styles/version.rb
191
185
  - lib/rubocop/cop/active_record_dependent.rb
192
186
  - lib/rubocop/cop/active_record_serialize.rb
@@ -207,7 +201,6 @@ files:
207
201
  - lib/rubocop/cop/rails/include_url_helper.rb
208
202
  - lib/rubocop/cop/redirect_with_status.rb
209
203
  - lib/rubocop/cop/rspec/base.rb
210
- - lib/rubocop/cop/rspec/empty_line_after_final_let_it_be.rb
211
204
  - lib/rubocop/cop/rspec/empty_line_after_let_block.rb
212
205
  - lib/rubocop/cop/rspec/empty_line_after_shared_example.rb
213
206
  - lib/rubocop/cop/rspec/example_starting_character.rb
@@ -1,18 +0,0 @@
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_IT_BE_HELPERS = SelectorSet.new(%i[let_it_be let_it_be_with_refind let_it_be_with_reload])
13
- LET = LET_IT_BE_HELPERS + RuboCop::RSpec::Language::Helpers::ALL
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubocop-rspec'
4
- require_relative 'base'
5
-
6
- module Rubocop
7
- module Cop
8
- module RSpec
9
- # Checks if there is an empty line after the last `let_it_be` block.
10
- #
11
- # @example
12
- # # bad
13
- # let_it_be(:foo) { bar }
14
- # let_it_be(:something) { other }
15
- # it { does_something }
16
- #
17
- # # good
18
- # let_it_be(:foo) { bar }
19
- # let_it_be(:something) { other }
20
- #
21
- # it { does_something }
22
- class EmptyLineAfterFinalLetItBe < Base
23
- extend RuboCop::Cop::AutoCorrector
24
- include RuboCop::RSpec::EmptyLineSeparation
25
-
26
- MSG = 'Add an empty line after the last `let_it_be`.'
27
-
28
- def_node_matcher :let_it_be?, <<-PATTERN
29
- {
30
- (block (send #rspec? {:let_it_be :let_it_be_with_refind :let_it_be_with_reload} ...) ...)
31
- (send #rspec? {:let_it_be :let_it_be_with_refind :let_it_be_with_reload} _ block_pass)
32
- }
33
- PATTERN
34
-
35
- def on_block(node)
36
- return unless example_group_with_body?(node)
37
-
38
- final_let_it_be = node.body.child_nodes.reverse.find { |child| let_it_be?(child) }
39
-
40
- return if final_let_it_be.nil?
41
-
42
- missing_separating_line_offense(final_let_it_be) { MSG }
43
- end
44
- end
45
- end
46
- end
47
- end