Skip to content

Connect Resolve Vulnerability with AI Response

Samantha Ming requested to merge 430888-handle-onclick-resolve-with-ai into master

What does this MR do and why?

When the Resolve with AI is clicked, it loads the AI response. When the MR link is returned, it will redirect the user to the newly created MR.

MR Changes
!136716 (merged) Introduce the "Resolve with AI" UI button
This MR Handle onClick of the "Resolve with AI" button

Screenshots or screen recordings

resolve-vulnerability-persisting-loading

How to set up and validate locally

  1. Have the related FF enabled: echo "Feature.enable(:resolve_vulnerability_ai)" | rails c
  2. In order to run a pipeline to generate a Vulnerability report, you'll need an EE license.
  3. Fork https://gitlab.com/gitlab-org/security-products/tests/webgoat.net (for the solo button)
  4. Fork https://gitlab.com/gitlab-examples/security/security-reports (no button)
  5. Run a pipeline against the default branch. It will generate vulnerabilities.
  6. Go to the project vulnerability report page
  7. Click on the SAST vulnerability
  8. You will see the "Resolve with AI" button
  9. When clicked, it will load the the AI request, and when the response returns, it will redirect to the MR

Note: The API has changed a bit (Update resolve vulnerability to return MR link (!137384 - merged)), please apply this patch: MR has been merged and I have rebased 💪

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137384/diffs.patch

Patch Code
From 7ac1d005e466f239f9182e0274fc76eef510c890 Mon Sep 17 00:00:00 2001
From: Samantha Ming <sming@gitlab.com>
Date: Mon, 20 Nov 2023 10:16:39 +0100
Subject: [PATCH 1/2] Update resolve vulnerability to return MR link

Update the response to return the MR link instead of the MR reference
---
 ee/lib/gitlab/llm/completions/resolve_vulnerability.rb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb b/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
index 06eb9e0dc2c0fb..93e63c25659c71 100644
--- a/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
+++ b/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
@@ -65,7 +65,8 @@ def create_merge_request(user, vulnerability, response)
 
           return formatted_error_response(RESOLUTION_FAILURE_ERROR, context: result) unless result[:status] == :success
 
-          { merge_request_reference: result[:merge_request].to_reference }
+          mr = result[:merge_request]
+          { merge_request_reference: Gitlab::Routing.url_helpers.project_merge_request_url(mr.project, mr) }
         end
 
         def error_message(error)
-- 
GitLab


From 251b8958af1a1bf521e322776e6fba07e06a408c Mon Sep 17 00:00:00 2001
From: Gregory <11164960-ghavenga@users.noreply.gitlab.com>
Date: Mon, 20 Nov 2023 13:22:31 +0200
Subject: [PATCH 2/2] Change RTV MR reference to the url

Changelog: changed
EE: true
---
 .../llm/completions/resolve_vulnerability.rb     |  2 +-
 .../response_modifiers/resolve_vulnerability.rb  |  6 +++---
 .../completions/resolve_vulnerability_spec.rb    |  4 ++--
 .../resolve_vulnerability_spec.rb                | 16 ++++++++--------
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb b/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
index 93e63c25659c71..e48ca16f7e265e 100644
--- a/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
+++ b/ee/lib/gitlab/llm/completions/resolve_vulnerability.rb
@@ -66,7 +66,7 @@ def create_merge_request(user, vulnerability, response)
           return formatted_error_response(RESOLUTION_FAILURE_ERROR, context: result) unless result[:status] == :success
 
           mr = result[:merge_request]
-          { merge_request_reference: Gitlab::Routing.url_helpers.project_merge_request_url(mr.project, mr) }
+          { merge_request_url: Gitlab::Routing.url_helpers.project_merge_request_url(mr.project, mr) }
         end
 
         def error_message(error)
diff --git a/ee/lib/gitlab/llm/response_modifiers/resolve_vulnerability.rb b/ee/lib/gitlab/llm/response_modifiers/resolve_vulnerability.rb
index abe7e7fdab43b3..301b295a26a625 100644
--- a/ee/lib/gitlab/llm/response_modifiers/resolve_vulnerability.rb
+++ b/ee/lib/gitlab/llm/response_modifiers/resolve_vulnerability.rb
@@ -7,7 +7,7 @@ class ResolveVulnerability < ::Gitlab::Llm::BaseResponseModifier
         include Gitlab::Utils::StrongMemoize
 
         def response_body
