summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/background_migration
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/background_migration')
-rw-r--r--spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb16
-rw-r--r--spec/lib/gitlab/background_migration/backfill_group_features_spec.rb28
-rw-r--r--spec/lib/gitlab/background_migration/backfill_incident_issue_escalation_statuses_spec.rb27
-rw-r--r--spec/lib/gitlab/background_migration/backfill_issue_search_data_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_id_for_project_route_spec.rb53
-rw-r--r--spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb67
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/backfill_issue_work_item_type_batching_strategy_spec.rb135
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb29
-rw-r--r--spec/lib/gitlab/background_migration/cleanup_draft_data_from_faulty_regex_spec.rb54
-rw-r--r--spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb8
-rw-r--r--spec/lib/gitlab/background_migration/fix_duplicate_project_name_and_path_spec.rb65
-rw-r--r--spec/lib/gitlab/background_migration/merge_topics_with_same_name_spec.rb135
-rw-r--r--spec/lib/gitlab/background_migration/migrate_shimo_confluence_integration_category_spec.rb28
-rw-r--r--spec/lib/gitlab/background_migration/populate_container_repository_migration_plan_spec.rb44
-rw-r--r--spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb71
-rw-r--r--spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb2
23 files changed, 737 insertions, 41 deletions
diff --git a/spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb
index a7895623d6f..1158eedfe7c 100644
--- a/spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillDraftStatusOnMergeRequests do
+RSpec.describe Gitlab::BackgroundMigration::BackfillDraftStatusOnMergeRequests, :migration, schema: 20220326161803 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:merge_requests) { table(:merge_requests) }
@@ -50,5 +50,19 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillDraftStatusOnMergeRequests d
subject.perform(mr_ids.first, mr_ids.last)
end
+
+ it_behaves_like 'marks background migration job records' do
+ let!(:non_eligible_mrs) do
+ Array.new(2) do
+ create_merge_request(
+ title: "Not a d-r-a-f-t 1",
+ draft: false,
+ state_id: 1
+ )
+ end
+ end
+
+ let(:arguments) { [non_eligible_mrs.first.id, non_eligible_mrs.last.id] }
+ end
end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
new file mode 100644
index 00000000000..4705f0d0ab9
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillGroupFeatures, :migration, schema: 20220302114046 do
+ let(:group_features) { table(:group_features) }
+ let(:namespaces) { table(:namespaces) }
+
+ subject { described_class.new(connection: ActiveRecord::Base.connection) }
+
+ describe '#perform' do
+ it 'creates settings for all group namespaces in range' do
+ namespaces.create!(id: 1, name: 'group1', path: 'group1', type: 'Group')
+ namespaces.create!(id: 2, name: 'user', path: 'user')
+ namespaces.create!(id: 3, name: 'group2', path: 'group2', type: 'Group')
+
+ # Checking that no error is raised if the group_feature for a group already exists
+ namespaces.create!(id: 4, name: 'group3', path: 'group3', type: 'Group')
+ group_features.create!(id: 1, group_id: 4)
+ expect(group_features.count).to eq 1
+
+ expect { subject.perform(1, 4, :namespaces, :id, 10, 0, 4) }.to change { group_features.count }.by(2)
+
+ expect(group_features.count).to eq 3
+ expect(group_features.all.pluck(:group_id)).to contain_exactly(1, 3, 4)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_incident_issue_escalation_statuses_spec.rb b/spec/lib/gitlab/background_migration/backfill_incident_issue_escalation_statuses_spec.rb
deleted file mode 100644
index 242da383453..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_incident_issue_escalation_statuses_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillIncidentIssueEscalationStatuses, schema: 20211214012507 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:issues) { table(:issues) }
- let(:issuable_escalation_statuses) { table(:incident_management_issuable_escalation_statuses) }
-
- subject(:migration) { described_class.new }
-
- it 'correctly backfills issuable escalation status records' do
- namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- issues.create!(project_id: project.id, title: 'issue 1', issue_type: 0) # non-incident issue
- issues.create!(project_id: project.id, title: 'incident 1', issue_type: 1)
- issues.create!(project_id: project.id, title: 'incident 2', issue_type: 1)
- incident_issue_existing_status = issues.create!(project_id: project.id, title: 'incident 3', issue_type: 1)
- issuable_escalation_statuses.create!(issue_id: incident_issue_existing_status.id)
-
- migration.perform(1, incident_issue_existing_status.id)
-
- expect(issuable_escalation_statuses.count).to eq(3)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_issue_search_data_spec.rb b/spec/lib/gitlab/background_migration/backfill_issue_search_data_spec.rb
index b29d4c3583b..f98aea2dda7 100644
--- a/spec/lib/gitlab/background_migration/backfill_issue_search_data_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_issue_search_data_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillIssueSearchData do
+RSpec.describe Gitlab::BackgroundMigration::BackfillIssueSearchData, :migration, schema: 20220326161803 do
let(:namespaces_table) { table(:namespaces) }
let(:projects_table) { table(:projects) }
let(:issue_search_data_table) { table(:issue_search_data) }
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_id_for_project_route_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_project_route_spec.rb
new file mode 100644
index 00000000000..2dcd4645c84
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_project_route_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdForProjectRoute do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:routes) { table(:routes) }
+
+ let(:namespace1) { namespaces.create!(name: 'batchtest1', type: 'Group', path: 'space1') }
+ let(:namespace2) { namespaces.create!(name: 'batchtest2', type: 'Group', parent_id: namespace1.id, path: 'space2') }
+ let(:namespace3) { namespaces.create!(name: 'batchtest3', type: 'Group', parent_id: namespace2.id, path: 'space3') }
+
+ let(:proj_namespace1) { namespaces.create!(name: 'proj1', path: 'proj1', type: 'Project', parent_id: namespace1.id) }
+ let(:proj_namespace2) { namespaces.create!(name: 'proj2', path: 'proj2', type: 'Project', parent_id: namespace2.id) }
+ let(:proj_namespace3) { namespaces.create!(name: 'proj3', path: 'proj3', type: 'Project', parent_id: namespace3.id) }
+ let(:proj_namespace4) { namespaces.create!(name: 'proj4', path: 'proj4', type: 'Project', parent_id: namespace3.id) }
+
+ # rubocop:disable Layout/LineLength
+ let(:proj1) { projects.create!(name: 'proj1', path: 'proj1', namespace_id: namespace1.id, project_namespace_id: proj_namespace1.id) }
+ let(:proj2) { projects.create!(name: 'proj2', path: 'proj2', namespace_id: namespace2.id, project_namespace_id: proj_namespace2.id) }
+ let(:proj3) { projects.create!(name: 'proj3', path: 'proj3', namespace_id: namespace3.id, project_namespace_id: proj_namespace3.id) }
+ let(:proj4) { projects.create!(name: 'proj4', path: 'proj4', namespace_id: namespace3.id, project_namespace_id: proj_namespace4.id) }
+ # rubocop:enable Layout/LineLength
+
+ let!(:namespace_route1) { routes.create!(path: 'space1', source_id: namespace1.id, source_type: 'Namespace') }
+ let!(:namespace_route2) { routes.create!(path: 'space1/space2', source_id: namespace2.id, source_type: 'Namespace') }
+ let!(:namespace_route3) { routes.create!(path: 'space1/space3', source_id: namespace3.id, source_type: 'Namespace') }
+
+ let!(:proj_route1) { routes.create!(path: 'space1/proj1', source_id: proj1.id, source_type: 'Project') }
+ let!(:proj_route2) { routes.create!(path: 'space1/space2/proj2', source_id: proj2.id, source_type: 'Project') }
+ let!(:proj_route3) { routes.create!(path: 'space1/space3/proj3', source_id: proj3.id, source_type: 'Project') }
+ let!(:proj_route4) { routes.create!(path: 'space1/space3/proj4', source_id: proj4.id, source_type: 'Project') }
+
+ subject(:perform_migration) { migration.perform(proj_route1.id, proj_route4.id, :routes, :id, 2, 0) }
+
+ it 'backfills namespace_id for the selected records', :aggregate_failures do
+ perform_migration
+
+ expected_namespaces = [proj_namespace1.id, proj_namespace2.id, proj_namespace3.id, proj_namespace4.id]
+
+ expected_projects = [proj_route1.id, proj_route2.id, proj_route3.id, proj_route4.id]
+ expect(routes.where.not(namespace_id: nil).pluck(:id)).to match_array(expected_projects)
+ expect(routes.where.not(namespace_id: nil).pluck(:namespace_id)).to match_array(expected_namespaces)
+ end
+
+ it 'tracks timings of queries' do
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { perform_migration }.to change { migration.batch_metrics.timings }
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb b/spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb
new file mode 100644
index 00000000000..8d82c533d20
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillWorkItemTypeIdForIssues, :migration, schema: 20220326161803 do
+ subject(:migrate) { migration.perform(start_id, end_id, batch_table, batch_column, sub_batch_size, pause_ms, issue_type_enum[:issue], issue_type.id) }
+
+ let(:migration) { described_class.new }
+
+ let(:batch_table) { 'issues' }
+ let(:batch_column) { 'id' }
+ let(:sub_batch_size) { 2 }
+ let(:pause_ms) { 0 }
+
+ # let_it_be can't be used in migration specs because all tables but `work_item_types` are deleted after each spec
+ let(:issue_type_enum) { { issue: 0, incident: 1, test_case: 2, requirement: 3, task: 4 } }
+ let(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let(:issues_table) { table(:issues) }
+ let(:issue_type) { table(:work_item_types).find_by!(namespace_id: nil, base_type: issue_type_enum[:issue]) }
+
+ let(:issue1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let(:issue2) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let(:issue3) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let(:incident1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:incident]) }
+ # test_case and requirement are EE only, but enum values exist on the FOSS model
+ let(:test_case1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:test_case]) }
+ let(:requirement1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:requirement]) }
+
+ let(:start_id) { issue1.id }
+ let(:end_id) { requirement1.id }
+
+ let(:all_issues) { [issue1, issue2, issue3, incident1, test_case1, requirement1] }
+
+ it 'sets work_item_type_id only for the given type' do
+ expect(all_issues).to all(have_attributes(work_item_type_id: nil))
+
+ expect { migrate }.to make_queries_matching(/UPDATE \"issues\" SET "work_item_type_id"/, 2)
+ all_issues.each(&:reload)
+
+ expect([issue1, issue2, issue3]).to all(have_attributes(work_item_type_id: issue_type.id))
+ expect(all_issues - [issue1, issue2, issue3]).to all(have_attributes(work_item_type_id: nil))
+ end
+
+ it 'tracks timings of queries' do
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { migrate }.to change { migration.batch_metrics.timings }
+ end
+
+ context 'when database timeouts' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(error_class: [ActiveRecord::StatementTimeout, ActiveRecord::QueryCanceled])
+
+ with_them do
+ it 'retries on timeout error' do
+ expect(migration).to receive(:update_batch).exactly(3).times.and_raise(error_class)
+ expect(migration).to receive(:sleep).with(30).twice
+
+ expect do
+ migrate
+ end.to raise_error(error_class)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/backfill_issue_work_item_type_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/backfill_issue_work_item_type_batching_strategy_spec.rb
new file mode 100644
index 00000000000..3cba99bfe51
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/batching_strategies/backfill_issue_work_item_type_batching_strategy_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillIssueWorkItemTypeBatchingStrategy, '#next_batch', schema: 20220326161803 do # rubocop:disable Layout/LineLength
+ # let! can't be used in migration specs because all tables but `work_item_types` are deleted after each spec
+ let!(:issue_type_enum) { { issue: 0, incident: 1, test_case: 2, requirement: 3, task: 4 } }
+ let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
+ let!(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let!(:issues_table) { table(:issues) }
+ let!(:task_type) { table(:work_item_types).find_by!(namespace_id: nil, base_type: issue_type_enum[:task]) }
+
+ let!(:issue1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let!(:task1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:task]) }
+ let!(:issue2) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let!(:issue3) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:issue]) }
+ let!(:task2) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:task]) }
+ let!(:incident1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:incident]) }
+ # test_case is EE only, but enum values exist on the FOSS model
+ let!(:test_case1) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:test_case]) }
+
+ let!(:task3) do
+ issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:task], work_item_type_id: task_type.id)
+ end
+
+ let!(:task4) { issues_table.create!(project_id: project.id, issue_type: issue_type_enum[:task]) }
+
+ let!(:batching_strategy) { described_class.new(connection: ActiveRecord::Base.connection) }
+
+ context 'when issue_type is issue' do
+ let(:job_arguments) { [issue_type_enum[:issue], 'irrelevant_work_item_id'] }
+
+ context 'when starting on the first batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = next_batch(issue1.id, 2)
+
+ expect(batch_bounds).to match_array([issue1.id, issue2.id])
+ end
+ end
+
+ context 'when additional batches remain' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = next_batch(issue2.id, 2)
+
+ expect(batch_bounds).to match_array([issue2.id, issue3.id])
+ end
+ end
+
+ context 'when on the final batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = next_batch(issue3.id, 2)
+
+ expect(batch_bounds).to match_array([issue3.id, issue3.id])
+ end
+ end
+
+ context 'when no additional batches remain' do
+ it 'returns nil' do
+ batch_bounds = next_batch(issue3.id + 1, 1)
+
+ expect(batch_bounds).to be_nil
+ end
+ end
+ end
+
+ context 'when issue_type is incident' do
+ let(:job_arguments) { [issue_type_enum[:incident], 'irrelevant_work_item_id'] }
+
+ context 'when starting on the first batch' do
+ it 'returns the bounds of the next batch with only one element' do
+ batch_bounds = next_batch(incident1.id, 2)
+
+ expect(batch_bounds).to match_array([incident1.id, incident1.id])
+ end
+ end
+ end
+
+ context 'when issue_type is requirement and there are no matching records' do
+ let(:job_arguments) { [issue_type_enum[:requirement], 'irrelevant_work_item_id'] }
+
+ context 'when starting on the first batch' do
+ it 'returns nil' do
+ batch_bounds = next_batch(1, 2)
+
+ expect(batch_bounds).to be_nil
+ end
+ end
+ end
+
+ context 'when issue_type is task' do
+ let(:job_arguments) { [issue_type_enum[:task], 'irrelevant_work_item_id'] }
+
+ context 'when starting on the first batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = next_batch(task1.id, 2)
+
+ expect(batch_bounds).to match_array([task1.id, task2.id])
+ end
+ end
+
+ context 'when additional batches remain' do
+ it 'returns the bounds of the next batch, does not skip records where FK is already set' do
+ batch_bounds = next_batch(task2.id, 2)
+
+ expect(batch_bounds).to match_array([task2.id, task3.id])
+ end
+ end
+
+ context 'when on the final batch' do
+ it 'returns the bounds of the next batch' do
+ batch_bounds = next_batch(task4.id, 2)
+
+ expect(batch_bounds).to match_array([task4.id, task4.id])
+ end
+ end
+
+ context 'when no additional batches remain' do
+ it 'returns nil' do
+ batch_bounds = next_batch(task4.id + 1, 1)
+
+ expect(batch_bounds).to be_nil
+ end
+ end
+ end
+
+ def next_batch(min_value, batch_size)
+ batching_strategy.next_batch(
+ :issues,
+ :id,
+ batch_min_value: min_value,
+ batch_size: batch_size,
+ job_arguments: job_arguments
+ )
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb
index b01dd5b410e..dc0935efa94 100644
--- a/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb
+++ b/spec/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillProjectNamespacePerGroupBatchingStrategy, '#next_batch' do
+RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillProjectNamespacePerGroupBatchingStrategy, '#next_batch', :migration, schema: 20220326161803 do
let!(:namespaces) { table(:namespaces) }
let!(:projects) { table(:projects) }
let!(:background_migrations) { table(:batched_background_migrations) }
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
index 4e0ebd4b692..521e2067744 100644
--- a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
+++ b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when starting on the first batch' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3, job_arguments: nil)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3, job_arguments: [])
expect(batch_bounds).to eq([namespace1.id, namespace3.id])
end
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when additional batches remain' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3, job_arguments: nil)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3, job_arguments: [])
expect(batch_bounds).to eq([namespace2.id, namespace4.id])
end
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when on the final batch' do
it 'returns the bounds of the next batch' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3, job_arguments: nil)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3, job_arguments: [])
expect(batch_bounds).to eq([namespace4.id, namespace4.id])
end
@@ -39,9 +39,30 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when no additional batches remain' do
it 'returns nil' do
- batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1, job_arguments: nil)
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1, job_arguments: [])
expect(batch_bounds).to be_nil
end
end
+
+ context 'additional filters' do
+ let(:strategy_with_filters) do
+ Class.new(described_class) do
+ def apply_additional_filters(relation, job_arguments:)
+ min_id = job_arguments.first
+
+ relation.where.not(type: 'Project').where('id >= ?', min_id)
+ end
+ end
+ end
+
+ let(:batching_strategy) { strategy_with_filters.new(connection: ActiveRecord::Base.connection) }
+ let!(:namespace5) { namespaces.create!(name: 'batchtest5', path: 'batch-test5', type: 'Project') }
+
+ it 'applies additional filters' do
+ batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3, job_arguments: [1])
+
+ expect(batch_bounds).to eq([namespace4.id, namespace4.id])
+ end
+ end
end
diff --git a/spec/lib/gitlab/background_migration/cleanup_draft_data_from_faulty_regex_spec.rb b/spec/lib/gitlab/background_migration/cleanup_draft_data_from_faulty_regex_spec.rb
new file mode 100644
index 00000000000..d1ef7ca2188
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/cleanup_draft_data_from_faulty_regex_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::CleanupDraftDataFromFaultyRegex, :migration, schema: 20220326161803 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:merge_requests) { table(:merge_requests) }
+
+ let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') }
+ let(:project) { projects.create!(namespace_id: group.id) }
+
+ let(:draft_prefixes) { ["[Draft]", "(Draft)", "Draft:", "Draft", "[WIP]", "WIP:", "WIP"] }
+
+ def create_merge_request(params)
+ common_params = {
+ target_project_id: project.id,
+ target_branch: 'feature1',
+ source_branch: 'master'
+ }
+
+ merge_requests.create!(common_params.merge(params))
+ end
+
+ context "mr.draft == true, and title matches the leaky regex and not the corrected regex" do
+ let(:mr_ids) { merge_requests.all.collect(&:id) }
+
+ before do
+ draft_prefixes.each do |prefix|
+ (1..4).each do |n|
+ create_merge_request(
+ title: "#{prefix} This is a title",
+ draft: true,
+ state_id: 1
+ )
+ end
+ end
+
+ create_merge_request(title: "This has draft in the title", draft: true, state_id: 1)
+ end
+
+ it "updates all open draft merge request's draft field to true" do
+ expect { subject.perform(mr_ids.first, mr_ids.last) }
+ .to change { MergeRequest.where(draft: true).count }
+ .by(-1)
+ end
+
+ it "marks successful slices as completed" do
+ expect(subject).to receive(:mark_job_as_succeeded).with(mr_ids.first, mr_ids.last)
+
+ subject.perform(mr_ids.first, mr_ids.last)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb b/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb
index 04eb9ad475f..8a63673bf38 100644
--- a/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb
+++ b/spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::DisableExpirationPoliciesLinkedToNoContainerImages do
+RSpec.describe Gitlab::BackgroundMigration::DisableExpirationPoliciesLinkedToNoContainerImages, :migration, schema: 20220326161803 do # rubocop:disable Layout/LineLength
let_it_be(:projects) { table(:projects) }
let_it_be(:container_expiration_policies) { table(:container_expiration_policies) }
let_it_be(:container_repositories) { table(:container_repositories) }
diff --git a/spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb b/spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb
index 94d9f4509a7..4e7b97d33f6 100644
--- a/spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb
+++ b/spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb
@@ -39,6 +39,14 @@ RSpec.describe Gitlab::BackgroundMigration::EncryptStaticObjectToken do
expect(new_state[user_with_encrypted_token.id]).to match_array([nil, 'encrypted'])
end
+ context 'when id range does not include existing user ids' do
+ let(:arguments) { [non_existing_record_id, non_existing_record_id.succ] }
+
+ it_behaves_like 'marks background migration job records' do
+ subject { described_class.new }
+ end
+ end
+
private
def create_user!(name:, token: nil, encrypted_token: nil)
diff --git a/spec/lib/gitlab/background_migration/fix_duplicate_project_name_and_path_spec.rb b/spec/lib/gitlab/background_migration/fix_duplicate_project_name_and_path_spec.rb
new file mode 100644
index 00000000000..65663d26f37
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/fix_duplicate_project_name_and_path_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::FixDuplicateProjectNameAndPath, :migration, schema: 20220325155953 do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:routes) { table(:routes) }
+
+ let(:namespace1) { namespaces.create!(name: 'batchtest1', type: 'Group', path: 'batch-test1') }
+ let(:namespace2) { namespaces.create!(name: 'batchtest2', type: 'Group', parent_id: namespace1.id, path: 'batch-test2') }
+ let(:namespace3) { namespaces.create!(name: 'batchtest3', type: 'Group', parent_id: namespace2.id, path: 'batch-test3') }
+
+ let(:project_namespace2) { namespaces.create!(name: 'project2', path: 'project2', type: 'Project', parent_id: namespace2.id, visibility_level: 20) }
+ let(:project_namespace3) { namespaces.create!(name: 'project3', path: 'project3', type: 'Project', parent_id: namespace3.id, visibility_level: 20) }
+
+ let(:project1) { projects.create!(name: 'project1', path: 'project1', namespace_id: namespace1.id, visibility_level: 20) }
+ let(:project2) { projects.create!(name: 'project2', path: 'project2', namespace_id: namespace2.id, project_namespace_id: project_namespace2.id, visibility_level: 20) }
+ let(:project2_dup) { projects.create!(name: 'project2', path: 'project2', namespace_id: namespace2.id, visibility_level: 20) }
+ let(:project3) { projects.create!(name: 'project3', path: 'project3', namespace_id: namespace3.id, project_namespace_id: project_namespace3.id, visibility_level: 20) }
+ let(:project3_dup) { projects.create!(name: 'project3', path: 'project3', namespace_id: namespace3.id, visibility_level: 20) }
+
+ let!(:namespace_route1) { routes.create!(path: 'batch-test1', source_id: namespace1.id, source_type: 'Namespace') }
+ let!(:namespace_route2) { routes.create!(path: 'batch-test1/batch-test2', source_id: namespace2.id, source_type: 'Namespace') }
+ let!(:namespace_route3) { routes.create!(path: 'batch-test1/batch-test3', source_id: namespace3.id, source_type: 'Namespace') }
+
+ let!(:proj_route1) { routes.create!(path: 'batch-test1/project1', source_id: project1.id, source_type: 'Project') }
+ let!(:proj_route2) { routes.create!(path: 'batch-test1/batch-test2/project2', source_id: project2.id, source_type: 'Project') }
+ let!(:proj_route2_dup) { routes.create!(path: "batch-test1/batch-test2/project2-route-#{project2_dup.id}", source_id: project2_dup.id, source_type: 'Project') }
+ let!(:proj_route3) { routes.create!(path: 'batch-test1/batch-test3/project3', source_id: project3.id, source_type: 'Project') }
+ let!(:proj_route3_dup) { routes.create!(path: "batch-test1/batch-test3/project3-route-#{project3_dup.id}", source_id: project3_dup.id, source_type: 'Project') }
+
+ subject(:perform_migration) { migration.perform(projects.minimum(:id), projects.maximum(:id)) }
+
+ describe '#up' do
+ it 'backfills namespace_id for the selected records', :aggregate_failures do
+ expect(namespaces.where(type: 'Project').count).to eq(2)
+
+ perform_migration
+
+ expect(namespaces.where(type: 'Project').count).to eq(5)
+
+ expect(project1.reload.name).to eq("project1-#{project1.id}")
+ expect(project1.path).to eq('project1')
+
+ expect(project2.reload.name).to eq('project2')
+ expect(project2.path).to eq('project2')
+
+ expect(project2_dup.reload.name).to eq("project2-#{project2_dup.id}")
+ expect(project2_dup.path).to eq("project2-route-#{project2_dup.id}")
+
+ expect(project3.reload.name).to eq("project3")
+ expect(project3.path).to eq("project3")
+
+ expect(project3_dup.reload.name).to eq("project3-#{project3_dup.id}")
+ expect(project3_dup.path).to eq("project3-route-#{project3_dup.id}")
+
+ projects.all.each do |pr|
+ project_namespace = namespaces.find(pr.project_namespace_id)
+ expect(project_namespace).to be_in_sync_with_project(pr)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/merge_topics_with_same_name_spec.rb b/spec/lib/gitlab/background_migration/merge_topics_with_same_name_spec.rb
new file mode 100644
index 00000000000..254b4fea698
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/merge_topics_with_same_name_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::MergeTopicsWithSameName, schema: 20220223124428 do
+ def set_avatar(topic_id, avatar)
+ topic = ::Projects::Topic.find(topic_id)
+ topic.avatar = avatar
+ topic.save!
+ topic.avatar.absolute_path
+ end
+
+ it 'merges project topics with same case insensitive name' do
+ namespaces = table(:namespaces)
+ projects = table(:projects)
+ topics = table(:topics)
+ project_topics = table(:project_topics)
+
+ group = namespaces.create!(name: 'group', path: 'group')
+ project_1 = projects.create!(namespace_id: group.id, visibility_level: 20)
+ project_2 = projects.create!(namespace_id: group.id, visibility_level: 10)
+ project_3 = projects.create!(namespace_id: group.id, visibility_level: 0)
+ topic_1_keep = topics.create!(
+ name: 'topic1',
+ description: 'description 1 to keep',
+ total_projects_count: 2,
+ non_private_projects_count: 2
+ )
+ topic_1_remove = topics.create!(
+ name: 'TOPIC1',
+ description: 'description 1 to remove',
+ total_projects_count: 2,
+ non_private_projects_count: 1
+ )
+ topic_2_remove = topics.create!(
+ name: 'topic2',
+ total_projects_count: 0
+ )
+ topic_2_keep = topics.create!(
+ name: 'TOPIC2',
+ description: 'description 2 to keep',
+ total_projects_count: 1
+ )
+ topic_3_remove_1 = topics.create!(
+ name: 'topic3',
+ total_projects_count: 2,
+ non_private_projects_count: 1
+ )
+ topic_3_keep = topics.create!(
+ name: 'Topic3',
+ total_projects_count: 2,
+ non_private_projects_count: 2
+ )
+ topic_3_remove_2 = topics.create!(
+ name: 'TOPIC3',
+ description: 'description 3 to keep',
+ total_projects_count: 2,
+ non_private_projects_count: 1
+ )
+ topic_4_keep = topics.create!(
+ name: 'topic4'
+ )
+
+ project_topics_1 = []
+ project_topics_3 = []
+ project_topics_removed = []
+
+ project_topics_1 << project_topics.create!(topic_id: topic_1_keep.id, project_id: project_1.id)
+ project_topics_1 << project_topics.create!(topic_id: topic_1_keep.id, project_id: project_2.id)
+ project_topics_removed << project_topics.create!(topic_id: topic_1_remove.id, project_id: project_2.id)
+ project_topics_1 << project_topics.create!(topic_id: topic_1_remove.id, project_id: project_3.id)
+
+ project_topics_3 << project_topics.create!(topic_id: topic_3_keep.id, project_id: project_1.id)
+ project_topics_3 << project_topics.create!(topic_id: topic_3_keep.id, project_id: project_2.id)
+ project_topics_removed << project_topics.create!(topic_id: topic_3_remove_1.id, project_id: project_1.id)
+ project_topics_3 << project_topics.create!(topic_id: topic_3_remove_1.id, project_id: project_3.id)
+ project_topics_removed << project_topics.create!(topic_id: topic_3_remove_2.id, project_id: project_1.id)
+ project_topics_removed << project_topics.create!(topic_id: topic_3_remove_2.id, project_id: project_3.id)
+
+ avatar_paths = {
+ topic_1_keep: set_avatar(topic_1_keep.id, fixture_file_upload('spec/fixtures/avatars/avatar1.png')),
+ topic_1_remove: set_avatar(topic_1_remove.id, fixture_file_upload('spec/fixtures/avatars/avatar2.png')),
+ topic_2_remove: set_avatar(topic_2_remove.id, fixture_file_upload('spec/fixtures/avatars/avatar3.png')),
+ topic_3_remove_1: set_avatar(topic_3_remove_1.id, fixture_file_upload('spec/fixtures/avatars/avatar4.png')),
+ topic_3_remove_2: set_avatar(topic_3_remove_2.id, fixture_file_upload('spec/fixtures/avatars/avatar5.png'))
+ }
+
+ subject.perform(%w[topic1 topic2 topic3 topic4])
+
+ # Topics
+ [topic_1_keep, topic_2_keep, topic_3_keep, topic_4_keep].each(&:reload)
+ expect(topic_1_keep.name).to eq('topic1')
+ expect(topic_1_keep.description).to eq('description 1 to keep')
+ expect(topic_1_keep.total_projects_count).to eq(3)
+ expect(topic_1_keep.non_private_projects_count).to eq(2)
+ expect(topic_2_keep.name).to eq('TOPIC2')
+ expect(topic_2_keep.description).to eq('description 2 to keep')
+ expect(topic_2_keep.total_projects_count).to eq(0)
+ expect(topic_2_keep.non_private_projects_count).to eq(0)
+ expect(topic_3_keep.name).to eq('Topic3')
+ expect(topic_3_keep.description).to eq('description 3 to keep')
+ expect(topic_3_keep.total_projects_count).to eq(3)
+ expect(topic_3_keep.non_private_projects_count).to eq(2)
+ expect(topic_4_keep.reload.name).to eq('topic4')
+
+ [topic_1_remove, topic_2_remove, topic_3_remove_1, topic_3_remove_2].each do |topic|
+ expect { topic.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ # Topic avatars
+ expect(topic_1_keep.avatar).to eq('avatar1.png')
+ expect(File.exist?(::Projects::Topic.find(topic_1_keep.id).avatar.absolute_path)).to be_truthy
+ expect(topic_2_keep.avatar).to eq('avatar3.png')
+ expect(File.exist?(::Projects::Topic.find(topic_2_keep.id).avatar.absolute_path)).to be_truthy
+ expect(topic_3_keep.avatar).to eq('avatar4.png')
+ expect(File.exist?(::Projects::Topic.find(topic_3_keep.id).avatar.absolute_path)).to be_truthy
+
+ [:topic_1_remove, :topic_2_remove, :topic_3_remove_1, :topic_3_remove_2].each do |topic|
+ expect(File.exist?(avatar_paths[topic])).to be_falsey
+ end
+
+ # Project Topic assignments
+ project_topics_1.each do |project_topic|
+ expect(project_topic.reload.topic_id).to eq(topic_1_keep.id)
+ end
+
+ project_topics_3.each do |project_topic|
+ expect(project_topic.reload.topic_id).to eq(topic_3_keep.id)
+ end
+
+ project_topics_removed.each do |project_topic|
+ expect { project_topic.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/migrate_shimo_confluence_integration_category_spec.rb b/spec/lib/gitlab/background_migration/migrate_shimo_confluence_integration_category_spec.rb
new file mode 100644
index 00000000000..8bc6bb8ae0a
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_shimo_confluence_integration_category_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::MigrateShimoConfluenceIntegrationCategory, schema: 20220326161803 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:integrations) { table(:integrations) }
+ let(:perform) { described_class.new.perform(1, 5) }
+
+ before do
+ namespace = namespaces.create!(name: 'test', path: 'test')
+ projects.create!(id: 1, namespace_id: namespace.id, name: 'gitlab', path: 'gitlab')
+ integrations.create!(id: 1, active: true, type_new: "Integrations::SlackSlashCommands",
+ category: 'chat', project_id: 1)
+ integrations.create!(id: 3, active: true, type_new: "Integrations::Confluence", category: 'common', project_id: 1)
+ integrations.create!(id: 5, active: true, type_new: "Integrations::Shimo", category: 'common', project_id: 1)
+ end
+
+ describe '#up' do
+ it 'updates category to third_party_wiki for Shimo and Confluence' do
+ perform
+
+ expect(integrations.where(category: 'third_party_wiki').count).to eq(2)
+ expect(integrations.where(category: 'chat').count).to eq(1)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_container_repository_migration_plan_spec.rb b/spec/lib/gitlab/background_migration/populate_container_repository_migration_plan_spec.rb
new file mode 100644
index 00000000000..0463f5a0c0d
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_container_repository_migration_plan_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateContainerRepositoryMigrationPlan, schema: 20220316202640 do
+ let_it_be(:container_repositories) { table(:container_repositories) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:gitlab_subscriptions) { table(:gitlab_subscriptions) }
+ let_it_be(:plans) { table(:plans) }
+ let_it_be(:namespace_statistics) { table(:namespace_statistics) }
+
+ let!(:namepace1) { namespaces.create!(id: 1, type: 'Group', name: 'group1', path: 'group1', traversal_ids: [1]) }
+ let!(:namepace2) { namespaces.create!(id: 2, type: 'Group', name: 'group2', path: 'group2', traversal_ids: [2]) }
+ let!(:namepace3) { namespaces.create!(id: 3, type: 'Group', name: 'group3', path: 'group3', traversal_ids: [3]) }
+ let!(:sub_namespace) { namespaces.create!(id: 4, type: 'Group', name: 'group3', path: 'group3', parent_id: 1, traversal_ids: [1, 4]) }
+ let!(:plan1) { plans.create!(id: 1, name: 'plan1') }
+ let!(:plan2) { plans.create!(id: 2, name: 'plan2') }
+ let!(:gitlab_subscription1) { gitlab_subscriptions.create!(id: 1, namespace_id: 1, hosted_plan_id: 1) }
+ let!(:gitlab_subscription2) { gitlab_subscriptions.create!(id: 2, namespace_id: 2, hosted_plan_id: 2) }
+ let!(:project1) { projects.create!(id: 1, name: 'project1', path: 'project1', namespace_id: 4) }
+ let!(:project2) { projects.create!(id: 2, name: 'project2', path: 'project2', namespace_id: 2) }
+ let!(:project3) { projects.create!(id: 3, name: 'project3', path: 'project3', namespace_id: 3) }
+ let!(:container_repository1) { container_repositories.create!(id: 1, name: 'cr1', project_id: 1) }
+ let!(:container_repository2) { container_repositories.create!(id: 2, name: 'cr2', project_id: 2) }
+ let!(:container_repository3) { container_repositories.create!(id: 3, name: 'cr3', project_id: 3) }
+
+ let(:migration) { described_class.new }
+
+ subject do
+ migration.perform(1, 4)
+ end
+
+ it 'updates the migration_plan to match the actual plan', :aggregate_failures do
+ expect(Gitlab::Database::BackgroundMigrationJob).to receive(:mark_all_as_succeeded)
+ .with('PopulateContainerRepositoryMigrationPlan', [1, 4]).and_return(true)
+
+ subject
+
+ expect(container_repository1.reload.migration_plan).to eq('plan1')
+ expect(container_repository2.reload.migration_plan).to eq('plan2')
+ expect(container_repository3.reload.migration_plan).to eq(nil)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb
new file mode 100644
index 00000000000..98b2bc437f3
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateNamespaceStatistics do
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:namespace_statistics) { table(:namespace_statistics) }
+ let_it_be(:dependency_proxy_manifests) { table(:dependency_proxy_manifests) }
+ let_it_be(:dependency_proxy_blobs) { table(:dependency_proxy_blobs) }
+
+ let!(:group1) { namespaces.create!(id: 10, type: 'Group', name: 'group1', path: 'group1') }
+ let!(:group2) { namespaces.create!(id: 20, type: 'Group', name: 'group2', path: 'group2') }
+
+ let!(:group1_manifest) do
+ dependency_proxy_manifests.create!(group_id: 10, size: 20, file_name: 'test-file', file: 'test', digest: 'abc123')
+ end
+
+ let!(:group2_manifest) do
+ dependency_proxy_manifests.create!(group_id: 20, size: 20, file_name: 'test-file', file: 'test', digest: 'abc123')
+ end
+
+ let!(:group1_stats) { namespace_statistics.create!(id: 10, namespace_id: 10) }
+
+ let(:ids) { namespaces.pluck(:id) }
+ let(:statistics) { [] }
+
+ subject(:perform) { described_class.new.perform(ids, statistics) }
+
+ it 'creates/updates all namespace_statistics and updates root storage statistics', :aggregate_failures do
+ expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group1.id)
+ expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group2.id)
+
+ expect { perform }.to change(namespace_statistics, :count).from(1).to(2)
+
+ namespace_statistics.all.each do |stat|
+ expect(stat.dependency_proxy_size).to eq 20
+ expect(stat.storage_size).to eq 20
+ end
+ end
+
+ context 'when just a stat is passed' do
+ let(:statistics) { [:dependency_proxy_size] }
+
+ it 'calls the statistics update service with just that stat' do
+ expect(Groups::UpdateStatisticsService)
+ .to receive(:new)
+ .with(anything, statistics: [:dependency_proxy_size])
+ .twice.and_call_original
+
+ perform
+ end
+ end
+
+ context 'when a statistics update fails' do
+ before do
+ error_response = instance_double(ServiceResponse, message: 'an error', error?: true)
+
+ allow_next_instance_of(Groups::UpdateStatisticsService) do |instance|
+ allow(instance).to receive(:execute).and_return(error_response)
+ end
+ end
+
+ it 'logs an error' do
+ expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
+ expect(instance).to receive(:error).twice
+ end
+
+ perform
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb b/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb
index a265fa95b23..3de84a4e880 100644
--- a/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateVulnerabilityReads do
+RSpec.describe Gitlab::BackgroundMigration::PopulateVulnerabilityReads, :migration, schema: 20220326161803 do
let(:vulnerabilities) { table(:vulnerabilities) }
let(:vulnerability_reads) { table(:vulnerability_reads) }
let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
diff --git a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
index 2c5de448fbc..2ad561ead87 100644
--- a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
+++ b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces, :migration do
+RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces, :migration, schema: 20220326161803 do
include MigrationsHelpers
context 'when migrating data', :aggregate_failures do
diff --git a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
index f6f4a3f6115..8003159f59e 100644
--- a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings do
+RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings, :migration, schema: 20220326161803 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
diff --git a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
index 28aa9efde4f..07cff32304e 100644
--- a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings do
+RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration, schema: 20220326161803 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb
index 6aea549b136..d02f7245c15 100644
--- a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects do
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects, :migration, schema: 20220326161803 do # rubocop:disable Layout/LineLength
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb
index cbe762c2680..fd61047d851 100644
--- a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValuesOnProjects do
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValuesOnProjects, :migration, schema: 20220326161803 do # rubocop:disable Layout/LineLength
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }