Skip to content

Add model for linked work items

What does this MR do and why?

Related to #416767 (closed)

This MR is the first step needed for the implementation of 🔗 Work Items - Linked (Related) Items (&7459 - closed).

Changes summary:

  1. Add model WorkItems::RelatedWorkItemLink that includes IssuableLink concern and uses the existing table issue_links
  2. Add validation check so items cannot be created if already related as parent and child
  3. Add a new factory and tests for the model

Note: This MR only implements the model in order to keep it at a manageable size. The GraphQL endpoints for this feature will be added in following iterations:

  1. Query linked items for a work item
  2. Add mutation to link work items
  3. Add mutation to unlink work items

How to set up and validate locally

  1. Use the rails console to create and link work items using the new model:
Click to expand
author, project = User.first, Project.first
task_type = WorkItems::Type.find_by(base_type: 'task')
issue_type = WorkItems::Type.find_by(base_type: 'issue')

# Create a work item of type `issue`
issue = WorkItem.create!(title: "Test Issue", project: project, author: author, work_item_type: issue_type)

# Create a work item of type `task` and assign it as a child of `issue` - this will be used to test an invalid link
child_task = WorkItem.create!(title: "Child Task", project: project, author: author, work_item_type: task_type)
WorkItems::ParentLink.create!(work_item: child_task, work_item_parent: issue)

# Create 3 more tasks
related_task = WorkItem.create!(title: "Related Task", project: project, author: author, work_item_type: task_type)
blocked_task = WorkItem.create!(title: "Blocked Task", project: project, author: author, work_item_type: task_type)
blocking_task = WorkItem.create!(title: "Blocking Task", project: project, author: author, work_item_type: task_type)

# Link them to `issue` using the 3 different link types - this should create 3 records
WorkItems::RelatedWorkItemLink.create!(source: issue, target: blocked_task, link_type: 'blocks')
WorkItems::RelatedWorkItemLink.create!(source: blocking_task, target: issue, link_type: 'blocks')
WorkItems::RelatedWorkItemLink.create!(source: issue, target: related_task, link_type: 'relates_to')

# Try linking the child task - this should raise a validation error
WorkItems::RelatedWorkItemLink.create!(source: issue, target: child_task, link_type: 'relates_to')
#=> ActiveRecord::RecordInvalid: Validation failed: Source is a parent or child of this work item

# Use `#related_issues` method to fetch the linked work items
linked_work_items = issue.related_issues(author)
linked_work_items.all?{ |item| item.class.class_name == 'WorkItem' } #=> true
linked_work_items.pluck(:title, :issue_link_type_value) #=> [["Blocked Task", 1], ["Blocking Task", 1], ["Related Task", 0]]

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Eugenia Grieff

Merge request reports