Skip to content

PUSH VAR

Appends to a list held in a stash key, creating the list on first use. Put it inside a loop or a branch to collect results as the rule walks over things, then read the finished list back once the loop ends.

SET VAR replaces a key outright. This op keeps what is already there and adds to the end of it.

every time the op runs current value turned into a list Value ${...} expanded Flatten? many items or one Unique? drop repeats the key always holds a list afterwards empty entries drop out unless both boxes are cleared

Fields

Variable

The stash key that holds the list. Type the bare name with no ${} wrapper. The name is taken literally, so placeholders in it are not expanded and a dot is part of the name rather than a path.

The key does not have to exist. On the first run the op creates the list for you.

If the key already holds something that is not a list, it is converted before anything is appended. A plain value becomes a one-entry list. A hash becomes a one-entry list containing that hash. Either way the original shape is gone, so pointing this op at a key that other ops read as a single value quietly breaks them.

The conversion also cleans the list. Entries that are unset or empty strings are thrown away on every pass, so a list built elsewhere can come back from this op shorter than it went in.

Blank leaves you appending to a key with an empty name, which nothing else can read.

Value

A multi-line text area. ${...} placeholders are expanded against the stash before the value is appended, using the same rules as SET VAR: a value that is nothing but a placeholder keeps its original type, while a placeholder with text around it is flattened to a string.

An empty value, or a placeholder that resolves to an empty string, normally adds nothing. The op runs, the list does not grow, and nothing tells you. This is the usual reason a collected list comes out shorter than the number of loop iterations. The exception is with both checkboxes below cleared: that combination does append an empty entry.

Flatten before insertion?

Ticked by default on a newly dropped op.

Ticked, a value that resolves to a list is unpacked and each entry is appended separately, so merging one list into another works as you would expect. Empty entries are dropped during the unpacking.

Cleared, the value is appended as a single entry. Feeding it a list then gives you a list nested inside your list, which loop ops will walk one level too shallow. Clear this only when you are deliberately building a list of lists.

Keep values unique?

Ticked by default on a newly dropped op.

After appending, repeats are removed from the whole list and the first occurrence of each value wins, so order is preserved. Entries are compared as text, which matters at the edges: 7 and 007 count as different, and two separately loaded copies of the same resource can both survive, because objects compare by identity rather than by contents. Push resource ids rather than resources when you want this check to mean something.

Cleared, the list keeps every entry in the order it arrived, repeats included.

Behaviour in a job

The value that was appended is never logged, and neither is the length of the list. To watch the list grow, follow the op with LOG Message and print ${myvar}.

The whole operation happens on every pass. Inside a loop that runs 200 times, the key is re-checked, re-listed and de-duplicated 200 times, which is fine for the sizes rules normally deal with and noticeable if you are collecting tens of thousands of entries.

During a rollback the rule runs again, and this op appends again unless you clear Run Rollback on the node. With Keep values unique? ticked that is harmless. With it cleared, the list doubles.

Rule quality analysis counts the name in Variable as declared by this op. If nothing later in the rule reads it, the analysis reports it as a variable that is not used, and a strict enough quality gate refuses to save the rule. The same analysis flags an op still carrying its palette name, so rename the node to say what it is collecting.

Combining with other ops

The natural pairing is a loop. Put this op inside FOREACH file/item or FOREACH CI and it collects one entry per pass.

Guard the push with IF var condition THEN to collect only the entries that matter.

After the loop, test the result with NOT EMPTY in IF var condition THEN, or walk it with another loop op.

To start from a known list rather than an empty one, run SET VAR first with the value set to a single ${...} placeholder so the type survives.

Examples

Collect changeset ids as a loop walks them, keeping the list clean.

Variable                     changeset_mids
Value                        ${changeset.mid}
Flatten before insertion?    yes
Keep values unique?          yes

Merge a list of revisions found this pass into a running total.

Variable                     all_revisions
Value                        ${revisions}
Flatten before insertion?    yes
Keep values unique?          yes

Build a list of lists, one entry per pass, by turning flattening off.

Variable                     batches
Value                        ${batch_items}
Flatten before insertion?    no
Keep values unique?          no