Runner¶
Run scenarios through a device pool and write the run's report artifacts.
bajutsu.runner.pipeline
¶
Run every scenario through a device pool and write the run's report artifacts.
with_lifecycle_phases(eff, scenarios)
¶
Fold the target config's before / after into each scenario's own (BE-0392).
The two merge in opposite orders. before is config-then-scenario, like interrupts: the
app-wide prelude seeds the state this scenario's own setup then builds on. after is
scenario-then-config, so this scenario releases the record it created before the app-wide
teardown closes around it — the last-acquired-first-released order a fixture-based teardown pair
gives.
Applied to the scenario itself rather than passed beside it, so the scenario the runner executes
and the scenario whose Before / After blocks the report renders are one object. Handing the
merged lists to the runner separately would leave the report pairing an app-wide step's outcome
with the scenario's own step definition, and drop an app-wide after rule's outcomes entirely.
run_all(eff, scenarios, lease, clock=None, alert_guard=None, alert_guard_for=None, run_dir=None, workers=1, bindings=None, secret_values=None, progress=None, baselines_dir=None, schemas_dir=None, actuator=None, resolve_actuator=None, golden_context=None, lease_udid_spec='booted', on_score=None, crash_retries=None, crash_recovery_budget=None, run_crash_recovery_budget=None, force_erase_on_retry=True, cancelled=not_cancelled)
¶
Run every scenario, each on a freshly leased device, and return one result per scenario.
lease(eff, scenario) blocks until a device is free, launches the app, and returns a Lease
bundling the live driver with that device's evidence sink / relaunch / control / network
collector; lease.release() afterwards terminates the app and returns the device to the pool.
A lease's collector, when present, has its exchanges cleared per scenario, exposed to request
assertions, and written to <sid>/network.json (redacted with secret_values).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eff
|
Effective
|
The resolved target config (drives redaction, backend, launch). |
required |
scenarios
|
list[Scenario]
|
The scenarios to run; results come back in this declaration order. |
required |
lease
|
LeaseFn
|
Leases a device and launches the app for one scenario (a single-device run is a pool of one). |
required |
clock
|
Clock | None
|
Injectable time source for condition waits, so tests need no real sleeps. None uses the real clock. |
None
|
alert_guard
|
AlertGuardConfig | None
|
A single alert-guard handler, used by tests. |
None
|
alert_guard_for
|
AlertGuardFor | None
|
Picks each scenario's alert-guard handler (honoring its |
None
|
run_dir
|
Path | None
|
Where per-scenario artifacts (network.json, visual diffs) are written. None skips writing them. |
None
|
workers
|
int
|
Concurrent scenarios; >1 hands each worker its own device + per-device resources, so the loop keeps no shared mutable state. |
1
|
bindings
|
Mapping[str, str] | None
|
|
None
|
secret_values
|
list[str] | None
|
The raw secret values to redact from evidence. |
None
|
progress
|
ProgressFn | None
|
Receives one-line progress messages (the web UI streams these). None is silent. |
None
|
baselines_dir
|
Path | None
|
Baseline images for |
None
|
schemas_dir
|
Path | None
|
Directory the |
None
|
actuator
|
str | None
|
The single selected actuator (e.g. |
None
|
resolve_actuator
|
Callable[[Scenario], str] | None
|
Per-scenario actuator resolver (BE-0240); when given, each scenario's
actuator — and thus the capability set it is preflighted against — is resolved from the
scenario's own steps (cheapest sufficient), instead of the one fixed |
None
|
golden_context
|
GoldenContext | None
|
Goldens directory for |
None
|
lease_udid_spec
|
str
|
The run's resolved udid spec (the provider's |
'booted'
|
on_score
|
Callable[[Score], None] | None
|
Sink for the app's entry-screen convention score, emitted once from the first
scenario's freshly launched driver (the |
None
|
crash_retries
|
int | None
|
How many times to re-run a scenario whose backend crashed mid-run
( |
None
|
crash_recovery_budget
|
float | None
|
A wall-clock ceiling (seconds) on the total time one scenario may spend
respawning after a crash, on top of |
None
|
run_crash_recovery_budget
|
float | None
|
A wall-clock ceiling (seconds) on the total time crash recovery may
spend across this one |
None
|
force_erase_on_retry
|
bool
|
Whether a crash-triggered retry (attempt > 1) may force
|
True
|
cancelled
|
CancelSource
|
Reports whether this run has been asked to stop (BE-0370). A scenario the request
reaches — at a step boundary, inside a condition wait's poll, or before it was leased at
all — comes back as |
not_cancelled
|
Returns:
| Type | Description |
|---|---|
list[RunResult]
|
One result per scenario, in the same order as |
run_and_report(eff, scenarios, lease, runs_dir, run_id, clock=None, alert_guard=None, alert_guard_for=None, workers=1, bindings=None, secret_values=None, source_name=None, description=None, progress=None, baselines_dir=None, schemas_dir=None, actuator=None, resolve_actuator=None, config_source=None, exec_provenance=None, label=None, golden_context=None, lease_udid_spec='booted', on_score=None, force_erase_on_retry=True, cancelled=not_cancelled)
¶
Run the scenarios, then write the run's artifacts under runs_dir/run_id.
Wraps run_all and persists the report: manifest.json, JUnit XML, and the executed
scenario.yaml (so a run is re-runnable / reviewable).
Beyond run_all's arguments (force_erase_on_retry and cancelled pass straight through — see
their docstrings there), runs_dir + run_id locate this run's artifact directory
(runs_dir/run_id),
source_name / description are recorded in the report, and config_source — the Git source
the config came from (BE-0063), or None for a local config — is stamped into the manifest's
provenance so a branch-based run states the exact commit it executed.
Returns:
| Type | Description |
|---|---|
tuple[list[RunResult], Path]
|
The per-scenario results and the path to the written |
run_matrix_and_report(eff, scenarios, engines, run_pass, runs_dir, run_id, *, source_name=None, description=None, secret_values=None, config_source=None, exec_provenance=None, label=None, cancelled=not_cancelled)
¶
Run the scenarios once per engine, then assemble ONE report at runs_dir/run_id (BE-0076).
The cross-browser fan-out: a loop over engines, each a full pass. run_pass(engine, run_dir)
runs the selected scenarios for one engine against its own pool, writing that engine's evidence
under run_dir (the caller hands it runs_dir/run_id/<engine>, prefixing the existing NN-slug
layout so two engines never collide); its results are tagged with engine here. The passes'
tagged results are concatenated into one flat list and written as a single manifest / JUnit /
report — the manifest's matrix block aggregates the per-engine verdicts, and ok is
all-must-pass across every engine x scenario (pure aggregation, no LLM).
cancelled (BE-0370) is read between passes: each one first builds a whole device_pool, so a
cancel during the first engine would otherwise still pay every remaining engine's bring-up and
teardown before the run could finish, overrunning the grace period. Every scenario of an engine
that never ran is failed as cancelled rather than left out, so the matrix still names every
requested engine and ok aggregates a cancelled run to False — dropping those engines instead
would let a first pass that happened to be green aggregate to a PASS for a run that never
finished.
Returns:
| Type | Description |
|---|---|
tuple[list[RunResult], Path]
|
The concatenated per-engine results and the path to the written |