Support target work item type in /move and /clone quick actions
What does this MR do and why?
Support target work item type in /move and /clone quick actions.
Adds an optional [type:<work item type>] token to the /move and /clone quick actions so users can specify the target work item type when moving or cloning a work item across namespaces. Mirrors the behavior of the issueMove GraphQL mutation and the move modal UI.
The bracketed syntax follows the same pattern as other quick action tokens like [timecategory:category-name] and [contact:email]. Because ] terminates the value, multi-word type names (for example, Key Result, Key Feature) do not need quoting.
Resolution rules are centralized in a new WorkItems::TargetTypeResolver (used by both the quick actions and WorkItems::DataSync::BaseService), evaluated against the destination namespace's WorkItems::TypesFramework::Provider via filtered_types so tier, feature flags, and namespace-level type visibility are honored:
- Explicit type supplied: resolved by name (case-insensitive) against the destination namespace. Must resolve and be enabled there; otherwise fail with a clear error listing the available types.
- No type, source type resolves at destination and is enabled: the item keeps that type (no override needed).
- No type, source type does not resolve (or is disabled) at destination: fail fast and prompt the user to pick one via
[type:NAME], listing the available types. - Resolved type exists but is disabled at the destination (archived, admin-disabled via type visibility settings, or not visible in the destination context): fail with a "disabled in the target namespace" error listing the available types.
- Same-namespace moves/clones: type conversion is skipped (no-op). An explicit
[type:...]is still validated so the user gets a clear error for unknown or disabled types, but the item keeps its existing type.
This closes the silent-success bug where a /move of a custom work item type to a namespace without that type would report success without actually moving the item.
Changelog: added Issue: #603929 (closed)
References
Screenshots or screen recordings
| Before | After |
|---|---|
How to set up and validate locally
Prerequisites
-
Start GDK with
GITLAB_SIMULATE_SAAS=1so that work item types can be configured per root group. Without this flag, type visibility is scoped per organization rather than per root group, which makes it impossible to exercise the per-namespace resolution branches below.GITLAB_SIMULATE_SAAS=1 gdk start -
Sign in as a user with at least the Reporter role on the source and Reporter role on the destination.
-
Create two projects (or a project and a group) under namespaces you can access, e.g.
group-a/source-projectandgroup-b/target-project. -
Create at least one issue in
group-a/source-projectto act as the work item you'll move/clone. -
(Optional, for the custom-type cases) In a Rails console, ensure the destination namespace has a different set of enabled work item types than the source so you can exercise the resolution branches:
# Example: disable "Issue" at the destination to force a [type:...] argument target_namespace = Group.find_by_full_path('group-b').namespace # use WorkItems::Type::Widgets or the admin UI under # Settings -> Work items -> Types to toggle visibility per namespace
Example commands
Run these as comments on a work item in group-a/source-project. Use the Preview tab in the comment editor or submit the comment to execute the quick action.
1. Happy path — explicit single-word type:
/move group-b/target-project [type:Task]Expected: success message, item appears in group-b/target-project as a Task.
2. Happy path — multi-word type (no quoting needed):
/move group-b/target-project [type:Key Result]/clone group-b/target-project [type:Key Result]Expected: success; the new/cloned item uses the Key Result type at the destination.
3. No [type:...], source type exists and is enabled at destination:
/move group-b/target-projectExpected: success; the item keeps its existing type.
4. No [type:...], source type missing or disabled at destination:
/move group-b/target-projectExpected error (the item is not moved):
Unable to move. The source work item type "Feature" is not available in the target namespace. Specify one using
[type:NAME]. Available types: Issue, Task, Incident, Key Result.
5. Explicit unknown type:
/move group-b/target-project [type:Bogus]Expected error:
Unable to move. The work item type "Bogus" is not available in the target namespace. Available types: Issue, Task, Incident, Key Result.
6. Explicit disabled type (archived, admin-disabled, or not visible in context):
/move group-b/target-project [type:Epic]Expected error:
Unable to move. The work item type "Epic" is disabled in the target namespace. Available types: Issue, Task, Incident, Key Result.
7. Same-namespace move with explicit [type:...] (validated but not applied):
/move group-a/source-project [type:Task]Expected: succeeds if Task is enabled in group-a (the item keeps its current type), or fails with the same available-types error message if Task is unknown or disabled.
8. Clone with --with_notes and a type:
/clone group-b/target-project [type:Key Result] --with_notesExpected: clone created at the destination as Key Result, with notes copied across.
Running the specs
bin/rspec spec/services/quick_actions/interpret_service_spec.rb
bin/rspec ee/spec/services/quick_actions/interpret_service_spec.rb
bin/rspec spec/services/issues/update_service_spec.rbAll suites should be green, including the new [type:...] cases and the TargetTypeResolver behavior.
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 #603929 (closed)