-          @response_body ||= ai_response&.dig(:merge_request_reference).to_s
+          @response_body ||= ai_response&.dig(:merge_request_url).to_s
         end
         strong_memoize_attr :response_body
 
@@ -21,8 +21,8 @@ def empty_response_error
           case ai_response
           when {}, nil
             "The response from the AI provider was empty."
-          when { 'merge_request_reference' => nil }
-            "No resolution merge request reference was provided"
+          when { 'merge_request_url' => nil }
+            "No resolution merge request url was provided"
           end
         end
       end
diff --git a/ee/spec/lib/gitlab/llm/completions/resolve_vulnerability_spec.rb b/ee/spec/lib/gitlab/llm/completions/resolve_vulnerability_spec.rb
index 971ea5f83408fc..671953617fe075 100644
--- a/ee/spec/lib/gitlab/llm/completions/resolve_vulnerability_spec.rb
+++ b/ee/spec/lib/gitlab/llm/completions/resolve_vulnerability_spec.rb
@@ -8,7 +8,7 @@
   let(:prompt_class) { Gitlab::Llm::Templates::Vulnerabilities::ResolveVulnerability }
   let(:merge_request_service) { ::MergeRequests::CreateFromVulnerabilityDataService }
   let(:merge_request) { create(:merge_request, source_project: project) }
-  let(:mr_reference) { merge_request.to_reference }
+  let(:mr_url) { Gitlab::Routing.url_helpers.project_merge_request_url(project, merge_request) }
   let(:code_patch) { "somecode\nexecute" }
   let(:example_response) do
     {
@@ -128,7 +128,7 @@ def execute_resolve(message_params = {}, options = {})
 
         expect(GraphqlTriggers).to have_received(:ai_completion_response).with(
           an_object_having_attributes(
-            content: mr_reference,
+            content: mr_url,
             role: ::Gitlab::Llm::AiMessage::ROLE_ASSISTANT,
             request_id: 'uuid',
             errors: [],
diff --git a/ee/spec/lib/gitlab/llm/response_modifiers/resolve_vulnerability_spec.rb b/ee/spec/lib/gitlab/llm/response_modifiers/resolve_vulnerability_spec.rb
index 1456efc2d1485e..636ccd97e5e1d3 100644
--- a/ee/spec/lib/gitlab/llm/response_modifiers/resolve_vulnerability_spec.rb
+++ b/ee/spec/lib/gitlab/llm/response_modifiers/resolve_vulnerability_spec.rb
@@ -27,25 +27,25 @@
     it_behaves_like 'empty response error'
   end
 
-  context 'when no merge request reference is passed' do
-    let(:reference) { nil }
-    let(:ai_response) { { 'merge_request_reference' => reference }.to_json }
+  context 'when no merge request url is passed' do
+    let(:url) { nil }
+    let(:ai_response) { { 'merge_request_url' => url }.to_json }
 
     it 'parses content from the ai response' do
       expect(response_modifier.response_body).to eq('')
     end
 
     it 'returns empty errors' do
-      expect(response_modifier.errors).to match_array("No resolution merge request reference was provided")
+      expect(response_modifier.errors).to match_array("No resolution merge request url was provided")
     end
   end
 
-  context 'when a merge request reference is passed' do
-    let(:reference) { "!1" }
-    let(:ai_response) { { 'merge_request_reference' => reference }.to_json }
+  context 'when a merge request url is passed' do
+    let(:url) { "http://localhost/namespace1/project-1/-/merge_requests/1" }
+    let(:ai_response) { { 'merge_request_url' => url }.to_json }
 
     it 'parses content from the ai response' do
-      expect(response_modifier.response_body).to eq(reference)
+      expect(response_modifier.response_body).to eq(url)
     end
 
     it 'returns empty errors' do
-- 
GitLab

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #430888 (closed)

Edited by Samantha Ming

Merge request reports