Skip to content

feat(glob): split vite_glob into env/path modules; env globs support negation#425

Merged
wan9chi merged 1 commit into
mainfrom
glob_refactor
Jun 6, 2026
Merged

feat(glob): split vite_glob into env/path modules; env globs support negation#425
wan9chi merged 1 commit into
mainfrom
glob_refactor

Conversation

@wan9chi
Copy link
Copy Markdown
Member

@wan9chi wan9chi commented Jun 5, 2026

vite_glob wraps wax, a filesystem path-glob engine — but most callers use it to match environment-variable names, which are flat strings, not paths. They push &str through is_match(impl AsRef<Path>), which is semantically muddy, and wax exposes no option to disable its path semantics.

This reorganizes the crate into two modules, each with its own matchers and separate error type, and adds negation to env-name matching:

  • vite_glob::envEnvGlob (one literal pattern) and EnvGlobSet (a set), backed by globset with literal_separator(false) and case_insensitive(cfg!(windows)), so */?/[...]/{a,b} are pure flat-string wildcards with the platform's env case rules (sensitive on Unix, insensitive on Windows). EnvGlobSet supports negation: a !-prefixed pattern excludes, and a name matches when it matches an include and no exclude. Errors: EnvGlobError.
  • vite_glob::pathPathGlobSet (the former GlobPatternSet, renamed); still wax-backed with unchanged gitignore (first/last-match-wins) path semantics. Errors: PathGlobError.

This mirrors how Turborepo splits env (regex) from path (wax) matching, and how Turbo treats ! in env wildcards. Non-negated env results are unchanged — globset matches the same */?/[...]/{} syntax wax did for separator-free names, including SENSITIVE_PATTERNS and the Unix/Windows case split (covered by existing envs.rs tests).

User-facing change

env: ["VITE_*", "!VITE_SECRET"] in a task config now fingerprints every VITE_* env except VITE_SECRET. Previously !-prefixed env patterns were dropped with a warning (no negation). Single-pattern EnvGlob (used by the runner's getEnvs) stays literal — ! has no special meaning there.

Migration

Pre-existing callers: envs.rs uses EnvGlobSet for its multi-pattern env matching; vite_workspace switches to PathGlobSet / PathGlobError. The runner-aware env-matching sites consume the single-pattern EnvGlob in the stacked PR #410.

globset is a new dependency (BurntSushi / ripgrep); its transitive deps (aho-corasick, regex) were already in the tree.

Copy link
Copy Markdown
Member Author

wan9chi commented Jun 5, 2026

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Jun 5, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​globset@​0.4.1810010093100100

View full report

@wan9chi wan9chi force-pushed the glob_refactor branch 2 times, most recently from 9c67598 to 6d7dfd5 Compare June 6, 2026 02:53
@wan9chi wan9chi changed the title refactor(glob): back env matching with globset, split EnvGlob / PathGlobSet feat(glob): split vite_glob into env/path modules; env globs support negation Jun 6, 2026
@wan9chi wan9chi force-pushed the glob_refactor branch 5 times, most recently from df080de to 79a5945 Compare June 6, 2026 15:34
…negation

`vite_glob` wrapped `wax`, a filesystem path-glob engine, but most callers
used it to match environment-variable *names* — flat strings, not paths —
by pushing `&str` through `is_match(impl AsRef<Path>)`. That is semantically
muddy, and `wax` exposes no option to disable its path semantics.

Reorganize the crate into two modules, each with its own matchers and error
type:

- `vite_glob::env` — `EnvGlob` (one literal pattern) and `EnvGlobSet` (a set,
  backed by `globset`) with `literal_separator(false)` and
  `case_insensitive(cfg!(windows))`, so `*`/`?`/`[...]`/`{a,b}` are pure
  flat-string wildcards with the platform's env case rules. `EnvGlobSet`
  supports **negation**: a `!`-prefixed pattern excludes, and a name matches
  when it matches an include and no exclude (e.g. `["VITE_*", "!VITE_SECRET"]`).
  Errors: `EnvGlobError`.
- `vite_glob::path` — `PathGlobSet` (the former `GlobPatternSet`, renamed),
  still `wax`-backed with unchanged gitignore (first/last-match-wins)
  semantics. Errors: `PathGlobError`.

This mirrors how Turborepo splits env (regex) from path (wax) matching, and how
Turbo treats `!` in env wildcards. Non-negated env results are unchanged —
globset matches the same `*`/`?`/`[...]`/`{}` syntax wax did for separator-free
names, including SENSITIVE_PATTERNS and the Unix/Windows case split (covered by
existing envs.rs tests).

Migrate the pre-existing callers: `envs.rs` uses `EnvGlobSet` for its
multi-pattern env matching — so `env: ["VITE_*", "!VITE_SECRET"]` in a task
config now excludes `VITE_SECRET` (previously `!` patterns were dropped with a
warning) — and `vite_workspace` switches to `PathGlobSet` / `PathGlobError`.
The runner-aware env-matching sites consume the single-pattern `EnvGlob` in the
stacked PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wan9chi wan9chi marked this pull request as ready for review June 6, 2026 15:56
@wan9chi wan9chi merged commit b472a3f into main Jun 6, 2026
18 checks passed
@wan9chi wan9chi deleted the glob_refactor branch June 6, 2026 15:57
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

.untracked_env
.iter()
.map(std::convert::AsRef::as_ref)
.chain(env_config.fingerprinted_envs.iter().map(std::convert::AsRef::as_ref))
.collect::<Vec<&str>>(),

P2 Badge Resolve env and untracked negations independently

When env and untrackedEnv both contain patterns for the same variable, this merges both lists into one negating matcher before fingerprinting. A negation intended only to subtract from an untracked wildcard, e.g. untrackedEnv: ["CI_*", "!CI_SECRET"] with env: ["CI_SECRET"], removes CI_SECRET from all_envs here, so the later fingerprint pass never sees it and the task does not receive it at all. The two config fields have different meanings, so their include/exclude sets need to be resolved separately and then unioned.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant