diff options
Diffstat (limited to 'spec/lib/gitlab/import_export')
11 files changed, 330 insertions, 45 deletions
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 7baa52ffb4f..3c6b17c10ec 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -242,6 +242,7 @@ project: - cluster_project - cluster_ingresses - creator +- cycle_analytics_stages - group - namespace - boards @@ -277,7 +278,6 @@ project: - bugzilla_service - gitlab_issue_tracker_service - external_wiki_service -- kubernetes_service - mock_ci_service - mock_deployment_service - mock_monitoring_service @@ -343,7 +343,6 @@ project: - fork_network_member - fork_network - custom_attributes -- prometheus_metrics - lfs_file_locks - project_badges - source_of_merge_requests @@ -470,3 +469,17 @@ incident_management_setting: merge_trains: - project - merge_request +boards: +- group +- lists +- destroyable_lists +- milestone +- board_labels +- board_assignee +- assignee +- labels +lists: +- user +- milestone +- board +- label diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb index 99669285d5b..873728f9909 100644 --- a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb @@ -22,7 +22,9 @@ describe Gitlab::ImportExport::AttributeCleaner do 'some_html' => '<p>dodgy html</p>', 'legit_html' => '<p>legit html</p>', '_html' => '<p>perfectly ordinary html</p>', - 'cached_markdown_version' => 12345 + 'cached_markdown_version' => 12345, + 'group_id' => 99, + 'commit_id' => 99 } end @@ -31,7 +33,9 @@ describe Gitlab::ImportExport::AttributeCleaner do 'project_id' => 99, 'user_id' => 99, 'random_id_in_the_middle' => 99, - 'notid' => 99 + 'notid' => 99, + 'group_id' => 99, + 'commit_id' => 99 } end @@ -59,6 +63,6 @@ describe Gitlab::ImportExport::AttributeCleaner do it 'does not remove excluded key if not listed' do parsed_hash = described_class.clean(relation_hash: unsafe_hash, relation_class: relation_class) - expect(parsed_hash.keys).to eq post_safe_hash.keys + excluded_keys + expect(parsed_hash.keys).to match_array post_safe_hash.keys + excluded_keys end end diff --git a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb index 70eeb9ee66b..2b0bdb909ae 100644 --- a/spec/lib/gitlab/import_export/lfs_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/lfs_restorer_spec.rb @@ -6,6 +6,7 @@ describe Gitlab::ImportExport::LfsRestorer do let(:export_path) { "#{Dir.tmpdir}/lfs_object_restorer_spec" } let(:project) { create(:project) } let(:shared) { project.import_export_shared } + let(:saver) { Gitlab::ImportExport::LfsSaver.new(project: project, shared: shared) } subject(:restorer) { described_class.new(project: project, shared: shared) } before do @@ -19,49 +20,98 @@ describe Gitlab::ImportExport::LfsRestorer do describe '#restore' do context 'when the archive contains lfs files' do - let(:dummy_lfs_file_path) { File.join(shared.export_path, 'lfs-objects', 'dummy') } - - def create_lfs_object_with_content(content) - dummy_lfs_file = Tempfile.new('existing') - File.write(dummy_lfs_file.path, content) - size = dummy_lfs_file.size - oid = LfsObject.calculate_oid(dummy_lfs_file.path) - LfsObject.create!(oid: oid, size: size, file: dummy_lfs_file) + let(:lfs_object) { create(:lfs_object, :correct_oid, :with_file) } + + # Use the LfsSaver to save data to be restored + def save_lfs_data + %w(project wiki).each do |repository_type| + create( + :lfs_objects_project, + project: project, + repository_type: repository_type, + lfs_object: lfs_object + ) + end + + saver.save + + project.lfs_objects.delete_all end before do - FileUtils.mkdir_p(File.dirname(dummy_lfs_file_path)) - File.write(dummy_lfs_file_path, 'not very large') - allow(restorer).to receive(:lfs_file_paths).and_return([dummy_lfs_file_path]) + save_lfs_data + project.reload end - it 'creates an lfs object for the project' do - expect { restorer.restore }.to change { project.reload.lfs_objects.size }.by(1) + it 'succeeds' do + expect(restorer.restore).to eq(true) + expect(shared.errors).to be_empty end - it 'assigns the file correctly' do + it 'does not create a new `LfsObject` records, as one already exists' do + expect { restorer.restore }.not_to change { LfsObject.count } + end + + it 'creates new `LfsObjectsProject` records in order to link the project to the existing `LfsObject`' do + expect { restorer.restore }.to change { LfsObjectsProject.count }.by(2) + end + + it 'restores the correct `LfsObject` records' do restorer.restore - expect(project.lfs_objects.first.file.read).to eq('not very large') + expect(project.lfs_objects).to contain_exactly(lfs_object) end - it 'links an existing LFS object if it existed' do - lfs_object = create_lfs_object_with_content('not very large') + it 'restores the correct `LfsObjectsProject` records for the project' do + restorer.restore + expect( + project.lfs_objects_projects.pluck(:repository_type) + ).to contain_exactly('project', 'wiki') + end + + it 'assigns the file correctly' do restorer.restore - expect(project.lfs_objects).to include(lfs_object) + expect(project.lfs_objects.first.file.read).to eq(lfs_object.file.read) end - it 'succeeds' do - expect(restorer.restore).to be_truthy - expect(shared.errors).to be_empty + context 'when there is not an existing `LfsObject`' do + before do + lfs_object.destroy + end + + it 'creates a new lfs object' do + expect { restorer.restore }.to change { LfsObject.count }.by(1) + end + + it 'stores the upload' do + expect_any_instance_of(LfsObjectUploader).to receive(:store!) + + restorer.restore + end end - it 'stores the upload' do - expect_any_instance_of(LfsObjectUploader).to receive(:store!) + context 'when there is no lfs-objects.json file' do + before do + json_file = File.join(shared.export_path, ::Gitlab::ImportExport.lfs_objects_filename) - restorer.restore + FileUtils.rm_rf(json_file) + end + + it 'restores the correct `LfsObject` records' do + restorer.restore + + expect(project.lfs_objects).to contain_exactly(lfs_object) + end + + it 'restores a single `LfsObjectsProject` record for the project with "project" for the `repository_type`' do + restorer.restore + + expect( + project.lfs_objects_projects.pluck(:repository_type) + ).to contain_exactly('project') + end end end diff --git a/spec/lib/gitlab/import_export/lfs_saver_spec.rb b/spec/lib/gitlab/import_export/lfs_saver_spec.rb index 9b0e21deb2e..c3c88486e16 100644 --- a/spec/lib/gitlab/import_export/lfs_saver_spec.rb +++ b/spec/lib/gitlab/import_export/lfs_saver_spec.rb @@ -19,6 +19,11 @@ describe Gitlab::ImportExport::LfsSaver do describe '#save' do context 'when the project has LFS objects locally stored' do let(:lfs_object) { create(:lfs_object, :with_file) } + let(:lfs_json_file) { File.join(shared.export_path, Gitlab::ImportExport.lfs_objects_filename) } + + def lfs_json + JSON.parse(IO.read(lfs_json_file)) + end before do project.lfs_objects << lfs_object @@ -35,6 +40,45 @@ describe Gitlab::ImportExport::LfsSaver do expect(File).to exist("#{shared.export_path}/lfs-objects/#{lfs_object.oid}") end + + describe 'saving a json file' do + before do + # Create two more LfsObjectProject records with different `repository_type`s + %w(wiki design).each do |repository_type| + create( + :lfs_objects_project, + project: project, + repository_type: repository_type, + lfs_object: lfs_object + ) + end + + FileUtils.rm_rf(lfs_json_file) + end + + it 'saves a json file correctly' do + saver.save + + expect(File.exist?(lfs_json_file)).to eq(true) + expect(lfs_json).to eq( + { + lfs_object.oid => [ + LfsObjectsProject.repository_types['wiki'], + LfsObjectsProject.repository_types['design'], + nil + ] + } + ) + end + + it 'does not save a json file if feature is disabled' do + stub_feature_flags(export_lfs_objects_projects: false) + + saver.save + + expect(File.exist?(lfs_json_file)).to eq(false) + end + end end context 'when the LFS objects are stored in object storage' do @@ -42,8 +86,11 @@ describe Gitlab::ImportExport::LfsSaver do before do allow(LfsObjectUploader).to receive(:object_store_enabled?).and_return(true) - allow(lfs_object.file).to receive(:url).and_return('http://my-object-storage.local') project.lfs_objects << lfs_object + + expect_next_instance_of(LfsObjectUploader) do |instance| + expect(instance).to receive(:url).and_return('http://my-object-storage.local') + end end it 'downloads the file to include in an archive' do diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index b95b5dfe791..a9e8431acba 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -154,5 +154,15 @@ describe Gitlab::ImportExport::MembersMapper do expect(members_mapper.map[exported_user_id]).to eq(user2.id) end end + + context 'when importer mapping fails' do + let(:exception_message) { 'Something went wrong' } + + it 'includes importer specific error message' do + expect(ProjectMember).to receive(:create!).and_raise(StandardError.new(exception_message)) + + expect { members_mapper.map }.to raise_error(StandardError, "Error adding importer user to project members. #{exception_message}") + end + end end end diff --git a/spec/lib/gitlab/import_export/project.group.json b/spec/lib/gitlab/import_export/project.group.json index 1a561e81e4a..66f5bb4c87b 100644 --- a/spec/lib/gitlab/import_export/project.group.json +++ b/spec/lib/gitlab/import_export/project.group.json @@ -19,7 +19,7 @@ "labels": [ { "id": 2, - "title": "project label", + "title": "A project label", "color": "#428bca", "project_id": 8, "created_at": "2016-07-22T08:55:44.161Z", @@ -105,7 +105,7 @@ "updated_at": "2017-08-15T18:37:40.795Z", "label": { "id": 6, - "title": "project label", + "title": "A project label", "color": "#A8D695", "project_id": null, "created_at": "2017-08-15T18:37:19.698Z", @@ -162,7 +162,7 @@ "updated_at": "2017-08-15T18:37:40.795Z", "label": { "id": 2, - "title": "project label", + "title": "A project label", "color": "#A8D695", "project_id": null, "created_at": "2017-08-15T18:37:19.698Z", diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 8be074f4b9b..a211675bbf2 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -2450,7 +2450,21 @@ "author": { "name": "Ottis Schuster II" }, - "events": [] + "events": [], + "suggestions": [ + { + "id": 1, + "note_id": 674, + "relative_order": 0, + "applied": false, + "commit_id": null, + "from_content": "Original line\n", + "to_content": "New line\n", + "lines_above": 0, + "lines_below": 0, + "outdated": false + } + ] }, { "id": 675, @@ -2775,7 +2789,8 @@ "action": 1, "author_id": 1 } - ] + ], + "approvals_before_merge": 1 }, { "id": 26, @@ -6630,8 +6645,16 @@ "id": 123, "token": "cdbfasdf44a5958c83654733449e585", "project_id": 5, + "owner_id": 1, "created_at": "2017-01-16T15:25:28.637Z", "updated_at": "2017-01-16T15:25:28.637Z" + }, + { + "id": 456, + "token": "33a66349b5ad01fc00174af87804e40", + "project_id": 5, + "created_at": "2017-01-16T15:25:29.637Z", + "updated_at": "2017-01-16T15:25:29.637Z" } ], "deploy_keys": [], @@ -7138,5 +7161,65 @@ "link_url": "http://www.example.com", "image_url": "http://www.example.com" } + ], + "boards": [ + { + "id": 29, + "project_id": 49, + "created_at": "2019-06-06T14:01:06.204Z", + "updated_at": "2019-06-06T14:22:37.045Z", + "name": "TestBoardABC", + "milestone_id": null, + "group_id": null, + "weight": null, + "lists": [ + { + "id": 59, + "board_id": 29, + "label_id": null, + "list_type": "backlog", + "position": null, + "created_at": "2019-06-06T14:01:06.214Z", + "updated_at": "2019-06-06T14:01:06.214Z", + "user_id": null, + "milestone_id": null + }, + { + "id": 61, + "board_id": 29, + "label_id": 20, + "list_type": "label", + "position": 0, + "created_at": "2019-06-06T14:01:43.197Z", + "updated_at": "2019-06-06T14:01:43.197Z", + "user_id": null, + "milestone_id": null, + "label": { + "id": 20, + "title": "testlabel", + "color": "#0033CC", + "project_id": 49, + "created_at": "2019-06-06T14:01:19.698Z", + "updated_at": "2019-06-06T14:01:19.698Z", + "template": false, + "description": null, + "group_id": null, + "type": "ProjectLabel", + "priorities": [] + } + }, + { + "id": 60, + "board_id": 29, + "label_id": null, + "list_type": "closed", + "position": null, + "created_at": "2019-06-06T14:01:06.221Z", + "updated_at": "2019-06-06T14:01:06.221Z", + "user_id": null, + "milestone_id": null + } + ] + } ] } 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 ca46006ea58..d6e1fbaa979 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -32,6 +32,10 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end context 'JSON' do + before do + stub_feature_flags(use_legacy_pipeline_triggers: false) + end + it 'restores models based on JSON' do expect(@restored_project_json).to be_truthy end @@ -121,6 +125,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do expect(MergeRequest.find_by(title: 'MR1').resource_label_events).not_to be_empty end + it 'restores suggestion' do + note = Note.find_by("note LIKE 'Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum%'") + + expect(note.suggestions.count).to eq(1) + expect(note.suggestions.first.from_content).to eq("Original line\n") + end + context 'event at forth level of the tree' do let(:event) { Event.where(action: 6).first } @@ -156,13 +167,21 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end it 'has project labels' do - expect(ProjectLabel.count).to eq(2) + expect(ProjectLabel.count).to eq(3) end it 'has no group labels' do expect(GroupLabel.count).to eq(0) end + it 'has issue boards' do + expect(Project.find_by_path('project').boards.count).to eq(1) + end + + it 'has lists associated with the issue board' do + expect(Project.find_by_path('project').boards.find_by_name('TestBoardABC').lists.count).to eq(3) + end + it 'has a project feature' do expect(@project.project_feature).not_to be_nil end @@ -198,8 +217,9 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end context 'tokens are regenerated' do - it 'has a new CI trigger token' do - expect(Ci::Trigger.where(token: 'cdbfasdf44a5958c83654733449e585')).to be_empty + it 'has new CI trigger tokens' do + expect(Ci::Trigger.where(token: %w[cdbfasdf44a5958c83654733449e585 33a66349b5ad01fc00174af87804e40])) + .to be_empty end it 'has a new CI build token' do @@ -212,7 +232,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do expect(@project.merge_requests.size).to eq(9) end - it 'has the correct number of triggers' do + it 'only restores valid triggers' do expect(@project.triggers.size).to eq(1) end @@ -267,7 +287,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end it 'has label priorities' do - expect(project.labels.first.priorities).not_to be_empty + expect(project.labels.find_by(title: 'A project label').priorities).not_to be_empty end it 'has milestones' do @@ -320,7 +340,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do it_behaves_like 'restores project correctly', issues: 1, - labels: 1, + labels: 2, milestones: 1, first_issue_labels: 1, services: 1 @@ -397,7 +417,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do it_behaves_like 'restores project successfully' it_behaves_like 'restores project correctly', issues: 2, - labels: 1, + labels: 2, milestones: 2, first_issue_labels: 1 @@ -491,6 +511,18 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end end + context 'with restricted internal visibility' do + describe 'internal project' do + let(:visibility) { Gitlab::VisibilityLevel::INTERNAL } + + it 'uses private visibility' do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::INTERNAL]) + + expect(restorer.restored_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end + end + end + context 'with group visibility' do before do group = create(:group, visibility_level: group_visibility) @@ -523,6 +555,14 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do it 'uses the group visibility' do expect(restorer.restored_project.visibility_level).to eq(group_visibility) end + + context 'with restricted internal visibility' do + it 'sets private visibility' do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::INTERNAL]) + + expect(restorer.restored_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end + end end end end 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 bc4f867e891..fefbed93316 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -42,6 +42,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver do expect(saved_project_json).to include({ 'description' => 'description', 'visibility_level' => 20 }) end + it 'has approvals_before_merge set' do + expect(saved_project_json['approvals_before_merge']).to eq(1) + end + it 'has milestones' do expect(saved_project_json['milestones']).not_to be_empty end @@ -175,9 +179,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver do end it 'has priorities associated to labels' do - priorities = saved_project_json['issues'].first['label_links'].map { |link| link['label']['priorities'] } + priorities = saved_project_json['issues'].first['label_links'].flat_map { |link| link['label']['priorities'] } - expect(priorities.flatten).not_to be_empty + expect(priorities).not_to be_empty end it 'has issue resource label events' do @@ -268,6 +272,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver do expect(saved_project_json).not_to include("runners_token" => 'token') end end + + it 'has a board and a list' do + expect(saved_project_json['boards'].first['lists']).not_to be_empty + end end end @@ -287,7 +295,8 @@ describe Gitlab::ImportExport::ProjectTreeSaver do issues: [issue], snippets: [snippet], releases: [release], - group: group + group: group, + approvals_before_merge: 1 ) project_label = create(:label, project: project) group_label = create(:group_label, group: group) @@ -322,6 +331,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver do create(:project_badge, project: project) create(:project_badge, project: project) + board = create(:board, project: project, name: 'TestBoard') + create(:list, board: board, position: 0, label: project_label) + project end diff --git a/spec/lib/gitlab/import_export/relation_rename_service_spec.rb b/spec/lib/gitlab/import_export/relation_rename_service_spec.rb index a20a844a492..15748407f0c 100644 --- a/spec/lib/gitlab/import_export/relation_rename_service_spec.rb +++ b/spec/lib/gitlab/import_export/relation_rename_service_spec.rb @@ -28,6 +28,7 @@ describe Gitlab::ImportExport::RelationRenameService do before do allow(shared).to receive(:export_path).and_return(import_path) + allow(ActiveSupport::JSON).to receive(:decode).and_call_original allow(ActiveSupport::JSON).to receive(:decode).with(file_content).and_return(json_file) end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 28b187c3676..f0545176a90 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -235,6 +235,12 @@ MergeRequest::Metrics: - latest_build_started_at - latest_build_finished_at - first_deployed_to_production_at +- first_comment_at +- first_commit_at +- last_commit_at +- diff_size +- modified_paths_size +- commits_count Ci::Pipeline: - id - project_id @@ -687,3 +693,22 @@ ProjectMetricsSetting: - external_dashboard_url - created_at - updated_at +Board: +- id +- project_id +- created_at +- updated_at +- group_id +- milestone_id +- weight +- name +List: +- id +- board_id +- label_id +- list_type +- position +- created_at +- updated_at +- milestone_id +- user_id |