Export MR list CSVs through GraphQL behind a flag

What does this MR do and why?

The merge request list "Export as CSV" action ignores some filters, such as merge user and target branch. Behind a new feature flag, the export modal now sends the list's own filters to the mergeRequestsCsvExport GraphQL mutation, so the CSV matches what the list shows.

With the flag off nothing changes. With it on, the export runs without a page redirect and shows a success alert with the server message, or "An error occurred while exporting merge requests." on failure.

This targets the branch of !261924 (merged), which adds the mutation.

Merge request stack

These merge requests fix #583992 together. Merge them in this order; same-numbered MRs are independent.

Order MR What Depends on
1 !262241 (merged) Extract the merge request filter arguments into a shared concern (no schema change) None
1 !262242 (merged) Accept the subscribed filter as a string in IssuableFinder None
2 !261924 (merged) Add the mergeRequestsCsvExport GraphQL mutation !262241 (merged), !262242 (merged)
3 !261946 (merged) (this MR) Switch the MR list export to the mutation behind merge_requests_csv_export_graphql !261924 (merged)
4 !261956 Remove the REST export and the flag after the rollout in #633656 (not before 2026-11-16) !261946 (merged)
Implementation details
  • Feature flag merge_requests_csv_export_graphql: gitlab_com_derisk, default off, project actor, pushed to the frontend on the MR index page. Rollout issue: #633656.
  • Why a flag: backend and frontend for the same GraphQL feature cannot ship in the same release (multi-version compatibility). The flag lets this merge right after !261924 (merged) and be enabled once both are deployed.
  • With the flag on, the modal calls mergeRequestsCsvExport with fullPath, state, search, and the list's API filter params instead of posting window.location.search to the REST export_csv action. The modal falls back to the REST path when no mutation is provided.
  • Mutation documents mirror the list query's variable names: queries/project/export_merge_requests_csv.mutation.graphql (CE) and an EE copy that adds $in and $approver, as the EE list query does. The page entry picks one with ee_else_ce, same as the list queries, and provides it to the app as exportMergeRequestsCsvMutation.
  • Variables flow: list app computed csvExportVariables, then more_actions_dropdown prop exportVariables, then csv_import_export_buttons, then csv_export_modal.
  • Changelog: none (behind a default-off flag).

Tests:

  • Jest csv_export_modal_spec.js covers flag on (no href, mutation called with list filters, success alert, error alert for returned errors and request failure, fallback to REST when no mutation) and flag off.
  • merge_requests_list_app_spec.js checks that filters from the URL (merge_user, target_branches[]) reach the dropdown's exportVariables.
  • All 151 MR list Jest tests pass.
  • The request spec checks have_pushed_frontend_feature_flags for flag on and off.

References

Screenshots or screen recordings

Not captured (local GDK runs precompiled assets). The UI is unchanged except that the export now runs without a page redirect and shows an alert.

How to set up and validate locally

  1. In a Rails console, enable the feature flag:
    Feature.enable(:merge_requests_csv_export_graphql)
  2. Open a project's merge requests list.
  3. Filter by the merged tab, merge user, and target branch.
  4. Choose Export as CSV.
  5. Open the emailed CSV in letter_opener at /rails/letter_opener and check it contains only matching merge requests.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

🤖 Generated with Claude Code

Edited by Kai Armstrong

Merge request reports

Loading
Loading