diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-25 09:11:50 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-25 09:11:50 +0300 |
commit | 03085fd4a4047d7e7a11e29e244b7bfccfe52f53 (patch) | |
tree | fcf019addfc755be22690d644ba21a8d88144161 | |
parent | 48a0a54a619b86f9b8664c76a9776068507b7d0e (diff) |
Add latest changes from gitlab-org/gitlab@master
24 files changed, 307 insertions, 55 deletions
diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue index 716321430d2..361d736f740 100644 --- a/app/assets/javascripts/blob/components/blob_header.vue +++ b/app/assets/javascripts/blob/components/blob_header.vue @@ -1,5 +1,5 @@ <script> -import DefaultActions from './blob_header_default_actions.vue'; +import DefaultActions from 'jh_else_ce/blob/components/blob_header_default_actions.vue'; import BlobFilepath from './blob_header_filepath.vue'; import ViewerSwitcher from './blob_header_viewer_switcher.vue'; import { SIMPLE_BLOB_VIEWER } from './constants'; diff --git a/db/post_migrate/20221115173607_ensure_work_item_type_backfill_migration_finished.rb b/db/post_migrate/20221115173607_ensure_work_item_type_backfill_migration_finished.rb new file mode 100644 index 00000000000..2cec1919e82 --- /dev/null +++ b/db/post_migrate/20221115173607_ensure_work_item_type_backfill_migration_finished.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class EnsureWorkItemTypeBackfillMigrationFinished < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + MIGRATION = 'BackfillWorkItemTypeIdForIssues' + + class MigrationWorkItemType < MigrationRecord + self.table_name = 'work_item_types' + + def self.id_by_type(types) + where(namespace_id: nil, base_type: types).pluck(:base_type, :id).to_h + end + end + + def up + # more types were added to the types table after the backfill run + # so we cannot fetch all from the DB but only those that were backfilled + relevant_types = { + issue: 0, + incident: 1, + test_case: 2, + requirement: 3, + task: 4 + } + + MigrationWorkItemType.id_by_type(relevant_types.values).each do |base_type, type_id| + ensure_batched_background_migration_is_finished( + job_class_name: MIGRATION, + table_name: :issues, + column_name: :id, + job_arguments: [base_type, type_id] + ) + end + end + + def down + # noop + end +end diff --git a/db/post_migrate/20221121184931_validate_not_null_contraint_on_issues_work_item_type_id.rb b/db/post_migrate/20221121184931_validate_not_null_contraint_on_issues_work_item_type_id.rb new file mode 100644 index 00000000000..be09f2ebe3a --- /dev/null +++ b/db/post_migrate/20221121184931_validate_not_null_contraint_on_issues_work_item_type_id.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ValidateNotNullContraintOnIssuesWorkItemTypeId < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + def up + add_not_null_constraint :issues, :work_item_type_id, validate: true + end + + def down + remove_not_null_constraint :issues, :work_item_type_id + end +end diff --git a/db/schema_migrations/20221115173607 b/db/schema_migrations/20221115173607 new file mode 100644 index 00000000000..1de7aaf5da6 --- /dev/null +++ b/db/schema_migrations/20221115173607 @@ -0,0 +1 @@ +c3e763e7c801b308cf44cd494104e8c3b37e61fa00b30d777ef97ca310f4823b
\ No newline at end of file diff --git a/db/schema_migrations/20221121184931 b/db/schema_migrations/20221121184931 new file mode 100644 index 00000000000..3d90e696941 --- /dev/null +++ b/db/schema_migrations/20221121184931 @@ -0,0 +1 @@ +1700ebce94f46e086d2f5f4ec3d00d5bf2f212009c8115f1a7851471912c829a
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index de560c954ec..e1d39106233 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16958,6 +16958,7 @@ CREATE TABLE issues ( work_item_type_id bigint, namespace_id bigint, start_date date, + CONSTRAINT check_2addf801cd CHECK ((work_item_type_id IS NOT NULL)), CONSTRAINT check_fba63f706d CHECK ((lock_version IS NOT NULL)) ); diff --git a/doc/update/index.md b/doc/update/index.md index 176cec159c3..29b6a1fc9c2 100644 --- a/doc/update/index.md +++ b/doc/update/index.md @@ -471,6 +471,13 @@ NOTE: Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/) and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches. +### 15.7.0 + +- This version validates a `NOT NULL DB` constraint on the `issues.work_item_type_id` column. + To upgrade to this version, no records with a `NULL` `work_item_type_id` should exist on the `issues` table. + There are multiple `BackfillWorkItemTypeIdForIssues` background migrations that will be finalized with + the `EnsureWorkItemTypeBackfillMigrationFinished` post-deploy migration. + ### 15.6.0 - You should use one of the [officially supported PostgreSQL versions](../administration/package_information/postgresql_versions.md). Some database migrations can cause stability and performance issues with older PostgreSQL versions. diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index e1add9ad434..329bf5f7143 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -390,6 +390,7 @@ module QA def click_open_in_web_ide click_element(:mr_code_dropdown) click_element(:open_in_web_ide_button) + page.driver.browser.switch_to.window(page.driver.browser.window_handles.last) wait_for_requests end diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb index e87bc5422d7..1f0c37df101 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb @@ -41,7 +41,7 @@ module QA 'successfully imports groups and labels', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347674' ) do - expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration) + expect_group_import_finished_successfully aggregate_failures do expect(imported_group.reload!).to eq(source_group) @@ -78,7 +78,7 @@ module QA 'successfully imports group milestones and badges', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347628' ) do - expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration) + expect_group_import_finished_successfully imported_milestone = imported_group.reload!.milestones.find { |ml| ml.title == source_milestone.title } aggregate_failures do diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb index 027628c35f5..dd2e7f06995 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb @@ -45,7 +45,7 @@ module QA 'successfully imports issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347608' ) do - expect_import_finished + expect_project_import_finished_successfully expect(imported_issues.count).to eq(1) expect(imported_issue).to eq(source_issue.reload!) expect(imported_issue_comments).to match_array(source_issue_comments) @@ -77,7 +77,7 @@ module QA 'successfully imports design', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366449' ) do - expect_import_finished + expect_project_import_finished_successfully expect(imported_issues.count).to eq(1) expect(imported_design.full_path).to eq(source_design.full_path) diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb index 51dd2098a22..7fe11c3bafe 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb @@ -35,7 +35,7 @@ module QA 'member retains indirect membership in imported project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354416' ) do - expect_import_finished + expect_project_import_finished_successfully aggregate_failures do expect(imported_project_member).to be_nil @@ -55,7 +55,7 @@ module QA 'member retains direct membership in imported project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354417' ) do - expect_import_finished + expect_project_import_finished_successfully aggregate_failures do expect(imported_group_member).to be_nil diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb index 94ed58cfd72..127db36052f 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb @@ -72,7 +72,7 @@ module QA 'successfully imports merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348478' ) do - expect_import_finished + expect_project_import_finished_successfully expect(imported_mrs.count).to eq(1) aggregate_failures do diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb index d8637a54a12..8d631808d17 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb @@ -47,7 +47,7 @@ module QA 'successfully imports ci pipeline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354650' ) do - expect_import_finished + expect_project_import_finished_successfully expect(imported_pipelines).to eq(source_pipelines) end diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb index 2b7818d1ed2..83691cdf143 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb @@ -5,14 +5,54 @@ module QA describe 'Gitlab migration', product_group: :import do include_context 'with gitlab project migration' + # this spec is used as a sanity test for gitlab migration because it can run outside of orchestrated setup + context 'with import within same instance', orchestrated: false, import: false, quarantine: { + type: :test_environment, + issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/383605", + only: { job: "review-qa" } + } do + let!(:source_project_with_readme) { true } + let!(:source_gitlab_address) { Runtime::Scenario.gitlab_address } + let!(:source_admin_api_client) { admin_api_client } + + let!(:source_sandbox) do + Resource::Sandbox.fabricate_via_api! do |group| + group.api_client = admin_api_client + end + end + + let!(:target_sandbox) { source_sandbox } + + let!(:source_group) do + Resource::Group.fabricate_via_api! do |group| + group.api_client = admin_api_client + group.sandbox = source_sandbox + group.path = "source-group-for-import-#{SecureRandom.hex(4)}" + group.avatar = File.new('qa/fixtures/designs/tanuki.jpg', 'r') + end + end + + let(:destination_group_path) { "target-group-for-import-#{SecureRandom.hex(4)}" } + let(:cleanup!) { user.remove_via_api! } + + it( + 'successfully imports project', + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/383351' + ) do + expect_project_import_finished_successfully + + expect(imported_project).to eq(source_project) + end + end + context 'with uninitialized project' do it( 'successfully imports project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347610' ) do - expect_import_finished + expect_project_import_finished_successfully - expect(imported_projects.first).to eq(source_project) + expect(imported_project).to eq(source_project) end end @@ -59,7 +99,7 @@ module QA 'successfully imports repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347570' ) do - expect_import_finished + expect_project_import_finished_successfully aggregate_failures do expect(imported_commits).to match_array(source_commits) @@ -78,9 +118,9 @@ module QA 'successfully imports project wiki', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347567' ) do - expect_import_finished + expect_project_import_finished_successfully - expect(imported_projects.first.wikis).to eq(source_project.wikis) + expect(imported_project.wikis).to eq(source_project.wikis) end end end diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb index 2f42b7a15e4..b3510cef3e9 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb @@ -60,7 +60,7 @@ module QA 'successfully imports project release', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/360243' ) do - expect_import_finished + expect_project_import_finished_successfully expect(imported_releases.size).to eq(1), "Expected to have 1 migrated release" expect(imported_release).to eq(source_release) diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb index e4f29952f99..69557fb359a 100644 --- a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', product_group: :editor, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/381530', type: :stale } do + RSpec.describe 'Create', product_group: :editor do describe 'Review a merge request in Web IDE' do let(:new_file) { 'awesome_new_file.txt' } let(:original_text) { 'Text' } diff --git a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb index 8a8587c39a8..f9df6e805c0 100644 --- a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb +++ b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb @@ -7,7 +7,7 @@ module QA :orchestrated, requires_admin: 'creates a user via API' ) do - let!(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } } + let!(:import_wait_duration) { { max_duration: 120, sleep_interval: 2 } } # source instance objects # @@ -57,12 +57,14 @@ module QA end end + let(:destination_group_path) { source_group.path } let(:imported_group) do Resource::BulkImportGroup.fabricate_via_api! do |group| group.api_client = api_client group.sandbox = target_sandbox group.source_group = source_group group.source_gitlab_address = source_gitlab_address + group.destination_group_path = destination_group_path group.import_access_token = source_admin_api_client.personal_access_token end end @@ -71,6 +73,21 @@ module QA imported_group.import_details.sum([]) { |details| details[:failures] } end + let(:cleanup!) {} + + def expect_group_import_finished_successfully + imported_group # trigger import + + status = nil + Support::Retrier.retry_until(**import_wait_duration, message: "Import did not complete") do + status = imported_group.import_status + %w[finished failed].include?(status) + end + + # finished status means success, all other statuses are considered to fail the test + expect(status).to eq('finished') + end + before do target_sandbox.add_member(user, Resource::Members::AccessLevel::OWNER) end @@ -78,9 +95,12 @@ module QA after do |example| # Checking for failures in the test currently makes test very flaky due to catching unrelated failures # Log failures for easier debugging - Runtime::Logger.warn("Import failures: #{import_failures}") if example.exception && !import_failures.empty? - rescue QA::Resource::Base::NoValueError - # rescue when import did not happen at all + Runtime::Logger.error("Import failures: #{import_failures}") if example.exception && !import_failures.empty? + rescue StandardError + # rescue when import did not happen at all and checking import failues will raise an error + ensure + # make sure cleanup runs last + cleanup! end end end diff --git a/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb b/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb index e1189a0ea66..728907c708f 100644 --- a/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb +++ b/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb @@ -19,14 +19,8 @@ module QA let(:imported_projects) { imported_group.reload!.projects } let(:imported_project) { imported_projects.first } - let(:import_failures) do - imported_group.import_details.sum([]) { |details| details[:failures] } - end - - def expect_import_finished - imported_group # trigger import - - expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration) + def expect_project_import_finished_successfully + expect_group_import_finished_successfully expect(imported_projects.count).to eq(1), "Expected to have 1 imported project. Found: #{imported_projects.count}" end diff --git a/spec/initializers/rails_yaml_safe_load_spec.rb b/spec/initializers/rails_yaml_safe_load_spec.rb index 8cf6a3676e0..ef1c5149bc6 100644 --- a/spec/initializers/rails_yaml_safe_load_spec.rb +++ b/spec/initializers/rails_yaml_safe_load_spec.rb @@ -13,7 +13,8 @@ RSpec.describe 'Rails YAML safe load' do end end - let(:instance) { klass.new(description: data) } + let(:issue_type) { WorkItems::Type.default_by_type(:issue) } + let(:instance) { klass.new(description: data, work_item_type_id: issue_type.id) } context 'with default permitted classes' do let(:data) do diff --git a/spec/lib/gitlab/background_migration/backfill_project_namespace_on_issues_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_namespace_on_issues_spec.rb index 3ca7d28f09d..1b7905cf7eb 100644 --- a/spec/lib/gitlab/background_migration/backfill_project_namespace_on_issues_spec.rb +++ b/spec/lib/gitlab/background_migration/backfill_project_namespace_on_issues_spec.rb @@ -7,6 +7,8 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillProjectNamespaceOnIssues do let(:namespaces) { table(:namespaces) } let(:projects) { table(:projects) } let(:issues) { table(:issues) } + let(:issue_base_type_enum_value) { 0 } + let(:issue_type) { table(:work_item_types).find_by!(namespace_id: nil, base_type: issue_base_type_enum_value) } let(:namespace1) { namespaces.create!(name: 'batchtest1', type: 'Group', path: 'space1') } let(:namespace2) { namespaces.create!(name: 'batchtest2', type: 'Group', parent_id: namespace1.id, path: 'space2') } @@ -18,12 +20,12 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillProjectNamespaceOnIssues do 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!(:proj1_issue_with_namespace) { issues.create!(title: 'issue1', project_id: proj1.id, namespace_id: proj_namespace1.id) } - let!(:proj1_issue_without_namespace1) { issues.create!(title: 'issue2', project_id: proj1.id) } - let!(:proj1_issue_without_namespace2) { issues.create!(title: 'issue3', project_id: proj1.id) } - let!(:proj2_issue_with_namespace) { issues.create!(title: 'issue4', project_id: proj2.id, namespace_id: proj_namespace2.id) } - let!(:proj2_issue_without_namespace1) { issues.create!(title: 'issue5', project_id: proj2.id) } - let!(:proj2_issue_without_namespace2) { issues.create!(title: 'issue6', project_id: proj2.id) } + let!(:proj1_issue_with_namespace) { issues.create!(title: 'issue1', project_id: proj1.id, namespace_id: proj_namespace1.id, work_item_type_id: issue_type.id) } + let!(:proj1_issue_without_namespace1) { issues.create!(title: 'issue2', project_id: proj1.id, work_item_type_id: issue_type.id) } + let!(:proj1_issue_without_namespace2) { issues.create!(title: 'issue3', project_id: proj1.id, work_item_type_id: issue_type.id) } + let!(:proj2_issue_with_namespace) { issues.create!(title: 'issue4', project_id: proj2.id, namespace_id: proj_namespace2.id, work_item_type_id: issue_type.id) } + let!(:proj2_issue_without_namespace1) { issues.create!(title: 'issue5', project_id: proj2.id, work_item_type_id: issue_type.id) } + let!(:proj2_issue_without_namespace2) { issues.create!(title: 'issue6', project_id: proj2.id, work_item_type_id: issue_type.id) } # rubocop:enable Layout/LineLength let(:migration) do diff --git a/spec/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy_spec.rb index 1a00fd7c8b3..909ad16879b 100644 --- a/spec/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy_spec.rb +++ b/spec/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy_spec.rb @@ -7,6 +7,8 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::LooseIndexScanBa let(:namespaces) { table(:namespaces) } let(:projects) { table(:projects) } let(:issues) { table(:issues) } + let(:issue_base_type_enum_value) { 0 } + let(:issue_type) { table(:work_item_types).find_by!(namespace_id: nil, base_type: issue_base_type_enum_value) } let!(:namespace1) { namespaces.create!(name: 'ns1', path: 'ns1') } let!(:namespace2) { namespaces.create!(name: 'ns2', path: 'ns2') } @@ -19,13 +21,47 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::LooseIndexScanBa let!(:project4) { projects.create!(name: 'p4', namespace_id: namespace4.id, project_namespace_id: namespace4.id) } let!(:project5) { projects.create!(name: 'p5', namespace_id: namespace5.id, project_namespace_id: namespace5.id) } - let!(:issue1) { issues.create!(title: 'title', description: 'description', project_id: project2.id) } - let!(:issue2) { issues.create!(title: 'title', description: 'description', project_id: project1.id) } - let!(:issue3) { issues.create!(title: 'title', description: 'description', project_id: project2.id) } - let!(:issue4) { issues.create!(title: 'title', description: 'description', project_id: project3.id) } - let!(:issue5) { issues.create!(title: 'title', description: 'description', project_id: project2.id) } - let!(:issue6) { issues.create!(title: 'title', description: 'description', project_id: project4.id) } - let!(:issue7) { issues.create!(title: 'title', description: 'description', project_id: project5.id) } + let!(:issue1) do + issues.create!( + title: 'title', description: 'description', project_id: project2.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue2) do + issues.create!( + title: 'title', description: 'description', project_id: project1.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue3) do + issues.create!( + title: 'title', description: 'description', project_id: project2.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue4) do + issues.create!( + title: 'title', description: 'description', project_id: project3.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue5) do + issues.create!( + title: 'title', description: 'description', project_id: project2.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue6) do + issues.create!( + title: 'title', description: 'description', project_id: project4.id, work_item_type_id: issue_type.id + ) + end + + let!(:issue7) do + issues.create!( + title: 'title', description: 'description', project_id: project5.id, work_item_type_id: issue_type.id + ) + end it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchingStrategies::BaseStrategy } diff --git a/spec/lib/gitlab/background_migration/rename_task_system_note_to_checklist_item_spec.rb b/spec/lib/gitlab/background_migration/rename_task_system_note_to_checklist_item_spec.rb index 45932defaf9..0df7decd8e6 100644 --- a/spec/lib/gitlab/background_migration/rename_task_system_note_to_checklist_item_spec.rb +++ b/spec/lib/gitlab/background_migration/rename_task_system_note_to_checklist_item_spec.rb @@ -8,7 +8,9 @@ RSpec.describe Gitlab::BackgroundMigration::RenameTaskSystemNoteToChecklistItem let(:namespace) { table(:namespaces).create!(name: 'batchtest1', type: 'Group', path: 'space1') } let(:project) { table(:projects).create!(name: 'proj1', path: 'proj1', namespace_id: namespace.id) } - let(:issue) { table(:issues).create!(title: 'Test issue') } + let(:issue_base_type_enum_value) { 0 } + let(:issue_type) { table(:work_item_types).find_by!(namespace_id: nil, base_type: issue_base_type_enum_value) } + let(:issue) { table(:issues).create!(title: 'Test issue', work_item_type_id: issue_type.id) } let!(:note1) do notes.create!( diff --git a/spec/migrations/20221115173607_ensure_work_item_type_backfill_migration_finished_spec.rb b/spec/migrations/20221115173607_ensure_work_item_type_backfill_migration_finished_spec.rb new file mode 100644 index 00000000000..70cac5ce2f3 --- /dev/null +++ b/spec/migrations/20221115173607_ensure_work_item_type_backfill_migration_finished_spec.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe EnsureWorkItemTypeBackfillMigrationFinished, :migration do + let(:batched_migrations) { table(:batched_background_migrations) } + let(:work_item_types) { table(:work_item_types) } + let(:batch_failed_status) { 2 } + let(:batch_finalized_status) { 3 } + + let_it_be(:migration_class) { described_class::MIGRATION } + + describe '#up', :redis do + context 'when 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:/) + .exactly(5).times + + migrate! + end + end + + context 'with migration present' do + let(:relevant_types) do + { + issue: 0, + incident: 1, + test_case: 2, + requirement: 3, + task: 4 + } + end + + let!(:backfill_migrations) do + relevant_types.map do |_base_type, enum_value| + type_id = work_item_types.find_by!(namespace_id: nil, base_type: enum_value).id + + create_migration_with(status, enum_value, type_id) + end + end + + context 'when migrations have finished' do + let(:status) { 3 } # finished enum value + + it 'does not raise an error' do + expect { migrate! }.not_to raise_error + end + end + + context 'with different migration statuses' do + using RSpec::Parameterized::TableSyntax + + where(:status, :description) do + 0 | 'paused' + 1 | 'active' + 4 | 'failed' + 5 | 'finalizing' + end + + with_them do + it 'finalizes the migration' do + expect do + migrate! + + backfill_migrations.each(&:reload) + end.to change { backfill_migrations.map(&:status).uniq }.from([status]).to([3]) + end + end + end + end + end + + def create_migration_with(status, base_type, type_id) + migration = batched_migrations.create!( + job_class_name: migration_class, + table_name: :issues, + column_name: :id, + job_arguments: [base_type, type_id], + interval: 2.minutes, + min_value: 1, + max_value: 2, + batch_size: 1000, + sub_batch_size: 200, + gitlab_schema: :gitlab_main, + status: status + ) + + table(:batched_background_migration_jobs).create!( + batched_background_migration_id: migration.id, + status: batch_failed_status, + min_value: 1, + max_value: 10, + attempts: 2, + batch_size: 100, + sub_batch_size: 10 + ) + + migration + end +end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index a4c52714458..82ee062aef0 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -257,7 +257,7 @@ RSpec.describe Issue do end context 'when no type was set' do - let_it_be(:issue, refind: true) { build(:issue, project: project, work_item_type: nil).tap { |issue| issue.save!(validate: false) } } + let(:issue) { build(:issue, project: project, work_item_type: nil) } it 'sets a work item type before validation' do expect(issue.work_item_type_id).to be_nil @@ -449,17 +449,6 @@ RSpec.describe Issue do end end - # TODO: Remove when NOT NULL constraint is added to the relationship - describe '#work_item_type' do - let(:issue) { build(:issue, :incident, project: reusable_project, work_item_type: nil).tap { |issue| issue.save!(validate: false) } } - - it 'returns a default type if the legacy issue does not have a work item type associated yet' do - expect(issue.work_item_type_id).to be_nil - expect(issue.issue_type).to eq('incident') - expect(issue.work_item_type).to eq(WorkItems::Type.default_by_type(:incident)) - end - end - describe '#sort' do let(:project) { reusable_project } |