Iterate through lists, maps, or collections using loops.
Loops iterate over collections defined by in, automatically creating index and element variables for each iteration. Access these with JQ expression ${{ .steps.<loopStepName>.loop.element }} or ${{ .steps.<loopStepName>.loop.index }}.
What loops enable:
- Iterate over collections, lists, or arrays
- Process each item with
elementand track position withindexvariables - Control loop flow with
breakandcontinuestatements - Nest loops for complex data processing
Parameters
for(Required): Signals loop startin(Required, string expression): Expression evaluating to a collectionsteps(Required): Steps executed each iteration. Can include any step type, including nested loops
Loop with workflow inputs
name: myWorkflow steps: - name: loopStep type: loop for: in: '${{ .workflowInputs.list }}' steps: - name: step1 type: action action: internal.example.sayHello version: '1' inputs: name: 'Element: ${{ .steps.loopStep.loop.element }}, Index: ${{ .steps.loopStep.loop.index }}'Important notes
for: required. Top-level element indicating loop startin: required. Input collection must be castable to Java Arraysteps: required. Steps execute each iterationelementandindexautomatically assigned per loop iterationindexis zero-basedelementcan be complex type for complex collections- Loop variables and step outputs only accessible within the loop
- Variables cleared on loop exit and null if accessed outside
- Loops can access variables defined outside the loop
Simple loop on integers
name: myWorkflow steps: - name: loopStep type: loop for: in: ${{ [range(1; 6)] }} steps: - name: step1 type: action action: internal.example.sayHello version: '1' inputs: name: 'Element: ${{ .steps.loopStep.loop.element }}, Index: ${{ .steps.loopStep.loop.index }}'Simple loop for map
name: myWorkflow steps: - name: loopStep type: loop for: in: '${{ [ { "key1": "val1" }, { "key2": "val2"} ] }}' steps: - name: step1 type: action action: internal.example.sayHello version: '1' inputs: name: 'Element: ${{ .steps.loopStep.loop.element }}, Index: ${{ .steps.loopStep.loop.index }}'Jump within a loop
Only jump between named steps within the same loop. Jumping in/out of loops, to inner/outer loops, or between different loops is not allowed.
name: myWorkflow steps: - name: firstStep type: action action: internal.example.sayHello version: '1' - name: loopStep type: loop for: in: '${{ .workflowInputs.list }}' steps: - name: step1 type: action action: internal.example.sayHello version: '1' inputs: name: '${{ .steps.loopStep.loop.element }}' next: step3 # Okay within the loop - name: step2 type: action action: internal.example.sayHello version: '1' inputs: name: '${{ .steps.step1.outputs.greeting }}' - name: step3 type: action action: internal.example.sayHello version: '1' next: firstStep # Not okay, first step is not in the loop contextUse break/continue in a loop
Change loop flow with next: break or next: continue. These are reserved jump targets implicitly defined within loops. Outside loops, they jump to workflow end.
end behaves as break inside loops. next works in switch steps or any step type.
name: myWorkflow steps: - name: loopStep type: loop for: in: '${{ [range(1; 6)] }}' steps: - name: insideLoopStep1 type: action action: internal.example.sayHello version: '1' inputs: name: '${{ .steps.loopStep.loop.element }}' next: continue - name: insideLoopStep2 type: action action: internal.example.sayHello version: '1' inputs: name: '${{ .steps.loopStep.loop.element }}' - name: loopStepAgain type: loop for: in: '${{ .workflowInputs.list }}' steps: - name: switchStep type: switch switch: - condition: '${{ .steps.loopStepAgain.loop.index >= 0 }}' next: break - name: insideLoopStepAgain type: action action: internal.example.sayHello version: '1' inputs: name: '${{ .steps.loopStepAgain.loop.element }}'What's next
- Conditional logic: Use switch statements for decision making
- REST API polling: See loops in action with real APIs