Commit 43832ee5 authored by Markus Koller's avatar Markus Koller

Merge branch '227114_calculate_and_store_resolved_on_default_branch' into 'master'

Calculate and store resolved_on_default_branch attribute of vulnerabilities

See merge request gitlab-org/gitlab!38639
parents 35e9c55b 9b0373e6
......@@ -18,7 +18,8 @@ module Security
# Ensure we're not trying to insert data twice for this report
return error("#{@report.type} report already stored for this pipeline, skipping...") if executed?
create_all_vulnerabilities!
vulnerability_ids = create_all_vulnerabilities!
mark_as_resolved_except(vulnerability_ids)
success
end
......@@ -30,9 +31,14 @@ module Security
end
def create_all_vulnerabilities!
@report.findings.each do |finding|
create_vulnerability_finding(finding)
@report.findings.map { |finding| create_vulnerability_finding(finding).id }.uniq
end
def mark_as_resolved_except(vulnerability_ids)
project.vulnerabilities
.with_report_types(report.type)
.id_not_in(vulnerability_ids)
.update_all(resolved_on_default_branch: true)
end
def create_vulnerability_finding(finding)
......@@ -100,7 +106,7 @@ module Security
def create_vulnerability(vulnerability_finding, pipeline)
if vulnerability_finding.vulnerability_id
Vulnerabilities::UpdateService.new(vulnerability_finding.project, pipeline.user, finding: vulnerability_finding).execute
Vulnerabilities::UpdateService.new(vulnerability_finding.project, pipeline.user, finding: vulnerability_finding, resolved_on_default_branch: false).execute
else
Vulnerabilities::CreateService.new(vulnerability_finding.project, pipeline.user, finding_id: vulnerability_finding.id).execute
end
......
......@@ -4,14 +4,15 @@ module Vulnerabilities
class UpdateService
include Gitlab::Allowable
attr_reader :project, :author, :finding
attr_reader :project, :author, :finding, :resolved_on_default_branch
delegate :vulnerability, to: :finding
def initialize(project, author, finding:)
def initialize(project, author, finding:, resolved_on_default_branch: nil)
@project = project
@author = author
@finding = finding
@resolved_on_default_branch = resolved_on_default_branch
end
def execute
......@@ -30,7 +31,8 @@ module Vulnerabilities
{
title: finding.name,
severity: vulnerability.severity_overridden? ? vulnerability.severity : finding.severity,
confidence: vulnerability.confidence_overridden? ? vulnerability.confidence : finding.confidence
confidence: vulnerability.confidence_overridden? ? vulnerability.confidence : finding.confidence,
resolved_on_default_branch: resolved_on_default_branch.nil? ? vulnerability.resolved_on_default_branch : resolved_on_default_branch
}
end
end
......
......@@ -135,6 +135,24 @@ RSpec.describe Security::StoreReportService, '#execute' do
subject
expect(vulnerability.reload).to have_attributes(severity: 'medium', title: 'Probable insecure usage of temp file/directory.', title_html: 'Probable insecure usage of temp file/directory.')
end
context 'when the existing vulnerability is resolved with the latest report' do
let!(:existing_vulnerability) { create(:vulnerability, report_type: report_type, project: project) }
it 'marks the vulnerability as resolved on default branch' do
expect { subject }.to change { existing_vulnerability.reload[:resolved_on_default_branch] }.from(false).to(true)
end
end
context 'when the existing resolved vulnerability is discovered again on the latest report' do
before do
vulnerability.update!(resolved_on_default_branch: true)
end
it 'marks the vulnerability as not resolved on default branch' do
expect { subject }.to change { vulnerability.reload[:resolved_on_default_branch] }.from(true).to(false)
end
end
end
context 'with existing data from same pipeline' do
......
......@@ -14,8 +14,9 @@ RSpec.describe Vulnerabilities::UpdateService do
let!(:vulnerability) { create(:vulnerability, project: project, severity: :low, severity_overridden: severity_overridden, confidence: :ignore, confidence_overridden: confidence_overridden) }
let(:severity_overridden) { false }
let(:confidence_overridden) { false }
let(:resolved_on_default_branch) { nil }
subject { described_class.new(project, user, finding: updated_finding).execute }
subject { described_class.new(project, user, finding: updated_finding, resolved_on_default_branch: resolved_on_default_branch).execute }
context 'with an authorized user with proper permissions' do
before do
......@@ -66,6 +67,20 @@ RSpec.describe Vulnerabilities::UpdateService do
end
end
context 'when the `resolved_on_default_branch` kwarg is provided' do
let(:resolved_on_default_branch) { true }
it 'updates the resolved_on_default_branch attribute of vulnerability' do
expect { subject }.to change { vulnerability[:resolved_on_default_branch] }.from(false).to(true)
end
end
context 'when the `resolved_on_default_branch` kwarg is not provided' do
it 'does not update the resolved_on_default_branch attribute of vulnerability' do
expect { subject }.not_to change { vulnerability[:resolved_on_default_branch] }
end
end
context 'when security dashboard feature is disabled' do
before do
stub_licensed_features(security_dashboard: false)
......
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