require 'spec_helper' include ImportExport::CommonUtil describe Gitlab::ImportExport::ProjectTreeRestorer do describe 'restore project tree' do before(:context) do @user = create(:user) RSpec::Mocks.with_temporary_scope do @shared = Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path') allow(@shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/') @project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') allow_any_instance_of(Repository).to receive(:fetch_ref).and_return(true) allow_any_instance_of(Gitlab::Git::Repository).to receive(:branch_exists?).and_return(false) 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) @restored_project_json = project_tree_restorer.restore end end context 'JSON' do it 'restores models based on JSON' do expect(@restored_project_json).to be true end it 'restore correct project features' do project = Project.find_by_path('project') expect(project.project_feature.issues_access_level).to eq(ProjectFeature::DISABLED) expect(project.project_feature.builds_access_level).to eq(ProjectFeature::DISABLED) expect(project.project_feature.snippets_access_level).to eq(ProjectFeature::ENABLED) expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::ENABLED) expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::ENABLED) end it 'has the project html description' do expect(Project.find_by_path('project').description_html).to eq('description') end it 'has the same label associated to two issues' do expect(ProjectLabel.find_by_title('test2').issues.count).to eq(2) end it 'has milestones associated to two separate issues' do expect(Milestone.find_by_description('test milestone').issues.count).to eq(2) end it 'creates a valid pipeline note' do expect(Ci::Pipeline.first.notes).not_to be_empty end it 'restores pipelines with missing ref' do expect(Ci::Pipeline.where(ref: nil)).not_to be_empty end it 'preserves updated_at on issues' do issue = Issue.where(description: 'Aliquam enim illo et possimus.').first expect(issue.reload.updated_at.to_s).to eq('2016-06-14 15:02:47 UTC') end it 'contains the merge access levels on a protected branch' do expect(ProtectedBranch.first.merge_access_levels).not_to be_empty end it 'contains the push access levels on a protected branch' do expect(ProtectedBranch.first.push_access_levels).not_to be_empty end it 'contains the create access levels on a protected tag' do expect(ProtectedTag.first.create_access_levels).not_to be_empty end context 'event at forth level of the tree' do let(:event) { Event.where(action: 6).first } it 'restores the event' do expect(event).not_to be_nil end it 'has the action' do expect(event.action).not_to be_nil end it 'event belongs to note, belongs to merge request, belongs to a project' do expect(event.note.noteable.project).not_to be_nil end end it 'has the correct data for merge request st_diffs' do # makes sure we are renaming the custom method +utf8_st_diffs+ into +st_diffs+ # one MergeRequestDiff uses the new format, where st_diffs is expected to be nil expect(MergeRequestDiff.where.not(st_diffs: nil).count).to eq(8) end it 'has the correct data for merge request diff files' do expect(MergeRequestDiffFile.where.not(diff: nil).count).to eq(9) end it 'has the correct data for merge request diff commits in serialised and table formats' do expect(MergeRequestDiff.where.not(st_commits: nil).count).to eq(7) expect(MergeRequestDiffCommit.count).to eq(6) end it 'has the correct time for merge request st_commits' do st_commits = MergeRequestDiff.where.not(st_commits: nil).first.st_commits expect(st_commits.first[:committed_date]).to be_kind_of(Time) end it 'has labels associated to label links, associated to issues' do expect(Label.first.label_links.first.target).not_to be_nil end it 'has project labels' do expect(ProjectLabel.count).to eq(2) end it 'has no group labels' do expect(GroupLabel.count).to eq(0) end it 'has a project feature' do expect(@project.project_feature).not_to be_nil end it 'restores the correct service' do expect(CustomIssueTrackerService.first).not_to be_nil end context 'Merge requests' do it 'always has the new project as a target' do expect(MergeRequest.find_by_title('MR1').target_project).to eq(@project) end it 'has the same source project as originally if source/target are the same' do expect(MergeRequest.find_by_title('MR1').source_project).to eq(@project) end it 'has the new project as target if source/target differ' do expect(MergeRequest.find_by_title('MR2').target_project).to eq(@project) end it 'has no source if source/target differ' do expect(MergeRequest.find_by_title('MR2').source_project_id).to eq(-1) end end context 'tokens are regenerated' do it 'has a new CI trigger token' do expect(Ci::Trigger.where(token: 'cdbfasdf44a5958c83654733449e585')).to be_empty end it 'has a new CI build token' do expect(Ci::Build.where(token: 'abcd')).to be_empty end end context 'has restored the correct number of records' do it 'has the correct number of merge requests' do expect(@project.merge_requests.size).to eq(9) end it 'has the correct number of triggers' do expect(@project.triggers.size).to eq(1) end it 'has the correct number of pipelines and statuses' do expect(@project.pipelines.size).to eq(5) @project.pipelines.zip([2, 2, 2, 2, 2]) .each do |(pipeline, expected_status_size)| expect(pipeline.statuses.size).to eq(expected_status_size) end end end end end context 'Light JSON' do let(:user) { create(:user) } let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path') } let!(:project) { create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') } let(:project_tree_restorer) { described_class.new(user: user, shared: shared, project: project) } let(:restored_project_json) { project_tree_restorer.restore } before do project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") allow(shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/') end context 'project.json file access check' do it 'does not read a symlink' do Dir.mktmpdir do |tmpdir| setup_symlink(tmpdir, 'project.json') allow(shared).to receive(:export_path).and_call_original restored_project_json expect(shared.errors.first).to be_nil end end end context 'when there is an existing build with build token' do it 'restores project json correctly' do create(:ci_build, token: 'abcd') expect(restored_project_json).to be true end end context 'with group' do let!(:project) do create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project', group: create(:group)) end before do project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") restored_project_json end it 'correctly restores project' do expect(restored_project_json).to be_truthy expect(shared.errors).to be_empty end it 'has labels' do expect(project.labels.count).to eq(2) end it 'creates group label' do expect(project.group.labels.count).to eq(1) end it 'has label priorities' do expect(project.labels.first.priorities).not_to be_empty end it 'has milestones' do expect(project.milestones.count).to eq(1) end it 'has issue' do expect(project.issues.count).to eq(1) expect(project.issues.first.labels.count).to eq(2) end it 'has issue with group label and project label' do labels = project.issues.first.labels expect(labels.where(type: "GroupLabel").count).to eq(1) expect(labels.where(type: "ProjectLabel").count).to eq(1) end end end end