Skip to content
Snippets Groups Projects
Commit 80559de9 authored by Jon Jenkins's avatar Jon Jenkins
Browse files

Add migration cop

To prevent schema-changing methods from being used in post migrations.

Add rspec test for time_enforced migration helper

Add rspec test for new schema change cop
parent a23527fd
No related branches found
No related tags found
1 merge request!102810Add post migration cop to prevent schema additions
......@@ -728,6 +728,12 @@ Migration/PreventIndexCreation:
- !ruby/regexp /\Adb\/(post_)?migrate\/2020.*\.rb\z/
- !ruby/regexp /\Adb\/(post_)?migrate\/20210[1-6].*\.rb\z/
Migration/SchemaChangeMethodsNoPost:
Enabled: true
Include:
- db/post_migrate/*.rb
EnforcedSince: 20221024034228
Gitlab/RailsLogger:
Exclude:
- 'spec/**/*.rb'
......
# frozen_string_literal: true
require_relative '../../migration_helpers'
module RuboCop
module Cop
module Migration
# Cop that checks that no background batched migration helpers are called by regular migrations.
class SchemaChangeMethodsNoPost < RuboCop::Cop::Base
include MigrationHelpers
MSG = "This method may not be used in post migrations."
PATH_TIMESTAMP_MATCHER = /\d{14}/.freeze
FORBIDDEN_METHODS = %w[
add_column
create_table
add_concurrent_foreign_key
].freeze
SYMBOLIZED_MATCHER = FORBIDDEN_METHODS.map { |w| ":#{w}" }.join(' | ')
def_node_matcher :on_forbidden_method, <<~PATTERN
(send nil? {#{SYMBOLIZED_MATCHER}} ...)
PATTERN
def on_send(node)
return unless time_enforced?(node)
on_forbidden_method(node) do
add_offense(node, message: MSG)
end
end
end
end
end
end
......@@ -49,6 +49,14 @@ 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
......@@ -80,5 +88,9 @@ def rubocop_migrations_config
def rubocop_path
File.expand_path(__dir__)
end
def enforced_since
@enforced_since ||= config.for_cop(name)['EnforcedSince']
end
end
end
# frozen_string_literal: true
require 'rubocop_spec_helper'
require_relative '../../../../rubocop/cop/migration/schema_change_methods_no_post'
RSpec.describe RuboCop::Cop::Migration::SchemaChangeMethodsNoPost do
before do
allow(cop).to receive(:time_enforced?).and_return true
end
it "does not allow 'add_column' to be called" do
expect_offense(<<~CODE)
add_column
^^^^^^^^^^ This method may not be used in post migrations.
CODE
end
it "does not allow 'create_table' to be called" do
expect_offense(<<~CODE)
create_table
^^^^^^^^^^^^ This method may not be used in post migrations.
CODE
end
it "does not allow 'delete_batched_background_migration' to be called" do
expect_offense(<<~CODE)
add_concurrent_foreign_key
^^^^^^^^^^^^^^^^^^^^^^^^^^ This method may not be used in post migrations.
CODE
end
end
......@@ -52,4 +52,20 @@
it { expect(fake_cop.version(node)).to eq(20200210184420) }
end
describe '#time_enforced?' do
before do
allow(fake_cop).to receive(:enforced_since).and_return(20221018000000)
end
where(:name, :expected) do
'/gitlab/db/post_migrate/20200210184420_create_operations_scopes_table.rb' | false
'/gitlab/db/post_migrate/20220210184420_create_fake_table.rb' | false
'/gitlab/db/post_migrate/20221019184420_add_id_to_reports_table.rb' | true
end
with_them do
it { expect(fake_cop.time_enforced?(node)).to eq(expected) }
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment