Skip to content

Allow cross-group work items hierarchy

Now that the work item of type Epic is supported and following the discussion in #362203 (comment 1553349971), we need to modify the validations in WorkItems::ParentLink to allow parent-child relationships between items from different groups/projects.

Proposal 1

A simple approach could be defining the relationships that support cross-hierarchy in a constant. The included relationships should be epic -> issue and epic -> epic.

example
--- a/app/models/work_items/parent_link.rb	(revision 667d5007cfdb202c6b6dd6f958b80a57a6329564)
+++ b/app/models/work_items/parent_link.rb	(date 1694618860153)
@@ -52,6 +52,7 @@
 
     def validate_same_project
       return if work_item.nil? || work_item_parent.nil?
+      return if cross_hierarchy_allowed?(work_item, work_item_parent)
 
       if work_item.resource_parent != work_item_parent.resource_parent
         errors.add :work_item_parent, _('parent must be in the same project as child.')
@@ -119,6 +120,13 @@
 
       errors.add(:work_item, _('cannot assign a linked work item as a parent'))
     end
+
+    def cross_hierarchy_allowed?(child, parent)
+      allowed_types = WorkItems::Type::CROSS_HIERARCHY_TYPES[child.work_item_type&.base_type]
+      return false unless allowed_types
+
+      allowed_types.include?(parent.work_item_type&.base_type)
+    end
   end
 end
 
--- a/app/models/work_items/type.rb	(revision 667d5007cfdb202c6b6dd6f958b80a57a6329564)
+++ b/app/models/work_items/type.rb	(date 1694619129247)
@@ -43,6 +43,12 @@
     # type must be included in this list. This is needed for legacy issues
     # where it's possible to switch between issue and incident.
     CHANGEABLE_BASE_TYPES = %w[issue incident test_case].freeze
+    # A list of types that support cross-group hierarchy when relating as child and parent
+    # This is needed for WorkItems::ParentLink#validate_same_project validation
+    CROSS_HIERARCHY_TYPES = HashWithIndifferentAccess.new(
+      issue: %w[epic],
+      epic: %w[issue epic]
+    ).freeze
 
     cache_markdown_field :description, pipeline: :single_line
 

Proposal 2

A more lasting solution could be storing this information in a new column in work_item_hierarchy_restrictions table where the relationship is already defined. For example, we could use a boolean column cross_hierarchy_enabled with a default value of false that we then enable for the two records that define the restriction for epic -> issue and epic -> epic relationships.

Edited by Eugenia Grieff