Validate pipeline event flow trigger filter fields
What does this MR do and why?
Addresses #597413
Trigger filters for pipeline_hooks events that use unsupported fields or invalid values save cleanly but silently never match any event, so a typo in a filter means the flow never runs and the user gets no feedback.
This MR validates pipeline_hooks filter rules against an allowlist of fields and values, so an invalid filter now fails with a clear validation error at create and update time. It mirrors the approach taken for merge_request/work_item action values in !244173 (merged):
- New
ALLOWED_FILTER_FIELDSallowlist onAi::FlowTrigger:object_attributes.status:running,success,failed,canceled(matches the statuses offered in the UI)object_attributes.source: anyEnums::Ci::Pipeline.sourceskeymerge_request.title: any value
- Unknown fields inside
pipeline_hooksfilters are rejected; values are checked per field. - The existing
collect_action_valuestraversal is reimplemented on a sharedcollect_leaf_ruleshelper (behavior-preserving; the pre-existing specs from !244173 (merged) pass unchanged). - Errors surface through the existing
ServiceResponse→ GraphQL mutationerrorspath; no service, GraphQL, or frontend changes. The filter format and supported pipeline event fields/values are documented on the Triggers page.
Behind the new feature flag validate_flow_trigger_filter_fields (gitlab_com_derisk, default off, project actor) so that updates to pre-existing records with now-invalid filters are not broken before a staged rollout.
Other event types are unaffected: event types without an entry in ALLOWED_FILTER_FIELDS are skipped entirely, and the merge_request/work_item action validation stays independently gated behind validate_flow_trigger_filter_actions.
How to set up and validate locally
-
Enable the feature flag in the rails console:
project = Project.find_by_full_path('<project full path>') Feature.enable(:validate_flow_trigger_filter_fields, project) -
Build an invalid trigger in the console:
trigger = project.ai_flow_triggers.new( description: 'test', config_path: '.gitlab/duo/flows/test.yaml', user: User.find_by(username: '<service account username>'), event_types: [Ai::FlowTrigger::EVENT_TYPES[:pipeline_hooks]], filter: { 'pipeline_hooks' => { 'rules' => [ { 'field' => 'object_attributes.status', 'operator' => 'eq', 'value' => 'passed' }] } } ) trigger.valid? # => false trigger.errors.full_messages # => ["Filter contains invalid object_attributes.status values for pipeline_hooks: passed. # Allowed values are: running, success, failed, canceled"] trigger.filter = { 'pipeline_hooks' => { 'rules' => [ { 'field' => 'object_attributes.ref', 'operator' => 'eq', 'value' => 'main' }] } } trigger.valid? # => false trigger.errors.full_messages # => ["Filter contains invalid fields for pipeline_hooks: object_attributes.ref. # Allowed fields are: object_attributes.status, object_attributes.source, merge_request.title"] Feature.disable(:validate_flow_trigger_filter_fields, project) trigger.valid? # => true (validation skipped when the flag is off) -
Or via GraphQL: send
aiFlowTriggerCreate/aiFlowTriggerUpdatewith afilterlike the above and confirm the message is returned in the mutationerrorsarray. Valid filters (for example{"pipeline_hooks": {"rules": [{"field": "object_attributes.status", "operator": "in", "value": ["failed", "canceled"]}]}}) save without errors.
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.
References
- #597413
- !244173 (merged) (equivalent validation for merge_request/work_item action values)