From 2c89e169769ead722394a79ed67fcd08e96863dd Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 12 Feb 2020 15:09:37 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .../projects/alerting/notify_service_spec.rb | 34 ++++ .../cleanup_tags_service_spec.rb | 4 +- .../delete_tags_service_spec.rb | 214 +++++++++++++++------ spec/services/projects/lsif_data_service_spec.rb | 29 ++- 4 files changed, 215 insertions(+), 66 deletions(-) create mode 100644 spec/services/projects/alerting/notify_service_spec.rb (limited to 'spec/services/projects') diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb new file mode 100644 index 00000000000..efd168a0a8a --- /dev/null +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::Alerting::NotifyService do + let_it_be(:project, reload: true) { create(:project) } + + shared_examples 'does not process incident issues' do |http_status:| + it 'does not process issues' do + expect(IncidentManagement::ProcessAlertWorker) + .not_to receive(:perform_async) + + expect(subject.status).to eq(:error) + expect(subject.http_status).to eq(http_status) + end + end + + describe '#execute' do + let(:token) { 'invalid-token' } + let(:starts_at) { Time.now.change(usec: 0) } + let(:service) { described_class.new(project, nil, payload) } + let(:payload_raw) do + { + 'title' => 'alert title', + 'start_time' => starts_at.rfc3339 + } + end + let(:payload) { ActionController::Parameters.new(payload_raw).permit! } + + subject { service.execute(token) } + + it_behaves_like 'does not process incident issues', http_status: 403 + end +end diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb index 78b969c8a0e..cd4d1e3fe67 100644 --- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb +++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb @@ -41,7 +41,7 @@ describe Projects::ContainerRepository::CleanupTagsService do let(:params) { {} } it 'does not remove anything' do - expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag) + expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_digest) is_expected.to include(status: :success, deleted: []) end @@ -156,7 +156,7 @@ describe Projects::ContainerRepository::CleanupTagsService do def expect_delete(digest) expect_any_instance_of(ContainerRegistry::Client) - .to receive(:delete_repository_tag) + .to receive(:delete_repository_tag_by_digest) .with(repository.path, digest) { true } end end 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 decbbb7597f..e17e4b6f7c9 100644 --- a/spec/services/projects/container_repository/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb @@ -18,10 +18,6 @@ describe Projects::ContainerRepository::DeleteTagsService do stub_container_registry_tags( repository: repository.path, tags: %w(latest A Ba Bb C D E)) - - stub_tag_digest('latest', 'sha256:configA') - stub_tag_digest('A', 'sha256:configA') - stub_tag_digest('Ba', 'sha256:configB') end describe '#execute' do @@ -38,82 +34,178 @@ describe Projects::ContainerRepository::DeleteTagsService do project.add_developer(user) end - context 'when no params are specified' do - let(:params) { {} } + context 'when the registry supports fast delete' do + context 'and the feature is enabled' do + let_it_be(:project) { create(:project, :private) } + let_it_be(:repository) { create(:container_repository, :root, project: project) } - it 'does not remove anything' do - expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag) + before do + allow(repository.client).to receive(:supports_tag_delete?).and_return(true) + end - is_expected.to include(status: :error) - end - end + context 'with tags to delete' do + let_it_be(:tags) { %w[A Ba] } - context 'with empty tags' do - let(:tags) { [] } + it 'deletes the tags by name' do + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/A") + .to_return(status: 200, body: "") - it 'does not remove anything' do - expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag) + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/Ba") + .to_return(status: 200, body: "") - is_expected.to include(status: :error) - end - end + expect_delete_tag_by_name('A') + expect_delete_tag_by_name('Ba') + + is_expected.to include(status: :success) + end + + it 'succeeds when tag delete returns 404' do + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/A") + .to_return(status: 200, body: "") + + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/Ba") + .to_return(status: 404, body: "") + + is_expected.to include(status: :success) + end + + context 'with failures' do + context 'when the delete request fails' do + before do + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/A") + .to_return(status: 500, body: "") + + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/Ba") + .to_return(status: 500, body: "") + end - context 'with tags to delete' do - let(:tags) { %w[A Ba] } + it { is_expected.to include(status: :error) } + end + end + end + + context 'when no params are specified' do + let_it_be(:params) { {} } + + it 'does not remove anything' do + expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_name) + + is_expected.to include(status: :error) + end + end - it 'deletes the tags using a dummy image' do - stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') + context 'with empty tags' do + let_it_be(:tags) { [] } - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") - .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + it 'does not remove anything' do + expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_name) - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") - .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + is_expected.to include(status: :error) + end + end + end + context 'and the feature is disabled' do + before do + stub_feature_flags(container_registry_fast_tag_delete: false) + end - expect_delete_tag('sha256:dummy') + it 'fallbacks to slow delete' do + expect(service).not_to receive(:fast_delete) + expect(service).to receive(:slow_delete).with(repository, tags) - is_expected.to include(status: :success) + subject + end end + end + context 'when the registry does not support fast delete' do + let_it_be(:project) { create(:project, :private) } + let_it_be(:repository) { create(:container_repository, :root, project: project) } - it 'succedes when tag delete returns 404' do - stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') + before do + stub_tag_digest('latest', 'sha256:configA') + stub_tag_digest('A', 'sha256:configA') + stub_tag_digest('Ba', 'sha256:configB') - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") - .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + allow(repository.client).to receive(:supports_tag_delete?).and_return(false) + end - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") - .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + context 'when no params are specified' do + let_it_be(:params) { {} } - stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/manifests/sha256:dummy") - .to_return(status: 404, body: "", headers: {}) + it 'does not remove anything' do + expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_digest) - is_expected.to include(status: :success) + is_expected.to include(status: :error) + end end - context 'with failures' do - context 'when the dummy manifest generation fails' do - before do - stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3', success: false) - end + context 'with empty tags' do + let_it_be(:tags) { [] } + + it 'does not remove anything' do + expect_any_instance_of(ContainerRegistry::Client).not_to receive(:delete_repository_tag_by_digest) + + is_expected.to include(status: :error) + end + end + + context 'with tags to delete' do + let_it_be(:tags) { %w[A Ba] } - it { is_expected.to include(status: :error) } + it 'deletes the tags using a dummy image' do + stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') + + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") + .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") + .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + + expect_delete_tag_by_digest('sha256:dummy') + + is_expected.to include(status: :success) end - context 'when updating the tags fails' do - before do - stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') + it 'succeeds when tag delete returns 404' do + stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") - .to_return(status: 500, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") + .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) - stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") - .to_return(status: 500, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") + .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/manifests/sha256:dummy") + .to_return(status: 404, body: "", headers: {}) + + is_expected.to include(status: :success) + end - stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/manifests/sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3") - .to_return(status: 200, body: "", headers: {}) + context 'with failures' do + context 'when the dummy manifest generation fails' do + before do + stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3', success: false) + end + + it { is_expected.to include(status: :error) } end - it { is_expected.to include(status: :error) } + context 'when updating the tags fails' do + before do + stub_upload("{\n \"config\": {\n }\n}", 'sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3') + + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/A") + .to_return(status: 500, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + + stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/Ba") + .to_return(status: 500, body: "", headers: { 'docker-content-digest' => 'sha256:dummy' }) + + stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/manifests/sha256:4435000728ee66e6a80e55637fc22725c256b61de344a2ecdeaac6bdb36e8bc3") + .to_return(status: 200, body: "", headers: {}) + end + + it { is_expected.to include(status: :error) } + end end end end @@ -141,9 +233,21 @@ describe Projects::ContainerRepository::DeleteTagsService do .with(repository.path, content, digest) { double(success?: success ) } end - def expect_delete_tag(digest) + def expect_delete_tag_by_digest(digest) expect_any_instance_of(ContainerRegistry::Client) - .to receive(:delete_repository_tag) + .to receive(:delete_repository_tag_by_digest) .with(repository.path, digest) { true } + + expect_any_instance_of(ContainerRegistry::Client) + .not_to receive(:delete_repository_tag_by_name) + end + + def expect_delete_tag_by_name(name) + expect_any_instance_of(ContainerRegistry::Client) + .to receive(:delete_repository_tag_by_name) + .with(repository.path, name) { true } + + expect_any_instance_of(ContainerRegistry::Client) + .not_to receive(:delete_repository_tag_by_digest) end end diff --git a/spec/services/projects/lsif_data_service_spec.rb b/spec/services/projects/lsif_data_service_spec.rb index b3c37c01c4d..29a99a96c41 100644 --- a/spec/services/projects/lsif_data_service_spec.rb +++ b/spec/services/projects/lsif_data_service_spec.rb @@ -23,43 +23,51 @@ describe Projects::LsifDataService do end context 'for main.go' do + let(:path_prefix) { "/#{project.full_path}/-/blob/#{commit_id}" } + it 'returns lsif ranges for the file' do expect(service.execute).to eq([ { end_char: 9, end_line: 6, start_char: 5, - start_line: 6 + start_line: 6, + definition_url: "#{path_prefix}/main.go#L7" }, { end_char: 36, end_line: 3, start_char: 1, - start_line: 3 + start_line: 3, + definition_url: "#{path_prefix}/main.go#L4" }, { end_char: 12, end_line: 7, start_char: 1, - start_line: 7 + start_line: 7, + definition_url: "#{path_prefix}/main.go#L4" }, { end_char: 20, end_line: 7, start_char: 13, - start_line: 7 + start_line: 7, + definition_url: "#{path_prefix}/morestrings/reverse.go#L11" }, { end_char: 12, end_line: 8, start_char: 1, - start_line: 8 + start_line: 8, + definition_url: "#{path_prefix}/main.go#L4" }, { end_char: 18, end_line: 8, start_char: 13, - start_line: 8 + start_line: 8, + definition_url: "#{path_prefix}/morestrings/reverse.go#L5" } ]) end @@ -73,7 +81,8 @@ describe Projects::LsifDataService do end_char: 2, end_line: 11, start_char: 1, - start_line: 11 + start_line: 11, + definition_url: "/#{project.full_path}/-/blob/#{commit_id}/morestrings/reverse.go#L12" }) end end @@ -87,7 +96,7 @@ describe Projects::LsifDataService do end end - describe '#doc_id_from' do + describe '#doc_id' do context 'when the passed path matches multiple files' do let(:path) { 'check/main.go' } let(:docs) do @@ -100,7 +109,9 @@ describe Projects::LsifDataService do end it 'fetches the document with the shortest absolute path' do - expect(service.__send__(:doc_id_from, docs)).to eq(3) + service.instance_variable_set(:@docs, docs) + + expect(service.__send__(:doc_id)).to eq(3) end end end -- cgit v1.2.3