From db0e7da00eb47fc2c2bf549ea388c05ffa59038f Mon Sep 17 00:00:00 2001 From: Mehdi ABAAKOUK Date: Fri, 31 Jul 2026 16:52:20 +0200 Subject: [PATCH] docs: document brace alternation in glob patterns Brace alternation (`**/*.{js,ts}`) works in the engine as well as in mergify-cli, and was documented nowhere. Document it where the glob syntax reference actually lives, in `configuration/data-types.mdx`, rather than in `conditions.mdx`, which only links there. Cover the surprising parts: an empty branch is dropped, an unbalanced brace is a configuration error rather than a literal, and patterns are capped at 128 alternatives and 32 levels of nesting. Link the scopes pages to that reference, which they never did, and show the brace form for `scopes.source.files`. Fixes MRGFY-8393 Change-Id: I8a2c5abba0a84ed107f6e43a628c9eb0375ff68d --- src/content/docs/configuration/data-types.mdx | 48 ++++++++++++++++++- src/content/docs/merge-queue/scopes.mdx | 2 +- .../docs/merge-queue/scopes/file-patterns.mdx | 19 ++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/content/docs/configuration/data-types.mdx b/src/content/docs/configuration/data-types.mdx index babdf3f49a..27fc2d1564 100644 --- a/src/content/docs/configuration/data-types.mdx +++ b/src/content/docs/configuration/data-types.mdx @@ -35,7 +35,10 @@ pull_request_rules: ## Globs -You can use globs expressions with matching operators in your [conditions](/configuration/conditions). +Glob patterns are used by the `*=` operator in your +[conditions](/configuration/conditions), by +[file-pattern scopes](/merge-queue/scopes/file-patterns), and by +[`barrier_files`](/merge-queue/scopes#declaring-a-pull-request-impacts-every-scope). {/* eslint-disable */} | Pattern | Description | @@ -46,6 +49,7 @@ You can use globs expressions with matching operators in your [conditions](/conf | `?` | Matches one non-separator character. | | `[seq]` | Matches one character in `seq`, where `seq` is a sequence of characters. Range expressions are supported; e.g., `[a-z]` matches any lowercase ASCII letter. Multiple ranges can be combined, e.g. `[a-zA-Z0-9_]` matches any ASCII letter, digit, or underscore. | | `[!seq]` | Matches one character **not** in `seq`, where `seq` follows the same rules as above. | +| `{a,b}` | Matches either `a` or `b`. See [brace alternation](#brace-alternation). | {/* eslint-enable */} :::note @@ -61,6 +65,48 @@ The `**` wildcard enables recursive globbing. A few examples: | `assets/**` | Any path starting with `assets/`. | | `assets/**/*` | Any path starting with `assets/`, excluding `assets/` itself. | +### Brace alternation + +A brace group matches any one of its comma-separated branches. Mergify expands +the group into one pattern per branch, so `**/*.{js,ts}` is equivalent to +listing `**/*.js` and `**/*.ts` separately: + +```yaml +pull_request_rules: + - name: label frontend changes + conditions: + - files *= web/**/*.{js,jsx,ts,tsx} + actions: + label: + add: + - frontend +``` + +A pattern can contain several groups, and groups can nest. `{a,b{c,d}}` matches +`a`, `bc` and `bd`, and `{src,tests}/**/*.{py,pyi}` covers the four +combinations of directory and extension. + +:::caution + An empty branch is dropped rather than matching nothing, so `foo{,.txt}` + matches `foo.txt` but **not** `foo`. List the two patterns separately when you + need both. +::: + +An unbalanced `{` or `}` is a configuration error, not a literal brace. Mergify +rejects the configuration instead of leaving you with a pattern that silently +matches nothing. To match a brace as a character, escape it as `\{` or `\}`, or +bracket it as `[{]` or `[}]`; a literal comma inside a group is `\,`. + +A pattern may expand to at most 128 alternatives and nest at most 32 levels +deep. Beyond either limit, Mergify rejects the configuration. + +:::note + YAML reads `{` at the start of a value as the beginning of a mapping, so quote + a pattern that starts with a brace: `'{src,tests}/**'`. Backslash escapes need + single quotes or no quotes at all, since a double-quoted YAML string treats + `\{` as an invalid escape. +::: + ## Regular Expressions {/* fix links to "Operators" */} diff --git a/src/content/docs/merge-queue/scopes.mdx b/src/content/docs/merge-queue/scopes.mdx index 3bc9707bc3..7b9f1890ea 100644 --- a/src/content/docs/merge-queue/scopes.mdx +++ b/src/content/docs/merge-queue/scopes.mdx @@ -128,7 +128,7 @@ queue_rules: - `scopes.source`: selects how scopes are provided. - `files`: map scope names to the file patterns that define them. Each entry accepts `include` - and optional `exclude` lists. + and optional `exclude` lists of [glob patterns](/configuration/data-types#globs). - `manual`: instructs Mergify to expect scopes from external systems via the API or GitHub Action. diff --git a/src/content/docs/merge-queue/scopes/file-patterns.mdx b/src/content/docs/merge-queue/scopes/file-patterns.mdx index c7526b0915..fb64cb1954 100644 --- a/src/content/docs/merge-queue/scopes/file-patterns.mdx +++ b/src/content/docs/merge-queue/scopes/file-patterns.mdx @@ -46,6 +46,25 @@ Mergify will intelligently batch PRs with overlapping scopes together. For examp they share a common scope. ::: +## Pattern Syntax + +`include` and `exclude` accept the same [glob patterns](/configuration/data-types#globs) as the `*=` +operator in conditions. That includes +[brace alternation](/configuration/data-types#brace-alternation), which collapses a list of +extensions into one pattern. The `frontend` scope above can also be written as: + +```yaml +scopes: + source: + files: + frontend: + include: + - web/**/*.{js,jsx,ts,tsx} +``` + +Mergify validates every pattern when it loads your configuration. An unbalanced `{` is a +configuration error, not a scope that silently matches nothing. + ## How Mergify Evaluates File-Pattern Scopes Mergify evaluates file-pattern scopes itself. For each pull request, it matches the changed files