diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 09:40:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 09:40:42 +0000 |
commit | ee664acb356f8123f4f6b00b73c1e1cf0866c7fb (patch) | |
tree | f8479f94a28f66654c6a4f6fb99bad6b4e86a40e /spec/lib/gitlab/background_migration | |
parent | 62f7d5c5b69180e82ae8196b7b429eeffc8e7b4f (diff) | |
download | gitlab-ce-ee664acb356f8123f4f6b00b73c1e1cf0866c7fb.tar.gz |
Add latest changes from gitlab-org/gitlab@15-5-stable-eev15.5.0-rc42
Diffstat (limited to 'spec/lib/gitlab/background_migration')
11 files changed, 585 insertions, 33 deletions
diff --git a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb index d8a7ec775dd..e6588644b4f 100644 --- a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb +++ b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb @@ -7,13 +7,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat let(:integrations) { table(:integrations) } let(:namespaced_integrations) do - Set.new(%w[ - Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog - Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost - MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker - Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao - Github GitlabSlackApplication - ]).freeze + Set.new( + %w[ + Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog + Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Harbor Irker Jenkins Jira Mattermost + MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker + Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao + Github GitlabSlackApplication + ]).freeze end before do @@ -40,13 +41,14 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew, :migrat expect(queries.count).to be(16) expect(queries.log.grep(/^SELECT/).size).to be(11) expect(queries.log.grep(/^UPDATE/).size).to be(5) - expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq([ - 'WHERE integrations.id BETWEEN 2 AND 3', - 'WHERE integrations.id BETWEEN 4 AND 5', - 'WHERE integrations.id BETWEEN 6 AND 7', - 'WHERE integrations.id BETWEEN 8 AND 9', - 'WHERE integrations.id BETWEEN 10 AND 10' - ]) + expect(queries.log.grep(/^UPDATE/).join.scan(/WHERE .*/)).to eq( + [ + 'WHERE integrations.id BETWEEN 2 AND 3', + 'WHERE integrations.id BETWEEN 4 AND 5', + 'WHERE integrations.id BETWEEN 6 AND 7', + 'WHERE integrations.id BETWEEN 8 AND 9', + 'WHERE integrations.id BETWEEN 10 AND 10' + ]) expect(integrations.where(id: 2..10).pluck(:type, :type_new)).to contain_exactly( ['AssemblaService', 'Integrations::Assembla'], diff --git a/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb new file mode 100644 index 00000000000..40a4758ba5f --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillInternalOnNotes, :migration, schema: 20220920124709 do + let(:notes_table) { table(:notes) } + + let!(:confidential_note) { notes_table.create!(id: 1, confidential: true, internal: false) } + let!(:non_confidential_note) { notes_table.create!(id: 2, confidential: false, internal: false) } + + describe '#perform' do + subject(:perform) do + described_class.new( + start_id: 1, + end_id: 2, + batch_table: :notes, + batch_column: :id, + sub_batch_size: 1, + pause_ms: 0, + connection: ApplicationRecord.connection + ).perform + end + + it 'backfills internal column on notes when confidential' do + expect { perform } + .to change { confidential_note.reload.internal }.from(false).to(true) + .and not_change { non_confidential_note.reload.internal } + end + end +end diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb new file mode 100644 index 00000000000..b6282de0da6 --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceDetails, :migration do + let(:namespaces) { table(:namespaces) } + let(:namespace_details) { table(:namespace_details) } + + subject(:perform_migration) do + described_class.new(start_id: namespaces.minimum(:id), + end_id: namespaces.maximum(:id), + batch_table: :namespaces, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + .perform + end + + describe '#perform' do + it 'creates details for all namespaces in range' do + namespace1 = namespaces.create!(id: 5, name: 'test1', path: 'test1', description: "Some description1", + description_html: "Some description html1", cached_markdown_version: 4) + namespaces.create!(id: 6, name: 'test2', path: 'test2', type: 'Project', + description: "Some description2", description_html: "Some description html2", + cached_markdown_version: 4) + namespace3 = namespaces.create!(id: 7, name: 'test3', path: 'test3', description: "Some description3", + description_html: "Some description html3", cached_markdown_version: 4) + namespace4 = namespaces.create!(id: 8, name: 'test4', path: 'test4', description: "Some description3", + description_html: "Some description html4", cached_markdown_version: 4) + namespace_details.delete_all + + expect(namespace_details.pluck(:namespace_id)).to eql [] + + expect { perform_migration } + .to change { namespace_details.pluck(:namespace_id) }.from([]).to contain_exactly( + namespace1.id, + namespace3.id, + namespace4.id + ) + + expect(namespace_details.find_by_namespace_id(namespace1.id)).to have_attributes(migrated_attributes(namespace1)) + expect(namespace_details.find_by_namespace_id(namespace3.id)).to have_attributes(migrated_attributes(namespace3)) + expect(namespace_details.find_by_namespace_id(namespace4.id)).to have_attributes(migrated_attributes(namespace4)) + end + end + + def migrated_attributes(namespace) + { + description: namespace.description, + description_html: namespace.description_html, + cached_markdown_version: namespace.cached_markdown_version + } + end +end diff --git a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb index 8a3671b2e53..dd202acc372 100644 --- a/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb +++ b/spec/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects_spec.rb @@ -40,23 +40,26 @@ RSpec.describe Gitlab::BackgroundMigration::CleanupOrphanedLfsObjectsProjects, s it 'lfs_objects_projects without an existing lfs object or project are removed' do subject.perform(without_object1.id, without_object3.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3, - without_project1, without_project2, without_project_and_object - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3, + without_project1, without_project2, without_project_and_object + ]) subject.perform(with_project_and_object1.id, with_project_and_object3.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3, - without_project1, without_project2, without_project_and_object - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3, + without_project1, without_project2, without_project_and_object + ]) subject.perform(without_project1.id, without_project_and_object.id) - expect(lfs_objects_projects.all).to match_array([ - with_project_and_object1, with_project_and_object2, with_project_and_object3 - ]) + expect(lfs_objects_projects.all).to match_array( + [ + with_project_and_object1, with_project_and_object2, with_project_and_object3 + ]) expect(lfs_objects.ids).to contain_exactly(lfs_object.id, another_lfs_object.id) expect(projects.ids).to contain_exactly(project.id, another_project.id) diff --git a/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb new file mode 100644 index 00000000000..afa955a6056 --- /dev/null +++ b/spec/lib/gitlab/background_migration/delete_orphaned_operational_vulnerabilities_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::DeleteOrphanedOperationalVulnerabilities, :migration do + include MigrationHelpers::VulnerabilitiesHelper + + let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') } + let_it_be(:users) { table(:users) } + let_it_be(:user) do + users.create!( + name: "Example User", + email: "user@example.com", + username: "Example User", + projects_limit: 0, + confirmed_at: Time.current + ) + end + + let_it_be(:project) do + table(:projects).create!( + id: 123, + namespace_id: namespace.id, + project_namespace_id: namespace.id + ) + end + + let_it_be(:scanners) { table(:vulnerability_scanners) } + let_it_be(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') } + let_it_be(:different_scanner) do + scanners.create!( + project_id: project.id, + external_id: 'test 2', + name: 'test scanner 2' + ) + end + + let_it_be(:vulnerabilities) { table(:vulnerabilities) } + let_it_be(:vulnerability_with_finding) do + create_vulnerability!( + project_id: project.id, + author_id: user.id + ) + end + + let_it_be(:vulnerability_without_finding) do + create_vulnerability!( + project_id: project.id, + author_id: user.id + ) + end + + let_it_be(:cis_vulnerability_without_finding) do + create_vulnerability!( + project_id: project.id, + author_id: user.id, + report_type: 7 + ) + end + + let_it_be(:custom_vulnerability_without_finding) do + create_vulnerability!( + project_id: project.id, + author_id: user.id, + report_type: 99 + ) + end + + let_it_be(:vulnerability_identifiers) { table(:vulnerability_identifiers) } + let_it_be(:primary_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_it_be(:vulnerabilities_findings) { table(:vulnerability_occurrences) } + let_it_be(:finding) do + create_finding!( + vulnerability_id: vulnerability_with_finding.id, + project_id: project.id, + scanner_id: scanner.id, + primary_identifier_id: primary_identifier.id + ) + end + + subject(:background_migration) do + described_class.new(start_id: vulnerabilities.minimum(:id), + end_id: vulnerabilities.maximum(:id), + batch_table: :vulnerabilities, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + end + + it 'drops Cluster Image Scanning and Custom Vulnerabilities without any Findings' do + expect(vulnerabilities.pluck(:id)).to match_array([ + vulnerability_with_finding.id, + vulnerability_without_finding.id, + cis_vulnerability_without_finding.id, + custom_vulnerability_without_finding.id + ]) + + expect { background_migration.perform }.to change(vulnerabilities, :count).by(-2) + + expect(vulnerabilities.pluck(:id)).to match_array([vulnerability_with_finding.id, vulnerability_without_finding.id]) + end +end diff --git a/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb b/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb new file mode 100644 index 00000000000..9b0cb96b30b --- /dev/null +++ b/spec/lib/gitlab/background_migration/destroy_invalid_members_spec.rb @@ -0,0 +1,141 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# rubocop: disable RSpec/MultipleMemoizedHelpers +RSpec.describe Gitlab::BackgroundMigration::DestroyInvalidMembers, :migration, schema: 20221004094814 do + let!(:migration_attrs) do + { + start_id: 1, + end_id: 1000, + batch_table: :members, + batch_column: :id, + sub_batch_size: 100, + pause_ms: 0, + connection: ApplicationRecord.connection + } + end + + let(:users_table) { table(:users) } + let(:namespaces_table) { table(:namespaces) } + let(:members_table) { table(:members) } + let(:projects_table) { table(:projects) } + let(:members_table_name) { 'members' } + let(:connection) { ApplicationRecord.connection } + let(:user1) { users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 5) } + let(:user2) { users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 5) } + let(:user3) { users_table.create!(name: 'user3', email: 'user3@example.com', projects_limit: 5) } + let(:user4) { users_table.create!(name: 'user4', email: 'user4@example.com', projects_limit: 5) } + let(:user5) { users_table.create!(name: 'user5', email: 'user5@example.com', projects_limit: 5) } + let(:user6) { users_table.create!(name: 'user6', email: 'user6@example.com', projects_limit: 5) } + let(:user7) { users_table.create!(name: 'user7', email: 'user7@example.com', projects_limit: 5) } + let(:user8) { users_table.create!(name: 'user8', email: 'user8@example.com', projects_limit: 5) } + let!(:group1) { namespaces_table.create!(name: 'marvellous group 1', path: 'group-path-1', type: 'Group') } + let!(:group2) { namespaces_table.create!(name: 'outstanding group 2', path: 'group-path-2', type: 'Group') } + let!(:project_namespace1) do + namespaces_table.create!(name: 'fabulous project', path: 'project-path-1', + type: 'ProjectNamespace', parent_id: group1.id) + end + + let!(:project1) do + projects_table.create!(name: 'fabulous project', path: 'project-path-1', + project_namespace_id: project_namespace1.id, namespace_id: group1.id) + end + + let!(:project_namespace2) do + namespaces_table.create!(name: 'splendiferous project', path: 'project-path-2', + type: 'ProjectNamespace', parent_id: group1.id) + end + + let!(:project2) do + projects_table.create!(name: 'splendiferous project', path: 'project-path-2', + project_namespace_id: project_namespace2.id, namespace_id: group1.id) + end + + # create valid project member records + let!(:project_member1) { create_valid_project_member(id: 1, user_id: user1.id, project: project1) } + let!(:project_member2) { create_valid_project_member(id: 2, user_id: user2.id, project: project2) } + # create valid group member records + let!(:group_member5) { create_valid_group_member(id: 5, user_id: user5.id, group_id: group1.id) } + let!(:group_member6) { create_valid_group_member(id: 6, user_id: user6.id, group_id: group2.id) } + + let!(:migration) { described_class.new(**migration_attrs) } + + subject(:perform_migration) { migration.perform } + + # create invalid project and group member records + def create_members + [ + create_invalid_project_member(id: 3, user_id: user3.id), + create_invalid_project_member(id: 4, user_id: user4.id), + create_invalid_group_member(id: 7, user_id: user7.id), + create_invalid_group_member(id: 8, user_id: user8.id) + ] + end + + it 'removes invalid memberships but keeps valid ones', :aggregate_failures do + without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do + create_members + + expect(members_table.count).to eq 8 + + queries = ActiveRecord::QueryRecorder.new do + perform_migration + end + + expect(queries.count).to eq(4) + expect(members_table.all).to match_array([project_member1, project_member2, group_member5, group_member6]) + end + end + + it 'tracks timings of queries' do + without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do + create_members + + expect(migration.batch_metrics.timings).to be_empty + + expect { perform_migration }.to change { migration.batch_metrics.timings } + end + end + + it 'logs IDs of deleted records' do + without_check_constraint(members_table_name, 'check_508774aac0', connection: connection) do + members = create_members + + member_data = members.map do |m| + { id: m.id, source_id: m.source_id, source_type: m.source_type } + end + + expect(Gitlab::AppLogger).to receive(:info).with({ message: 'Removing invalid member records', + deleted_count: 4, + deleted_member_data: member_data }) + + perform_migration + end + end + + def create_invalid_project_member(id:, user_id:) + members_table.create!(id: id, user_id: user_id, source_id: non_existing_record_id, + access_level: Gitlab::Access::MAINTAINER, type: "ProjectMember", + source_type: "Project", notification_level: 3, member_namespace_id: nil) + end + + def create_valid_project_member(id:, user_id:, project:) + members_table.create!(id: id, user_id: user_id, source_id: project.id, + access_level: Gitlab::Access::MAINTAINER, type: "ProjectMember", source_type: "Project", + member_namespace_id: project.project_namespace_id, notification_level: 3) + end + + def create_invalid_group_member(id:, user_id:) + members_table.create!(id: id, user_id: user_id, source_id: non_existing_record_id, + access_level: Gitlab::Access::MAINTAINER, type: "GroupMember", + source_type: "Namespace", notification_level: 3, member_namespace_id: nil) + end + + def create_valid_group_member(id:, user_id:, group_id:) + members_table.create!(id: id, user_id: user_id, source_id: group_id, + access_level: Gitlab::Access::MAINTAINER, type: "GroupMember", + source_type: "Namespace", member_namespace_id: group_id, notification_level: 3) + end +end +# rubocop: enable RSpec/MultipleMemoizedHelpers diff --git a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb index 31b6ee0c7cd..c3ae2cc060c 100644 --- a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb @@ -79,10 +79,11 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers, it 'produces a union of the given queries' do alice = commit_users.create!(name: 'Alice', email: 'alice@example.com') bob = commit_users.create!(name: 'Bob', email: 'bob@example.com') - users = commit_users.union([ - commit_users.where(name: 'Alice').to_sql, - commit_users.where(name: 'Bob').to_sql - ]) + users = commit_users.union( + [ + commit_users.where(name: 'Alice').to_sql, + commit_users.where(name: 'Bob').to_sql + ]) expect(users).to include(alice) expect(users).to include(bob) diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb index a609227be05..29cc4f34f6d 100644 --- a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb +++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb @@ -246,9 +246,15 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence end it 'drops duplicates and related records', :aggregate_failures do - expect(vulnerability_findings.pluck(:id)).to match_array([ - finding_with_correct_uuid.id, finding_with_incorrect_uuid.id, finding_with_correct_uuid2.id, finding_with_incorrect_uuid2.id, finding_with_incorrect_uuid3.id, duplicate_not_in_the_same_batch.id - ]) + expect(vulnerability_findings.pluck(:id)).to match_array( + [ + finding_with_correct_uuid.id, + finding_with_incorrect_uuid.id, + finding_with_correct_uuid2.id, + finding_with_incorrect_uuid2.id, + finding_with_incorrect_uuid3.id, + duplicate_not_in_the_same_batch.id + ]) expect { subject }.to change(vulnerability_finding_pipelines, :count).from(16).to(8) .and change(vulnerability_findings, :count).from(6).to(3) @@ -306,7 +312,8 @@ RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrence it 'retries the recalculation' do subject - expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding).to have_received(:find_by).with(uuid: uuid).once + expect(Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid::VulnerabilitiesFinding) + .to have_received(:find_by).with(uuid: uuid).once end it 'logs the conflict' do diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb new file mode 100644 index 00000000000..b6da8f7fc2d --- /dev/null +++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValues, + :migration, + schema: 20220922143634 do + it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob } + + describe '#perform' do + let(:ci_runners) { table(:ci_runners, database: :ci) } + + let(:test_worker) do + described_class.new( + start_id: 1, + end_id: 4, + batch_table: :ci_runners, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: Ci::ApplicationRecord.connection + ) + end + + subject(:perform) { test_worker.perform } + + before do + ci_runners.create!(id: 1, runner_type: 1, token_encrypted: 'duplicate') + ci_runners.create!(id: 2, runner_type: 1, token_encrypted: 'a-token') + ci_runners.create!(id: 3, runner_type: 1, token_encrypted: 'duplicate-2') + ci_runners.create!(id: 4, runner_type: 1, token_encrypted: nil) + ci_runners.create!(id: 5, runner_type: 1, token_encrypted: 'duplicate-2') + ci_runners.create!(id: 6, runner_type: 1, token_encrypted: 'duplicate') + ci_runners.create!(id: 7, runner_type: 1, token_encrypted: 'another-token') + ci_runners.create!(id: 8, runner_type: 1, token_encrypted: 'another-token') + end + + it 'nullifies duplicate encrypted tokens', :aggregate_failures do + expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token_encrypted).to_h } + .from( + { + 1 => 'duplicate', + 2 => 'a-token', + 3 => 'duplicate-2', + 4 => nil, + 5 => 'duplicate-2', + 6 => 'duplicate', + 7 => 'another-token', + 8 => 'another-token' + } + ) + .to( + { + 1 => nil, + 2 => 'a-token', + 3 => nil, + 4 => nil, + 5 => nil, + 6 => nil, + 7 => 'another-token', + 8 => 'another-token' + } + ) + expect(ci_runners.count).to eq(8) + expect(ci_runners.pluck(:token_encrypted).uniq).to match_array [ + nil, 'a-token', 'another-token' + ] + end + end +end diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb new file mode 100644 index 00000000000..423b1815e75 --- /dev/null +++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValues, + :migration, + schema: 20220922143143 do + it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob } + + describe '#perform' do + let(:ci_runners) { table(:ci_runners, database: :ci) } + + let(:test_worker) do + described_class.new( + start_id: 1, + end_id: 4, + batch_table: :ci_runners, + batch_column: :id, + sub_batch_size: 2, + pause_ms: 0, + connection: Ci::ApplicationRecord.connection + ) + end + + subject(:perform) { test_worker.perform } + + before do + ci_runners.create!(id: 1, runner_type: 1, token: 'duplicate') + ci_runners.create!(id: 2, runner_type: 1, token: 'a-token') + ci_runners.create!(id: 3, runner_type: 1, token: 'duplicate-2') + ci_runners.create!(id: 4, runner_type: 1, token: nil) + ci_runners.create!(id: 5, runner_type: 1, token: 'duplicate-2') + ci_runners.create!(id: 6, runner_type: 1, token: 'duplicate') + ci_runners.create!(id: 7, runner_type: 1, token: 'another-token') + ci_runners.create!(id: 8, runner_type: 1, token: 'another-token') + end + + it 'nullifies duplicate tokens', :aggregate_failures do + expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token).to_h } + .from( + { + 1 => 'duplicate', + 2 => 'a-token', + 3 => 'duplicate-2', + 4 => nil, + 5 => 'duplicate-2', + 6 => 'duplicate', + 7 => 'another-token', + 8 => 'another-token' + } + ) + .to( + { + 1 => nil, + 2 => 'a-token', + 3 => nil, + 4 => nil, + 5 => nil, + 6 => nil, + 7 => 'another-token', + 8 => 'another-token' + } + ) + expect(ci_runners.count).to eq(8) + expect(ci_runners.pluck(:token).uniq).to match_array [ + nil, 'a-token', 'another-token' + ] + end + end +end diff --git a/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb b/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb new file mode 100644 index 00000000000..98939e15952 --- /dev/null +++ b/spec/lib/gitlab/background_migration/update_ci_pipeline_artifacts_unknown_locked_status_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::UpdateCiPipelineArtifactsUnknownLockedStatus do + describe '#perform' do + let(:batch_table) { :ci_pipeline_artifacts } + let(:batch_column) { :id } + + let(:sub_batch_size) { 1 } + let(:pause_ms) { 0 } + let(:connection) { Ci::ApplicationRecord.connection } + + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:pipelines) { table(:ci_pipelines, database: :ci) } + let(:pipeline_artifacts) { table(:ci_pipeline_artifacts, database: :ci) } + + let(:namespace) { namespaces.create!(name: 'name', path: 'path') } + let(:project) do + projects + .create!(name: "project", path: "project", namespace_id: namespace.id, project_namespace_id: namespace.id) + end + + let(:unlocked) { 0 } + let(:locked) { 1 } + let(:unknown) { 2 } + + let(:unlocked_pipeline) { pipelines.create!(locked: unlocked) } + let(:locked_pipeline) { pipelines.create!(locked: locked) } + + # rubocop:disable Layout/LineLength + let!(:locked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: locked_pipeline.id, size: 1024, file_type: 0, file_format: 'gzip', file: 'a.gz', locked: unknown) } + let!(:unlocked_artifact_1) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 2048, file_type: 1, file_format: 'raw', file: 'b', locked: unknown) } + let!(:unlocked_artifact_2) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 4096, file_type: 2, file_format: 'gzip', file: 'c.gz', locked: unknown) } + let!(:already_unlocked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: unlocked_pipeline.id, size: 8192, file_type: 3, file_format: 'raw', file: 'd', locked: unlocked) } + let!(:already_locked_artifact) { pipeline_artifacts.create!(project_id: project.id, pipeline_id: locked_pipeline.id, size: 8192, file_type: 3, file_format: 'raw', file: 'd', locked: locked) } + # rubocop:enable Layout/LineLength + + subject do + described_class.new( + start_id: locked_artifact.id, + end_id: already_locked_artifact.id, + batch_table: batch_table, + batch_column: batch_column, + sub_batch_size: sub_batch_size, + pause_ms: pause_ms, + connection: connection + ).perform + end + + it 'updates ci_pipeline_artifacts with unknown lock status' do + subject + + expect(locked_artifact.reload.locked).to eq(locked) + expect(unlocked_artifact_1.reload.locked).to eq(unlocked) + expect(unlocked_artifact_2.reload.locked).to eq(unlocked) + expect(already_unlocked_artifact.reload.locked).to eq(unlocked) + expect(already_locked_artifact.reload.locked).to eq(locked) + end + end +end |