Commit b9416ca7 authored by Michael Eddington's avatar Michael Eddington Committed by Sean McGivern

Add api_fuzzing_reports operation to MR

parent 84fdbbe8
......@@ -23,7 +23,7 @@ module EE
feature_category :code_review, [:delete_description_version, :description_diff]
feature_category :container_scanning, [:container_scanning_reports]
feature_category :dependency_scanning, [:dependency_scanning_reports]
feature_category :fuzz_testing, [:coverage_fuzzing_reports]
feature_category :fuzz_testing, [:coverage_fuzzing_reports, :api_fuzzing_reports]
feature_category :license_compliance, [:license_scanning_reports]
feature_category :static_application_security_testing, [:sast_reports]
feature_category :secret_detection, [:secret_detection_reports]
......
......@@ -248,6 +248,10 @@ module EE
compare_reports(::Ci::CompareSecurityReportsService, current_user, 'coverage_fuzzing')
end
def has_api_fuzzing_reports?
!!actual_head_pipeline&.has_reports?(::Ci::JobArtifact.api_fuzzing_reports)
end
def compare_api_fuzzing_reports(current_user)
return missing_report_error('api fuzzing') unless has_api_fuzzing_reports?
......
......@@ -12,6 +12,7 @@ resources :merge_requests, only: [], constraints: { id: /\d+/ } do
get :secret_detection_reports
get :dast_reports
get :coverage_fuzzing_reports
get :api_fuzzing_reports
post :rebase
end
......
......@@ -659,6 +659,79 @@ RSpec.describe Projects::MergeRequestsController do
it_behaves_like 'authorize read pipeline'
end
describe 'GET #api_fuzzing_reports' do
let(:merge_request) { create(:ee_merge_request, :with_api_fuzzing_reports, source_project: project, author: create(:user)) }
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.iid
}
end
subject { get :api_fuzzing_reports, params: params, format: :json }
before do
allow_any_instance_of(::MergeRequest).to receive(:compare_reports)
.with(::Ci::CompareSecurityReportsService, viewer, 'api_fuzzing').and_return(comparison_status)
end
it_behaves_like 'pending pipeline response'
context 'when comparison is being processed' do
let(:comparison_status) { { status: :parsing } }
it 'sends polling interval' do
expect(::Gitlab::PollingInterval).to receive(:set_header)
subject
end
it 'returns 204 HTTP status' do
subject
expect(response).to have_gitlab_http_status(:no_content)
end
end
context 'when comparison is done' do
let(:comparison_status) { { status: :parsed, data: { added: [], fixed: [], existing: [] } } }
it 'does not send polling interval' do
expect(::Gitlab::PollingInterval).not_to receive(:set_header)
subject
end
it 'returns 200 HTTP status' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq({ "added" => [], "fixed" => [], "existing" => [] })
end
end
context 'when user created corrupted fuzzing reports' do
let(:comparison_status) { { status: :error, status_reason: 'Failed to parse api fuzzing reports' } }
it 'does not send polling interval' do
expect(::Gitlab::PollingInterval).not_to receive(:set_header)
subject
end
it 'returns 400 HTTP status' do
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to eq({ 'status_reason' => 'Failed to parse api fuzzing reports' })
end
end
it_behaves_like 'authorize read pipeline'
end
describe 'GET #secret_detection_reports' do
let(:merge_request) { create(:ee_merge_request, :with_secret_detection_reports, source_project: project, author: create(:user)) }
let(:params) do
......
......@@ -157,6 +157,18 @@ FactoryBot.define do
end
end
trait :with_api_fuzzing_reports do
after(:build) do |merge_request|
merge_request.head_pipeline = build(
:ee_ci_pipeline,
:success,
:with_api_fuzzing_report,
project: merge_request.source_project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha)
end
end
trait :with_dast_reports do
after(:build) do |merge_request|
merge_request.head_pipeline = build(
......
......@@ -115,6 +115,22 @@ RSpec.describe Ci::JobArtifact do
end
end
describe '.api_fuzzing_reports' do
subject { Ci::JobArtifact.api_fuzzing }
context 'when there is a metrics report' do
let!(:artifact) { create(:ee_ci_job_artifact, :api_fuzzing) }
it { is_expected.to eq([artifact]) }
end
context 'when there is no coverage fuzzing reports' do
let!(:artifact) { create(:ee_ci_job_artifact, :trace) }
it { is_expected.to be_empty }
end
end
describe '.associated_file_types_for' do
using RSpec::Parameterized::TableSyntax
......
......@@ -175,6 +175,7 @@ RSpec.describe MergeRequest do
:license_scanning | :with_license_management_reports | :license_scanning
:license_scanning | :with_license_scanning_reports | :license_scanning
:coverage_fuzzing | :with_coverage_fuzzing_reports | :coverage_fuzzing
:api_fuzzing | :with_api_fuzzing_reports | :api_fuzzing
end
with_them do
......@@ -403,6 +404,28 @@ RSpec.describe MergeRequest do
end
end
describe '#has_api_fuzzing_reports?' do
subject { merge_request.has_api_fuzzing_reports? }
let_it_be(:project) { create(:project, :repository) }
before do
stub_licensed_features(api_fuzzing: true)
end
context 'when head pipeline has coverage fuzzing reports' do
let(:merge_request) { create(:ee_merge_request, :with_api_fuzzing_reports, source_project: project) }
it { is_expected.to be_truthy }
end
context 'when head pipeline does not have coverage fuzzing reports' do
let(:merge_request) { create(:ee_merge_request, source_project: project) }
it { is_expected.to be_falsey }
end
end
describe '#calculate_reactive_cache with current_user' do
let(:project) { create(:project, :repository) }
let(:current_user) { project.users.take }
......@@ -854,6 +877,66 @@ RSpec.describe MergeRequest do
end
end
describe '#compare_api_fuzzing_reports' do
subject { merge_request.compare_api_fuzzing_reports(current_user) }
let_it_be(:project) { create(:project, :repository) }
let(:current_user) { project.users.first }
let(:merge_request) { create(:merge_request, source_project: project) }
let!(:base_pipeline) do
create(:ee_ci_pipeline,
:with_api_fuzzing_report,
project: project,
ref: merge_request.target_branch,
sha: merge_request.diff_base_sha)
end
before do
merge_request.update!(head_pipeline_id: head_pipeline.id)
end
context 'when head pipeline has api fuzzing reports' do
let!(:head_pipeline) do
create(:ee_ci_pipeline,
:with_api_fuzzing_report,
project: project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha)
end
context 'when reactive cache worker is parsing asynchronously' do
it 'returns status' do
expect(subject[:status]).to eq(:parsing)
end
end
context 'when reactive cache worker is inline' do
before do
synchronous_reactive_cache(merge_request)
end
it 'returns status and data' do
expect_any_instance_of(Ci::CompareSecurityReportsService)
.to receive(:execute).with(base_pipeline, head_pipeline).and_call_original
subject
end
context 'when cached results is not latest' do
before do
allow_any_instance_of(Ci::CompareSecurityReportsService)
.to receive(:latest?).and_return(false)
end
it 'raises an InvalidateReactiveCache error' do
expect { subject }.to raise_error(ReactiveCaching::InvalidateReactiveCache)
end
end
end
end
end
describe '#mergeable_with_quick_action?' do
def create_pipeline(status)
pipeline = create(:ci_pipeline,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment