@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,109 @@
1
+ ---
2
+ name: atlas-run
3
+ description: Start and size an Atlas load test - how many machines or cluster units, how users map onto them, ramp-up, pass/fail gates, exit codes and CI usage. Use when someone asks to run a test, asks how many machines they need, wants a test to fail a build on a threshold, or is waiting on a queued run.
4
+ ---
5
+
6
+ # Running and sizing
7
+
8
+ ```bash
9
+ atlas run -p <project> --jmx <plan> --servers 5 --wait --gate "error_rate<1,p95<2000"
10
+ ```
11
+
12
+ ## How load adds up
13
+
14
+ **Each machine runs the whole plan independently.** There is no controller
15
+ splitting users between them. So:
16
+
17
+ ```
18
+ total users = users in the plan x number of machines
19
+ ```
20
+
21
+ A plan with 100 users on 5 machines is 500 concurrent users. This is the single
22
+ most common thing to get wrong, and it is wrong by a factor of the fleet size.
23
+
24
+ A plan produced by the recorder exposes its size as run-time settings, so you can
25
+ scale it without editing the file:
26
+
27
+ ```bash
28
+ atlas run -p SHOP --jmx flow.jmx --servers 5 --args "-Jthreads=100 -Jrampup=300 -Jloops=-1"
29
+ ```
30
+
31
+ - `-Jthreads` — users **per machine**
32
+ - `-Jrampup` — seconds to start them all; ramping 500 users instantly tests your
33
+ own patience, not the application
34
+ - `-Jloops` — iterations per user; `-1` is continuous
35
+
36
+ An older or hand-written plan usually has fixed numbers inside it. Then machines
37
+ are the only dial, and a plan with 2 users cannot be made into a 500-user test by
38
+ asking for 5 machines. Say so instead of running it anyway.
39
+
40
+ ## Where it runs
41
+
42
+ ```bash
43
+ atlas capacity --json
44
+ ```
45
+
46
+ - `--servers <n>` — n available machines
47
+ - `--server <name...>` — specific machines by name
48
+ - `--cluster <name> --units <n>` — elastic capacity: n containers created for the
49
+ test and destroyed afterwards
50
+
51
+ Machines that are off are fine: they are powered on for the run and powered off
52
+ afterwards. That is also why a run costs money — confirm before starting a large
53
+ one.
54
+
55
+ If every machine is busy, the run is **queued** rather than rejected, and starts
56
+ when they free up. `atlas run` says so; with `--wait` it waits through the queue.
57
+
58
+ ## Data files
59
+
60
+ Data files are **divided** between machines by default — 10,000 rows across 5
61
+ machines is 2,000 each, so no two users get the same row. Use `--no-split` when
62
+ every machine must see the whole file (a small lookup table, a list of products
63
+ every user should hit).
64
+
65
+ ## Gates
66
+
67
+ ```bash
68
+ --gate "error_rate<1,p95<2000" --gate "throughput>50"
69
+ ```
70
+
71
+ Metrics: `error_rate`, `avg`, `p90`, `p95`, `p99`, `max`, `throughput`,
72
+ `requests`, with `<`, `<=`, `>`, `>=`. They are evaluated against the whole test.
73
+ `--gate` and `--junit` imply `--wait`, because there is nothing to judge until
74
+ the run has finished.
75
+
76
+ ## Exit codes
77
+
78
+ | Code | Meaning |
79
+ |---|---|
80
+ | 0 | ran, every gate passed |
81
+ | 1 | ran, a gate was breached |
82
+ | 2 | usage error: bad flags, unknown project, not authenticated |
83
+ | 3 | the run failed or timed out, or the server was unreachable |
84
+
85
+ 1 and 3 are different in the way that matters for CI: 1 is a result, 3 is a
86
+ failure to get a result. Do not paper over either.
87
+
88
+ ## In CI
89
+
90
+ ```bash
91
+ atlas run -p SHOP --jmx flow.jmx --servers 3 --wait \
92
+ --gate "error_rate<1,p95<2000" --junit results.xml
93
+ ```
94
+
95
+ Authenticate with a token in `ATLAS_TOKEN` — never a password. A token acts as
96
+ its owner in one account, and it stops working the moment that user is removed.
97
+
98
+ ## While it runs, and stopping
99
+
100
+ ```bash
101
+ atlas status <testId> # still going? headline numbers
102
+ atlas tests -p <project> # recent runs, including anything running now
103
+ atlas stop <testId>
104
+ ```
105
+
106
+ `atlas stop` only reports success once it has **confirmed** the process is gone
107
+ on every machine. If it comes back with machines it could not reach, the test may
108
+ well still be running and reporting: say that, and retry. Treating an unconfirmed
109
+ stop as a stop is how a runaway test goes unnoticed for hours.
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: atlas-test-plan
3
+ description: Get a test plan and its data files into an Atlas project - download an existing plan, edit it or add a scenario to it, turn a fresh recording into a real test, put repeated values into a data file, debug it locally, check it will actually run, and upload it back. Use when someone wants to change an existing test, add a flow to one, asks what to do next with a plan or a recording they just made, fix a plan that reports nothing, or manage a project's test data files.
4
+ ---
5
+
6
+ # Test plans and data files
7
+
8
+ Every test needs a plan (`.jmx`) and usually data files (`.csv`/`.txt`) in the
9
+ project. There are two ways to arrive at one, and both end the same way: check
10
+ it, upload it, smoke-run it.
11
+
12
+ **Start by looking at what is already there:**
13
+
14
+ ```bash
15
+ atlas files list -p <project> --json
16
+ ```
17
+
18
+ ## Path A — change an existing plan
19
+
20
+ ```bash
21
+ atlas files download -p <project> checkout.jmx -o ./checkout.jmx
22
+ ```
23
+
24
+ Downloading first is not optional: **uploading replaces a file of the same name**
25
+ and there is no version history. The copy you downloaded is the only way back.
26
+
27
+ Then edit. Three kinds of change, in order of preference:
28
+
29
+ **Add a whole new scenario** — record it straight into the downloaded plan. An
30
+ existing target file is merged into, not overwritten, so the new flow arrives as
31
+ an additional thread group and a `.bak` is written first:
32
+
33
+ ```bash
34
+ atlas-rec start https://shop.example.com -o ./checkout.jmx -n "New checkout"
35
+ # ... drive it, see atlas-record ...
36
+ atlas-rec stop
37
+ ```
38
+
39
+ **Change values in place** — thread counts, a data-file name, a host. Edit the
40
+ specific `<stringProp>` and nothing else:
41
+
42
+ ```xml
43
+ <stringProp name="ThreadGroup.num_threads">50</stringProp>
44
+ <stringProp name="filename">users.csv</stringProp>
45
+ ```
46
+
47
+ Never reformat the file, and never add or remove an element by hand unless you
48
+ are certain about its `<hashTree>`. Every element in a JMeter plan is followed by
49
+ a `<hashTree>` holding its children; an unbalanced one means JMeter will not open
50
+ the file at all. `atlas plan check` counts them for you.
51
+
52
+ **Structural surgery** — new controllers, reordering, deleting a thread group.
53
+ Say plainly that this is better done in the JMeter GUI, and offer the targeted
54
+ alternative instead. Replacing a plan you do not fully understand is how someone
55
+ loses a scenario nobody has the source for.
56
+
57
+ ## Path B — a new plan
58
+
59
+ Record one (see `atlas-record`), which produces a plan whose thread counts can be
60
+ set at run time. Then continue below.
61
+
62
+ ## Turning a recording into a test
63
+
64
+ A freshly recorded plan is a draft. Someone arriving with one — "I recorded a
65
+ flow, what next?" — needs these stages, in this order, **asking as you go rather
66
+ than deciding for them**. Do not upload it, and do not start editing it, before
67
+ they have answered.
68
+
69
+ Start by saying what is there: the scenario name, each transaction with its
70
+ request count, any unexpected status codes, and where the plan and capture files
71
+ are.
72
+
73
+ **1. Is the flow right?** Are the steps and their names the ones they want
74
+ reported? A missing step means recording again; a bad name is a one-line fix.
75
+
76
+ **2. Should the recorded values become test data?** This is the question that
77
+ turns a recording into a load test, so raise it every time. Read the capture and
78
+ list what each simulated user would otherwise send identically:
79
+
80
+ ```bash
81
+ atlas-rec state --full # while recording
82
+ atlas-rec inspect flow.capture.json
83
+ ```
84
+
85
+ Look through the request parameters and bodies for:
86
+
87
+ - **Credentials** — a username and password typed during the recording. Every
88
+ user signing in as one person is the most common way a test measures nothing
89
+ real: sessions collide, caches hide the work, and the login step is not tested
90
+ at all.
91
+ - **Search terms, product ids, categories, postcodes** — one value means one
92
+ cached answer, repeated.
93
+ - **Quantities, dates, addresses** — anything a real user varies.
94
+
95
+ Distinguish these from **values the server issued** — session ids, tokens,
96
+ cart ids, anything that came back in an earlier response. Those are correlation,
97
+ not test data, and belong to `atlas-correlate`. `atlas-rec suggest` finds them.
98
+
99
+ Propose a data file for the rest: say which values you would parameterise, what
100
+ you would call the columns, and how many rows they need. Ask whether they have
101
+ real data to use or want you to generate it — realistic data is theirs to
102
+ provide, and generated data is fine when they say so.
103
+
104
+ ```csv
105
+ username,password,search_term
106
+ user001,...,laptop
107
+ user002,...,headphones
108
+ ```
109
+
110
+ Then wire the plan to read it: a CSV data set at the top of the thread group, and
111
+ `${username}`-style variables replacing the literals in the requests. That edit is
112
+ "Change values in place" below, and Atlas divides the rows between machines at run time,
113
+ so each user gets a different row.
114
+
115
+ **3. Do the dynamic values need handling?** Run `atlas-rec suggest`, show what it
116
+ found with its evidence, and pin anything it missed — see `atlas-correlate`.
117
+
118
+ **4. Are checks needed?** A 200 that returns a login page or an empty result is a
119
+ pass as far as the plan is concerned. Offer assertions on the responses that
120
+ matter, and debug them locally before uploading (see below).
121
+
122
+ **5. Upload and smoke-run it** — the rest of this skill, then `atlas-load-test`.
123
+
124
+ ## How these plans are put together
125
+
126
+ A recorded plan — and most plans in these projects — has the same skeleton, and
127
+ knowing it saves you from reading 700 lines of XML to find one value:
128
+
129
+ - **`Settings - Sleeps`** — a variables element at the top of the plan holding
130
+ `round_sleep`, `short_sleep` and `long_sleep`. Every pause in the plan is a
131
+ *Think Time* step reading one of them: `round_sleep` once per iteration,
132
+ `short_sleep` between steps the person clicked through quickly, `long_sleep`
133
+ where they paused. The pauses themselves stay enabled; **the variables element
134
+ is what switches them on and off.** Disabled, the variables do not exist, every
135
+ pause resolves to 0 ms, and the plan runs flat out. Enabled, its values are the
136
+ wait in milliseconds — typically 10s and 30s, so a four-step scenario takes
137
+ well over a minute per user.
138
+ - **`Settings - Host`** — variables for the target host, normally disabled so the
139
+ recorded URLs are used as-is. Enable and edit it to point the same plan at
140
+ another environment.
141
+ - **Cache and Cookie Managers, and HTTP Request Defaults**, applying to the whole
142
+ plan.
143
+ - **One thread group per scenario**, each holding numbered transactions
144
+ (`01 Open home page`) and numbered samplers inside them (`01.01 /`). The
145
+ numbering is what makes a results report readable — keep it when you add a
146
+ step.
147
+ - **Sizing through run-time settings** — `${__P(threads,..)}`, `${__P(rampup,..)}`
148
+ and `${__P(loops,..)}`, so `--args "-Jthreads=50"` scales the plan without
149
+ editing it. Note the sleep variables are **not** settings of that kind: `-J`
150
+ will not change them.
151
+
152
+ Merging a recorded scenario into an existing plan keeps **that plan's** settings,
153
+ not the recording's. A new recording has its sleeps switched off; a plan someone
154
+ has been running usually has them on, and the new scenario inherits that.
155
+
156
+ ## Debugging a plan locally
157
+
158
+ Running the plan yourself with one user is the fastest way to confirm a new
159
+ scenario, an assertion or a correlation actually works. It needs JMeter on the
160
+ machine (`jmeter -v`); when it is missing, say so and use a smoke run on Atlas
161
+ instead.
162
+
163
+ **Work on a copy.** Never debug the file you are about to upload:
164
+
165
+ ```bash
166
+ cp ./checkout.jmx ./debug.jmx
167
+ ```
168
+
169
+ **Check the sleeps, do not assume.** This is the single biggest time sink: with
170
+ the pauses on, a four-step scenario takes ~100 s per user instead of ~5 s, and
171
+ every re-check costs another two minutes.
172
+
173
+ ```bash
174
+ grep -n 'testname="Settings - Sleeps"' ./debug.jmx
175
+ ```
176
+
177
+ If the element does not carry `enabled="false"`, the pauses are live. Disable it
178
+ in the copy — the element only, not the pauses:
179
+
180
+ ```xml
181
+ <Arguments ... testname="Settings - Sleeps" enabled="false">
182
+ ```
183
+
184
+ **Cut the run down to what you are testing:** add `enabled="false"` to the thread
185
+ groups you are not debugging, and run one user, one iteration.
186
+
187
+ ```bash
188
+ JVM_ARGS="-XX:TieredStopAtLevel=1" HEAP="-Xms256m -Xmx512m" \
189
+ jmeter -n -t debug.jmx -l debug.jtl -Jthreads=1 -Jloops=1 \
190
+ -Jjmeter.save.saveservice.output_format=csv \
191
+ -Jjmeter.save.saveservice.assertion_results_failure_message=true >/dev/null 2>&1
192
+ awk -F, '{print $3" | "$4" | "$8" | "$9}' debug.jtl # label, code, ok, why not
193
+ ```
194
+
195
+ **Read the results file, not the console.** JMeter ends every non-GUI run with a
196
+ page of log4j shutdown lines that mean nothing; the `.jtl` is the answer. The
197
+ `JVM_ARGS`/`HEAP` prefix roughly halves JMeter's startup for a one-user run. A
198
+ four-step scenario like this takes about 5 seconds end to end — if it takes a
199
+ minute or more, the sleeps are still on.
200
+
201
+ **Restore anything you changed.** If you had to disable the sleeps in the real
202
+ plan rather than a copy — say, because the person asked you to debug that file —
203
+ note the original values and the enabled/disabled state first, put them back
204
+ before uploading, and confirm with the same `grep`. A plan uploaded with its
205
+ think time switched off hammers the target far harder than intended, and nothing
206
+ downstream will warn anyone.
207
+
208
+ **Prove an assertion can fail, cheaply.** An assertion that passes may simply
209
+ never have been evaluated. Check it against the recording before spending a run:
210
+ the capture file holds the real response bodies, so a JSON path or a text match
211
+ can be tested in a second with `python3`/`jq` — including the failing case. When
212
+ you do want JMeter to prove it, put the passing and failing variants in the same
213
+ copy, or start both runs at once, rather than one run after another.
214
+
215
+ ## Check before uploading
216
+
217
+ ```bash
218
+ atlas plan check ./checkout.jmx -p <project>
219
+ ```
220
+
221
+ This answers the questions that otherwise only surface as an empty dashboard an
222
+ hour later. With `-p` it also checks the plan's data files against what the
223
+ project actually holds. It exits non-zero when the plan would not produce
224
+ results, and reports:
225
+
226
+ - **A data file the plan reads that is not in the project.** This is the one that
227
+ hurts: every user in that thread group fails before sending a request, so the
228
+ group vanishes from the results *with no errors at all* while the other groups
229
+ look healthy.
230
+ - **A plan Atlas cannot attach its reporting to** — it would run and report
231
+ nothing.
232
+ - **A broken structure**, or no enabled thread group.
233
+ - **Fixed user counts**, meaning machines are the only way to scale it.
234
+ - Paths from another machine and GUI listeners are reported for information:
235
+ Atlas rewrites data-file paths to the uploaded file and switches off View
236
+ Results Tree and Simple Data Writer in the copy it deploys. Your stored file is
237
+ never modified.
238
+
239
+ ## Upload
240
+
241
+ ```bash
242
+ atlas files upload -p <project> ./checkout.jmx ./users.csv
243
+ ```
244
+
245
+ Same name replaces. Different name adds — so `--jmx` chooses which plan a run
246
+ uses, and a project can hold several. Uploading a plan does not start anything.
247
+
248
+ Then check it from the project's point of view, which is what will actually run:
249
+
250
+ ```bash
251
+ atlas plan check -p <project> --jmx checkout.jmx
252
+ ```
253
+
254
+ ## Data files
255
+
256
+ - **Names must match** what the plan reads. The plan referring to
257
+ `C:\data\users.csv` is fine as long as `users.csv` is uploaded — Atlas resolves
258
+ it. Nothing named `users.csv` in the project is not fine.
259
+ - **Rows are divided between machines**, not copied. 10,000 rows across 5
260
+ machines is 2,000 each, so no two users get the same row. Pass `--no-split` at
261
+ run time when every machine must see the whole file.
262
+ - **The first line is a header only if the plan says so.** Atlas reads that from
263
+ the plan's data-set configuration, so leave the file exactly as the plan
264
+ expects it — do not add or strip a header row to be helpful.
265
+ - Generating test data is fine and often useful; say what you generated and how
266
+ many rows, and make sure it matches the columns the plan expects.
267
+
268
+ ## Deleting
269
+
270
+ ```bash
271
+ atlas files rm -p <project> old-data.csv --yes
272
+ ```
273
+
274
+ Deletion is not undoable from here. Download first if there is any doubt, and
275
+ never delete a file you did not just upload without asking.
276
+
277
+ ## Finish the job
278
+
279
+ An uploaded plan is not a working plan. Smoke-run it — one machine, a couple of
280
+ users — and check the results contain data before anyone sizes it up. That flow
281
+ is in `atlas-load-test`, and reading the result is in `atlas-analyze`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbeat/atlas-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Atlas CLI — run JMeter load tests from CI and record scenarios",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -24,11 +24,13 @@
24
24
  },
25
25
  "license": "UNLICENSED",
26
26
  "scripts": {
27
- "build": "tsc",
27
+ "build": "tsc && node scripts/bundle-docs.js && node scripts/bundle-skills.js",
28
28
  "dev": "ts-node src/cli.ts",
29
29
  "start": "node dist/cli.js",
30
30
  "watch": "tsc --watch",
31
- "prepublishOnly": "npm run build"
31
+ "prepublishOnly": "npm run build",
32
+ "test:plan": "ts-node --compiler-options '{\"module\":\"commonjs\"}' test/plan.test.ts",
33
+ "test": "npm run test:plan"
32
34
  },
33
35
  "dependencies": {
34
36
  "chalk": "^4.1.2",