The for_each Step
The for_each step in Bosun allows you to iterate over a list of items, executing a sub-step (which can contain agent or run steps) for each item. This is effective for automating repetitive tasks across multiple files, configurations, or data entries.
for_each steps are executed in parallel batches. If you need to run them sequentially, you can set parallel: false within the for_each definition.
Key properties of a for_each step include:
from: A templated expression that defines the list of items to iterate over. This can be any JSON array. If needed you can use templating functions likesplit(),slice(), andjson_encode()to transform outputs from previous steps into the required format.for_each.value: Inside thefor_eachloop, this variable holds the current item being processed in the iteration.
Example from Workflow
Consider the for_each step from an example workflow, which processes multiple source files:
- name: Get source files
run: find src -name "*.js"
- name: Apply linting fixes
for_each:
from: '{{ outputs.1 | split(pat="\n") | slice(end=5) | json_encode() }}'
agent:
extends: Coding
instructions: "Apply automatic linting fixes to the file {{ for_each.value }}"
role: "You are a meticulous code formatter."
constraints:
- "Use the project's ESLint configuration"
- "Only apply fixes that do not change code logic"
- "Ensure the file remains syntactically correct"
- "Focus only on the specified file"
In this example:
run: find src -name "*.js": This step (which would beoutputs.1in this snippet) finds all.jsfiles in thesrc/directory and outputs their paths, one per line.from: '{{ outputs.1 | split(pat="\n") | slice(end=5) | json_encode() }}':outputs.1: Retrieves the output (list of file paths) from the "Get source files" step.split(pat="\n"): Splits the string output into an array of file paths.slice(end=5): Takes only the first 5 file paths from the array (for demonstration purposes).json_encode(): Converts the array into a JSON string, which thefor_eachstep can then iterate over.
instructions: "Apply automatic linting fixes to the file {{ for_each.value }}": Inside thefor_eachloop, anagentstep is defined. The{{ for_each.value }}template dynamically inserts the current file path from the iteration into the agent's instructions, allowing the agent to process each file individually.
Set parallel: false when order matters or when the target system cannot handle concurrent writes. Leave it omitted for maximum throughput.
Error handling
Every iteration runs as its own sub-task. With the default settings a single failure stops the step, but continue_on_error: true lets the loop finish and collects each failure under errors.<step> along with the failed iteration index and input. See Error handling for strategies.