gitlab-styles 13.1.0 → 14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e57fcdf2fdb535c445887ec28fe2c32809c24b90cf0202a27cf04f086c32fbc
4
- data.tar.gz: '074834caba51bf818e60afdffe2260f644d270d065af3eb46dd256d6deb90d5c'
3
+ metadata.gz: 97c5d02f5527dfe3cfecf408460d9613ca6b2d820d21ebd95d39dbc79f3b94b8
4
+ data.tar.gz: 92ade99f8c31fa1617d47c80a575fe572d67a03f113c2aff9417932bca74b305
5
5
  SHA512:
6
- metadata.gz: 60c696ef6dcde1baac7ff18ba02267f1d275182cf4ffa0bdfe400c7144ae8100bfc9f15e3faea4597e45afc3dd18e3445fda8b55ce1b9251ca57b985f682ab40
7
- data.tar.gz: 980a9c08bf84a10dc151c188b66cc60d3e42a953aea058955ad65bc6d8ad32d7498f154ce74257b71a1ef620d58cd3ef1f28c0025f2547c17eb5b5be02e60bb8
6
+ metadata.gz: 3d189c88f35cf67f0c211f40a27cd2bcac2b6964e0719279bcb4ae28601c98381150752332a0f894aedd1c7e0a57a3160ca44cc1877629594fa1eea737668e36
7
+ data.tar.gz: 30b2281cdb5ec7b966065ed926cdacbbcd7bdd9de66b85be0e7eb1758057759add13080e7a7c4c0c63ba5f2603c6ad8f863e8b7ccc44e412bb40bd2e0fc27ccf
@@ -11,11 +11,37 @@ Please describe the proposal and add a link to the source (for example, http://w
11
11
  - CHOICE_A: :a:
12
12
  - CHOICE_B: :b:
13
13
  - Vote yourself for both choices so that people know these are the choices
14
+ - [ ] Provide the impact of the proposal on `gitlab-org/gitlab`
14
15
  - [ ] The MR doesn't have significant objections, and is getting a majority of :+1: vs :-1: (remember that [we don't need to reach a consensus](https://about.gitlab.com/handbook/values/#collaboration-is-not-consensus))
15
16
  - [ ] (If applicable) One style is getting a majority of vote (compared to the other choice)
16
17
  - [ ] (If applicable) Update the MR with the chosen style
17
18
  - [ ] Follow the [review process](https://docs.gitlab.com/ee/development/code_review.html) as usual
18
19
 
20
+ ### Impact on gitlab-org/gitlab>
21
+
22
+ <!--
23
+
24
+ 1. In monolith's Gemfile, point `gitlab-styles` gem to this very MR branch.
25
+
26
+ For example, in Gemfile:
27
+
28
+ ...
29
+ gem 'gitlab-styles', '~> 13.1.0', require: false,
30
+ git: 'https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles.git',
31
+ ref: '<MR branch>' # rubocop:disable Cop/GemFetcher
32
+ ...
33
+
34
+ 2. Run `bundle update`
35
+ 3. Run `bundle exec rubocop --only <cop/rule> | pbcopy`
36
+ 4. Paste the output below
37
+
38
+ -->
39
+
40
+ ```
41
+ [Paste the output here]
42
+ ```
43
+
44
+
19
45
  /label ~"Engineering Productivity" ~"development guidelines" ~"static code analysis"
20
46
 
21
47
  /cc @gitlab-org/maintainers/rails-backend
data/.gitlab-ci.yml CHANGED
@@ -16,7 +16,7 @@ default:
16
16
  - gitlab-org
17
17
 
18
18
  .base-ruby-job:
19
- image: "ruby:${RUBY_VERSION}"
19
+ image: "${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}"
20
20
  before_script:
21
21
  - bundle_version=$(grep -A 1 "BUNDLED WITH" Gemfile.lock | grep -oE '[[:digit:].]+')
22
22
  - gem install bundler --version "$bundle_version" --no-document # Bundler is not installed with the image
data/.rubocop_todo.yml CHANGED
@@ -1,27 +1,11 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config --exclude-limit 10000`
3
- # on 2025-02-02 02:50:28 UTC using RuboCop version 1.71.0.
3
+ # on 2026-01-26 16:12:08 UTC using RuboCop version 1.81.7.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 11
10
- # This cop supports safe autocorrection (--autocorrect).
11
- InternalAffairs/CopDescriptionWithExample:
12
- Exclude:
13
- - 'lib/rubocop/cop/fips/md5.rb'
14
- - 'lib/rubocop/cop/fips/open_ssl.rb'
15
- - 'lib/rubocop/cop/fips/sha1.rb'
16
- - 'lib/rubocop/cop/gem_fetcher.rb'
17
- - 'lib/rubocop/cop/gitlab_security/deep_munge.rb'
18
- - 'lib/rubocop/cop/in_batches.rb'
19
- - 'lib/rubocop/cop/internal_affairs/deprecate_cop_helper.rb'
20
- - 'lib/rubocop/cop/line_break_around_conditional_block.rb'
21
- - 'lib/rubocop/cop/migration/update_large_table.rb'
22
- - 'lib/rubocop/cop/performance/rubyzip.rb'
23
- - 'lib/rubocop/cop/polymorphic_associations.rb'
24
-
25
9
  # Offense count: 10
26
10
  InternalAffairs/MissingCopDepartment:
27
11
  Exclude:
data/Gemfile.lock CHANGED
@@ -1,15 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-styles (13.1.0)
5
- rubocop (= 1.71.1)
6
- rubocop-capybara (~> 2.21.0)
7
- rubocop-factory_bot (~> 2.26.1)
8
- rubocop-graphql (~> 1.5.4)
9
- rubocop-performance (~> 1.21.1)
10
- rubocop-rails (~> 2.26.0)
11
- rubocop-rspec (~> 3.0.4)
12
- rubocop-rspec_rails (~> 2.30.0)
4
+ gitlab-styles (14.1.0)
5
+ rubocop (= 1.81.7)
6
+ rubocop-capybara (= 2.21.0)
7
+ rubocop-factory_bot (= 2.26.1)
8
+ rubocop-graphql (= 1.5.4)
9
+ rubocop-performance (= 1.23.1)
10
+ rubocop-rails (= 2.29.1)
11
+ rubocop-rspec (= 3.4.0)
12
+ rubocop-rspec_rails (= 2.30.0)
13
13
 
14
14
  GEM
15
15
  remote: https://rubygems.org/
@@ -101,6 +101,7 @@ GEM
101
101
  kramdown (~> 2.0)
102
102
  language_server-protocol (3.17.0.3)
103
103
  lefthook (1.3.13)
104
+ lint_roller (1.1.0)
104
105
  method_source (1.0.0)
105
106
  mini_mime (1.1.5)
106
107
  minitest (5.18.0)
@@ -113,9 +114,10 @@ GEM
113
114
  sawyer (~> 0.9)
114
115
  open4 (1.3.4)
115
116
  parallel (1.24.0)
116
- parser (3.3.1.0)
117
+ parser (3.3.10.0)
117
118
  ast (~> 2.4.1)
118
119
  racc
120
+ prism (1.6.0)
119
121
  proc_to_ast (0.1.0)
120
122
  coderay
121
123
  parser
@@ -156,35 +158,37 @@ GEM
156
158
  binding_of_caller
157
159
  rspec-parameterized-core (< 2)
158
160
  rspec-support (3.12.0)
159
- rubocop (1.71.1)
161
+ rubocop (1.81.7)
160
162
  json (~> 2.3)
161
- language_server-protocol (>= 3.17.0)
163
+ language_server-protocol (~> 3.17.0.2)
164
+ lint_roller (~> 1.1.0)
162
165
  parallel (~> 1.10)
163
166
  parser (>= 3.3.0.2)
164
167
  rainbow (>= 2.2.2, < 4.0)
165
168
  regexp_parser (>= 2.9.3, < 3.0)
166
- rubocop-ast (>= 1.38.0, < 2.0)
169
+ rubocop-ast (>= 1.47.1, < 2.0)
167
170
  ruby-progressbar (~> 1.7)
168
171
  unicode-display_width (>= 2.4.0, < 4.0)
169
- rubocop-ast (1.38.0)
170
- parser (>= 3.3.1.0)
172
+ rubocop-ast (1.48.0)
173
+ parser (>= 3.3.7.2)
174
+ prism (~> 1.4)
171
175
  rubocop-capybara (2.21.0)
172
176
  rubocop (~> 1.41)
173
177
  rubocop-factory_bot (2.26.1)
174
178
  rubocop (~> 1.61)
175
179
  rubocop-graphql (1.5.4)
176
180
  rubocop (>= 1.50, < 2)
177
- rubocop-performance (1.21.1)
181
+ rubocop-performance (1.23.1)
178
182
  rubocop (>= 1.48.1, < 2.0)
179
183
  rubocop-ast (>= 1.31.1, < 2.0)
180
- rubocop-rails (2.26.0)
184
+ rubocop-rails (2.29.1)
181
185
  activesupport (>= 4.2.0)
182
186
  rack (>= 1.1)
183
187
  rubocop (>= 1.52.0, < 2.0)
184
188
  rubocop-ast (>= 1.31.1, < 2.0)
185
189
  rubocop-rake (0.6.0)
186
190
  rubocop (~> 1.0)
187
- rubocop-rspec (3.0.4)
191
+ rubocop-rspec (3.4.0)
188
192
  rubocop (~> 1.61)
189
193
  rubocop-rspec_rails (2.30.0)
190
194
  rubocop (~> 1.61)
data/README.md CHANGED
@@ -19,6 +19,19 @@ Or install it yourself as:
19
19
 
20
20
  $ gem install gitlab-styles
21
21
 
22
+ ## Why We Pin Gem Versions
23
+
24
+ `gitlab-styles` pins specific versions of RuboCop and related gems (e.g., `rubocop-rails`, `rubocop-rspec`, `rubocop-performance`) to ensure **consistent rule configuration and behavior across all GitLab projects**.
25
+
26
+ When gems are left unpinned, minor or patch version updates can introduce:
27
+
28
+ - **New or modified RuboCop rules** that may conflict with your project's configuration
29
+ - **Inconsistent linting results** across different environments and CI/CD pipelines
30
+ - **Unexpected build failures** when developers or CI systems install different versions
31
+ - **Configuration drift** between projects using `gitlab-styles`
32
+
33
+ By pinning versions, we guarantee that all projects using `gitlab-styles` enforce the same coding standards and rules, regardless of when they install the gem.
34
+
22
35
  ## Usage
23
36
 
24
37
  ### Inherit all rules
@@ -22,14 +22,14 @@ Gem::Specification.new do |spec|
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', '1.71.1'
26
- spec.add_dependency 'rubocop-capybara', '~> 2.21.0'
27
- spec.add_dependency 'rubocop-factory_bot', '~> 2.26.1'
28
- spec.add_dependency 'rubocop-graphql', '~> 1.5.4'
29
- spec.add_dependency 'rubocop-performance', '~> 1.21.1'
30
- spec.add_dependency 'rubocop-rails', '~> 2.26.0'
31
- spec.add_dependency 'rubocop-rspec', '~> 3.0.4'
32
- spec.add_dependency 'rubocop-rspec_rails', '~> 2.30.0'
25
+ spec.add_dependency 'rubocop', '1.81.7'
26
+ spec.add_dependency 'rubocop-capybara', '2.21.0'
27
+ spec.add_dependency 'rubocop-factory_bot', '2.26.1'
28
+ spec.add_dependency 'rubocop-graphql', '1.5.4'
29
+ spec.add_dependency 'rubocop-performance', '1.23.1'
30
+ spec.add_dependency 'rubocop-rails', '2.29.1'
31
+ spec.add_dependency 'rubocop-rspec', '3.4.0'
32
+ spec.add_dependency 'rubocop-rspec_rails', '2.30.0'
33
33
 
34
34
  spec.add_development_dependency 'bundler', '~> 2.1'
35
35
  spec.add_development_dependency 'gitlab-dangerfiles', '~> 4.6.0'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module Styles
5
- VERSION = '13.1.0'
5
+ VERSION = '14.1.0'
6
6
  end
7
7
  end
@@ -67,8 +67,7 @@ module Rubocop
67
67
  end
68
68
 
69
69
  def def?(node)
70
- node.type?(:def, :defs) ||
71
- (node.block_type? && DEF_METHODS.include?(node.method_name))
70
+ node.any_def_type? || (node.block_type? && DEF_METHODS.include?(node.method_name))
72
71
  end
73
72
 
74
73
  def allowed?(block_node)
@@ -5,6 +5,16 @@ require_relative '../../../gitlab/styles/common/banned_constants'
5
5
  module Rubocop
6
6
  module Cop
7
7
  module Fips
8
+ # Checks for the usage of MD5, which is not FIPS-compliant.
9
+ # It suggests using a FIPS-compliant alternative like SHA256.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # OpenSSL::Digest::MD5.hexdigest('foo')
14
+ # Digest::MD5.hexdigest('foo')
15
+ #
16
+ # # good
17
+ # OpenSSL::Digest::SHA256.hexdigest('foo')
8
18
  class MD5 < RuboCop::Cop::Base
9
19
  include Gitlab::Styles::Common::BannedConstants
10
20
 
@@ -5,6 +5,17 @@ require_relative '../../../gitlab/styles/common/banned_constants'
5
5
  module Rubocop
6
6
  module Cop
7
7
  module Fips
8
+ # Flags usage of the Digest class (which is not FIPS-compliant) and suggests replacing it with OpenSSL::Digest
9
+ # (which is FIPS-compliant).
10
+ #
11
+ # @example
12
+ # # bad
13
+ # Digest::SHA1.hexdigest('foo')
14
+ # Digest::SHA512('foo')
15
+ #
16
+ # # good
17
+ # OpenSSL::Digest::SHA1.hexdigest('foo')
18
+ # OpenSSL::Digest::SHA512.hexdigest('foo')
8
19
  class OpenSSL < RuboCop::Cop::Base
9
20
  extend RuboCop::Cop::AutoCorrector
10
21
  include Gitlab::Styles::Common::BannedConstants
@@ -5,6 +5,14 @@ require_relative '../../../gitlab/styles/common/banned_constants'
5
5
  module Rubocop
6
6
  module Cop
7
7
  module Fips
8
+ # Cop that denies the use of Digest::SHA1
9
+ # @example
10
+ # # bad
11
+ # OpenSSL::Digest::SHA1.hexdigest('foo')
12
+ # Digest::SHA1('ABC')
13
+ #
14
+ # # good
15
+ # OpenSSL::Digest::SHA256.hexdigest('foo')
8
16
  class SHA1 < RuboCop::Cop::Base
9
17
  include Gitlab::Styles::Common::BannedConstants
10
18
 
@@ -5,6 +5,12 @@ module Rubocop
5
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
+ # @example
9
+ # # bad
10
+ # gem 'rack', git: 'https://github.com/rack/rack'
11
+ #
12
+ # # good
13
+ # gem "rack"
8
14
  class GemFetcher < RuboCop::Cop::Base
9
15
  MSG = 'Do not use gems from git repositories, only use gems from RubyGems or vendored gems. ' \
10
16
  'See https://docs.gitlab.com/ee/development/gemfile.html#no-gems-fetched-from-git-repositories'
@@ -13,7 +13,17 @@ module RuboCop
13
13
  # # bad
14
14
  # config.action_dispatch.perform_deep_munge = false
15
15
  #
16
+ # # bad
17
+ # config.action_dispatch.perform_deep_munge = !true
18
+ #
19
+ # # good
20
+ # config.action_dispatch.perform_deep_munge = true
21
+ #
22
+ # # good
23
+ # # Deep munge is not explicitly disabled
24
+ #
16
25
  # See CVE-2012-2660, CVE-2012-2694, and CVE-2013-0155.
26
+
17
27
  class DeepMunge < RuboCop::Cop::Base
18
28
  MSG = 'Never disable the deep munge security option.'
19
29
 
@@ -3,6 +3,14 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  # Cop that prevents the use of `in_batches`
6
+ # @example
7
+ # # bad
8
+ # Foo.in_batches do |relation|
9
+ # end
10
+ #
11
+ # # good
12
+ # Foo.each_batch do |relation|
13
+ # end
6
14
  class InBatches < RuboCop::Cop::Base
7
15
  MSG = 'Do not use `in_batches`, use `each_batch` from the EachBatch module instead'
8
16
 
@@ -81,7 +81,7 @@ module Rubocop
81
81
  index_of_example = lines.index { |line| line.text.match?(/# @example( |$)/) }
82
82
  return false unless index_of_example
83
83
 
84
- lines_after_example = lines[index_of_example + 1..]
84
+ lines_after_example = lines[(index_of_example + 1)..]
85
85
 
86
86
  lines_after_example.any? { |line| line.text.downcase.match?(/# # good( |$)/) } &&
87
87
  lines_after_example.any? { |line| line.text.downcase.match?(/# # bad( |$)/) }
@@ -4,6 +4,18 @@ module Rubocop
4
4
  module Cop
5
5
  module InternalAffairs
6
6
  # Cop that denies the use of CopHelper.
7
+ # @example
8
+ # # bad
9
+ # include CopHelper
10
+ #
11
+ # inspect_source(<<~RUBY)
12
+ # #....
13
+ # RUBY
14
+ #
15
+ # # good
16
+ # expect_offense(<<~RUBY)
17
+ # # ....
18
+ # RUBY
7
19
  class DeprecateCopHelper < RuboCop::Cop::Base
8
20
  MSG = 'Do not use `CopHelper` or methods from it, use improved patterns described in https://www.rubydoc.info/gems/rubocop/RuboCop/RSpec/ExpectOffense'
9
21
 
@@ -45,37 +45,35 @@ module RuboCop
45
45
  MSG = 'Define constant `RESTRICT_ON_SEND` to speed up calls to `on_send`. ' \
46
46
  'The following line is then no longer necessary:'
47
47
 
48
- # @!method method_name_plain(node)
48
+ # @!method method_name_plain(node, send_param)
49
49
  def_node_matcher :method_name_plain, <<~PATTERN
50
50
  {
51
- (send _ :method_name _ ...) # method_name(node)
52
- (send
53
- (send _ :children) :[] (int 1) # node.children[1]
54
- )
51
+ (send _ :method_name (lvar %1) ...) # method_name(on_send_param)
52
+ (send (send (lvar %1) :children) :[] (int 1)) # on_send_param.children[1]
55
53
  }
56
54
  PATTERN
57
55
 
58
- # @!method method_name_call(node)
56
+ # @!method method_name_call(node, send_param, local_assignments)
59
57
  def_node_matcher :method_name_call, <<~PATTERN
60
58
  {
61
- #method_name_plain
62
- (lvar %1)
59
+ #method_name_plain(%1) # direct method_name/children[1] call on the on_send param
60
+ (lvar %2) # local variable previously assigned from such a call
63
61
  }
64
62
  PATTERN
65
63
 
66
- # @!method method_name_assignment(node)
64
+ # @!method method_name_assignment(node, send_param)
67
65
  def_node_search :method_name_assignment, <<~PATTERN
68
- (lvasgn $_name #method_name_plain)
66
+ (lvasgn $_ #method_name_plain(%1))
69
67
  PATTERN
70
68
 
71
- # @!method method_name_check(node)
69
+ # @!method method_name_check(node, send_param, local_assignments)
72
70
  def_node_search :method_name_check, <<~PATTERN
73
71
  (if
74
72
  ${
75
- (send #method_name_call(%1) {:== :!=} _) # method_name(node) == foo
76
- (send _ :include? #method_name_call(%1)) # a.include?(method_name(node))
73
+ (send #method_name_call(%1, %2) {:== :!=} _) # method_name(on_send_param) == foo
74
+ (send _ :include? #method_name_call(%1, %2)) # a.include?(method_name(on_send_param))
77
75
  }
78
- {!nil? nil? | nil? !nil?} # has either `if` or `else` branch - not both
76
+ {!nil? nil? | nil? !nil?} # has either `if` or `else` branch - not both
79
77
  )
80
78
  PATTERN
81
79
 
@@ -83,9 +81,12 @@ module RuboCop
83
81
  return unless node.method?(:on_send)
84
82
  return if @restrict_on_send_set
85
83
 
86
- local_assignments = method_name_assignment(node).to_set
84
+ send_param = node.first_argument&.name
85
+ return unless send_param
87
86
 
88
- method_name_check(node, local_assignments) do |call_node|
87
+ local_assignments = method_name_assignment(node, send_param).to_set
88
+
89
+ method_name_check(node, send_param, local_assignments) do |call_node|
89
90
  add_offense(call_node)
90
91
  end
91
92
  end
@@ -5,43 +5,43 @@ module Rubocop
5
5
  # Ensures a line break around conditional blocks.
6
6
  #
7
7
  # @example
8
- # # bad
9
- # do_something
10
- # if condition
11
- # do_extra_stuff
12
- # end
13
- # do_something_more
8
+ # # bad
9
+ # do_something
10
+ # if condition
11
+ # do_extra_stuff
12
+ # end
13
+ # do_something_more
14
14
  #
15
- # # good
16
- # do_something
15
+ # # good
16
+ # do_something
17
17
  #
18
- # if condition
19
- # do_extra_stuff
20
- # end
18
+ # if condition
19
+ # do_extra_stuff
20
+ # end
21
21
  #
22
- # do_something_more
22
+ # do_something_more
23
23
  #
24
- # # bad
25
- # do_something
26
- # unless condition
27
- # do_extra_stuff
28
- # end
24
+ # # bad
25
+ # do_something
26
+ # unless condition
27
+ # do_extra_stuff
28
+ # end
29
29
  #
30
- # do_something_more
30
+ # do_something_more
31
31
  #
32
- # # good
33
- # def a_method
34
- # if condition
35
- # do_something
36
- # end
37
- # end
32
+ # # good
33
+ # def a_method
34
+ # if condition
35
+ # do_something
36
+ # end
37
+ # end
38
38
  #
39
- # # good
40
- # on_block do
41
- # if condition
42
- # do_something
43
- # end
44
- # end
39
+ # # good
40
+ # on_block do
41
+ # if condition
42
+ # do_something
43
+ # end
44
+ # end
45
45
  class LineBreakAroundConditionalBlock < RuboCop::Cop::Base
46
46
  extend RuboCop::Cop::AutoCorrector
47
47
  include RuboCop::Cop::RangeHelp
@@ -100,7 +100,7 @@ module Rubocop
100
100
  end
101
101
 
102
102
  def end_clause_line?(line)
103
- line =~ /^\s*(#|rescue|else|elsif|when)/
103
+ line =~ /^\s*(#|rescue|else|elsif|when|ensure)/
104
104
  end
105
105
 
106
106
  def begin_line?(line)
@@ -8,10 +8,33 @@ module Rubocop
8
8
  # Checks for methods that may lead to batch type issues on a table that's been
9
9
  # explicitly denied because of its size.
10
10
  #
11
- # Even though though these methods perform functions to avoid
11
+ # Even though these methods perform functions to avoid
12
12
  # downtime, using it with tables with millions of rows still causes a
13
13
  # significant delay in the deploy process and is best avoided.
14
14
  #
15
+ # @example
16
+ #
17
+ # # bad
18
+ # class ExampleMigration < ActiveRecord::Migration[7.0]
19
+ # def change
20
+ # denied_method(:denied_table, column: :value)
21
+ # end
22
+ # end
23
+ #
24
+ # # good
25
+ # class ExampleMigration < ActiveRecord::Migration[7.0]
26
+ # def change
27
+ # denied_method(:allowed_table, column: :value)
28
+ # end
29
+ # end
30
+ #
31
+ # # good
32
+ # class ExampleMigration < ActiveRecord::Migration[7.0]
33
+ # def change
34
+ # allowed_method(:denied_table, column: :value)
35
+ # end
36
+ # end
37
+ #
15
38
  # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more
16
39
  # information.
17
40
  class UpdateLargeTable < RuboCop::Cop::Base
@@ -8,6 +8,12 @@ module Rubocop
8
8
  # files and directories, this can be very expensive even when the archive's size
9
9
  # in bytes is small.
10
10
  #
11
+ # @example
12
+ # # bad
13
+ # Zip::File.open('file_path.zip', &block)
14
+ #
15
+ # # good
16
+ # Zip::InputStream.open('file_path.zip')
11
17
  # See also:
12
18
  # - https://github.com/rubyzip/rubyzip/issues/506
13
19
  # - https://github.com/rubyzip/rubyzip#notes-on-zipinputstream
@@ -3,6 +3,17 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  # Cop that prevents the use of polymorphic associations
6
+ # @example
7
+ # # bad
8
+ # class Comment < ApplicationRecord
9
+ # belongs_to :commentable, polymorphic: true
10
+ # end
11
+ #
12
+ # # good
13
+ # class Comment < ApplicationRecord
14
+ # belongs_to :post
15
+ # belongs_to :article
16
+ # end
6
17
  class PolymorphicAssociations < RuboCop::Cop::Base
7
18
  MSG = 'Do not use polymorphic associations, use separate tables instead'
8
19
 
@@ -0,0 +1,45 @@
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
+ # Limits the number of examples in feature spec files.
10
+ #
11
+ # Feature specs with too many examples are slow to run, hard to maintain,
12
+ # and often indicate the file should be split into smaller, focused specs.
13
+ #
14
+ # The maximum number of examples can be configured with the `Max` option
15
+ # (default: 25).
16
+ #
17
+ # @example Max: 25 (default)
18
+ #
19
+ # # bad
20
+ # # A feature spec file with more than 25 examples.
21
+ #
22
+ # # good
23
+ # # A feature spec file with 25 or fewer examples.
24
+ class FeatureSpecMaxExamples < Base
25
+ MSG = 'Feature spec file has %<count>d examples, which exceeds the maximum of %<max>d. ' \
26
+ 'Consider splitting into smaller, focused files grouped by user flow or feature area.'
27
+
28
+ def on_new_investigation
29
+ super
30
+ @example_count = 0
31
+ @max = cop_config['Max'] || 25
32
+ end
33
+
34
+ def on_block(node)
35
+ @example_count += 1 if example?(node)
36
+ end
37
+ alias_method :on_numblock, :on_block
38
+
39
+ def on_investigation_end
40
+ add_global_offense(format(MSG, count: @example_count, max: @max)) if @example_count > @max
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -14,7 +14,8 @@ module Rubocop
14
14
  # css_classes = ["gl-mt-3", "md:gl-mt-5"]
15
15
  # %div{ class: ["gl-mt-3", "md:gl-mt-5"] }
16
16
  class MaxWidthMediaQueries < RuboCop::Cop::Base
17
- TAILWIND_CSS_CLASS = /max-(sm|md|lg|xl):gl-/
17
+ ALLOWLIST = ['hidden'].freeze
18
+ TAILWIND_CSS_CLASS = /max-(sm|md|lg|xl):gl-(?!#{ALLOWLIST.join('|')})/
18
19
  MSG = 'Do not use max-width media query utility classes unless absolutely necessary. ' \
19
20
  'Use min-width media query utility classes instead.'
20
21
 
data/rubocop-naming.yml CHANGED
@@ -48,7 +48,7 @@ Naming/MethodParameterName:
48
48
  # NamePrefix: is_, has_, have_
49
49
  # NamePrefixBlacklist: is_, has_, have_
50
50
  # NameWhitelist: is_a?
51
- Naming/PredicateName:
51
+ Naming/PredicatePrefix:
52
52
  Enabled: true
53
53
  ForbiddenPrefixes:
54
54
  - is_
data/rubocop-rspec.yml CHANGED
@@ -96,6 +96,12 @@ RSpec/ExpectChange:
96
96
  RSpec/ExpectOutput:
97
97
  Enabled: true
98
98
 
99
+ # Limits the number of examples in feature spec files to encourage splitting
100
+ # large specs into smaller, focused files.
101
+ RSpec/FeatureSpecMaxExamples:
102
+ Enabled: false
103
+ Max: 25
104
+
99
105
  # Checks if there are focused specs.
100
106
  RSpec/Focus:
101
107
  Enabled: true
data/rubocop-style.yml CHANGED
@@ -475,6 +475,10 @@ Style/TrailingCommaInArguments:
475
475
  Enabled: true
476
476
  EnforcedStyleForMultiline: no_comma
477
477
 
478
+ # Checks for the use of logical operators in an unless condition.
479
+ Style/UnlessLogicalOperators:
480
+ Enabled: true
481
+
478
482
  # Don't interpolate global, instance and class variables directly in strings.
479
483
  Style/VariableInterpolation:
480
484
  Enabled: true
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: 13.1.0
4
+ version: 14.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: 2025-02-10 00:00:00.000000000 Z
11
+ date: 2026-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -16,110 +16,110 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.71.1
19
+ version: 1.81.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.71.1
26
+ version: 1.81.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubocop-capybara
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - '='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.21.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - '='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.21.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop-factory_bot
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
47
  version: 2.26.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.26.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rubocop-graphql
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
61
  version: 1.5.4
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.5.4
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-performance
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 1.21.1
75
+ version: 1.23.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 1.21.1
82
+ version: 1.23.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 2.26.0
89
+ version: 2.29.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 2.26.0
96
+ version: 2.29.1
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop-rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 3.0.4
103
+ version: 3.4.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 3.0.4
110
+ version: 3.4.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop-rspec_rails
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - '='
116
116
  - !ruby/object:Gem::Version
117
117
  version: 2.30.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - '='
123
123
  - !ruby/object:Gem::Version
124
124
  version: 2.30.0
125
125
  - !ruby/object:Gem::Dependency
@@ -357,6 +357,7 @@ files:
357
357
  - lib/rubocop/cop/rspec/empty_line_after_let_block.rb
358
358
  - lib/rubocop/cop/rspec/empty_line_after_shared_example.rb
359
359
  - lib/rubocop/cop/rspec/example_starting_character.rb
360
+ - lib/rubocop/cop/rspec/feature_spec_max_examples.rb
360
361
  - lib/rubocop/cop/rspec/have_link_parameters.rb
361
362
  - lib/rubocop/cop/rspec/rails_controller_testing.rb
362
363
  - lib/rubocop/cop/rspec/single_line_hook.rb
@@ -409,7 +410,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
409
410
  - !ruby/object:Gem::Version
410
411
  version: '0'
411
412
  requirements: []
412
- rubygems_version: 3.3.27
413
+ rubygems_version: 3.5.22
413
414
  signing_key:
414
415
  specification_version: 4
415
416
  summary: GitLab style guides and shared style configs.