Commit 1b063778 authored by Stan Hu's avatar Stan Hu

Prevent EE backport migrations from running if CE is not migrated

If a user upgraded to any GitLab 11.x EE version but switched
back to CE, it's possible the state of the EE tables are not
in the right state for the EE backport migration to work properly.
In particular, there were three tables that had trouble:

* epics
* geo_event_log
* vulnerability_feedback

The EE backport migration would fail while trying to add foreign key
constraints because a key didn't exist in the table. This happens
because any EE migration that add or removed columns between v11.0.0 and
v11.11.3 are not guaranteed to be applied in an CE installation. The EE
backport schema does not individually backport these migrations.

We now check if certain columns are present to determine whether
the backport migration is in the proper state. CE users are required
to upgrade to v11.11.3 EE if they ever installed EE previously before
they can go back to v12.x CE.

Tested via:

```
git checkout -f v11.0.0-ee
bundle exec rake db:reset
git checkout .; git checkout -f v11.11.3
bundle exec rake db:migrate
git checkout .; git checkout -f v12.0.0
bundle exec rake db:migrate
<failure happens>
```
parent 1cffafbf
---
title: Prevent EE backport migrations from running if CE is not migrated
merge_request: 30002
author:
type: fixed
...@@ -117,6 +117,8 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0] ...@@ -117,6 +117,8 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
end end
def up def up
check_schema!
create_missing_tables create_missing_tables
update_appearances update_appearances
...@@ -868,6 +870,52 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0] ...@@ -868,6 +870,52 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
remove_column_if_exists(:geo_nodes, :internal_url) remove_column_if_exists(:geo_nodes, :internal_url)
end end
# Some users may have upgraded to EE at some point but downgraded to
# CE v11.11.3. As a result, their EE tables may not be in the right
# state. Here we check for these such cases and attempt to guide the
# user into recovering from this state by upgrading to v11.11.3 EE
# before installing v12.0.0 CE.
def check_schema!
# The following cases will fail later when this migration attempts
# to add a foreign key for non-existent columns.
columns_to_check = [
[:epics, :parent_id], # Added in GitLab 11.7
[:geo_event_log, :cache_invalidation_event_id], # Added in GitLab 11.4
[:vulnerability_feedback, :merge_request_id] # Added in GitLab 11.9
].freeze
columns_to_check.each do |table, column|
check_ee_columns!(table, column)
end
end
def check_ee_columns!(table, column)
return unless table_exists?(table)
return if column_exists?(table, column)
raise_ee_migration_error!(table, column)
end
def raise_ee_migration_error!(table, column)
message = "Your database is missing the '#{column}' column from the '#{table}' table that is present for GitLab EE."
message +=
if ::Gitlab.ee?
"\nUpgrade your GitLab instance to 11.11.3 EE first!"
else
<<~MSG
Even though it looks like you're running a CE installation, it appears
you may have installed GitLab EE at some point. To migrate to GitLab 12.0:
1. Install GitLab 11.11.3 EE
2. Install GitLab 12.0.x CE
MSG
end
raise Exception.new(message)
end
def create_missing_tables def create_missing_tables
create_table_if_not_exists "approval_merge_request_rule_sources", id: :bigserial do |t| create_table_if_not_exists "approval_merge_request_rule_sources", id: :bigserial do |t|
t.bigint "approval_merge_request_rule_id", null: false t.bigint "approval_merge_request_rule_id", null: false
......
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20190402150158_backport_enterprise_schema.rb')
describe BackportEnterpriseSchema, :migration, schema: 20190329085614 do
include MigrationsHelpers
def drop_if_exists(table)
active_record_base.connection.drop_table(table) if active_record_base.connection.table_exists?(table)
end
describe '#up' do
it 'creates new EE tables' do
migrate!
expect(active_record_base.connection.table_exists?(:epics)).to be true
expect(active_record_base.connection.table_exists?(:geo_nodes)).to be true
end
context 'missing EE columns' do
before do
drop_if_exists(:epics)
active_record_base.connection.create_table "epics" do |t|
t.integer :group_id, null: false, index: true
t.integer :author_id, null: false, index: true
end
end
after do
drop_if_exists(:epics)
end
it 'flags an error' do
expect { migrate! }.to raise_error(/Your database is missing.*that is present for GitLab EE/)
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