blob: db8fc079774b81384809613824f7a45d73e9b120 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# frozen_string_literal: true
module RuboCop
# Module containing helper methods for writing migration cops.
module MigrationHelpers
# Tables with permanently small number of records
SMALL_TABLES = %i[
application_settings
plan_limits
].freeze
# Tables with large number of columns (> 50 on GitLab.com as of 01/2021)
WIDE_TABLES = %i[
ci_builds
namespaces
projects
users
].freeze
# List of helpers that add new columns, either directly (ADD_COLUMN_METHODS)
# or through a create/alter table (TABLE_METHODS)
ADD_COLUMN_METHODS = %i(add_column change_column_type_concurrently).freeze
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', 'HighTrafficTables')
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)
end
def in_background_migration?(node)
filepath(node).include?('/lib/gitlab/background_migration/') ||
in_ee_background_migration?(node)
end
def in_ee_background_migration?(node)
filepath(node).include?('/ee/lib/ee/gitlab/background_migration/')
end
def in_deployment_migration?(node)
dirname(node).end_with?('db/migrate', 'db/geo/migrate')
end
def in_post_deployment_migration?(node)
dirname(node).end_with?('db/post_migrate', 'db/geo/post_migrate')
end
# Returns true if we've defined an 'EnforcedSince' variable in rubocop.yml and the migration version
# is greater.
def time_enforced?(node)
return false unless enforced_since
version(node) > enforced_since
end
def version(node)
File.basename(node.location.expression.source_buffer.name).split('_').first.to_i
end
# Returns true if a column definition is for an array, like { array: true }
#
# @example
# add_column :table, :ids, :integer, array: true, default: []
#
# rubocop:disable Lint/BooleanSymbol
def array_column?(node)
node.each_descendant(:pair).any? do |pair_node|
pair_node.child_nodes[0].sym_type? && # Searching for a RuboCop::AST::SymbolNode
pair_node.child_nodes[0].value == :array && # Searching for a (pair (sym :array) (true)) node
pair_node.child_nodes[1].type == :true # RuboCop::AST::Node uses symbols for types, even when that is a :true
end
end
# rubocop:enable Lint/BooleanSymbol
private
def filepath(node)
node.location.expression.source_buffer.name
end
def dirname(node)
File.dirname(filepath(node))
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
def enforced_since
@enforced_since ||= config.for_cop(name)['EnforcedSince']
end
end
end
|