Expressions are small computations on Pull Request attributes. Expressions are most useful in workflow conditions, string templates, and custom merge checks. Expressions can be as simple as a constant (like a number or a string) or an attribute value, but expressions can also be more complex manipulation of attributes.
Some examples of expressions are
-
draft -
true -
'Hello World' -
'PR ${title} opened by ${author}' -
source ~= 'bugfix/*' -
count(approved-by) -
builds.successful -
forall(changed-files, $1 ~= '**/*.js')
Expressions can be composed in any form or fashion using expression operators described below, as long as their type requirements are fulfilled. If an expression does not type-check (e.g., source > 3), it will make the devsensei.yaml file invalid.
Expressions can return any type, but expressions involved in conditions have to return a boolean. For example, even though count(approved-by) is a valid expression, it is not valid as part of the conditions.
String Template Literals
A literal string also supports templating. Arbitrary expressions can be spliced in with ${expr} if expr is convertible to string.
Template Examples
-
'PR: ${title}'directly embeds thetitleattribute of typestring. -
'Found ${count(commits)} commits'embeds the expressioncount(commits)of typeintby automatic conversion tostring.
String Conversions
Expressions of the following types may be directly inserted into a string template: int, boolean, string, regex (inserts the pattern).
Other types, such as duration, range, users, sets and arrays, cannot be inserted directly. Use join to turn a collection of strings into a single string, e.g. 'Keys: ${join(jira-keys, ', ')}'.
💡 We plan to support more data types in string templates soon. Let us know if you need this for your use case.
Lambda functions 🔬
Some functions require a lambda function as argument, for example exists or forall. A lambda function looks like a usual expression except $1 is used as a placeholder for the function argument.
For example, the following expressions are valid lambdas:
-
$1 ~= 'alice' -
'${$1}' ~= 'alice'(the same via conversion.) -
!$1 -
count($1) < 50 -
contains(reviewers.approved, $1)
As a complete example, the following expression checks that at least one reviewer is called "alice":
-
exists(reviewers, $1 = 'alice'),
in this expression reviewers is a collection of type set(pr-participant), and $1 is a placeholder that will be substituted with each reviewer in the collection until a true result is found.
since 9.8 Lambdas can be nested, and $1 may be used several times within one lambda. $1 always refers to the argument of the innermost lambda. For example:
-
exists(commits, forall($1.jira-keys, $1 ~= 'PROJ-*')) -
map(changed-lines.added, '${$1.file-path}: ${$1.text}')
Only the single argument $1 is supported, and it may only be used inside a lambda.
Expression Syntax reference
Atomic expressions
|
Kind |
Example |
|---|---|
|
boolean literals |
|
|
integer literals |
|
|
string literals, enclosed in single quotes. Within quotes, the following escapes are supported: |
|
|
unquoted strings: a single word without spaces or any of |
|
|
an attribute reference |
|
|
lambda function argument reference |
|
|
wrapped expressions: |
|
compound expressions
|
Kind |
Syntax |
Example |
|---|---|---|
|
infix operator |
|
|
|
prefix operator |
|
|
|
function call |
|
|
|
property access |
|
|
Whitespace
Outside of string literals, spaces are insignificant, with these exceptions:
-
no space between a function name and its opening parenthesis:
count(commits), notcount (commits) -
no spaces around the
.of a property access:builds.successful -
the prefix
notmust be followed by a space:not draft
Combining infix operators
An infix operator takes exactly one operand on each side; infix operators cannot be chained. Use parentheses to combine them, e.g. (count(approved-by) > 1) = draft instead of count(approved-by) > 1 = draft. There are no and / or operators within an expression.
Expression types
Here are the following types that can be involved in expressions
Markers show the constraints a type satisfies, which some operators require of their arguments:
-
⚖️ equatable: values can be compared with
=and!=, and can be elements of aset. -
🔤 displayable: values can be inserted into a string template or joined with
join.
|
Type name |
Description |
|---|---|
|
|
type variables, used in the signatures of generic operators. Every occurrence of the same variable in one signature stands for the same type, e.g. |
|
|
a value that is one of either |
|
|
any UTF-8 text value. |
|
|
a string written directly in the expression, e.g. |
|
|
an integer value (between |
|
|
a sequence of elements of type |
|
|
an aggregate of unique elements of type |
|
|
someone identified by a key: a platform user or a git author, e.g. the elements of |
|
|
a registered application user, e.g. |
|
|
a user participating in the PR review, e.g. the elements of |
|
|
the author of a commit, as recorded by git (identified by email). Can be used wherever |
|
|
a lambda function expression taking an argument of type |
|
|
Value that represents a duration, such as 1 minute or 2 days. Durations can be created using the |
|
|
Regular expression object to be used for string comparisons (with the |
|
|
Represents values between a lower bound (inclusive) and an upper bound (exclusive). Ranges can be created using the |
|
|
a commit in the PR, e.g. the elements of |
|
|
a line changed in the PR's diff, e.g. the elements of |
|
|
a build reported for the PR's latest commit, e.g. the elements of |
|
|
a file changed in the PR's diff, the |
|
|
an open task on the PR. Tasks can only be counted (e.g. |
Expression Operators
Use Operators to transform expressions into more complex ones. For example, to compare two int values or to count the number of elements in a set. Operators can be infix (only for binary operators), prefix or call. Infix operators are placed within their arguments, prefix operators must be placed before their arguments, and call operators must enclose their argument(s) in parenthesis, separated by commas.
|
Operator |
Meaning |
Type |
Position |
Example |
|---|---|---|---|---|
|
|
Matches a string against a pattern: a glob (branch pattern) given as a string, or a regex. A regex matches if the pattern occurs anywhere in the string. On a collection of strings (e.g. On changed lines since 9.1 , returns true when the content of at least one line matches the regex. |
|
|
|
|
|
Negation of glob or regex match (i.e. no matches) |
Same signatures as |
|
|
|
|
Equals A user can be compared with a string holding a user key, with the arguments in either order: |
|
|
|
|
|
Not equals |
Same signatures as |
|
|
|
|
Negate a boolean attribute (use of |
|
|
|
|
|
Number, string length or duration comparison |
|
|
|
|
|
Computes the number of elements in a |
|
|
|
|
|
Checks whether a set of users contains a user matching the given user key, e.g. |
|
|
|
|
|
Negates a boolean expression |
|
|
|
|
|
Checks whether the items in the first argument collection all satisfy the predicate specified by the lambda in the second argument. Always returns |
|
|
|
|
|
Checks whether there is at least one item in the first argument collection that satisfy the predicate specified by the lambda in the second argument. Always returns |
|
|
|
|
since 9.2 |
Keeps only elements from the collection in the first argument that satisfy the predicate specified by the lambda in second argument. |
|
|
|
|
since 9.2 |
Returns a new collection by transforming all elements in the first argument collection by the lambda in the second argument. Mapping a |
|
|
|
|
|
Joins the elements of a collection into a single string, separated by the specified delimiter. Elements must be displayable (see String Conversions). |
|
|
|
|
|
Creates a range between the specified bounds (lower is inclusive, upper is exclusive) |
|
|
|
|
since 9.3 |
Returns the part of the string in the first argument with characters taken from the range specified as second argument. If the range is empty (i.e., lower bound bigger than or equal to the upper bound), then returns the empty string. |
|
|
|
|
|
Creates a duration from its expression. A duration expression is a number followed by a time unit, with or without a space, e.g. |
|
|
|
|
|
Creates a regular expression from its string pattern representation. The pattern must be a literal string, e.g. If the pattern is not valid, the DevSensei configuration will be invalid as well. Please refer to the re2 regex specification for its syntax. |
|
|
|
|
since 9.3 |
Uses a regular expression with a matching group to extract its value within the string given as first argument. The regular expression must have exactly 1 defined group, otherwise the expression is invalid. If the regular expression does not match the string, this function returns the empty string. |
|
|
|
Attributes🔰
These are the various attributes available to use in conditions, retrigger-on, and merge-checks. Each attribute results in a typed value when evaluated.
Attributes labelled with the lightning emoji ⚡️ can be used in the retrigger-on section. Each retrigger-on entry must be exactly one attribute name, not an expression.
|
Condition Attribute |
Type |
Meaning |
|---|---|---|
|
|
|
The pull request title |
|
|
|
The pull request description |
|
|
|
Source branch of pull request |
|
|
|
Destination branch of pull request |
|
|
|
Destination repository of pull request |
|
|
|
The SHA-1 hash of commit of the HEAD ref on the source branch |
|
|
|
Is it a draft pull request |
|
|
|
Whether the Pull Request currently has conflicts with the target branch. |
|
since 8.6 |
|
The user who created the PR. |
|
since 8.11 |
|
Time since the pull request was opened. Conditions involving the age can be configured via a schedule. |
|
|
|
The tasks that are still open in the PR. Tasks can only be counted, e.g. |
|
|
|
The set of users who have approved the PR. Compare with a user key, e.g. |
|
|
|
The set of users who are reviewers of the PR and their review status. Has properties |
|
since 8.6 |
|
The set of paths of all files that are affected by the pull request. Has properties |
|
since 9.1 |
|
The list of all changed lines (added or removed) that are affected by the pull request. Has properties |
|
since 8.6 |
|
The set of builds for the most recent commit for the pull request. Has properties |
|
since 8.7 |
|
The set of users who are watchers of the PR. Watchers are people that interacted with the pull request. See Bitbucket documentation. |
|
since 8.7 |
|
List of commits in this PR. Has properties |
|
since 8.7 |
|
Set of Jira keys mentioned in all commit messages. |
|
|
n/a |
Only usable in |
Attribute and data types Properties 🔬
Some attributes have properties, (for use in property access expressions) that provide a view over the contained data.
|
attribute/data type |
Property |
Meaning |
|---|---|---|
|
|
|
The successful builds |
|
|
|
The failed builds |
|
|
|
The builds that are in progress |
|
|
|
The name of the build. Eg |
|
|
|
The key of the build |
|
|
|
Only the new files that were not seen before |
|
|
|
Only the files that will be deleted after merging |
|
|
|
Only the files that changed (and possibly also moved). |
|
|
|
Only the files that were not changed, but were moved |
|
|
|
Only the added lines |
|
|
|
Only the removed lines |
|
|
|
Only the reviewers who have approved the PR. |
|
|
|
Only the reviewers who have requested changes on the PR. |
|
|
|
Only the reviewers who have not completed their review. |
|
|
|
The key identifying the person (user key, or email for a git author). Eg |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The title of the commit message (the first line) |
|
|
|
set of Jira keys in commit. Eg |
|
since 9.1 |
|
The content of the line Eg |
|
|
|
The path (from repository root) of the line |
|
|
|
Whether the line was added within the PR |
|
|
|
Whether the line was removed within the PR |
|
since 9.2 |
|
The path (from repository root) of the file in the PR diff. A |
|
|
|
Whether the file was added in the PR |
|
|
|
Whether the file was deleted in the PR |
|
|
|
Whether the file was modified in the PR |
|
|
since 9.3 |
The changed lines of this file, with properties |