Skip to content

Conditionals

duckflux provides two mechanisms for conditional flow control: the if/then/else block for multi-step branching, and the when field as a guard condition on individual steps.


The if block evaluates a CEL expression and routes execution to one of two branches:

flow:
- stepA
- if:
condition: stepA.output.score > 7
then:
- stepB
- stepC
else:
- stepD

The else branch is optional. If omitted and the condition is false, execution continues to the next step after the if block.

flow:
- analyze
- if:
condition: analyze.output.hasIssues == true
then:
- fix
- reanalyze
- deploy

In the example above, if analyze.output.hasIssues is false, execution jumps directly to deploy.

Each branch (then and else) accepts a sequence of steps, including nested control flow constructs:

flow:
- runTests
- if:
condition: runTests.output.passed == true
then:
- buildArtifact
- if:
condition: workflow.inputs.env == "production"
then:
- deployProd
else:
- deployStaging
- notifySuccess
else:
- notifyFailure
- openIssue

The when field on a flow step is a CEL precondition that determines whether that step should execute. If the expression evaluates to false, the step is marked as skipped and execution continues.

flow:
- coder
- reviewer
- deploy:
when: reviewer.output.approved == true
- notify:
when: reviewer.output.approved == false

when can be used on any participant reference in the flow:

flow:
- fetchData
- processData:
when: fetchData.output.records.size() > 0
- generateReport

Guard conditions are especially useful inside loops to control which steps execute on each iteration:

flow:
- loop:
as: attempt
max: 3
steps:
- coder
- reviewer:
when: attempt.index > 0

In this example, reviewer is skipped on the first iteration (attempt.index == 0) and runs on all subsequent ones.


whenif/then/else
ScopeA single stepOne or more steps per branch
elseNoYes
ReadabilityHigh for simple guardsBetter for explicit branching
Typical useSkip or run a single stepRoute execution to distinct paths

Use when when you simply want to skip or run a step based on a condition:

- deploy:
when: reviewer.output.approved == true

Use if/then/else when the branch involves multiple steps or explicit alternative paths:

- if:
condition: reviewer.output.approved == true
then:
- deploy
- notifySuccess
else:
- rollback
- notifyFailure

A code review pipeline combining if/then/else, when, and a conditional loop:

id: code-review
name: Code Review Pipeline
version: "1"
defaults:
timeout: 5m
inputs:
branch:
type: string
default: "main"
max_rounds:
type: integer
default: 3
participants:
coder:
type: exec
run: echo '{"status":"coded"}'
onError: retry
retry:
max: 2
backoff: 1s
reviewer:
type: exec
run: echo '{"approved":true,"score":8}'
tests:
type: exec
run: npm test
onError: skip
lint:
type: exec
run: npm run lint
onError: skip
notifySuccess:
type: http
url: https://hooks.example.com/success
method: POST
onError: skip
notifyFailure:
type: http
url: https://hooks.example.com/failure
method: POST
onError: skip
flow:
- coder
- loop:
until: reviewer.output.approved == true
max: 3
steps:
- reviewer
- coder:
when: reviewer.output.approved == false
- parallel:
- tests
- lint
- if:
condition: tests.status == "success" && lint.status == "success"
then:
- notifySuccess
else:
- notifyFailure
output:
approved: reviewer.output.approved
score: reviewer.output.score