Loading
Create links between workflows and work_items
What does this MR do and why?
Stacked MR, that uses the tables created in !239375 (merged)
This MR adds the model-level layer on top of the join tables, for workflow -> work_items
- Added the Ai::DuoWorkflows::WorkflowWorkItem model on the workflow to work-items join table, with a link_type enum (Two link types added here:
source, andcreated). - Extracted shared join-model behavior into the Ai::DuoWorkflows::WorkflowLinkable concern (associations, validations, and a links_workflow_to macro).
- Added the generic Ai::DuoWorkflows::LinkArtifactService as the single entry point for creating workflow-artifact links, dispatching to the right join model by artifact type.
- Leverages the header added in gitlab-org#22201 (closed) to track any work items created by a flow.
References
Starts the linking for #600655 (closed)
Uses the tables created in #599435 (closed)
How to set up and validate locally
- Go to an issue in your GDK
- Add a comment tagging developer, telling it to create a new issue, e.g.
@duo-developer-gitlab-duo Create an issue with this title: "Create a list of cars in cars.txt" - In your rails console, confirm the link was created from the source issue, and to the created issue:
[20] pry(main)> workflow = Ai::DuoWorkflows::Workflow.last
[21] pry(main)> workflow.linked_work_items
...
=> [#<WorkItem id:759 gitlab-duo/ai-assist-2#6>, #<WorkItem id:761 gitlab-duo/ai-assist-2#8>]
[22] pry(main)> workflow.work_item_links
...
=> [#<Ai::DuoWorkflows::WorkflowWorkItem:0x0000000102e09108
id: 3,
workflow_id: 4536,
work_item_id: 759,
project_id: 78,
namespace_id: nil,
created_at: "2026-06-19 22:04:48.766891000 +0000",
updated_at: "2026-06-19 22:04:48.766891000 +0000",
link_type: "source">,
#<Ai::DuoWorkflows::WorkflowWorkItem:0x0000000102e08fc8
id: 4,
workflow_id: 4536,
work_item_id: 761,
project_id: 78,
namespace_id: nil,
created_at: "2026-06-19 22:05:58.106203000 +0000",
updated_at: "2026-06-19 22:05:58.106203000 +0000",
link_type: "created">]
[23] pry(main)> workflow.work_item_links.where(link_type: :source)
...
=> [#<Ai::DuoWorkflows::WorkflowWorkItem:0x0000000139ba9d90
id: 3,
workflow_id: 4536,
work_item_id: 759,
project_id: 78,
namespace_id: nil,
created_at: "2026-06-19 22:04:48.766891000 +0000",
updated_at: "2026-06-19 22:04:48.766891000 +0000",
link_type: "source">]
[24] pry(main)> workflow.work_item_links.where(link_type: :created)
...
=> [#<Ai::DuoWorkflows::WorkflowWorkItem:0x0000000139ba4890
id: 4,
workflow_id: 4536,
work_item_id: 761,
project_id: 78,
namespace_id: nil,
created_at: "2026-06-19 22:05:58.106203000 +0000",
updated_at: "2026-06-19 22:05:58.106203000 +0000",
link_type: "created">]We can also check the inverse:
[4] pry(main)> project = workflow.project
[5] pry(main)> work_item = project&.work_items&.find_by_iid(6)
[6] pry(main)> work_item.linked_duo_workflows
...
=> [#<Ai::DuoWorkflows::Workflow:0x0000000138376688
id: 4536,
user_id: 1,
project_id: 78,An additional test: Click "Implement work item" on a work_item and validate that it has a source link:
> workflow.work_item_linksMR 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.
Edited by Roman Eisner