Condition nodes
Condition nodes add branching logic to a workflow. A condition node defines one or more outlets, each with a JQ expression. When the workflow reaches the node, Port evaluates the expressions and continues down the path of the first outlet whose expression is true.
Like input nodes, condition nodes branch the workflow. Unlike input nodes, they don't pause the run or require any human interaction - the decision is made instantly based on data already in the workflow run context.
How it works
- The workflow reaches the condition node.
- Port evaluates each outlet's
expressionin the order they're defined, against the current workflow run context. - The workflow continues down the path of the first outlet whose expression evaluates to
true. Remaining outlets are not evaluated. - If none of the outlets evaluate to
true, the workflow continues down the node's fallback connection, if one is defined. See connections. - If no outlet matches and no fallback connection is defined, that branch of the workflow ends without an error.
If an outlet's expression fails to evaluate (for example, due to invalid JQ syntax or a reference to a field that doesn't exist), the entire node fails and the workflow run fails. Make sure your expressions evaluate safely against the data you expect to be present.
Example
{
"identifier": "check-environment",
"title": "Check Environment",
"config": {
"type": "CONDITION",
"outlets": [
{
"identifier": "production",
"title": "Production",
"expression": ".outputs.trigger.environment == \"production\""
},
{
"identifier": "staging",
"title": "Staging",
"expression": ".outputs.trigger.environment == \"staging\""
}
]
}
}
Configuration
A condition node is defined by a config object with "type": "CONDITION" and the following fields:
| Field | Required | Description |
|---|---|---|
type | Yes | Must be "CONDITION". |
outlets | Yes | The ordered list of branches the node can continue on. See outlets below. |
Outlets
Each outlet has the following fields:
Outlets are evaluated in the order they're defined, and the first match wins - so put more specific conditions before more general ones. Each outlet's identifier must be unique within the node.
| Field | Required | Description |
|---|---|---|
identifier | Yes | A unique identifier for the outlet. Connections reference this value. |
title | No | A human-readable name for the outlet, shown in the graph. |
expression | Yes | A JQ expression evaluated against the workflow run context. The outlet is taken when this evaluates to true. |
statusLabel | No | A label applied to the node run when this outlet is taken. Has a text field (supports JQ) and an optional variant of success or alert. |
workflowStatusLabel | No | Same as statusLabel, but applied to the entire workflow run. |
Unlike other node fields, expression is a raw JQ expression, not a {{ }} template. Write .outputs.trigger.environment == "production", not {{ .outputs.trigger.environment == "production" }}.
Connections
Connections from a condition node must specify which outlet they're connected to, using sourceOutletIdentifier. You can also mark one connection as the fallback (shown as else in the workflow builder), which the workflow takes when no outlet's expression matches:
{
"connections": [
{
"sourceIdentifier": "check-environment",
"targetIdentifier": "production-deploy",
"sourceOutletIdentifier": "production"
},
{
"sourceIdentifier": "check-environment",
"targetIdentifier": "staging-deploy",
"sourceOutletIdentifier": "staging"
},
{
"sourceIdentifier": "check-environment",
"targetIdentifier": "default-deploy",
"fallback": true
}
]
}
Each sourceOutletIdentifier must reference a valid outlet identifier on the node, and a node can have at most one fallback connection.
Outputs
When an outlet matches, a condition node produces the following output, which subsequent nodes can reference through data flow:
selectedOutlet.identifier- the identifier of the outlet the node continued on.selectedOutlet.expression- the expression of the outlet that matched.
When the workflow continues down the fallback connection instead, selectedOutlet is not set.
For example, to branch further on the selected outlet in a downstream node:
{{ .outputs["check-environment"].selectedOutlet.identifier }}
Related links
- Input nodes - Branch a workflow based on human responses.
- Data flow - Pass outputs between nodes.