Skip to content

Server CODE

Runs a block of JavaScript or Perl on the Clarive server, in the middle of the rule, with the stash in scope. This is the escape hatch for logic no other op covers: reshaping a list, calling a library, reading the database, building one value out of three others.

Reach for it after the palette runs out, not before. SET EXPR already covers a one-line calculation and the condition builder in IF var condition THEN already covers comparisons. Eval Remote is the op that runs code on a target machine; this one always runs on the server. Server CODE supersedes CODE and EVAL, both of which are marked deprecated in the palette.

Clarive server stash Server CODE JavaScript: cla.stash() Perl: $stash in scope last value goes to Return Key an error here stops the rule

Fields

Programming language

JavaScript or Perl. A freshly dropped op starts on JavaScript. Changing the selection re-highlights the editor and shows or hides the help button next to it; it does not translate anything you have already typed. The setting belongs to the op, so one rule can hold blocks in both languages.

Code

The block itself, in an editor with syntax highlighting for the language above. There is no length limit and no ${...} expansion: the text is handed to the language exactly as you typed it. In JavaScript, backtick template strings work, so `build-${n}` interpolates a JavaScript variable, never a stash variable.

JavaScript blocks run in strict mode, which is not optional and is not shown anywhere in the form. Assigning to a name you never declared throws instead of quietly creating a global, and an octal literal such as 0755 is rejected outright.

Whatever the block evaluates to last is its value. See the return value for the rules, which are less obvious than they look.

JS API Help

The small button beside the language selector, tooltip JS API Help. It opens the JavaScript introduction in the help panel, which is the way into the module reference. The button is there while the language is JavaScript and disappears when you switch to Perl.

The return value

The block produces one value: whatever its last evaluated expression produced. Put a name in Return Key on the op's Options tab and that value is stored in the stash under that name. Leave Return Key empty and the value is thrown away.

Return Key takes a bare variable name with no ${} around it, and it has to be a single word. A key with a space in it is dropped without a warning, so my key stores nothing at all.

Two traps, one per language:

  • In JavaScript, a declaration is not an expression. A block ending in var total = 7; returns nothing. End with a bare expression instead, total;. A top-level return is a syntax error here, because your code is not wrapped in a function.
  • In Perl, return does work, and it does more than you want: it ends the whole rule immediately. Every op after this one is skipped and nothing in the log says why. Finish the block with a plain expression instead.

Reading and writing the stash

In JavaScript the stash is reached through cla.stash. cla.stash('foo') reads a top-level key, cla.stash('foo', 3) writes one, and cla.stash() with no argument hands back the whole stash as an object. Nested values need a slash path, cla.stash('/topic/title'), not a dotted one; dots are path separators inside ${...} templates, which is a different mechanism. The full interface is in cla/stash, and the module list is in the Clarive JavaScript DSL.

In Perl the stash arrives as $stash, an ordinary hash reference you index by key. Resources, database access and the logging helpers are in scope too, the same ones available anywhere else in rule code.

Values written to the stash by either language survive for the rest of the rule and, in a job, for the rest of the job. Each JavaScript block runs in a brand new engine, so a variable set in one block is gone by the next one and every require reloads from scratch. That fresh engine has a cost: a JavaScript block inside a loop pays for engine startup on every iteration, so when the loop is long, move the loop inside the block.

Perl leaks where JavaScript does not, and whether it leaks depends on Return Key. With the key empty the block is dropped straight into the rule, so a my variable declared here is still in scope in the next Perl block further down the same branch. Fill the key in and the block gets a scope of its own, and that variable stops at the end of it. Write to the stash rather than relying on either behaviour: adding a Return Key later will break code that leaned on the leak, with no warning.

When the code fails

A JavaScript error stops the rule and reports the message with a line number and a stack. A Perl die at runtime does the same. Either way the ops after this one do not run, and in a job the step ends in error.

The two languages fail at different moments. A Perl block is compiled together with the whole rule, so a syntax error in it is caught the moment you save: the designer refuses with a DSL validation failed message and offers Ignore and Save beside it. Save it anyway and no op in the rule runs at all, not even the ones above the broken block. JavaScript is compiled only when the op is reached and is never checked at save time, so a typo in a branch that rarely runs stays hidden until the day it runs.

To survive a failure, set Error Handling on the op's Options tab to trap or ignore errors, or wrap the op in TRY statement and CATCH statement.

What shows in the job log

The op contributes one entry to the job log: its name. The code itself logs nothing, however much it computes. To report progress, call the logging module from JavaScript, described in cla/log, or drop a LOG Message op beside the block.

In JavaScript, console.warn, console.error and console.debug reach the job log. console.log goes to the server output instead, where a job operator will never see it.

Rollback

The op runs in the forward pass and again during rollback, because Run Forward and Run Rollback on the Options tab are both on by default. Code that changes something outside Clarive should check the job mode before acting, or sit under an IF ROLLBACK block. Nothing the block does is undone for you.

Combining with other ops

Use the block to prepare a value, then let ordinary ops act on it. A block that writes a list to the stash pairs with FOREACH CI or FOREACH file/item to walk it, and one that writes a flag pairs with IF var condition THEN to branch on it. Both read better in the tree than the equivalent if buried inside the block.

When the value is a single expression, SET EXPR does the same work in one line and shows the variable name in the tree.

To stop the rule on a verdict the block reached, write the verdict to the stash and let FAIL raise it. The message then lands in the log as a rule failure rather than as a code error.

Examples

Derive a tag from two stash values and hand it to later ops.

Programming language: JavaScript
Return Key: release_tag

  var env = cla.stash('bl');
  var version = cla.stash('version') || '0';

  'rel-' + version + '-' + env.toLowerCase();

Decide whether the job is inside its maintenance window, and read the answer later with a condition op. Note the bare expression on the last line.

Programming language: Perl
Return Key: window_open

  my $hour = (localtime)[2];
  $hour >= 22 || $hour < 6 ? 1 : 0;

Build a list for a loop to consume. Nothing is returned, so Return Key stays empty and the block writes to the stash itself.

Programming language: JavaScript
Return Key:

  var log = require('cla/log');
  var all = cla.stash('changesets') || [];

  var urgent = all.filter(function(cs) {
      return cs.category === 'hotfix';
  });

  log.info('hotfix changesets: ' + urgent.length);
  cla.stash('urgent_changesets', urgent);