gitlab-styles 8.0.0 → 9.1.0

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 (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