Custom review instructions: support brace expansion in fileFilters glob patterns
## Problem The `fileFilters` glob matcher used by GitLab Duo for custom review instructions does not support brace expansion (`{a,b,c}`), even though our public documentation has shown it in examples (`**/*.{h,hpp}`, `**/*.{js,jsx}`). Users following those examples saw no review comments for the patterns they expected to cover — the pattern is treated as a literal string and silently fails to match. Concrete check: ``` python3 -c "import fnmatch; print(fnmatch.fnmatch('app/main.h', '**/*.{h,hpp}'))" # False ruby -e "p File.fnmatch?('app/main.h', '**/*.{h,hpp}', File::FNM_PATHNAME)" # false ``` ## Root cause Two implementations, both without brace-expansion support today: - **Classic Duo Code Review (Ruby):** [`ee/lib/gitlab/duo/code_review/custom_instruction.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/duo/code_review/custom_instruction.rb) calls `File.fnmatch?(pattern, path, File::FNM_PATHNAME)`. Ruby supports brace expansion in `File.fnmatch?` via the `File::FNM_EXTGLOB` flag, which is not passed. - **Agent Platform (Python):** [`duo_workflow_service/tools/code_review.py`](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/main/duo_workflow_service/tools/code_review.py) calls `fnmatch.fnmatch(path, pattern)` from the standard library. Python's stdlib `fnmatch` does not support brace expansion, and the code does no preprocessing of `{...}` patterns. ## Proposal Add brace-expansion support to both implementations so the behavior matches user expectations and our prior documentation: - **Ruby (low effort).** Add `File::FNM_EXTGLOB` to the flags passed to `File.fnmatch?` in `custom_instruction.rb`. Effectively a one-line change. - **Python (medium effort).** Two options: 1. Preprocess `{a,b,c}` patterns into multiple separate patterns before calling `fnmatch.fnmatch`, and OR the results. Roughly 15 lines, no new dependencies. 2. Replace `fnmatch.fnmatch` with a library that supports brace expansion natively, such as [`wcmatch`](https://pypi.org/project/wcmatch/). Option 1 keeps the dependency surface unchanged and is sufficient for the use case. ## Workaround Until this is supported, users must list each pattern separately: ```yaml fileFilters: - "**/*.h" - "**/*.hpp" ``` This is now documented on both custom review instructions pages. ## Related - !237945 — docs MR removing the misleading examples and adding a note about the current limitation. - #600607 — related issue on making custom instruction processing more deterministic.
issue