Skip to content

SET EXPR

Runs a short block of Perl and stores whatever it produces in one stash key. Use it when the value cannot be written as a template: a lookup in the database, a calculation, a list built from other lists, a string cut apart and put back together.

For a plain value or a ${var} template, SET VAR is shorter and safer. When the block runs long, writes several keys, or would read better in JavaScript, Server CODE takes the same code in either language. Neither op traps errors: a run-time failure stops the rule in both.

Fields

Variable

The stash key to write. Type the bare name with no ${} wrapper, and keep it flat: a dot is part of the name rather than a path into nested data.

Leaving it blank does not fail. The op falls back to the node's own name in the rule tree, lowered and reduced to an identifier, with spaces and punctuation folded to _. A node still called SET EXPR writes to a key named set_expr. Rename the node to Build app list and the key becomes build_app_list. That is worth knowing in both directions: renaming a node for readability moves the key, and every unnamed, unconfigured copy of this op in the same rule fights over the same key.

Expression

A code editor with Perl highlighting. The block can be several statements long. The value assigned is the value of the last statement, in the same way a function returns its last expression, so end the block with the thing you want rather than with a semicolon-terminated side effect.

Placeholders are not expanded here. ${foo} inside the expression stays a literal dollar-brace string. Read the stash directly instead: the stash is in scope as a hash reference named stash, so $$stash{foo} gives you the key foo, and you can assign to other keys the same way.

The code is spliced into the rule and compiled with it, which has two consequences worth planning around:

  • A syntax error is caught when you save the rule, not when the job runs. The designer refuses the save with a DSL validation failed message naming the line, and offers Ignore and Save beside it. Take that offer and the rule is stored broken: the next run stops before its first op, because the whole rule is compiled in one piece.
  • A run-time error, a division by zero or a lookup against a collection that is not there, throws and stops the rule at that point. There is no trap around the block and no default value. Wrap the op in TRY statement with a CATCH statement, or set the node's Error Handling to trap or ignore errors, when the rule should carry on.

An empty expression stores nothing usable and leaves the key undefined.

Whatever the block returns keeps its type. Return a list reference and the key holds a list. Return a resource and the key holds a resource, ready for ${myvar.name} later. Return nothing at all and the key is undefined, which reads as empty to every condition op.

What later ops see

The key is written into the same stash every other op reads, so the next op can pick it up with ${myvar} straight away. Nothing about the value is recorded anywhere else. The job log gets one entry for the op, carrying the node's name and nothing more, so neither the expression nor the value it produced shows up there. To see what was computed, follow the op with LOG Message.

Assignments the expression makes to other stash keys stick too. That is a legitimate way to set several keys at once, but it hides the writes from anyone reading the rule tree, so prefer one op per key unless the values are computed together.

During a rollback the op runs again unless you clear Run Rollback on the node. Expressions with side effects outside the stash, a write to a collection or a file, will therefore happen twice over the life of a failed job. Either make them idempotent or restrict the direction on the node.

Combining with other ops

Compute a value here, branch on it with IF var condition THEN, which reads the stash without any code at all.

Return a list and hand it straight to FOREACH CI or FOREACH file/item. Building the list with repeated PUSH VAR ops is usually clearer when the entries arrive one at a time.

For JavaScript rather than Perl, SET JS EXPR assigns the result of a JavaScript expression to a stash key, and falls back to the node's name the same way when you leave its variable blank.

Examples

Derive a short branch name from a topic title.

Variable     branch_name
Expression   my $t = $$stash{topic_title} // 'none';
             $t =~ s/\W+/-/g;
             lc substr( $t, 0, 40 );

Build a comma-separated list for a command line, dropping blanks.

Variable     app_list
Expression   join ',', grep { length } @{ $$stash{apps} || [] };

Keep the result as a real list so a loop op can walk it.

Variable     ports
Expression   [ 8080, 8081, 8082 ];