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
mergeRequestsCsvExportwithfullPath,state,search, and the list's API filter params instead of postingwindow.location.searchto the RESTexport_csvaction. 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$inand$approver, as the EE list query does. The page entry picks one withee_else_ce, same as the list queries, and provides it to the app asexportMergeRequestsCsvMutation. - Variables flow: list app computed
csvExportVariables, thenmore_actions_dropdownpropexportVariables, thencsv_import_export_buttons, thencsv_export_modal. - Changelog: none (behind a default-off flag).
Tests:
- Jest
csv_export_modal_spec.jscovers 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.jschecks that filters from the URL (merge_user,target_branches[]) reach the dropdown'sexportVariables.- All 151 MR list Jest tests pass.
- The request spec checks
have_pushed_frontend_feature_flagsfor flag on and off.
References
- Related to #583992
- Stacked on !261924 (merged)
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
- In a Rails console, enable the feature flag:
Feature.enable(:merge_requests_csv_export_graphql) - Open a project's merge requests list.
- Filter by the merged tab, merge user, and target branch.
- Choose Export as CSV.
- Open the emailed CSV in letter_opener at
/rails/letter_openerand 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.