Skip to main content

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 your source is plain text output, use templating functions like split(), slice(), and json_encode() to transform it into an array.
  • for_each.value: Inside the for_each loop, 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:

steps:
- id: get_source_files
name: Get source files
run: find src -name "*.js"

- id: apply_linting_fixes
name: Apply linting fixes
for_each:
from: '{{ outputs.get_source_files | 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"

starts_with: get_source_files

edges:
- from: get_source_files
to: apply_linting_fixes

In this example:

  1. run: find src -name "*.js": The get_source_files step finds all .js files in the src/ directory and outputs their paths, one per line.
  2. from: '{{ outputs.get_source_files | split(pat="\n") | slice(end=5) | json_encode() }}':
    • outputs.get_source_files: 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 the for_each step can then iterate over.
  3. instructions: "Apply automatic linting fixes to the file {{ for_each.value }}": Inside the for_each loop, an agent step 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.
Control ordering

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.