Run and test
Run a suite with chalupa test
One command that launches a server, runs a declared browser-flow suite from your machine against it, collects the results and sinks the server.
Reviewed 2026-10-04
chalupa test <suite> runs one suite you declared in chalupa.yml. It is the
whole loop in one command: it prepares the data volume, launches the server,
opens the tunnel, runs the suite, collects the results and sinks the server.
Status: Beta. The command, its consent flow and its exit codes are
covered by offline tests that use fake provider and runner processes. The only
runner it supports is CairnTrace (runner: cairn), version
2.5.0 or newer, and the browser and the runner run on your machine, not on the
server.
chalupa test is the laptop-side sibling of ci:. A test: suite
runs on your machine against the server's ports over the tunnel. A ci:
suite runs inside the server.
Declare a suite
Add a test: block next to the rest of the environment. The block is checked
when the config loads, so a mistake is reported before anything bills.
test:
runner: cairn
config: ./cairntrace.config.yml
environment: chalupa
suitesRoot: ./flows
secretsEnv: shop-test
labels:
team: checkout
env:
SHOP_BASE_URL: http://localhost:8080
report: true
onFinish:
local: pkill -f agent-browser
timeoutSeconds: 30
suites:
smoke: {}
checkout:
flows: ./flows/checkout-v2
changed:
sinceRef: main
| Field | Required | Meaning |
|---|---|---|
runner |
yes | Must be cairn. No other runner exists yet. |
config |
yes | Path to the CairnTrace config file, relative to chalupa.yml. It must be a regular file. |
environment |
yes | The CairnTrace environment name the suite runs under. Chalupa asks CairnTrace to list the suite's specs under this name before anything bills, so a name CairnTrace refuses stops the run there. |
suites |
yes | A map of suite names to suites. Declare at least one. Names are lowercase letters, digits and . _ -. |
suites.<name>.flows |
one of | Directory holding the suite's specs, relative to chalupa.yml. |
suites.<name>.sinceRef |
no | A git ref (branch, tag or commit). CairnTrace narrows the suite to the flows affected since that ref. |
suitesRoot |
one of | Used when a suite has no flows: the flows directory is <suitesRoot>/<suite name>. Every suite needs flows or suitesRoot. |
secretsEnv |
no | The TinyVault environment CairnTrace reads secrets from. Chalupa passes it as CAIRN_TVAULT_ENV. Names only: values stay in TinyVault. |
labels |
no | Labels attached to every run. suite is set by Chalupa and cannot be overridden. |
env |
no | Literal, non-secret variables injected into the runner (at most 64). Names that could hijack a loader, interpreter or proxy are refused. |
report |
no | true publishes the run's results to the console when it finishes, and requires cloud.url (the config is refused without it). Default false: results stay on your machine. |
onFinish.local |
no | A local command that runs when the run finalizes, whatever the outcome. Its failure is reported and ignored. |
onFinish.timeoutSeconds |
no | How long that command may run, 5 to 600, default 60. |
A test: block needs compose and services: the suite reaches the server
through the tunnelled Compose ports, so a workspace environment with no Compose
stack is refused. chalupa test --list prints the declared suites and never
runs anything. Without a test: block, chalupa test refuses and says so.
What a run does
chalupa test checkout --config ./chalupa.yml
Before anything bills, Chalupa resolves the suite offline: it loads the config, finds the flows directory, checks that CairnTrace is installed and new enough, and asks CairnTrace which specs the suite selects. Then it shows one summary (environment, specs, server size, estimated cost, data volume, what happens on exit) and asks for one confirmation.
The billable phases follow, each printed as one numbered line:
| Phase | What happens |
|---|---|
| plan | The offline resolution above. Nothing is created. |
| data | Creates the protected data volume if the config declares persist and it does not exist yet. An existing volume is left unchanged and is never deleted by a run. |
| compute | Launches the server. If a server for the same config is already running, the run adopts it and starts no new spend. |
| watchdog | Registers the expiry backstop so an abandoned server is still sunk. If it cannot be armed the run continues and says so. |
| tunnel | Opens the supervised tunnel to the server's ports. |
| readiness | Only when compute.readiness is declared: every probe must pass before any spec starts. A probe that fails ends the run as an infrastructure failure (exit 69), not a test failure. |
| suite | Runs cairn run on your machine. Its own output is the suite output. |
| results | Collects the run statistics. With report: true it publishes them to the console. Publishing never fails the run. |
| sink | Destroys the server, then confirms the data volume is still there. |
The run keeps a transcript of each phase on your machine. Read an earlier run's
transcripts with chalupa test logs [--run ID] [--phase NAME]. The phase names
are data-up, up, watchdog, tunnel, report, release and down.
The confirmation
chalupa test asks you to type one phrase, test <environment> <suite>, for
example test shop-test checkout. That single phrase covers every billable
phase of the run. It needs a terminal.
A script passes the same phrase with --confirm and an explicit --config:
chalupa test checkout --config ./chalupa.yml --confirm "test shop-test checkout"
When the run would adopt a server that is already running and create nothing,
it needs no phrase and refuses --confirm: leave the flag out in that case.
chalupa up with session.keepFor is the usual way to
have a warm server waiting.
Options
| Option | Effect |
|---|---|
--spec NAME |
Run only this spec. Repeat it for several. NAME is an exact file name from the suite's selection, with no path. An unknown name is refused before anything bills. |
--keep |
Skip the sink. The server stays up and bills, and the run prints the exact chalupa down command that ends it. |
--fresh |
Go ahead and launch when a server is already running that was started from a different chalupa.yml. Without it the run is refused and the message tells you to sink the old server first. |
--parallel N |
Passed to CairnTrace: run up to N specs at once. |
--junit PATH |
Passed to CairnTrace: write a JUnit report to PATH. |
--tag TAG |
Passed to CairnTrace. Repeat it for several tags. |
--headed |
Passed to CairnTrace: show the browser. |
--progress auto|plain |
plain prints append-only lines with no terminal control codes, for logs. |
--dry-run |
Resolve the suite and print the exact cairn command it would run. It creates nothing and costs nothing. Add --json for a machine-readable form. |
--json |
With --list or --dry-run, print JSON. |
-q, -v |
Quieter or more verbose phase output. |
-- ARGS |
Everything after -- goes to CairnTrace unchanged, except flags that chalupa.yml owns: --config, --env, --label, --artifact-root, --no-services, --services-dry-run and --select-only. Put those in the config instead. |
--dry-run is the safest way to see what a suite will do:
chalupa test checkout --dry-run --config ./chalupa.yml
What happens when the run ends
By default the server is sunk and the data volume is left alone, so the next run starts from the same data.
- With
--keep, nothing is sunk. The server bills until you run the printedchalupa downcommand. - With
session.keepFordeclared, the run releases the server into a warm window instead of sinking it, shows the maximum cost of that window in the confirmation summary, and then the reaper sinks it. If the release fails or is refused, the run sinks the server. See Warm boxes and reuse. - Ctrl-C interrupts the suite and sinks the server (exit 130). The results of an interrupted run stay on your machine and are not published.
The onFinish.local command, if declared, runs last, after the run finalizes.
It receives CHALUPA_ENVIRONMENT and CHALUPA_TEST_SUITE.
Exit codes
| Code | Meaning |
|---|---|
| 0 | The suite passed. |
| 1, 2, 6 | Passed through from cairn run: the suite failed, the runner errored, or the runner reported a contract error. |
| 64 | Usage or config refusal: a bad flag, an unknown suite or spec, no test: block, a refused phrase, an old CairnTrace. Nothing was changed. |
| 69 | Infrastructure failure: the server or tunnel failed, or a readiness probe never passed. Check chalupa status, because compute may still be running. |
| 70 | The sink failed. The server may still be billing: run chalupa status and chalupa down. |
| 130 | Interrupted, and the sink completed. |
A suite failure (1) and an infrastructure failure (69) are different on purpose, so a script can retry one and page someone for the other.