Repository navigation
Conversation
Merge Protections🔴 2 of 6 protections blocking · waiting on 👀 reviews
🔴 👀 Review RequirementsWaiting for
This rule is failing.
🔴 🔎 ReviewsWaiting for
This rule is failing.
Show 4 satisfied protections🟢 🤖 Continuous Integration
🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
🟢 📕 PR description
🟢 🚦 Auto-queueWhen all merge protections are satisfied, this pull request will be queued automatically. |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused Unicode correction includes regression coverage, with no unresolved review findings.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes Unicode scope matching in mergify ci scopes so ? and character classes match characters rather than UTF-8 bytes.
Changes:
- Recompiles globset patterns as Unicode-aware regular expressions.
- Adds regression tests and documents known engine differences.
- Adds the workspace
regexdependency.
| File | Description |
|---|---|
crates/mergify-ci/src/scopes_detect/matching.rs |
Implements Unicode matching and adds regression coverage. |
crates/mergify-ci/Cargo.toml |
Declares the shared regex dependency. |
Cargo.lock |
Records the dependency for mergify-ci. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Merge Queue Status
This pull request spent 11 minutes 46 seconds in the queue, with no time running CI. ReasonThe pull request conflicts with the base branch The pull request was held in the queue, conflicting with at least one of 2 pull requests ahead of it. The conflict became a base branch one after #1879, #1881 merged. HintYou should update or rebase your pull request. If you want to requeue this pull request, you can post a Tick the box to put this pull request back in the merge queue (same as
|
|
@sileht this pull request is now in conflict 😩 |
globset compiles a glob to a `(?-u)` byte regex, so in `mergify ci scopes` a `?` matched one byte and `[é]` was a class of é's two UTF-8 bytes. The engine matches `str`, so on any non-ASCII path a pattern like `critical/caf?.txt` put `critical/café.txt` in the scope on the engine side and not in `ci scopes`, which then skipped the scope-gated job. globset still parses the glob (braces, escapes, `literal_separator` all unchanged); its regex is recompiled in Unicode mode, with the `\xNN` byte escapes folded back into the characters they spell. Fixes MRGFY-10066 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: I030bec464bbd2a85413524f6e652ea850265a905
91ce6c7 to
5ec5782
Compare
Revision history
|
Pull request has been modified.
`mergify ci scopes` matched scope globs with globset, the engine with its own brace expansion plus Python's `glob.translate`. Even with `*` bounded and `?` matching characters, the two dialects still disagreed on ASCII patterns, so one config could select different files in CI and in the merge queue: - `[^x]` negated in globset, it is a class holding `^` and `x` for the engine; - a class spanning a separator (`x[a/b]y`) was a class in globset, the engine splits the pattern on separators first, so it is literal text; - `\` was an escape in globset, it is a path separator for the engine. Replace globset with `engine_glob`, a port of the engine's `globs.expand_braces` and of `glob.translate(recursive=True, include_hidden=True, seps=["/", "\\"])`, emitting a `regex` crate pattern. `engine_glob_cases.json` holds patterns and paths with the verdicts the engine itself gives, generated by `engine_glob_cases.py` from the engine's `globs.py` on Python 3.14 with the `regex` module, and a test checks this side reproduces every one. A local run of the same comparison over ~190,000 random pattern/path pairs found no other difference. The one deliberate divergence: the `regex` module reads `[:name:]` inside a set as a POSIX class, which swallows the glob class's closing bracket. The engine then rejects the pattern or matches something meaningless; the CLI refuses it as a configuration error. A regex that fails to compile is a bug in the port, so it is reported as such rather than as the user's config. This also matches `?` and `[...]` per character on non-ASCII paths, which #1883 (MRGFY-10066) did on top of globset; that pull request is closed in favour of this one. Fixes MRGFY-10075 Fixes MRGFY-10066 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: I67724907949c50cfc3f10f37dd968cc2e68dab2e
`mergify ci scopes` matched scope globs with globset, the engine with its own brace expansion plus Python's `glob.translate`. Even with `*` bounded and `?` matching characters, the two dialects still disagreed on ASCII patterns, so one config could select different files in CI and in the merge queue: - `[^x]` negated in globset, it is a class holding `^` and `x` for the engine; - a class spanning a separator (`x[a/b]y`) was a class in globset, the engine splits the pattern on separators first, so it is literal text; - `\` was an escape in globset, it is a path separator for the engine. Replace globset with `engine_glob`, a port of the engine's `globs.expand_braces` and of `glob.translate(recursive=True, include_hidden=True, seps=["/", "\\"])`, emitting a `regex` crate pattern. `engine_glob_cases.json` holds patterns and paths with the verdicts the engine itself gives, generated by `engine_glob_cases.py` from the engine's `globs.py` on Python 3.14 with the `regex` module, and a test checks this side reproduces every one. A local run of the same comparison over ~190,000 random pattern/path pairs found no other difference. The one deliberate divergence: the `regex` module reads `[:name:]` inside a set as a POSIX class, which swallows the glob class's closing bracket. The engine then rejects the pattern or matches something meaningless; the CLI refuses it as a configuration error. A regex that fails to compile is a bug in the port, so it is reported as such rather than as the user's config. This also matches `?` and `[...]` per character on non-ASCII paths, which #1883 (MRGFY-10066) did on top of globset; that pull request is closed in favour of this one. Fixes MRGFY-10075 Fixes MRGFY-10066 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
globset compiles a glob to a
(?-u)byte regex, so inmergify ci scopesa?matched one byte and[é]was a class of é's two UTF-8bytes. The engine matches
str, so on any non-ASCII path a patternlike
critical/caf?.txtputcritical/café.txtin the scope on theengine side and not in
ci scopes, which then skipped the scope-gatedjob.
globset still parses the glob (braces, escapes,
literal_separatorall unchanged); its regex is recompiled in Unicode mode, with the
\xNNbyte escapes folded back into the characters they spell.Fixes MRGFY-10066
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com