Workflows
A workflow chains your saved requests into a flow. Send “Create an order”, wait until the order is paid, check the answer, and if something goes wrong take another path. You draw it on a canvas, run it in the dashboard, and run the same file in CI with one command.
A workflow lives in its own file, zyvra.workflows.yaml, next to your collections, so it goes to Git with the rest. Its request blocks point at requests you already saved in a collection: write a request once, use it in both.
Draw a flow
Open Workflows in the sidebar and choose New workflow. Pick the collection its requests come from. A new flow is a canvas with one Start block. Then build it:
- Add and wire in one move: drag from an output port on the right of a block (Success, Fail, Yes, No…) and drop on empty canvas. A list of blocks opens where you dropped: search it, and the block you pick is added there and wired from that output. The same list opens with Add block, or when you double-click or right-click the canvas.
- Wire existing blocks: drag from an output port to the input on the left of the next block. The wire shows where the flow goes. Draw another wire from the same port to replace it.
- Select a block to change it in the panel on the right. A block that is not filled in yet says what is missing.
- Select a wire or a block and press Delete to remove it. A block’s … menu duplicates it, turns it off (the flow goes through it) or deletes it.
- Tidy up arranges the blocks left to right. Scroll to zoom, drag the background to pan, and use the mini map to move around a big flow.
Wires only go forward, so a flow always ends: Zyvra will not let you draw a wire back to an earlier block. Looping is what the Repeat and For each row blocks are for. Two branches may meet again at a block.
Save keeps the file, with where each block sits. A flow with blocks not filled in can be saved and finished later, but it cannot run. Leaving the page with unsaved changes asks first.
Blocks
| Block | Outputs | What it does |
|---|---|---|
| Start | Start | Where the flow begins. Wire it to the first block. |
| Send request | Success, Fail | Sends a saved request, with its checks and scripts. It leaves by Success when everything passed, and by Fail when a check failed or the request could not be sent. |
| Set variable | Next | Gives a variable a value. It may use other variables, such as order-{{orderId}}. |
| Wait (shown as Delay in the list) | Next | Pauses, up to 60 seconds. |
| If | Yes, No | Looks at the last response (its status, a header, a value in the body, its time or size) or at a variable, and goes one way or the other. |
| Check | Holds, Does not hold | The same kind of condition, as a check. |
| Repeat | Each pass, Done, Never held | Runs the chain wired to Each pass a number of times, or until something holds, with a pause between passes and a maximum. Then the flow carries on from Done. If the condition never holds, it leaves by Never held. |
| For each row | Each row, Done | Runs the chain wired to Each row once per row of a CSV or JSON file in the project. Each column is a variable for its row. |
| Validate | Valid, Invalid | Checks the last response body against a JSON Schema you write. With nothing wired to Invalid, the flow fails here. |
| Display | Next | Shows a value on the block after a run, for example id is {{orderId}}. |
| Log | Next | Writes a message to the run’s log, listed with the run and printed by zyvra workflow run. |
| Output | Next | Records a named result of the flow, such as orderId = {{orderId}}. Outputs are listed with the run and in --json. |
| User input | Next | Stops the flow and asks the person running it a question, then carries on with the answer in a variable ({{who}}). You can offer an answer, and hide what is typed for a password. In the terminal it asks on the command line; in CI give it with --var who=ann (or the answer on offer is used). |
| Change a mock | Next | Makes a mock endpoint answer with a scenario, puts it back to automatic, or resets stored state. See below. |
| Stop | none | Ends the flow as passed or failed, with a message. |
Handling a failure: wire a Fail output to the blocks that should run instead. With nothing wired to it, a failed request or check ends the flow as failed, so a flow never carries on past a problem you did not plan for.
Values travel by variables. A request’s Save to variable checks and its scripts set variables, and later blocks use them as {{name}}.
Group blocks
A Group (under Other in the list) is a labelled box you place behind blocks to keep them together. Drag it and the blocks inside it move with it; drag its corners to resize it. It is only a drawing: it is not part of the flow and has no wires.
Run it
Press Run. The flow is saved first if it changed. The run is live: each step appears as it finishes, the blocks on the canvas show whether they passed as the flow reaches them, and Cancel stops it. A User input block opens a question and the flow waits until you answer. Each block then shows whether it passed, a loop shows how many times it ran, the wires the flow went along stand out and the others fade, and the list under the canvas gives every step with what it did: the request sent and its status, the check and what it found. Variables come from the environment chosen at the top right of the page. Secrets stay masked.
A flow ends at its first unhandled failure. A flow may run at most 2000 steps and send at most 500 requests, loops nest 6 deep, and a flow has 200 blocks.
Change the mocks while it runs
A Change a mock block pins a scenario on one of the project’s mock endpoints, for example the 503 from the payment service, and the flow checks how your requests cope. The change lasts for the run only: it is never written to zyvra.yaml, and it is undone when the run ends, even when the flow fails. Mock blocks need the project’s mock services to run in the same program, which the dashboard does.
In CI
zyvra workflow list
zyvra workflow run "Order flow" --with-mocks --junit workflow.xml
--with-mocks starts the project’s mock services for the run (a workflow with mock blocks needs it). A User input block is answered with --var name=value; without it the command asks on the terminal, and with no terminal it uses the answer on offer, or fails instead of waiting. The exit code is 1 when the flow fails. --env, --var name=value, --json file work as they do for zyvra run. See Commands.
What the file looks like
version: 1
workflows:
- id: order-flow
name: Order flow
collection: shop-api
nodes:
- { id: start, type: start, x: 0, y: 0 }
- { id: create, type: request, request: create-order, x: 340, y: 0 }
- id: ok
type: if
x: 680
y: 0
when: { source: status, op: equals, value: "201" }
- { id: wait, type: repeat, x: 1020, y: -80, max: 10, ms: 500, until: { source: body, jsonPath: $.state, op: equals, value: paid } }
- { id: poll, type: request, request: get-order, x: 1360, y: -80 }
- { id: bad, type: stop, result: failed, message: the order was not created, x: 1020, y: 120 }
edges:
- { from: start, port: next, to: create }
- { from: create, port: success, to: ok }
- { from: ok, port: then, to: wait }
- { from: ok, port: else, to: bad }
- { from: wait, port: each, to: poll }
You can edit it by hand: it is checked when it is read, and the dashboard shows what is wrong.