Duo Developer: MR-triggered flows do not check out the MR source branch
<!--IssueSummary start--> <details> <summary> Everyone can contribute. [Help move this issue forward](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#contributor-links) while earning points, leveling up and collecting rewards. </summary> - [Label this issue](https://contributors.gitlab.com/manage-issue?action=label&projectId=278964&issueIid=603034) </details> <!--IssueSummary end--> ## Summary When the **Duo Developer** flow is triggered from a **merge request** (e.g. via an `@`-mention in an MR note), the MR's **source branch is not passed through** to the workflow. As a result the workspace is built from the **default branch**, not the MR branch — so the agent operates on the wrong ref. This is independent of the workspace clone strategy: it affects both the default shallow path and the full-clone path (`dap_full_clone`, !240212). It was found while validating the full-clone option on a local GDK. ## Evidence (local GDK) Triggered Duo Developer via a mention on MRsource branch `duo/feature/8-append-dap-marker` @ `31c442e9`, target = default branch). - Workload pipeline ref / SHA: `f1919d0b` = **default branch tip** (not the MR branch) - `DUO_WORKFLOW_SOURCE_BRANCH` in the job: **empty** - Full-clone checkout: `Already on 'swe-bench-seeder-…'` (the default branch) Expected: the workspace checks out the MR's source branch (`duo/feature/8-…`). ## Root cause `Ai::FlowTriggers::RunService` has two separate, inconsistent `source_branch` paths: 1. `#source_branch` (feeds the workflow params → `DUO_WORKFLOW_SOURCE_BRANCH`) only resolves for `Ci::Pipeline` resources: ```ruby def source_branch resource.source_ref if resource.is_a?(::Ci::Pipeline) end ``` 2. `#branch_args` (builds the workload pipeline ref) uses a different rule: ```ruby source_branch = resource.source_branch if resource.is_a?(MergeRequest) ``` For an MR **note mention**, `resource` is the note (not a `MergeRequest`/`Pipeline`), so both fall through to `nil` → default branch. ## Proposed fix Resolve the MR from the trigger context (note → noteable MR) and populate `source_branch` from it for **both**: - the workflow params (so `DUO_WORKFLOW_SOURCE_BRANCH` is set), and - the workload branch ref (`branch_args`), so MR-triggered flows consistently land on the MR's source branch. Add coverage for the note-on-MR mention case. ## Out of scope - The `dap_full_clone` workspace change itself (!240212) — its checkout logic is correct given the inputs; this issue is about supplying the right input. ## References - !240212 (full-clone workspace option) - #602990 (FF rollout — "what can go wrong" references this) - #602558 (investigation)
issue