Add ancestors field to hierarchy widget
Related to #421615 (closed)
What does this MR do and why?
In order to implement Work Items: Ancestry Widget (&11197 - closed) we need to be able to access the ancestors of a work item, meaning the list of consecutive parents starting from the top-level.
This list is returned in the GraphQL field ancestors
that is included in the existing widget WorkItemWidgetHierarchy
. The list of work items is authenticated for the current user and if any inaccessible items are present the list is truncated at the last visible one, starting from the bottom.
The work items' namespace (or project) is preloaded to avoid N+1 queries during authorization. We also use lookahead to prevent N+1s when fetching the ancestors' own fields.
Screenshots or screen recordings
This functionality hasn't been implemented in the UI but it can be tested using GraphQL explorer:
How to set up and validate locally
-
Using rails console enable the feature flag
Feature.enable(:namespace_level_work_items)
-
Create two groups, one public and one private
user = User.first private = Group.create!(name: 'Private Group', path: 'private_group', visibility_level: Gitlab::VisibilityLevel::PRIVATE) public = Group.create!(name: 'Public Group', path: 'public_group', visibility_level: Gitlab::VisibilityLevel::PUBLIC)
-
Create 3 work items with type
Epicz
in the public group, and one in the private groupwi_type = WorkItems::Type.find_by(base_type: 'epic') child = WorkItem.create!(title: "Child", namespace: public, author: user, work_item_type: wi_type) ancestor1 = WorkItem.create!(title: "Ancestor 1", namespace: public, author: user, work_item_type: wi_type) ancestor2 = WorkItem.create!(title: "Ancestor 2 (cross-group)", namespace: private, author: user, work_item_type: wi_type) ancestor3 = WorkItem.create!(title: "Ancestor 3", namespace: public, author: user, work_item_type: wi_type)
-
Create the hierarchy by adding each epic as a parent of the previous one
WorkItems::ParentLink.create!(work_item: child, work_item_parent: ancestor1) WorkItems::ParentLink.create!(work_item: ancestor1, work_item_parent: ancestor2) WorkItems::ParentLink.create!(work_item: ancestor2, work_item_parent: ancestor3)
-
Logged in as the root user visit
127.0.0.1:3000/-/graphql-explorer
and query the ancestors using the following query:Click to expand
query getAncestors { workItem(id: "gid://gitlab/WorkItem/<child_id>") { title widgets { ...on WorkItemWidgetHierarchy { ancestors { edges { node { title } } } } } } }
-
Verify that the response includes the 3 ancestors in the correct order:
Click to expand
{ "data": { "workItem": { "title": "Child", "widgets": [ { "ancestors": { "edges": [ { "node": { "title": "Ancestor 3" } }, { "node": { "title": "Ancestor 2 (cross-group)" } }, { "node": { "title": "Ancestor 1" } } ] } }, ] } } }
-
Login with a different (non-admin) user and execute the same query. This time the response should only include
Ancestor 1
because the list is truncated at the last visible ancestor:Click to expand
{ "data": { "workItem": { "title": "Child", "widgets": [ { "ancestors": { "edges": [ { "node": { "title": "Ancestor 1" } } ] } } ] } } }
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.