Support '*' wildcards in --actions selectors as documented (#2224) - #2234
Support '*' wildcards in --actions selectors as documented (#2224)#2234ihistand wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
/gcbrun |
|
PTAL at following error: |
| // escaped); each '*' matches any run of characters, so "mrd*" -> /^mrd.*$/ and | ||
| // "*features*" -> /^.*features.*$/. | ||
| function globToRegExp(pattern: string): RegExp { | ||
| const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, ".*"); |
There was a problem hiding this comment.
Can you simplify this logic?
There was a problem hiding this comment.
Agreed, that was doing too much at once — escaping every metacharacter including *, then
un-escaping \* back into .*. You had to read both replaces together to see what it did.
Rewritten to split on the wildcards, escape the literal parts, and rejoin:
function globToRegExp(pattern: string): RegExp {
const escapeLiteral = (literal: string) => literal.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
return new RegExp(`^${pattern.split("*").map(escapeLiteral).join(".*")}$`);
}Behaviour is unchanged — the existing matchPatterns tests pass, and I diffed the two
implementations exhaustively over patterns covering every regex metacharacter plus ** and a**b.
There was a problem hiding this comment.
(note that this change isn't pushed yet, awaiting response)
There was a problem hiding this comment.
sounds ok, but let's comment the choice of characters and why first replace is needed
There was a problem hiding this comment.
// Turns a selector pattern into an anchored RegExp in which "" is a wildcard and
// everything else is literal text, e.g. "mrd" -> /^mrd.$/ and
// "features" -> /^.features.$/.
//
// Splitting on "" first is what keeps the rest simple: every "" in a pattern is a
// wildcard by definition, so the pieces between them are pure literal text and can be
// escaped wholesale, then rejoined with ".".
//
// The escape is needed because an action name is not regex-safe. Names are
// dot-separated ("project.dataset.name"), and "." in a regex matches any character, so
// without escaping "schema." would also select "schemaXtable" — see the "literal dot"
// case in utils_test.ts. The set below is the usual list of JavaScript regex
// metacharacters with one deliberate omission: "", which is left out because the split
// above has already consumed every "*", so none can reach here. ("]" and "" carry
// backslashes for the character class's own syntax; "-" and "/" are not metacharacters
// outside a class and so need no escaping.)
function globToRegExp(pattern: string): RegExp {
const escapeLiteral = (literal: string) => literal.replace(/[.+?^${}()|[]\]/g, "\$&");
return new RegExp(^${pattern.split("*").map(escapeLiteral).join(".*")}$);
}
…co#2224) matchPatterns did plain string equality only, so the '*' wildcards the --actions help text (run + compile) advertises never matched anything — `run --actions "*"` / "mrd*" reported "No actions to run." Compile wildcard patterns to an anchored RegExp: non-'*' characters match literally (regex metacharacters escaped, so '.' stays a literal dot), each '*' becomes '.*'. A pattern containing '.' matches the fully-qualified action name, otherwise the unqualified last segment — mirroring the existing exact-match branches. Wildcards bypass the ambiguous-name error since matching many actions is the intent; exact selection is unchanged. Adds a matchPatterns test suite (previously untested). Fixes dataform-co#2224
18e4fb3 to
7df93b7
Compare
|
/gcbrun |
kolina
left a comment
There was a problem hiding this comment.
Let's fix issues from #2234 (comment)
| // escaped); each '*' matches any run of characters, so "mrd*" -> /^mrd.*$/ and | ||
| // "*features*" -> /^.*features.*$/. | ||
| function globToRegExp(pattern: string): RegExp { | ||
| const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, ".*"); |
There was a problem hiding this comment.
sounds ok, but let's comment the choice of characters and why first replace is needed
Escaping every metacharacter (including '*') and then un-escaping '\*' back into '.*' meant reading the pair of replaces together to see what it does, and made the literal-asterisk case hard to check by eye. Split on the wildcards instead, escape the literal parts, and rejoin with '.*'. Same behaviour: verified against the existing matchPatterns tests, and exhaustively against the previous implementation over patterns covering every regex metacharacter plus '**' and 'a**b'.
Port of the upstream review outcome on dataform-co/dataform#2234. Escaping every metacharacter (including '*') and then un-escaping '\*' back into '.*' meant reading the pair of replaces together to see what it does. Split on the wildcards instead, escape the literal parts, and rejoin with '.*'. Behaviour is unchanged. The comment now explains why the escape is needed and why '*' is excluded from the character set, and records that '*' spans dots on purpose -- SQLAnvil action names have two parts on Postgres/MySQL and three on BigQuery, so component-wise matching would make "*.orders" silently select nothing depending on the warehouse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W86VUf4ptKnmhxWoqgA7gb
|
/gcbrun |
kolina
left a comment
There was a problem hiding this comment.
I don't have more comments, but #2234 (comment) still needs to be fixed
Fixes #2224 — following up on #2224 (comment) ("Feel free to send a PR :)").
Problem
The
--actionshelp text forrunandcompilesays patterns "can include '*' wildcards", butmatchPatternsincore/utils.tsdoes plain string equality only, so no wildcard pattern ever matches —dataform run --actions "*"reportsNo actions to run.even when the compiled graph has actions.Fix
Wildcard patterns are compiled to an anchored
RegExp:*character matches literally (regex metacharacters are escaped, so.stays a literal dot);*matches any run of characters (mrd*→/^mrd.*$/,*features*→/^.*features.*$/).Scoping mirrors the existing exact-match branches: a pattern containing
.matches against the fully-qualified action name; otherwise it matches against the unqualified last segment. Wildcard matches bypass the ambiguous-name error since selecting many actions is the intent. Exact (non-wildcard) selection behavior is completely unchanged.Tests
Adds a
matchPatternssuite tocore/utils_test.ts(the function was previously untested) covering: exact unqualified/qualified selection, the ambiguity error, bare*, prefix and substring wildcards, qualified wildcards (schema.*), no-match returning empty, and the literal-dot escaping edge case.Understood that GCP Dataform's hosted actions filter doesn't use this implementation — this change only brings the open-source CLI in line with its own documented behavior.
🤖 Generated with Claude Code
https://claude.ai/code/session_0171FwKo8gRQQ35VoYDtSHNU