diff options
Diffstat (limited to 'spec/services/projects')
10 files changed, 273 insertions, 66 deletions
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb index 809b12910a1..4674f614cf1 100644 --- a/spec/services/projects/alerting/notify_service_spec.rb +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -34,13 +34,11 @@ RSpec.describe Projects::Alerting::NotifyService do let(:payload) { ActionController::Parameters.new(payload_raw).permit! } - subject { service.execute(token) } - - context 'with activated Alerts Service' do - let_it_be_with_reload(:alerts_service) { create(:alerts_service, project: project) } + subject { service.execute(token, nil) } + shared_examples 'notifcations are handled correctly' do context 'with valid token' do - let(:token) { alerts_service.token } + let(:token) { integration.token } let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled, auto_close_incident?: auto_close_enabled) } let(:email_enabled) { false } let(:issue_enabled) { false } @@ -131,6 +129,12 @@ RSpec.describe Projects::Alerting::NotifyService do it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') } it { expect { subject }.to change(ResourceStateEvent, :count).by(1) } end + + context 'with issue enabled' do + let(:issue_enabled) { true } + + it_behaves_like 'does not process incident issues' + end end end @@ -197,7 +201,7 @@ RSpec.describe Projects::Alerting::NotifyService do it 'creates a system note corresponding to alert creation' do expect { subject }.to change(Note, :count).by(1) - expect(Note.last.note).to include('Generic Alert Endpoint') + expect(Note.last.note).to include(source) end end end @@ -247,10 +251,20 @@ RSpec.describe Projects::Alerting::NotifyService do it_behaves_like 'does not process incident issues due to error', http_status: :unauthorized it_behaves_like 'does not an create alert management alert' end + end + + context 'with an HTTP Integration' do + let_it_be_with_reload(:integration) { create(:alert_management_http_integration, project: project) } + + subject { service.execute(token, integration) } + + it_behaves_like 'notifcations are handled correctly' do + let(:source) { integration.name } + end - context 'with deactivated Alerts Service' do + context 'with deactivated HTTP Integration' do before do - alerts_service.update!(active: false) + integration.update!(active: false) end it_behaves_like 'does not process incident issues due to error', http_status: :forbidden diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb index aff1aa41091..ef7741c2d0f 100644 --- a/spec/services/projects/autocomplete_service_spec.rb +++ b/spec/services/projects/autocomplete_service_spec.rb @@ -79,14 +79,28 @@ RSpec.describe Projects::AutocompleteService do expect(issues.count).to eq 3 end - it 'lists all project issues for admin' do - autocomplete = described_class.new(project, admin) - issues = autocomplete.issues.map(&:iid) + context 'when admin mode is enabled', :enable_admin_mode do + it 'lists all project issues for admin', :enable_admin_mode do + autocomplete = described_class.new(project, admin) + issues = autocomplete.issues.map(&:iid) + + expect(issues).to include issue.iid + expect(issues).to include security_issue_1.iid + expect(issues).to include security_issue_2.iid + expect(issues.count).to eq 3 + end + end - expect(issues).to include issue.iid - expect(issues).to include security_issue_1.iid - expect(issues).to include security_issue_2.iid - expect(issues.count).to eq 3 + context 'when admin mode is disabled' do + it 'does not list project confidential issues for admin' do + autocomplete = described_class.new(project, admin) + issues = autocomplete.issues.map(&:iid) + + expect(issues).to include issue.iid + expect(issues).not_to include security_issue_1.iid + expect(issues).not_to include security_issue_2.iid + expect(issues.count).to eq 1 + end end end end diff --git a/spec/services/projects/cleanup_service_spec.rb b/spec/services/projects/cleanup_service_spec.rb index 7c28b729e84..6fd29813d98 100644 --- a/spec/services/projects/cleanup_service_spec.rb +++ b/spec/services/projects/cleanup_service_spec.rb @@ -3,14 +3,84 @@ require 'spec_helper' RSpec.describe Projects::CleanupService do - let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) } - let(:object_map) { project.bfg_object_map } + subject(:service) { described_class.new(project) } - let(:cleaner) { service.__send__(:repository_cleaner) } + describe '.enqueue' do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } - subject(:service) { described_class.new(project) } + let(:object_map_file) { fixture_file_upload('spec/fixtures/bfg_object_map.txt') } + + subject(:enqueue) { described_class.enqueue(project, user, object_map_file) } + + it 'makes the repository read-only' do + expect { enqueue } + .to change(project, :repository_read_only?) + .from(false) + .to(true) + end + + it 'sets the bfg_object_map of the project' do + enqueue + + expect(project.bfg_object_map.read).to eq(object_map_file.read) + end + + it 'enqueues a RepositoryCleanupWorker' do + enqueue + + expect(RepositoryCleanupWorker.jobs.count).to eq(1) + end + + it 'returns success' do + expect(enqueue[:status]).to eq(:success) + end + + it 'returns an error if making the repository read-only fails' do + project.set_repository_read_only! + + expect(enqueue[:status]).to eq(:error) + end + + it 'returns an error if updating the project fails' do + expect_next_instance_of(Projects::UpdateService) do |service| + expect(service).to receive(:execute).and_return(status: :error) + end + + expect(enqueue[:status]).to eq(:error) + expect(project.reload.repository_read_only?).to be_falsy + end + end + + describe '.cleanup_after' do + let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) } + + subject(:cleanup_after) { described_class.cleanup_after(project) } + + before do + project.set_repository_read_only! + end + + it 'sets the repository read-write' do + expect { cleanup_after }.to change(project, :repository_read_only?).from(true).to(false) + end + + it 'removes the BFG object map' do + cleanup_after + + expect(project.bfg_object_map).not_to be_exist + end + end describe '#execute' do + let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) } + let(:object_map) { project.bfg_object_map } + let(:cleaner) { service.__send__(:repository_cleaner) } + + before do + project.set_repository_read_only! + end + it 'runs the apply_bfg_object_map_stream gitaly RPC' do expect(cleaner).to receive(:apply_bfg_object_map_stream).with(kind_of(IO)) @@ -19,7 +89,7 @@ RSpec.describe Projects::CleanupService do it 'runs garbage collection on the repository' do expect_next_instance_of(GitGarbageCollectWorker) do |worker| - expect(worker).to receive(:perform).with(project.id, :gc, "project_cleanup:gc:#{project.id}") + expect(worker).to receive(:perform).with(project.id, :prune, "project_cleanup:gc:#{project.id}") end service.execute @@ -37,6 +107,13 @@ RSpec.describe Projects::CleanupService do expect(object_map.exists?).to be_falsy end + it 'makes the repository read-write again' do + expect { service.execute } + .to change(project, :repository_read_only?) + .from(true) + .to(false) + end + context 'with a tainted merge request diff' do let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:diff) { merge_request.merge_request_diff } diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb index c3ae26b1f05..a012ec29be5 100644 --- a/spec/services/projects/container_repository/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb @@ -27,13 +27,17 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do end end - RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags'| + RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}| it 'logs an error message' do - expect(service).to receive(:log_error).with( - service_class: 'Projects::ContainerRepository::DeleteTagsService', - message: message, - container_repository_id: repository.id - ) + log_data = { + service_class: 'Projects::ContainerRepository::DeleteTagsService', + message: message, + container_repository_id: repository.id + } + + log_data.merge!(extra_log) if extra_log.any? + + expect(service).to receive(:log_error).with(log_data) subject end @@ -115,7 +119,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do it { is_expected.to include(status: :error, message: 'timeout while deleting tags') } - it_behaves_like 'logging an error response', message: 'timeout while deleting tags' + it_behaves_like 'logging an error response', message: 'timeout while deleting tags', extra_log: { deleted_tags_count: 0 } end end end diff --git a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb index 3bbcec8775e..988971171fc 100644 --- a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb @@ -67,7 +67,7 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do stub_delete_reference_requests('A' => 200) end - it { is_expected.to include(status: :error, message: 'timeout while deleting tags') } + it { is_expected.to eq(status: :error, message: 'timeout while deleting tags', deleted: ['A']) } it 'tracks the exception' do expect(::Gitlab::ErrorTracking) diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index d959cc87901..6c0e6654622 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -72,14 +72,25 @@ RSpec.describe Projects::CreateService, '#execute' do end context "admin creates project with other user's namespace_id" do - it 'sets the correct permissions' do - admin = create(:admin) - project = create_project(admin, opts) + context 'when admin mode is enabled', :enable_admin_mode do + it 'sets the correct permissions' do + admin = create(:admin) + project = create_project(admin, opts) - expect(project).to be_persisted - expect(project.owner).to eq(user) - expect(project.team.maintainers).to contain_exactly(user) - expect(project.namespace).to eq(user.namespace) + expect(project).to be_persisted + expect(project.owner).to eq(user) + expect(project.team.maintainers).to contain_exactly(user) + expect(project.namespace).to eq(user.namespace) + end + end + + context 'when admin mode is disabled' do + it 'is not allowed' do + admin = create(:admin) + project = create_project(admin, opts) + + expect(project).not_to be_persisted + end end end @@ -336,7 +347,15 @@ RSpec.describe Projects::CreateService, '#execute' do ) end - it 'allows a restricted visibility level for admins' do + it 'does not allow a restricted visibility level for admins when admin mode is disabled' do + admin = create(:admin) + project = create_project(admin, opts) + + expect(project.errors.any?).to be(true) + expect(project.saved?).to be_falsey + end + + it 'allows a restricted visibility level for admins when admin mode is enabled', :enable_admin_mode do admin = create(:admin) project = create_project(admin, opts) diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb index cfe8e863223..1b829df6e6a 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb @@ -241,18 +241,6 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do context 'and first fragments are the same' do let(:lfs_content) { existing_lfs_object.file.read } - context 'when lfs_link_existing_object feature flag disabled' do - before do - stub_feature_flags(lfs_link_existing_object: false) - end - - it 'does not call link_existing_lfs_object!' do - expect(subject).not_to receive(:link_existing_lfs_object!) - - subject.execute - end - end - it 'returns success' do expect(subject.execute).to eq({ status: :success }) end diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index d3eb84a3137..d2c6c0eb971 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -27,7 +27,7 @@ RSpec.describe Projects::UpdatePagesService do context 'for new artifacts' do context "for a valid job" do - let!(:artifacts_archive) { create(:ci_job_artifact, file: file, job: build) } + let!(:artifacts_archive) { create(:ci_job_artifact, :correct_checksum, file: file, job: build) } before do create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build) @@ -66,9 +66,45 @@ RSpec.describe Projects::UpdatePagesService do expect(deployment.size).to eq(file.size) expect(deployment.file).to be + expect(deployment.file_count).to eq(3) + expect(deployment.file_sha256).to eq(artifacts_archive.file_sha256) expect(project.pages_metadatum.reload.pages_deployment_id).to eq(deployment.id) end + it 'does not fail if pages_metadata is absent' do + project.pages_metadatum.destroy! + project.reload + + expect do + expect(execute).to eq(:success) + end.to change { project.pages_deployments.count }.by(1) + + expect(project.pages_metadatum.reload.pages_deployment).to eq(project.pages_deployments.last) + end + + context 'when there is an old pages deployment' do + let!(:old_deployment_from_another_project) { create(:pages_deployment) } + let!(:old_deployment) { create(:pages_deployment, project: project) } + + it 'schedules a destruction of older deployments' do + expect(DestroyPagesDeploymentsWorker).to( + receive(:perform_in).with(described_class::OLD_DEPLOYMENTS_DESTRUCTION_DELAY, + project.id, + instance_of(Integer)) + ) + + execute + end + + it 'removes older deployments', :sidekiq_inline do + expect do + execute + end.not_to change { PagesDeployment.count } # it creates one and deletes one + + expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil + end + end + it 'does not create deployment when zip_pages_deployments feature flag is disabled' do stub_feature_flags(zip_pages_deployments: false) @@ -188,6 +224,25 @@ RSpec.describe Projects::UpdatePagesService do end end + # this situation should never happen in real life because all new archives have sha256 + # and we only use new archives + # this test is here just to clarify that this behavior is intentional + context 'when artifacts archive does not have sha256' do + let!(:artifacts_archive) { create(:ci_job_artifact, file: file, job: build) } + + before do + create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build) + + build.reload + end + + it 'fails with exception raised' do + expect do + execute + end.to raise_error("Validation failed: File sha256 can't be blank") + end + end + it 'fails to remove project pages when no pages is deployed' do expect(PagesWorker).not_to receive(:perform_in) expect(project.pages_deployed?).to be_falsey @@ -210,7 +265,7 @@ RSpec.describe Projects::UpdatePagesService do file = fixture_file_upload('spec/fixtures/pages.zip') metafile = fixture_file_upload('spec/fixtures/pages.zip.meta') - create(:ci_job_artifact, :archive, file: file, job: build) + create(:ci_job_artifact, :archive, :correct_checksum, file: file, job: build) create(:ci_job_artifact, :metadata, file: metafile, job: build) allow(build).to receive(:artifacts_metadata_entry) diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb index 0fcd14f3bc9..123f604e7a4 100644 --- a/spec/services/projects/update_repository_storage_service_spec.rb +++ b/spec/services/projects/update_repository_storage_service_spec.rb @@ -168,6 +168,24 @@ RSpec.describe Projects::UpdateRepositoryStorageService do end end + context 'project with no repositories' do + let(:project) { create(:project) } + let(:repository_storage_move) { create(:project_repository_storage_move, :scheduled, project: project, destination_storage_name: 'test_second_storage') } + + it 'updates the database' do + allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original + allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid) + + result = subject.execute + project.reload + + expect(result).to be_success + expect(project).not_to be_repository_read_only + expect(project.repository_storage).to eq('test_second_storage') + expect(project.project_repository.shard_name).to eq('test_second_storage') + end + end + context 'with wiki repository' do include_examples 'moves repository to another storage', 'wiki' do let(:project) { create(:project, :repository, wiki_enabled: true) } diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 989426fde8b..760cd85bf71 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -127,11 +127,22 @@ RSpec.describe Projects::UpdateService do end context 'when updated by an admin' do - it 'updates the project to public' do - result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC) + context 'when admin mode is enabled', :enable_admin_mode do + it 'updates the project to public' do + result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC) - expect(result).to eq({ status: :success }) - expect(project).to be_public + expect(result).to eq({ status: :success }) + expect(project).to be_public + end + end + + context 'when admin mode is disabled' do + it 'does not update the project to public' do + result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC) + + expect(result).to eq({ status: :error, message: 'New visibility level not allowed!' }) + expect(project).to be_private + end end end end @@ -144,7 +155,7 @@ RSpec.describe Projects::UpdateService do project.update!(namespace: group, visibility_level: group.visibility_level) end - it 'does not update project visibility level' do + it 'does not update project visibility level even if admin', :enable_admin_mode do result = update_project(project, admin, visibility_level: Gitlab::VisibilityLevel::PUBLIC) expect(result).to eq({ status: :error, message: 'Visibility level public is not allowed in a internal group.' }) @@ -181,6 +192,7 @@ RSpec.describe Projects::UpdateService do describe 'when updating project that has forks' do let(:project) { create(:project, :internal) } + let(:user) { project.owner } let(:forked_project) { fork_project(project) } context 'and unlink forks feature flag is off' do @@ -194,7 +206,7 @@ RSpec.describe Projects::UpdateService do expect(project).to be_internal expect(forked_project).to be_internal - expect(update_project(project, admin, opts)).to eq({ status: :success }) + expect(update_project(project, user, opts)).to eq({ status: :success }) expect(project).to be_private expect(forked_project.reload).to be_private @@ -206,7 +218,7 @@ RSpec.describe Projects::UpdateService do expect(project).to be_internal expect(forked_project).to be_internal - expect(update_project(project, admin, opts)).to eq({ status: :success }) + expect(update_project(project, user, opts)).to eq({ status: :success }) expect(project).to be_public expect(forked_project.reload).to be_internal @@ -220,7 +232,7 @@ RSpec.describe Projects::UpdateService do expect(project).to be_internal expect(forked_project).to be_internal - expect(update_project(project, admin, opts)).to eq({ status: :success }) + expect(update_project(project, user, opts)).to eq({ status: :success }) expect(project).to be_private expect(forked_project.reload).to be_internal @@ -576,15 +588,21 @@ RSpec.describe Projects::UpdateService do context 'authenticated as admin' do let(:user) { create(:admin) } - it 'schedules the transfer of the repository to the new storage and locks the project' do - update_project(project, admin, opts) + context 'when admin mode is enabled', :enable_admin_mode do + it 'schedules the transfer of the repository to the new storage and locks the project' do + update_project(project, admin, opts) - expect(project).to be_repository_read_only - expect(project.repository_storage_moves.last).to have_attributes( - state: ::ProjectRepositoryStorageMove.state_machines[:state].states[:scheduled].value, - source_storage_name: 'default', - destination_storage_name: 'test_second_storage' - ) + expect(project).to be_repository_read_only + expect(project.repository_storage_moves.last).to have_attributes( + state: ::ProjectRepositoryStorageMove.state_machines[:state].states[:scheduled].value, + source_storage_name: 'default', + destination_storage_name: 'test_second_storage' + ) + end + end + + context 'when admin mode is disabled' do + it_behaves_like 'the transfer was not scheduled' end context 'the repository is read-only' do |