Expressions
PullApprove expressions allow you to write powerful, custom rules to design your workflow.
Expressions are evaluated in a Python environment, using the provided functions and variables. You can use human-readable operators like "in", "not in", "and", and, "or".
The same syntax powers the group conditions, pullapprove_conditions, and notification filters.
Single vs multi-line
Most basic expressions can be written in a single line. In YAML, you'll typically want to surround these with quotes since you'll have quotes inside.
version: 3
groups:
security:
conditions:
- '"security" in labels'
When you're comparing lots of values, it may be easier to write the expression over multiple lines.
version: 3
pullapprove_conditions:
- >
contains_any_fnmatches(files, [
"packages/*",
"apps/*",
"docs/*",
])
Examples
You can apply the same basic operations to most of the data we make available. Here are some common examples of how to use the available functions and variables.
Files
Basic string comparisons will use fnmatch under the hood.
"*.js" in files or "frontend/*" in files
You can also use the contains_any_fnmatch
function to check more paths at once without writing lots of "or" lines.
contains_any_fnmatches(files, [
"packages/*",
"apps/*",
"docs/*",
])
Or globs!
contains_any_globs(files, [
"packages/animations/**",
"packages/platform-browser/animations/**",
"aio/content/guide/animations.md",
"aio/content/examples/animations/**",
"aio/content/images/guide/animations/**",
"aio/content/guide/complex-animation-sequences.md",
"aio/content/guide/reusable-animations.md",
"aio/content/guide/route-animations.md",
"aio/content/guide/transition-and-triggers.md",
])
glob("packages/**/*.js") in files
You can also chain the include
and exclude
methods to further filter down a list of files:
files.include("src/*").exclude("*.md")
Branches
Use the base
and head
branch variables.
base.ref == "master"
base.ref != base.repo.default_branch
"feature" in head.ref
Labels
"bug" in labels
"sig-*" in labels
regex('.*/app') in labels
Other PullApprove groups
Use the state of preceding groups (above the current group in your config).
len(groups.approved) > 3
"admins" in groups.passing
Checks and statuses
The "checks" on a PR come in two forms: the Checks API, and the commit Statuses API.
The GitHub interface often combines these, making it hard to tell the difference.
The best way to tell the difference is to look for the Checks tab on a PR page.
For anything on that page (like GitHub Actions/Workflows), use the check_runs
object.
If you have a status that is not on that page, it will be found in statuses
.
Checks
"build" not in check_runs.failed
Statuses
"*travis*" in statuses.succeeded
PR body or title
"WIP" in title
regex("WIP: .*") in title
"needs review" in body
PR size
changed_files > 30
PR author
author in ["internA", "internB"]
author_association == "FIRST_TIME_CONTRIBUTOR"
Mergeability
not mergeable
Git diff and files changed
contains_regex(files.patches, '(?m)^[\+\-].*dangerouslySetInnerHTML.*')
Dates
created_at < date('3 days ago')