Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 16:16:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 16:16:36 +0300
commit311b0269b4eb9839fa63f80c8d7a58f32b8138a0 (patch)
tree07e7870bca8aed6d61fdcc810731c50d2c40af47 /spec/lib/gitlab/import_export
parent27909cef6c4170ed9205afa7426b8d3de47cbb0c (diff)
Add latest changes from gitlab-org/gitlab@14-5-stable-eev14.5.0-rc42
Diffstat (limited to 'spec/lib/gitlab/import_export')
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml3
-rw-r--r--spec/lib/gitlab/import_export/attributes_permitter_spec.rb83
-rw-r--r--spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb88
-rw-r--r--spec/lib/gitlab/import_export/project/object_builder_spec.rb132
-rw-r--r--spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb150
-rw-r--r--spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb48
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb50
-rw-r--r--spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb184
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
11 files changed, 510 insertions, 237 deletions
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 10f0e687077..b474f5825fd 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -60,6 +60,7 @@ issues:
- incident_management_issuable_escalation_status
- pending_escalations
- customer_relations_contacts
+- issue_customer_relations_contacts
work_item_type:
- issues
events:
@@ -132,6 +133,7 @@ project_members:
- user
- source
- project
+- member_task
merge_requests:
- status_check_responses
- subscriptions
@@ -382,6 +384,7 @@ project:
- emails_on_push_integration
- pipelines_email_integration
- mattermost_slash_commands_integration
+- shimo_integration
- slack_slash_commands_integration
- irker_integration
- packagist_integration
diff --git a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
index 2b974f8985d..8ae387d95e3 100644
--- a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
@@ -80,25 +80,66 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
let(:attributes_permitter) { described_class.new }
- where(:relation_name, :permitted_attributes_defined) do
- :user | false
- :author | false
- :ci_cd_settings | true
- :metrics_setting | true
- :project_badges | true
- :pipeline_schedules | true
- :error_tracking_setting | true
- :auto_devops | true
- :boards | true
- :custom_attributes | true
- :labels | true
- :protected_branches | true
- :protected_tags | true
- :create_access_levels | true
- :merge_access_levels | true
- :push_access_levels | true
- :releases | true
- :links | true
+ where(:relation_name, :permitted_attributes_defined ) do
+ :user | true
+ :author | false
+ :ci_cd_settings | true
+ :metrics_setting | true
+ :project_badges | true
+ :pipeline_schedules | true
+ :error_tracking_setting | true
+ :auto_devops | true
+ :boards | true
+ :custom_attributes | true
+ :label | true
+ :labels | true
+ :protected_branches | true
+ :protected_tags | true
+ :create_access_levels | true
+ :merge_access_levels | true
+ :push_access_levels | true
+ :releases | true
+ :links | true
+ :priorities | true
+ :milestone | true
+ :milestones | true
+ :snippets | true
+ :project_members | true
+ :merge_request | true
+ :merge_requests | true
+ :award_emoji | true
+ :commit_author | true
+ :committer | true
+ :events | true
+ :label_links | true
+ :merge_request_diff | true
+ :merge_request_diff_commits | true
+ :merge_request_diff_files | true
+ :metrics | true
+ :notes | true
+ :push_event_payload | true
+ :resource_label_events | true
+ :suggestions | true
+ :system_note_metadata | true
+ :timelogs | true
+ :container_expiration_policy | true
+ :project_feature | true
+ :prometheus_metrics | true
+ :service_desk_setting | true
+ :external_pull_request | true
+ :external_pull_requests | true
+ :statuses | true
+ :ci_pipelines | true
+ :stages | true
+ :actions | true
+ :design | true
+ :designs | true
+ :design_versions | true
+ :issue_assignees | true
+ :sentry_issue | true
+ :zoom_meetings | true
+ :issues | true
+ :group_members | true
end
with_them do
@@ -109,9 +150,11 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
describe 'included_attributes for Project' do
subject { described_class.new }
+ additional_attributes = { user: %w[id] }
+
Gitlab::ImportExport::Config.new.to_h[:included_attributes].each do |relation_sym, permitted_attributes|
context "for #{relation_sym}" do
- it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes
+ it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes, additional_attributes[relation_sym]
end
end
end
diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
index fc08a13a8bd..d5f31f235f5 100644
--- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
@@ -207,9 +207,9 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
context 'relation ordering' do
it 'orders exported pipelines by primary key' do
- expected_order = project.ci_pipelines.reorder(:id).ids
+ expected_order = project.ci_pipelines.reorder(:id).pluck(:sha)
- expect(subject['ci_pipelines'].pluck('id')).to eq(expected_order)
+ expect(subject['ci_pipelines'].pluck('sha')).to eq(expected_order)
end
end
diff --git a/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
new file mode 100644
index 00000000000..473dbf5ecc5
--- /dev/null
+++ b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+# This spec is a lightweight version of:
+# * project/tree_restorer_spec.rb
+#
+# In depth testing is being done in the above specs.
+# This spec tests that restore project works
+# but does not have 100% relation coverage.
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Group::RelationTreeRestorer do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:importable) { create(:group, parent: group) }
+
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { nil }
+ end
+
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json' }
+ let(:relation_reader) do
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
+ path,
+ relation_names: reader.group_relation_names)
+ end
+
+ let(:reader) do
+ Gitlab::ImportExport::Reader.new(
+ shared: shared,
+ config: Gitlab::ImportExport::Config.new(config: Gitlab::ImportExport.legacy_group_config_file).to_h
+ )
+ end
+
+ let(:relation_tree_restorer) do
+ described_class.new(
+ user: user,
+ shared: shared,
+ relation_reader: relation_reader,
+ object_builder: Gitlab::ImportExport::Group::ObjectBuilder,
+ members_mapper: members_mapper,
+ relation_factory: Gitlab::ImportExport::Group::RelationFactory,
+ reader: reader,
+ importable: importable,
+ importable_path: nil,
+ importable_attributes: attributes
+ )
+ end
+
+ subject { relation_tree_restorer.restore }
+
+ shared_examples 'logging of relations creation' do
+ context 'when log_import_export_relation_creation feature flag is enabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: group)
+ end
+
+ it 'logs top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .at_least(:once)
+
+ subject
+ end
+ end
+
+ context 'when log_import_export_relation_creation feature flag is disabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: false)
+ end
+
+ it 'does not log top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .never
+
+ subject
+ end
+ end
+ end
+
+ it 'restores group tree' do
+ expect(subject).to eq(true)
+ end
+
+ include_examples 'logging of relations creation'
+end
diff --git a/spec/lib/gitlab/import_export/project/object_builder_spec.rb b/spec/lib/gitlab/import_export/project/object_builder_spec.rb
index 4c9f9f7c690..189b798c2e8 100644
--- a/spec/lib/gitlab/import_export/project/object_builder_spec.rb
+++ b/spec/lib/gitlab/import_export/project/object_builder_spec.rb
@@ -123,6 +123,24 @@ RSpec.describe Gitlab::ImportExport::Project::ObjectBuilder do
expect(milestone.persisted?).to be true
end
+
+ context 'with clashing iid' do
+ it 'creates milestone and claims iid for the new milestone' do
+ clashing_iid = 1
+ create(:milestone, iid: clashing_iid, project: project)
+
+ milestone = described_class.build(Milestone,
+ 'iid' => clashing_iid,
+ 'title' => 'milestone',
+ 'project' => project,
+ 'group' => nil,
+ 'group_id' => nil)
+
+ expect(milestone.persisted?).to be true
+ expect(Milestone.count).to eq(2)
+ expect(milestone.iid).to eq(clashing_iid)
+ end
+ end
end
context 'merge_request' do
@@ -176,4 +194,118 @@ RSpec.describe Gitlab::ImportExport::Project::ObjectBuilder do
expect(found.email).to eq('alice@example.com')
end
end
+
+ context 'merge request diff commits' do
+ context 'when the "committer" object is present' do
+ it 'uses this object as the committer' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer' => user,
+ 'committer_name' => 'Bla',
+ 'committer_email' => 'bla@example.com',
+ 'author_name' => 'Bla',
+ 'author_email' => 'bla@example.com'
+ }
+ )
+
+ expect(commit.committer).to eq(user)
+ end
+ end
+
+ context 'when the "committer" object is missing' do
+ it 'creates one from the committer name and Email' do
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'author_name' => 'Alice',
+ 'author_email' => 'alice@example.com'
+ }
+ )
+
+ expect(commit.committer.name).to eq('Alice')
+ expect(commit.committer.email).to eq('alice@example.com')
+ end
+ end
+
+ context 'when the "commit_author" object is present' do
+ it 'uses this object as the author' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'commit_author' => user,
+ 'author_name' => 'Bla',
+ 'author_email' => 'bla@example.com'
+ }
+ )
+
+ expect(commit.commit_author).to eq(user)
+ end
+ end
+
+ context 'when the "commit_author" object is missing' do
+ it 'creates one from the author name and Email' do
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'author_name' => 'Alice',
+ 'author_email' => 'alice@example.com'
+ }
+ )
+
+ expect(commit.commit_author.name).to eq('Alice')
+ expect(commit.commit_author.email).to eq('alice@example.com')
+ end
+ end
+ end
+
+ describe '#find_or_create_diff_commit_user' do
+ context 'when the user already exists' do
+ it 'returns the existing user' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ found = described_class
+ .new(MergeRequestDiffCommit, {})
+ .send(:find_or_create_diff_commit_user, user.name, user.email)
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'creates the user' do
+ found = described_class
+ .new(MergeRequestDiffCommit, {})
+ .send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+
+ expect(found.name).to eq('Alice')
+ expect(found.email).to eq('alice@example.com')
+ end
+ end
+
+ it 'caches the results' do
+ builder = described_class.new(MergeRequestDiffCommit, {})
+
+ builder.send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+
+ record = ActiveRecord::QueryRecorder.new do
+ builder.send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+ end
+
+ expect(record.count).to eq(1)
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb
new file mode 100644
index 00000000000..5ebace263ba
--- /dev/null
+++ b/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+# This spec is a lightweight version of:
+# * project/tree_restorer_spec.rb
+#
+# In depth testing is being done in the above specs.
+# This spec tests that restore project works
+# but does not have 100% relation coverage.
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Project::RelationTreeRestorer do
+ let_it_be(:importable, reload: true) do
+ create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
+ end
+
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { 'project' }
+ end
+
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+ let(:relation_tree_restorer) do
+ described_class.new(
+ user: user,
+ shared: shared,
+ relation_reader: relation_reader,
+ object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
+ members_mapper: members_mapper,
+ relation_factory: Gitlab::ImportExport::Project::RelationFactory,
+ reader: reader,
+ importable: importable,
+ importable_path: 'project',
+ importable_attributes: attributes
+ )
+ end
+
+ subject { relation_tree_restorer.restore }
+
+ shared_examples 'import project successfully' do
+ describe 'imported project' do
+ it 'has the project attributes and relations', :aggregate_failures do
+ expect(subject).to eq(true)
+
+ project = Project.find_by_path('project')
+
+ expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
+ expect(project.labels.count).to eq(3)
+ expect(project.boards.count).to eq(1)
+ expect(project.project_feature).not_to be_nil
+ expect(project.custom_attributes.count).to eq(2)
+ expect(project.project_badges.count).to eq(2)
+ expect(project.snippets.count).to eq(1)
+ end
+ end
+ end
+
+ shared_examples 'logging of relations creation' do
+ context 'when log_import_export_relation_creation feature flag is enabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: group)
+ end
+
+ it 'logs top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .at_least(:once)
+
+ subject
+ end
+ end
+
+ context 'when log_import_export_relation_creation feature flag is disabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: false)
+ end
+
+ it 'does not log top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .never
+
+ subject
+ end
+ end
+ end
+
+ context 'with legacy reader' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
+ let(:relation_reader) do
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
+ path,
+ relation_names: reader.project_relation_names,
+ allowed_path: 'project'
+ )
+ end
+
+ let(:attributes) { relation_reader.consume_attributes('project') }
+
+ it_behaves_like 'import project successfully'
+
+ context 'with logging of relations creation' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:importable) do
+ create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project', group: group)
+ end
+
+ include_examples 'logging of relations creation'
+ end
+ end
+
+ context 'with ndjson reader' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
+
+ it_behaves_like 'import project successfully'
+
+ context 'when inside a group' do
+ let_it_be(:group) do
+ create(:group, :disabled_and_unoverridable)
+ end
+
+ before do
+ importable.update!(shared_runners_enabled: false, group: group)
+ end
+
+ it_behaves_like 'import project successfully'
+ end
+ end
+
+ context 'with invalid relations' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
+
+ it 'logs the invalid relation and its errors' do
+ expect(shared.logger)
+ .to receive(:warn)
+ .with(
+ error_messages: "Title can't be blank. Title is invalid",
+ message: '[Project/Group Import] Invalid object relation built',
+ relation_class: 'ProjectLabel',
+ relation_index: 0,
+ relation_key: 'labels'
+ ).once
+
+ relation_tree_restorer.restore
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
index f6a028383f2..3dab84af744 100644
--- a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
@@ -10,19 +10,26 @@
require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
- include_context 'relation tree restorer shared context'
+ let_it_be(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { 'project' }
+ end
+
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
let(:sample_data_relation_tree_restorer) do
described_class.new(
user: user,
shared: shared,
relation_reader: relation_reader,
- object_builder: object_builder,
+ object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
members_mapper: members_mapper,
- relation_factory: relation_factory,
+ relation_factory: Gitlab::ImportExport::Project::Sample::RelationFactory,
reader: reader,
importable: importable,
- importable_path: importable_path,
+ importable_path: 'project',
importable_attributes: attributes
)
end
@@ -69,32 +76,21 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
end
end
- context 'when restoring a project' do
- let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
- let(:importable_name) { 'project' }
- let(:importable_path) { 'project' }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::Sample::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it 'initializes relation_factory with date_calculator as parameter' do
- expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
+ it 'initializes relation_factory with date_calculator as parameter' do
+ expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
- subject
- end
+ subject
+ end
- context 'when relation tree restorer is initialized' do
- it 'initializes date calculator with due dates' do
- expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
+ context 'when relation tree restorer is initialized' do
+ it 'initializes date calculator with due dates' do
+ expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
- sample_data_relation_tree_restorer
- end
+ sample_data_relation_tree_restorer
end
+ end
- context 'using ndjson reader' do
- it_behaves_like 'import project successfully'
- end
+ context 'using ndjson reader' do
+ it_behaves_like 'import project successfully'
end
end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index f512f49764d..cd3d29f1a51 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
]
RSpec::Mocks.with_temporary_scope do
- @project = create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
+ @project = create(:project, :repository, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
@shared = @project.import_export_shared
stub_all_feature_flags
@@ -36,7 +36,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
allow_any_instance_of(Gitlab::Git::Repository).to receive(:branch_exists?).and_return(false)
expect(@shared).not_to receive(:error)
- expect_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch).with('feature', 'DCBA')
allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch)
project_tree_restorer = described_class.new(user: @user, shared: @shared, project: @project)
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index 374d688576e..f68ec21039d 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -5,6 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
let_it_be(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let_it_be(:exportable_path) { 'project' }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { setup_project }
shared_examples 'saves project tree successfully' do |ndjson_enabled|
include ImportExport::CommonUtil
@@ -12,9 +15,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
subject { get_json(full_path, exportable_path, relation_name, ndjson_enabled) }
describe 'saves project tree attributes' do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { setup_project }
let_it_be(:shared) { project.import_export_shared }
let(:relation_name) { :projects }
@@ -402,6 +402,50 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
it_behaves_like "saves project tree successfully", true
end
+ context 'when streaming has to retry', :aggregate_failures do
+ let(:shared) { double('shared', export_path: exportable_path) }
+ let(:logger) { Gitlab::Import::Logger.build }
+ let(:serializer) { double('serializer') }
+ let(:error_class) { Net::OpenTimeout }
+ let(:info_params) do
+ {
+ 'error.class': error_class,
+ project_name: project.name,
+ project_id: project.id
+ }
+ end
+
+ before do
+ allow(Gitlab::ImportExport::Json::StreamingSerializer).to receive(:new).and_return(serializer)
+ end
+
+ subject(:project_tree_saver) do
+ described_class.new(project: project, current_user: user, shared: shared, logger: logger)
+ end
+
+ it 'retries and succeeds' do
+ call_count = 0
+ allow(serializer).to receive(:execute) do
+ call_count += 1
+ call_count > 1 ? true : raise(error_class, 'execution expired')
+ end
+
+ expect(logger).to receive(:info).with(hash_including(info_params)).once
+
+ expect(project_tree_saver.save).to be(true)
+ end
+
+ it 'retries and does not succeed' do
+ retry_count = 3
+ allow(serializer).to receive(:execute).and_raise(error_class, 'execution expired')
+
+ expect(logger).to receive(:info).with(hash_including(info_params)).exactly(retry_count).times
+ expect(shared).to receive(:error).with(instance_of(error_class))
+
+ expect(project_tree_saver.save).to be(false)
+ end
+ end
+
def setup_project
release = create(:release)
diff --git a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
deleted file mode 100644
index 5e4075c2b59..00000000000
--- a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-# frozen_string_literal: true
-
-# This spec is a lightweight version of:
-# * project/tree_restorer_spec.rb
-#
-# In depth testing is being done in the above specs.
-# This spec tests that restore project works
-# but does not have 100% relation coverage.
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
- include_context 'relation tree restorer shared context'
-
- let(:relation_tree_restorer) do
- described_class.new(
- user: user,
- shared: shared,
- relation_reader: relation_reader,
- object_builder: object_builder,
- members_mapper: members_mapper,
- relation_factory: relation_factory,
- reader: reader,
- importable: importable,
- importable_path: importable_path,
- importable_attributes: attributes
- )
- end
-
- subject { relation_tree_restorer.restore }
-
- shared_examples 'import project successfully' do
- describe 'imported project' do
- it 'has the project attributes and relations', :aggregate_failures do
- expect(subject).to eq(true)
-
- project = Project.find_by_path('project')
-
- expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
- expect(project.labels.count).to eq(3)
- expect(project.boards.count).to eq(1)
- expect(project.project_feature).not_to be_nil
- expect(project.custom_attributes.count).to eq(2)
- expect(project.project_badges.count).to eq(2)
- expect(project.snippets.count).to eq(1)
- end
- end
- end
-
- shared_examples 'logging of relations creation' do
- context 'when log_import_export_relation_creation feature flag is enabled' do
- before do
- stub_feature_flags(log_import_export_relation_creation: group)
- end
-
- it 'logs top-level relation creation' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:info)
- .with(hash_including(message: '[Project/Group Import] Created new object relation'))
- .at_least(:once)
-
- subject
- end
- end
-
- context 'when log_import_export_relation_creation feature flag is disabled' do
- before do
- stub_feature_flags(log_import_export_relation_creation: false)
- end
-
- it 'does not log top-level relation creation' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:info)
- .with(hash_including(message: '[Project/Group Import] Created new object relation'))
- .never
-
- subject
- end
- end
- end
-
- context 'when restoring a project' do
- let_it_be(:importable, reload: true) do
- create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
- end
-
- let(:importable_name) { 'project' }
- let(:importable_path) { 'project' }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
-
- context 'using legacy reader' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
- let(:relation_reader) do
- Gitlab::ImportExport::Json::LegacyReader::File.new(
- path,
- relation_names: reader.project_relation_names,
- allowed_path: 'project'
- )
- end
-
- let(:attributes) { relation_reader.consume_attributes('project') }
-
- it_behaves_like 'import project successfully'
-
- context 'logging of relations creation' do
- let_it_be(:group) { create(:group) }
- let_it_be(:importable) do
- create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project', group: group)
- end
-
- include_examples 'logging of relations creation'
- end
- end
-
- context 'using ndjson reader' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it_behaves_like 'import project successfully'
-
- context 'when inside a group' do
- let_it_be(:group) do
- create(:group, :disabled_and_unoverridable)
- end
-
- before do
- importable.update!(shared_runners_enabled: false, group: group)
- end
-
- it_behaves_like 'import project successfully'
- end
- end
-
- context 'with invalid relations' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it 'logs the invalid relation and its errors' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:warn)
- .with(
- error_messages: "Title can't be blank. Title is invalid",
- message: '[Project/Group Import] Invalid object relation built',
- relation_class: 'ProjectLabel',
- relation_index: 0,
- relation_key: 'labels'
- ).once
-
- relation_tree_restorer.restore
- end
- end
- end
-
- context 'when restoring a group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:importable) { create(:group, parent: group) }
-
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json' }
- let(:importable_name) { nil }
- let(:importable_path) { nil }
- let(:object_builder) { Gitlab::ImportExport::Group::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Group::RelationFactory }
- let(:relation_reader) do
- Gitlab::ImportExport::Json::LegacyReader::File.new(
- path,
- relation_names: reader.group_relation_names)
- end
-
- let(:reader) do
- Gitlab::ImportExport::Reader.new(
- shared: shared,
- config: Gitlab::ImportExport::Config.new(config: Gitlab::ImportExport.legacy_group_config_file).to_h
- )
- end
-
- it 'restores group tree' do
- expect(subject).to eq(true)
- end
-
- include_examples 'logging of relations creation'
- end
-end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 4b125cab49b..9daa3b32fd1 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -561,6 +561,7 @@ Project:
- require_password_to_approve
- autoclose_referenced_issues
- suggestion_commit_message
+- merge_commit_template
ProjectTracingSetting:
- external_url
Author:
@@ -692,6 +693,7 @@ ProjectCiCdSetting:
ProjectSetting:
- allow_merge_on_skipped_pipeline
- has_confluence
+- has_shimo
- has_vulnerabilities
ProtectedEnvironment:
- id