Fix 500 error when moving or cloning an epic via quick actions
What does this MR do and why?
This MR fixes a 500 error that happens when running /move or /clone quick actions on an epic.
Merge request !242269 (merged) added an optional [type:NAME] token to the /move and /clone quick actions. Since that change, these quick actions always pass a target_work_item_type_id parameter to WorkItems::DataSync::MoveService and WorkItems::DataSync::CloneService, even when the user did not type a [type:...] token.
WorkItems::DataSync::BaseService#verify_target_work_item_type is supposed to read that parameter and delete it from params. For epics, the method returned early, before the params.delete calls ran, so the key stayed in params. The leftover key was later merged into the create params of the copied work item in WorkItems::DataSync::Handlers::CopyDataHandler, and assign_attributes raised ActiveModel::UnknownAttributeError: unknown attribute 'target_work_item_type_id' for WorkItem. Nothing rescued the error, so the comment that contained the quick action failed with a 500.
Moving issues was not affected, because the non-epic path already removed the key.
The fix moves the params.delete(:target_work_item_type_id) and params.delete(:target_work_item_type_name) calls in app/services/work_items/data_sync/base_service.rb so they run before both early returns (the same-namespace skip and the epic skip). This way the keys are always consumed and can never leak into the create params.
Specs were added in ee/spec/services/work_items/data_sync/move_service_spec.rb and ee/spec/services/work_items/data_sync/clone_service_spec.rb. The service is now built with a params: argument, and the existing "with epic work item" context gained a new "when target_work_item_type_id is provided" context that reuses the "cloneable and moveable work item" shared examples. These new examples fail on master with the UnknownAttributeError and pass with the fix. The full EE and CE move and clone data-sync spec files pass (207 examples), and rubocop is clean.
References
This regression was introduced by !242269 (merged).
Reported internally in Slack: https://gitlab.slack.com/archives/CETG54GQ0/p1787902512010009
Screenshots or screen recordings
This is a backend-only change with no UI change, so there are no screenshots.
How to set up and validate locally
- Make sure the GDK has an Ultimate license so epics are available.
- Create a top-level group with a subgroup, or use any two groups.
- Create an epic in the source group.
- On master, add a comment on the epic containing
/move <target-group-full-path>and observe a 500 error, withActiveModel::UnknownAttributeError: unknown attribute 'target_work_item_type_id' for WorkItemin the Rails log. - Check out this branch and repeat: the epic is moved to the target group and keeps the Epic type.
- Optionally repeat with
/clone <target-group-full-path>.