fix(workflows): filter parser rejects trailing tokens (fullmatch, not match) (#3689)

_apply_filter parsed a name(arg) filter with an UNANCHORED regex
(re.match(r"(\w+)\((.+)\)")), so any tokens after the closing paren were
silently discarded. Because _evaluate_simple_expression splits the top-level
pipe before comparison/boolean operators, `count | default(0) > 5` was split
into value `count` and filter segment `default(0) > 5`; the segment matched
as `default(0)` and `> 5` vanished — the filter's value was returned as the
whole expression, giving a silently wrong result.

Use re.fullmatch so a mis-wired segment falls through to the existing
"unsupported form" ValueError, mirroring the from_json branch's strict
trailing-token handling. The greedy `.+` still matches legitimate forms
(literal `)` / `|` inside quoted args), so registered/chained/quoted-pipe
filters are unaffected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali jawwad
2026-07-23 23:37:07 +05:00
committed by GitHub
parent 5ad312863f
commit 043c4ec572
2 changed files with 30 additions and 2 deletions

View File

@@ -392,8 +392,14 @@ def _apply_filter(value: Any, filter_expr: str, namespace: dict[str, Any]) -> An
)
return _filter_from_json(value)
# Parse filter name and argument
filter_match = re.match(r"(\w+)\((.+)\)", filter_expr)
# Parse filter name and argument. Use fullmatch (not match) so trailing
# tokens after the closing paren — e.g. a comparison/boolean operator that
# binds looser than the pipe, as in ``count | default(0) > 5`` — are not
# silently discarded but fall through to the "unsupported form" ValueError
# below, mirroring the strict trailing-token handling of the from_json
# branch above. The greedy ``.+`` still handles literal ``)`` and ``|``
# inside quoted args.
filter_match = re.fullmatch(r"(\w+)\((.+)\)", filter_expr)
if filter_match:
fname = filter_match.group(1)
farg = _evaluate_simple_expression(filter_match.group(2).strip(), namespace)