Shipfox
Reference

Expressions (CEL)

Look up the syntax, operators, and functions available inside a Shipfox expression.

Shipfox expressions use CEL. A workflow writes them in two forms.

A template puts a value into text with ${{ }}. A predicate gives a true or false result that controls a trigger, job, step, or gate.

For the data an expression can read, see Contexts.

Syntax

Write an expression between ${{ and }}:

run: echo "Building ${{ trigger.event }}"
FormExampleResult
Property accessevent.refThe ref property of event
Index accessvars["API_URL"]A property whose name is not an identifier
List indexexecution.events[0].dataThe first element of a list
Escape$${{The literal text ${{

A predicate field takes the expression on its own. An if field takes exactly one ${{ }} and nothing else:

if: ${{ trigger.event == "push" }}

vars and secrets accept a literal key only. vars["API_URL"] is valid and a computed key such as vars[inputs.name] is not.

Run identifiers

The run context has a UUID id and a sequential number. The UUID identifies the run in API and client routes. The number is scoped to the workflow definition and is available for labels, predicates, and display text. It is not resolved as a route address.

execution_name: 'Deploy #${{ run.number }}'

Types

TypeWritten as
string"refs/heads/main"
int42
double1.5
booltrue
list["main", "release"]
map{"env": "prod"}
timestamptimestamp("2026-01-01T00:00:00Z")

Operators

OperatorExampleResult
==, !=trigger.event == "push"Compares two values of the same type
<, <=, >, >=run.created_at > timestamp("2026-01-01T00:00:00Z")Orders numbers, strings, and timestamps
&&, ||, !job.key == "deploy" && !step.is_retryCombines boolean values
in"prod" in inputs.environmentsTrue when a list contains the value
in"API_URL" in varsTrue when a map contains the key
+"v" + inputs.versionAdds numbers, joins strings, joins lists
-, *, /, %executions.size() % 2 == 0Arithmetic on numbers
? :run.number == 1 ? "first" : "rerun"The middle value when true, the last when false
( )(a || b) && cGroups an expression against precedence

Comparing values of different types is an error rather than a false result, and int and double count as different types. A predicate that errors never passes.

Functions and macros

CallExampleResult
list.size(), string.size()executions.size() > 1Number of elements or characters
list.all(item, predicate)executions.all(e, e.status == "succeeded")True when every element matches
list.exists(item, predicate)execution.events.exists(e, e.event == "push")True when at least one element matches
list.exists_one(item, predicate)needs.exists_one(j, j.status == "failed")True when exactly one element matches
list.filter(item, predicate)executions.filter(e, e.status == "failed")The elements that match
list.map(item, expression)needs.map(j, j.key)The expression applied to each element
string.contains(part)event.ref.contains("release")True when the string contains part
string.startsWith(part), string.endsWith(part)event.ref.startsWith("refs/heads/")Prefix and suffix tests
string.matches(pattern)event.ref.matches("^refs/tags/v[0-9]+$")True when the string matches a regular expression
string.split(separator)event.ref.split("/")[2]The parts between each separator
string.lowerAscii(), string.upperAscii()event.ref.lowerAscii()The string in one case
has(field)has(event.pull_request)True when the field is present
string(value), int(value), double(value)"run-" + string(run.number)The value converted to that type
timestamp(string)timestamp("2026-01-01T00:00:00Z")A timestamp from an RFC 3339 string
range(start, stop, step)range(1, 3, 1)An inclusive list of integers
toJson(value)toJson(event.pull_request.labels)The value serialized as compact JSON text
fromJson(string)fromJson(event.payload)The JSON text parsed into a CEL value

range() accepts a positive step and can materialize at most 1,000 values and 1,000,000 context-byte fan-out units in one evaluation. toJson() can produce at most 1,000,000 UTF-8 bytes in one evaluation. fromJson() expects a valid JSON string and converts safe integer numbers to CEL integers. toJson() writes integers outside the range JSON numbers represent exactly as quoted strings.

The CEL language definition documents the full standard library.

Was this page helpful?
Edit this page on GitHub

On this page