Commit f291aae8 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'check-min-schema-migrate' into 'master'

Ensure we are on a supported version before migrating

See merge request gitlab-org/gitlab-ce!29882
parents df717efa af284655
......@@ -244,7 +244,7 @@ migration:path-pg:
extends: .dedicated-no-docs-and-no-qa-pull-cache-job
script:
- bundle exec rake db:migrate VERSION=20170523121229
- bundle exec rake db:migrate
- bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
dependencies:
- setup-test-env
......
---
title: Added a min schema version check to db:migrate
merge_request: 29882
author:
type: added
......@@ -85,3 +85,21 @@ eric 37709 0.0 0.0 2518640 7524 s006 S Wed11AM 0:00.79 s
$ kill 87304
$ kill 37709
```
### db:migrate `database version is too old to be migrated` error
Users receive this error when `db:migrate` detects that the current schema version
is older than the `MIN_SCHEMA_VERSION` defined in the `Gitlab::Database` library
module.
Over time we cleanup/combine old migrations in the codebase, so it is not always
possible to migrate GitLab from every previous version.
In some cases you may want to bypass this check. For example, if you were on a version
of GitLab schema later than the `MIN_SCHEMA_VERSION`, and then rolled back the
to an older migration, from before. In this case, in order to migrate forward again,
you should set the `SKIP_SCHEMA_VERSION_CHECK` environment variable.
```sh
bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
```
......@@ -13,6 +13,11 @@ module Gitlab
# https://dev.mysql.com/doc/refman/5.7/en/datetime.html
MAX_TIMESTAMP_VALUE = Time.at((1 << 31) - 1).freeze
# Minimum schema version from which migrations are supported
# Migrations before this version may have been removed
MIN_SCHEMA_VERSION = 20190506135400
MIN_SCHEMA_GITLAB_VERSION = '11.11.0'
define_histogram :gitlab_database_transaction_seconds do
docstring "Time spent in database transactions, in seconds"
end
......
# frozen_string_literal: true
# Configures the database by running migrate, or by loading the schema and seeding if needed
task schema_version_check: :environment do
next if ENV['SKIP_SCHEMA_VERSION_CHECK']
schema_version = ActiveRecord::Migrator.current_version
# Ensure migrations are being run from a supported schema version
# A schema verison of 0 is a fresh db, and should be safe to run migrations
# But a database with existing migrations less than our min version is not
if schema_version > 0 && schema_version < Gitlab::Database::MIN_SCHEMA_VERSION
raise "Your current database version is too old to be migrated. " \
"You should upgrade to GitLab #{Gitlab::Database::MIN_SCHEMA_GITLAB_VERSION} before moving to this version. " \
"Please see https://docs.gitlab.com/ee/policy/maintenance.html#upgrade-recommendations"
end
end
# Ensure the check is a pre-requisite when running db:migrate
Rake::Task["db:migrate"].enhance [:schema_version_check]
# frozen_string_literal: true
require 'spec_helper'
require 'rake'
describe 'schema_version_check rake task' do
include StubENV
before :all do
Rake.application.rake_require 'active_record/railties/databases'
Rake.application.rake_require 'tasks/migrate/schema_check'
# empty task as env is already loaded
Rake::Task.define_task :environment
end
before do
# Stub out db tasks
allow(ActiveRecord::Tasks::DatabaseTasks).to receive(:migrate).and_return(true)
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(Gitlab::Database::MIN_SCHEMA_VERSION)
# Ensure our check can re-run each time
Rake::Task[:schema_version_check].reenable
end
it 'allows migrations on databases meeting the min schema version requirement' do
expect { run_rake_task('db:migrate') }.not_to raise_error
end
it 'raises an error when schema version is too old to migrate' do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(25)
expect { run_rake_task('db:migrate') }.to raise_error(RuntimeError, /current database version is too old to be migrated/)
end
it 'skips running validation when passed the skip env variable' do
stub_env('SKIP_SCHEMA_VERSION_CHECK', 'true')
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(25)
expect { run_rake_task('db:migrate') }.not_to raise_error
end
it 'allows migrations on fresh databases' do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(0)
expect { run_rake_task('db:migrate') }.not_to raise_error
end
def run_rake_task(task_name)
Rake::Task[task_name].reenable
Rake.application.invoke_task task_name
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