diff options
author | Shinya Maeda <shinya@gitlab.com> | 2018-08-03 08:17:22 +0300 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2018-08-03 08:17:22 +0300 |
commit | 1f53cf7cf0cb53b5d69ab141fa9020356e62027e (patch) | |
tree | fac87bd3fcf2900116bbc2777eb6f347f50922f6 /spec/lib | |
parent | d867081df185b873667d9eec1184ac92efc8973e (diff) | |
parent | 5f664759b57ef1c0fcfb7e95dfbff6c080a7a72f (diff) |
Merge branch 'master-ce' into artifact-format-v2-with-parser
Diffstat (limited to 'spec/lib')
26 files changed, 561 insertions, 77 deletions
diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb index 92a27e308d2..c5a854b5660 100644 --- a/spec/lib/backup/repository_spec.rb +++ b/spec/lib/backup/repository_spec.rb @@ -73,37 +73,27 @@ describe Backup::Repository do end end - describe '#delete_all_repositories', :seed_helper do - shared_examples('delete_all_repositories') do - before do - allow(FileUtils).to receive(:mkdir_p).and_call_original - allow(FileUtils).to receive(:mv).and_call_original - end - - after(:all) do - ensure_seeds - end - - it 'removes all repositories' do - # Sanity check: there should be something for us to delete - expect(list_repositories).to include(File.join(SEED_STORAGE_PATH, TEST_REPO_PATH)) + describe '#prepare_directories', :seed_helper do + before do + allow(FileUtils).to receive(:mkdir_p).and_call_original + allow(FileUtils).to receive(:mv).and_call_original + end - subject.delete_all_repositories('default', Gitlab.config.repositories.storages['default']) + after(:all) do + ensure_seeds + end - expect(list_repositories).to be_empty - end + it' removes all repositories' do + # Sanity check: there should be something for us to delete + expect(list_repositories).to include(File.join(SEED_STORAGE_PATH, TEST_REPO_PATH)) - def list_repositories - Dir[File.join(SEED_STORAGE_PATH, '*.git')] - end - end + subject.prepare_directories - context 'with gitaly' do - it_behaves_like 'delete_all_repositories' + expect(list_repositories).to be_empty end - context 'without gitaly', :skip_gitaly_mock do - it_behaves_like 'delete_all_repositories' + def list_repositories + Dir[File.join(SEED_STORAGE_PATH, '*.git')] end end diff --git a/spec/lib/gitlab/bare_repository_import/importer_spec.rb b/spec/lib/gitlab/bare_repository_import/importer_spec.rb index 468f6ff6d24..6e21c846c0a 100644 --- a/spec/lib/gitlab/bare_repository_import/importer_spec.rb +++ b/spec/lib/gitlab/bare_repository_import/importer_spec.rb @@ -1,10 +1,11 @@ require 'spec_helper' -describe Gitlab::BareRepositoryImport::Importer, repository: true do +describe Gitlab::BareRepositoryImport::Importer, :seed_helper do let!(:admin) { create(:admin) } let!(:base_dir) { Dir.mktmpdir + '/' } let(:bare_repository) { Gitlab::BareRepositoryImport::Repository.new(base_dir, File.join(base_dir, "#{project_path}.git")) } let(:gitlab_shell) { Gitlab::Shell.new } + let(:source_project) { TEST_REPO_PATH } subject(:importer) { described_class.new(admin, bare_repository) } @@ -17,16 +18,11 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do after do FileUtils.rm_rf(base_dir) + TestEnv.clean_test_path + ensure_seeds Rainbow.enabled = @rainbow end - around do |example| - # TODO migrate BareRepositoryImport https://gitlab.com/gitlab-org/gitaly/issues/953 - Gitlab::GitalyClient::StorageSettings.allow_disk_access do - example.run - end - end - shared_examples 'importing a repository' do describe '.execute' do it 'creates a project for a repository in storage' do @@ -86,8 +82,8 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do importer.create_project_if_needed end - it 'creates the Git repo on disk with the proper symlink for hooks' do - create_bare_repository("#{project_path}.git") + it 'creates the Git repo on disk' do + prepare_repository("#{project_path}.git", source_project) importer.create_project_if_needed @@ -97,9 +93,6 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do expect(gitlab_shell.exists?(project.repository_storage, repo_path)).to be(true) expect(gitlab_shell.exists?(project.repository_storage, hook_path)).to be(true) - - full_hook_path = File.join(project.repository.path_to_repo, 'hooks') - expect(File.readlink(full_hook_path)).to eq(Gitlab.config.gitlab_shell.hooks_path) end context 'hashed storage enabled' do @@ -148,7 +141,7 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do end it 'creates the Git repo in disk' do - create_bare_repository("#{project_path}.git") + prepare_repository("#{project_path}.git", source_project) importer.create_project_if_needed @@ -158,23 +151,23 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do expect(gitlab_shell.exists?(project.repository_storage, project.disk_path + '.wiki.git')).to be(true) end - it 'moves an existing project to the correct path' do + context 'with a repository already on disk' do + let!(:base_dir) { TestEnv.repos_path } # This is a quick way to get a valid repository instead of copying an # existing one. Since it's not persisted, the importer will try to # create the project. - project = build(:project, :legacy_storage, :repository) - original_commit_count = project.repository.commit_count - - legacy_path = Gitlab.config.repositories.storages[project.repository_storage].legacy_disk_path + let(:project) { build(:project, :legacy_storage, :repository) } + let(:project_path) { project.full_path } - bare_repo = Gitlab::BareRepositoryImport::Repository.new(legacy_path, project.repository.path) - gitlab_importer = described_class.new(admin, bare_repo) + it 'moves an existing project to the correct path' do + original_commit_count = project.repository.commit_count - expect(gitlab_importer).to receive(:create_project).and_call_original + expect(importer).to receive(:create_project).and_call_original - new_project = gitlab_importer.create_project_if_needed + new_project = importer.create_project_if_needed - expect(new_project.repository.commit_count).to eq(original_commit_count) + expect(new_project.repository.commit_count).to eq(original_commit_count) + end end end @@ -185,8 +178,8 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do it_behaves_like 'importing a repository' it 'creates the Wiki git repo in disk' do - create_bare_repository("#{project_path}.git") - create_bare_repository("#{project_path}.wiki.git") + prepare_repository("#{project_path}.git", source_project) + prepare_repository("#{project_path}.wiki.git", source_project) expect(Projects::CreateService).to receive(:new).with(admin, hash_including(skip_wiki: true, import_type: 'bare_repository')).and_call_original @@ -213,8 +206,13 @@ describe Gitlab::BareRepositoryImport::Importer, repository: true do end end - def create_bare_repository(project_path) + def prepare_repository(project_path, source_project) repo_path = File.join(base_dir, project_path) - Gitlab::Git::Repository.create(repo_path, bare: true) + + return create_bare_repository(repo_path) unless source_project + + cmd = %W(#{Gitlab.config.git.bin_path} clone --bare #{source_project} #{repo_path}) + + system(git_env, *cmd, chdir: SEED_STORAGE_PATH, out: '/dev/null', err: '/dev/null') end end diff --git a/spec/lib/gitlab/cleanup/project_uploads_spec.rb b/spec/lib/gitlab/cleanup/project_uploads_spec.rb new file mode 100644 index 00000000000..37b38776775 --- /dev/null +++ b/spec/lib/gitlab/cleanup/project_uploads_spec.rb @@ -0,0 +1,278 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Cleanup::ProjectUploads do + subject { described_class.new(logger: logger) } + let(:logger) { double(:logger) } + + before do + allow(logger).to receive(:info).at_least(1).times + allow(logger).to receive(:debug).at_least(1).times + end + + describe '#run!' do + shared_examples_for 'moves the file' do + shared_examples_for 'a real run' do + let(:args) { [dry_run: false] } + + it 'moves the file to its proper location' do + subject.run!(*args) + + expect(File.exist?(path)).to be_falsey + expect(File.exist?(new_path)).to be_truthy + end + + it 'logs action as done' do + expect(logger).to receive(:info).with("Looking for orphaned project uploads to clean up...") + expect(logger).to receive(:info).with("Did #{action}") + + subject.run!(*args) + end + end + + shared_examples_for 'a dry run' do + it 'does not move the file' do + subject.run!(*args) + + expect(File.exist?(path)).to be_truthy + expect(File.exist?(new_path)).to be_falsey + end + + it 'logs action as able to be done' do + expect(logger).to receive(:info).with("Looking for orphaned project uploads to clean up. Dry run...") + expect(logger).to receive(:info).with("Can #{action}") + + subject.run!(*args) + end + end + + context 'when dry_run is false' do + let(:args) { [dry_run: false] } + + it_behaves_like 'a real run' + end + + context 'when dry_run is nil' do + let(:args) { [dry_run: nil] } + + it_behaves_like 'a real run' + end + + context 'when dry_run is true' do + let(:args) { [dry_run: true] } + + it_behaves_like 'a dry run' + end + + context 'with dry_run not specified' do + let(:args) { [] } + + it_behaves_like 'a dry run' + end + end + + shared_examples_for 'moves the file to lost and found' do + let(:action) { "move to lost and found #{path} -> #{new_path}" } + + it_behaves_like 'moves the file' + end + + shared_examples_for 'fixes the file' do + let(:action) { "fix #{path} -> #{new_path}" } + + it_behaves_like 'moves the file' + end + + context 'orphaned project upload file' do + context 'when an upload record matching the secret and filename is found' do + context 'when the project is still in legacy storage' do + let(:orphaned) { create(:upload, :issuable_upload, :with_file, model: create(:project, :legacy_storage)) } + let(:new_path) { orphaned.absolute_path } + let(:path) { File.join(FileUploader.root, 'some', 'wrong', 'location', orphaned.path) } + + before do + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.mv(new_path, path) + end + + it_behaves_like 'fixes the file' + end + + context 'when the project was moved to hashed storage' do + let(:orphaned) { create(:upload, :issuable_upload, :with_file) } + let(:new_path) { orphaned.absolute_path } + let(:path) { File.join(FileUploader.root, 'some', 'wrong', 'location', orphaned.path) } + + before do + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.mv(new_path, path) + end + + it_behaves_like 'fixes the file' + end + + context 'when the project is missing (the upload *record* is an orphan)' do + let(:orphaned) { create(:upload, :issuable_upload, :with_file, model: build(:project, :legacy_storage)) } + let!(:path) { orphaned.absolute_path } + let!(:new_path) { File.join(FileUploader.root, '-', 'project-lost-found', orphaned.model.full_path, orphaned.path) } + + before do + orphaned.model.delete + end + + it_behaves_like 'moves the file to lost and found' + end + + # We will probably want to add logic (Reschedule background upload) to + # cover Case 2 in https://gitlab.com/gitlab-org/gitlab-ce/issues/46535#note_75355104 + context 'when the file should be in object storage' do + context 'when the file otherwise has the correct local path' do + let!(:orphaned) { create(:upload, :issuable_upload, :object_storage, model: build(:project, :legacy_storage)) } + let!(:path) { File.join(FileUploader.root, orphaned.model.full_path, orphaned.path) } + + before do + stub_feature_flags(import_export_object_storage: true) + stub_uploads_object_storage(FileUploader) + + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.touch(path) + end + + it 'does not move the file' do + expect(File.exist?(path)).to be_truthy + + subject.run!(dry_run: false) + + expect(File.exist?(path)).to be_truthy + end + end + + # E.g. the upload file was orphaned, and then uploads were migrated to + # object storage + context 'when the file has the wrong local path' do + let!(:orphaned) { create(:upload, :issuable_upload, :object_storage, model: build(:project, :legacy_storage)) } + let!(:path) { File.join(FileUploader.root, 'wrong', orphaned.path) } + let!(:new_path) { File.join(FileUploader.root, '-', 'project-lost-found', 'wrong', orphaned.path) } + + before do + stub_feature_flags(import_export_object_storage: true) + stub_uploads_object_storage(FileUploader) + + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.touch(path) + end + + it_behaves_like 'moves the file to lost and found' + end + end + end + + context 'when a matching upload record can not be found' do + context 'when the file path fits the known pattern' do + let!(:orphaned) { create(:upload, :issuable_upload, :with_file, model: build(:project, :legacy_storage)) } + let!(:path) { orphaned.absolute_path } + let!(:new_path) { File.join(FileUploader.root, '-', 'project-lost-found', orphaned.model.full_path, orphaned.path) } + + before do + orphaned.delete + end + + it_behaves_like 'moves the file to lost and found' + end + + context 'when the file path does not fit the known pattern' do + let!(:invalid_path) { File.join('group', 'file.jpg') } + let!(:path) { File.join(FileUploader.root, invalid_path) } + let!(:new_path) { File.join(FileUploader.root, '-', 'project-lost-found', invalid_path) } + + before do + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.touch(path) + end + + after do + File.delete(path) if File.exist?(path) + end + + it_behaves_like 'moves the file to lost and found' + end + end + end + + context 'non-orphaned project upload file' do + it 'does not move the file' do + tracked = create(:upload, :issuable_upload, :with_file, model: build(:project, :legacy_storage)) + tracked_path = tracked.absolute_path + + expect(logger).not_to receive(:info).with(/move|fix/i) + expect(File.exist?(tracked_path)).to be_truthy + + subject.run!(dry_run: false) + + expect(File.exist?(tracked_path)).to be_truthy + end + end + + context 'ignorable cases' do + # Because we aren't concerned about these, and can save a lot of + # processing time by ignoring them. If we wish to cleanup hashed storage + # directories, it should simply require removing this test and modifying + # the find command. + context 'when the file is already in hashed storage' do + let(:project) { create(:project) } + + before do + expect(logger).not_to receive(:info).with(/move|fix/i) + end + + it 'does not move even an orphan file' do + orphaned = create(:upload, :issuable_upload, :with_file, model: project) + path = orphaned.absolute_path + orphaned.delete + + expect(File.exist?(path)).to be_truthy + + subject.run!(dry_run: false) + + expect(File.exist?(path)).to be_truthy + end + end + + it 'does not move any non-project (FileUploader) uploads' do + paths = [] + orphaned1 = create(:upload, :personal_snippet_upload, :with_file) + orphaned2 = create(:upload, :namespace_upload, :with_file) + orphaned3 = create(:upload, :attachment_upload, :with_file) + paths << orphaned1.absolute_path + paths << orphaned2.absolute_path + paths << orphaned3.absolute_path + Upload.delete_all + + expect(logger).not_to receive(:info).with(/move|fix/i) + paths.each do |path| + expect(File.exist?(path)).to be_truthy + end + + subject.run!(dry_run: false) + + paths.each do |path| + expect(File.exist?(path)).to be_truthy + end + end + + it 'does not move any uploads in tmp (which would interfere with ongoing upload activity)' do + path = File.join(FileUploader.root, 'tmp', 'foo.jpg') + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.touch(path) + + expect(logger).not_to receive(:info).with(/move|fix/i) + expect(File.exist?(path)).to be_truthy + + subject.run!(dry_run: false) + + expect(File.exist?(path)).to be_truthy + end + end + end +end diff --git a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb index 5d22dcfb508..ca067a29174 100644 --- a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb +++ b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::AttributesAtRefParser, seed_helper: true do +describe Gitlab::Git::AttributesAtRefParser, :seed_helper do let(:project) { create(:project, :repository) } let(:repository) { project.repository } diff --git a/spec/lib/gitlab/git/attributes_parser_spec.rb b/spec/lib/gitlab/git/attributes_parser_spec.rb index 2d103123998..18ebfef38f0 100644 --- a/spec/lib/gitlab/git/attributes_parser_spec.rb +++ b/spec/lib/gitlab/git/attributes_parser_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::AttributesParser, seed_helper: true do +describe Gitlab::Git::AttributesParser, :seed_helper do let(:attributes_path) { File.join(SEED_STORAGE_PATH, 'with-git-attributes.git', 'info', 'attributes') } let(:data) { File.read(attributes_path) } diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb index ba790b717ae..e704d1c673c 100644 --- a/spec/lib/gitlab/git/blame_spec.rb +++ b/spec/lib/gitlab/git/blame_spec.rb @@ -1,7 +1,7 @@ # coding: utf-8 require "spec_helper" -describe Gitlab::Git::Blame, seed_helper: true do +describe Gitlab::Git::Blame, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:blame) do Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md") diff --git a/spec/lib/gitlab/git/blob_snippet_spec.rb b/spec/lib/gitlab/git/blob_snippet_spec.rb index d6d365f6492..6effec8295c 100644 --- a/spec/lib/gitlab/git/blob_snippet_spec.rb +++ b/spec/lib/gitlab/git/blob_snippet_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -describe Gitlab::Git::BlobSnippet, seed_helper: true do +describe Gitlab::Git::BlobSnippet, :seed_helper do describe '#data' do context 'empty lines' do let(:snippet) { Gitlab::Git::BlobSnippet.new('master', nil, nil, nil) } diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb index 034b89a46fa..ea49502ae2e 100644 --- a/spec/lib/gitlab/git/blob_spec.rb +++ b/spec/lib/gitlab/git/blob_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -describe Gitlab::Git::Blob, seed_helper: true do +describe Gitlab::Git::Blob, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } describe 'initialize' do diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb index a8c5627e678..79ccbb79966 100644 --- a/spec/lib/gitlab/git/branch_spec.rb +++ b/spec/lib/gitlab/git/branch_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Branch, seed_helper: true do +describe Gitlab::Git::Branch, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:rugged) do Gitlab::GitalyClient::StorageSettings.allow_disk_access do diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index 0adb684765d..2718a3c5e49 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Commit, seed_helper: true do +describe Gitlab::Git::Commit, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) } let(:rugged_commit) do diff --git a/spec/lib/gitlab/git/committer_with_hooks_spec.rb b/spec/lib/gitlab/git/committer_with_hooks_spec.rb index 2100690f873..c7626058acd 100644 --- a/spec/lib/gitlab/git/committer_with_hooks_spec.rb +++ b/spec/lib/gitlab/git/committer_with_hooks_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::CommitterWithHooks, seed_helper: true do +describe Gitlab::Git::CommitterWithHooks, :seed_helper do # TODO https://gitlab.com/gitlab-org/gitaly/issues/1234 skip 'needs to be moved to gitaly-ruby test suite' do shared_examples 'calling wiki hooks' do diff --git a/spec/lib/gitlab/git/compare_spec.rb b/spec/lib/gitlab/git/compare_spec.rb index b6a42e422b5..7cc6f52f8ee 100644 --- a/spec/lib/gitlab/git/compare_spec.rb +++ b/spec/lib/gitlab/git/compare_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Compare, seed_helper: true do +describe Gitlab::Git::Compare, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:compare) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) } let(:compare_straight) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: true) } diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb index 65edc750f39..81658874be7 100644 --- a/spec/lib/gitlab/git/diff_collection_spec.rb +++ b/spec/lib/gitlab/git/diff_collection_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::DiffCollection, seed_helper: true do +describe Gitlab::Git::DiffCollection, :seed_helper do subject do Gitlab::Git::DiffCollection.new( iterator, diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb index 11ab376ab8f..87d9fcee39e 100644 --- a/spec/lib/gitlab/git/diff_spec.rb +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Diff, seed_helper: true do +describe Gitlab::Git::Diff, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } before do diff --git a/spec/lib/gitlab/git/hooks_service_spec.rb b/spec/lib/gitlab/git/hooks_service_spec.rb index 9337aa39e13..55ffced36ac 100644 --- a/spec/lib/gitlab/git/hooks_service_spec.rb +++ b/spec/lib/gitlab/git/hooks_service_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::HooksService, seed_helper: true do +describe Gitlab::Git::HooksService, :seed_helper do let(:gl_id) { 'user-456' } let(:gl_username) { 'janedoe' } let(:user) { Gitlab::Git::User.new(gl_username, 'Jane Doe', 'janedoe@example.com', gl_id) } diff --git a/spec/lib/gitlab/git/index_spec.rb b/spec/lib/gitlab/git/index_spec.rb index e51b875be11..c4edd6961e1 100644 --- a/spec/lib/gitlab/git/index_spec.rb +++ b/spec/lib/gitlab/git/index_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::Index, seed_helper: true do +describe Gitlab::Git::Index, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } let(:index) { described_class.new(repository) } diff --git a/spec/lib/gitlab/git/remote_repository_spec.rb b/spec/lib/gitlab/git/remote_repository_spec.rb index eb148cc3804..53ed7c5a13a 100644 --- a/spec/lib/gitlab/git/remote_repository_spec.rb +++ b/spec/lib/gitlab/git/remote_repository_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Git::RemoteRepository, seed_helper: true do +describe Gitlab::Git::RemoteRepository, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } subject { described_class.new(repository) } diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 62396af1ebe..35a6fc94753 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1,7 +1,7 @@ # coding: utf-8 require "spec_helper" -describe Gitlab::Git::Repository, seed_helper: true do +describe Gitlab::Git::Repository, :seed_helper do include Gitlab::EncodingHelper using RSpec::Parameterized::TableSyntax diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb index be2f5bfb819..2d9db576a6c 100644 --- a/spec/lib/gitlab/git/tag_spec.rb +++ b/spec/lib/gitlab/git/tag_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Tag, seed_helper: true do +describe Gitlab::Git::Tag, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } shared_examples 'Gitlab::Git::Repository#tags' do diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb index 001e406a930..3792d6bf67b 100644 --- a/spec/lib/gitlab/git/tree_spec.rb +++ b/spec/lib/gitlab/git/tree_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Gitlab::Git::Tree, seed_helper: true do +describe Gitlab::Git::Tree, :seed_helper do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') } context :repo do diff --git a/spec/lib/gitlab/gitaly_client/storage_service_spec.rb b/spec/lib/gitlab/gitaly_client/storage_service_spec.rb new file mode 100644 index 00000000000..6c25e2d6ebd --- /dev/null +++ b/spec/lib/gitlab/gitaly_client/storage_service_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Gitlab::GitalyClient::StorageService do + describe '#delete_all_repositories' do + let!(:project) { create(:project, :repository) } + + it 'removes all repositories' do + described_class.new(project.repository_storage).delete_all_repositories + + expect(project.repository.exists?).to be(false) + end + end +end diff --git a/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb b/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb new file mode 100644 index 00000000000..287745eb40e --- /dev/null +++ b/spec/lib/gitlab/import_export/file_importer_object_storage_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::FileImporter do + let(:shared) { Gitlab::ImportExport::Shared.new(nil) } + let(:storage_path) { "#{Dir.tmpdir}/file_importer_spec" } + let(:valid_file) { "#{shared.export_path}/valid.json" } + let(:symlink_file) { "#{shared.export_path}/invalid.json" } + let(:hidden_symlink_file) { "#{shared.export_path}/.hidden" } + let(:subfolder_symlink_file) { "#{shared.export_path}/subfolder/invalid.json" } + let(:evil_symlink_file) { "#{shared.export_path}/.\nevil" } + + before do + stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0) + stub_feature_flags(import_export_object_storage: true) + stub_uploads_object_storage(FileUploader) + + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(storage_path) + allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true) + allow_any_instance_of(Gitlab::ImportExport::Shared).to receive(:relative_archive_path).and_return('test') + allow(SecureRandom).to receive(:hex).and_return('abcd') + setup_files + end + + after do + FileUtils.rm_rf(storage_path) + end + + context 'normal run' do + before do + described_class.import(project: build(:project), archive_file: '', shared: shared) + end + + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes evil symlinks in root folder' do + expect(File.exist?(evil_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end + + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end + + it 'creates the file in the right subfolder' do + expect(shared.export_path).to include('test/abcd') + end + end + + context 'error' do + before do + allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError) + described_class.import(project: build(:project), archive_file: '', shared: shared) + end + + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end + + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end + end + + def setup_files + FileUtils.mkdir_p("#{shared.export_path}/subfolder/") + FileUtils.touch(valid_file) + FileUtils.ln_s(valid_file, symlink_file) + FileUtils.ln_s(valid_file, subfolder_symlink_file) + FileUtils.ln_s(valid_file, hidden_symlink_file) + FileUtils.ln_s(valid_file, evil_symlink_file) + end +end diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb index 265937f899e..78fccdf1dfc 100644 --- a/spec/lib/gitlab/import_export/file_importer_spec.rb +++ b/spec/lib/gitlab/import_export/file_importer_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::ImportExport::FileImporter do context 'normal run' do before do - described_class.import(archive_file: '', shared: shared) + described_class.import(project: nil, archive_file: '', shared: shared) end it 'removes symlinks in root folder' do @@ -55,7 +55,7 @@ describe Gitlab::ImportExport::FileImporter do context 'error' do before do allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError) - described_class.import(archive_file: '', shared: shared) + described_class.import(project: nil, archive_file: '', shared: shared) end it 'removes symlinks in root folder' do diff --git a/spec/lib/gitlab/import_export/importer_object_storage_spec.rb b/spec/lib/gitlab/import_export/importer_object_storage_spec.rb new file mode 100644 index 00000000000..24a994b3611 --- /dev/null +++ b/spec/lib/gitlab/import_export/importer_object_storage_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::Importer do + let(:user) { create(:user) } + let(:test_path) { "#{Dir.tmpdir}/importer_spec" } + let(:shared) { project.import_export_shared } + let(:project) { create(:project) } + let(:import_file) { fixture_file_upload('spec/features/projects/import_export/test_project_export.tar.gz') } + + subject(:importer) { described_class.new(project) } + + before do + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path) + allow_any_instance_of(Gitlab::ImportExport::FileImporter).to receive(:remove_import_file) + stub_feature_flags(import_export_object_storage: true) + stub_uploads_object_storage(FileUploader) + + FileUtils.mkdir_p(shared.export_path) + ImportExportUpload.create(project: project, import_file: import_file) + end + + after do + FileUtils.rm_rf(test_path) + end + + describe '#execute' do + it 'succeeds' do + importer.execute + + expect(shared.errors).to be_empty + end + + it 'extracts the archive' do + expect(Gitlab::ImportExport::FileImporter).to receive(:import).and_call_original + + importer.execute + end + + it 'checks the version' do + expect(Gitlab::ImportExport::VersionChecker).to receive(:check!).and_call_original + + importer.execute + end + + context 'all restores are executed' do + [ + Gitlab::ImportExport::AvatarRestorer, + Gitlab::ImportExport::RepoRestorer, + Gitlab::ImportExport::WikiRestorer, + Gitlab::ImportExport::UploadsRestorer, + Gitlab::ImportExport::LfsRestorer, + Gitlab::ImportExport::StatisticsRestorer + ].each do |restorer| + it "calls the #{restorer}" do + fake_restorer = double(restorer.to_s) + + expect(fake_restorer).to receive(:restore).and_return(true).at_least(1) + expect(restorer).to receive(:new).and_return(fake_restorer).at_least(1) + + importer.execute + end + end + + it 'restores the ProjectTree' do + expect(Gitlab::ImportExport::ProjectTreeRestorer).to receive(:new).and_call_original + + importer.execute + end + + it 'removes the import file' do + expect(importer).to receive(:remove_import_file).and_call_original + + importer.execute + + expect(project.import_export_upload.import_file&.file).to be_nil + end + end + + context 'when project successfully restored' do + let!(:existing_project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace, name: 'whatever', path: 'whatever') } + + before do + restorers = double(:restorers, all?: true) + + allow(subject).to receive(:import_file).and_return(true) + allow(subject).to receive(:check_version!).and_return(true) + allow(subject).to receive(:restorers).and_return(restorers) + allow(project).to receive(:import_data).and_return(double(data: { 'original_path' => existing_project.path })) + end + + context 'when import_data' do + context 'has original_path' do + it 'overwrites existing project' do + expect_any_instance_of(::Projects::OverwriteProjectService).to receive(:execute).with(existing_project) + + subject.execute + end + end + + context 'has not original_path' do + before do + allow(project).to receive(:import_data).and_return(double(data: {})) + end + + it 'does not call the overwrite service' do + expect_any_instance_of(::Projects::OverwriteProjectService).not_to receive(:execute).with(existing_project) + + subject.execute + end + end + end + end + end +end diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb index c074e61da26..f07946824c4 100644 --- a/spec/lib/gitlab/import_export/importer_spec.rb +++ b/spec/lib/gitlab/import_export/importer_spec.rb @@ -10,9 +10,10 @@ describe Gitlab::ImportExport::Importer do before do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(test_path) + allow_any_instance_of(Gitlab::ImportExport::FileImporter).to receive(:remove_import_file) + FileUtils.mkdir_p(shared.export_path) FileUtils.cp(Rails.root.join('spec/features/projects/import_export/test_project_export.tar.gz'), test_path) - allow(subject).to receive(:remove_import_file) end after do @@ -69,7 +70,7 @@ describe Gitlab::ImportExport::Importer do let(:project) { create(:project, namespace: user.namespace, name: 'whatever', path: 'whatever') } before do - restorers = double + restorers = double(:restorers, all?: true) allow(subject).to receive(:import_file).and_return(true) allow(subject).to receive(:check_version!).and_return(true) diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index 25c6fa3b9a3..cd456a45287 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -14,7 +14,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do let(:commands) do <<~EOS helm init --client-only >/dev/null - helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm install #{application.chart} --name #{application.name} --version #{application.version} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null EOS end end @@ -42,7 +42,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do <<~EOS helm init --client-only >/dev/null helm repo add #{application.name} #{application.repository} - helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm install #{application.chart} --name #{application.name} --version #{application.version} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null EOS end end @@ -56,7 +56,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do <<~EOS helm init --client-only >/dev/null helm repo add #{application.name} #{application.repository} - helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm install #{application.chart} --name #{application.name} --version #{application.version} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null EOS end end |