summaryrefslogtreecommitdiff
path: root/rubocop
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /rubocop
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
downloadgitlab-ce-85dc423f7090da0a52c73eb66faf22ddb20efff9.tar.gz
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'rubocop')
-rw-r--r--rubocop/cop/avoid_route_redirect_leading_slash.rb4
-rw-r--r--rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb51
-rw-r--r--rubocop/cop/gitlab/bulk_insert.rb2
-rw-r--r--rubocop/cop/gitlab/except.rb23
-rw-r--r--rubocop/cop/gitlab/intersect.rb23
-rw-r--r--rubocop/cop/gitlab/rails_logger.rb35
-rw-r--r--rubocop/cop/migration/complex_indexes_require_name.rb61
-rw-r--r--rubocop/cop/migration/create_table_with_foreign_keys.rb99
-rw-r--r--rubocop/cop/migration/refer_to_index_by_name.rb67
-rw-r--r--rubocop/cop/migration/safer_boolean_column.rb2
-rw-r--r--rubocop/cop/rspec/timecop_freeze.rb41
-rw-r--r--rubocop/cop/rspec/top_level_describe_path.rb2
-rw-r--r--rubocop/cop/static_translation_definition.rb18
-rw-r--r--rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb20
-rw-r--r--rubocop/migration_helpers.rb19
-rw-r--r--rubocop/routes_under_scope.rb9
-rw-r--r--rubocop/rubocop-migrations.yml1
-rw-r--r--rubocop/rubocop-usage-data.yml18
18 files changed, 457 insertions, 38 deletions
diff --git a/rubocop/cop/avoid_route_redirect_leading_slash.rb b/rubocop/cop/avoid_route_redirect_leading_slash.rb
index d66e434dc9c..0b0dc7d3d33 100644
--- a/rubocop/cop/avoid_route_redirect_leading_slash.rb
+++ b/rubocop/cop/avoid_route_redirect_leading_slash.rb
@@ -7,10 +7,10 @@ module RuboCop
#
# @example
# # bad
- # root to: redirect('/-/instance/statistics/dev_ops_score')
+ # root to: redirect('/-/autocomplete/users')
#
# # good
- # root to: redirect('-/instance/statistics/dev_ops_score')
+ # root to: redirect('-/autocomplete/users')
#
class AvoidRouteRedirectLeadingSlash < RuboCop::Cop::Cop
diff --git a/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb b/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb
new file mode 100644
index 00000000000..599371aa5a1
--- /dev/null
+++ b/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # This cop checks for `UploadedFile.from_params` usage.
+ # See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route
+ #
+ # @example
+ #
+ # # bad
+ # class MyAwfulApi < Grape::API::Instance
+ # params do
+ # optional 'file.path', type: String
+ # optional 'file.name', type: String
+ # optional 'file.type', type: String
+ # optional 'file.size', type: Integer
+ # optional 'file.md5', type: String
+ # optional 'file.sha1', type: String
+ # optional 'file.sha256', type: String
+ # end
+ # put '/files' do
+ # uploaded_file = UploadedFile.from_params(params, :file, FileUploader.workhorse_local_upload_path)
+ # end
+ # end
+ #
+ # # good
+ # class MyMuchBetterApi < Grape::API::Instance
+ # params do
+ # requires :file, type: ::API::Validations::Types::WorkhorseFile
+ # end
+ # put '/files' do
+ # uploaded_file = declared_params[:file]
+ # end
+ # end
+ class AvoidUploadedFileFromParams < RuboCop::Cop::Cop
+ MSG = 'Use the `UploadedFile` set by `multipart.rb` instead of calling `UploadedFile.from_params` directly. See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route'
+
+ def_node_matcher :calling_uploaded_file_from_params?, <<~PATTERN
+ (send (const nil? :UploadedFile) :from_params ...)
+ PATTERN
+
+ def on_send(node)
+ return unless calling_uploaded_file_from_params?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/bulk_insert.rb b/rubocop/cop/gitlab/bulk_insert.rb
index c03ffbe0b2a..83d879ddf44 100644
--- a/rubocop/cop/gitlab/bulk_insert.rb
+++ b/rubocop/cop/gitlab/bulk_insert.rb
@@ -9,7 +9,7 @@ module RuboCop
MSG = 'Use the `BulkInsertSafe` concern, instead of using `Gitlab::Database.bulk_insert`. See https://docs.gitlab.com/ee/development/insert_into_tables_in_batches.html'
def_node_matcher :raw_union?, <<~PATTERN
- (send (const (const nil? :Gitlab) :Database) :bulk_insert ...)
+ (send (const (const _ :Gitlab) :Database) :bulk_insert ...)
PATTERN
def on_send(node)
diff --git a/rubocop/cop/gitlab/except.rb b/rubocop/cop/gitlab/except.rb
new file mode 100644
index 00000000000..24da6962457
--- /dev/null
+++ b/rubocop/cop/gitlab/except.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that disallows the use of `Gitlab::SQL::Except`, in favour of using
+ # the `FromExcept` module.
+ class Except < RuboCop::Cop::Cop
+ MSG = 'Use the `FromExcept` concern, instead of using `Gitlab::SQL::Except` directly'
+
+ def_node_matcher :raw_except?, <<~PATTERN
+ (send (const (const (const nil? :Gitlab) :SQL) :Except) :new ...)
+ PATTERN
+
+ def on_send(node)
+ return unless raw_except?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/intersect.rb b/rubocop/cop/gitlab/intersect.rb
new file mode 100644
index 00000000000..4b61073b804
--- /dev/null
+++ b/rubocop/cop/gitlab/intersect.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that disallows the use of `Gitlab::SQL::Intersect`, in favour of using
+ # the `FromIntersect` module.
+ class Intersect < RuboCop::Cop::Cop
+ MSG = 'Use the `FromIntersect` concern, instead of using `Gitlab::SQL::Intersect` directly'
+
+ def_node_matcher :raw_intersect?, <<~PATTERN
+ (send (const (const (const nil? :Gitlab) :SQL) :Intersect) :new ...)
+ PATTERN
+
+ def on_send(node)
+ return unless raw_intersect?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/rails_logger.rb b/rubocop/cop/gitlab/rails_logger.rb
index d1a06a9a100..ad35d2ccfbb 100644
--- a/rubocop/cop/gitlab/rails_logger.rb
+++ b/rubocop/cop/gitlab/rails_logger.rb
@@ -8,7 +8,7 @@ module RuboCop
class RailsLogger < ::RuboCop::Cop::Cop
include CodeReuseHelpers
- # This cop checks for the Rails.logger in the codebase
+ # This cop checks for the Rails.logger log methods in the codebase
#
# @example
#
@@ -17,34 +17,29 @@ module RuboCop
#
# # good
# Gitlab::AppLogger.error("Project %{project_path} could not be saved" % { project_path: project.full_path })
+ #
+ # # OK
+ # Rails.logger.level
MSG = 'Use a structured JSON logger instead of `Rails.logger`. ' \
'https://docs.gitlab.com/ee/development/logging.html'.freeze
- def_node_matcher :rails_logger?, <<~PATTERN
- (send (const nil? :Rails) :logger ... )
- PATTERN
+ # See supported log methods:
+ # https://ruby-doc.org/stdlib-2.6.6/libdoc/logger/rdoc/Logger.html
+ LOG_METHODS = %i[debug error fatal info warn].freeze
+ LOG_METHODS_PATTERN = LOG_METHODS.map(&:inspect).join(' ').freeze
- WHITELISTED_DIRECTORIES = %w[
- spec
- ].freeze
+ def_node_matcher :rails_logger_log?, <<~PATTERN
+ (send
+ (send (const nil? :Rails) :logger)
+ {#{LOG_METHODS_PATTERN}} ...
+ )
+ PATTERN
def on_send(node)
- return if in_whitelisted_directory?(node)
- return unless rails_logger?(node)
+ return unless rails_logger_log?(node)
add_offense(node, location: :expression)
end
-
- def in_whitelisted_directory?(node)
- path = file_path_for_node(node)
-
- WHITELISTED_DIRECTORIES.any? do |directory|
- path.start_with?(
- File.join(rails_root, directory),
- File.join(rails_root, 'ee', directory)
- )
- end
- end
end
end
end
diff --git a/rubocop/cop/migration/complex_indexes_require_name.rb b/rubocop/cop/migration/complex_indexes_require_name.rb
new file mode 100644
index 00000000000..82deb36716d
--- /dev/null
+++ b/rubocop/cop/migration/complex_indexes_require_name.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class ComplexIndexesRequireName < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'indexes added with custom options must be explicitly named'
+
+ def_node_matcher :match_create_table_index_with_options, <<~PATTERN
+ (send _ {:index } _ (hash $...))
+ PATTERN
+
+ def_node_matcher :match_add_index_with_options, <<~PATTERN
+ (send _ {:add_index :add_concurrent_index} _ _ (hash $...))
+ PATTERN
+
+ def_node_matcher :name_option?, <<~PATTERN
+ (pair {(sym :name) (str "name")} _)
+ PATTERN
+
+ def_node_matcher :unique_option?, <<~PATTERN
+ (pair {(:sym :unique) (str "unique")} _)
+ PATTERN
+
+ def on_def(node)
+ return unless in_migration?(node)
+
+ node.each_descendant(:send) do |send_node|
+ next unless create_table_with_index_offense?(send_node) || add_index_offense?(send_node)
+
+ add_offense(send_node, location: :selector)
+ end
+ end
+
+ private
+
+ def create_table_with_index_offense?(send_node)
+ match_create_table_index_with_options(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def add_index_offense?(send_node)
+ match_add_index_with_options(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def needs_name_option?(option_nodes)
+ return false if only_unique_option?(option_nodes)
+
+ option_nodes.none? { |node| name_option?(node) }
+ end
+
+ def only_unique_option?(option_nodes)
+ option_nodes.size == 1 && unique_option?(option_nodes.first)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/create_table_with_foreign_keys.rb b/rubocop/cop/migration/create_table_with_foreign_keys.rb
new file mode 100644
index 00000000000..01cab032049
--- /dev/null
+++ b/rubocop/cop/migration/create_table_with_foreign_keys.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class CreateTableWithForeignKeys < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'Creating a table with more than one foreign key at once violates our migration style guide. ' \
+ 'For more details check the https://docs.gitlab.com/ce/development/migration_style_guide.html#examples'
+
+ def_node_matcher :create_table_with_block?, <<~PATTERN
+ (block
+ (send nil? :create_table ...)
+ (args (arg _var))
+ _)
+ PATTERN
+
+ def_node_search :belongs_to_and_references, <<~PATTERN
+ (send _var {:references :belongs_to} $...)
+ PATTERN
+
+ def_node_search :foreign_key_options, <<~PATTERN
+ (_pair
+ {(sym :foreign_key) (str "foreign_key")}
+ {(hash _) (true)}
+ )
+ PATTERN
+
+ def_node_search :to_table, <<~PATTERN
+ (_pair
+ {(sym :to_table) (str "to_table")} {(sym $...) (str $...)}
+ )
+ PATTERN
+
+ def_node_matcher :argument_name?, <<~PATTERN
+ {(sym $...) (str $...)}
+ PATTERN
+
+ def_node_search :standalone_foreign_keys, <<~PATTERN
+ (send _var :foreign_key $...)
+ PATTERN
+
+ def on_send(node)
+ return unless in_migration?(node)
+ return unless node.command?(:create_table)
+ return unless create_table_with_block?(node.parent)
+
+ add_offense(node) if violates?(node.parent)
+ end
+
+ private
+
+ def violates?(node)
+ tables = all_target_tables(node).uniq
+
+ tables.length > 1 && !(tables & high_traffic_tables).empty?
+ end
+
+ def all_target_tables(node)
+ belongs_to_and_references_foreign_key_targets(node) + standalone_foreign_key_targets(node)
+ end
+
+ def belongs_to_and_references_foreign_key_targets(node)
+ belongs_to_and_references(node).select { |candidate| has_fk_option?(candidate) }
+ .flat_map { |definition| definition_to_table_names(definition) }
+ .compact
+ end
+
+ def standalone_foreign_key_targets(node)
+ standalone_foreign_keys(node).flat_map { |definition| definition_to_table_names(definition) }
+ .compact
+ end
+
+ def has_fk_option?(candidate)
+ foreign_key_options(candidate.last).first
+ end
+
+ def definition_to_table_names(definition)
+ table_name_from_options(definition.last) || arguments_to_table_names(definition)
+ end
+
+ def table_name_from_options(options)
+ to_table(options).to_a.first&.first
+ end
+
+ def arguments_to_table_names(arguments)
+ arguments.select { |argument| argument_name?(argument) }
+ .map(&:value)
+ .map(&:to_s)
+ .map(&:pluralize)
+ .map(&:to_sym)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/refer_to_index_by_name.rb b/rubocop/cop/migration/refer_to_index_by_name.rb
new file mode 100644
index 00000000000..fbf3c0d7030
--- /dev/null
+++ b/rubocop/cop/migration/refer_to_index_by_name.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class ReferToIndexByName < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'migration methods that refer to existing indexes must do so by name'
+
+ def_node_matcher :match_index_exists, <<~PATTERN
+ (send _ :index_exists? _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :match_remove_index, <<~PATTERN
+ (send _ :remove_index _ $_)
+ PATTERN
+
+ def_node_matcher :match_remove_concurrent_index, <<~PATTERN
+ (send _ :remove_concurrent_index _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :name_option?, <<~PATTERN
+ (pair {(sym :name) (str "name")} _)
+ PATTERN
+
+ def on_def(node)
+ return unless in_migration?(node)
+
+ node.each_descendant(:send) do |send_node|
+ next unless index_exists_offense?(send_node) || removing_index_offense?(send_node)
+
+ add_offense(send_node, location: :selector)
+ end
+ end
+
+ private
+
+ def index_exists_offense?(send_node)
+ match_index_exists(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def removing_index_offense?(send_node)
+ remove_index_offense?(send_node) || remove_concurrent_index_offense?(send_node)
+ end
+
+ def remove_index_offense?(send_node)
+ match_remove_index(send_node) do |column_or_options_node|
+ break true unless column_or_options_node.type == :hash
+
+ column_or_options_node.children.none? { |pair| name_option?(pair) }
+ end
+ end
+
+ def remove_concurrent_index_offense?(send_node)
+ match_remove_concurrent_index(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def needs_name_option?(option_nodes)
+ option_nodes.empty? || option_nodes.first.none? { |node| name_option?(node) }
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/safer_boolean_column.rb b/rubocop/cop/migration/safer_boolean_column.rb
index 25aaf42d00e..22d5d37a83d 100644
--- a/rubocop/cop/migration/safer_boolean_column.rb
+++ b/rubocop/cop/migration/safer_boolean_column.rb
@@ -37,7 +37,7 @@ module RuboCop
table, _, type = matched.to_a.take(3).map(&:children).map(&:first)
opts = matched[3]
- return unless WHITELISTED_TABLES.include?(table) && type == :boolean
+ return unless SMALL_TABLES.include?(table) && type == :boolean
no_default = no_default?(opts)
nulls_allowed = nulls_allowed?(opts)
diff --git a/rubocop/cop/rspec/timecop_freeze.rb b/rubocop/cop/rspec/timecop_freeze.rb
new file mode 100644
index 00000000000..508b5df7c7f
--- /dev/null
+++ b/rubocop/cop/rspec/timecop_freeze.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module RSpec
+ # This cop checks for `Timecop.freeze` usage in specs.
+ #
+ # @example
+ #
+ # # bad
+ # Timecop.freeze(Time.current) { example.run }
+ #
+ # # good
+ # freeze_time(Time.current) { example.run }
+ #
+ class TimecopFreeze < RuboCop::Cop::Cop
+ include MatchRange
+ MESSAGE = 'Do not use `Timecop.freeze`, use `freeze_time` instead. ' \
+ 'See https://gitlab.com/gitlab-org/gitlab/-/issues/214432 for more info.'
+
+ def_node_matcher :timecop_freeze?, <<~PATTERN
+ (send (const nil? :Timecop) :freeze ?_)
+ PATTERN
+
+ def on_send(node)
+ return unless timecop_freeze?(node)
+
+ add_offense(node, location: :expression, message: MESSAGE)
+ end
+
+ def autocorrect(node)
+ -> (corrector) do
+ each_match_range(node.source_range, /^(Timecop\.freeze)/) do |match_range|
+ corrector.replace(match_range, 'freeze_time')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/rspec/top_level_describe_path.rb b/rubocop/cop/rspec/top_level_describe_path.rb
index 61796e23af0..3cc1ee8df90 100644
--- a/rubocop/cop/rspec/top_level_describe_path.rb
+++ b/rubocop/cop/rspec/top_level_describe_path.rb
@@ -21,7 +21,7 @@ module RuboCop
private
def acceptable_file_path?(path)
- File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path)
+ File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path) || File.fnmatch?('*/docs_screenshots/*_docs.rb', path)
end
def shared_example?(node)
diff --git a/rubocop/cop/static_translation_definition.rb b/rubocop/cop/static_translation_definition.rb
index 736d8767342..55956d9665b 100644
--- a/rubocop/cop/static_translation_definition.rb
+++ b/rubocop/cop/static_translation_definition.rb
@@ -21,6 +21,8 @@ module RuboCop
method_name = node.children[1]
return unless TRANSLATION_METHODS.include?(method_name)
+ translation_memoized = false
+
node.each_ancestor do |ancestor|
receiver, _ = *ancestor
break if lambda_node?(receiver) # translations defined in lambda nodes should be allowed
@@ -30,6 +32,14 @@ module RuboCop
break
end
+
+ translation_memoized = true if memoization?(ancestor)
+
+ if translation_memoized && class_method_definition?(ancestor)
+ add_offense(node, location: :expression)
+
+ break
+ end
end
end
@@ -38,6 +48,14 @@ module RuboCop
def constant_assignment?(node)
node.type == :casgn
end
+
+ def memoization?(node)
+ node.type == :or_asgn
+ end
+
+ def class_method_definition?(node)
+ node.type == :defs
+ end
end
end
end
diff --git a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
index c10ecbcb4ba..9fdf52dac8b 100644
--- a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
+++ b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
@@ -22,6 +22,7 @@ module RuboCop
def on_send(node)
distinct_count?(node) do |method_name, method_arguments|
next unless method_arguments && method_arguments.length >= 2
+ next if batch_set_to_false?(method_arguments[2])
next if allowed_foreign_key?(method_arguments[1])
add_offense(node, location: :selector, message: format(MSG, method_name))
@@ -31,11 +32,26 @@ module RuboCop
private
def allowed_foreign_key?(key)
- key.type == :sym && allowed_foreign_keys.include?(key.value)
+ [:sym, :str].include?(key.type) && allowed_foreign_keys.include?(key.value.to_s)
end
def allowed_foreign_keys
- cop_config['AllowedForeignKeys'] || []
+ (cop_config['AllowedForeignKeys'] || []).map(&:to_s)
+ end
+
+ def batch_set_to_false?(options)
+ return false unless options.is_a?(RuboCop::AST::HashNode)
+
+ batch_set_to_false = false
+ options.each_pair do |key, value|
+ next unless value.boolean_type? && value.falsey_literal?
+ next unless key.type == :sym && key.value == :batch
+
+ batch_set_to_false = true
+ break
+ end
+
+ batch_set_to_false
end
end
end
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index 355450bbf57..c26ba88f269 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -1,14 +1,13 @@
module RuboCop
# Module containing helper methods for writing migration cops.
module MigrationHelpers
- WHITELISTED_TABLES = %i[
+ # Tables with permanently small number of records
+ SMALL_TABLES = %i[
application_settings
plan_limits
].freeze
- # Blacklisted tables due to:
- # - number of columns (> 50 on GitLab.com as of 03/2020)
- # - number of records
+ # Tables with large number of columns (> 50 on GitLab.com as of 03/2020)
WIDE_TABLES = %i[
users
projects
@@ -21,6 +20,10 @@ module RuboCop
TABLE_METHODS = %i(create_table create_table_if_not_exists change_table).freeze
+ def high_traffic_tables
+ @high_traffic_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'DeniedTables')
+ end
+
# Returns true if the given node originated from the db/migrate directory.
def in_migration?(node)
in_deployment_migration?(node) || in_post_deployment_migration?(node)
@@ -53,5 +56,13 @@ module RuboCop
def dirname(node)
File.dirname(node.location.expression.source_buffer.name)
end
+
+ def rubocop_migrations_config
+ @rubocop_migrations_config ||= YAML.load_file(File.join(rubocop_path, 'rubocop-migrations.yml'))
+ end
+
+ def rubocop_path
+ File.expand_path(__dir__)
+ end
end
end
diff --git a/rubocop/routes_under_scope.rb b/rubocop/routes_under_scope.rb
index 3f049bb09fa..7ffb0fd36f2 100644
--- a/rubocop/routes_under_scope.rb
+++ b/rubocop/routes_under_scope.rb
@@ -12,6 +12,7 @@ module RuboCop
def on_send(node)
return unless route_method?(node)
return unless outside_scope?(node)
+ return if root_route?(node)
add_offense(node)
end
@@ -25,5 +26,13 @@ module RuboCop
def route_method?(node)
ROUTE_METHODS.include?(node.method_name)
end
+
+ def root_route?(node)
+ first_argument = node.arguments.first
+
+ if first_argument.respond_to?(:value)
+ first_argument.value == '/'
+ end
+ end
end
end
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index f8820c0c6aa..a919d570ccc 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -11,6 +11,7 @@ Migration/UpdateLargeTable:
- :ci_stages
- :deployments
- :events
+ - :gitlab_subscriptions
- :issues
- :merge_request_diff_commits
- :merge_request_diff_files
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index 46e8a067431..9f594bc5817 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -4,6 +4,7 @@ UsageData/LargeTable:
- 'lib/gitlab/usage_data.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
NonRelatedClasses:
+ - :ActionMailer::Base
- :Date
- :Feature
- :Gitlab
@@ -37,10 +38,13 @@ UsageData/DistinctCountByLargeForeignKey:
- 'lib/gitlab/usage_data.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
AllowedForeignKeys:
- - :user_id
- - :author_id
- - :creator_id
- - :owner_id
- - :project_id
- - :issue_id
- - :merge_request_id
+ - 'agent_id'
+ - 'author_id'
+ - 'clusters.user_id'
+ - 'creator_id'
+ - 'issue_id'
+ - 'merge_request_id'
+ - 'merge_requests.target_project_id'
+ - 'owner_id'
+ - 'project_id'
+ - 'user_id'