Commit f7b456da authored by Andreas Brandl's avatar Andreas Brandl

Cop for database migration class

parent 137f716c
# frozen_string_literal: true
require_relative '../../migration_helpers'
module RuboCop
module Cop
module Migration
class VersionedMigrationClass < RuboCop::Cop::Cop
include MigrationHelpers
ENFORCED_SINCE = 2021_08_30_00_00_00
MSG_INHERIT = 'Don\'t inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead.'
MSG_INCLUDE = 'Don\'t include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead.'
MIGRATION_CLASS = 'Gitlab::Database::Migration'
def_node_search :includes_helpers?, <<~PATTERN
(send nil? :include
(const
(const
(const nil? :Gitlab) :Database) :MigrationHelpers))
PATTERN
def on_class(node)
return unless relevant_migration?(node)
add_offense(node, location: :expression, message: MSG_INHERIT) unless gitlab_migration_class?(node)
end
def on_send(node)
return unless relevant_migration?(node)
add_offense(node, location: :expression, message: MSG_INCLUDE) if includes_helpers?(node)
end
private
def relevant_migration?(node)
in_migration?(node) && version(node) >= ENFORCED_SINCE
end
def gitlab_migration_class?(node)
superclass(node) == MIGRATION_CLASS
end
def superclass(class_node)
_, *others = class_node.descendants
others.find { |node| node.const_type? && node&.const_name != 'Types' }&.const_name
end
end
end
end
end
# frozen_string_literal: true
require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/migration/versioned_migration_class'
RSpec.describe RuboCop::Cop::Migration::VersionedMigrationClass do
subject(:cop) { described_class.new }
let(:migration) do
<<~SOURCE
class TestMigration < Gitlab::Database::Migration[1.0]
def up
execute 'select 1'
end
def down
execute 'select 1'
end
end
SOURCE
end
shared_examples 'a disabled cop' do
it 'does not register any offenses' do
expect_no_offenses(migration)
end
end
context 'outside of a migration' do
it_behaves_like 'a disabled cop'
end
context 'in migration' do
before do
allow(cop).to receive(:in_migration?).and_return(true)
end
context 'in an old migration' do
before do
allow(cop).to receive(:version).and_return(described_class::ENFORCED_SINCE - 5)
end
it_behaves_like 'a disabled cop'
end
context 'that is recent' do
before do
allow(cop).to receive(:version).and_return(described_class::ENFORCED_SINCE + 5)
end
it 'adds an offence if inheriting from ActiveRecord::Migration' do
expect_offense(<<~RUBY)
class MyMigration < ActiveRecord::Migration[6.1]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead.
end
RUBY
end
it 'adds an offence if including Gitlab::Database::MigrationHelpers directly' do
expect_offense(<<~RUBY)
class MyMigration < Gitlab::Database::Migration[1.0]
include Gitlab::Database::MigrationHelpers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead.
end
RUBY
end
end
end
end
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