@cloudbeat/atlas-cli 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +46 -19
  2. package/dist/api.js +20 -0
  3. package/dist/cli.js +34 -6
  4. package/dist/commands/analyze.js +118 -0
  5. package/dist/commands/capacity.js +104 -0
  6. package/dist/commands/docs.js +57 -0
  7. package/dist/commands/files.js +18 -4
  8. package/dist/commands/plan.js +100 -0
  9. package/dist/commands/record.js +11 -1
  10. package/dist/commands/results.js +13 -7
  11. package/dist/commands/schema.js +86 -0
  12. package/dist/commands/skills.js +111 -0
  13. package/dist/commands/tests.js +73 -0
  14. package/dist/docs/agent-setup.md +109 -0
  15. package/dist/docs/agent-tasks.md +169 -0
  16. package/dist/docs/ai-agents.md +90 -0
  17. package/dist/docs/auth.md +74 -0
  18. package/dist/docs/automation.md +150 -0
  19. package/dist/docs/ci.md +105 -0
  20. package/dist/docs/clusters.md +48 -0
  21. package/dist/docs/commands.md +155 -0
  22. package/dist/docs/files.md +86 -0
  23. package/dist/docs/generators.md +52 -0
  24. package/dist/docs/getting-started.md +85 -0
  25. package/dist/docs/index.json +110 -0
  26. package/dist/docs/projects.md +50 -0
  27. package/dist/docs/recorder.md +143 -0
  28. package/dist/docs/results.md +79 -0
  29. package/dist/docs/running.md +80 -0
  30. package/dist/docs/skills.md +88 -0
  31. package/dist/docs/test-plans.md +92 -0
  32. package/dist/docs/troubleshooting.md +79 -0
  33. package/dist/plan.js +250 -0
  34. package/dist/skills/AGENTS.md +70 -0
  35. package/dist/skills/atlas-analyze/SKILL.md +104 -0
  36. package/dist/skills/atlas-correlate/SKILL.md +89 -0
  37. package/dist/skills/atlas-load-test/SKILL.md +154 -0
  38. package/dist/skills/atlas-record/SKILL.md +167 -0
  39. package/dist/skills/atlas-run/SKILL.md +109 -0
  40. package/dist/skills/atlas-test-plan/SKILL.md +281 -0
  41. package/package.json +5 -3
