1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# frozen_string_literal: true
# Security::JobsFinder
#
# Abstract class encapsulating common logic for finding jobs (builds) that are related to the Secure products
# SAST, DAST, Dependency Scanning, Container Scanning and License Management, Coverage Fuzzing
#
# Arguments:
# params:
# pipeline: required, only jobs for the specified pipeline will be found
# job_types: required, array of job types that should be returned, defaults to all job types
module Security
class JobsFinder
attr_reader :pipeline
def self.allowed_job_types
# Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_management, :coverage_fuzzing]
raise NotImplementedError, 'allowed_job_types must be overwritten to return an array of job types'
end
def initialize(pipeline:, job_types: [])
if self.class == Security::JobsFinder
raise NotImplementedError, 'This is an abstract class, please instantiate its descendants'
end
if job_types.empty?
@job_types = self.class.allowed_job_types
elsif valid_job_types?(job_types)
@job_types = job_types
else
raise ArgumentError, "job_types must be from the following: #{self.class.allowed_job_types}"
end
@pipeline = pipeline
end
def execute
return [] if @job_types.empty?
if Feature.enabled?(:ci_build_metadata_config)
find_jobs
else
find_jobs_legacy
end
end
private
def find_jobs
@pipeline.builds.with_secure_reports_from_config_options(@job_types)
end
def find_jobs_legacy
# the query doesn't guarantee accuracy, so we verify it here
legacy_jobs_query.select do |job|
@job_types.find { |job_type| job.options.dig(:artifacts, :reports, job_type) }
end
end
def legacy_jobs_query
@job_types.map do |job_type|
@pipeline.builds.with_secure_reports_from_options(job_type)
end.reduce(&:or)
end
def valid_job_types?(job_types)
(job_types - self.class.allowed_job_types).empty?
end
end
end
|