Skip to content

Add GraphQL mutation to link work items

Related to #416787 (closed)

What does this MR do and why?

In !126980 (merged) we added the functionality to query the items that are linked to a work item and this MR adds a GraphQL mutation that allows us to link work items.

These changes are part of the implementation of linked work items feature which is being developed behind the feature flag :linked_work_items. A mutation for unlinking the items will be added in a following MR !127639 (merged).

Summary of changes:

  1. Modifies IssuableLinks::CreateService so the :target_issuable param can accept an array of records, instead of a single one. The service already treated the single record as a collection after calling #referenced_issuables method so there are not changes in functionality. This change is necessary because work items don't support references and can't use the :issuable_references to link multiple items simultaneously.
  2. Adds a new service that handles the creation of work item links and inherits from IssuableLinks::CreateService. This new service behaves similarly to IssueLinks::CreateService but it contains some key differences:
  • Uses the policy admin_work_item_link to check for permissions to create the link (Guest+ role required)
  • Checks for the licensed feature blocked_work_items before allowing to create the blocks and blocked_by type of links
  • Includes the :message attribute in its response to communicate which work item IDs were successfully linked
  • Uses different error messages to mention ids and links, instead of references and relations
  1. Modifies 'issuable link creation' shared examples so they can be used when testing the new service. The changes allow us to use the examples with the option use_references: false where the :target_issuable param would be used instead of :issuable_references param.
  2. Adds a new mutation WorkItemAddLinkedItems that accepts the global id of the work item, a list of global ids for the work items that will be linked and a link type. The link type defaults to related if omitted and can be BLOCKS or BLOCKED_BY if blocked_work_items licensed feature is available. This mutation returns the work item, a message that indicates which IDs were linked and an array of errors. We may have items that were linked successfully along with items that failed, in this case both message and errors fields will be returned. Also, this mutation will raise an error if the feature flag :linked_work_items is disabled.

Screenshots or screen recordings

This MR doesn't contain any UI changes

add_linked_items

How to set up and validate locally

  1. Using rails console enable the feature flag
Feature.enable(:linked_work_items)
  1. Still in rails console create a work item of type task and take note of its ID
author, project = User.first, Project.first
wi_type = WorkItems::Type.find_by(base_type: 'task')
task = WorkItem.create!(title: "Source Task", project: project, author: author, work_item_type: wi_type)
  1. Create 4 more tasks
related1 = WorkItem.create!(title: "Related 1", project: project, author: author, work_item_type: wi_type)
related2 = WorkItem.create!(title: "Related 2", project: project, author: author, work_item_type: wi_type)
blocked = WorkItem.create!(title: "Blocked", project: project, author: author, work_item_type: wi_type)
blocking = WorkItem.create!(title: "Blocking", project: project, author: author, work_item_type: wi_type)
  1. Visit https://gdk.test:3000/-/graphql-explorer and use the following mutation (replace task IDs) to add linked items
Click to expand
mutation addRelated {
  workItemAddLinkedItems(input: {id: "gid://gitlab/WorkItem/1", workItemsIds: ["gid://gitlab/WorkItem/2", "gid://gitlab/WorkItem/3"]}) {
    errors
    message
  }
} #=> "Successfully linked ID(s): 2 and 3."

mutation addBlocked {
  workItemAddLinkedItems(input: {id: "gid://gitlab/WorkItem/1", workItemsIds: ["gid://gitlab/WorkItem/4"], linkType: BLOCKS}) {
    errors
    message
  }
} #=> "Successfully linked ID(s): 4."

mutation addBlocking {
  workItemAddLinkedItems(input: {id: "gid://gitlab/WorkItem/1", workItemsIds: ["gid://gitlab/WorkItem/5"], linkType: BLOCKED_BY}) {
    errors
    message
  }
} #=> "Successfully linked ID(s): 5." or "Work item(s) already linked" is returned if executed a second time
  1. Linking an item that the current user have no access to or executing the mutation with the FF disable should return unauthorised message: "The resource that you are attempting to access does not exist or you don't have permission to perform this action"

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