diff options
Diffstat (limited to 'spec/lib/gitlab/background_migration')
8 files changed, 368 insertions, 340 deletions
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 index 2dcd4645c84..2949bc068c8 100644 --- 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 @@ -1,8 +1,8 @@ # frozen_string_literal: true require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdForProjectRoute do +# this needs the schema to be before we introduce the not null constraint on routes#namespace_id +RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdForProjectRoute, schema: 20220606060825 do let(:migration) { described_class.new } let(:namespaces) { table(:namespaces) } let(:projects) { table(:projects) } diff --git a/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb new file mode 100644 index 00000000000..fd6c055b9f6 --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillProjectFeaturePackageRegistryAccessLevel do + let(:non_null_project_features) { { pages_access_level: 20 } } + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:project_features) { table(:project_features) } + + let(:namespace1) { namespaces.create!(name: 'namespace 1', path: 'namespace1') } + let(:namespace2) { namespaces.create!(name: 'namespace 2', path: 'namespace2') } + let(:namespace3) { namespaces.create!(name: 'namespace 3', path: 'namespace3') } + let(:namespace4) { namespaces.create!(name: 'namespace 4', path: 'namespace4') } + let(:namespace5) { namespaces.create!(name: 'namespace 5', path: 'namespace5') } + let(:namespace6) { namespaces.create!(name: 'namespace 6', path: 'namespace6') } + + let(:project1) do + projects.create!(namespace_id: namespace1.id, project_namespace_id: namespace1.id, packages_enabled: false) + end + + let(:project2) do + projects.create!(namespace_id: namespace2.id, project_namespace_id: namespace2.id, packages_enabled: nil) + end + + let(:project3) do + projects.create!( + namespace_id: namespace3.id, + project_namespace_id: namespace3.id, + packages_enabled: true, + visibility_level: Gitlab::VisibilityLevel::PRIVATE + ) + end + + let(:project4) do + projects.create!( + namespace_id: namespace4.id, + project_namespace_id: namespace4.id, + packages_enabled: true, visibility_level: Gitlab::VisibilityLevel::INTERNAL) + end + + let(:project5) do + projects.create!( + namespace_id: namespace5.id, + project_namespace_id: namespace5.id, + packages_enabled: true, + visibility_level: Gitlab::VisibilityLevel::PUBLIC + ) + end + + let(:project6) do + projects.create!(namespace_id: namespace6.id, project_namespace_id: namespace6.id, packages_enabled: false) + end + + let!(:project_feature1) do + project_features.create!( + project_id: project1.id, + package_registry_access_level: ProjectFeature::ENABLED, + **non_null_project_features + ) + end + + let!(:project_feature2) do + project_features.create!( + project_id: project2.id, + package_registry_access_level: ProjectFeature::ENABLED, + **non_null_project_features + ) + end + + let!(:project_feature3) do + project_features.create!( + project_id: project3.id, + package_registry_access_level: ProjectFeature::DISABLED, + **non_null_project_features + ) + end + + let!(:project_feature4) do + project_features.create!( + project_id: project4.id, + package_registry_access_level: ProjectFeature::DISABLED, + **non_null_project_features + ) + end + + let!(:project_feature5) do + project_features.create!( + project_id: project5.id, + package_registry_access_level: ProjectFeature::DISABLED, + **non_null_project_features + ) + end + + let!(:project_feature6) do + project_features.create!( + project_id: project6.id, + package_registry_access_level: ProjectFeature::ENABLED, + **non_null_project_features + ) + end + + subject(:perform_migration) do + described_class.new(start_id: project1.id, + end_id: project5.id, + batch_table: :projects, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + .perform + end + + it 'backfills project_features.package_registry_access_level', :aggregate_failures do + perform_migration + + expect(project_feature1.reload.package_registry_access_level).to eq(ProjectFeature::DISABLED) + expect(project_feature2.reload.package_registry_access_level).to eq(ProjectFeature::DISABLED) + expect(project_feature3.reload.package_registry_access_level).to eq(ProjectFeature::PRIVATE) + expect(project_feature4.reload.package_registry_access_level).to eq(ProjectFeature::ENABLED) + expect(project_feature5.reload.package_registry_access_level).to eq(ProjectFeature::PUBLIC) + expect(project_feature6.reload.package_registry_access_level).to eq(ProjectFeature::ENABLED) + end +end diff --git a/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb new file mode 100644 index 00000000000..ca7ca41a33e --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillProjectMemberNamespaceId, :migration, schema: 20220516054011 do + let(:migration) do + described_class.new(start_id: 1, end_id: 10, + batch_table: table_name, batch_column: batch_column, + sub_batch_size: sub_batch_size, pause_ms: pause_ms, + connection: ApplicationRecord.connection) + end + + let(:members_table) { table(:members) } + let(:projects_table) { table(:projects) } + let(:namespaces_table) { table(:namespaces) } + + let(:table_name) { 'members' } + let(:batch_column) { :id } + let(:sub_batch_size) { 100 } + let(:pause_ms) { 0 } + + subject(:perform_migration) do + migration.perform + end + + before do + namespaces_table.create!(id: 201, name: 'group1', path: 'group1', type: 'Group') + namespaces_table.create!(id: 202, name: 'group2', path: 'group2', type: 'Group') + namespaces_table.create!(id: 300, name: 'project-namespace-1', path: 'project-namespace-1-path', type: 'Project') + namespaces_table.create!(id: 301, name: 'project-namespace-2', path: 'project-namespace-2-path', type: 'Project') + namespaces_table.create!(id: 302, name: 'project-namespace-3', path: 'project-namespace-3-path', type: 'Project') + + projects_table.create!(id: 100, name: 'project1', path: 'project1', namespace_id: 202, project_namespace_id: 300) + projects_table.create!(id: 101, name: 'project2', path: 'project2', namespace_id: 202, project_namespace_id: 301) + projects_table.create!(id: 102, name: 'project3', path: 'project3', namespace_id: 202, project_namespace_id: 302) + + # project1, no member namespace (fill in) + members_table.create!(id: 1, source_id: 100, + source_type: 'Project', type: 'ProjectMember', + member_namespace_id: nil, access_level: 10, notification_level: 3) + # bogus source id, no member namespace id (do nothing) + members_table.create!(id: 2, source_id: non_existing_record_id, + source_type: 'Project', type: 'ProjectMember', + member_namespace_id: nil, access_level: 10, notification_level: 3) + # project3, existing member namespace id (do nothing) + members_table.create!(id: 3, source_id: 102, + source_type: 'Project', type: 'ProjectMember', + member_namespace_id: 300, access_level: 10, notification_level: 3) + + # Group memberships (do not change) + # group1, no member namespace (do nothing) + members_table.create!(id: 4, source_id: 201, + source_type: 'Namespace', type: 'GroupMember', + member_namespace_id: nil, access_level: 10, notification_level: 3) + # group2, existing member namespace (do nothing) + members_table.create!(id: 5, source_id: 202, + source_type: 'Namespace', type: 'GroupMember', + member_namespace_id: 201, access_level: 10, notification_level: 3) + + # Project Namespace memberships (do not change) + # project namespace, existing member namespace (do nothing) + members_table.create!(id: 6, source_id: 300, + source_type: 'Namespace', type: 'ProjectNamespaceMember', + member_namespace_id: 201, access_level: 10, notification_level: 3) + # project namespace, not member namespace (do nothing) + members_table.create!(id: 7, source_id: 301, + source_type: 'Namespace', type: 'ProjectNamespaceMember', + member_namespace_id: 201, access_level: 10, notification_level: 3) + end + + it 'backfills `member_namespace_id` for the selected records', :aggregate_failures do + expect(members_table.where(type: 'ProjectMember', member_namespace_id: nil).count).to eq 2 + expect(members_table.where(type: 'GroupMember', member_namespace_id: nil).count).to eq 1 + + queries = ActiveRecord::QueryRecorder.new do + perform_migration + end + + # rubocop:disable Layout/LineLength + expect(queries.count).to eq(3) + expect(members_table.where(type: 'ProjectMember', member_namespace_id: nil).count).to eq 1 # just the bogus one + expect(members_table.where(type: 'ProjectMember').pluck(:member_namespace_id)).to match_array([nil, 300, 300]) + expect(members_table.where(type: 'GroupMember', member_namespace_id: nil).count).to eq 1 + expect(members_table.where(type: 'GroupMember').pluck(:member_namespace_id)).to match_array([nil, 201]) + # rubocop:enable Layout/LineLength + 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 + + context 'when given a negative pause_ms' do + let(:pause_ms) { -9 } + let(:sub_batch_size) { 2 } + + it 'uses 0 as a floor for pause_ms' do + expect(migration).to receive(:sleep).with(0) + + perform_migration + end + end +end diff --git a/spec/lib/gitlab/background_migration/cleanup_orphaned_routes_spec.rb b/spec/lib/gitlab/background_migration/cleanup_orphaned_routes_spec.rb new file mode 100644 index 00000000000..a09d5559d33 --- /dev/null +++ b/spec/lib/gitlab/background_migration/cleanup_orphaned_routes_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# this needs the schema to be before we introduce the not null constraint on routes#namespace_id +RSpec.describe Gitlab::BackgroundMigration::CleanupOrphanedRoutes, schema: 20220606060825 do + 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) } + + # 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) } + + # valid namespace routes with not null namespace_id + let!(:namespace_route1) { routes.create!(path: 'space1', source_id: namespace1.id, source_type: 'Namespace', namespace_id: namespace1.id) } + # valid namespace routes with null namespace_id + 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') } + # invalid/orphaned namespace route + let!(:orphaned_namespace_route_a) { routes.create!(path: 'space1/space4', source_id: non_existing_record_id, source_type: 'Namespace') } + let!(:orphaned_namespace_route_b) { routes.create!(path: 'space1/space5', source_id: non_existing_record_id - 1, source_type: 'Namespace') } + + # valid project routes with not null namespace_id + let!(:proj_route1) { routes.create!(path: 'space1/proj1', source_id: proj1.id, source_type: 'Project', namespace_id: proj_namespace1.id) } + # valid project routes with null namespace_id + 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') } + # invalid/orphaned namespace route + let!(:orphaned_project_route_a) { routes.create!(path: 'space1/space3/proj5', source_id: non_existing_record_id, source_type: 'Project') } + let!(:orphaned_project_route_b) { routes.create!(path: 'space1/space3/proj6', source_id: non_existing_record_id - 1, source_type: 'Project') } + # rubocop:enable Layout/LineLength + + let!(:migration_attrs) do + { + start_id: Route.minimum(:id), + end_id: Route.maximum(:id), + batch_table: :routes, + batch_column: :id, + sub_batch_size: 100, + pause_ms: 0, + connection: ApplicationRecord.connection + } + end + + let!(:migration) { described_class.new(**migration_attrs) } + + subject(:perform_migration) { migration.perform } + + it 'cleans orphaned routes', :aggregate_failures do + all_route_ids = Route.pluck(:id) + + orphaned_route_ids = [ + orphaned_namespace_route_a, orphaned_namespace_route_b, orphaned_project_route_a, orphaned_project_route_b + ].pluck(:id) + remaining_routes = (all_route_ids - orphaned_route_ids).sort + + expect { perform_migration }.to change { Route.pluck(:id) }.to contain_exactly(*remaining_routes) + expect(Route.all).to all(have_attributes(namespace_id: be_present)) + + # expect that routes that had namespace_id set did not change namespace_id + expect(namespace_route1.reload.namespace_id).to eq(namespace1.id) + expect(proj_route1.reload.namespace_id).to eq(proj_namespace1.id) + 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/encrypt_integration_properties_spec.rb b/spec/lib/gitlab/background_migration/encrypt_integration_properties_spec.rb index 7334867e8fb..38e8b159e63 100644 --- a/spec/lib/gitlab/background_migration/encrypt_integration_properties_spec.rb +++ b/spec/lib/gitlab/background_migration/encrypt_integration_properties_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Gitlab::BackgroundMigration::EncryptIntegrationProperties do +RSpec.describe Gitlab::BackgroundMigration::EncryptIntegrationProperties, schema: 20220415124804 do let(:integrations) do table(:integrations) do |integrations| integrations.send :attr_encrypted, :encrypted_properties_tmp, diff --git a/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb index c343ee438b8..99df21562b0 100644 --- a/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb +++ b/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb @@ -2,314 +2,23 @@ require 'spec_helper' -# The underlying migration relies on the global models (e.g. Project). This -# means we also need to use FactoryBot factories to ensure everything is -# operating using the same types. If we use `table()` and similar methods we -# would have to duplicate a lot of logic just for these tests. -# # rubocop: disable RSpec/FactoriesInMigrationSpecs RSpec.describe Gitlab::BackgroundMigration::FixMergeRequestDiffCommitUsers do let(:migration) { described_class.new } describe '#perform' do context 'when the project exists' do - it 'processes the project' do + it 'does nothing' do project = create(:project) - expect(migration).to receive(:process).with(project) - expect(migration).to receive(:schedule_next_job) - - migration.perform(project.id) - end - - it 'marks the background job as finished' do - project = create(:project) - - Gitlab::Database::BackgroundMigrationJob.create!( - class_name: 'FixMergeRequestDiffCommitUsers', - arguments: [project.id] - ) - - migration.perform(project.id) - - job = Gitlab::Database::BackgroundMigrationJob - .find_by(class_name: 'FixMergeRequestDiffCommitUsers') - - expect(job.status).to eq('succeeded') + expect { migration.perform(project.id) }.not_to raise_error end end context 'when the project does not exist' do it 'does nothing' do - expect(migration).not_to receive(:process) - expect(migration).to receive(:schedule_next_job) - - migration.perform(-1) - end - end - end - - describe '#process' do - it 'processes the merge requests of the project' do - project = create(:project, :repository) - commit = project.commit - mr = create( - :merge_request_with_diffs, - source_project: project, - target_project: project - ) - - diff = mr.merge_request_diffs.first - - create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000 - ) - - migration.process(project) - - updated = diff - .merge_request_diff_commits - .find_by(sha: commit.sha, relative_order: 9000) - - expect(updated.commit_author_id).not_to be_nil - expect(updated.committer_id).not_to be_nil - end - end - - describe '#update_commit' do - let(:project) { create(:project, :repository) } - let(:mr) do - create( - :merge_request_with_diffs, - source_project: project, - target_project: project - ) - end - - let(:diff) { mr.merge_request_diffs.first } - let(:commit) { project.commit } - - def update_row(migration, project, diff, row) - migration.update_commit(project, row) - - diff - .merge_request_diff_commits - .find_by(sha: row.sha, relative_order: row.relative_order) - end - - it 'populates missing commit authors' do - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000 - ) - - updated = update_row(migration, project, diff, commit_row) - - expect(updated.commit_author.name).to eq(commit.to_hash[:author_name]) - expect(updated.commit_author.email).to eq(commit.to_hash[:author_email]) - end - - it 'populates missing committers' do - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000 - ) - - updated = update_row(migration, project, diff, commit_row) - - expect(updated.committer.name).to eq(commit.to_hash[:committer_name]) - expect(updated.committer.email).to eq(commit.to_hash[:committer_email]) - end - - it 'leaves existing commit authors as-is' do - user = create(:merge_request_diff_commit_user) - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000, - commit_author: user - ) - - updated = update_row(migration, project, diff, commit_row) - - expect(updated.commit_author).to eq(user) - end - - it 'leaves existing committers as-is' do - user = create(:merge_request_diff_commit_user) - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000, - committer: user - ) - - updated = update_row(migration, project, diff, commit_row) - - expect(updated.committer).to eq(user) - end - - it 'does nothing when both the author and committer are present' do - user = create(:merge_request_diff_commit_user) - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000, - committer: user, - commit_author: user - ) - - recorder = ActiveRecord::QueryRecorder.new do - migration.update_commit(project, commit_row) - end - - expect(recorder.count).to be_zero - end - - it 'does nothing if the commit does not exist in Git' do - user = create(:merge_request_diff_commit_user) - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: 'kittens', - relative_order: 9000, - committer: user, - commit_author: user - ) - - recorder = ActiveRecord::QueryRecorder.new do - migration.update_commit(project, commit_row) + expect { migration.perform(-1) }.not_to raise_error end - - expect(recorder.count).to be_zero - end - - it 'does nothing when the committer/author are missing in the Git commit' do - user = create(:merge_request_diff_commit_user) - commit_row = create( - :merge_request_diff_commit, - merge_request_diff: diff, - sha: commit.sha, - relative_order: 9000, - committer: user, - commit_author: user - ) - - allow(migration).to receive(:find_or_create_user).and_return(nil) - - recorder = ActiveRecord::QueryRecorder.new do - migration.update_commit(project, commit_row) - end - - expect(recorder.count).to be_zero - end - end - - describe '#schedule_next_job' do - it 'schedules the next background migration' do - Gitlab::Database::BackgroundMigrationJob - .create!(class_name: 'FixMergeRequestDiffCommitUsers', arguments: [42]) - - expect(BackgroundMigrationWorker) - .to receive(:perform_in) - .with(2.minutes, 'FixMergeRequestDiffCommitUsers', [42]) - - migration.schedule_next_job - end - - it 'does nothing when there are no jobs' do - expect(BackgroundMigrationWorker) - .not_to receive(:perform_in) - - migration.schedule_next_job - end - end - - describe '#find_commit' do - let(:project) { create(:project, :repository) } - - it 'finds a commit using Git' do - commit = project.commit - found = migration.find_commit(project, commit.sha) - - expect(found).to eq(commit.to_hash) - end - - it 'caches the results' do - commit = project.commit - - migration.find_commit(project, commit.sha) - - expect { migration.find_commit(project, commit.sha) } - .not_to change { Gitlab::GitalyClient.get_request_count } - end - - it 'returns an empty hash if the commit does not exist' do - expect(migration.find_commit(project, 'kittens')).to eq({}) - end - end - - describe '#find_or_create_user' do - let(:project) { create(:project, :repository) } - - it 'creates missing users' do - commit = project.commit.to_hash - id = migration.find_or_create_user(commit, :author_name, :author_email) - - expect(MergeRequest::DiffCommitUser.count).to eq(1) - - created = MergeRequest::DiffCommitUser.first - - expect(created.name).to eq(commit[:author_name]) - expect(created.email).to eq(commit[:author_email]) - expect(created.id).to eq(id) - end - - it 'returns users that already exist' do - commit = project.commit.to_hash - user1 = migration.find_or_create_user(commit, :author_name, :author_email) - user2 = migration.find_or_create_user(commit, :author_name, :author_email) - - expect(user1).to eq(user2) - end - - it 'caches the results' do - commit = project.commit.to_hash - - migration.find_or_create_user(commit, :author_name, :author_email) - - recorder = ActiveRecord::QueryRecorder.new do - migration.find_or_create_user(commit, :author_name, :author_email) - end - - expect(recorder.count).to be_zero - end - - it 'returns nil if the commit details are missing' do - id = migration.find_or_create_user({}, :author_name, :author_email) - - expect(id).to be_nil - end - end - - describe '#matches_row' do - it 'returns the query matches for the composite primary key' do - row = double(:commit, merge_request_diff_id: 4, relative_order: 5) - arel = migration.matches_row(row) - - expect(arel.to_sql).to eq( - '("merge_request_diff_commits"."merge_request_diff_id", "merge_request_diff_commits"."relative_order") = (4, 5)' - ) end end end diff --git a/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb b/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb deleted file mode 100644 index 557dd8ddee6..00000000000 --- a/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::MigratePagesToZipStorage do - let(:namespace) { create(:group) } # rubocop: disable RSpec/FactoriesInMigrationSpecs - let(:migration) { described_class.new } - - describe '#perform' do - context 'when there is project to migrate' do - let!(:project) { create_project('project') } - - after do - FileUtils.rm_rf(project.pages_path) - end - - it 'migrates project to zip storage' do - expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, - anything, - ignore_invalid_entries: false, - mark_projects_as_not_deployed: false) do |service| - expect(service).to receive(:execute_for_batch).with(project.id..project.id).and_call_original - end - - migration.perform(project.id, project.id) - - expect(project.reload.pages_metadatum.pages_deployment.file.filename).to eq("_migrated.zip") - end - end - end - - def create_project(path) - project = create(:project) # rubocop: disable RSpec/FactoriesInMigrationSpecs - project.mark_pages_as_deployed - - FileUtils.mkdir_p File.join(project.pages_path, "public") - File.open(File.join(project.pages_path, "public/index.html"), "w") do |f| - f.write("Hello!") - end - - project - end -end diff --git a/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb new file mode 100644 index 00000000000..035ea6eadcf --- /dev/null +++ b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::SetLegacyOpenSourceLicenseAvailableForNonPublicProjects, + :migration, + schema: 20220520040416 do + let(:namespaces_table) { table(:namespaces) } + let(:projects_table) { table(:projects) } + let(:project_settings_table) { table(:project_settings) } + + subject(:perform_migration) do + described_class.new(start_id: 1, + end_id: 30, + batch_table: :projects, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + .perform + end + + let(:queries) { ActiveRecord::QueryRecorder.new { perform_migration } } + + before do + namespaces_table.create!(id: 1, name: 'namespace', path: 'namespace-path-1') + namespaces_table.create!(id: 2, name: 'namespace', path: 'namespace-path-2', type: 'Project') + namespaces_table.create!(id: 3, name: 'namespace', path: 'namespace-path-3', type: 'Project') + namespaces_table.create!(id: 4, name: 'namespace', path: 'namespace-path-4', type: 'Project') + + projects_table + .create!(id: 11, name: 'proj-1', path: 'path-1', namespace_id: 1, project_namespace_id: 2, visibility_level: 0) + projects_table + .create!(id: 12, name: 'proj-2', path: 'path-2', namespace_id: 1, project_namespace_id: 3, visibility_level: 10) + projects_table + .create!(id: 13, name: 'proj-3', path: 'path-3', namespace_id: 1, project_namespace_id: 4, visibility_level: 20) + + project_settings_table.create!(project_id: 11, legacy_open_source_license_available: true) + project_settings_table.create!(project_id: 12, legacy_open_source_license_available: true) + project_settings_table.create!(project_id: 13, legacy_open_source_license_available: true) + end + + it 'sets `legacy_open_source_license_available` attribute to false for non-public projects', :aggregate_failures do + expect(queries.count).to eq(3) + + expect(migrated_attribute(11)).to be_falsey + expect(migrated_attribute(12)).to be_falsey + expect(migrated_attribute(13)).to be_truthy + end + + def migrated_attribute(project_id) + project_settings_table.find(project_id).legacy_open_source_license_available + end +end |