@@ -0,0 +1,169 @@
1
+ # What an Agent Can Do
2
+
3
+ The whole lifecycle, from an empty project to a report you can send someone.
4
+ Each section below is a real thing to ask for, what the agent does about it, and
5
+ what it should ask you along the way.
6
+
7
+ ## Find its bearings
8
+
9
+ > What can I load test here, and how much capacity do I have?
10
+
11
+ Before anything else, a well-behaved assistant establishes what it is looking
12
+ at: who it is signed in as, which account is active, which projects it can
13
+ reach, which test plans and data files those hold, what ran recently, and how
14
+ much capacity and usage allowance you have left.
15
+
16
+ That last part matters more than it sounds. Sizing a test without knowing the
17
+ fleet is how people ask for 50 machines on a 20-machine account, or blow a
18
+ monthly allowance on a warm-up run.
19
+
20
+ ## Record a scenario
21
+
22
+ > Open our staging site, sign in as the demo user, add two items to the basket
23
+ > and check out. Turn that into a test plan.
24
+
25
+ The agent opens a **real, visible browser**. It reads each page as an
26
+ accessibility tree — the same structure a screen reader sees — so it clicks
27
+ "Add to basket" because that button exists, not because a selector was guessed.
28
+ It names each step *before* performing it, because those names become the rows
29
+ in your results report, and `Rome` is a useless row title.
30
+
31
+ You can watch the whole thing and take over whenever you like. For a password,
32
+ an MFA prompt, or a decision only you can make, the agent hands the window back,
33
+ you do that step, and it carries on recording.
34
+
35
+ Prefer to drive yourself? Say so, and it opens a plain recording session for you
36
+ to click through while it waits.
37
+
38
+ Export your cookies, or reuse a saved browser profile, and the recording starts
39
+ already signed in — see [Recording a Scenario](/recorder/). Never give an agent
40
+ a password to type.
41
+
42
+ ## Turn the recording into a real test
43
+
44
+ This is the step people skip, and it is the difference between a load test and
45
+ an expensive replay.
46
+
47
+ A recording is a draft: it contains exactly what *you* did. The agent reads the
48
+ capture and works through it with you, stage by stage, asking rather than
49
+ deciding:
50
+
51
+ 1. **Is the flow right?** The steps, their names, anything missing.
52
+ 2. **Which recorded values should become test data?** The username and password
53
+ you typed. The search term. The product id that appears in three different
54
+ requests. If every simulated user sends the same ones, they collide on the
55
+ same session and hit the same cache — the application looks fast because it
56
+ is barely working. The agent proposes a CSV, the columns, and how many rows;
57
+ you say whether to generate them or supply real data. Atlas then divides
58
+ those rows between machines at run time, so no two users get the same row.
59
+ 3. **What changes per session?** Session ids, CSRF tokens, cart ids — values the
60
+ *server* issued, which must be captured from an earlier response instead of
61
+ replayed. The recorder detects these with evidence, and the agent pins
62
+ anything it missed. See [Dynamic values](/recorder/#dynamic-values-are-handled).
63
+ 4. **Do you need checks?** A `200` that returns a login page is a pass as far as
64
+ JMeter is concerned. Assertions on the responses that matter turn that into a
65
+ visible failure.
66
+ 5. **Upload and smoke-run it.**
67
+
68
+ ## Edit an existing plan
69
+
70
+ > Add a "search by postcode" step to our existing plan, and point it at staging.
71
+
72
+ The agent downloads the stored plan first — uploading replaces a file and there
73
+ is no version history — then makes the narrowest change that does the job:
74
+ recording a new scenario straight into the plan as an additional thread group,
75
+ or editing specific values in place.
76
+
77
+ For structural surgery it will tell you plainly that the JMeter GUI is the right
78
+ tool, rather than rewriting a plan nobody has the source for.
79
+
80
+ ## Debug it locally, in seconds
81
+
82
+ If JMeter is installed on your machine, the agent can run a single user through
83
+ the plan locally before spending any Atlas capacity — the fastest way to confirm
84
+ a new step, an assertion or a data file actually works.
85
+
86
+ It knows the trick that makes this practical: recorded plans contain **think
87
+ time**, typically ten to thirty seconds between steps, which is correct for a
88
+ real load test and absurd for a debug run. The agent switches it off in a
89
+ throwaway copy, so a check that would have taken two minutes takes five seconds,
90
+ then restores it — your plan keeps its pauses, and nothing gets uploaded with
91
+ the think time missing.
92
+
93
+ It can also prove an assertion *fails* when it should, which is the only way to
94
+ know a check is doing anything at all.
95
+
96
+ ## Check before you spend
97
+
98
+ > Will this plan actually run?
99
+
100
+ `atlas plan check` catches what otherwise surfaces as an empty dashboard an hour
101
+ later:
102
+
103
+ - **A data file the plan reads that the project does not have.** Every user in
104
+ that thread group dies before sending a request, so the group disappears from
105
+ your results with *no errors at all* while the rest look healthy.
106
+ - **A plan Atlas cannot attach its reporting to** — it runs, and reports nothing.
107
+ - **A broken structure, or no enabled thread group.**
108
+ - **Fixed user counts**, meaning more machines is the only way to scale it.
109
+
110
+ ## Size and run it
111
+
112
+ > Run it with 500 users for ten minutes, ramped up over five.
113
+
114
+ Sizing is where load tests are most often wrong, in both directions. Each
115
+ machine runs the **whole** plan, so 100 users in the plan across 5 machines is
116
+ 500 users, not 100. The agent does that arithmetic against your real fleet,
117
+ explains it, and confirms with you before starting anything larger than a smoke
118
+ test.
119
+
120
+ It smoke-runs first — one machine, a couple of users — and checks the result
121
+ contains actual data. A smoke run that finishes in seconds with nothing in it is
122
+ a broken plan, not a fast application, and catching that costs one minute
123
+ instead of twenty machine-minutes.
124
+
125
+ While the run is live it can report progress, and stop the test if you ask.
126
+
127
+ ## Read the results
128
+
129
+ > How did it go? Where did it start to break?
130
+
131
+ Numbers are the easy part. The agent reports which steps degraded and at what
132
+ user count, what the errors actually say — with the real request and response,
133
+ not just a code — and how the run behaved over time rather than as one average.
134
+
135
+ It is also taught to distrust a clean-looking result. A test that measured
136
+ nothing looks *better* than one that worked: a missing thread group with zero
137
+ errors, a run that ended in seconds, or fast `200`s returning login pages. Those
138
+ are reported as failures of the test, not as performance.
139
+
140
+ ## Wire it into CI
141
+
142
+ > Add a nightly load test to our pipeline and fail the build if p95 goes over
143
+ > 800ms.
144
+
145
+ The agent writes the pipeline step, using thresholds and exit codes rather than
146
+ a human reading a dashboard:
147
+
148
+ ```sh
149
+ atlas run -p SHOP --jmx checkout.jmx --servers 4 \
150
+ --gate "error_rate<1,p95<800" --junit results.xml
151
+ ```
152
+
153
+ `0` passed · `1` a threshold was breached · `2` a usage or sign-in problem ·
154
+ `3` the run failed or Atlas was unreachable. JUnit output drops into whatever
155
+ already reports your test results. See [Running in CI](/cli/ci).
156
+
157
+ ## What it should always ask
158
+
159
+ - Which project, and which plan when there is more than one
160
+ - How many users, for how long, over what ramp-up
161
+ - Fixed machines or a cluster
162
+ - Confirmation before the full run
163
+ - Whether to generate test data or use yours
164
+
165
+ And what it should never do without you: start a large run, stop someone else's
166
+ test, delete a file it did not just upload, or upload a plan it has not checked.
167
+
168
+ [The skills behind this →](/agents/skills) ·
169
+ [Build your own integration →](/agents/automation)
@@ -0,0 +1,90 @@
1
+ # Atlas for AI Agents
2
+
3
+ **Describe the test. Let the agent build it.**
4
+
5
+ Load testing has always had a gap between wanting a test and having one. Someone
6
+ has to click through the flow, capture the requests, work out which values are
7
+ per-session tokens, wire up the data files, size the run, and then interpret a
8
+ report full of percentiles. It is a day of work for a thirty-second question:
9
+ *will this hold up on launch day?*
10
+
11
+ Atlas closes that gap. Every part of it — recording, test plans, data files,
12
+ machines, runs, results — is reachable through one command-line tool that speaks
13
+ JSON, and it ships with the guidance an AI coding assistant needs to use it
14
+ properly. Point your assistant at Atlas and ask in plain language:
15
+
16
+ > Record a checkout on our staging site, then run it with 500 users for ten
17
+ > minutes and tell me where it breaks.
18
+
19
+ It records the flow in a real browser, turns the recording into a genuine load
20
+ test, checks the plan will actually report, smoke-runs it, asks you to confirm
21
+ the real run, and comes back with what broke and at what point.
22
+
23
+ <div class="tip custom-block" style="padding-top: 8px">
24
+
25
+ New here? [Set it up](/agents/setup) in two commands, then see
26
+ [what it can do](/agents/capabilities).
27
+
28
+ </div>
29
+
30
+ ## Why this works with Atlas
31
+
32
+ **One tool, every surface.** The agent does not need infrastructure credentials,
33
+ a database, or your cloud account. Everything goes through the same CLI you use,
34
+ so your permissions, your account's quota and your machine limits apply exactly
35
+ as they do in the browser.
36
+
37
+ **Machine-readable by design.** Every command takes `--json`. Failures print
38
+ JSON on standard error, so clean output stays clean. `atlas schema --json`
39
+ describes the entire command tree, so an agent can discover the surface instead
40
+ of guessing at flags.
41
+
42
+ **It knows the traps.** Load testing fails quietly. A data file that was never
43
+ uploaded silently removes an entire thread group — with *zero* errors to explain
44
+ it. A plan whose structure defeats reporting runs perfectly and tells you
45
+ nothing. Fast responses that are really login pages look like excellent
46
+ performance. The bundled guidance teaches an assistant to recognise all of these
47
+ before you act on a number that means nothing.
48
+
49
+ **The documentation travels with it.** `atlas docs` prints this documentation
50
+ offline, so an agent in a sandbox or a CI container still has the manual.
51
+
52
+ ## What you get
53
+
54
+ | | |
55
+ |---|---|
56
+ | **Recording without clicking** | The agent opens a real browser, reads the page as an accessibility tree, clicks through your flow and names each step — or hands the window to you for the parts only you can do, like a password or an MFA prompt. |
57
+ | **A real test, not a replay** | It spots the values every simulated user would otherwise repeat — credentials, search terms, product ids — and moves them into a data file, so you are testing your application rather than your cache. |
58
+ | **Plans that actually report** | Before anything runs, `atlas plan check` catches the three failures that produce an empty dashboard an hour later. |
59
+ | **Sizing you can defend** | It reads your real capacity and explains what 500 users means in machines, because each machine runs the whole plan. |
60
+ | **Results in sentences** | Not just p95 numbers: which step degraded, at what user count, and what the errors actually say. |
61
+ | **CI that fails honestly** | Pass/fail thresholds, JUnit output and exit codes, written into your pipeline by the same assistant. |
62
+
63
+ ## Guardrails
64
+
65
+ An agent that can start a load test can spend money and put load on production.
66
+ The bundled guidance is explicit about this, and a good assistant will:
67
+
68
+ - **Confirm before any real run.** Machines are powered on for a test and billed
69
+ to your account. Smoke tests are cheap and encouraged; a 20-machine run is not
70
+ something to start on an assumption.
71
+ - **Never stop a run it did not start.** Someone else's test is someone else's.
72
+ - **Ask rather than guess** about the things that change the result: which
73
+ project, how many users, how long, ramp-up, fixed machines or a cluster.
74
+ - **Report what happened, not what should have.** Including failed thresholds, a
75
+ thread group that vanished, and its own uncertainty.
76
+ - **Leave your files as it found them.** It downloads before it edits, and it
77
+ restores anything it changed for debugging — think time included.
78
+
79
+ Everything an agent can do, you can do by hand with the same commands. Nothing
80
+ here is required, and nothing here is hidden from you.
81
+
82
+ ## Which assistants
83
+
84
+ | Assistant | How it reads the guidance |
85
+ |---|---|
86
+ | **Claude Code** | Skills — loaded automatically when your request is about load testing |
87
+ | **GitHub Copilot, Cursor, Codex, Gemini CLI, Windsurf** | `AGENTS.md` in your project root |
88
+ | **Anything else** | `atlas schema --json`, `atlas docs`, and `--json` on every command |
89
+
90
+ [Set it up →](/agents/setup)
@@ -0,0 +1,74 @@
1
+ # Signing In
2
+
3
+ ## For everyday use
4
+
5
+ ```sh
6
+ atlas login --url https://atlas.cloudbeat.io -u you@company.com
7
+ ```
8
+
9
+ You'll be prompted for your password. The session lasts **8 hours**.
10
+
11
+ Credentials are stored in `~/.atlas/config.json`, readable only by you.
12
+
13
+ ```sh
14
+ atlas whoami # who am I, and in which account
15
+ atlas logout # forget the credential
16
+ ```
17
+
18
+ ## For CI: API tokens
19
+
20
+ A password prompt is no use in a pipeline, and storing a human's password is
21
+ worse. Create an **API token** instead.
22
+
23
+ On your Atlas instance, go to **Profile → API tokens** and create one. The token
24
+ is shown **once** — copy it then.
25
+
26
+ ```sh
27
+ atlas login --token atlas_pat_...
28
+ ```
29
+
30
+ Or, better in CI, pass it as an environment variable and don't store it at all:
31
+
32
+ ```sh
33
+ export ATLAS_TOKEN=atlas_pat_...
34
+ ```
35
+
36
+ ### What a token can and can't do
37
+
38
+ A token acts as **the person who created it**, with the same permissions and in
39
+ one fixed account. If that person's access is reduced or removed, the token
40
+ follows immediately.
41
+
42
+ Two things it deliberately **cannot** do:
43
+
44
+ - create more tokens
45
+ - change a password
46
+
47
+ So a leaked pipeline token can't mint replacements for itself or lock you out.
48
+ Revoking it on the Profile page stops it working at once.
49
+
50
+ If you belong to several accounts, switch to the one the pipeline should use
51
+ *before* creating the token. The token is fixed to whichever account was active
52
+ when it was made.
53
+
54
+ A token is a credential. Put it in your CI system's secret store, not in the
55
+ repository, and not in a build log.
56
+
57
+ ## Settings and precedence
58
+
59
+ Command-line options win over environment variables, which win over the saved
60
+ configuration file.
61
+
62
+ | Variable | Meaning |
63
+ |---|---|
64
+ | `ATLAS_URL` | your Atlas instance |
65
+ | `ATLAS_TOKEN` | API token |
66
+ | `ATLAS_PROJECT` | project to use when `--project` is omitted |
67
+ | `ATLAS_DEBUG` | set to any value to print full error details |
68
+
69
+ To avoid repeating yourself:
70
+
71
+ ```sh
72
+ atlas config set url https://atlas.cloudbeat.io
73
+ atlas config set project SHOP
74
+ ```
@@ -0,0 +1,150 @@
1
+ # Building Your Own Integration
2
+
3
+ The same surfaces the bundled skills use are there for your own scripts, bots
4
+ and agents. No SDK, no separate API client: the CLI is the integration point,
5
+ and everything it does is scriptable.
6
+
7
+ ## JSON everywhere
8
+
9
+ ```sh
10
+ atlas projects --json
11
+ atlas capacity --json
12
+ atlas results SHOP-20260917-101500 --json
13
+ ```
14
+
15
+ Every command takes `--json`. On failure it prints the error as JSON on
16
+ **standard error**, so standard out stays parseable:
17
+
18
+ ```json
19
+ {"error":{"message":"Project 'SHOPP' not found","code":"not_found"}}
20
+ ```
21
+
22
+ Exit codes are the contract, and they do not change with `--json`:
23
+
24
+ | Code | Meaning |
25
+ |---|---|
26
+ | `0` | Success, and any thresholds passed |
27
+ | `1` | A `--gate` threshold was breached — the test ran, the numbers failed |
28
+ | `2` | A usage or authentication problem: bad flags, unknown project, not signed in |
29
+ | `3` | The run failed or timed out, or Atlas could not be reached |
30
+
31
+ `1` and `3` are deliberately distinct: a breached threshold is a result, an
32
+ unreachable server is not.
33
+
34
+ ## Discovering the surface
35
+
36
+ Rather than hard-coding flags, read them:
37
+
38
+ ```sh
39
+ atlas schema --json
40
+ ```
41
+
42
+ This returns every command, argument and option, with its description. Two
43
+ fields worth knowing: `takesValue` says whether the flag expects a value, and
44
+ `valueOptional` whether that value may be omitted. Neither means the flag itself
45
+ is mandatory.
46
+
47
+ ## Documentation, offline
48
+
49
+ ```sh
50
+ atlas docs # list the topics
51
+ atlas docs troubleshooting # print one
52
+ ```
53
+
54
+ The documentation is bundled inside the package, so it works with no network —
55
+ in CI, in a container, in a sandboxed agent.
56
+
57
+ ## Checking a plan without running it
58
+
59
+ ```sh
60
+ atlas plan check ./checkout.jmx -p SHOP --json
61
+ ```
62
+
63
+ Read-only and advisory: it never rewrites your plan. Useful as a pre-commit
64
+ hook or a pipeline step, because it exits non-zero when the plan would produce
65
+ no usable results.
66
+
67
+ ## Driving the recorder from code
68
+
69
+ The recorder can be controlled step by step, which is what lets an agent click
70
+ through a flow. It is also a perfectly good scripting interface:
71
+
72
+ ```sh
73
+ atlas-rec start https://shop.example.com -o flow.jmx -n "Checkout"
74
+ atlas-rec snapshot # the page, as an accessibility tree
75
+ atlas-rec tx new "Search" # name the step that follows
76
+ atlas-rec click --role button --name "Search"
77
+ atlas-rec fill "laptop" --selector "#q"
78
+ atlas-rec wait --selector ".results"
79
+ atlas-rec state --full # everything captured so far
80
+ atlas-rec stop # writes the plan and the capture
81
+ ```
82
+
83
+ The window stays visible and a person can click in the same session — the two
84
+ mix freely, so a script can pause for a human to sign in and then carry on.
85
+
86
+ The control channel is **local to your machine**: it listens on the loopback
87
+ interface, on an ephemeral port, and requires a per-session token that is kept
88
+ out of the process list. It only accepts commands while a recording you started
89
+ is open.
90
+
91
+ Afterwards, a capture can be re-read and rebuilt without recording again:
92
+
93
+ ```sh
94
+ atlas-rec inspect flow.capture.json # transactions, hosts, response codes
95
+ atlas-rec suggest flow.capture.json # per-session values, with evidence
96
+ atlas-rec generate flow.capture.json -o flow.jmx --correlations rules.json
97
+ ```
98
+
99
+ The same capture always produces the same plan, so regenerating is safe to
100
+ repeat and easy to review.
101
+
102
+ ## Authentication for automation
103
+
104
+ Use an API token, never a password:
105
+
106
+ ```sh
107
+ export ATLAS_TOKEN=atlas_pat_...
108
+ export ATLAS_URL=https://atlas.cloudbeat.io
109
+ export ATLAS_PROJECT=SHOP
110
+ atlas run --servers 4 --gate "error_rate<1,p95<800" --junit results.xml
111
+ ```
112
+
113
+ A token acts as its creating user, in one account. Revoking it takes effect
114
+ immediately, and a token cannot mint further tokens or change a password — so a
115
+ leaked CI credential cannot entrench itself. See
116
+ [Signing In](/cli/authentication).
117
+
118
+ ## A worked example
119
+
120
+ Everything together — gate a deployment on a load test:
121
+
122
+ ```sh
123
+ #!/usr/bin/env bash
124
+ set -euo pipefail
125
+
126
+ # Refuse to run a plan that could not report
127
+ atlas plan check -p SHOP --jmx checkout.jmx --json >/dev/null
128
+
129
+ # `|| rc=$?` keeps `set -e` from aborting on a breached threshold, which is a
130
+ # result we want to act on rather than a crash
131
+ rc=0
132
+ atlas run -p SHOP --jmx checkout.jmx --servers 4 \
133
+ --args "-Jthreads=125 -Jrampup=300" \
134
+ --gate "error_rate<1,p95<800" \
135
+ --junit results.xml --json > run.json || rc=$?
136
+
137
+ case $rc in
138
+ 0) echo "passed: $(jq -r .testId run.json)" ;;
139
+ 1) echo "thresholds breached"; jq '.gates[] | select(.passed | not)' run.json; exit 1 ;;
140
+ *) echo "the test did not run (exit $rc)"; exit "$rc" ;;
141
+ esac
142
+ ```
143
+
144
+ With `--wait` — which `--gate` and `--junit` imply — the JSON on standard out
145
+ carries `testId`, `state`, `durationSec`, the overall figures and every gate
146
+ result. It is written **before** a breached threshold sets the exit code, so
147
+ `run.json` is complete either way.
148
+
149
+ [Running in CI](/cli/ci) has the pipeline-ready version, including GitHub
150
+ Actions.
@@ -0,0 +1,105 @@
1
+ # Running in CI
2
+
3
+ The point of running Atlas from CI is to catch a performance regression the same
4
+ way you catch a failing unit test — automatically, on the build that caused it.
5
+
6
+ ## A complete example
7
+
8
+ ```sh
9
+ export ATLAS_URL=https://atlas.cloudbeat.io
10
+ export ATLAS_TOKEN=atlas_pat_...
11
+
12
+ # Only if the plan or its data live in this repository and may have changed.
13
+ atlas files upload -p SHOP ./checkout.jmx ./data/users.csv
14
+
15
+ atlas run -p SHOP --jmx checkout.jmx --servers 5 \
16
+ --gate "error_rate<1,p95<2000" \
17
+ --junit results.xml
18
+ ```
19
+
20
+ If your test plan is maintained in Atlas rather than in the repository, drop the
21
+ upload step — the run command works on its own.
22
+
23
+ ## Pass/fail thresholds
24
+
25
+ `--gate` fails the command when a threshold is breached, checked against the
26
+ run's overall totals.
27
+
28
+ | Metric | Meaning |
29
+ |---|---|
30
+ | `error_rate` | percentage of failed requests |
31
+ | `avg` | average response time, ms |
32
+ | `p90`, `p95`, `p99` | percentile response times, ms |
33
+ | `max` | slowest response, ms |
34
+ | `throughput` | requests per second |
35
+ | `requests` | total requests |
36
+
37
+ Use `<`, `<=`, `>` or `>=`. Separate several with commas, or repeat `--gate`.
38
+
39
+ ```sh
40
+ --gate "error_rate<1,p95<2000,throughput>50"
41
+ ```
42
+
43
+ Setting a gate implies `--wait` — there is nothing to check until the test has
44
+ finished.
45
+
46
+ `error_rate` and a percentile. Averages hide the tail: a p95 catches the slow
47
+ requests a handful of users actually felt, which an average smooths away.
48
+
49
+ ## Exit codes
50
+
51
+ | Code | Meaning |
52
+ |---|---|
53
+ | `0` | the test ran and every threshold passed |
54
+ | `1` | the test ran but a `--gate` threshold was breached |
55
+ | `2` | something was wrong with the request — bad option, unknown project, not signed in |
56
+ | `3` | the test failed or timed out, or the server could not be reached |
57
+
58
+ The distinction that matters: **`1` means your system was too slow, `2` and `3`
59
+ mean the test never produced a verdict.** Treating them the same makes a broken
60
+ pipeline look like a performance regression.
61
+
62
+ ## JUnit report
63
+
64
+ ```sh
65
+ atlas run -p SHOP --servers 5 --junit results.xml
66
+ ```
67
+
68
+ Writes a standard JUnit file with one test case per threshold, so CI shows each
69
+ one as a separate pass or fail. The run's headline numbers are included as
70
+ properties. Point your CI's test reporter at it and gates appear alongside your
71
+ other tests.
72
+
73
+ ## Example: GitHub Actions
74
+
75
+ ```yaml
76
+ - name: Load test
77
+ env:
78
+ ATLAS_URL: https://atlas.cloudbeat.io
79
+ ATLAS_TOKEN: ${{ secrets.ATLAS_TOKEN }}
80
+ run: |
81
+ npm install -g @cloudbeat/atlas-cli
82
+ atlas run -p SHOP --servers 5 \
83
+ --gate "error_rate<1,p95<2000" \
84
+ --junit results.xml
85
+
86
+ - name: Publish results
87
+ if: always()
88
+ uses: actions/upload-artifact@v4
89
+ with:
90
+ name: load-test
91
+ path: results.xml
92
+ ```
93
+
94
+ ## Things worth knowing
95
+
96
+ **Load tests take minutes, not seconds.** Give the job a generous timeout, and
97
+ consider running it on a schedule or on merges to main rather than on every
98
+ push.
99
+
100
+ **Machines may be busy.** If another test holds the generators you asked for,
101
+ your run is queued and starts when they free up. Set `--timeout` to bound how
102
+ long you're willing to wait.
103
+
104
+ **A queued or failed run is not a regression.** That's the exit-code distinction
105
+ above — don't let a `3` open a performance bug.
@@ -0,0 +1,48 @@
1
+ # Clusters
2
+
3
+ A **cluster** is elastic capacity: instead of fixed machines that sit there
4
+ between tests, units are created when a test starts and destroyed when it ends.
5
+
6
+ You pay for what a test uses, and you're not limited by how many machines you
7
+ happened to set up in advance.
8
+
9
+ ## When to use one
10
+
11
+ Use a cluster when your load varies a lot between tests, or when you want a
12
+ large run occasionally without keeping that capacity around. Use fixed
13
+ [servers](/generators/adding) when you want predictable, always-available
14
+ machines — or when your test needs to come from a specific network location.
15
+
16
+ ## Setting one up
17
+
18
+ A cluster runs on a Docker host you provide. Atlas talks to it through a small
19
+ **controller** you install on that host, which connects outbound — so the host
20
+ needs no inbound access, exactly like a load generator.
21
+
22
+ Go to **Fleet → Clusters**, create a cluster, and run the install command it
23
+ gives you on your Docker host. When the controller connects, the cluster shows
24
+ as ready.
25
+
26
+ ## Running on a cluster
27
+
28
+ On the **Run Test** tab choose **Cluster** instead of Servers, and say how many
29
+ units you want:
30
+
31
+ ```bash
32
+ atlas run -p SHOP --cluster my-cluster --units 10
33
+ ```
34
+
35
+ Each unit is one JMeter instance, equivalent to one load generator. Ten units
36
+ running a 100-thread plan is 1,000 concurrent users.
37
+
38
+ ## While it runs
39
+
40
+ Units register themselves as they come up, then the test deploys and starts as
41
+ usual. When the test finishes, every unit is destroyed.
42
+
43
+ If a run ends unexpectedly, check the Clusters tab to confirm nothing was left
44
+ behind.
45
+
46
+ Clusters are newer than fixed servers. If a run needs to be reliable — a
47
+ scheduled regression test, a customer demo — fixed machines are the safer
48
+ choice today.