Commit b010130b authored by Adrien Kohlbecker's avatar Adrien Kohlbecker Committed by Shinya Maeda

Fix project transfer corrupting shared runners state

Fix project transfer corrupting shared runners state
parent d7ed14ee
---
title: Fix project transfer corrupting shared runners state
merge_request: 47316
author:
type: fixed
# frozen_string_literal: true
class CleanupTransferedProjectsSharedRunners < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
BATCH_SIZE = 25_000
INTERVAL = 3.minutes
MIGRATION = 'ResetSharedRunnersForTransferredProjects'
disable_ddl_transaction!
class Namespace < ActiveRecord::Base
include EachBatch
self.table_name = 'namespaces'
end
def up
queue_background_migration_jobs_by_range_at_intervals(Namespace,
MIGRATION,
INTERVAL,
batch_size: BATCH_SIZE)
end
def down
# This migration fixes an inconsistent database state resulting from https://gitlab.com/gitlab-org/gitlab/-/issues/271728
# and as such does not require a down migration
end
end
ebc304867bab499da3f9fa69b32373a328948b5068b226df5166042d1c1c7604
\ No newline at end of file
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# Resets inconsistent state of shared_runners_enabled for projects that have been transferred
class ResetSharedRunnersForTransferredProjects
# Model specifically used for migration.
class Namespace < ActiveRecord::Base
include EachBatch
self.table_name = 'namespaces'
end
# Model specifically used for migration.
class Project < ActiveRecord::Base
self.table_name = 'projects'
end
def perform(start_id, stop_id)
Project.reset_column_information
Namespace.where(id: start_id..stop_id).each_batch(of: 1_000) do |relation|
ids = relation.where(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false).select(:id)
Project.where(namespace_id: ids).update_all(shared_runners_enabled: false)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::ResetSharedRunnersForTransferredProjects, schema: 20201110161542 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:namespace_1) { namespaces.create!(name: 'foo', path: 'foo', shared_runners_enabled: true, allow_descendants_override_disabled_shared_runners: false ) }
let(:namespace_2) { namespaces.create!(name: 'foo', path: 'foo', shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false ) }
let(:namespace_3) { namespaces.create!(name: 'bar', path: 'bar', shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: true ) }
let(:project_1_1) { projects.create!(namespace_id: namespace_1.id, shared_runners_enabled: true) }
let(:project_1_2) { projects.create!(namespace_id: namespace_1.id, shared_runners_enabled: false) }
let(:project_2_1) { projects.create!(namespace_id: namespace_2.id, shared_runners_enabled: true) }
let(:project_2_2) { projects.create!(namespace_id: namespace_2.id, shared_runners_enabled: false) }
let(:project_3_1) { projects.create!(namespace_id: namespace_3.id, shared_runners_enabled: true) }
let(:project_3_2) { projects.create!(namespace_id: namespace_3.id, shared_runners_enabled: false) }
it 'corrects each project shared_runners_enabled column' do
expect do
described_class.new.perform(namespace_1.id, namespace_3.id)
project_1_1.reload
project_1_2.reload
project_2_1.reload
project_2_2.reload
project_3_1.reload
project_3_2.reload
end.to not_change(project_1_1, :shared_runners_enabled).from(true)
.and not_change(project_1_2, :shared_runners_enabled).from(false)
.and change(project_2_1, :shared_runners_enabled).from(true).to(false)
.and not_change(project_2_2, :shared_runners_enabled).from(false)
.and not_change(project_3_1, :shared_runners_enabled).from(true)
.and not_change(project_3_2, :shared_runners_enabled).from(false)
end
end
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20201110161542_cleanup_transfered_projects_shared_runners.rb')
RSpec.describe CleanupTransferedProjectsSharedRunners, :sidekiq, schema: 20201110161542 do
let(:namespaces) { table(:namespaces) }
let(:migration) { described_class.new }
let(:batch_interval) { described_class::INTERVAL }
let!(:namespace_1) { namespaces.create!(name: 'foo', path: 'foo') }
let!(:namespace_2) { namespaces.create!(name: 'bar', path: 'bar') }
let!(:namespace_3) { namespaces.create!(name: 'baz', path: 'baz') }
describe '#up' do
before do
stub_const("#{described_class}::BATCH_SIZE", 2)
end
it 'schedules ResetSharedRunnersForTransferredProjects background jobs' do
Sidekiq::Testing.fake! do
freeze_time do
migration.up
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, namespace_1.id, namespace_2.id)
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval * 2, namespace_3.id, namespace_3.id)
end
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