ezcater_rubocop 7.1.2 → 8.0.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: 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