Fix importing WITs from CSV with spaces in their name

What does this MR do and why?

This MR updates the work items CSV import to support work item types with spaces in their names (e.g. Key Result).

This would fail on the import, since the import service would check if the type was available, but was missing a conversion to snake case.

After this failure, the email template would also fail, since type_errors[:missing] and type_errors[:disallowed] were expected to be an array in the template, but were passed as a hash from the service. Converting these in the template resolves this issue and allows the failure email to be rendered correctly.

References

Screenshots or screen recordings

Before After (with OKRs disabled) After (with OKRs enabled)
Email template would fail with exception Undefined method .join() for instance of hash Screenshot_2025-07-22_at_3.07.10_pm Screenshot_2025-07-22_at_3.09.34_pm

How to set up and validate locally

Since there's no way to currently call the mutation from the UI, we'll update the backend controller to call the WI equivalent APIs:

Happy Path

  1. In app/controllers/projects/issues_controller.rb, edit the import_csv method to call the work item service:
result = WorkItems::PrepareImportCsvService.new(project, current_user, file: params[:file]).execute
  1. In app/controllers/projects/issues_controller.rb, edit the export_csv method to call the work item service:
IssuableExportCsvWorker.perform_async(:work_item, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker
  1. Ensure the okrs_mvc and import_export_work_items_csv FFs are enabled
  2. Create some key results and other work items in a project
  3. Export a CSV of the work items. Note that since we're using the work items API, the CSV will contain a type column (once of which will include the type Key Result)
  4. Either delete the work items you create, or go to another blank project
  5. Select import CSV and select the CSV you exported. Alternatively, you can skip steps 4-6 above and use the following CSV: Example_CSV.csv
  6. Observe that the work item type for key result is correctly assigned after import
  7. Observe that an email is sent indicating the import was successful (using http://127.0.0.1:3000/rails/letter_opener)

Sad Path

  1. Disable the okrs_mvc FF
  2. Attempt to import the CSV in a blank project as before
  3. Observe that the import never succeeds, and an email is sent indicating as such, with the correct line numbers in the CSV
  • Note that emails and the background import export jobs can take some time to complete. To speed this process up, I changed the following lines to perform these actions synchronously for testing:
  1. IssuesController#export_csv: IssuableExportCsvWorker.new.perform(:work_item, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker
  2. ImportCsvService#email_results_to_user: Notify.import_work_items_csv_email(user.id, project.id, results).deliver_now
  3. PrepareService#enqueue_import: worker.new.perform(current_user.id, project.id, upload.id)

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.

Related to #556858 (closed)

Edited by Matt D'Angelo

Merge request reports

Loading