diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 14:10:13 +0300 |
commit | 0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch) | |
tree | 7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /spec/migrations | |
parent | 72123183a20411a36d607d70b12d57c484394c8e (diff) |
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'spec/migrations')
19 files changed, 743 insertions, 65 deletions
diff --git a/spec/migrations/20220416054011_schedule_backfill_project_member_namespace_id_spec.rb b/spec/migrations/20220416054011_schedule_backfill_project_member_namespace_id_spec.rb new file mode 100644 index 00000000000..2838fc9387c --- /dev/null +++ b/spec/migrations/20220416054011_schedule_backfill_project_member_namespace_id_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe ScheduleBackfillProjectMemberNamespaceId do + let_it_be(:migration) { described_class::MIGRATION } + + describe '#up' do + it 'schedules background jobs for each batch of project members' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + table_name: :members, + column_name: :id, + interval: described_class::INTERVAL + ) + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/migrations/20220502015011_clean_up_fix_merge_request_diff_commit_users_spec.rb b/spec/migrations/20220502015011_clean_up_fix_merge_request_diff_commit_users_spec.rb index 769c0993b67..2bc3e89a748 100644 --- a/spec/migrations/20220502015011_clean_up_fix_merge_request_diff_commit_users_spec.rb +++ b/spec/migrations/20220502015011_clean_up_fix_merge_request_diff_commit_users_spec.rb @@ -15,21 +15,5 @@ RSpec.describe CleanUpFixMergeRequestDiffCommitUsers, :migration do migrate! end - - it 'processes pending background jobs' do - project = projects.create!(name: 'p1', namespace_id: namespace.id, project_namespace_id: project_namespace.id) - - Gitlab::Database::BackgroundMigrationJob.create!( - class_name: 'FixMergeRequestDiffCommitUsers', - arguments: [project.id] - ) - - migrate! - - background_migrations = Gitlab::Database::BackgroundMigrationJob - .where(class_name: 'FixMergeRequestDiffCommitUsers') - - expect(background_migrations.count).to eq(0) - end end end diff --git a/spec/migrations/20220503035221_add_gitlab_schema_to_batched_background_migrations_spec.rb b/spec/migrations/20220503035221_add_gitlab_schema_to_batched_background_migrations_spec.rb new file mode 100644 index 00000000000..5002c665c79 --- /dev/null +++ b/spec/migrations/20220503035221_add_gitlab_schema_to_batched_background_migrations_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe AddGitlabSchemaToBatchedBackgroundMigrations do + it 'sets gitlab_schema for existing methods to "gitlab_main" and default to NULL' do + batched_migrations = table(:batched_background_migrations) + batched_migration = batched_migrations.create!( + id: 1, created_at: Time.now, updated_at: Time.now, + max_value: 100, batch_size: 100, sub_batch_size: 10, interval: 120, + job_class_name: 'TestJob', table_name: '_test', column_name: 'id' + ) + + reversible_migration do |migration| + migration.before -> { + batched_migrations.reset_column_information + column = batched_migrations.columns.find { |column| column.name == 'gitlab_schema' } + + expect(column).to be_nil + } + + migration.after -> { + expect(batched_migration.reload.gitlab_schema).to eq('gitlab_main') + + batched_migrations.reset_column_information + column = batched_migrations.columns.find { |column| column.name == 'gitlab_schema' } + + expect(column).to be + expect(column.default).to be_nil + } + end + end +end diff --git a/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb b/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb index 8bc336a6b26..575157f8331 100644 --- a/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb +++ b/spec/migrations/20220505044348_fix_automatic_iterations_cadences_start_date_spec.rb @@ -4,8 +4,7 @@ require 'spec_helper' require_migration! -RSpec.describe FixAutomaticIterationsCadencesStartDate, - quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/362446' do +RSpec.describe FixAutomaticIterationsCadencesStartDate do let(:migration) { described_class.new } let(:namespaces) { table(:namespaces) } let(:sprints) { table(:sprints) } diff --git a/spec/migrations/20220512190659_remove_web_hooks_web_hook_logs_web_hook_id_fk_spec.rb b/spec/migrations/20220512190659_remove_web_hooks_web_hook_logs_web_hook_id_fk_spec.rb new file mode 100644 index 00000000000..fa94a73582d --- /dev/null +++ b/spec/migrations/20220512190659_remove_web_hooks_web_hook_logs_web_hook_id_fk_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe RemoveWebHooksWebHookLogsWebHookIdFk do + let(:web_hooks) { table(:web_hooks) } + let(:logs) { table(:web_hook_logs) } + + let!(:hook) { web_hooks.create! } + + let!(:log_a) { logs.create!(web_hook_id: hook.id, response_body: 'msg-a') } + let!(:log_b) { logs.create!(web_hook_id: hook.id, response_body: 'msg-b') } + + describe '#up' do + it 'allows us to delete web-hooks and leave web-hook logs intact' do + migrate! + + expect { hook.delete }.not_to change(logs, :count) + + expect(logs.pluck(:response_body)).to match_array %w[msg-a msg-b] + end + end + + describe '#down' do + it 'ensures referential integrity of hook logs' do + migrate! + schema_migrate_down! + + expect { hook.delete }.to change(logs, :count).by(-2) + end + end +end diff --git a/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb new file mode 100644 index 00000000000..e3bc832a10b --- /dev/null +++ b/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe ScheduleSetLegacyOpenSourceLicenseAvailableForNonPublicProjects do + context 'on gitlab.com' do + let(:migration) { described_class::MIGRATION } + + before do + allow(Gitlab).to receive(:com?).and_return(true) + end + + describe '#up' do + it 'schedules background jobs for each batch of projects' do + migrate! + + expect(migration).to( + have_scheduled_batched_migration( + table_name: :projects, + column_name: :id, + interval: described_class::INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + ) + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end + end + + context 'on self-managed instance' do + let(:migration) { described_class.new } + + before do + allow(Gitlab).to receive(:com?).and_return(false) + end + + describe '#up' do + it 'does not schedule background job' do + expect(migration).not_to receive(:queue_batched_background_migration) + + migration.up + end + end + + describe '#down' do + it 'does not delete background job' do + expect(migration).not_to receive(:delete_batched_background_migration) + + migration.down + end + end + end +end diff --git a/spec/migrations/20220523171107_drop_deploy_tokens_token_column_spec.rb b/spec/migrations/20220523171107_drop_deploy_tokens_token_column_spec.rb new file mode 100644 index 00000000000..78df6f5fc35 --- /dev/null +++ b/spec/migrations/20220523171107_drop_deploy_tokens_token_column_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe DropDeployTokensTokenColumn do + let(:deploy_tokens) { table(:deploy_tokens) } + + it 'correctly migrates up and down' do + reversible_migration do |migration| + migration.before -> { + expect(deploy_tokens.column_names).to include('token') + } + + migration.after -> { + deploy_tokens.reset_column_information + + expect(deploy_tokens.column_names).not_to include('token') + } + end + end +end diff --git a/spec/migrations/20220524074947_finalize_backfill_null_note_discussion_ids_spec.rb b/spec/migrations/20220524074947_finalize_backfill_null_note_discussion_ids_spec.rb new file mode 100644 index 00000000000..74ad4662b3e --- /dev/null +++ b/spec/migrations/20220524074947_finalize_backfill_null_note_discussion_ids_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require_migration! + +RSpec.describe FinalizeBackfillNullNoteDiscussionIds, :migration do + subject(:migration) { described_class.new } + + let(:notes) { table(:notes) } + let(:bg_migration_class) { Gitlab::BackgroundMigration::BackfillNoteDiscussionId } + let(:bg_migration) { instance_double(bg_migration_class) } + + before do + stub_const("#{described_class.name}::BATCH_SIZE", 2) + end + + it 'performs remaining background migrations', :aggregate_failures do + # Already migrated + notes.create!(noteable_type: 'Issue', noteable_id: 1, discussion_id: Digest::SHA1.hexdigest('note1')) + notes.create!(noteable_type: 'Issue', noteable_id: 1, discussion_id: Digest::SHA1.hexdigest('note2')) + # update required + record1 = notes.create!(noteable_type: 'Issue', noteable_id: 1, discussion_id: nil) + record2 = notes.create!(noteable_type: 'Issue', noteable_id: 1, discussion_id: nil) + record3 = notes.create!(noteable_type: 'Issue', noteable_id: 1, discussion_id: nil) + + expect(Gitlab::BackgroundMigration).to receive(:steal).with(bg_migration_class.name.demodulize) + expect(bg_migration_class).to receive(:new).twice.and_return(bg_migration) + expect(bg_migration).to receive(:perform).with(record1.id, record2.id) + expect(bg_migration).to receive(:perform).with(record3.id, record3.id) + + migrate! + end +end diff --git a/spec/migrations/add_web_hook_calls_to_plan_limits_paid_tiers_spec.rb b/spec/migrations/add_web_hook_calls_to_plan_limits_paid_tiers_spec.rb new file mode 100644 index 00000000000..63ad9367503 --- /dev/null +++ b/spec/migrations/add_web_hook_calls_to_plan_limits_paid_tiers_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe AddWebHookCallsToPlanLimitsPaidTiers do + let_it_be(:plans) { table(:plans) } + let_it_be(:plan_limits) { table(:plan_limits) } + + context 'when on Gitlab.com' do + let(:free_plan) { plans.create!(name: 'free') } + let(:bronze_plan) { plans.create!(name: 'bronze') } + let(:silver_plan) { plans.create!(name: 'silver') } + let(:gold_plan) { plans.create!(name: 'gold') } + let(:premium_plan) { plans.create!(name: 'premium') } + let(:premium_trial_plan) { plans.create!(name: 'premium_trial') } + let(:ultimate_plan) { plans.create!(name: 'ultimate') } + let(:ultimate_trial_plan) { plans.create!(name: 'ultimate_trial') } + let(:opensource_plan) { plans.create!(name: 'opensource') } + + before do + allow(Gitlab).to receive(:com?).and_return(true) + # 120 is the value for 'free' migrated in `db/migrate/20210601131742_update_web_hook_calls_limit.rb` + plan_limits.create!(plan_id: free_plan.id, web_hook_calls: 120) + plan_limits.create!(plan_id: bronze_plan.id) + plan_limits.create!(plan_id: silver_plan.id) + plan_limits.create!(plan_id: gold_plan.id) + plan_limits.create!(plan_id: premium_plan.id) + plan_limits.create!(plan_id: premium_trial_plan.id) + plan_limits.create!(plan_id: ultimate_plan.id) + plan_limits.create!(plan_id: ultimate_trial_plan.id) + plan_limits.create!(plan_id: opensource_plan.id) + end + + it 'correctly migrates up and down' do + reversible_migration do |migration| + migration.before -> { + expect( + plan_limits.pluck(:plan_id, :web_hook_calls, :web_hook_calls_mid, :web_hook_calls_low) + ).to contain_exactly( + [free_plan.id, 120, 0, 0], + [bronze_plan.id, 0, 0, 0], + [silver_plan.id, 0, 0, 0], + [gold_plan.id, 0, 0, 0], + [premium_plan.id, 0, 0, 0], + [premium_trial_plan.id, 0, 0, 0], + [ultimate_plan.id, 0, 0, 0], + [ultimate_trial_plan.id, 0, 0, 0], + [opensource_plan.id, 0, 0, 0] + ) + } + + migration.after -> { + expect( + plan_limits.pluck(:plan_id, :web_hook_calls, :web_hook_calls_mid, :web_hook_calls_low) + ).to contain_exactly( + [free_plan.id, 500, 500, 500], + [bronze_plan.id, 4_000, 2_800, 1_600], + [silver_plan.id, 4_000, 2_800, 1_600], + [gold_plan.id, 13_000, 9_000, 6_000], + [premium_plan.id, 4_000, 2_800, 1_600], + [premium_trial_plan.id, 4_000, 2_800, 1_600], + [ultimate_plan.id, 13_000, 9_000, 6_000], + [ultimate_trial_plan.id, 13_000, 9_000, 6_000], + [opensource_plan.id, 13_000, 9_000, 6_000] + ) + } + end + end + end + + context 'when on self hosted' do + let(:default_plan) { plans.create!(name: 'default') } + + before do + allow(Gitlab).to receive(:com?).and_return(false) + + plan_limits.create!(plan_id: default_plan.id) + end + + it 'does nothing' do + reversible_migration do |migration| + migration.before -> { + expect( + plan_limits.pluck(:plan_id, :web_hook_calls, :web_hook_calls_mid, :web_hook_calls_low) + ).to contain_exactly( + [default_plan.id, 0, 0, 0] + ) + } + + migration.after -> { + expect( + plan_limits.pluck(:plan_id, :web_hook_calls, :web_hook_calls_mid, :web_hook_calls_low) + ).to contain_exactly( + [default_plan.id, 0, 0, 0] + ) + } + end + end + end +end diff --git a/spec/migrations/bulk_insert_cluster_enabled_grants_spec.rb b/spec/migrations/bulk_insert_cluster_enabled_grants_spec.rb new file mode 100644 index 00000000000..a359a78ab45 --- /dev/null +++ b/spec/migrations/bulk_insert_cluster_enabled_grants_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe BulkInsertClusterEnabledGrants, :migration do + let(:migration) { described_class.new } + + let(:cluster_enabled_grants) { table(:cluster_enabled_grants) } + let(:namespaces) { table(:namespaces) } + let(:cluster_projects) { table(:cluster_projects) } + let(:cluster_groups) { table(:cluster_groups) } + let(:clusters) { table(:clusters) } + let(:projects) { table(:projects) } + + context 'with namespaces, cluster_groups and cluster_projects' do + it 'creates unique cluster_enabled_grants for root_namespaces with clusters' do + # Does not create grants for namespaces without clusters + namespaces.create!(id: 1, path: 'eee', name: 'eee', traversal_ids: [1]) # not used + + # Creates unique grant for a root namespace with its own cluster + root_ns_with_own_cluster = namespaces.create!(id: 2, path: 'ddd', name: 'ddd', traversal_ids: [2]) + cluster_root_ns_with_own_cluster = clusters.create!(name: 'cluster_root_ns_with_own_cluster') + cluster_groups.create!( + cluster_id: cluster_root_ns_with_own_cluster.id, + group_id: root_ns_with_own_cluster.id) + + # Creates unique grant for namespaces with multiple sub-group clusters + root_ns_with_sub_group_clusters = namespaces.create!(id: 3, path: 'aaa', name: 'aaa', traversal_ids: [3]) + + subgroup_1 = namespaces.create!( + id: 4, + path: 'bbb', + name: 'bbb', + parent_id: root_ns_with_sub_group_clusters.id, + traversal_ids: [root_ns_with_sub_group_clusters.id, 4]) + cluster_subgroup_1 = clusters.create!(name: 'cluster_subgroup_1') + cluster_groups.create!(cluster_id: cluster_subgroup_1.id, group_id: subgroup_1.id) + + subgroup_2 = namespaces.create!( + id: 5, + path: 'ccc', + name: 'ccc', + parent_id: subgroup_1.id, + traversal_ids: [root_ns_with_sub_group_clusters.id, subgroup_1.id, 5]) + cluster_subgroup_2 = clusters.create!(name: 'cluster_subgroup_2') + cluster_groups.create!(cluster_id: cluster_subgroup_2.id, group_id: subgroup_2.id) + + # Creates unique grant for a root namespace with multiple projects clusters + root_ns_with_project_group_clusters = namespaces.create!(id: 6, path: 'fff', name: 'fff', traversal_ids: [6]) + + project_namespace_1 = namespaces.create!(id: 7, path: 'ggg', name: 'ggg', traversal_ids: [7]) + project_1 = projects.create!( + name: 'project_1', + namespace_id: root_ns_with_project_group_clusters.id, + project_namespace_id: project_namespace_1.id) + cluster_project_1 = clusters.create!(name: 'cluster_project_1') + cluster_projects.create!(cluster_id: cluster_project_1.id, project_id: project_1.id) + + project_namespace_2 = namespaces.create!(id: 8, path: 'hhh', name: 'hhh', traversal_ids: [8]) + project_2 = projects.create!( + name: 'project_2', + namespace_id: root_ns_with_project_group_clusters.id, + project_namespace_id: project_namespace_2.id) + cluster_project_2 = clusters.create!(name: 'cluster_project_2') + cluster_projects.create!(cluster_id: cluster_project_2.id, project_id: project_2.id) + + migrate! + + expected_cluster_enabled_grants = [ + root_ns_with_sub_group_clusters.id, + root_ns_with_own_cluster.id, + root_ns_with_project_group_clusters.id + ] + + expect(cluster_enabled_grants.pluck(:namespace_id)).to match_array(expected_cluster_enabled_grants) + end + end + + context 'without namespaces, cluster_groups or cluster_projects' do + it 'does nothing' do + expect { migrate! }.not_to change { cluster_enabled_grants.count } + end + end +end diff --git a/spec/migrations/cleanup_backfill_integrations_enable_ssl_verification_spec.rb b/spec/migrations/cleanup_backfill_integrations_enable_ssl_verification_spec.rb new file mode 100644 index 00000000000..1517405b358 --- /dev/null +++ b/spec/migrations/cleanup_backfill_integrations_enable_ssl_verification_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe CleanupBackfillIntegrationsEnableSslVerification, :migration do + let(:job_class_name) { 'BackfillIntegrationsEnableSslVerification' } + + before do + # Jobs enqueued in Sidekiq. + Sidekiq::Testing.disable! do + BackgroundMigrationWorker.perform_in(10, job_class_name, [1, 2]) + BackgroundMigrationWorker.perform_in(20, job_class_name, [3, 4]) + end + + # Jobs tracked in the database. + Gitlab::Database::BackgroundMigrationJob.create!( + class_name: job_class_name, + arguments: [5, 6], + status: Gitlab::Database::BackgroundMigrationJob.statuses['pending'] + ) + Gitlab::Database::BackgroundMigrationJob.create!( + class_name: job_class_name, + arguments: [7, 8], + status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded'] + ) + + migrate! + end + + it_behaves_like( + 'finalized tracked background migration', + Gitlab::BackgroundMigration::BackfillIntegrationsEnableSslVerification + ) +end diff --git a/spec/migrations/cleanup_orphaned_routes_spec.rb b/spec/migrations/cleanup_orphaned_routes_spec.rb new file mode 100644 index 00000000000..68598939557 --- /dev/null +++ b/spec/migrations/cleanup_orphaned_routes_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe CleanupOrphanedRoutes, :migration do + let(:migration) { described_class::MIGRATION } + + describe '#up' do + it 'schedules background jobs' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + table_name: :routes, + column_name: :id, + interval: described_class::DELAY_INTERVAL, + gitlab_schema: :gitlab_main + ) + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/migrations/finalize_routes_backfilling_for_projects_spec.rb b/spec/migrations/finalize_routes_backfilling_for_projects_spec.rb new file mode 100644 index 00000000000..2bb740d0c2f --- /dev/null +++ b/spec/migrations/finalize_routes_backfilling_for_projects_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe FinalizeRoutesBackfillingForProjects, :migration do + let(:batched_migrations) { table(:batched_background_migrations) } + + let_it_be(:migration) { described_class::MIGRATION } + + describe '#up' do + shared_examples 'finalizes the migration' do + it 'finalizes the migration' do + allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner| + expect(runner).to receive(:finalize).with('BackfillNamespaceIdForProjectRoute', :projects, :id, []) + end + end + end + + context 'when routes backfilling migration is missing' do + it 'warns migration not found' do + expect(Gitlab::AppLogger) + .to receive(:warn).with(/Could not find batched background migration for the given configuration:/) + + migrate! + end + end + + context 'with backfilling migration present' do + let!(:project_namespace_backfill) do + batched_migrations.create!( + job_class_name: 'BackfillNamespaceIdForProjectRoute', + table_name: :routes, + column_name: :id, + job_arguments: [], + interval: 2.minutes, + min_value: 1, + max_value: 2, + batch_size: 1000, + sub_batch_size: 200, + gitlab_schema: :gitlab_main, + status: 3 # finished + ) + end + + context 'when backfilling migration finished successfully' do + it 'does not raise exception' do + expect { migrate! }.not_to raise_error + end + end + + context 'with different backfilling migration statuses' do + using RSpec::Parameterized::TableSyntax + + where(:status, :description) do + 0 | 'paused' + 1 | 'active' + 4 | 'failed' + 5 | 'finalizing' + end + + with_them do + before do + project_namespace_backfill.update!(status: status) + end + + it_behaves_like 'finalizes the migration' + end + end + end + end +end diff --git a/spec/migrations/queue_backfill_project_feature_package_registry_access_level_spec.rb b/spec/migrations/queue_backfill_project_feature_package_registry_access_level_spec.rb new file mode 100644 index 00000000000..487d94b82a1 --- /dev/null +++ b/spec/migrations/queue_backfill_project_feature_package_registry_access_level_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillProjectFeaturePackageRegistryAccessLevel do + let_it_be(:batched_migration) { described_class::MIGRATION } + + it 'schedules a new batched migration' do + reversible_migration do |migration| + migration.before -> { + expect(batched_migration).not_to have_scheduled_batched_migration + } + + migration.after -> { + expect(batched_migration).to have_scheduled_batched_migration( + table_name: :projects, + column_name: :id, + interval: described_class::DELAY_INTERVAL + ) + } + end + end +end diff --git a/spec/migrations/remove_invalid_integrations_spec.rb b/spec/migrations/remove_invalid_integrations_spec.rb new file mode 100644 index 00000000000..cab2d79998e --- /dev/null +++ b/spec/migrations/remove_invalid_integrations_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe RemoveInvalidIntegrations, :migration do + describe '#up' do + let!(:integrations) { table(:integrations) } + + let!(:valid_integration) { integrations.create!(type_new: 'Foo') } + let!(:invalid_integration) { integrations.create! } + + it 'removes invalid integrations', :aggregate_failures do + expect { migrate! } + .to change { integrations.pluck(:id) }.to(contain_exactly(valid_integration.id)) + end + + context 'when there are many invalid integrations' do + before do + stub_const('RemoveInvalidIntegrations::BATCH_SIZE', 3) + 5.times { integrations.create! } + end + + it 'removes them all' do + migrate! + + expect(integrations.pluck(:type_new)).to all(be_present) + end + end + end +end diff --git a/spec/migrations/remove_not_null_contraint_on_title_from_sprints_spec.rb b/spec/migrations/remove_not_null_contraint_on_title_from_sprints_spec.rb index fdafc4a5a89..198644fe183 100644 --- a/spec/migrations/remove_not_null_contraint_on_title_from_sprints_spec.rb +++ b/spec/migrations/remove_not_null_contraint_on_title_from_sprints_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' require_migration! -RSpec.describe RemoveNotNullContraintOnTitleFromSprints, :migration, schema: 20220304052335 do +RSpec.describe RemoveNotNullContraintOnTitleFromSprints, :migration do let(:migration) { described_class.new } let(:namespaces) { table(:namespaces) } let(:sprints) { table(:sprints) } diff --git a/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb b/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb deleted file mode 100644 index 52bbd5b4f6e..00000000000 --- a/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require_migration! - -RSpec.describe ScheduleMigratePagesToZipStorage, :sidekiq_might_not_need_inline, schema: 20210301200959 do - let(:migration_class) { described_class::MIGRATION } - let(:migration_name) { migration_class.to_s.demodulize } - - let(:namespaces_table) { table(:namespaces) } - let(:projects_table) { table(:projects) } - let(:metadata_table) { table(:project_pages_metadata) } - let(:deployments_table) { table(:pages_deployments) } - - let(:namespace) { namespaces_table.create!(path: "group", name: "group") } - - def create_project_metadata(path, deployed, with_deployment) - project = projects_table.create!(path: path, namespace_id: namespace.id) - - deployment_id = nil - - if with_deployment - deployment_id = deployments_table.create!(project_id: project.id, file_store: 1, file: '1', file_count: 1, file_sha256: '123', size: 1).id - end - - metadata_table.create!(project_id: project.id, deployed: deployed, pages_deployment_id: deployment_id) - end - - it 'correctly schedules background migrations' do - Sidekiq::Testing.fake! do - freeze_time do - create_project_metadata("not-deployed-project", false, false) - - first_id = create_project_metadata("project1", true, false).id - last_id = create_project_metadata("project2", true, false).id - - create_project_metadata("project-with-deployment", true, true) - - migrate! - - expect(migration_name).to be_scheduled_delayed_migration(5.minutes, first_id, last_id) - expect(BackgroundMigrationWorker.jobs.size).to eq(1) - end - end - end -end diff --git a/spec/migrations/schedule_populate_requirements_issue_id_spec.rb b/spec/migrations/schedule_populate_requirements_issue_id_spec.rb new file mode 100644 index 00000000000..2702c000b60 --- /dev/null +++ b/spec/migrations/schedule_populate_requirements_issue_id_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe SchedulePopulateRequirementsIssueId do + include MigrationHelpers::WorkItemTypesHelper + + let(:issues) { table(:issues) } + let(:requirements) { table(:requirements) } + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:users) { table(:users) } + let!(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') } + let!(:project_namespace) { namespaces.create!(name: 'project-namespace', path: 'project-namespace') } + + let!(:project) do + projects.create!(namespace_id: group.id, project_namespace_id: project_namespace.id, name: 'gitlab', path: 'gitlab') + end + + let(:migration) { described_class::MIGRATION } + + let!(:author) do + users.create!( + email: 'author@example.com', + notification_email: 'author@example.com', + name: 'author', + username: 'author', + projects_limit: 10, + state: 'active') + end + + before do + stub_const("#{described_class.name}::BATCH_SIZE", 2) + end + + it 'schedules jobs for all requirements without issues in sync' do + Sidekiq::Testing.fake! do + freeze_time do + migrate! + + # Restores the previous schema so we do not have a NOT NULL + # constraint on requirements.issue_id column, which would + # prevent us to create invalid requirement records. + migration_context.down(previous_migration(3).version) + + requirement_1 = create_requirement(iid: 1, title: 'r 1') + + # Create one requirement with issue_id present, to make + # sure a job won't be scheduled for it + work_item_type_id = work_item_types_table.find_by(namespace_id: nil, name: 'Issue').id + issue = issues.create!(state_id: 1, work_item_type_id: work_item_type_id) + create_requirement(iid: 2, title: 'r 2', issue_id: issue.id) + + requirement_3 = create_requirement(iid: 3, title: 'r 3') + requirement_4 = create_requirement(iid: 4, title: 'r 4') + requirement_5 = create_requirement(iid: 5, title: 'r 5') + + migrate! + + expect(migration).to be_scheduled_delayed_migration(120.seconds, requirement_1.id, requirement_3.id) + expect(migration).to be_scheduled_delayed_migration(240.seconds, requirement_4.id, requirement_5.id) + expect(BackgroundMigrationWorker.jobs.size).to eq(2) + end + end + end + + def create_requirement(iid:, title:, issue_id: nil) + requirements.create!( + iid: iid, + project_id: project.id, + issue_id: issue_id, + title: title, + state: 1, + created_at: Time.now, + updated_at: Time.now, + author_id: author.id) + end +end diff --git a/spec/migrations/schedule_purging_stale_security_scans_spec.rb b/spec/migrations/schedule_purging_stale_security_scans_spec.rb new file mode 100644 index 00000000000..b5a38634b58 --- /dev/null +++ b/spec/migrations/schedule_purging_stale_security_scans_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe SchedulePurgingStaleSecurityScans do + let_it_be(:namespaces) { table(:namespaces) } + let_it_be(:projects) { table(:projects) } + let_it_be(:pipelines) { table(:ci_pipelines) } + let_it_be(:builds) { table(:ci_builds) } + let_it_be(:security_scans) { table(:security_scans) } + + let_it_be(:namespace) { namespaces.create!(name: "foo", path: "bar") } + let_it_be(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) } + let_it_be(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') } + let_it_be(:ci_build) { builds.create!(commit_id: pipeline.id, retried: false, type: 'Ci::Build') } + + let!(:security_scan_1) { security_scans.create!(build_id: ci_build.id, scan_type: 1, created_at: 92.days.ago) } + let!(:security_scan_2) { security_scans.create!(build_id: ci_build.id, scan_type: 2, created_at: 91.days.ago) } + + let(:com?) { false } + let(:dev_or_test_env?) { false } + + before do + allow(::Gitlab).to receive(:com?).and_return(com?) + allow(::Gitlab).to receive(:dev_or_test_env?).and_return(dev_or_test_env?) + + stub_const("#{described_class.name}::BATCH_SIZE", 1) + end + + shared_examples_for 'schedules the background jobs' do + before do + # This will not be scheduled as it's not stale + security_scans.create!(build_id: ci_build.id, scan_type: 3) + end + + around do |example| + freeze_time { Sidekiq::Testing.fake! { example.run } } + end + + it 'creates 2 jobs', :aggregate_failures do + migrate! + + expect(BackgroundMigrationWorker.jobs.size).to be(2) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes, security_scan_1.id, security_scan_1.id) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes, security_scan_2.id, security_scan_2.id) + end + end + + context 'when the migration does not run on GitLab.com or `dev_or_test_env`' do + it 'does not run the migration' do + expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size } + end + end + + context 'when the migration runs on GitLab.com' do + let(:com?) { true } + + it_behaves_like 'schedules the background jobs' + end + + context 'when the migration runs on dev or test env' do + let(:dev_or_test_env?) { true } + + it_behaves_like 'schedules the background jobs' + end +end |