Commit e16b3e3e authored by Mayra Cabrera's avatar Mayra Cabrera

Concentrate whitelisted and blacklisted tables

Whitelisted and blacklisted tables were defined in different rubocop
files, this commit changes that so they can be defined on the
MigrationHelpers.

Specs were updated as well
parent 3089df26
...@@ -14,14 +14,18 @@ class AddStatusToDeployments < ActiveRecord::Migration[4.2] ...@@ -14,14 +14,18 @@ class AddStatusToDeployments < ActiveRecord::Migration[4.2]
# Ideally, `status` column should not have default value because it should be leveraged by state machine (i.e. application level). # Ideally, `status` column should not have default value because it should be leveraged by state machine (i.e. application level).
# However, we have to use the default value for avoiding `NOT NULL` violation during the transition period. # However, we have to use the default value for avoiding `NOT NULL` violation during the transition period.
# The default value should be removed in the future release. # The default value should be removed in the future release.
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default(:deployments, # rubocop:disable Migration/AddColumnWithDefault add_column_with_default(:deployments,
:status, :status,
:integer, :integer,
limit: 2, limit: 2,
default: DEPLOYMENT_STATUS_SUCCESS, default: DEPLOYMENT_STATUS_SUCCESS,
allow_null: false) allow_null: false)
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable
def down def down
remove_column(:deployments, :status) remove_column(:deployments, :status)
......
...@@ -7,10 +7,12 @@ class AddMergeTrainEnabledToCiCdSettings < ActiveRecord::Migration[5.1] ...@@ -7,10 +7,12 @@ class AddMergeTrainEnabledToCiCdSettings < ActiveRecord::Migration[5.1]
disable_ddl_transaction! disable_ddl_transaction!
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable # rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default :project_ci_cd_settings, :merge_trains_enabled, :boolean, default: false, allow_null: false add_column_with_default :project_ci_cd_settings, :merge_trains_enabled, :boolean, default: false, allow_null: false
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable # rubocop:enable Migration/UpdateLargeTable
def down def down
......
...@@ -7,9 +7,13 @@ class AddVariableTypeToCiPipelineVariables < ActiveRecord::Migration[5.0] ...@@ -7,9 +7,13 @@ class AddVariableTypeToCiPipelineVariables < ActiveRecord::Migration[5.0]
DOWNTIME = false DOWNTIME = false
ENV_VAR_VARIABLE_TYPE = 1 ENV_VAR_VARIABLE_TYPE = 1
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default(:ci_pipeline_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE) # rubocop:disable Migration/AddColumnWithDefault add_column_with_default(:ci_pipeline_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE)
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable
def down def down
remove_column(:ci_pipeline_variables, :variable_type) remove_column(:ci_pipeline_variables, :variable_type)
......
...@@ -7,9 +7,13 @@ class AddDeploymentEventsToServices < ActiveRecord::Migration[5.0] ...@@ -7,9 +7,13 @@ class AddDeploymentEventsToServices < ActiveRecord::Migration[5.0]
disable_ddl_transaction! disable_ddl_transaction!
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default(:services, :deployment_events, :boolean, default: false, allow_null: false) add_column_with_default(:services, :deployment_events, :boolean, default: false, allow_null: false)
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable
def down def down
remove_column(:services, :deployment_events) remove_column(:services, :deployment_events)
......
...@@ -7,9 +7,13 @@ class AddCommentActionsToServices < ActiveRecord::Migration[5.2] ...@@ -7,9 +7,13 @@ class AddCommentActionsToServices < ActiveRecord::Migration[5.2]
disable_ddl_transaction! disable_ddl_transaction!
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default(:services, :comment_on_event_enabled, :boolean, default: true) add_column_with_default(:services, :comment_on_event_enabled, :boolean, default: true)
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable
def down def down
remove_column(:services, :comment_on_event_enabled) remove_column(:services, :comment_on_event_enabled)
......
...@@ -7,9 +7,13 @@ class AddInstanceToServices < ActiveRecord::Migration[6.0] ...@@ -7,9 +7,13 @@ class AddInstanceToServices < ActiveRecord::Migration[6.0]
disable_ddl_transaction! disable_ddl_transaction!
# rubocop:disable Migration/AddColumnWithDefault
# rubocop:disable Migration/UpdateLargeTable
def up def up
add_column_with_default(:services, :instance, :boolean, default: false) add_column_with_default(:services, :instance, :boolean, default: false)
end end
# rubocop:enable Migration/AddColumnWithDefault
# rubocop:enable Migration/UpdateLargeTable
def down def down
remove_column(:services, :instance) remove_column(:services, :instance)
......
...@@ -7,6 +7,7 @@ class ReaddTemplateColumnToServices < ActiveRecord::Migration[6.0] ...@@ -7,6 +7,7 @@ class ReaddTemplateColumnToServices < ActiveRecord::Migration[6.0]
disable_ddl_transaction! disable_ddl_transaction!
# rubocop:disable Migration/UpdateLargeTable
def up def up
return if column_exists? :services, :template return if column_exists? :services, :template
...@@ -16,6 +17,7 @@ class ReaddTemplateColumnToServices < ActiveRecord::Migration[6.0] ...@@ -16,6 +17,7 @@ class ReaddTemplateColumnToServices < ActiveRecord::Migration[6.0]
# of `template`, we would look for entries with `project_id IS NULL`. # of `template`, we would look for entries with `project_id IS NULL`.
add_column_with_default :services, :template, :boolean, default: false, allow_null: true add_column_with_default :services, :template, :boolean, default: false, allow_null: true
end end
# rubocop:enable Migration/UpdateLargeTable
def down def down
# NOP since the column is expected to exist # NOP since the column is expected to exist
......
...@@ -8,11 +8,6 @@ module RuboCop ...@@ -8,11 +8,6 @@ module RuboCop
class AddColumn < RuboCop::Cop::Cop class AddColumn < RuboCop::Cop::Cop
include MigrationHelpers include MigrationHelpers
WHITELISTED_TABLES = %i[
application_settings
plan_limits
].freeze
MSG = '`add_column` with a default value requires downtime, ' \ MSG = '`add_column` with a default value requires downtime, ' \
'use `add_column_with_default` instead'.freeze 'use `add_column_with_default` instead'.freeze
......
...@@ -10,38 +10,6 @@ module RuboCop ...@@ -10,38 +10,6 @@ module RuboCop
class AddColumnWithDefault < RuboCop::Cop::Cop class AddColumnWithDefault < RuboCop::Cop::Cop
include MigrationHelpers include MigrationHelpers
# Tables >= 10 GB on GitLab.com as of 02/2020
BLACKLISTED_TABLES = %i[
audit_events
ci_build_trace_sections
ci_builds
ci_builds_metadata
ci_job_artifacts
ci_pipeline_variables
ci_pipelines
ci_stages
deployments
events
issues
merge_request_diff_commits
merge_request_diff_files
merge_request_diffs
merge_request_metrics
merge_requests
note_diff_files
notes
project_authorizations
projects
push_event_payloads
resource_label_events
sent_notifications
system_note_metadata
taggings
todos
users
web_hook_logs
].freeze
MSG = '`add_column_with_default` without `allow_null: true` may cause prolonged lock situations and downtime, ' \ MSG = '`add_column_with_default` without `allow_null: true` may cause prolonged lock situations and downtime, ' \
'see https://gitlab.com/gitlab-org/gitlab/issues/38060'.freeze 'see https://gitlab.com/gitlab-org/gitlab/issues/38060'.freeze
......
...@@ -23,10 +23,6 @@ module RuboCop ...@@ -23,10 +23,6 @@ module RuboCop
NULL_OFFENSE = 'Boolean columns on the `%s` table should disallow nulls.'.freeze NULL_OFFENSE = 'Boolean columns on the `%s` table should disallow nulls.'.freeze
DEFAULT_AND_NULL_OFFENSE = 'Boolean columns on the `%s` table should have a default and should disallow nulls. You may wish to use `add_column_with_default`.'.freeze DEFAULT_AND_NULL_OFFENSE = 'Boolean columns on the `%s` table should have a default and should disallow nulls. You may wish to use `add_column_with_default`.'.freeze
SMALL_TABLES = %i[
application_settings
].freeze
def_node_matcher :add_column?, <<~PATTERN def_node_matcher :add_column?, <<~PATTERN
(send nil? :add_column $...) (send nil? :add_column $...)
PATTERN PATTERN
...@@ -41,7 +37,7 @@ module RuboCop ...@@ -41,7 +37,7 @@ module RuboCop
table, _, type = matched.to_a.take(3).map(&:children).map(&:first) table, _, type = matched.to_a.take(3).map(&:children).map(&:first)
opts = matched[3] opts = matched[3]
return unless SMALL_TABLES.include?(table) && type == :boolean return unless WHITELISTED_TABLES.include?(table) && type == :boolean
no_default = no_default?(opts) no_default = no_default?(opts)
nulls_allowed = nulls_allowed?(opts) nulls_allowed = nulls_allowed?(opts)
......
...@@ -19,26 +19,6 @@ module RuboCop ...@@ -19,26 +19,6 @@ module RuboCop
'complete, and should be avoided unless absolutely ' \ 'complete, and should be avoided unless absolutely ' \
'necessary'.freeze 'necessary'.freeze
LARGE_TABLES = %i[
ci_build_trace_sections
ci_builds
ci_job_artifacts
ci_pipelines
ci_stages
events
issues
merge_request_diff_commits
merge_request_diff_files
merge_request_diffs
merge_requests
namespaces
notes
projects
project_ci_cd_settings
routes
users
].freeze
BATCH_UPDATE_METHODS = %w[ BATCH_UPDATE_METHODS = %w[
:add_column_with_default :add_column_with_default
:change_column_type_concurrently :change_column_type_concurrently
...@@ -59,7 +39,7 @@ module RuboCop ...@@ -59,7 +39,7 @@ module RuboCop
update_method = matches.first update_method = matches.first
table = matches.last.to_a.first table = matches.last.to_a.first
return unless LARGE_TABLES.include?(table) return unless BLACKLISTED_TABLES.include?(table)
add_offense(node, location: :expression, message: format(MSG, update_method, table)) add_offense(node, location: :expression, message: format(MSG, update_method, table))
end end
......
module RuboCop module RuboCop
# Module containing helper methods for writing migration cops. # Module containing helper methods for writing migration cops.
module MigrationHelpers module MigrationHelpers
WHITELISTED_TABLES = %i[
application_settings
plan_limits
].freeze
# Blacklisted table due to:
# - size in GB (>= 10 GB on GitLab.com as of 02/2020)
# - number of records
BLACKLISTED_TABLES = %i[
audit_events
ci_build_trace_sections
ci_builds
ci_builds_metadata
ci_job_artifacts
ci_pipeline_variables
ci_pipelines
ci_stages
deployments
events
issues
merge_request_diff_commits
merge_request_diff_files
merge_request_diffs
merge_request_metrics
merge_requests
namespaces
note_diff_files
notes
project_authorizations
projects
project_ci_cd_settings
push_event_payloads
resource_label_events
routes
sent_notifications
services
system_note_metadata
taggings
todos
users
web_hook_logs
].freeze
# Returns true if the given node originated from the db/migrate directory. # Returns true if the given node originated from the db/migrate directory.
def in_migration?(node) def in_migration?(node)
dirname(node).end_with?('db/migrate', 'db/geo/migrate') || in_post_deployment_migration?(node) dirname(node).end_with?('db/migrate', 'db/geo/migrate') || in_post_deployment_migration?(node)
......
...@@ -17,7 +17,7 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do ...@@ -17,7 +17,7 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do
allow(cop).to receive(:in_migration?).and_return(true) allow(cop).to receive(:in_migration?).and_return(true)
end end
described_class::SMALL_TABLES.each do |table| described_class::WHITELISTED_TABLES.each do |table|
context "for the #{table} table" do context "for the #{table} table" do
sources_and_offense = [ sources_and_offense = [
["add_column :#{table}, :column, :boolean, default: true", 'should disallow nulls'], ["add_column :#{table}, :column, :boolean, default: true", 'should disallow nulls'],
...@@ -62,14 +62,14 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do ...@@ -62,14 +62,14 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do
end end
end end
it 'registers no offense for tables not listed in SMALL_TABLES' do it 'registers no offense for tables not listed in WHITELISTED_TABLES' do
inspect_source("add_column :large_table, :column, :boolean") inspect_source("add_column :large_table, :column, :boolean")
expect(cop.offenses).to be_empty expect(cop.offenses).to be_empty
end end
it 'registers no offense for non-boolean columns' do it 'registers no offense for non-boolean columns' do
table = described_class::SMALL_TABLES.sample table = described_class::WHITELISTED_TABLES.sample
inspect_source("add_column :#{table}, :column, :string") inspect_source("add_column :#{table}, :column, :string")
expect(cop.offenses).to be_empty expect(cop.offenses).to be_empty
...@@ -78,7 +78,7 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do ...@@ -78,7 +78,7 @@ describe RuboCop::Cop::Migration::SaferBooleanColumn do
context 'outside of migration' do context 'outside of migration' do
it 'registers no offense' do it 'registers no offense' do
table = described_class::SMALL_TABLES.sample table = described_class::WHITELISTED_TABLES.sample
inspect_source("add_column :#{table}, :column, :boolean") inspect_source("add_column :#{table}, :column, :boolean")
expect(cop.offenses).to be_empty expect(cop.offenses).to be_empty
......
...@@ -18,7 +18,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do ...@@ -18,7 +18,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do
end end
shared_examples 'large tables' do |update_method| shared_examples 'large tables' do |update_method|
described_class::LARGE_TABLES.each do |table| described_class::BLACKLISTED_TABLES.each do |table|
it "registers an offense for the #{table} table" do it "registers an offense for the #{table} table" do
inspect_source("#{update_method} :#{table}, :column, default: true") inspect_source("#{update_method} :#{table}, :column, default: true")
...@@ -53,7 +53,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do ...@@ -53,7 +53,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do
end end
it 'registers no offense for non-blacklisted methods' do it 'registers no offense for non-blacklisted methods' do
table = described_class::LARGE_TABLES.sample table = described_class::BLACKLISTED_TABLES.sample
inspect_source("some_other_method :#{table}, :column, default: true") inspect_source("some_other_method :#{table}, :column, default: true")
...@@ -62,7 +62,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do ...@@ -62,7 +62,7 @@ describe RuboCop::Cop::Migration::UpdateLargeTable do
end end
context 'outside of migration' do context 'outside of migration' do
let(:table) { described_class::LARGE_TABLES.sample } let(:table) { described_class::BLACKLISTED_TABLES.sample }
it 'registers no offense for add_column_with_default' do it 'registers no offense for add_column_with_default' do
inspect_source("add_column_with_default :#{table}, :column, default: true") inspect_source("add_column_with_default :#{table}, :column, default: true")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment