Commit be53ef4b authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Jarka Košanová

Rewrite query to check resolved_on_default_branch

parent 3762f8b4
......@@ -233,9 +233,12 @@ module EE
self.tracing_setting.try(:external_url)
end
def latest_pipeline_with_security_reports
all_pipelines.newest_first(ref: default_branch).with_reports(::Ci::JobArtifact.security_reports).first ||
all_pipelines.newest_first(ref: default_branch).with_legacy_security_reports.first
def latest_pipeline_with_security_reports(only_successful: false)
pipeline_scope = all_pipelines.newest_first(ref: default_branch)
pipeline_scope = pipeline_scope.success if only_successful
pipeline_scope.with_reports(::Ci::JobArtifact.security_reports).first ||
pipeline_scope.with_legacy_security_reports.first
end
def latest_pipeline_with_reports(reports)
......
......@@ -142,9 +142,18 @@ class Vulnerability < ApplicationRecord
def resolved_on_default_branch
return false unless findings.any?
latest_successful_pipeline_for_default_branch = project.latest_successful_pipeline_for_default_branch
latest_pipeline_with_vulnerability = finding.pipelines.order(created_at: :desc).first
latest_pipeline_with_vulnerability != latest_successful_pipeline_for_default_branch
# We can't just use project.latest_successful_pipeline_for_default_branch
# because there's no guarantee that it actually ran the security jobs
# See https://gitlab.com/gitlab-org/gitlab/-/issues/218012
latest_successful_pipeline = project
.latest_pipeline_with_security_reports(only_successful: true)
# Technically this shouldn't ever happen.
# If an vulnerability was discovered, then we must have ran a scan of the
# appropriate type at least once.
return false unless latest_successful_pipeline
finding.pipelines.exclude?(latest_successful_pipeline)
end
def user_notes_count
......
---
title: Fetch latest successful pipeline with security jobs to check if vulnerability
was resolved
merge_request: 38452
author:
type: changed
......@@ -1513,41 +1513,81 @@ RSpec.describe Project do
end
describe '#latest_pipeline_with_security_reports' do
let(:project) { create(:project) }
let!(:pipeline_1) { create(:ci_pipeline, project: project) }
let!(:pipeline_2) { create(:ci_pipeline, project: project) }
let!(:pipeline_3) { create(:ci_pipeline, project: project) }
let(:only_successful) { false }
subject { project.latest_pipeline_with_security_reports }
let_it_be(:project) { create(:project) }
let_it_be(:pipeline_1) { create(:ci_pipeline, :success, project: project) }
let_it_be(:pipeline_2) { create(:ci_pipeline, project: project) }
let_it_be(:pipeline_3) { create(:ci_pipeline, :success, project: project) }
context 'when legacy reports are used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_1)
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_2)
subject { project.latest_pipeline_with_security_reports(only_successful: only_successful) }
context 'when all pipelines are used' do
context 'when legacy reports are used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_1)
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_2)
end
it 'returns the latest pipeline with security reports' do
is_expected.to eq(pipeline_2)
end
end
it "returns the latest pipeline with security reports" do
is_expected.to eq(pipeline_2)
context 'when new reports are used' do
before do
create(:ee_ci_build, :sast, pipeline: pipeline_1)
create(:ee_ci_build, :sast, pipeline: pipeline_2)
end
it 'returns the latest pipeline with security reports' do
is_expected.to eq(pipeline_2)
end
context 'when legacy used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_3)
end
it 'prefers the new reports' do
is_expected.to eq(pipeline_2)
end
end
end
end
context 'when new reports are used' do
before do
create(:ee_ci_build, :sast, pipeline: pipeline_1)
create(:ee_ci_build, :sast, pipeline: pipeline_2)
end
context 'when only successful pipelines are used' do
let(:only_successful) { true }
it "returns the latest pipeline with security reports" do
is_expected.to eq(pipeline_2)
context 'when legacy reports are used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_1)
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_2)
end
it "returns the latest succesful pipeline with security reports" do
is_expected.to eq(pipeline_1)
end
end
context 'when legacy used' do
context 'when new reports are used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_3)
create(:ee_ci_build, :sast, pipeline: pipeline_1)
create(:ee_ci_build, :sast, pipeline: pipeline_2)
end
it "prefers the new reports" do
is_expected.to eq(pipeline_2)
it 'returns the latest successful pipeline with security reports' do
is_expected.to eq(pipeline_1)
end
context 'when legacy used' do
before do
create(:ee_ci_build, :legacy_sast, pipeline: pipeline_3)
end
it 'prefers the new reports' do
is_expected.to eq(pipeline_1)
end
end
end
end
......
......@@ -267,7 +267,7 @@ RSpec.describe Vulnerability do
describe '#resolved_on_default_branch' do
let_it_be(:project) { create(:project, :repository, :with_vulnerability) }
let_it_be(:pipeline_with_vulnerability) { create(:ci_pipeline, :success, project: project, sha: project.commit.id) }
let_it_be(:pipeline_with_vulnerability) { create(:ee_ci_pipeline, :success, :with_sast_report, project: project, sha: project.commit.id) }
let_it_be(:vulnerability) { project.vulnerabilities.first }
let_it_be(:finding1) { create(:vulnerabilities_occurrence, vulnerability: vulnerability, pipelines: [pipeline_with_vulnerability]) }
let_it_be(:finding2) { create(:vulnerabilities_occurrence, vulnerability: vulnerability, pipelines: [pipeline_with_vulnerability]) }
......@@ -276,14 +276,22 @@ RSpec.describe Vulnerability do
context 'Vulnerability::Finding is present on the pipeline for default branch' do
it { is_expected.to eq(false) }
end
context 'Vulnerability::Finding is not present on the pipeline for default branch' do
before do
project.instance_variable_set(:@latest_successful_pipeline_for_default_branch, pipeline_without_vulnerability)
context 'but pipeline is failed' do
let!(:unsucessful_pipeline_with_vulnerability) { create(:ee_ci_pipeline, :with_sast_report, :failed, project: project, sha: project.commit.id) }
it { is_expected.to eq(false) }
end
end
let_it_be(:pipeline_without_vulnerability) { create(:ci_pipeline, :success, project: project, sha: project.commit.id) }
context 'Vulnerability::Finding is not present on the latest pipeline without security job' do
let!(:pipeline_without_security_job) { create(:ee_ci_pipeline, :success, project: project, sha: project.commit.id) }
it { is_expected.to eq(false) }
end
context 'Vulnerability::Finding is not present on the pipeline for default branch' do
let!(:pipeline_without_vulnerability) { create(:ee_ci_pipeline, :success, :with_sast_report, project: project, sha: project.commit.id) }
it { is_expected.to eq(true) }
end
......
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