Fix group vulnerability export segment boundaries

What does this MR do and why?

Since !253454 (merged) (b87a93e1, "Speed up filtered vulnerability CSV export enqueue"), group-level vulnerability CSV exports fail: Gitlab::Export::SegmentedExportWorker raises ActiveRecord::RecordNotFound: Couldn't find Vulnerabilities::Read with 'vulnerability_id'=<id> in ExportService#export_segment, the export is marked failed, and the user never gets the "export ready" email.

Root cause: enqueue_segmented_export now stores part boundaries with records.first[boundary_column], where boundary_column was :id for groups. Vulnerabilities::Read uses vulnerability_id as its primary key, and record[:id] reads the raw vulnerability_reads.id column rather than the primary key (before !253454 (merged) the code used records.first.id, which returns the primary key). export_segment then looks the boundaries up with Vulnerabilities::Read.find, by vulnerability_id, so it raises RecordNotFound whenever the two ids differ, which is true for nearly all real data. The group keyset scopes (in_parent_group_after_and_including / before_and_including) also compare on the primary key.

Fix: store vulnerability_id boundaries for groups too, which is what export_segment and the keyset scopes expect. The now-unneeded boundary_column helper is removed. Project exports are unchanged: they already bounded on vulnerability_id, and the narrowed select from !253454 (merged) is kept.

Specs:

  • The shared segmented export behaviour example expected group parts to use the read's id, encoding the bug. It now expects vulnerability_id for both groups and projects.
  • New regression test: a group export where vulnerability_reads.id differs from vulnerability_id enqueues parts that export_segment can generate. It raises RecordNotFound without this fix.

References

Closes #631098

Regression from !253454 (merged).

How to set up and validate locally

  1. In a group whose vulnerability_reads.id values differ from their vulnerability_id (for example, run Vulnerabilities::Read.where(project: <project>).update_all('id = id + 1000000') in a Rails console on GDK).
  2. Request a group vulnerability export from Secure > Vulnerability report > Export.
  3. Before: SegmentedExportWorker fails with RecordNotFound and no email is sent. After: the export completes and the email arrives.

Specs:

bundle exec rspec ee/spec/services/vulnerability_exports/export_service_spec.rb

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Merge request reports

Loading
Loading