summaryrefslogtreecommitdiff
path: root/spec/migrations
diff options
context:
space:
mode:
Diffstat (limited to 'spec/migrations')
-rw-r--r--spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb138
-rw-r--r--spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb46
-rw-r--r--spec/migrations/cleanup_projects_with_bad_has_external_issue_tracker_data_spec.rb94
-rw-r--r--spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb30
-rw-r--r--spec/migrations/reschedule_artifact_expiry_backfill_spec.rb38
-rw-r--r--spec/migrations/reschedule_set_default_iteration_cadences_spec.rb41
-rw-r--r--spec/migrations/schedule_merge_request_assignees_migration_progress_check_spec.rb16
-rw-r--r--spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb10
8 files changed, 394 insertions, 19 deletions
diff --git a/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb b/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
new file mode 100644
index 00000000000..fce32be4683
--- /dev/null
+++ b/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
@@ -0,0 +1,138 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb')
+
+RSpec.describe ScheduleRecalculateUuidOnVulnerabilitiesOccurrences, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'uuid-v5',
+ external_id: 'uuid-v5',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'Identifier for UUIDv5')
+ end
+
+ let(:different_vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'uuid-v4',
+ external_id: 'uuid-v4',
+ fingerprint: '772da93d34a1ba010bcb5efa9fb6f8e01bafcc89',
+ name: 'Identifier for UUIDv4')
+ end
+
+ let!(:vulnerability_for_uuidv4) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:vulnerability_for_uuidv5) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let(:known_uuid_v4) { "b3cc2518-5446-4dea-871c-89d5e999c1ac" }
+ let!(:finding_with_uuid_v4) do
+ create_finding!(
+ vulnerability_id: vulnerability_for_uuidv4.id,
+ project_id: project.id,
+ scanner_id: different_scanner.id,
+ primary_identifier_id: different_vulnerability_identifier.id,
+ report_type: 0, # "sast"
+ location_fingerprint: "fa18f432f1d56675f4098d318739c3cd5b14eb3e",
+ uuid: known_uuid_v4
+ )
+ end
+
+ let(:known_uuid_v5) { "e7d3d99d-04bb-5771-bb44-d80a9702d0a2" }
+ let!(:finding_with_uuid_v5) do
+ create_finding!(
+ vulnerability_id: vulnerability_for_uuidv5.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id,
+ report_type: 0, # "sast"
+ location_fingerprint: "838574be0210968bf6b9f569df9c2576242cbf0a",
+ uuid: known_uuid_v5
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migration' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION).to be_scheduled_migration(finding_with_uuid_v4.id, finding_with_uuid_v4.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(finding_with_uuid_v5.id, finding_with_uuid_v5.id)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+end
diff --git a/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb b/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb
new file mode 100644
index 00000000000..e525101f3a0
--- /dev/null
+++ b/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('add_environment_scope_to_group_variables')
+
+RSpec.describe AddEnvironmentScopeToGroupVariables do
+ let(:migration) { described_class.new }
+ let(:ci_group_variables) { table(:ci_group_variables) }
+ let(:group) { table(:namespaces).create!(name: 'group', path: 'group') }
+
+ def create_variable!(group, key:, environment_scope: '*')
+ table(:ci_group_variables).create!(
+ group_id: group.id,
+ key: key,
+ environment_scope: environment_scope
+ )
+ end
+
+ describe '#down' do
+ context 'group has variables with duplicate keys' do
+ it 'deletes all but the first record' do
+ migration.up
+
+ remaining_variable = create_variable!(group, key: 'key')
+ create_variable!(group, key: 'key', environment_scope: 'staging')
+ create_variable!(group, key: 'key', environment_scope: 'production')
+
+ migration.down
+
+ expect(ci_group_variables.pluck(:id)).to eq [remaining_variable.id]
+ end
+ end
+
+ context 'group does not have variables with duplicate keys' do
+ it 'does not delete any records' do
+ migration.up
+
+ create_variable!(group, key: 'key')
+ create_variable!(group, key: 'staging')
+ create_variable!(group, key: 'production')
+
+ expect { migration.down }.not_to change { ci_group_variables.count }
+ end
+ end
+ end
+end
diff --git a/spec/migrations/cleanup_projects_with_bad_has_external_issue_tracker_data_spec.rb b/spec/migrations/cleanup_projects_with_bad_has_external_issue_tracker_data_spec.rb
new file mode 100644
index 00000000000..8aedd1f9607
--- /dev/null
+++ b/spec/migrations/cleanup_projects_with_bad_has_external_issue_tracker_data_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe CleanupProjectsWithBadHasExternalIssueTrackerData, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'foo', path: 'bar') }
+ let(:projects) { table(:projects) }
+ let(:services) { table(:services) }
+
+ def create_projects!(num)
+ Array.new(num) do
+ projects.create!(namespace_id: namespace.id)
+ end
+ end
+
+ def create_active_external_issue_tracker_integrations!(*projects)
+ projects.each do |project|
+ services.create!(category: 'issue_tracker', project_id: project.id, active: true)
+ end
+ end
+
+ def create_disabled_external_issue_tracker_integrations!(*projects)
+ projects.each do |project|
+ services.create!(category: 'issue_tracker', project_id: project.id, active: false)
+ end
+ end
+
+ def create_active_other_integrations!(*projects)
+ projects.each do |project|
+ services.create!(category: 'not_an_issue_tracker', project_id: project.id, active: true)
+ end
+ end
+
+ it 'sets `projects.has_external_issue_tracker` correctly' do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+
+ project_with_an_external_issue_tracker_1,
+ project_with_an_external_issue_tracker_2,
+ project_with_only_a_disabled_external_issue_tracker_1,
+ project_with_only_a_disabled_external_issue_tracker_2,
+ project_without_any_external_issue_trackers_1,
+ project_without_any_external_issue_trackers_2 = create_projects!(6)
+
+ create_active_external_issue_tracker_integrations!(
+ project_with_an_external_issue_tracker_1,
+ project_with_an_external_issue_tracker_2
+ )
+
+ create_disabled_external_issue_tracker_integrations!(
+ project_with_an_external_issue_tracker_1,
+ project_with_an_external_issue_tracker_2,
+ project_with_only_a_disabled_external_issue_tracker_1,
+ project_with_only_a_disabled_external_issue_tracker_2
+ )
+
+ create_active_other_integrations!(
+ project_with_an_external_issue_tracker_1,
+ project_with_an_external_issue_tracker_2,
+ project_without_any_external_issue_trackers_1,
+ project_without_any_external_issue_trackers_2
+ )
+
+ # PG triggers on the services table added in
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51852 will have set
+ # the `has_external_issue_tracker` columns to correct data when the services
+ # records were created above.
+ #
+ # We set the `has_external_issue_tracker` columns for projects to incorrect
+ # data manually below to emulate projects in a state before the PG
+ # triggers were added.
+ project_with_an_external_issue_tracker_2.update!(has_external_issue_tracker: false)
+ project_with_only_a_disabled_external_issue_tracker_2.update!(has_external_issue_tracker: true)
+ project_without_any_external_issue_trackers_2.update!(has_external_issue_tracker: true)
+
+ migrate!
+
+ expected_true = [
+ project_with_an_external_issue_tracker_1,
+ project_with_an_external_issue_tracker_2
+ ].each(&:reload).map(&:has_external_issue_tracker)
+
+ expected_not_true = [
+ project_without_any_external_issue_trackers_1,
+ project_without_any_external_issue_trackers_2,
+ project_with_only_a_disabled_external_issue_tracker_1,
+ project_with_only_a_disabled_external_issue_tracker_2
+ ].each(&:reload).map(&:has_external_issue_tracker)
+
+ expect(expected_true).to all(eq(true))
+ expect(expected_not_true).to all(be_falsey)
+ end
+end
diff --git a/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb b/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb
new file mode 100644
index 00000000000..28a8dcf0d4c
--- /dev/null
+++ b/spec/migrations/migrate_delayed_project_removal_from_namespaces_to_namespace_settings_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'post_migrate', '20210215095328_migrate_delayed_project_removal_from_namespaces_to_namespace_settings.rb')
+
+RSpec.describe MigrateDelayedProjectRemovalFromNamespacesToNamespaceSettings, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:namespace_settings) { table(:namespace_settings) }
+
+ let!(:namespace_wo_settings) { namespaces.create!(name: generate(:name), path: generate(:name), delayed_project_removal: true) }
+ let!(:namespace_wo_settings_delay_false) { namespaces.create!(name: generate(:name), path: generate(:name), delayed_project_removal: false) }
+ let!(:namespace_w_settings_delay_true) { namespaces.create!(name: generate(:name), path: generate(:name), delayed_project_removal: true) }
+ let!(:namespace_w_settings_delay_false) { namespaces.create!(name: generate(:name), path: generate(:name), delayed_project_removal: false) }
+
+ let!(:namespace_settings_delay_true) { namespace_settings.create!(namespace_id: namespace_w_settings_delay_true.id, delayed_project_removal: false, created_at: DateTime.now, updated_at: DateTime.now) }
+ let!(:namespace_settings_delay_false) { namespace_settings.create!(namespace_id: namespace_w_settings_delay_false.id, delayed_project_removal: false, created_at: DateTime.now, updated_at: DateTime.now) }
+
+ it 'migrates delayed_project_removal to namespace_settings' do
+ disable_migrations_output { migrate! }
+
+ expect(namespace_settings.count).to eq(3)
+
+ expect(namespace_settings.find_by(namespace_id: namespace_wo_settings.id).delayed_project_removal).to eq(true)
+ expect(namespace_settings.find_by(namespace_id: namespace_wo_settings_delay_false.id)).to be_nil
+
+ expect(namespace_settings_delay_true.reload.delayed_project_removal).to eq(true)
+ expect(namespace_settings_delay_false.reload.delayed_project_removal).to eq(false)
+ end
+end
diff --git a/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb b/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb
new file mode 100644
index 00000000000..532035849cb
--- /dev/null
+++ b/spec/migrations/reschedule_artifact_expiry_backfill_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'post_migrate', '20210224150506_reschedule_artifact_expiry_backfill.rb')
+
+RSpec.describe RescheduleArtifactExpiryBackfill, :migration do
+ let(:migration_class) { Gitlab::BackgroundMigration::BackfillArtifactExpiryDate }
+ let(:migration_name) { migration_class.to_s.demodulize }
+
+ before do
+ table(:namespaces).create!(id: 123, name: 'test_namespace', path: 'test_namespace')
+ table(:projects).create!(id: 123, name: 'sample_project', path: 'sample_project', namespace_id: 123)
+ end
+
+ it 'correctly schedules background migrations' do
+ first_artifact = create_artifact(job_id: 0, expire_at: nil, created_at: Date.new(2020, 06, 21))
+ second_artifact = create_artifact(job_id: 1, expire_at: nil, created_at: Date.new(2020, 06, 21))
+ create_artifact(job_id: 2, expire_at: Date.yesterday, created_at: Date.new(2020, 06, 21))
+ create_artifact(job_id: 3, expire_at: nil, created_at: Date.new(2020, 06, 23))
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ expect(migration_name).to be_scheduled_migration_with_multiple_args(first_artifact.id, second_artifact.id)
+ end
+ end
+ end
+
+ private
+
+ def create_artifact(params)
+ table(:ci_builds).create!(id: params[:job_id], project_id: 123)
+ table(:ci_job_artifacts).create!(project_id: 123, file_type: 1, **params)
+ end
+end
diff --git a/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb b/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb
new file mode 100644
index 00000000000..fb629c90d9f
--- /dev/null
+++ b/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe RescheduleSetDefaultIterationCadences do
+ let(:namespaces) { table(:namespaces) }
+ let(:iterations) { table(:sprints) }
+
+ let(:group_1) { namespaces.create!(name: 'test_1', path: 'test_1') }
+ let!(:group_2) { namespaces.create!(name: 'test_2', path: 'test_2') }
+ let(:group_3) { namespaces.create!(name: 'test_3', path: 'test_3') }
+ let(:group_4) { namespaces.create!(name: 'test_4', path: 'test_4') }
+ let(:group_5) { namespaces.create!(name: 'test_5', path: 'test_5') }
+ let(:group_6) { namespaces.create!(name: 'test_6', path: 'test_6') }
+ let(:group_7) { namespaces.create!(name: 'test_7', path: 'test_7') }
+ let(:group_8) { namespaces.create!(name: 'test_8', path: 'test_8') }
+
+ let!(:iteration_1) { iterations.create!(iid: 1, title: 'iteration 1', group_id: group_1.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_2) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_3.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_3) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_4.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_4) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_5.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_5) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_6.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_6) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_7.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+ let!(:iteration_7) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_8.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules the background jobs', :aggregate_failures do
+ stub_const("#{described_class.name}::BATCH_SIZE", 3)
+
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to be(3)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, group_1.id, group_3.id, group_4.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, group_5.id, group_6.id, group_7.id)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, group_8.id)
+ end
+end
diff --git a/spec/migrations/schedule_merge_request_assignees_migration_progress_check_spec.rb b/spec/migrations/schedule_merge_request_assignees_migration_progress_check_spec.rb
deleted file mode 100644
index 0a69f49f10d..00000000000
--- a/spec/migrations/schedule_merge_request_assignees_migration_progress_check_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190402224749_schedule_merge_request_assignees_migration_progress_check.rb')
-
-RSpec.describe ScheduleMergeRequestAssigneesMigrationProgressCheck do
- describe '#up' do
- it 'schedules MergeRequestAssigneesMigrationProgressCheck background job' do
- expect(BackgroundMigrationWorker).to receive(:perform_async)
- .with(described_class::MIGRATION)
- .and_call_original
-
- subject.up
- end
- end
-end
diff --git a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
index 8678361fc64..faa993dfbc7 100644
--- a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
+++ b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
@@ -6,11 +6,15 @@ require Rails.root.join('db', 'post_migrate', '20200714075739_schedule_populate_
RSpec.describe SchedulePopulatePersonalSnippetStatistics do
let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
let(:snippets) { table(:snippets) }
let(:projects) { table(:projects) }
- let(:user1) { users.create!(id: 1, email: 'user1@example.com', projects_limit: 10, username: 'test1', name: 'Test1', state: 'active') }
- let(:user2) { users.create!(id: 2, email: 'user2@example.com', projects_limit: 10, username: 'test2', name: 'Test2', state: 'active') }
- let(:user3) { users.create!(id: 3, email: 'user3@example.com', projects_limit: 10, username: 'test3', name: 'Test3', state: 'active') }
+ let!(:user1) { users.create!(id: 1, email: 'user1@example.com', projects_limit: 10, username: 'test1', name: 'Test1', state: 'active') }
+ let!(:user2) { users.create!(id: 2, email: 'user2@example.com', projects_limit: 10, username: 'test2', name: 'Test2', state: 'active') }
+ let!(:user3) { users.create!(id: 3, email: 'user3@example.com', projects_limit: 10, username: 'test3', name: 'Test3', state: 'active') }
+ let!(:namespace1) { namespaces.create!(id: 1, owner_id: user1.id, name: 'test1', path: 'test1') }
+ let!(:namespace2) { namespaces.create!(id: 2, owner_id: user2.id, name: 'test2', path: 'test2') }
+ let!(:namespace3) { namespaces.create!(id: 3, owner_id: user3.id, name: 'test3', path: 'test3') }
def create_snippet(id, user_id, type = 'PersonalSnippet')
params = {