Skip to content

tropel v0.2.0

Choose a tag to compare

@github-actions github-actions released this 31 Aug 11:23
· 97 commits to master since this release
de6c337

Tropel is an open-source load-testing framework in Rust. It runs
Postman collections, HAR files, OpenAPI specs, Bruno and
Insomnia exports, and k6 scripts as load tests — a native Rust hot
path with an embedded QuickJS engine for script execution.

Pre-1.0: the API is unstable. k6 parity is actively expanding and the
tropel-sdk surface still changes between minor versions. Pin an exact
version if you depend on it.

Install

Pick your platform. Linux builds are static musl — they run unmodified in
Alpine, distroless and scratch containers.

# Linux x86_64
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-unknown-linux-musl.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-x86_64-unknown-linux-musl/tropel /usr/local/bin/

# Linux arm64
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-aarch64-unknown-linux-musl.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-aarch64-unknown-linux-musl/tropel /usr/local/bin/

# macOS Apple Silicon
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-aarch64-apple-darwin.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-aarch64-apple-darwin/tropel /usr/local/bin/

# macOS Intel
curl -fsSL https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-apple-darwin.tar.gz | tar xz
sudo install -m755 tropel-v0.2.0-x86_64-apple-darwin/tropel /usr/local/bin/

Windows (PowerShell):

Invoke-WebRequest -Uri "https://github.com/transithq/tropel/releases/download/v0.2.0/tropel-v0.2.0-x86_64-pc-windows-msvc.zip" -OutFile tropel.zip
Expand-Archive tropel.zip -DestinationPath .

macOS note: binaries are unsigned, so Gatekeeper will quarantine a downloaded
archive. Clear it with xattr -d com.apple.quarantine ./tropel.

Verify your download

curl -fsSLO https://github.com/transithq/tropel/releases/download/v0.2.0/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing      # macOS: shasum -a 256 -c

From source (Rust 1.94+)

cargo build --release      # ./target/release/tropel

Assets

asset contents
tropel-v0.2.0-<target>.tar.gz / .zip tropel, tropel-controller, tropel-agent + LICENSE, README
tropel-wasm-v0.2.0.tar.gz the browser/edge tier — core-wasm, input-wasm, runtime-wasm, shims
SHA256SUMS checksums over every asset above

Targets: x86_64/aarch64 Linux (musl), x86_64/aarch64 macOS,
x86_64 Windows (MSVC).

Quick start

tropel run collection.json --vus 50 --duration 2m   # Postman, HAR, OpenAPI, k6, Bruno, Insomnia
tropel inspect collection.json                      # preview without sending traffic
tropel extensions                                   # list the input formats this binary ships

Full docs: docs/ — CLI
reference, executors, scripting, metrics, extensions, distributed execution.

What's in it

  • Seven executors — constant-vus, ramping-vus, shared/per-vu iterations,
    constant & ramping arrival rate, externally-controlled, with graceful
    stop/ramp-down, think time and pacing
  • Postman pm.* scripting — tests, assertions, variable scopes,
    setNextRequest, sendRequest, custom metrics
  • k6-style scripting — http.*, check(), group(), sleep(),
    Counter/Gauge/Rate/Trend; exported options honoured
  • HDR-histogram metrics — p50/p90/p95/p99, sub-timings, tag-scoped
    aggregation, thresholds with k6-compatible abort semantics
  • Streaming outputs — NDJSON, StatsD, InfluxDB, Prometheus, OTLP
    (protobuf + gzip), plus stdout/JSON/CSV reporters
  • Distributed — k6-style execution segments for multi-node runs
  • Extensible — tropel-sdk + tropel build --with <crate>, plus a
    sandboxed WASM plugin tier for third-party input formats

npm packages

@tropel/core-wasm@0.2.0   @tropel/input-wasm@0.2.0   @tropel/runtime-wasm@0.2.0   @tropel/shims@0.2.0

Changes in 0.2.0

