Skip to content

IF condition THEN

Runs the ops nested underneath it when a piece of code you write comes back true. The code can be Perl or JavaScript, and it can look at anything the rule can reach, not only the stash.

This is the escape hatch. Reach for it when the test needs arithmetic, a file check, a database lookup or a call into the API. For a comparison against stash values, IF var condition THEN gets there with no code and stays readable to whoever inherits the rule.

Condition Code Perl the last value decides JavaScript you must return a value result true? run the block skip the block

Fields

Programming language

Picks the language for the code below. The choices are Perl and JavaScript, and a new op arrives set to Perl.

Choosing a language repaints the editor with matching syntax highlighting and shows or hides the help button next to it. It does not translate what you already wrote. Switching an op from Perl to JavaScript leaves you with Perl in a JavaScript editor, and the rule then fails with a parse error the first time it reaches the op.

JS API Help

The small button beside the language combo, labelled only by its tooltip. It opens the developer documentation in the help panel, which lists what the JavaScript side can call.

It shows while JavaScript is selected and hides the moment you pick Perl. An op that arrived without a language of its own, from an imported or hand-edited rule, shows the button as well even though the combo reads Perl.

Condition Code

The code itself, in a full-height editor.

For Perl, the value of the last expression decides the branch. There is no return to write. An empty editor counts as false, quietly, with no error.

For JavaScript, your code is wrapped in a function and that function is called, so you have to return the answer. Code that computes the right thing and forgets to return it is false every time. The evaluator starts clean at every evaluation, so nothing you declare here survives into the next op or the next pass through a loop.

Nothing in this field expands ${var} before the code runs. Read values through the stash instead, as described below.

Reaching the stash

In Perl the stash is in scope as $stash. A top-level key reads as $$stash{name}, and nested values follow the same shape: $$stash{topic}{title}.

In JavaScript the stash is not laid out as plain variables. Call cla.stash('name') for a top-level key. For anything nested, pass a slash path: cla.stash('/topic/title'), with numbers for list positions, as in cla.stash('/changesets/0/name'). The two-argument form writes a value back, which makes it easy to leave a side effect in a condition by accident.

Failure behaviour

Perl that does not compile stops the whole rule when it starts, before the first op runs. The error names the rule rather than the op, so a rule that used to work and now dies at startup is usually a condition someone edited.

Perl that compiles but dies at run time stops the rule and fails the job at that point. It is not treated as a false condition.

JavaScript is different in timing. The code is not looked at until the op is reached, so a syntax error in JavaScript gets past the start of the rule and stops the job partway through, on the pass where the op first runs. The message names the JavaScript problem. A branch that only runs on Fridays will only break on a Friday.

If you want a condition that tolerates its own failure, set Error Handling on the ops inside the block rather than trying to catch it here, or move the risky part into Server CODE ahead of the branch and test the value it leaves behind.

What it does at run time

A new op arrives with 1 in the editor, which is always true. An op left that way runs its block unconditionally and is easy to miss when reading the tree.

Before the condition is evaluated, the op records the name you gave it in the job log at debug level, and checks whether a cancel was requested on the job. A cancel found here ends the job with the name of the user who asked for it. Both of those happen whether the condition turns out true or false, so a skipped block still leaves a trace with the Debug filter on.

The name also lands in the stash as current_task_name, with any ${var} in it expanded. Every named op overwrites it, so read it inside the block and not two ops later. Nothing else is written unless your own code writes it.

ELSE and ELSIF condition THEN attach directly after it. Note that ELSIF only accepts Perl, so a chain that starts in JavaScript has to continue in Perl or nest a second IF instead.

On a rollback pass the code runs again against the stash as it stands then. Conditions with side effects run twice on a job that rolls back.

Combining with other ops

Keep the condition to one expression and put the work somewhere visible. Server CODE runs the same two languages, stores its result under a Return Key, and shows up properly in the log. Branch afterwards on that stored value with IF var condition THEN.

LOG Message inside each branch makes a code-driven decision reviewable after the fact, which a bare condition is not.

FAIL nested inside turns a failed check into a job that stops with your own message rather than a raw error.

Examples

Branch on the number of entries a previous op left in the stash.

Programming language   Perl
Condition Code         scalar @{ $$stash{changed_files} || [] } > 0

Branch on a value that is not a plain string comparison, in JavaScript.

Programming language   JavaScript
Condition Code         var n = cla.stash('build_number');
                       return n && parseInt(n, 10) % 2 === 0;

Skip a block when a file the job was supposed to produce is not there.

Programming language   Perl
Condition Code         -e parse_vars('${job_dir}/foo/bar.sql', $stash)