VERIFY INFRASTRUCTURE WITH ASSERT STEPS
This guide shows you how to add assert steps to a workflow so that data-producing steps run first, then assert steps check the results.
Prerequisites
- Swamp installed and on your
PATH - An initialised repo (
swamp repo init) - A model that produces data you want to verify (this guide uses
command/shell) - Familiarity with workflow definitions
Add assert steps to a workflow
Place assert steps after the step that collects data. Use dependsOn so the
assert waits for the data-producing step to finish, then reference its output
with data.latest() in the expr field:
jobs:
- name: verify
steps:
- name: collect-state
task:
type: model_method
modelIdOrName: server-check
methodName: execute
inputs:
run: echo '{"healthy":true,"count":3,"region":"us-east-1"}'
- name: check-healthy
dependsOn:
- step: collect-state
condition:
type: succeeded
task:
type: assert
expr: data.latest("server-check", "result").attributes.exitCode == 0
message: "Server exited cleanly"
severity: high
- name: check-output
dependsOn:
- step: collect-state
condition:
type: succeeded
task:
type: assert
expr: >-
data.latest("server-check", "result").attributes.stdout.contains("healthy")
message: >-
Expected stdout to contain 'healthy', got
${{ data.latest("server-check", "result").attributes.stdout }}
severity: mediumexpr is a raw CEL expression — do not wrap it in ${{ }}. The message field
does support ${{ }} interpolation for including dynamic values.
When a CEL expression contains double quotes, use a >- block scalar to avoid
YAML quoting conflicts:
expr: >-
data.latest("server-check", "result").attributes.stdout.contains("healthy")Set severity levels
Each assert step accepts a severity — low, medium, or high (default
high). Severity controls whether a failure causes the workflow run to fail,
based on the --fail-on threshold.
Run with the default threshold (any failure fails the run):
swamp workflow run infra-verifyRun with a higher threshold so only high-severity failures fail the run:
swamp workflow run infra-verify --fail-on highWith --fail-on high, failed low and medium assertions are recorded but do
not affect the exit code:
system │ Starting workflow infra-verify
verify │ start
verify │ step collect-state · server-check · execute · start
verify │ done collect-state
verify │ done ✓ check-healthy
verify │ failed ✗ check-count
verify │ Expected count of 3 in output
verify │ failed ✗ check-region
verify │ Region must be us-east-1
verify │ completed
system │ Assertions: 1 passed, 2 failed
system │ Completed workflow infra-verify succeededThe run succeeds because the two failures are below the high threshold.
Generate JUnit XML for CI
Add --junit to emit assert results as JUnit XML that CI test reporters (GitHub
Actions, GitLab, Jenkins) can consume:
swamp workflow run infra-verify --junit<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="infra-verify" tests="3" failures="0" time="0.1">
<testsuite name="verify" tests="3" failures="0" time="0.0">
<testcase name="check-healthy" classname="infra-verify.verify" time="0.0"/>
<testcase name="check-output" classname="infra-verify.verify" time="0.0"/>
<testcase name="check-no-errors" classname="infra-verify.verify" time="0.0"/>
</testsuite>
</testsuites>To write the XML to a file instead of stdout, add --out:
swamp workflow run infra-verify --junit --out results.xml--junit and --json cannot be combined — use one or the other.
Reference
- Assert step reference — full
field table, severity truth table, and
assertResultschema - The workflow execution model — why assert steps exist and how they fit the workflow DAG