Fix vulnerability report to show latest non-closed MR
What does this MR do?
The vulnerability report (list) and vulnerability details page disagreed about which merge request to show for a vulnerability that has multiple linked MRs:
- The details page filters
mergeRequestLinksfor non-closed and picks the latest. - The report displayed
vulnerability.mergeRequest, the GraphQL singular field, which returns the oldest linked MR — even if closed.
This MR makes the report match the details page.
Approach
- Extract the rule (
m.state !== 'closed', take the last) into a shared utillatestOpenMergeRequestinee/app/assets/javascripts/vue_shared/security_reports/utils.js— the single source of truth. - Have the details page (
header.vue,footer.vue) consume the util. Behavior unchanged; this just deduplicates the inline filter. - Switch the vulnerability report's GraphQL fragment from the singular
mergeRequest { ... }tomergeRequests { nodes { ... } }so the report has the data needed to apply the same rule. vulnerability_list.vuederives the displayed MR via the util.
Steps to reproduce
The natural product path to hit this bug is to enable dependency_management_auto_remediation and let it create multiple auto-remediation MRs for a single vulnerability. That requires a fully-configured dependency-scanning pipeline, so for local verification we seed the fixture directly via Rails console instead.
-
Import https://gitlab.com/gitlab-examples/security/security-reports/ into your local GDK and run its pipeline so that vulnerabilities get ingested. Then pick any of the resulting vulnerabilities.
-
Open Rails console (
gdk rails console) and paste (replacing'<your/project/path>'with the path you imported the project to):project = Project.find_by_full_path('<your/project/path>') or abort 'Project not found.' user = project.first_owner || User.find_by_username('root') || User.admins.first vuln = project.vulnerabilities.first abort 'No vulnerabilities on this project.' if vuln.nil? base = project.default_branch vuln.merge_request_links.destroy_all %w[mr-old-branch-600450 mr-new-branch-600450].each do |b| next if project.repository.branch_exists?(b) result = Branches::CreateService.new(project, user).execute(b, "refs/heads/#{base}") raise "Could not create #{b}: #{result[:message]}" if result[:status] == :error end build_mr = ->(branch, title) do result = MergeRequests::CreateService.new( project: project, current_user: user, params: { source_branch: branch, target_branch: base, title: title } ).execute result.is_a?(Hash) ? result[:merge_request] : result end old_mr = build_mr.call('mr-old-branch-600450', 'Old auto-remediation (closed) — #600450 repro') new_mr = build_mr.call('mr-new-branch-600450', 'New auto-remediation (open) — #600450 repro') raise "old_mr failed: #{old_mr.errors.full_messages}" unless old_mr.persisted? raise "new_mr failed: #{new_mr.errors.full_messages}" unless new_mr.persisted? old_mr.close! unless old_mr.closed? Vulnerabilities::MergeRequestLink.create!(vulnerability: vuln, merge_request: old_mr, created_at: 2.days.ago) Vulnerabilities::MergeRequestLink.create!(vulnerability: vuln, merge_request: new_mr, created_at: Time.current) puts "Vulnerability URL: #{Gitlab::Routing.url_helpers.project_security_vulnerability_url(project, vuln)}"Result: one closed MR (
!1, older) and one open MR (!2, newer) linked to the same vulnerability. -
Before this MR (on
master):- Open the project's vulnerability report. The MR badge on that vulnerability's row points to
!1(closed). ← bug. - Open the vulnerability details page. The "Related merge request" card shows
!2(open). ← inconsistency.
- Open the project's vulnerability report. The MR badge on that vulnerability's row points to
-
After this MR (on this branch): both surfaces show
!2.
How to validate locally
Run the affected Jest specs:
yarn jest ee/spec/frontend/vue_shared/security_reports/utils_spec.js \
ee/spec/frontend/vulnerabilities/header_spec.js \
ee/spec/frontend/vulnerabilities/footer_spec.js \
ee/spec/frontend/security_dashboard/components/shared/vulnerability_report/vulnerability_list_spec.js \
ee/spec/frontend/security_dashboard/components/shared/merge_request_badge_spec.jsThen walk through the reproduction steps above and confirm the report's badge follows the details page.
Screenshots
MR acceptance checklist
- Frontend test coverage for the new util and the regression scenario.
- Manual verification against the reproduction steps above.
- Screenshots of the vulnerability report MR badge before/after.
Related to #600450