Skip to content

fix(ci): match ? and [...] in scope globs per character - #1883

Closed
sileht wants to merge 1 commit into
mainfrom
devs/sileht/mrgfy-10066-scopes-glob-char-semantics/match-scope-globs-per-character--030bec46
Closed

sileht wants to merge 1 commit into
mainfrom
devs/sileht/mrgfy-10066-scopes-glob-char-semantics/match-scope-globs-per-character--030bec46

Conversation

@sileht

@sileht sileht commented Oct 5, 2026

Copy link
Copy Markdown
Member

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

Copilot AI balanced review requested due to automatic review settings October 5, 2026 14:37
@mergify

mergify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 2 of 6 protections blocking · waiting on 👀 reviews

Protection Waiting on
🔴 👀 Review Requirements 👀 reviews
🔴 🔎 Reviews 👀 reviews
🟢 🤖 Continuous Integration —
🟢 Enforce conventional commit —
🟢 📕 PR description —
🟢 🚦 Auto-queue —

🔴 👀 Review Requirements

Waiting for

  • #approved-reviews-by>=2
This rule is failing.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🔴 🔎 Reviews

Waiting for

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

Show 4 satisfied protections

🟢 🤖 Continuous Integration

  • all of:
    • check-success=ci-gate

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:

🟢 📕 PR description

  • body ~= (?ms:.{48,})

🟢 🚦 Auto-queue

When all merge protections are satisfied, this pull request will be queued automatically.

@mergify
mergify Bot deployed to Mergify Merge Protections October 5, 2026 14:37 Active
@sileht
sileht deployed to func-tests-live October 5, 2026 14:38 — with GitHub Actions Active

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 regex dependency.
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.

@mergify
mergify Bot requested a review from a team October 5, 2026 14:46
@sileht
sileht marked this pull request as ready for review October 5, 2026 14:53
JulianMaurin
JulianMaurin previously approved these changes Oct 5, 2026

@JulianMaurin JulianMaurin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

日本語 !

@mergify
mergify Bot requested a review from a team October 5, 2026 14:58
remyduthu
remyduthu previously approved these changes Oct 5, 2026
@mergify

mergify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • ✅ Entered queue — 2026-10-05 15:01 UTC · Rule: default · triggered by merge protections
  • 🚫 Left the queue — 2026-10-05 15:13 UTC · at 91ce6c76968a2c9c16032be8504ab696e51bd329

This pull request spent 11 minutes 46 seconds in the queue, with no time running CI.

Reason

The 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.

Hint

You should update or rebase your pull request.

If you want to requeue this pull request, you can post a @mergifyio queue comment.

Tick the box to put this pull request back in the merge queue (same as @mergifyio queue).

  • Requeue this pull request

@mergify

mergify Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@sileht this pull request is now in conflict 😩

@mergify mergify Bot added the conflict label Oct 5, 2026
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
@sileht
sileht force-pushed the devs/sileht/mrgfy-10066-scopes-glob-char-semantics/match-scope-globs-per-character--030bec46 branch from 91ce6c7 to 5ec5782 Compare October 5, 2026 15:24
@sileht

sileht commented Oct 5, 2026

Copy link
Copy Markdown
Member Author

Revision history

# Type Changes Reason Date
1 initial 91ce6c7 2026-10-05 15:24 UTC
2 content 91ce6c7 → 5ec5782 2026-10-05 15:24 UTC

@sileht
sileht deployed to func-tests-live October 5, 2026 15:24 — with GitHub Actions Active
@mergify
mergify Bot dismissed stale reviews from JulianMaurin and remyduthu October 5, 2026 15:24

Pull request has been modified.

@mergify
mergify Bot had a problem deploying to Mergify Merge Protections October 5, 2026 15:24 Failure
@mergify
mergify Bot requested a review from a team October 5, 2026 15:30
@sileht

sileht commented Oct 6, 2026

Copy link
Copy Markdown
Member Author

Superseded by #1888 (MRGFY-10075), which includes this fix and replaces globset entirely. MRGFY-10066 closes with #1888.

@sileht sileht closed this Oct 6, 2026
sileht added a commit that referenced this pull request Oct 6, 2026
`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 Bot pushed a commit that referenced this pull request Oct 6, 2026
`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>

This branch had an error being deployed

1 failed and 1 active deployments
Mergify Merge Protections — 5ec5782b Deployed Oct 5, 2026 by mergify[bot]
func-tests-live — 5ec5782b Deployed Oct 5, 2026 by sileht via live-tests #1980
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants