ezcater_rubocop 7.1.2 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 911fadcf937e62f81a8fc64de11cb3d59738c0fcb25b95839439248afbb5d620
4
- data.tar.gz: 57099d0884b73639be2669343e3fbd516e3b0b10f518b2e4003220c910f0ae64
3
+ metadata.gz: d1a7228be76189e5a330bb1e9edae0e1bc35be77af84aebae08fd9b76f652283
4
+ data.tar.gz: 5727cedd1aa216879a69a06b02448a1eb3806e15ea82339d4ee5f14cfb87c162
5
5
  SHA512:
6
- metadata.gz: 82d100a66b9c66c1da3f491f0c8f5c9876771c7ab4e608be8e9357c1e1e7838cd63f6d5578d854141d46aae65ade6d90ba0499410d68c6902c6083fa5636893e
7
- data.tar.gz: 2904b76df7994b7e8b746a921108137d3c98dafbdfef4993866ab415f021f8d60900f8730699e248d5208c1205c47405e77471f87dafd2493adef3ddf8b74e95
6
+ metadata.gz: 4cc8fd3788297b86403405edfc35e2b17ade3aa5a6656249021b022e41377cebd894ab45938204eefc556cb5585761ee89ecdf45c9613ce6256d99bcc06e0258
7
+ data.tar.gz: 844b539b44ffd246b2cc03af450d0239f2e3cd515e9e0ba7acdbd797b9cd229888ecd0ef1785faced9e7c06d82051690bc779e13d56c448afa57e000423b3d7c
data/CHANGELOG.md CHANGED
@@ -6,8 +6,16 @@ This gem is moving onto its own [Semantic Versioning](https://semver.org/) schem
6
6
 
7
7
  Prior to v1.0.0 this gem was versioned based on the `MAJOR`.`MINOR` version of RuboCop. The first release of the ezcater_rubocop gem was `v0.49.0`.
8
8
 
9
+ ## 8.0.0
10
+
11
+ - Add `Ezcater/Migration/BigintForeignKey` Cop, which enforces the use of `bigint` for foreign keys in migrations.
12
+
13
+ ## 7.1.3
14
+
15
+ - Update internal CI processes to validate Rubocop config files
16
+
9
17
  ## 7.1.2
10
- -
18
+
11
19
  - Fix a stray space in `Rails/BulkChangeTable` definition
12
20
 
13
21
  ## 7.1.1
data/README.md CHANGED
@@ -48,6 +48,10 @@ Further customization of RuboCop for your local project may be added to this fil
48
48
  - **rubocop_gem**: For use in Ruby gem projects, this inherits from the **rubocop** configuration.
49
49
  - **rubocop_rails**: For Rails projects, this inherits from the **rubocop** configuration.
50
50
 
51
+ ### Documentation
52
+
53
+ Visit https://gemdocs.org/gems/ezcater_rubocop to view the documentation for our custom cops in the latest release.
54
+
51
55
  ## Usage
52
56
 
53
57
  Run `rubocop` for an entire project:
@@ -92,8 +96,9 @@ not add cops with `enabled: false` unless you want that cop to always be disable
92
96
  * [RspecRequireFeatureFlagMock](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/rspec_require_feature_flag_mock.rb) - Enforce use of `mock_feature_flag` helper instead of mocking `FeatureFlag.is_active?` directly.
93
97
  * [RspecRequireHttpStatusMatcher](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/rspec_require_http_status_matcher.rb) - Use the HTTP status code matcher, like `expect(response).to have_http_status :bad_request`, rather than `expect(response.code).to eq 400`
94
98
  * [StyleDig](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/style_dig.rb) - Recommend `dig` for deeply nested access.
99
+ * [Migration/BigintForeignKey](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/migration/bigint_foreign_key.rb) - Use `#bigint` instead of `#integer` for all foreign keys.
95
100
 
96
- [GraphQL/NotAuthorizedScalarField]: https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb)
101
+ [GraphQL/NotAuthorizedScalarField]: https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb
97
102
 
98
103
  ## Development
99
104
 
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ # Checks the validity of RuboCop config files in `conf/` directory (excluding the base config).
4
+
5
+ CONFIGS=(
6
+ "conf/rubocop_gem.yml"
7
+ "conf/rubocop_rails.yml"
8
+ )
9
+
10
+ exit_code=0
11
+
12
+ for config in "${CONFIGS[@]}"; do
13
+ if ! output=$(bundle exec rubocop --show-cops -c "$config" 2>&1); then
14
+ echo "❌ Error in $config"
15
+ echo "$output"
16
+ exit_code=1
17
+ fi
18
+ done
19
+
20
+ if [[ $exit_code -eq 0 ]]; then
21
+ echo "✅ All configs are valid"
22
+ fi
23
+ exit $exit_code
data/config/default.yml CHANGED
@@ -74,3 +74,8 @@ GraphQL/ObjectDescription:
74
74
  GraphQL/ExtractInputType:
