Define a minimal, stable filter attribute set for the pipeline_hooks flow trigger

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Background

The pipeline_hooks flow trigger (behind the ai_flow_trigger_pipeline_hooks feature flag) already supports customer-configurable filters via a GraphQL mutation. The filter evaluation engine (Ai::FlowTriggers::FilterEvaluator + Gitlab::FilterEvaluator) supports the following operators: eq, ne, gt, lt, contains, not_contains, in, not_in.

Filters are stored as a JSON structure on Ai::FlowTrigger#filter, keyed by hook scope (e.g. pipeline_hooks), and evaluated against the full pipeline webhook payload produced by Gitlab::DataBuilder::Pipeline (the same serializer used for project webhooks).

Today, the Fix CI/CD Pipeline foundational flow uses this mechanism with a built-in precondition (not customer-configurable) that enforces:

{
  "match": "all",
  "rules": [
    { "field": "object_attributes.status", "operator": "eq", "value": "failed" }
  ]
}

Customers have expressed a need to further scope which failing pipelines trigger the flow — for example, only master-broken failures (source: push && ref: master) or only non-draft MR pipelines (source: merge_request_event && merge_request.title not_contains Draft:).

Problem

The current filter implementation evaluates rules against the entire pipeline webhook payload (Gitlab::DataBuilder::Pipeline). This payload is large and was designed for webhook consumers, not for flow trigger configuration. Exposing it directly to customers creates tight coupling to an internal serialization format that may change, and surfaces many fields that are irrelevant or potentially sensitive in the context of flow triggers.

Before the ai_flow_trigger_pipeline_hooks FF is rolled out broadly, we need to define a minimal, stable set of pipeline attributes that customers can filter on, and validate/allowlist those fields in the filter evaluation path.

Requirements

Filterable attributes (minimum viable set)

The following attributes must be supported as filter fields for the pipeline_hooks trigger:

Field path Type Description Example values
pipeline.source string How the pipeline was triggered push, merge_request_event, schedule, web, api, trigger
pipeline.ref string The branch or tag the pipeline ran on master, main, release/1.0
pipeline.merge_request.title string Title of the associated merge request (if any) "Fix login bug", "Draft: WIP feature"

Note: pipeline.status is already handled by the Fix Pipeline foundational flow's built-in precondition (object_attributes.status eq failed) and does not need to be part of the customer-configurable filter set for that flow. However, it may be useful for custom flows.

Supported operators

All three fields must support the following operators (already implemented in Gitlab::FilterEvaluator):

  • eq — equals
  • ne — not equals
  • contains — string contains substring
  • not_contains — string does not contain substring

Field allowlisting / validation

  • The filter evaluation for pipeline_hooks must only accept the fields listed above (and object_attributes.status for the precondition). Any filter rule referencing an unlisted field path should be rejected at save time (GraphQL mutation validation) and/or silently skipped at evaluation time.
  • This prevents customers from coupling their trigger configuration to internal webhook payload fields that may change.

Payload mapping

The filter data passed to Ai::FlowTriggers::FilterEvaluator for pipeline_hooks must be a purpose-built minimal hash (not the raw Gitlab::DataBuilder::Pipeline output). The mapping from pipeline model attributes to filter field paths should be:

Filter field path Pipeline model attribute
pipeline.source Ci::Pipeline#source
pipeline.ref Ci::Pipeline#ref
pipeline.merge_request.title Ci::Pipeline#merge_request&.title
object_attributes.status Ci::Pipeline#status (for precondition compatibility)

Example filter configurations

Only trigger on master-broken pipelines (push to master):

{
  "pipeline_hooks": {
    "match": "all",
    "rules": [
      { "field": "pipeline.source", "operator": "eq", "value": "push" },
      { "field": "pipeline.ref", "operator": "eq", "value": "master" }
    ]
  }
}

Only trigger on MR pipelines that are not drafts:

{
  "pipeline_hooks": {
    "match": "all",
    "rules": [
      { "field": "pipeline.source", "operator": "eq", "value": "merge_request_event" },
      { "field": "pipeline.merge_request.title", "operator": "not_contains", "value": "Draft:" }
    ]
  }
}

What exists today

  • Ai::FlowTriggers::FilterEvaluator — merges the customer-defined base_filter with the foundational flow's precondition and delegates to Gitlab::FilterEvaluator.evaluate.
  • Gitlab::FilterEvaluator — generic rule engine supporting nested groups, match: all/any, and the operators listed above. Field values are resolved via dot-notation path traversal (dig_value).
  • EE::Ci::Pipelines::HookService#execute_flow_triggers — calls project.execute_flow_triggers(hook_data, :pipeline_hooks) where hook_data is the full Gitlab::DataBuilder::Pipeline payload.
  • Mutations::Ai::FlowTriggers::Create / Update — accept a free-form JSON filter argument (no field-level validation today).
  • The Fix Pipeline precondition (object_attributes.status eq failed) is defined in Ai::Catalog::FoundationalFlow['fix_pipeline/v1'].precondition and is always AND-ed with the customer filter.

Out of scope

  • UI for configuring filters (tracked separately — see the thread on #592451 (closed))
  • Group/instance-level enablement controls (tracked in #600203)
  • Expanding the filterable attribute set beyond the minimum defined here (can be done incrementally once the allowlist mechanism is in place)
  • Renaming the pipeline_hooks event type (separate concern)

References

  • Parent issue: #592451 (closed) — Implement trigger: Pipeline Failed
  • Discussion thread: #592451 (comment 3467210059)
  • Ai::FlowTriggers::FilterEvaluator: ee/app/services/ai/flow_triggers/filter_evaluator.rb
  • Gitlab::FilterEvaluator: lib/gitlab/filter_evaluator.rb
  • EE::Ci::Pipelines::HookService: ee/app/services/ee/ci/pipelines/hook_service.rb
  • Ai::Catalog::FoundationalFlow (fix_pipeline/v1 precondition): ee/app/models/ai/catalog/foundational_flow.rb
Edited by 🤖 GitLab Bot 🤖