First tagged release. Versioned 0.2.0 rather than 0.1.0 across all seven
surfaces (binary, tropel-engine, tropel-web, and the four @tropel/* npm
packages — tropel-engine is what --version prints) because
@tropel/shims@0.1.0 and @tropel/runtime-wasm@0.1.0 were published on
2026-08-10 and npm versions are immutable: those artifacts still call the
__tropel_pm_* bridges this tree renamed to __tropel_trp_*, so they cannot
be paired with this runtime. 0.2.0 is the first npm set that matches the
binary.

The API is unstable pre-1.0. k6 parity is actively expanding and the
tropel-sdk surface still moves between minor versions.

Fixed — correctness

  • sleep() was non-functional on every declarative format (Postman, HAR,
    OpenAPI, .http, Insomnia, Bruno). __tropel_native_sleep was registered as
    an async host function on an rquickjs Runtime with no spawner, so the first
    call panicked with "tried to use async function in non async runtime";
    rquickjs stashed that panic and re-raised it on whichever VU next threw — a
    different VU on a shared runtime. Now a blocking sleep with an absolute
    deadline. This also fixes bru.sleep(ms).
  • Headline http_req_duration / iteration_duration were computed from one
    metrics shard.
    shard_for_key hashed the metric name and its tags,
    against its own documented contract, so {url:/a} and {url:/b} landed on
    different shards and the merge kept only the largest-count partial. Count,
    avg, min, max and p95 were derived from a fraction of the population.
  • http_req_failed was the maximum of per-shard rates — 10 failures across
    400 requests reported 0.10 instead of 0.025. Now merges numerator and
    denominator.
  • output_samples_dropped / aggregator_samples_dropped were multiplied by
    SHARD_COUNT
    — process-global atomics read once per shard and summed, so
    one output dropping 1,000 samples reported 4,000.
  • absorb_snapshot discarded over-cap series without counting them, so a
    controller merge that lost series still reported "unverified": false.
  • The QuickJS promise-rejection tracker was overwritten by every new VU.
    It is a property of the runtime, not the context, so on a shared runtime one
    VU's unhandled rejection was recorded into another's map — the first VU
    passed silently, the second failed with an error it never raised.
  • bru.setVar / setEnvVar / setCollectionVar were not inverses of their
    getters
    — they wrote with String(value) while the getters used
    JSON.parse, so setVar('id','1234') read back as the number 1234 and an
    object read back as "[object Object]".
  • @tropel/shims shipped without k6-core.js, leaving every
    @tropel/runtime-wasm embedder without check/group/Counter/Gauge/
    Rate/Trend. The npm bundle list is now derived from Shim::ALL in the
    Rust source, so the two cannot diverge silently.
  • ws_* samples carried group:"ws" where k6's root group is "".

Changed

  • Per-VU JS shims are now selected by input format, and the bytecode cache is keyed by bundle (TR-501). The compiled-shim-bytecode cache was a single OnceLock keyed on nothing, so only the full default bundle could use it and every narrowed bundle paid a per-VU source parse+compile — which made shim gating a pessimisation: an http-only script measured 557,824 B/VU against the full bundle's 497,584 B/VU. The cache is now keyed by bundle identity, and ShimBundle::for_format picks the shim set from the resolving InputAdapter::id(). ✅MEAS (Apple M2, release, N=25, contexts sharing one worker-thread Runtime): har/openapi/http/insomnia 203,400 B/VU, content-gated http-only 261,878, postman 369,424, k6/unknown format 385,324. (An earlier revision of this entry quoted 280,480 / 336,848 / 479,952 / 497,584 — those came from a harness that summed a shared runtime's heap once per context and divided by N, reporting the whole 25-context total as a per-VU figure. Withdrawn; do not cite them.) Behaviour change: a context created by create_vu_js_context no longer necessarily has all of pm/chai/_/CryptoJS/bru — bru is dropped for every format except bru, and the assertion/utility libraries are dropped for the four formats whose adapters cannot emit a script. pm.js is still loaded for every format. The k6 Driver's own shim bundle (tropel-input-k6) is unchanged.
  • License: dual MIT OR Apache-2.0 → Apache-2.0 only. LICENSE-MIT removed; LICENSE-APACHE now carries the full canonical text (previously a placeholder stub) and is copied into crates/tropel-sdk/ so published artifacts include it. deny.toml keeps MIT on the dependency allowlist (third-party crates only).

Full changelog: CHANGELOG.md ·
Issues: github.com/transithq/tropel/issues ·
Licence: Apache-2.0