Expose `has_ai_resolution` via GraphQL
Context
We need to be able to filter vulnerabilities on whether they have the "Resolve with Duo" button enabled.
This button is enabled if a finding's CWE value is included in this
hard-coded list of CWE values.
In previous MRs we:
This Issue
The database work isn't done yet as we still need to backfill the existing rows3 and add database indexes4.
However, we can expose graphql fields with FFs according to the docs:
This will unblock the frontend team from building and testing their code, as well as help us solidify the API contract.
Implementation Plan
Update the finder
We can basically mirror the has_resolution filter. The basic diff
will look something like:
diff --git a/ee/app/finders/security/vulnerability_reads_finder.rb b/ee/app/finders/security/vulnerability_reads_finder.rb
index e5682db8fc37..277423181331 100644
--- a/ee/app/finders/security/vulnerability_reads_finder.rb
+++ b/ee/app/finders/security/vulnerability_reads_finder.rb
@@ -52,6 +52,7 @@ def execute
filter_by_scanner_external_id
filter_by_scanner_ids
filter_by_resolution
+ filter_by_vulnerability_resolution
filter_by_issues
filter_by_has_merge_request
filter_by_cluster_agent_id
@@ -164,5 +165,11 @@ def filter_by_resolution
@vulnerability_reads = vulnerability_reads.with_resolution(params[:has_resolution])
end
+ def filter_by_vulnerability_resolution
+ return unless params[:has_vulnerability_resolution].in?([true, false])
+
+ @vulnerability_reads = vulnerability_reads.with_vulnerability_resolution(params[:has_vulnerability_resolution])
+ end
+
def filter_by_issues
return unless params[:has_issues].in?([true, false])
In addition to this diff, we will need:
-
Update the doc string at the top of the finder class -
Add the with_vulnerability_resolutionmodel scope -
Tests for the new scope -
Tests for the finder
Expose value in GraphQL
We can expose the field in the graphql API behind a feature flag according to the docs:
The diff will look something like this:
diff --git a/ee/app/graphql/resolvers/vulnerabilities_resolver.rb b/ee/app/graphql/resolvers/vulnerabilities_resolver.rb
index d11b402fe0ec..93953646f754 100644
--- a/ee/app/graphql/resolvers/vulnerabilities_resolver.rb
+++ b/ee/app/graphql/resolvers/vulnerabilities_resolver.rb
@@ -47,6 +47,11 @@ class VulnerabilitiesResolver < VulnerabilitiesBaseResolver
required: false,
description: 'Returns only the vulnerabilities which have been resolved on default branch.'
+ argument :has_vulnerability_resolution, GraphQL::Types::Boolean,
+ required: false,
+ alpha: { milestone: '17.5' },
+ description: 'Returns only the vulnerabilities which can likely be resolved by Duo. Requires the `vulnerability_report_vr_filter` feature flag to be enabled, otherwise the argument is ignored.'
+
argument :has_issues, GraphQL::Types::Boolean,
required: false,
description: 'Returns only the vulnerabilities which have linked issues.'
@@ -110,6 +115,7 @@ def preloads
def vulnerabilities(params)
finder_params = params.merge(before_severity: before_severity, after_severity: after_severity)
+ params.delete(:has_vulnerability_resolution) unless Feature.enabled?(:vulnerability_report_vr_filter, vulnerable)
apply_lookahead(::Security::VulnerabilityReadsFinder.new(vulnerable, finder_params).execute.as_vulnerabilities)
end
We will also need to:
-
Update the resolver specs -
Run the graphql docs generator -
Run the FF generator (docs)
bin/feature-flag -M '17.5' \
-a 'https://gitlab.com/gitlab-org/gitlab/-/issues/490323' \
-g 'group::threat insights' \
-i 'https://gitlab.com/gitlab-org/gitlab/-/issues/486534' \
-t 'wip' \
-e \
'vulnerability_report_vr_filter'
-
Add `has_vulnerability_resolution` column to `v... (!165548 - merged) • Michael Becker • 17.5
↩ -
Begin populating the `has_vulnerability_resolut... (!165952 - merged) • Michael Becker • 17.5
↩ -
Backfill for `vulnerability_reads.has_vulnerabi... (!166110 - merged) • Michael Becker • 17.5
↩ -
The index addition is being pushed off due to the difficulty of testing an index in database lab until the backfill is complete. This thread has more discussion
↩