Trigger risk classification from the flow trigger platform

What does this MR do and why?

Nothing started a risk classification. The flow existed, a project could turn it on, and it still never ran: something had to call it, and that something was a service and a worker written only for this one flow.

The flow now declares its own triggers instead. It runs when a merge request opens and when one changes from draft to ready, so turning the flow on for a project is the only switch a user touches. That is how every other foundational flow works.

Getting there needed one thing the platform did not have. A flow sometimes has to put a record in place before it starts, and there was no way to say so from a flow definition. Two optional callbacks, before_start and after_start, close that: each takes the triggered resource, each defaults to nothing. Risk classification uses before_start to record that a classification is running, which is what lets the widget tell "running" from "never ran" once it ships.

before_start fires after the last check that can still refuse a run, not before it. Otherwise a refused run would leave a record claiming a classification is in progress.

This is deliberately incomplete. Nothing scores the claims a run sends back, and nothing expires a record whose run goes quiet. Both arrive with the scoring work, which is also when duo_mr_risk_classification can be turned on. Until then a triggered run stores its claims and stops there. Left as a draft for that reason.

What the flow is told about the merge request it classifies is a separate change, !254877 (merged). Both target master and neither depends on the other, but a run started from this branch alone stops at the agent's input validation, because the agent platform config expects the inputs that MR sends. Check out both to watch a run reach the agent.

References

Screenshots or screen recordings

Not applicable. No user-facing surface changes here: the widget that reads the record ships in !251381 (merged).

How to set up and validate locally

The flow is ultimate_only, so the GDK needs an Ultimate licence. One feature flag gates the flow:

# Gates the flow itself. Without it the flow is hidden in group settings, and a
# trigger that somehow fires is refused.
Feature.enable(:duo_mr_risk_classification)

The "merge request created" event needs no flag of its own. It fires for any project that already has an active trigger.

  1. Turn the flow on for the top-level group. Go to the group, then Settings > GitLab Duo > Change configuration. Under Flow execution, select Allow flow execution and Allow foundational flows, select Risk Classification, then Save changes.

  2. Turn it on for the project. Go to the project, then Settings > General, expand GitLab Duo, turn on GitLab Duo, Allow flow execution and Allow foundational flows, then Save changes.

  3. Confirm the triggers came with it. Go to AI > Triggers in the project. Risk Classification has a trigger listing the merge request and merge request ready events, created for you when the flow was turned on. That is the point of this MR: enabling the flow is the only switch, where before nothing started a classification at all.

  4. Open a merge request, or mark an existing draft as ready. Then go to AI > Sessions: a Risk Classification session appears for it.

  5. Confirm before_start recorded the run, which is what the widget will read to tell "running" from "never ran":

    mr = MergeRequest.last
    
    mr.risk_assessment.status     # => "pending"
    mr.risk_assessment.diff_sha   # => the merge request head SHA
    mr.risk_assessment.score      # => nil, nothing scores it yet
  6. This branch alone stopped at input validation. The agent platform config asked for inputs this branch does not send:

    input 'risk_classification' does not match specified schema: 'merge_request_iid' is a required property

    The two merge requests that supplied the missing inputs, !254877 (merged) and gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6872 (merged), have since merged. A run on current master now reaches its submit step instead. This MR is responsible for everything up to that point: the trigger fired, a session started, and the record is in place.

  7. Confirm a flow that declares no callbacks is unaffected, so this changes nothing for every other flow:

    Ai::Catalog::FoundationalFlow.code_review_v1.run_before_start(resource: MergeRequest.last)
    # => nil

MR 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 Wanderson Policarpo

Merge request reports

Loading
Loading