Commit 876d4151 authored by Nick Thomas's avatar Nick Thomas

Remove migration specs from 201[4567]

Since the migrations are gone, we don't need these specs either
parent 2f66a7bb
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170713104829_add_foreign_key_to_merge_requests.rb')
describe AddForeignKeyToMergeRequests, :migration do
let(:projects) { table(:projects) }
let(:merge_requests) { table(:merge_requests) }
let(:pipelines) { table(:ci_pipelines) }
before do
projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce')
pipelines.create!(project_id: projects.first.id,
ref: 'some-branch',
sha: 'abc12345')
# merge request without a pipeline
create_merge_request(head_pipeline_id: nil)
# merge request with non-existent pipeline
create_merge_request(head_pipeline_id: 1234)
# merge reqeust with existing pipeline assigned
create_merge_request(head_pipeline_id: pipelines.first.id)
end
it 'correctly adds a foreign key to head_pipeline_id' do
migrate!
expect(merge_requests.first.head_pipeline_id).to be_nil
expect(merge_requests.second.head_pipeline_id).to be_nil
expect(merge_requests.third.head_pipeline_id).to eq pipelines.first.id
end
def create_merge_request(**opts)
merge_requests.create!(source_project_id: projects.first.id,
target_project_id: projects.first.id,
source_branch: 'some-branch',
target_branch: 'master', **opts)
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170508170547_add_head_pipeline_for_each_merge_request.rb')
describe AddHeadPipelineForEachMergeRequest, :migration do
let(:migration) { described_class.new }
let!(:project) { table(:projects).create! }
let!(:other_project) { table(:projects).create! }
let!(:pipeline_1) { table(:ci_pipelines).create!(project_id: project.id, ref: "branch_1") }
let!(:pipeline_2) { table(:ci_pipelines).create!(project_id: other_project.id, ref: "branch_1") }
let!(:pipeline_3) { table(:ci_pipelines).create!(project_id: other_project.id, ref: "branch_1") }
let!(:pipeline_4) { table(:ci_pipelines).create!(project_id: project.id, ref: "branch_2") }
let!(:mr_1) { table(:merge_requests).create!(source_project_id: project.id, target_project_id: project.id, source_branch: "branch_1", target_branch: "target_1") }
let!(:mr_2) { table(:merge_requests).create!(source_project_id: other_project.id, target_project_id: project.id, source_branch: "branch_1", target_branch: "target_2") }
let!(:mr_3) { table(:merge_requests).create!(source_project_id: project.id, target_project_id: project.id, source_branch: "branch_2", target_branch: "master") }
let!(:mr_4) { table(:merge_requests).create!(source_project_id: project.id, target_project_id: project.id, source_branch: "branch_3", target_branch: "master") }
context "#up" do
context "when source_project and source_branch of pipeline are the same of merge request" do
it "sets head_pipeline_id of given merge requests" do
migration.up
expect(mr_1.reload.head_pipeline_id).to eq(pipeline_1.id)
expect(mr_2.reload.head_pipeline_id).to eq(pipeline_3.id)
expect(mr_3.reload.head_pipeline_id).to eq(pipeline_4.id)
expect(mr_4.reload.head_pipeline_id).to be_nil
end
end
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170803090603_calculate_conv_dev_index_percentages.rb')
describe CalculateConvDevIndexPercentages, :migration do
let(:migration) { described_class.new }
let!(:conv_dev_index) do
table(:conversational_development_index_metrics).create!(
leader_issues: 9.256,
leader_notes: 0,
leader_milestones: 16.2456,
leader_boards: 5.2123,
leader_merge_requests: 1.2,
leader_ci_pipelines: 12.1234,
leader_environments: 3.3333,
leader_deployments: 1.200,
leader_projects_prometheus_active: 0.111,
leader_service_desk_issues: 15.891,
instance_issues: 1.234,
instance_notes: 28.123,
instance_milestones: 0,
instance_boards: 3.254,
instance_merge_requests: 0.6,
instance_ci_pipelines: 2.344,
instance_environments: 2.2222,
instance_deployments: 0.771,
instance_projects_prometheus_active: 0.109,
instance_service_desk_issues: 13.345,
percentage_issues: 0,
percentage_notes: 0,
percentage_milestones: 0,
percentage_boards: 0,
percentage_merge_requests: 0,
percentage_ci_pipelines: 0,
percentage_environments: 0,
percentage_deployments: 0,
percentage_projects_prometheus_active: 0,
percentage_service_desk_issues: 0)
end
describe '#up' do
it 'calculates percentages correctly' do
migration.up
conv_dev_index.reload
expect(conv_dev_index.percentage_issues).to be_within(0.1).of(13.3)
expect(conv_dev_index.percentage_notes).to be_zero # leader 0
expect(conv_dev_index.percentage_milestones).to be_zero # instance 0
expect(conv_dev_index.percentage_boards).to be_within(0.1).of(62.4)
expect(conv_dev_index.percentage_merge_requests).to eq(50.0)
expect(conv_dev_index.percentage_ci_pipelines).to be_within(0.1).of(19.3)
expect(conv_dev_index.percentage_environments).to be_within(0.1).of(66.7)
expect(conv_dev_index.percentage_deployments).to be_within(0.1).of(64.2)
expect(conv_dev_index.percentage_projects_prometheus_active).to be_within(0.1).of(98.2)
expect(conv_dev_index.percentage_service_desk_issues).to be_within(0.1).of(84.0)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170613111224_clean_appearance_symlinks.rb')
describe CleanAppearanceSymlinks do
let(:migration) { described_class.new }
let(:test_dir) { File.join(Rails.root, "tmp", "tests", "clean_appearance_test") }
let(:uploads_dir) { File.join(test_dir, "public", "uploads") }
let(:new_uploads_dir) { File.join(uploads_dir, "system") }
let(:original_path) { File.join(new_uploads_dir, 'appearance') }
let(:symlink_path) { File.join(uploads_dir, 'appearance') }
before do
FileUtils.remove_dir(test_dir) if File.directory?(test_dir)
FileUtils.mkdir_p(uploads_dir)
allow(migration).to receive(:base_directory).and_return(test_dir)
allow(migration).to receive(:say)
end
describe "#up" do
before do
FileUtils.mkdir_p(original_path)
FileUtils.ln_s(original_path, symlink_path)
end
it 'removes the symlink' do
migration.up
expect(File.symlink?(symlink_path)).to be(false)
end
end
describe '#down' do
before do
FileUtils.mkdir_p(File.join(original_path))
FileUtils.touch(File.join(original_path, 'dummy.file'))
end
it 'creates a symlink' do
expected_path = File.join(symlink_path, "dummy.file")
migration.down
expect(File.exist?(expected_path)).to be(true)
expect(File.symlink?(symlink_path)).to be(true)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170710083355_clean_stage_id_reference_migration.rb')
describe CleanStageIdReferenceMigration, :migration, :sidekiq, :redis do
let(:migration_class) { 'MigrateBuildStageIdReference' }
let(:migration) { spy('migration') }
before do
allow(Gitlab::BackgroundMigration.const_get(migration_class))
.to receive(:new).and_return(migration)
end
context 'when there are pending background migrations' do
it 'processes pending jobs synchronously' do
Sidekiq::Testing.disable! do
BackgroundMigrationWorker.perform_in(2.minutes, migration_class, [1, 1])
BackgroundMigrationWorker.perform_async(migration_class, [1, 1])
migrate!
expect(migration).to have_received(:perform).with(1, 1).twice
end
end
end
context 'when there are no background migrations pending' do
it 'does nothing' do
Sidekiq::Testing.disable! do
migrate!
expect(migration).not_to have_received(:perform)
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170912113435_clean_stages_statuses_migration.rb')
describe CleanStagesStatusesMigration, :migration, :sidekiq, :redis do
let(:migration) { spy('migration') }
before do
allow(Gitlab::BackgroundMigration::MigrateStageStatus)
.to receive(:new).and_return(migration)
end
context 'when there are pending background migrations' do
it 'processes pending jobs synchronously' do
Sidekiq::Testing.disable! do
BackgroundMigrationWorker
.perform_in(2.minutes, 'MigrateStageStatus', [1, 1])
BackgroundMigrationWorker
.perform_async('MigrateStageStatus', [1, 1])
migrate!
expect(migration).to have_received(:perform).with(1, 1).twice
end
end
end
context 'when there are no background migrations pending' do
it 'does nothing' do
Sidekiq::Testing.disable! do
migrate!
expect(migration).not_to have_received(:perform)
end
end
end
context 'when there are still unmigrated stages afterwards' do
let(:stages) { table('ci_stages') }
before do
stages.create!(status: nil, name: 'build')
stages.create!(status: nil, name: 'test')
end
it 'migrates statuses sequentially in batches' do
migrate!
expect(migration).to have_received(:perform).once
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170406111121_clean_upload_symlinks.rb')
describe CleanUploadSymlinks do
let(:migration) { described_class.new }
let(:test_dir) { File.join(Rails.root, "tmp", "tests", "move_uploads_test") }
let(:uploads_dir) { File.join(test_dir, "public", "uploads") }
let(:new_uploads_dir) { File.join(uploads_dir, "-", "system") }
let(:original_path) { File.join(new_uploads_dir, 'user') }
let(:symlink_path) { File.join(uploads_dir, 'user') }
before do
FileUtils.remove_dir(test_dir) if File.directory?(test_dir)
FileUtils.mkdir_p(uploads_dir)
allow(migration).to receive(:base_directory).and_return(test_dir)
allow(migration).to receive(:say)
end
describe "#up" do
before do
FileUtils.mkdir_p(original_path)
FileUtils.ln_s(original_path, symlink_path)
end
it 'removes the symlink' do
migration.up
expect(File.symlink?(symlink_path)).to be(false)
end
end
describe '#down' do
before do
FileUtils.mkdir_p(File.join(original_path))
FileUtils.touch(File.join(original_path, 'dummy.file'))
end
it 'creates a symlink' do
expected_path = File.join(symlink_path, "dummy.file")
migration.down
expect(File.exist?(expected_path)).to be(true)
expect(File.symlink?(symlink_path)).to be(true)
end
end
end
require 'spec_helper'
require Rails.root.join("db", "post_migrate", "20170717111152_cleanup_move_system_upload_folder_symlink.rb")
describe CleanupMoveSystemUploadFolderSymlink do
let(:migration) { described_class.new }
let(:test_base) { File.join(Rails.root, 'tmp', 'tests', 'move-system-upload-folder') }
let(:test_folder) { File.join(test_base, '-', 'system') }
before do
allow(migration).to receive(:base_directory).and_return(test_base)
FileUtils.rm_rf(test_base)
FileUtils.mkdir_p(test_folder)
allow(migration).to receive(:say)
end
describe '#up' do
before do
FileUtils.ln_s(test_folder, File.join(test_base, 'system'))
end
it 'removes the symlink' do
migration.up
expect(File.exist?(File.join(test_base, 'system'))).to be_falsey
end
end
describe '#down' do
it 'creates the symlink' do
migration.down
expect(File.symlink?(File.join(test_base, 'system'))).to be_truthy
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb')
describe CleanupNonexistingNamespacePendingDeleteProjects, :migration do
let(:projects) { table(:projects) }
let(:namespaces) { table(:namespaces) }
describe '#up' do
let!(:some_project) { projects.create! }
let(:namespace) { namespaces.create!(name: 'test', path: 'test') }
it 'only cleans up when namespace does not exist' do
projects.create!(pending_delete: true, namespace_id: namespace.id)
project = projects.create!(pending_delete: true, namespace_id: 0)
expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]])
described_class.new.up
end
it 'does nothing when no pending delete projects without namespace found' do
projects.create!(pending_delete: true, namespace_id: namespace.id)
expect(NamespacelessProjectDestroyWorker).not_to receive(:bulk_perform_async)
described_class.new.up
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170607121233_convert_custom_notification_settings_to_columns')
describe ConvertCustomNotificationSettingsToColumns, :migration do
let(:user_class) { table(:users) }
let(:settings_params) do
[
{ level: 0, events: [:new_note] }, # disabled, single event
{ level: 3, events: [:new_issue, :reopen_issue, :close_issue, :reassign_issue] }, # global, multiple events
{ level: 5, events: described_class::EMAIL_EVENTS }, # custom, all events
{ level: 5, events: [] } # custom, no events
]
end
let(:notification_settings_before) do
settings_params.map do |params|
events = {}
params[:events].each do |event|
events[event] = true
end
user = user_class.create!(email: "user-#{SecureRandom.hex}@example.org", username: "user-#{SecureRandom.hex}", encrypted_password: '12345678')
create_params = { user_id: user.id, level: params[:level], events: events }
notification_setting = described_class::NotificationSetting.create(create_params)
[notification_setting, params]
end
end
let(:notification_settings_after) do
settings_params.map do |params|
events = {}
params[:events].each do |event|
events[event] = true
end
user = user_class.create!(email: "user-#{SecureRandom.hex}@example.org", username: "user-#{SecureRandom.hex}", encrypted_password: '12345678')
create_params = events.merge(user_id: user.id, level: params[:level])
notification_setting = described_class::NotificationSetting.create(create_params)
[notification_setting, params]
end
end
describe '#up' do
it 'migrates all settings where a custom event is enabled, even if they are not currently using the custom level' do
notification_settings_before
described_class.new.up
notification_settings_before.each do |(notification_setting, params)|
notification_setting.reload
expect(notification_setting.read_attribute_before_type_cast(:events)).to be_nil
expect(notification_setting.level).to eq(params[:level])
described_class::EMAIL_EVENTS.each do |event|
# We don't set the others to false, just let them default to nil
expected = params[:events].include?(event) || nil
expect(notification_setting.read_attribute(event)).to eq(expected)
end
end
end
end
describe '#down' do
it 'creates a custom events hash for all settings where at least one event is enabled' do
notification_settings_after
described_class.new.down
notification_settings_after.each do |(notification_setting, params)|
notification_setting.reload
expect(notification_setting.level).to eq(params[:level])
if params[:events].empty?
# We don't migrate empty settings
expect(notification_setting.events).to eq({})
else
described_class::EMAIL_EVENTS.each do |event|
expected = params[:events].include?(event)
expect(notification_setting.events[event]).to eq(expected)
expect(notification_setting.read_attribute(event)).to be_nil
end
end
end
end
it 'reverts the database to the state it was in before' do
notification_settings_before
described_class.new.up
described_class.new.down
notification_settings_before.each do |(notification_setting, params)|
notification_setting.reload
expect(notification_setting.level).to eq(params[:level])
if params[:events].empty?
# We don't migrate empty settings
expect(notification_setting.events).to eq({})
else
described_class::EMAIL_EVENTS.each do |event|
expected = params[:events].include?(event)
expect(notification_setting.events[event]).to eq(expected)
expect(notification_setting.read_attribute(event)).to be_nil
end
end
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170907170235_delete_conflicting_redirect_routes')
describe DeleteConflictingRedirectRoutes, :migration, :sidekiq do
let!(:redirect_routes) { table(:redirect_routes) }
let!(:routes) { table(:routes) }
around do |example|
Timecop.freeze { example.run }
end
before do
routes.create!(id: 1, source_id: 1, source_type: 'Namespace', path: 'foo1')
routes.create!(id: 2, source_id: 2, source_type: 'Namespace', path: 'foo2')
routes.create!(id: 3, source_id: 3, source_type: 'Namespace', path: 'foo3')
routes.create!(id: 4, source_id: 4, source_type: 'Namespace', path: 'foo4')
routes.create!(id: 5, source_id: 5, source_type: 'Namespace', path: 'foo5')
# Valid redirects
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'bar')
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'bar2')
redirect_routes.create!(source_id: 2, source_type: 'Namespace', path: 'bar3')
# Conflicting redirects
redirect_routes.create!(source_id: 2, source_type: 'Namespace', path: 'foo1')
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'foo2')
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'foo3')
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'foo4')
redirect_routes.create!(source_id: 1, source_type: 'Namespace', path: 'foo5')
end
# No-op. See https://gitlab.com/gitlab-com/infrastructure/issues/3460#note_53223252
it 'NO-OP: does not schedule any background migrations' do
Sidekiq::Testing.fake! do
Timecop.freeze do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq 0
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170518231126_fix_wrongly_renamed_routes.rb')
describe FixWronglyRenamedRoutes, :migration do
let(:subject) { described_class.new }
let(:namespaces_table) { table(:namespaces) }
let(:projects_table) { table(:projects) }
let(:routes_table) { table(:routes) }
let(:broken_namespace) do
namespaces_table.create!(name: 'apiis', path: 'apiis').tap do |namespace|
routes_table.create!(source_type: 'Namespace', source_id: namespace.id, name: 'api0is', path: 'api0is')
end
end
let(:broken_namespace_route) { routes_table.where(source_type: 'Namespace', source_id: broken_namespace.id).first }
describe '#wrongly_renamed' do
it "includes routes that have names that don't match their namespace" do
broken_namespace
other_namespace = namespaces_table.create!(name: 'api0', path: 'api0')
routes_table.create!(source_type: 'Namespace', source_id: other_namespace.id, name: 'api0', path: 'api0')
expect(subject.wrongly_renamed.map(&:id))
.to contain_exactly(broken_namespace_route.id)
end
end
describe "#paths_and_corrections" do
it 'finds the wrong path and gets the correction from the namespace' do
broken_namespace
namespaces_table.create!(name: 'uploads-test', path: 'uploads-test').tap do |namespace|
routes_table.create!(source_type: 'Namespace', source_id: namespace.id, name: 'uploads-test', path: 'uploads0-test')
end
expected_result = [
{ 'namespace_path' => 'apiis', 'path' => 'api0is' },
{ 'namespace_path' => 'uploads-test', 'path' => 'uploads0-test' }
]
expect(subject.paths_and_corrections).to include(*expected_result)
end
end
describe '#routes_in_namespace_query' do
it 'includes only the required routes' do
namespace = namespaces_table.create!(name: 'hello', path: 'hello')
namespace_route = routes_table.create!(source_type: 'Namespace', source_id: namespace.id, name: 'hello', path: 'hello')
project = projects_table.new(name: 'my-project', path: 'my-project', namespace_id: namespace.id).tap do |project|
project.save!(validate: false)
end
routes_table.create!(source_type: 'Project', source_id: project.id, name: 'my-project', path: 'hello/my-project')
_other_namespace = namespaces_table.create!(name: 'hello0', path: 'hello0')
result = routes_table.where(subject.routes_in_namespace_query('hello'))
project_route = routes_table.where(source_type: 'Project', source_id: project.id).first
expect(result).to contain_exactly(namespace_route, project_route)
end
end
describe '#up' do
it 'renames incorrectly named routes' do
broken_project =
projects_table.new(name: 'broken-project', path: 'broken-project', namespace_id: broken_namespace.id).tap do |project|
project.save!(validate: false)
routes_table.create!(source_type: 'Project', source_id: project.id, name: 'broken-project', path: 'api0is/broken-project')
end
subject.up
broken_project_route = routes_table.where(source_type: 'Project', source_id: broken_project.id).first
expect(broken_project_route.path).to eq('apiis/broken-project')
expect(broken_namespace_route.reload.path).to eq('apiis')
end
it "doesn't touch namespaces that look like something that should be renamed" do
namespaces_table.create!(name: 'apiis', path: 'apiis')
namespace = namespaces_table.create!(name: 'hello', path: 'api0')
namespace_route = routes_table.create!(source_type: 'Namespace', source_id: namespace.id, name: 'hello', path: 'api0')
subject.up
expect(namespace_route.reload.path).to eq('api0')
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20171106151218_issues_moved_to_id_foreign_key.rb')
describe IssuesMovedToIdForeignKey, :migration do
let(:issues) { table(:issues) }
let!(:issue_third) { issues.create! }
let!(:issue_second) { issues.create!(moved_to_id: issue_third.id) }
let!(:issue_first) { issues.create!(moved_to_id: issue_second.id) }
subject { described_class.new }
it 'removes the orphaned moved_to_id' do
subject.down
issue_third.update!(moved_to_id: 0)
subject.up
expect(issue_first.reload.moved_to_id).to eq(issue_second.id)
expect(issue_second.reload.moved_to_id).to eq(issue_third.id)
expect(issue_third.reload.moved_to_id).to be_nil
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170526190000_migrate_build_stage_reference_again.rb')
describe MigrateBuildStageReferenceAgain, :migration do
##
# Create test data - pipeline and CI/CD jobs.
#
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
let(:projects) { table(:projects) }
before do
# Create projects
#
projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
projects.create!(id: 456, name: 'gitlab2', path: 'gitlab2')
# Create CI/CD pipelines
#
pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a')
pipelines.create!(id: 2, project_id: 456, ref: 'feature', sha: '21a3deb')
# Create CI/CD jobs
#
jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 3, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
jobs.create!(id: 4, commit_id: 1, project_id: 123, stage_idx: 3, stage: 'deploy')
jobs.create!(id: 5, commit_id: 2, project_id: 456, stage_idx: 2, stage: 'test:2')
jobs.create!(id: 6, commit_id: 2, project_id: 456, stage_idx: 1, stage: 'test:1')
jobs.create!(id: 7, commit_id: 2, project_id: 456, stage_idx: 1, stage: 'test:1')
jobs.create!(id: 8, commit_id: 3, project_id: 789, stage_idx: 3, stage: 'deploy')
# Create CI/CD stages
#
stages.create(id: 101, pipeline_id: 1, project_id: 123, name: 'test')
stages.create(id: 102, pipeline_id: 1, project_id: 123, name: 'build')
stages.create(id: 103, pipeline_id: 1, project_id: 123, name: 'deploy')
stages.create(id: 104, pipeline_id: 2, project_id: 456, name: 'test:1')
stages.create(id: 105, pipeline_id: 2, project_id: 456, name: 'test:2')
stages.create(id: 106, pipeline_id: 2, project_id: 456, name: 'deploy')
end
it 'correctly migrate build stage references' do
expect(jobs.where(stage_id: nil).count).to eq 8
migrate!
expect(jobs.where(stage_id: nil).count).to eq 1
expect(jobs.find(1).stage_id).to eq 102
expect(jobs.find(2).stage_id).to eq 102
expect(jobs.find(3).stage_id).to eq 101
expect(jobs.find(4).stage_id).to eq 103
expect(jobs.find(5).stage_id).to eq 105
expect(jobs.find(6).stage_id).to eq 104
expect(jobs.find(7).stage_id).to eq 104
expect(jobs.find(8).stage_id).to eq nil
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb')
describe MigrateGcpClustersToNewClustersArchitectures, :migration do
let(:projects) { table(:projects) }
let(:project) { projects.create }
let(:users) { table(:users) }
let(:user) { users.create! }
let(:service) { GcpMigrationSpec::KubernetesService.create!(project_id: project.id) }
module GcpMigrationSpec
class KubernetesService < ActiveRecord::Base
self.table_name = 'services'
serialize :properties, JSON
default_value_for :active, true
default_value_for :type, 'KubernetesService'
default_value_for :properties, {
api_url: 'https://kubernetes.example.com',
token: 'a' * 40
}
end
end
context 'when cluster is being created' do
let(:project_id) { project.id }
let(:user_id) { user.id }
let(:service_id) { service.id }
let(:status) { 2 } # creating
let(:gcp_cluster_size) { 1 }
let(:created_at) { "'2017-10-17 20:24:02'" }
let(:updated_at) { "'2017-10-17 20:28:44'" }
let(:enabled) { true }
let(:status_reason) { "''" }
let(:project_namespace) { "'sample-app'" }
let(:endpoint) { 'NULL' }
let(:ca_cert) { 'NULL' }
let(:encrypted_kubernetes_token) { 'NULL' }
let(:encrypted_kubernetes_token_iv) { 'NULL' }
let(:username) { 'NULL' }
let(:encrypted_password) { 'NULL' }
let(:encrypted_password_iv) { 'NULL' }
let(:gcp_project_id) { "'gcp_project_id'" }
let(:gcp_cluster_zone) { "'gcp_cluster_zone'" }
let(:gcp_cluster_name) { "'gcp_cluster_name'" }
let(:gcp_machine_type) { "'gcp_machine_type'" }
let(:gcp_operation_id) { 'NULL' }
let(:encrypted_gcp_token) { "'encrypted_gcp_token'" }
let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" }
let(:cluster) { described_class::Cluster.last }
let(:cluster_id) { cluster.id }
before do
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO gcp_clusters (project_id, user_id, service_id, status, gcp_cluster_size, created_at, updated_at, enabled, status_reason, project_namespace, endpoint, ca_cert, encrypted_kubernetes_token, encrypted_kubernetes_token_iv, username, encrypted_password, encrypted_password_iv, gcp_project_id, gcp_cluster_zone, gcp_cluster_name, gcp_machine_type, gcp_operation_id, encrypted_gcp_token, encrypted_gcp_token_iv)
VALUES (#{project_id}, #{user_id}, #{service_id}, #{status}, #{gcp_cluster_size}, #{created_at}, #{updated_at}, #{enabled}, #{status_reason}, #{project_namespace}, #{endpoint}, #{ca_cert}, #{encrypted_kubernetes_token}, #{encrypted_kubernetes_token_iv}, #{username}, #{encrypted_password}, #{encrypted_password_iv}, #{gcp_project_id}, #{gcp_cluster_zone}, #{gcp_cluster_name}, #{gcp_machine_type}, #{gcp_operation_id}, #{encrypted_gcp_token}, #{encrypted_gcp_token_iv});
SQL
end
it 'correctly migrate to new clusters architectures' do
migrate!
expect(described_class::Cluster.count).to eq(1)
expect(described_class::ClustersProject.count).to eq(1)
expect(described_class::ProvidersGcp.count).to eq(1)
expect(described_class::PlatformsKubernetes.count).to eq(1)
expect(cluster.user_id).to eq(user.id)
expect(cluster.enabled).to be_truthy
expect(cluster.name).to eq(gcp_cluster_name.delete!("'"))
expect(cluster.provider_type).to eq('gcp')
expect(cluster.platform_type).to eq('kubernetes')
expect(cluster.project_ids).to include(project.id)
expect(cluster.provider_gcp.cluster_id).to eq(cluster.id)
expect(cluster.provider_gcp.status).to eq(status)
expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason))
expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id))
expect(cluster.provider_gcp.zone).to eq(tr(gcp_cluster_zone))
expect(cluster.provider_gcp.num_nodes).to eq(gcp_cluster_size)
expect(cluster.provider_gcp.machine_type).to eq(tr(gcp_machine_type))
expect(cluster.provider_gcp.operation_id).to be_nil
expect(cluster.provider_gcp.endpoint).to be_nil
expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token))
expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv))
expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id)
expect(cluster.platform_kubernetes.api_url).to be_nil
expect(cluster.platform_kubernetes.ca_cert).to be_nil
expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace))
expect(cluster.platform_kubernetes.username).to be_nil
expect(cluster.platform_kubernetes.encrypted_password).to be_nil
expect(cluster.platform_kubernetes.encrypted_password_iv).to be_nil
expect(cluster.platform_kubernetes.encrypted_token).to be_nil
expect(cluster.platform_kubernetes.encrypted_token_iv).to be_nil
end
end
context 'when cluster has been created' do
let(:project_id) { project.id }
let(:user_id) { user.id }
let(:service_id) { service.id }
let(:status) { 3 } # created
let(:gcp_cluster_size) { 1 }
let(:created_at) { "'2017-10-17 20:24:02'" }
let(:updated_at) { "'2017-10-17 20:28:44'" }
let(:enabled) { true }
let(:status_reason) { "'general error'" }
let(:project_namespace) { "'sample-app'" }
let(:endpoint) { "'111.111.111.111'" }
let(:ca_cert) { "'ca_cert'" }
let(:encrypted_kubernetes_token) { "'encrypted_kubernetes_token'" }
let(:encrypted_kubernetes_token_iv) { "'encrypted_kubernetes_token_iv'" }
let(:username) { "'username'" }
let(:encrypted_password) { "'encrypted_password'" }
let(:encrypted_password_iv) { "'encrypted_password_iv'" }
let(:gcp_project_id) { "'gcp_project_id'" }
let(:gcp_cluster_zone) { "'gcp_cluster_zone'" }
let(:gcp_cluster_name) { "'gcp_cluster_name'" }
let(:gcp_machine_type) { "'gcp_machine_type'" }
let(:gcp_operation_id) { "'gcp_operation_id'" }
let(:encrypted_gcp_token) { "'encrypted_gcp_token'" }
let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" }
let(:cluster) { described_class::Cluster.last }
let(:cluster_id) { cluster.id }
before do
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO gcp_clusters (project_id, user_id, service_id, status, gcp_cluster_size, created_at, updated_at, enabled, status_reason, project_namespace, endpoint, ca_cert, encrypted_kubernetes_token, encrypted_kubernetes_token_iv, username, encrypted_password, encrypted_password_iv, gcp_project_id, gcp_cluster_zone, gcp_cluster_name, gcp_machine_type, gcp_operation_id, encrypted_gcp_token, encrypted_gcp_token_iv)
VALUES (#{project_id}, #{user_id}, #{service_id}, #{status}, #{gcp_cluster_size}, #{created_at}, #{updated_at}, #{enabled}, #{status_reason}, #{project_namespace}, #{endpoint}, #{ca_cert}, #{encrypted_kubernetes_token}, #{encrypted_kubernetes_token_iv}, #{username}, #{encrypted_password}, #{encrypted_password_iv}, #{gcp_project_id}, #{gcp_cluster_zone}, #{gcp_cluster_name}, #{gcp_machine_type}, #{gcp_operation_id}, #{encrypted_gcp_token}, #{encrypted_gcp_token_iv});
SQL
end
it 'correctly migrate to new clusters architectures' do
migrate!
expect(described_class::Cluster.count).to eq(1)
expect(described_class::ClustersProject.count).to eq(1)
expect(described_class::ProvidersGcp.count).to eq(1)
expect(described_class::PlatformsKubernetes.count).to eq(1)
expect(cluster.user_id).to eq(user.id)
expect(cluster.enabled).to be_truthy
expect(cluster.name).to eq(tr(gcp_cluster_name))
expect(cluster.provider_type).to eq('gcp')
expect(cluster.platform_type).to eq('kubernetes')
expect(cluster.project_ids).to include(project.id)
expect(cluster.provider_gcp.cluster_id).to eq(cluster.id)
expect(cluster.provider_gcp.status).to eq(status)
expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason))
expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id))
expect(cluster.provider_gcp.zone).to eq(tr(gcp_cluster_zone))
expect(cluster.provider_gcp.num_nodes).to eq(gcp_cluster_size)
expect(cluster.provider_gcp.machine_type).to eq(tr(gcp_machine_type))
expect(cluster.provider_gcp.operation_id).to eq(tr(gcp_operation_id))
expect(cluster.provider_gcp.endpoint).to eq(tr(endpoint))
expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token))
expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv))
expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id)
expect(cluster.platform_kubernetes.api_url).to eq('https://' + tr(endpoint))
expect(cluster.platform_kubernetes.ca_cert).to eq(tr(ca_cert))
expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace))
expect(cluster.platform_kubernetes.username).to eq(tr(username))
expect(cluster.platform_kubernetes.encrypted_password).to eq(tr(encrypted_password))
expect(cluster.platform_kubernetes.encrypted_password_iv).to eq(tr(encrypted_password_iv))
expect(cluster.platform_kubernetes.encrypted_token).to eq(tr(encrypted_kubernetes_token))
expect(cluster.platform_kubernetes.encrypted_token_iv).to eq(tr(encrypted_kubernetes_token_iv))
end
end
def tr(str)
str.delete("'")
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170825104051_migrate_issues_to_ghost_user.rb')
describe MigrateIssuesToGhostUser, :migration do
describe '#up' do
let(:projects) { table(:projects) }
let(:issues) { table(:issues) }
let(:users) { table(:users) }
before do
project = projects.create!(name: 'gitlab', namespace_id: 1)
user = users.create(email: 'test@example.com')
issues.create(title: 'Issue 1', author_id: nil, project_id: project.id)
issues.create(title: 'Issue 2', author_id: user.id, project_id: project.id)
end
context 'when ghost user exists' do
let!(:ghost) { users.create(ghost: true, email: 'ghost@example.com') }
it 'does not create a new user' do
expect { migrate! }.not_to change { User.count }
end
it 'migrates issues where author = nil to the ghost user' do
migrate!
expect(issues.first.reload.author_id).to eq(ghost.id)
end
it 'does not change issues authored by an existing user' do
expect { migrate! }.not_to change { issues.second.reload.author_id}
end
end
context 'when ghost user does not exist' do
it 'creates a new user' do
expect { migrate! }.to change { User.count }.by(1)
end
it 'migrates issues where author = nil to the ghost user' do
migrate!
expect(issues.first.reload.author_id).to eq(User.ghost.id)
end
it 'does not change issues authored by an existing user' do
expect { migrate! }.not_to change { issues.second.reload.author_id}
end
end
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170523083112_migrate_old_artifacts.rb')
# Adding the ci_job_artifacts table (from the 20170918072948 schema)
# makes the use of model code below easier.
describe MigrateOldArtifacts, :migration, schema: 20170918072948 do
let(:migration) { described_class.new }
let!(:directory) { Dir.mktmpdir }
before do
allow(Gitlab.config.artifacts).to receive(:path).and_return(directory)
end
after do
FileUtils.remove_entry_secure(directory)
end
context 'with migratable data' do
let(:projects) { table(:projects) }
let(:ci_pipelines) { table(:ci_pipelines) }
let(:ci_builds) { table(:ci_builds) }
let!(:project1) { projects.create!(ci_id: 2) }
let!(:project2) { projects.create!(ci_id: 3) }
let!(:project3) { projects.create! }
let!(:pipeline1) { ci_pipelines.create!(project_id: project1.id) }
let!(:pipeline2) { ci_pipelines.create!(project_id: project2.id) }
let!(:pipeline3) { ci_pipelines.create!(project_id: project3.id) }
let!(:build_with_legacy_artifacts) { ci_builds.create!(commit_id: pipeline1.id, project_id: project1.id, type: 'Ci::Build').becomes(Ci::Build) }
let!(:build_without_artifacts) { ci_builds.create!(commit_id: pipeline1.id, project_id: project1.id, type: 'Ci::Build').becomes(Ci::Build) }
let!(:build2) { ci_builds.create!(commit_id: pipeline2.id, project_id: project2.id, type: 'Ci::Build').becomes(Ci::Build) }
let!(:build3) { ci_builds.create!(commit_id: pipeline3.id, project_id: project3.id, type: 'Ci::Build').becomes(Ci::Build) }
before do
setup_builds(build2, build3)
store_artifacts_in_legacy_path(build_with_legacy_artifacts)
end
it "legacy artifacts are not accessible" do
expect(build_with_legacy_artifacts.artifacts?).to be_falsey
end
describe '#min_id' do
subject { migration.send(:min_id) }
it 'returns the newest build for which ci_id is not defined' do
is_expected.to eq(build3.id)
end
end
describe '#builds_with_artifacts' do
subject { migration.send(:builds_with_artifacts).map(&:id) }
it 'returns a list of builds that has artifacts and could be migrated' do
is_expected.to contain_exactly(build_with_legacy_artifacts.id, build2.id)
end
end
describe '#up' do
context 'when migrating artifacts' do
before do
migration.up
end
it 'all files do have artifacts' do
Ci::Build.with_artifacts_archive do |build|
expect(build).to have_artifacts
end
end
it 'artifacts are no longer present on legacy path' do
expect(File.exist?(legacy_path(build_with_legacy_artifacts))).to eq(false)
end
end
context 'when there are artifacts in old and new directory' do
before do
store_artifacts_in_legacy_path(build2)
migration.up
end
it 'does not move old files' do
expect(File.exist?(legacy_path(build2))).to eq(true)
end
end
end
private
def store_artifacts_in_legacy_path(build)
FileUtils.mkdir_p(legacy_path(build))
FileUtils.copy(
Rails.root.join('spec/fixtures/ci_build_artifacts.zip'),
File.join(legacy_path(build), "ci_build_artifacts.zip"))
FileUtils.copy(
Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'),
File.join(legacy_path(build), "ci_build_artifacts_metadata.gz"))
build.update_columns(
artifacts_file: 'ci_build_artifacts.zip',
artifacts_metadata: 'ci_build_artifacts_metadata.gz')
build.reload
end
def legacy_path(build)
File.join(directory,
build.created_at.utc.strftime('%Y_%m'),
build.project.ci_id.to_s,
build.id.to_s)
end
def new_legacy_path(build)
File.join(directory,
build.created_at.utc.strftime('%Y_%m'),
build.project_id.to_s,
build.id.to_s)
end
def setup_builds(*builds)
builds.each do |build|
FileUtils.mkdir_p(new_legacy_path(build))
build.update_columns(
artifacts_file: 'ci_build_artifacts.zip',
artifacts_metadata: 'ci_build_artifacts_metadata.gz')
build.reload
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170822101017_migrate_pipeline_sidekiq_queues.rb')
describe MigratePipelineSidekiqQueues, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
include StubWorker
context 'when there are jobs in the queues' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
stub_worker(queue: :pipeline).perform_async('Something', [1])
stub_worker(queue: :build).perform_async('Something', [1])
described_class.new.up
expect(sidekiq_queue_length('pipeline')).to eq 0
expect(sidekiq_queue_length('build')).to eq 0
expect(sidekiq_queue_length('pipeline_default')).to eq 2
end
end
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
stub_worker(queue: :pipeline_default).perform_async('Class', [1])
stub_worker(queue: :pipeline_processing).perform_async('Class', [2])
stub_worker(queue: :pipeline_hooks).perform_async('Class', [3])
stub_worker(queue: :pipeline_cache).perform_async('Class', [4])
described_class.new.down
expect(sidekiq_queue_length('pipeline')).to eq 4
expect(sidekiq_queue_length('pipeline_default')).to eq 0
expect(sidekiq_queue_length('pipeline_processing')).to eq 0
expect(sidekiq_queue_length('pipeline_hooks')).to eq 0
expect(sidekiq_queue_length('pipeline_cache')).to eq 0
end
end
end
context 'when there are no jobs in the queues' do
it 'does not raise error when migrating up' do
expect { described_class.new.up }.not_to raise_error
end
it 'does not raise error when migrating down' do
expect { described_class.new.down }.not_to raise_error
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb')
describe MigratePipelineStages, :migration do
##
# Create test data - pipeline and CI/CD jobs.
#
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
let(:projects) { table(:projects) }
before do
# Create projects
#
projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
projects.create!(id: 456, name: 'gitlab2', path: 'gitlab2')
# Create CI/CD pipelines
#
pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a')
pipelines.create!(id: 2, project_id: 456, ref: 'feature', sha: '21a3deb')
# Create CI/CD jobs
#
jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 3, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
jobs.create!(id: 4, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
jobs.create!(id: 5, commit_id: 1, project_id: 123, stage_idx: 3, stage: 'deploy')
jobs.create!(id: 6, commit_id: 2, project_id: 456, stage_idx: 3, stage: 'deploy')
jobs.create!(id: 7, commit_id: 2, project_id: 456, stage_idx: 2, stage: 'test:2')
jobs.create!(id: 8, commit_id: 2, project_id: 456, stage_idx: 1, stage: 'test:1')
jobs.create!(id: 9, commit_id: 2, project_id: 456, stage_idx: 1, stage: 'test:1')
jobs.create!(id: 10, commit_id: 2, project_id: 456, stage_idx: 2, stage: 'test:2')
jobs.create!(id: 11, commit_id: 3, project_id: 456, stage_idx: 3, stage: 'deploy')
jobs.create!(id: 12, commit_id: 2, project_id: 789, stage_idx: 3, stage: 'deploy')
end
it 'correctly migrates pipeline stages' do
expect(stages.count).to be_zero
migrate!
expect(stages.count).to eq 6
expect(stages.all.pluck(:name))
.to match_array %w[test build deploy test:1 test:2 deploy]
expect(stages.where(pipeline_id: 1).order(:id).pluck(:name))
.to eq %w[test build deploy]
expect(stages.where(pipeline_id: 2).order(:id).pluck(:name))
.to eq %w[test:1 test:2 deploy]
expect(stages.where(pipeline_id: 3).count).to be_zero
expect(stages.where(project_id: 789).count).to be_zero
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_worker_jobs.rb')
describe MigrateProcessCommitWorkerJobs do
set(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
set(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:commit) do
Gitlab::Git::Commit.last(project.repository.raw)
end
describe 'Project' do
describe 'find_including_path' do
it 'returns Project instances' do
expect(described_class::Project.find_including_path(project.id))
.to be_an_instance_of(described_class::Project)
end
it 'selects the full path for every Project' do
migration_project = described_class::Project
.find_including_path(project.id)
expect(migration_project[:path_with_namespace])
.to eq(project.full_path)
end
end
describe '#repository' do
it 'returns a mock implemention of ::Repository' do
migration_project = described_class::Project
.find_including_path(project.id)
expect(migration_project.repository).to respond_to(:storage)
expect(migration_project.repository).to respond_to(:gitaly_repository)
end
end
end
describe '#up', :clean_gitlab_redis_shared_state do
let(:migration) { described_class.new }
def job_count
Sidekiq.redis { |r| r.llen('queue:process_commit') }
end
def pop_job
JSON.parse(Sidekiq.redis { |r| r.lpop('queue:process_commit') })
end
before do
Sidekiq.redis do |redis|
job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job)
end
end
it 'skips jobs using a project that no longer exists' do
allow(described_class::Project).to receive(:find_including_path)
.with(project.id)
.and_return(nil)
migration.up
expect(job_count).to eq(0)
end
it 'skips jobs using commits that no longer exist' do
allow_any_instance_of(Gitlab::GitalyClient::CommitService)
.to receive(:find_commit)
.with(commit.id)
.and_return(nil)
migration.up
expect(job_count).to eq(0)
end
it 'inserts migrated jobs back into the queue' do
migration.up
expect(job_count).to eq(1)
end
it 'encodes data to UTF-8' do
allow(commit).to receive(:body)
.and_return('김치'.force_encoding('BINARY'))
migration.up
job = pop_job
# We don't care so much about what is being stored, instead we just want
# to make sure the encoding is right so that JSON encoding the data
# doesn't produce any errors.
expect(job['args'][2]['message'].encoding).to eq(Encoding::UTF_8)
end
context 'a migrated job' do
let(:job) do
migration.up
pop_job
end
let(:commit_hash) do
job['args'][2]
end
it 'includes the project ID' do
expect(job['args'][0]).to eq(project.id)
end
it 'includes the user ID' do
expect(job['args'][1]).to eq(user.id)
end
it 'includes the commit ID' do
expect(commit_hash['id']).to eq(commit.id)
end
it 'includes the commit message' do
expect(commit_hash['message']).to eq(commit.message)
end
it 'includes the parent IDs' do
expect(commit_hash['parent_ids']).to eq(commit.parent_ids)
end
it 'includes the author date' do
expect(commit_hash['authored_date']).to eq(commit.authored_date.to_s)
end
it 'includes the author name' do
expect(commit_hash['author_name']).to eq(commit.author_name)
end
it 'includes the author Email' do
expect(commit_hash['author_email']).to eq(commit.author_email)
end
it 'includes the commit date' do
expect(commit_hash['committed_date']).to eq(commit.committed_date.to_s)
end
it 'includes the committer name' do
expect(commit_hash['committer_name']).to eq(commit.committer_name)
end
it 'includes the committer Email' do
expect(commit_hash['committer_email']).to eq(commit.committer_email)
end
end
end
describe '#down', :clean_gitlab_redis_shared_state do
let(:migration) { described_class.new }
def job_count
Sidekiq.redis { |r| r.llen('queue:process_commit') }
end
before do
Sidekiq.redis do |redis|
job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job)
migration.up
end
end
it 'pushes migrated jobs back into the queue' do
migration.down
expect(job_count).to eq(1)
end
context 'a migrated job' do
let(:job) do
migration.down
JSON.parse(Sidekiq.redis { |r| r.lpop('queue:process_commit') })
end
it 'includes the project ID' do
expect(job['args'][0]).to eq(project.id)
end
it 'includes the user ID' do
expect(job['args'][1]).to eq(user.id)
end
it 'includes the commit SHA' do
expect(job['args'][2]).to eq(commit.id)
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170628080858_migrate_stage_id_reference_in_background')
describe MigrateStageIdReferenceInBackground, :migration, :sidekiq do
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
let(:projects) { table(:projects) }
before do
stub_const("#{described_class.name}::BATCH_SIZE", 3)
stub_const("#{described_class.name}::RANGE_SIZE", 2)
projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
projects.create!(id: 345, name: 'gitlab2', path: 'gitlab2')
pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a')
pipelines.create!(id: 2, project_id: 345, ref: 'feature', sha: 'cdf43c3c')
jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
jobs.create!(id: 3, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
jobs.create!(id: 4, commit_id: 1, project_id: 123, stage_idx: 3, stage: 'deploy')
jobs.create!(id: 5, commit_id: 2, project_id: 345, stage_idx: 1, stage: 'test')
stages.create(id: 101, pipeline_id: 1, project_id: 123, name: 'test')
stages.create(id: 102, pipeline_id: 1, project_id: 123, name: 'build')
stages.create(id: 103, pipeline_id: 1, project_id: 123, name: 'deploy')
jobs.create!(id: 6, commit_id: 2, project_id: 345, stage_id: 101, stage_idx: 1, stage: 'test')
end
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
Timecop.freeze do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 3, 3)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 4, 5)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
end
it 'schedules background migrations' do
perform_enqueued_jobs do
expect(jobs.where(stage_id: nil).count).to eq 5
migrate!
expect(jobs.where(stage_id: nil).count).to eq 1
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170711145558_migrate_stages_statuses.rb')
describe MigrateStagesStatuses, :sidekiq, :migration do
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
let(:projects) { table(:projects) }
STATUSES = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
before do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
stub_const("#{described_class.name}::RANGE_SIZE", 1)
projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
projects.create!(id: 2, name: 'gitlab2', path: 'gitlab2')
pipelines.create!(id: 1, project_id: 1, ref: 'master', sha: 'adf43c3a')
pipelines.create!(id: 2, project_id: 2, ref: 'feature', sha: '21a3deb')
create_job(project: 1, pipeline: 1, stage: 'test', status: 'success')
create_job(project: 1, pipeline: 1, stage: 'test', status: 'running')
create_job(project: 1, pipeline: 1, stage: 'build', status: 'success')
create_job(project: 1, pipeline: 1, stage: 'build', status: 'failed')
create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
create_job(project: 2, pipeline: 2, stage: 'test', status: 'failed', retried: true)
stages.create!(id: 1, pipeline_id: 1, project_id: 1, name: 'test', status: nil)
stages.create!(id: 2, pipeline_id: 1, project_id: 1, name: 'build', status: nil)
stages.create!(id: 3, pipeline_id: 2, project_id: 2, name: 'test', status: nil)
end
it 'correctly migrates stages statuses' do
perform_enqueued_jobs do
expect(stages.where(status: nil).count).to eq 3
migrate!
expect(stages.where(status: nil)).to be_empty
expect(stages.all.order('id ASC').pluck(:status))
.to eq [STATUSES[:running], STATUSES[:failed], STATUSES[:success]]
end
end
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
Timecop.freeze do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 1, 1)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 2, 2)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, 3, 3)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
end
def create_job(project:, pipeline:, stage:, status:, **opts)
stages = { test: 1, build: 2, deploy: 3 }
jobs.create!(project_id: project, commit_id: pipeline,
stage_idx: stages[stage.to_sym], stage: stage,
status: status, **opts)
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170324160416_migrate_user_activities_to_users_last_activity_on.rb')
describe MigrateUserActivitiesToUsersLastActivityOn, :clean_gitlab_redis_shared_state, :migration do
let(:migration) { described_class.new }
let!(:user_active_1) { table(:users).create!(email: 'test1', username: 'test1') }
let!(:user_active_2) { table(:users).create!(email: 'test2', username: 'test2') }
def record_activity(user, time)
Gitlab::Redis::SharedState.with do |redis|
redis.zadd(described_class::USER_ACTIVITY_SET_KEY, time.to_i, user.username)
end
end
around do |example|
Timecop.freeze { example.run }
end
before do
record_activity(user_active_1, described_class::TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED + 2.months)
record_activity(user_active_2, described_class::TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED + 3.months)
mute_stdout { migration.up }
end
describe '#up' do
it 'fills last_activity_on from the legacy Redis Sorted Set' do
expect(user_active_1.reload.last_activity_on).to eq((described_class::TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED + 2.months).to_date)
expect(user_active_2.reload.last_activity_on).to eq((described_class::TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED + 3.months).to_date)
end
end
describe '#down' do
it 'sets last_activity_on to NULL for all users' do
mute_stdout { migration.down }
expect(user_active_1.reload.last_activity_on).to be_nil
expect(user_active_2.reload.last_activity_on).to be_nil
end
end
def mute_stdout
orig_stdout = $stdout
$stdout = StringIO.new
yield
$stdout = orig_stdout
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20171012125712_migrate_user_authentication_token_to_personal_access_token.rb')
describe MigrateUserAuthenticationTokenToPersonalAccessToken, :migration do
let(:users) { table(:users) }
let(:personal_access_tokens) { table(:personal_access_tokens) }
let!(:user) { users.create!(id: 1, email: 'user@example.com', authentication_token: 'user-token', admin: false) }
let!(:admin) { users.create!(id: 2, email: 'admin@example.com', authentication_token: 'admin-token', admin: true) }
it 'migrates private tokens to Personal Access Tokens' do
migrate!
expect(personal_access_tokens.count).to eq(2)
user_token = personal_access_tokens.find_by(user_id: user.id)
admin_token = personal_access_tokens.find_by(user_id: admin.id)
expect(user_token.token).to eq('user-token')
expect(admin_token.token).to eq('admin-token')
expect(user_token.scopes).to eq(%w[api].to_yaml)
expect(admin_token.scopes).to eq(%w[api sudo].to_yaml)
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170406142253_migrate_user_project_view.rb')
describe MigrateUserProjectView, :migration do
let(:migration) { described_class.new }
let!(:user) { table(:users).create!(project_view: User.project_views['readme']) }
describe '#up' do
it 'updates project view setting with new value' do
migration.up
expect(user.reload.project_view).to eq(User.project_views['files'])
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170612071012_move_personal_snippets_files.rb')
describe MovePersonalSnippetsFiles, :migration do
let(:migration) { described_class.new }
let(:test_dir) { File.join(Rails.root, "tmp", "tests", "move_snippet_files_test") }
let(:uploads_dir) { File.join(test_dir, 'uploads') }
let(:new_uploads_dir) { File.join(uploads_dir, '-', 'system') }
let(:notes) { table(:notes) }
let(:snippets) { table(:snippets) }
let(:uploads) { table(:uploads) }
let(:user) { table(:users).create!(email: 'user@example.com', projects_limit: 10) }
let(:project) { table(:projects).create!(name: 'gitlab', namespace_id: 1) }
before do
allow(CarrierWave).to receive(:root).and_return(test_dir)
allow(migration).to receive(:base_directory).and_return(test_dir)
FileUtils.remove_dir(test_dir) if File.directory?(test_dir)
allow(migration).to receive(:say)
end
describe "#up" do
let(:snippet) do
snippet = snippets.create!(author_id: user.id)
create_upload('picture.jpg', snippet)
snippet.update(description: markdown_linking_file('picture.jpg', snippet))
snippet
end
let(:snippet_with_missing_file) do
snippet = snippets.create!(author_id: user.id, project_id: project.id)
create_upload('picture.jpg', snippet, create_file: false)
snippet.update(description: markdown_linking_file('picture.jpg', snippet))
snippet
end
it 'moves the files' do
source_path = File.join(uploads_dir, model_file_path('picture.jpg', snippet))
destination_path = File.join(new_uploads_dir, model_file_path('picture.jpg', snippet))
migration.up
expect(File.exist?(source_path)).to be_falsy
expect(File.exist?(destination_path)).to be_truthy
end
describe 'updating the markdown' do
it 'includes the new path when the file exists' do
secret = "secret#{snippet.id}"
file_location = "/uploads/-/system/personal_snippet/#{snippet.id}/#{secret}/picture.jpg"
migration.up
expect(snippet.reload.description).to include(file_location)
end
it 'does not update the markdown when the file is missing' do
secret = "secret#{snippet_with_missing_file.id}"
file_location = "/uploads/personal_snippet/#{snippet_with_missing_file.id}/#{secret}/picture.jpg"
migration.up
expect(snippet_with_missing_file.reload.description).to include(file_location)
end
it 'updates the note markdown' do
secret = "secret#{snippet.id}"
file_location = "/uploads/-/system/personal_snippet/#{snippet.id}/#{secret}/picture.jpg"
markdown = markdown_linking_file('picture.jpg', snippet)
note = notes.create!(noteable_id: snippet.id,
noteable_type: Snippet,
note: "with #{markdown}",
author_id: user.id)
migration.up
expect(note.reload.note).to include(file_location)
end
end
end
describe "#down" do
let(:snippet) do
snippet = snippets.create!(author_id: user.id)
create_upload('picture.jpg', snippet, in_new_path: true)
snippet.update(description: markdown_linking_file('picture.jpg', snippet, in_new_path: true))
snippet
end
let(:snippet_with_missing_file) do
snippet = snippets.create!(author_id: user.id)
create_upload('picture.jpg', snippet, create_file: false, in_new_path: true)
snippet.update(description: markdown_linking_file('picture.jpg', snippet, in_new_path: true))
snippet
end
it 'moves the files' do
source_path = File.join(new_uploads_dir, model_file_path('picture.jpg', snippet))
destination_path = File.join(uploads_dir, model_file_path('picture.jpg', snippet))
migration.down
expect(File.exist?(source_path)).to be_falsey
expect(File.exist?(destination_path)).to be_truthy
end
describe 'updating the markdown' do
it 'includes the new path when the file exists' do
secret = "secret#{snippet.id}"
file_location = "/uploads/personal_snippet/#{snippet.id}/#{secret}/picture.jpg"
migration.down
expect(snippet.reload.description).to include(file_location)
end
it 'keeps the markdown as is when the file is missing' do
secret = "secret#{snippet_with_missing_file.id}"
file_location = "/uploads/-/system/personal_snippet/#{snippet_with_missing_file.id}/#{secret}/picture.jpg"
migration.down
expect(snippet_with_missing_file.reload.description).to include(file_location)
end
it 'updates the note markdown' do
markdown = markdown_linking_file('picture.jpg', snippet, in_new_path: true)
secret = "secret#{snippet.id}"
file_location = "/uploads/personal_snippet/#{snippet.id}/#{secret}/picture.jpg"
note = notes.create!(noteable_id: snippet.id,
noteable_type: Snippet,
note: "with #{markdown}",
author_id: user.id)
migration.down
expect(note.reload.note).to include(file_location)
end
end
end
describe '#update_markdown' do
it 'escapes sql in the snippet description' do
migration.instance_variable_set('@source_relative_location', '/uploads/personal_snippet')
migration.instance_variable_set('@destination_relative_location', '/uploads/system/personal_snippet')
secret = '123456789'
filename = 'hello.jpg'
snippet = snippets.create!(author_id: user.id)
path_before = "/uploads/personal_snippet/#{snippet.id}/#{secret}/#{filename}"
path_after = "/uploads/system/personal_snippet/#{snippet.id}/#{secret}/#{filename}"
description_before = "Hello world; ![image](#{path_before})'; select * from users;"
description_after = "Hello world; ![image](#{path_after})'; select * from users;"
migration.update_markdown(snippet.id, secret, filename, description_before)
expect(snippet.reload.description).to eq(description_after)
end
end
def create_upload(filename, snippet, create_file: true, in_new_path: false)
secret = "secret#{snippet.id}"
absolute_path = if in_new_path
File.join(new_uploads_dir, model_file_path(filename, snippet))
else
File.join(uploads_dir, model_file_path(filename, snippet))
end
if create_file
FileUtils.mkdir_p(File.dirname(absolute_path))
FileUtils.touch(absolute_path)
end
uploads.create!(model_id: snippet.id,
model_type: snippet.class,
path: "#{secret}/#{filename}",
uploader: PersonalFileUploader,
size: 100.kilobytes)
end
def markdown_linking_file(filename, snippet, in_new_path: false)
markdown = "![#{filename.split('.')[0]}]"
markdown += '(/uploads'
markdown += '/-/system' if in_new_path
markdown += "/#{model_file_path(filename, snippet)})"
markdown
end
def model_file_path(filename, snippet)
secret = "secret#{snippet.id}"
File.join('personal_snippet', snippet.id.to_s, secret, filename)
end
end
require 'spec_helper'
require Rails.root.join("db", "migrate", "20170717074009_move_system_upload_folder.rb")
describe MoveSystemUploadFolder do
let(:migration) { described_class.new }
let(:test_base) { File.join(Rails.root, 'tmp', 'tests', 'move-system-upload-folder') }
before do
allow(migration).to receive(:base_directory).and_return(test_base)
FileUtils.rm_rf(test_base)
FileUtils.mkdir_p(test_base)
allow(migration).to receive(:say)
end
describe '#up' do
let(:test_folder) { File.join(test_base, 'system') }
let(:test_file) { File.join(test_folder, 'file') }
before do
FileUtils.mkdir_p(test_folder)
FileUtils.touch(test_file)
end
it 'moves the related folder' do
migration.up
expect(File.exist?(File.join(test_base, '-', 'system', 'file'))).to be_truthy
end
it 'creates a symlink linking making the new folder available on the old path' do
migration.up
expect(File.symlink?(File.join(test_base, 'system'))).to be_truthy
expect(File.exist?(File.join(test_base, 'system', 'file'))).to be_truthy
end
it 'does not move if the target directory already exists' do
FileUtils.mkdir_p(File.join(test_base, '-', 'system'))
expect(FileUtils).not_to receive(:mv)
expect(migration).to receive(:say).with(/already exists. No need to redo the move/)
migration.up
end
end
describe '#down' do
let(:test_folder) { File.join(test_base, '-', 'system') }
let(:test_file) { File.join(test_folder, 'file') }
before do
FileUtils.mkdir_p(test_folder)
FileUtils.touch(test_file)
end
it 'moves the system folder back to the old location' do
migration.down
expect(File.exist?(File.join(test_base, 'system', 'file'))).to be_truthy
end
it 'removes the symlink if it existed' do
FileUtils.ln_s(test_folder, File.join(test_base, 'system'))
migration.down
expect(File.directory?(File.join(test_base, 'system'))).to be_truthy
expect(File.symlink?(File.join(test_base, 'system'))).to be_falsey
end
it 'does not move if the old directory already exists' do
FileUtils.mkdir_p(File.join(test_base, 'system'))
expect(FileUtils).not_to receive(:mv)
expect(migration).to receive(:say).with(/already exists and is not a symlink, no need to revert/)
migration.down
end
end
end
require "spec_helper"
require Rails.root.join("db", "migrate", "20170316163845_move_uploads_to_system_dir.rb")
describe MoveUploadsToSystemDir do
let(:migration) { described_class.new }
let(:test_dir) { File.join(Rails.root, "tmp", "move_uploads_test") }
let(:uploads_dir) { File.join(test_dir, "public", "uploads") }
let(:new_uploads_dir) { File.join(uploads_dir, "-", "system") }
before do
FileUtils.remove_dir(test_dir) if File.directory?(test_dir)
FileUtils.mkdir_p(uploads_dir)
allow(migration).to receive(:base_directory).and_return(test_dir)
allow(migration).to receive(:say)
end
describe "#up" do
before do
FileUtils.mkdir_p(File.join(uploads_dir, 'user'))
FileUtils.touch(File.join(uploads_dir, 'user', 'dummy.file'))
end
it 'moves the directory to the new path' do
expected_path = File.join(new_uploads_dir, 'user', 'dummy.file')
migration.up
expect(File.exist?(expected_path)).to be(true)
end
it 'creates a symlink in the old location' do
symlink_path = File.join(uploads_dir, 'user')
expected_path = File.join(symlink_path, 'dummy.file')
migration.up
expect(File.exist?(expected_path)).to be(true)
expect(File.symlink?(symlink_path)).to be(true)
end
end
describe "#down" do
before do
FileUtils.mkdir_p(File.join(new_uploads_dir, 'user'))
FileUtils.touch(File.join(new_uploads_dir, 'user', 'dummy.file'))
end
it 'moves the directory to the old path' do
expected_path = File.join(uploads_dir, 'user', 'dummy.file')
migration.down
expect(File.exist?(expected_path)).to be(true)
end
it 'removes the symlink if it existed' do
FileUtils.ln_s(File.join(new_uploads_dir, 'user'), File.join(uploads_dir, 'user'))
directory = File.join(uploads_dir, 'user')
expected_path = File.join(directory, 'dummy.file')
migration.down
expect(File.exist?(expected_path)).to be(true)
expect(File.symlink?(directory)).to be(false)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170921101004_normalize_ldap_extern_uids')
describe NormalizeLdapExternUids, :migration, :sidekiq do
let!(:identities) { table(:identities) }
around do |example|
Timecop.freeze { example.run }
end
before do
stub_const("Gitlab::Database::MigrationHelpers::BACKGROUND_MIGRATION_BATCH_SIZE", 2)
stub_const("Gitlab::Database::MigrationHelpers::BACKGROUND_MIGRATION_JOB_BUFFER_SIZE", 2)
# LDAP identities
(1..4).each do |i|
identities.create!(id: i, provider: 'ldapmain', extern_uid: " uid = foo #{i}, ou = People, dc = example, dc = com ", user_id: i)
end
# Non-LDAP identity
identities.create!(id: 5, provider: 'foo', extern_uid: " uid = foo 5, ou = People, dc = example, dc = com ", user_id: 5)
end
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
Timecop.freeze do
migrate!
expect(BackgroundMigrationWorker.jobs[0]['args']).to eq([described_class::MIGRATION, [1, 2]])
expect(BackgroundMigrationWorker.jobs[0]['at']).to eq(2.minutes.from_now.to_f)
expect(BackgroundMigrationWorker.jobs[1]['args']).to eq([described_class::MIGRATION, [3, 4]])
expect(BackgroundMigrationWorker.jobs[1]['at']).to eq(4.minutes.from_now.to_f)
expect(BackgroundMigrationWorker.jobs[2]['args']).to eq([described_class::MIGRATION, [5, 5]])
expect(BackgroundMigrationWorker.jobs[2]['at']).to eq(6.minutes.from_now.to_f)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
end
it 'migrates the LDAP identities' do
perform_enqueued_jobs do
migrate!
identities.where(id: 1..4).each do |identity|
expect(identity.extern_uid).to eq("uid=foo #{identity.id},ou=people,dc=example,dc=com")
end
end
end
it 'does not modify non-LDAP identities' do
perform_enqueued_jobs do
migrate!
identity = identities.last
expect(identity.extern_uid).to eq(" uid = foo 5, ou = People, dc = example, dc = com ")
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20171215113714_populate_can_push_from_deploy_keys_projects.rb')
describe PopulateCanPushFromDeployKeysProjects, :migration do
let(:migration) { described_class.new }
let(:deploy_keys) { table(:keys) }
let(:deploy_keys_projects) { table(:deploy_keys_projects) }
let(:projects) { table(:projects) }
before do
deploy_keys.inheritance_column = nil
projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
(1..10).each do |index|
deploy_keys.create!(id: index, title: 'dummy', type: 'DeployKey', key: Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate + ' dummy@gitlab.com')
deploy_keys_projects.create!(id: index, deploy_key_id: index, project_id: 1)
end
end
describe '#up' do
it 'migrates can_push from deploy_keys to deploy_keys_projects' do
deploy_keys.limit(5).update_all(can_push: true)
expected = deploy_keys.order(:id).pluck(:id, :can_push)
migration.up
expect(deploy_keys_projects.order(:id).pluck(:deploy_key_id, :can_push)).to eq expected
end
end
describe '#down' do
it 'migrates can_push from deploy_keys_projects to deploy_keys' do
deploy_keys_projects.limit(5).update_all(can_push: true)
expected = deploy_keys_projects.order(:id).pluck(:deploy_key_id, :can_push)
migration.down
expect(deploy_keys.order(:id).pluck(:id, :can_push)).to eq expected
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170523073948_remove_assignee_id_from_issue.rb')
describe RemoveAssigneeIdFromIssue, :migration do
let(:issues) { table(:issues) }
let(:issue_assignees) { table(:issue_assignees) }
let(:users) { table(:users) }
let!(:user_1) { users.create(email: 'email1@example.com') }
let!(:user_2) { users.create(email: 'email2@example.com') }
let!(:user_3) { users.create(email: 'email3@example.com') }
def create_issue(assignees:)
issues.create.tap do |issue|
assignees.each do |assignee|
issue_assignees.create(issue_id: issue.id, user_id: assignee.id)
end
end
end
let!(:issue_single_assignee) { create_issue(assignees: [user_1]) }
let!(:issue_no_assignee) { create_issue(assignees: []) }
let!(:issue_multiple_assignees) { create_issue(assignees: [user_2, user_3]) }
describe '#down' do
it 'sets the assignee_id to a random matching assignee from the assignees table' do
migrate!
disable_migrations_output { described_class.new.down }
expect(issue_single_assignee.reload.assignee_id).to eq(user_1.id)
expect(issue_no_assignee.reload.assignee_id).to be_nil
expect(issue_multiple_assignees.reload.assignee_id).to eq(user_2.id).or(user_3.id)
disable_migrations_output { described_class.new.up }
end
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20161226122833_remove_dot_git_from_usernames.rb')
describe RemoveDotGitFromUsernames do
let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:migration) { described_class.new }
describe '#up' do
before do
update_namespace(user, 'test.git')
end
it 'renames user with .git in username' do
migration.up
expect(user.reload.username).to eq('test_git')
expect(user.namespace.reload.path).to eq('test_git')
expect(user.namespace.route.path).to eq('test_git')
end
end
context 'when new path exists already' do
describe '#up' do
let(:user2) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
before do
update_namespace(user, 'test.git')
update_namespace(user2, 'test_git')
default_hash = Gitlab.config.repositories.storages.default.to_h
default_hash['path'] = 'tmp/tests/custom_repositories'
storages = { 'default' => Gitlab::GitalyClient::StorageSettings.new(default_hash) }
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
allow(migration).to receive(:route_exists?).with('test_git').and_return(true)
allow(migration).to receive(:route_exists?).with('test_git1').and_return(false)
end
it 'renames user with .git in username' do
migration.up
expect(user.reload.username).to eq('test_git1')
expect(user.namespace.reload.path).to eq('test_git1')
expect(user.namespace.route.path).to eq('test_git1')
end
end
end
def update_namespace(user, path)
namespace = user.namespace
namespace.path = path
namespace.save!(validate: false)
user.update_column(:username, path)
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170815060945_remove_duplicate_mr_events.rb')
describe RemoveDuplicateMrEvents, :delete do
let(:migration) { described_class.new }
describe '#up' do
let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:merge_requests) { create_list(:merge_request, 2) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:issue) { create(:issue) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:events) do
[
create(:event, :created, author: user, target: merge_requests.first), # rubocop:disable RSpec/FactoriesInMigrationSpecs
create(:event, :created, author: user, target: merge_requests.first), # rubocop:disable RSpec/FactoriesInMigrationSpecs
create(:event, :updated, author: user, target: merge_requests.first), # rubocop:disable RSpec/FactoriesInMigrationSpecs
create(:event, :created, author: user, target: merge_requests.second), # rubocop:disable RSpec/FactoriesInMigrationSpecs
create(:event, :created, author: user, target: issue), # rubocop:disable RSpec/FactoriesInMigrationSpecs
create(:event, :created, author: user, target: issue) # rubocop:disable RSpec/FactoriesInMigrationSpecs
]
end
it 'removes duplicated merge request create records' do
expect { migration.up }.to change { Event.count }.from(6).to(5)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171114104051_remove_empty_fork_networks.rb')
describe RemoveEmptyForkNetworks, :migration do
let!(:fork_networks) { table(:fork_networks) }
let!(:projects) { table(:projects) }
let!(:fork_network_members) { table(:fork_network_members) }
let(:deleted_project) { projects.create! }
let!(:empty_network) { fork_networks.create!(id: 1, root_project_id: deleted_project.id) }
let!(:other_network) { fork_networks.create!(id: 2, root_project_id: projects.create.id) }
before do
fork_network_members.create(fork_network_id: empty_network.id,
project_id: empty_network.root_project_id)
fork_network_members.create(fork_network_id: other_network.id,
project_id: other_network.root_project_id)
deleted_project.destroy!
end
after do
Upload.reset_column_information
end
it 'deletes only the fork network without members' do
expect(fork_networks.count).to eq(2)
migrate!
expect(fork_networks.find_by(id: empty_network.id)).to be_nil
expect(fork_networks.find_by(id: other_network.id)).not_to be_nil
expect(fork_networks.count).to eq(1)
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170622135451_rename_duplicated_variable_key.rb')
describe RenameDuplicatedVariableKey, :migration do
let(:variables) { table(:ci_variables) }
let(:projects) { table(:projects) }
before do
projects.create!(id: 1)
variables.create!(id: 1, key: 'key1', project_id: 1)
variables.create!(id: 2, key: 'key2', project_id: 1)
variables.create!(id: 3, key: 'keyX', project_id: 1)
variables.create!(id: 4, key: 'keyX', project_id: 1)
variables.create!(id: 5, key: 'keyY', project_id: 1)
variables.create!(id: 6, key: 'keyX', project_id: 1)
variables.create!(id: 7, key: 'key7', project_id: 1)
variables.create!(id: 8, key: 'keyY', project_id: 1)
end
it 'correctly remove duplicated records with smaller id' do
migrate!
expect(variables.pluck(:id, :key)).to contain_exactly(
[1, 'key1'],
[2, 'key2'],
[3, 'keyX_3'],
[4, 'keyX_4'],
[5, 'keyY_5'],
[6, 'keyX'],
[7, 'key7'],
[8, 'keyY']
)
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170313133418_rename_more_reserved_project_names.rb')
# This migration uses multiple threads, and thus different transactions. This
# means data created in this spec may not be visible to some threads. To work
# around this we use the DELETE cleaning strategy.
describe RenameMoreReservedProjectNames, :delete do
let(:migration) { described_class.new }
let!(:project) { create(:project) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
before do
project.path = 'artifacts'
project.save!(validate: false)
end
describe '#up' do
context 'when project repository exists' do
before do
project.create_repository
end
context 'when no exception is raised' do
it 'renames project with reserved names' do
migration.up
expect(project.reload.path).to eq('artifacts0')
end
end
context 'when exception is raised during rename' do
before do
service = instance_double('service')
allow(service)
.to receive(:execute)
.and_raise(Projects::AfterRenameService::RenameFailedError)
expect(migration)
.to receive(:after_rename_service)
.and_return(service)
end
it 'captures exception from project rename' do
expect { migration.up }.not_to raise_error
end
end
end
context 'when project repository does not exist' do
it 'does not raise error' do
expect { migration.up }.not_to raise_error
end
end
end
end
# encoding: utf-8
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20161221153951_rename_reserved_project_names.rb')
# This migration is using factories, which set fields that don't actually
# exist in the DB schema previous to 20161221153951. Thus we just use the
# latest schema when testing this migration.
# This is ok-ish because:
# 1. This migration is a data migration
# 2. It only relies on very stable DB fields: routes.id, routes.path, namespaces.id, projects.namespace_id
# Ideally, the test should not use factories and rely on the `table` helper instead.
describe RenameReservedProjectNames, :migration, schema: :latest do
let(:migration) { described_class.new }
let!(:project) { create(:project) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
before do
project.path = 'projects'
project.save!(validate: false)
end
describe '#up' do
context 'when project repository exists' do
before do
project.create_repository
end
context 'when no exception is raised' do
it 'renames project with reserved names' do
migration.up
expect(project.reload.path).to eq('projects0')
end
end
context 'when exception is raised during rename' do
before do
service = instance_double('service')
allow(service)
.to receive(:execute)
.and_raise(Projects::AfterRenameService::RenameFailedError)
expect(migration)
.to receive(:after_rename_service)
.and_return(service)
end
it 'captures exception from project rename' do
expect { migration.up }.not_to raise_error
end
end
end
context 'when project repository does not exist' do
it 'does not raise error' do
expect { migration.up }.not_to raise_error
end
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170518200835_rename_users_with_renamed_namespace.rb')
describe RenameUsersWithRenamedNamespace, :delete do
it 'renames a user that had their namespace renamed to the namespace path' do
other_user = create(:user, username: 'kodingu') # rubocop:disable RSpec/FactoriesInMigrationSpecs
other_user1 = create(:user, username: 'api0') # rubocop:disable RSpec/FactoriesInMigrationSpecs
user = create(:user, username: "Users0") # rubocop:disable RSpec/FactoriesInMigrationSpecs
user.update_column(:username, 'Users')
user1 = create(:user, username: "import0") # rubocop:disable RSpec/FactoriesInMigrationSpecs
user1.update_column(:username, 'import')
described_class.new.up
expect(user.reload.username).to eq('Users0')
expect(user1.reload.username).to eq('import0')
expect(other_user.reload.username).to eq('kodingu')
expect(other_user1.reload.username).to eq('api0')
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations')
describe ScheduleMergeRequestLatestMergeRequestDiffIdMigrations, :migration, :sidekiq do
let(:projects_table) { table(:projects) }
let(:merge_requests_table) { table(:merge_requests) }
let(:merge_request_diffs_table) { table(:merge_request_diffs) }
let(:project) { projects_table.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce') }
let!(:merge_request_1) { create_mr!('mr_1', diffs: 1) }
let!(:merge_request_2) { create_mr!('mr_2', diffs: 2) }
let!(:merge_request_migrated) { create_mr!('merge_request_migrated', diffs: 3) }
let!(:merge_request_4) { create_mr!('mr_4', diffs: 3) }
def create_mr!(name, diffs: 0)
merge_request =
merge_requests_table.create!(target_project_id: project.id,
target_branch: 'master',
source_project_id: project.id,
source_branch: name,
title: name)
diffs.times do
merge_request_diffs_table.create!(merge_request_id: merge_request.id)
end
merge_request
end
def diffs_for(merge_request)
merge_request_diffs_table.where(merge_request_id: merge_request.id)
end
before do
stub_const("#{described_class.name}::BATCH_SIZE", 1)
diff_id = diffs_for(merge_request_migrated).minimum(:id)
merge_request_migrated.update!(latest_merge_request_diff_id: diff_id)
end
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
Timecop.freeze do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, merge_request_1.id, merge_request_1.id)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, merge_request_2.id, merge_request_2.id)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(15.minutes, merge_request_4.id, merge_request_4.id)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
end
it 'schedules background migrations' do
perform_enqueued_jobs do
expect(merge_requests_table.where(latest_merge_request_diff_id: nil).count).to eq 3
migrate!
expect(merge_requests_table.where(latest_merge_request_diff_id: nil).count).to eq 0
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171103140253_track_untracked_uploads')
describe TrackUntrackedUploads, :migration, :sidekiq do
include MigrationsHelpers::TrackUntrackedUploadsHelpers
it 'correctly schedules the follow-up background migration' do
Sidekiq::Testing.fake! do
migrate!
expect(described_class::MIGRATION).to be_scheduled_migration
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb')
describe TurnNestedGroupsIntoRegularGroupsForMysql do
let!(:parent_group) { create(:group) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:child_group) { create(:group, parent: parent_group) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:project) { create(:project, :legacy_storage, :empty_repo, namespace: child_group) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:member) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:migration) { described_class.new }
before do
parent_group.add_developer(member)
allow(migration).to receive(:run_migration?).and_return(true)
allow(migration).to receive(:verbose).and_return(false)
end
describe '#up' do
let(:updated_project) do
# path_with_namespace is memoized in an instance variable so we retrieve a
# new row here to work around that.
Project.find(project.id)
end
before do
migration.up
end
it 'unsets the parent_id column' do
expect(Namespace.where('parent_id IS NOT NULL').any?).to eq(false)
end
it 'adds members of parent groups as members to the migrated group' do
is_member = child_group.members
.where(user_id: member, access_level: Gitlab::Access::DEVELOPER).any?
expect(is_member).to eq(true)
end
it 'update the path of the nested group' do
child_group.reload
expect(child_group.path).to eq("#{parent_group.name}-#{child_group.name}")
end
it 'renames projects of the nested group' do
expect(updated_project.full_path)
.to eq("#{parent_group.name}-#{child_group.name}/#{updated_project.path}")
end
it 'renames the repository of any projects' do
repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
updated_project.repository.path
end
expect(repo_path)
.to end_with("#{parent_group.name}-#{child_group.name}/#{updated_project.path}.git")
expect(File.directory?(repo_path)).to eq(true)
end
it 'creates a redirect route for renamed projects' do
exists = RedirectRoute
.where(source_type: 'Project', source_id: project.id)
.any?
expect(exists).to eq(true)
end
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170927112318_update_legacy_diff_notes_type_for_import.rb')
describe UpdateLegacyDiffNotesTypeForImport, :migration do
let(:notes) { table(:notes) }
before do
notes.inheritance_column = nil
notes.create(type: 'Note')
notes.create(type: 'LegacyDiffNote')
notes.create(type: 'Github::Import::Note')
notes.create(type: 'Github::Import::LegacyDiffNote')
end
it 'updates the notes type' do
migrate!
expect(notes.pluck(:type))
.to contain_exactly('Note', 'Github::Import::Note', 'LegacyDiffNote', 'LegacyDiffNote')
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170927112319_update_notes_type_for_import.rb')
describe UpdateNotesTypeForImport, :migration do
let(:notes) { table(:notes) }
before do
notes.inheritance_column = nil
notes.create(type: 'Note')
notes.create(type: 'LegacyDiffNote')
notes.create(type: 'Github::Import::Note')
notes.create(type: 'Github::Import::LegacyDiffNote')
end
it 'updates the notes type' do
migrate!
expect(notes.pluck(:type))
.to contain_exactly('Note', 'Note', 'LegacyDiffNote', 'Github::Import::LegacyDiffNote')
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170503004427_update_retried_for_ci_build.rb')
describe UpdateRetriedForCiBuild, :delete do
let(:pipeline) { create(:ci_pipeline) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:build_old) { create(:ci_build, pipeline: pipeline, name: 'test') } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let!(:build_new) { create(:ci_build, pipeline: pipeline, name: 'test') } # rubocop:disable RSpec/FactoriesInMigrationSpecs
before do
described_class.new.up
end
it 'updates ci_builds.is_retried' do
expect(build_old.reload).to be_retried
expect(build_new.reload).not_to be_retried
end
end
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170317162059_update_upload_paths_to_system.rb')
describe UpdateUploadPathsToSystem, :migration do
let(:migration) { described_class.new }
let(:uploads_table) { table(:uploads) }
let(:base_upload_attributes) { { size: 42, uploader: 'John Doe' } }
before do
allow(migration).to receive(:say)
end
describe '#uploads_to_switch_to_new_path' do
it 'contains only uploads with the old path for the correct models' do
_upload_for_other_type = create_upload('Pipeline', 'uploads/ci_pipeline/avatar.jpg')
_upload_with_system_path = create_upload('Project', 'uploads/-/system/project/avatar.jpg')
_upload_with_other_path = create_upload('Project', 'thelongsecretforafileupload/avatar.jpg')
old_upload = create_upload('Project', 'uploads/project/avatar.jpg')
group_upload = create_upload('Namespace', 'uploads/group/avatar.jpg')
expect(uploads_table.where(migration.uploads_to_switch_to_new_path)).to contain_exactly(old_upload, group_upload)
end
end
describe '#uploads_to_switch_to_old_path' do
it 'contains only uploads with the new path for the correct models' do
_upload_for_other_type = create_upload('Pipeline', 'uploads/ci_pipeline/avatar.jpg')
upload_with_system_path = create_upload('Project', 'uploads/-/system/project/avatar.jpg')
_upload_with_other_path = create_upload('Project', 'thelongsecretforafileupload/avatar.jpg')
_old_upload = create_upload('Project', 'uploads/project/avatar.jpg')
expect(uploads_table.where(migration.uploads_to_switch_to_old_path)).to contain_exactly(upload_with_system_path)
end
end
describe '#up' do
it 'updates old upload records to the new path' do
old_upload = create_upload('Project', 'uploads/project/avatar.jpg')
migration.up
expect(old_upload.reload.path).to eq('uploads/-/system/project/avatar.jpg')
end
end
describe '#down' do
it 'updates the new system patsh to the old paths' do
new_upload = create_upload('Project', 'uploads/-/system/project/avatar.jpg')
migration.down
expect(new_upload.reload.path).to eq('uploads/project/avatar.jpg')
end
end
def create_upload(type, path)
uploads_table.create(base_upload_attributes.merge(model_type: type, path: path))
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