75
75
  Exclude:
76
76
  - "**/input_objects/**/*.rb"
77
+
78
+ Ezcater/Migration/BigintForeignKey:
79
+ Description: "Use `bigint` instead of `integer` for all foreign keys."
80
+ Include:
81
+ - "**/db/migrate/**/*.rb"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EzcaterRubocop
4
- VERSION = "7.1.2"
4
+ VERSION = "8.0.0"
5
5
  end
@@ -16,19 +16,20 @@ puts "configuration from #{DEFAULT_FILES}" if RuboCop::ConfigLoader.debug?
16
16
  config = RuboCop::ConfigLoader.merge_with_default(config, path)
17
17
  RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
18
18
 
19
- require "rubocop/cop/ezcater/direct_env_check"
20
- require "rubocop/cop/ezcater/feature_flag_active"
21
- require "rubocop/cop/ezcater/feature_flag_name_valid"
22
- require "rubocop/cop/ezcater/graphql/not_authorized_scalar_field"
23
- require "rubocop/cop/ezcater/rails_configuration"
24
- require "rubocop/cop/ezcater/rails_env"
25
- require "rubocop/cop/ezcater/ruby_timeout"
26
- require "rubocop/cop/ezcater/rails_top_level_sql_execute"
27
- require "rubocop/cop/ezcater/require_custom_error"
28
- require "rubocop/cop/ezcater/require_gql_error_helpers"
29
- require "rubocop/cop/ezcater/rspec_match_ordered_array"
30
- require "rubocop/cop/ezcater/rspec_require_browser_mock"
31
- require "rubocop/cop/ezcater/rspec_require_feature_flag_mock"
32
- require "rubocop/cop/ezcater/rspec_require_http_status_matcher"
33
- require "rubocop/cop/ezcater/rspec_dot_not_self_dot"
34
- require "rubocop/cop/ezcater/style_dig"
19
+ require_relative "rubocop/cop/ezcater/direct_env_check"
20
+ require_relative "rubocop/cop/ezcater/feature_flag_active"
21
+ require_relative "rubocop/cop/ezcater/feature_flag_name_valid"
22
+ require_relative "rubocop/cop/ezcater/graphql/not_authorized_scalar_field"
23
+ require_relative "rubocop/cop/ezcater/rails_configuration"
24
+ require_relative "rubocop/cop/ezcater/rails_env"
25
+ require_relative "rubocop/cop/ezcater/ruby_timeout"
26
+ require_relative "rubocop/cop/ezcater/rails_top_level_sql_execute"
27
+ require_relative "rubocop/cop/ezcater/require_custom_error"
28
+ require_relative "rubocop/cop/ezcater/require_gql_error_helpers"
29
+ require_relative "rubocop/cop/ezcater/rspec_match_ordered_array"
30
+ require_relative "rubocop/cop/ezcater/rspec_require_browser_mock"
31
+ require_relative "rubocop/cop/ezcater/rspec_require_feature_flag_mock"
32
+ require_relative "rubocop/cop/ezcater/rspec_require_http_status_matcher"
33
+ require_relative "rubocop/cop/ezcater/rspec_dot_not_self_dot"
34
+ require_relative "rubocop/cop/ezcater/style_dig"
35
+ require_relative "rubocop/cop/ezcater/migration/bigint_foreign_key"
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Ezcater
6
+ module Migration
7
+ # Use `bigint` instead of `integer` for all foreign keys.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # create_table :foos do |t|
13
+ # t.integer :bar_id
14
+ # end
15
+ #
16
+ # # bad
17
+ # create_table :foos do |t|
18
+ # t.integer :bar_id, limit: 7
19
+ # end
20
+ #
21
+ # # bad
22
+ # add_column :foos, :bar_id, :integer
23
+ #
24
+ # # bad
25
+ # add_column :foos, :bar_id, :integer, limit: 7
26
+ #
27
+ # # bad
28
+ # add_reference :foos, :bar, type: :integer
29
+ #
30
+ # # bad
31
+ # add_reference :foos, :bar, type: :integer, limit: 7
32
+ #
33
+ # # good
34
+ # create_table :foos do |t|
35
+ # t.bigint :bar_id
36
+ # end
37
+ #
38
+ # # good
39
+ # create_table :foos do |t|
40
+ # t.references :bar
41
+ # end
42
+ #
43
+ # # good
44
+ # add_column :foos, :bar_id, :bigint
45
+ #
46
+ # # good
47
+ # add_reference :foos, :bar
48
+ #
49
+ class BigintForeignKey < Base # rubocop:disable Metrics/ClassLength
50
+ extend AutoCorrector
51
+
52
+ MSG = <<~MSG.chomp
53
+ Use `bigint` instead of `integer` for foreign keys. This ensures that they are capable of storing all possible values from referenced primary keys which are `bigint` or may eventually be migrated to `bigint`.
54
+ MSG
55
+
56
+ # Optimization: only call `on_send` for the methods in this list
57
+ RESTRICT_ON_SEND = %i(
58
+ integer
59
+ references
60
+ belongs_to
61
+ add_column
62
+ add_reference
63
+ add_belongs_to
64
+ ).freeze
65
+
66
+ BIGINT_BYTES = 8
67
+
68
+ # @!method t_integer_method(node)
69
+ def_node_matcher :t_integer_method, <<~PATTERN
70
+ (send
71
+ # Any local variable that calls an `integer` method
72
+ (lvar _) :integer
73
+
74
+ # Column name: symbol or string ending in _id
75
+ {(sym #ends_with_id?) (str #ends_with_id?)}
76
+
77
+ # Optional hash that includes a limit key
78
+ (hash <(pair (sym :limit) (int $_)) ...>)?
79
+ )
80
+ PATTERN
81
+
82
+ # @!method t_references_method(node)
83
+ def_node_matcher :t_references_method, <<~PATTERN
84
+ (send
85
+ # Any local variable that calls a `references` or `belongs_to` method
86
+ (lvar _) {:references :belongs_to}
87
+
88
+ # Reference name
89
+ {(sym _) (str _)}
90
+
91
+ # A hash that includes `type: :integer`
92
+ (hash <(pair (sym :type) (sym :integer)) ...>)
93
+ )
94
+ PATTERN
95
+
96
+ # @!method add_column_method(node)
97
+ def_node_matcher :add_column_method, <<~PATTERN
98
+ # A call to an `add_column` method
99
+ (send nil? :add_column
100
+ # Table name
101
+ {(sym _) (str _)}
102
+
103
+ # Column name: a symbol or string ending in _id
104
+ {(sym #ends_with_id?) (str #ends_with_id?)}
105
+
106
+ # Column type
107
+ (sym :integer)
108
+
109
+ # Optional hash that includes a limit key
110
+ (hash <(pair (sym :limit) (int $_)) ...>)?
111
+ )
112
+ PATTERN
113
+
114
+ # @!method add_reference_method(node)
115
+ def_node_matcher :add_reference_method, <<~PATTERN
116
+ # A call to a `add_reference` or `add_belongs_to` method
117
+ (send nil? {:add_reference :add_belongs_to}
118
+ # Table name
119
+ {(sym _) (str _)}
120
+
121
+ # Reference name
122
+ {(sym _) (str _)}
123
+
124
+ # A hash that includes `type: :integer`
125
+ (hash <(pair (sym :type) (sym :integer)) ...>)
126
+ )
127
+ PATTERN
128
+
129
+ # @!method limit_pair(node)
130
+ def_node_search :limit_pair, <<~PATTERN
131
+ (pair (sym :limit) (int $_))
132
+ PATTERN
133
+
134
+ def on_send(node)
135
+ t_integer_method(node) do |captures|
136
+ check_integer_method(node, captures)
137
+ end
138
+
139
+ add_column_method(node) do |captures|
140
+ check_integer_method(node, captures)
141
+ end
142
+
143
+ t_references_method(node) do
144
+ check_reference_method(node)
145
+ end
146
+
147
+ add_reference_method(node) do
148
+ check_reference_method(node)
149
+ end
150
+ end
151
+
152
+ private
153
+
154
+ def ends_with_id?(str)
155
+ str.end_with?("_id")
156
+ end
157
+
158
+ def check_integer_method(node, captures)
159
+ limit_value = captures.first
160
+ check_for_offense(node, limit_value)
161
+ end
162
+
163
+ def check_reference_method(node)
164
+ limit_vals = limit_pair(node)
165
+ limit_value = limit_vals.first
166
+
167
+ check_for_offense(node, limit_value)
168
+ end
169
+
170
+ def check_for_offense(node, limit_value)
171
+ return unless limit_value.nil? || limit_value < BIGINT_BYTES
172
+
173
+ add_offense(node) do |corrector|
174
+ make_correction(node, corrector)
175
+ end
176
+ end
177
+
178
+ def make_correction(node, corrector)
179
+ case node.method_name
180
+ when :integer
181
+ correct_integer_method(node, corrector)
182
+ when :references, :belongs_to
183
+ correct_references_method(node, corrector)
184
+ when :add_column
185
+ correct_add_column_method(node, corrector)
186
+ when :add_reference, :add_belongs_to
187
+ correct_add_reference_method(node, corrector)
188
+ end
189
+ end
190
+
191
+ def correct_integer_method(node, corrector)
192
+ # There's no hash argument or it has only one pair
193
+ if node.arguments.size == 1 ||
194
+ (node.arguments.size == 2 &&
195
+ (node.arguments[1].hash_type? &&
196
+ node.arguments[1].pairs.size == 1))
197
+
198
+ corrector.replace(
199
+ range_for_method_and_optional_limit(node),
200
+ "bigint #{node.arguments[0].source}"
201
+ )
202
+ end
203
+ end
204
+
205
+ def correct_references_method(node, corrector)
206
+ # There's only one hash pair (:type) or only two: :type and :limit
207
+ return unless node.arguments.size == 2 && node.arguments[1].hash_type?
208
+
209
+ hash_pairs = node.arguments[1].pairs
210
+ keys = hash_pairs.map { |pair| pair.key.source }
211
+
212
+ if keys.size == 1 ||
213
+ (keys.size == 2 && keys.include?("limit"))
214
+
215
+ corrector.replace(
216
+ range_for_method_and_optional_limit(node),
217
+ "#{node.method_name} #{node.arguments[0].source}"
218
+ )
219
+ end
220
+ end
221
+
222
+ def correct_add_column_method(node, corrector)
223
+ # There's no hash argument or it has only one pair (:limit)
224
+ if node.arguments.size == 3 ||
225
+ (node.arguments.size == 4 &&
226
+ (node.arguments[3].hash_type? &&
227
+ node.arguments[3].pairs.size == 1))
228
+
229
+ corrector.replace(
230
+ range_for_method_and_optional_limit(node),
231
+ "add_column #{node.arguments[0].source}, #{node.arguments[1].source}, :bigint"
232
+ )
233
+ end
234
+ end
235
+
236
+ def correct_add_reference_method(node, corrector)
237
+ # There's only one hash pair (:type) or only two: :type and :limit
238
+ return unless node.arguments.size == 3 && node.arguments[2].hash_type?
239
+
240
+ hash_pairs = node.arguments[2].pairs
241
+ keys = hash_pairs.map { |pair| pair.key.source }
242
+
243
+ if keys.size == 1 ||
244
+ (keys.size == 2 && keys.include?("limit"))
245
+
246
+ corrector.replace(
247
+ range_for_method_and_optional_limit(node),
248
+ "#{node.method_name} #{node.arguments[0].source}, #{node.arguments[1].source}"
249
+ )
250
+ end
251
+ end
252
+
253
+ def range_for_method_and_optional_limit(node)
254
+ Parser::Source::Range.new(
255
+ node.source_range.source_buffer,
256
+ node.selector.begin_pos,
257
+ node.source_range.end_pos
258
+ )
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ezcater_rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.2
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ezCater, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-12 00:00:00.000000000 Z
11
+ date: 2025-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -205,6 +205,7 @@ files:
205
205
  - Gemfile
206
206
  - LICENSE.txt
207
207
  - README.md
208
+ - bin/check_configs.sh
208
209
  - bin/circle_rubocop.rb
209
210
  - conf/rubocop.yml
210
211
  - conf/rubocop_gem.yml
@@ -217,6 +218,7 @@ files:
217
218
  - lib/rubocop/cop/ezcater/feature_flag_active.rb
218
219
  - lib/rubocop/cop/ezcater/feature_flag_name_valid.rb
219
220
  - lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb
221
+ - lib/rubocop/cop/ezcater/migration/bigint_foreign_key.rb
220
222
  - lib/rubocop/cop/ezcater/rails_configuration.rb
221
223
  - lib/rubocop/cop/ezcater/rails_env.rb
222
224
  - lib/rubocop/cop/ezcater/rails_top_level_sql_execute.rb