Configuration (glubean.yaml)
glubean.yaml at the project root is the canonical config. It declares
suites (where runnable files live) and profiles (named run plans you
select with --profile), plus shared defaults. Profiles select test,
contract, and flow suites for glubean run / glubean ci run, and can
also select named load plans (a top-level load: block) for
glubean load --profile.
glubean init scaffolds one. Load an alternate file with
--config ./path/to/glubean.yaml where the command supports it.
Secrets (a cloud token, the project’s tokenEnv value) never live in
glubean.yaml — they come from .env.secrets, environment variables, or
glubean login. See Tokens.
A complete example
version: 1
# Applied to every profile unless the profile overrides them.
defaults:
envFile: .env
redaction:
replacementFormat: simple # simple | labeled | partial
sensitiveKeys: [x-internal-token]
customPatterns:
- { name: stripe-key, regex: "sk_live_[a-zA-Z0-9]{24,}" }
execution:
concurrency: 4
timeoutMs: 30000
thresholds:
http_duration_ms: { p95: "<500" }
# Where runnable files live. Reference these by name from a profile.
suites:
api: { target: ./tests/api, kinds: [test] }
contracts: { target: ./tests/contracts, kinds: [contract, flow] }
browser: { target: ./tests/browser, kinds: [test] }
explore: { target: ./explore, kinds: [test] }
# Named run plans. `glubean run --profile <name>`.
profiles:
# `glubean run` with no --profile uses `local`.
local:
suites: [api, contracts]
# `glubean ci run` uses `ci`.
ci:
suites: [api, contracts]
selection:
excludeTags: [manual, destructive]
tagMode: or # or | and
execution:
failFast: true
failAfter: 5
concurrency: 2
timeoutMs: 60000
noSession: false
# Capability gates default to false. Turn them on only for profiles that
# intentionally run browser, out-of-band, or expensive/side-effecting cases.
capabilities:
browser: false
outOfBand: false
optIn: false
reporters:
console: summary # summary | detailed
junit: .glubean/results/junit.xml
resultJson: .glubean/results/ci.result.json
thresholds:
http_duration_ms: { p95: "<500", avg: "<200" }
upload:
enabled: true
projectId: prj_abc123 # project short ID (from Project Settings)
tokenEnv: GLUBEAN_TOKEN_CI # env var NAME holding this profile's token
explore:
suites: [explore]
# `glubean load --profile perf`. A load-only profile needs no suites.
perf:
load: { plans: [shop] }
envFile: .env.staging
upload: { enabled: true, targetId: tgt_abc123 }
# Named load plans referenced by profiles' `load.plans`.
load:
plans:
shop: { target: tests/load/shop.load.ts }Top level
| Key | Meaning |
|---|---|
version | Schema version. Always 1. |
defaults | Settings inherited by every profile (overridable per profile). |
suites | Map of suite name → { target, kinds, data }. |
profiles | Map of profile name → run plan. |
load | Named load plans (load.plans.<name> → { target }) referenced by profiles’ load.plans. |
mcp | MCP server options — mcp.trace.{keepRequestHeaders, keepResponseHeaders}. |
suites
A suite points at a directory (or file/glob) of runnable files.
| Key | Meaning |
|---|---|
target | Path to the suite’s files, e.g. ./tests/api. |
kinds | Which runnable kinds to include: any of test, contract, flow. |
data | Optional data-driven inputs directory/config. |
flow is the config kind for exported workflow() files. The authoring API is
still workflow(); flow remains the runner-level kind name.
profiles
Each profile composes suites + selection + execution + capabilities +
reporters + thresholds + upload. Every key except suites is optional and
falls back to defaults.
For load testing, keep the traffic shape (virtual-user concurrency, duration,
mix, and thresholds) in exported loadRunner(...) plans inside *.load.ts
files. Run them ad hoc with glubean load [file|dir|glob], or declare named
plans in the top-level load: block and select them
per profile with load.plans for glubean load --profile <name>.
| Key | Meaning |
|---|---|
suites | List of suite names this profile runs. Narrow to one at run time with --suite <name>. |
load.plans | List of top-level load.plans names this profile runs under glubean load --profile <name>. Narrow to one with --plan <name>. A load-only profile may omit suites. |
selection | Filter which runnables execute (see below). |
execution | How they run (see below). |
capabilities | Opt-in gates for runnables that need extra setup (see below). |
reporters | Output formats (see below). |
thresholds | Pass/fail metric gates (see below). |
upload | Cloud upload directive (see below). |
selection
| Key | Meaning |
|---|---|
tags | Run only runnables with one of these tags. |
excludeTags | Drop runnables with any of these tags (always OR). |
tagMode | or (any tag matches) or and (all tags). |
filter | Substring match on name/id. |
pick | Select specific test.pick example key(s). |
execution
| Key | Meaning |
|---|---|
failFast | Stop on first failure. |
failAfter | Stop after N failures. |
timeoutMs | Per-test timeout. |
concurrency | Max parallel runnables. |
noSession | Skip session setup/teardown. |
capabilities
Opt-in gates — runnables that require these are skipped unless the gate is on
(equivalent to the --include-* flags).
| Key | Flag | Meaning |
|---|---|---|
browser | --include-browser | Cases that drive a real browser. |
outOfBand | --include-out-of-band | Cases using email / SMS / webhooks. |
optIn | --include-opt-in | Expensive / slow / side-effecting cases. |
reporters
| Key | Meaning |
|---|---|
console | summary or detailed. |
junit | Write a JUnit XML report to this path. |
resultJson | Write a structured result JSON to this path. |
emitFullTrace | Include full request/response headers + bodies in traces. |
inferSchema | Infer JSON Schema from response bodies. |
truncateArrays | Truncate arrays in trace bodies (AI-friendly). |
redaction (under defaults)
| Key | Meaning |
|---|---|
replacementFormat | simple, labeled, or partial. |
sensitiveKeys | Extra header/field names to redact. |
customPatterns | List of { name, regex } to redact by value. |
thresholds
Per-metric pass/fail gates. Each metric maps to aggregation rules (p95,
avg, min, max) with comparison strings, or a shorthand string:
thresholds:
http_duration_ms: { p95: "<500", avg: "<200" }
error_rate: "<0.05" # shorthandupload
Cloud upload, per profile. Secrets stay out of this file.
| Key | Meaning |
|---|---|
enabled | Turn on upload for this profile (no --upload flag needed). |
projectId | Destination project’s short ID (e.g. prj_abc123). For profile runs, this wins over GLUBEAN_PROJECT_ID unless --project is passed; shown in the printed plan. |
targetId | Destination target’s short ID (e.g. tgt_abc123). For profile runs, this wins over GLUBEAN_TARGET_ID unless --upload-target is passed; shown in the printed plan. |
tokenEnv | Name of the env var holding this profile’s token (value lives in .env.secrets). After an explicit --token, this env var is exclusive for the profile; it does not silently fall back to GLUBEAN_TOKEN. |
upload.projectAliasis the deprecated former name forprojectId— still accepted (with a warning), but useprojectId.
See Upload to Cloud and Tokens for the project-ID / token resolution order.
load — named load plans
Load plans are deliberately not a suite kind — load has its own execution
model and artifact. Declare each plan under the top-level load: block, then
reference plans by name from a profile’s load.plans:
load:
plans:
shop: { target: tests/load/shop.load.ts }
search: { target: tests/load/search.load.ts }
profiles:
perf:
load: { plans: [shop, search] }
envFile: .env.staging
upload: { enabled: true, targetId: tgt_abc123 }| Key | Meaning |
|---|---|
plans.<name>.target | File/dir/glob (typically one .load.ts module) this plan runs. |
glubean load --profile perf runs every listed plan (overlapping targets are
deduped); --plan <name> narrows to one. The profile’s envFile and upload
directive apply exactly as they do for glubean run --profile. The traffic
shape itself (concurrency, duration, thresholds) always lives in the
loadRunner(...) inside the .load.ts file — see
Load Testing.