Add wildcard-to-wildcard pattern matching for MRAP

Summary

Implements wildcard-to-wildcard (pattern-to-pattern) matching for Merge Request Approval Policies (MRAP) branch targeting, behind the wildcard_pattern_overlap_for_mrap feature flag.

Problem: When an MRAP policy specifies branches: ["production-v1*"] and a project has a wildcard protected branch rule production-*, the system fails to associate them because it only matches patterns against literal branch names — never pattern-to-pattern. This means the policy won't generate approval rules for the matching protected branch unless literal branches happen to exist as intermediaries.

Solution: Added RefMatcher#overlaps? — a recursive algorithm with memoization that detects whether two *-glob patterns have overlapping match sets. Integrated into the MRAP sync pipeline so protected_branch_ids resolution directly compares policy patterns against protected branch rule patterns.

Related issue: #586351

Changes

File What
app/models/ref_matcher.rb Added #overlaps? public method + private patterns_overlap? algorithm
ee/app/services/security/scan_result_policies/approval_rules/base_service.rb Overlap check in protected_branch_ids, behind feature flag
ee/app/services/security/security_orchestration_policies/base_project_policy_service.rb Same overlap check in approval_policy_protected_branch_ids
config/feature_flags/development/wildcard_pattern_overlap_for_mrap.yml Feature flag definition
spec/models/ref_matcher_spec.rb #overlaps? describe block
spec/support/shared_examples/ref_matcher_shared_examples.rb 24 shared examples (16 core + 8 symmetry)
ee/spec/services/security/scan_result_policies/approval_rules/create_service_spec.rb 4 integration tests

How to test locally

Prerequisites

  1. GDK running with a project that has a security policy management project configured
  2. Enable the feature flag:
    Feature.enable(:wildcard_pattern_overlap_for_mrap)

Test scenario 1: Pattern overlap (superset policy pattern)

  1. Create a new project
  2. Go to Code > Branches
  3. Click on New branch
  4. Add a branch called production-v1
  5. Go to Settings > Repository
  6. Expand the Protected branches section
  7. Click on Add protected branch
  8. Create a wildcard protected branch rule production-*
  9. Go to Secure > Policies
  10. Click on New policy
  11. Select Merge Request Approval Policy
  12. Create a policy like:
approval_policy:
  - name: Wildcard test policy
    description: ''
    enabled: true
    enforcement_type: enforce
    rules:
      - type: scan_finding
        branches:
          - "prod*"
        scanners:
          - container_scanning
        vulnerabilities_allowed: 0
        severity_levels:
          - critical
        vulnerability_states:
          - detected
    actions:
      - type: require_approval
        approvals_required: 1
        role_approvers:
          - developer
      - type: send_bot_message
        enabled: true 
  1. Click on Create a new project with the new policy
  2. Merge the MR to create the policy
  3. Wait for the policy to sync (or trigger manually via Security::SyncScanPoliciesWorker.new.perform(project.id))
  4. Expected: An ApprovalProjectRule is created and linked to the production-* protected branch
  5. Verify in Rails console:
project = Project.second_to_last
rule = project.approval_rules.last
rule.protected_branches.map(&:name)
# => ["production-*"]

Test scenario 2: Subset policy pattern

  1. Same setup but use branches: ["production-v1*"] in the policy
  2. Expected: Still matches production-* protected branch (because production-v1* is a subset of production-*)

Test scenario 3: Non-overlapping patterns

  1. Same setup but use branches: ["release/*"] in the policy
  2. Expected: Does NOT match production-* protected branch (different character at position 7: / vs u)

Test scenario 4: Feature flag disabled (regression)

  1. Disable the feature flag: Feature.disable(:wildcard_pattern_overlap_for_mrap)
  2. Repeat scenario 1
  3. Expected: Falls back to existing behavior — only matches if literal branches exist as intermediaries

Running specs

# Unit tests for the overlap algorithm
bundle exec rspec spec/models/ref_matcher_spec.rb

# Integration tests for the sync pipeline
bundle exec rspec ee/spec/services/security/scan_result_policies/approval_rules/create_service_spec.rb

# Existing service specs (regression)
bundle exec rspec ee/spec/services/security/security_orchestration_policies/base_project_policy_service_spec.rb

Feature flag

wildcard_pattern_overlap_for_mrap — disabled by default. Enable to activate pattern-to-pattern overlap matching in MRAP branch targeting.

Edited by Marcos Rocha

Merge request reports

Loading