Skip to content
Snippets Groups Projects
Verified Commit 0cd6961b authored by Mehmet Emin INAC's avatar Mehmet Emin INAC :two:
Browse files

Add security report ingestion information to dashboard seed data

Client application can use `has_warnings` and `has_errors` attributes
to show the necessary alert information to end users.

This change also introduces a database migration to add indices on
`security_scans` table.

Changelog: added
parent f2598e43
No related branches found
No related tags found
1 merge request!91368Add security report ingestion information to dashboard seed data
# frozen_string_literal: true
class AddIndicesOnSecurityScansInfoColumn < Gitlab::Database::Migration[2.0]
INDEX_NAME_ON_ERRORS = :index_security_scans_on_length_of_errors
INDEX_NAME_ON_WARNINGS = :index_security_scans_on_length_of_warnings
disable_ddl_transaction!
def up
add_concurrent_index(
:security_scans,
"pipeline_id, jsonb_array_length(COALESCE((security_scans.info -> 'errors'::text), '[]'::jsonb))",
name: INDEX_NAME_ON_ERRORS
)
add_concurrent_index(
:security_scans,
"pipeline_id, jsonb_array_length(COALESCE((security_scans.info -> 'warnings'::text), '[]'::jsonb))",
name: INDEX_NAME_ON_WARNINGS
)
end
def down
remove_concurrent_index_by_name :security_scans, INDEX_NAME_ON_ERRORS
remove_concurrent_index_by_name :security_scans, INDEX_NAME_ON_WARNINGS
end
end
ea387b35bfb7f15a036aca9413b8fd15ede6b16048fa9e9be5a62b9e21ca362d
\ No newline at end of file
......@@ -29527,6 +29527,10 @@ CREATE INDEX index_security_scans_on_created_at ON security_scans USING btree (c
 
CREATE INDEX index_security_scans_on_date_created_at_and_id ON security_scans USING btree (date(timezone('UTC'::text, created_at)), id);
 
CREATE INDEX index_security_scans_on_length_of_errors ON security_scans USING btree (pipeline_id, jsonb_array_length(COALESCE((info -> 'errors'::text), '[]'::jsonb)));
CREATE INDEX index_security_scans_on_length_of_warnings ON security_scans USING btree (pipeline_id, jsonb_array_length(COALESCE((info -> 'warnings'::text), '[]'::jsonb)));
CREATE INDEX index_security_scans_on_pipeline_id ON security_scans USING btree (pipeline_id);
 
CREATE INDEX index_security_scans_on_project_id ON security_scans USING btree (project_id);
......@@ -282,6 +282,8 @@ def security_dashboard_pipeline_data(project)
id: pipeline.id,
path: pipeline_path(pipeline),
created_at: pipeline.created_at.to_s(:iso8601),
has_warnings: pipeline.has_security_report_ingestion_warnings?,
has_errors: pipeline.has_security_report_ingestion_errors?,
security_builds: {
failed: {
count: pipeline.latest_failed_security_builds.count,
......
......@@ -188,6 +188,14 @@ def ensure_persistent_ref
super
end
def has_security_report_ingestion_warnings?
security_scans.with_warnings.exists?
end
def has_security_report_ingestion_errors?
security_scans.with_errors.exists?
end
private
def has_security_reports?
......
......@@ -49,6 +49,8 @@ class Scan < ApplicationRecord
scope :by_build_ids, ->(build_ids) { where(build_id: build_ids) }
scope :without_errors, -> { where("jsonb_array_length(COALESCE(info->'errors', '[]'::jsonb)) = 0") }
scope :stale, -> { succeeded.or(preparation_failed).where('created_at < ?', STALE_AFTER.ago) }
scope :with_warnings, -> { where("jsonb_array_length(COALESCE(info->'warnings', '[]'::jsonb)) > 0") }
scope :with_errors, -> { where("jsonb_array_length(COALESCE(info->'errors', '[]'::jsonb)) > 0") }
delegate :name, to: :build
......
......@@ -11,6 +11,10 @@
info { { errors: [{ type: 'ParsingError', message: 'Unknown error happened' }] } }
end
trait :with_warning do
info { { warnings: [{ type: 'Deprecation Warning', message: 'Schema is deprecated' }] } }
end
trait :latest_successful do
latest { true }
status { :succeeded }
......
......@@ -229,6 +229,8 @@
id: pipeline.id,
path: "/#{project.full_path}/-/pipelines/#{pipeline.id}",
created_at: pipeline_created_at,
has_warnings: true,
has_errors: false,
security_builds: {
failed: {
count: 0,
......@@ -241,6 +243,8 @@
before do
allow(project).to receive(:latest_ingested_security_pipeline).and_return(pipeline)
allow(pipeline).to receive_messages(has_security_report_ingestion_warnings?: true,
has_security_report_ingestion_errors?: false)
end
it { is_expected.to match(base_values.merge!(pipeline_values)) }
......
......@@ -669,4 +669,36 @@
it { is_expected.to eq(true) }
end
end
describe '#has_security_report_ingestion_warnings?' do
subject { pipeline.has_security_report_ingestion_warnings? }
context 'when there are no associated security scans with warnings' do
it { is_expected.to be_falsey }
end
context 'when there is an associated security scan with warnings' do
before do
create(:security_scan, :with_warning, pipeline: pipeline)
end
it { is_expected.to be_truthy }
end
end
describe '#has_security_report_ingestion_errors?' do
subject { pipeline.has_security_report_ingestion_errors? }
context 'when there are no associated security scans with errors' do
it { is_expected.to be_falsey }
end
context 'when there is an associated security scan with errors' do
before do
create(:security_scan, :with_error, pipeline: pipeline)
end
it { is_expected.to be_truthy }
end
end
end
......@@ -231,8 +231,8 @@
end
describe '.without_errors' do
let(:scan_1) { create(:security_scan, :with_error) }
let(:scan_2) { create(:security_scan) }
let!(:scan_1) { create(:security_scan, :with_error) }
let!(:scan_2) { create(:security_scan) }
subject { described_class.without_errors }
......@@ -267,6 +267,24 @@
it { is_expected.to match_array([stale_succeeded_scan, stale_failed_scan]) }
end
describe '.with_warnings' do
let!(:scan_1) { create(:security_scan) }
let!(:scan_2) { create(:security_scan, :with_warning) }
subject { described_class.with_warnings }
it { is_expected.to contain_exactly(scan_2) }
end
describe '.with_errors' do
let!(:scan_1) { create(:security_scan, :with_error) }
let!(:scan_2) { create(:security_scan) }
subject { described_class.with_errors }
it { is_expected.to contain_exactly(scan_1) }
end
describe '#report_findings' do
let(:artifact) { create(:ee_ci_job_artifact, :dast) }
let(:scan) { create(:security_scan, build: artifact.job) }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment