Hi all,
I’ve run into a limitation in Gerrit submit requirements when trying to express path-dependent validation rules and wanted to check whether this is expected and/or if there’s interest in improving it.
Use caseWe have a single repository with a subdirectory (aviary/) that has its own CI pipeline and verification requirements, separate from the rest of the repo.
We would like to express the following behaviour via submit requirements:
Changes affecting only aviary/** → require Aviary checks only
Changes affecting only non-aviary/** paths → require non-Aviary checks only
Changes affecting both → require both sets of checks
The positive case works fine: applicableIf = file:^aviary/.*
ProblemThere does not appear to be a way to express:
“there exists a changed file that is not under aviary/”
The natural regex form would be:
However, this fails during submit-requirement validation:
This appears to be because the expression is first parsed by Gerrit’s query parser, which rejects the ? before the file:operator sees the pattern.
I also tried:
quoting: file:"^(?!aviary/).*"
brace grouping: file:{^(?!aviary/).*}
These are accepted syntactically in some contexts, but do not behave correctly for applicability. I also tried variations of double and higher escaping.
NOTE:
This is semantically different from negating the existing file: predicate.
NOT file:^aviary/.*
means:
"no changed file is under aviary/"
whereas:
fileNot:^aviary/.*
means:
"there exists at least one changed file not under aviary/"
These differ for mixed changes (touching both aviary and non-aviary paths), which is exactly the case we need to support.
The only viable workaround seems to be moving this logic into CI orchestration (e.g. an aggregator build that decides which labels to apply), rather than expressing it in submit requirements. This works, but loses the declarative nature of submit requirements and introduces ordering/race concerns.
ProposalIt would be very useful to have a first-class way to express the negative case, for example:
or
with semantics:
file:^aviary/.* → at least one changed path matches
fileNot:^aviary/.* → at least one changed path does not match
This would allow clean expression of mixed-path requirements without relying on regex lookahead or CI-side logic.
Why a new operator?While it might be possible to extend the query parser to support more complex regex constructs, this would require changes to the parser and could introduce unintended compatibility issues.
A dedicated operator seems:
clearer to users
easier to document
safer from a backward-compatibility perspective
Is there an existing way to express this that I’ve missed?
Would a fileNot: / pathNot: predicate be acceptable?
If so, I’m happy to work on this. I’ve attached a draft patch to illustrate the approach — happy to revise or rework this based on feedback.
Thanks!
David
There does not appear to be a way to express:
“there exists a changed file that is not under aviary/”
Hi all,
I wanted to follow up with a correction and some additional findings after digging further into the implementation.
CorrectionIn my original message, I suggested that the file: operator uses Java regex matching. That is only partially true.
The implementation behaves differently depending on whether the input matches the FILE_EDITS_PATTERN:
If it matches:
then Gerrit uses FileEditsPredicate, which does rely on java.util.regex.Pattern.
Otherwise, it falls back to the standard path handling:
which ultimately uses RegexPathPredicate → RegexListSearcher → dk.brics.automaton.RegExp.
The dk.brics regex engine does not support lookahead constructs, so patterns such as: ^(?!aviary/).* cannot be expressed via the normal file: operator, even if they pass parsing.
Attempt to use FILE_EDITS_PATTERNI also attempted to force the FileEditsPredicate path using:
This was intended to:
However:
FileEditsPredicate evaluates both:
This means its behaviour differs from file: in important ways, for example:
So while it uses Java regex, it does not provide a clean way to express “there exists a changed file not matching X”.
Thanks,
David