Guides

Script steps

A script step runs a program you wrote, in your own Node or Python, and reads back what it reports. Use one when a check needs a loop, a client library, or a flow that a plan cannot express; keep everything else in plain http, sql and exec steps, where vero can see and time each request.

- script:
    runtime: node               # node, or python (python3 is tried before python)
    entry: ./scripts/checkout.mjs
    input: { baseUrl: "{{ env.baseUrl }}", apiKey: "node-{{ run.id }}" }
    timeout: 30s
  assert: [ok == true, result.total == 2000]
  results: { orderId: result.orderId }

Writing one

The whole protocol is in vero.script/v1. In short:

  1. Read one JSON line from stdin: {"protocol":"vero.script/v1","input":{...},"deadline":"..."}. input is the step's input with templates rendered; it is the only thing from the run you see.
  2. Write events to stdout, one JSON object per line:
    • {"type":"log","level":"info","msg":"..."} for anything worth reading later;
    • {"type":"step","name":"...","status":"passed","durationMs":12} for each thing you checked;
    • {"type":"result","ok":true,"result":{...}} last. ok and result are what the plan's assertions see.
  3. Exit 0. stderr is kept as log lines. A non-zero exit code makes the step errored, result event or not; ok: false makes it failed.

Report steps. A script that returns ok: true without a single step event is reported as passed (unverified): vero cannot tell whether it checked three things or nothing. Both examples here emit one step per request.

The examples

First build and start the fixture. The example prerequisites cover both runtimes and other plans. The combined examples/scripts.yaml needs Node with global fetch and Python 3 on PATH. The scripts live in examples/scripts/.

  • checkout.mjs: Node, fetch only, no package.json.
  • checkout.py: Python, urllib.request only, no packages.
  • examples/scripts.yaml: runs both against vero-testserver and verifies the Node script's order with an http step that reads the id through a derived edge.
  • A browser through the script step: the same checkout through a real browser, with Playwright from npm. It needs installs the two above do not.

In Terminal 1 at the checkout root, run the fixture in the foreground:

bin/vero-testserver

In Terminal 2 at the checkout root:

bin/vero run examples/scripts.yaml

The child receives PATH, HOME, and LANG from the parent environment, not arbitrary parent variables, plus VERO_SCRIPT_TOKEN, a value unique to the step that vero uses to find a process that outlived it. The fixture address reaches the scripts via plan input ({{ env.baseUrl }}), not a constant in the script. Pass configuration explicitly through input to retarget a script.

Secrets you pass in input are scrubbed from the script's events and stderr, not from anything it writes to disk. An exec or script step runs with your privileges and is not a sandbox.

This page is docs/content/guides/script-steps.md in the repository.

verodocs