@plune-ai/cli 0.16.0 → 0.17.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.
package/README.md CHANGED
@@ -120,7 +120,7 @@ the last resort, used only when `PLUNE_TOKEN` is set nowhere else. Nothing write
120
120
  | `plune login` | Save a [Plune platform](https://plune.ai/platform) API token so `sync` and `ingest` can reach it. The token is **checked against the API before it is saved**, so a wrong one fails here rather than two commands later. Get one at `https://beta.plune.ai` → Account → API tokens. Flags: `--token <token>` (omit to paste it or pipe it via stdin), `--skip-verify` (save without checking, for offline setup). In CI, skip this step: every platform command reads `PLUNE_TOKEN` from the environment first, and the saved login only when it is not set. |
121
121
  | `plune logout` | Remove the saved token. |
122
122
  | `plune sync` | Upload the latest local run to the platform. Flags: `--file <path>` to send a specific run JSON. |
123
- | `plune run import <file>` | Turn a **JUnit XML** or **Playwright JSON** report into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json` (detected from the file when omitted), `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue. |
123
+ | `plune run import <file>` | Turn a **JUnit XML** or **Playwright JSON** report, or an **Allure `allure-results` folder**, into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json\|allure` (detected from the file when omitted; a folder is Allure), `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue, `--fail-on-missing-attachments` to exit 1 when a file a JUnit report names with `[[ATTACHMENT\|path]]`, or an Allure result names as a `source`, is not there (the results are sent either way). |
124
124
  | `plune run start` | Open a platform run — or join the one already carrying `--key` — and print its id. Flags: `--key <externalKey>` (generated when absent), `--json` for one machine-readable line. |
125
125
  | `plune run finish <id>` | Close a platform run. This is what the reporter tells you to do for a run it had to leave open. Flags: `--terminate` to record it as cut short, `--reason <text>`. |
126
126
  | `plune run exec -- <command>` | Open a run, run the command inside it, close the run — and exit with whatever the command returned. Sets `PLUNE_SHARED_RUN` for you, so anything reporting inside joins that run. Flags: `--key <externalKey>`. |
@@ -145,6 +145,7 @@ costs nothing beyond a Plune token.
145
145
  plune login # once, on your machine; in CI export PLUNE_TOKEN instead
146
146
  plune run import ./junit.xml # Jest, Vitest, pytest, PHPUnit, Surefire, Cypress, …
147
147
  plune run import ./playwright.json # or Playwright's own JSON report
148
+ plune run import ./allure-results # or the folder an Allure adapter wrote — see below
148
149
  ```
149
150
 
150
151
  The format is read from the file, not from its name. Statuses go over as the report wrote them and
@@ -165,6 +166,125 @@ JPEG or WebP, up to 2 MB each, 20 per result — is uploaded to that result, a p
165
166
  run in Plune shows each test with what it looked at. `plune run import` finds them where the report
166
167
  says they are, so run it where the report was written; the summary counts any it could not find.
167
168
 
169
+ JSON and plain text come the same way — the answer of an API, a log — whether a test attached them
170
+ with a `path` or as a `body` (a report holds a body itself, so `plune run import` needs no file for
171
+ it). Only `application/json` and `text/plain`, as the attachment names them; UTF-8 without NUL
172
+ bytes, up to 512 KiB each and 10 per result. The summary counts them apart from the screenshots.
173
+
174
+ A project that has connected its own storage bucket in Plune takes more. Every file an attempt kept
175
+ — screenshots, text, a Playwright trace, a video — goes straight from this machine into that bucket
176
+ over short-lived links Plune hands out per file, so a trace of up to 100 MB is streamed from disk,
177
+ never read into memory. Up to four files go at once. The limits there are larger: 10 MiB for an
178
+ image, 5 MiB for a text, 50 MiB for any other file and 100 MiB for a video or a trace, 30 files a
179
+ result. The links are write keys to your bucket, so they are never printed — not in the log, not with
180
+ `--verbose`, not in an error; a line names the file and a code. The first time a run finds the
181
+ bucket it says so, and the summary reads `N file(s) uploaded to your bucket`, with the number
182
+ skipped or failed when there are any. A file that does not arrive is a warning, never a failed
183
+ import. Without a bucket, screenshots and text go as before, and a trace or a video is not stored —
184
+ the log says so once and the summary counts them.
185
+
186
+ ### Files from a JUnit report
187
+
188
+ JUnit has no field for a file, so the runners that keep one print a line of their own in the test's
189
+ output, as Jenkins and GitLab read it: `[[ATTACHMENT|path]]` on a line by itself, in `system-out` or
190
+ `system-err` of the test. `plune run import` reads that line in every test case and sends the file the
191
+ way the Playwright reporter sends one: into your bucket if the project has one, to the result if it is a
192
+ PNG, JPEG, WebP, JSON or plain text; any other file (a trace, a video) needs the bucket and is counted as
193
+ not stored without one. Any extension is read. A relative path
194
+ counts from the folder of the report, so run the import where the report and its files were written.
195
+
196
+ pytest (`junit_logging=system-out` is what puts the output into the report):
197
+
198
+ ```python
199
+ def test_checkout(page):
200
+ page.screenshot(path="artifacts/checkout.png")
201
+ print("[[ATTACHMENT|artifacts/checkout.png]]")
202
+ ```
203
+
204
+ ```bash
205
+ pytest --junitxml=report.xml -o junit_logging=system-out
206
+ plune run import report.xml
207
+ ```
208
+
209
+ Java, JUnit 5 (Maven Surefire writes the test's output into its testcase):
210
+
211
+ ```java
212
+ @Test
213
+ void checkout() {
214
+ // ...
215
+ System.out.println("[[ATTACHMENT|target/artifacts/checkout.png]]");
216
+ }
217
+ ```
218
+
219
+ A file that is not there (a cleaned-up workspace, a typo, a screenshot that was never taken) does not
220
+ fail the import: every result still goes to Plune. Each one gets a line, always, not only with
221
+ `--verbose`, and the end of the output counts them:
222
+
223
+ ```
224
+ plune: attachment not found — "shop.Cart › rejects a negative quantity": artifacts/missing-trace.zip
225
+ Imported 120 results · 34 files uploaded · 2 files not found
226
+ ```
227
+
228
+ A CI step that should go red for it passes `--fail-on-missing-attachments`: exit code 1, with the
229
+ results already sent. A path that leaves the folder of the report (`../../etc/passwd`, an absolute path
230
+ elsewhere, a link that points outside) is refused with the same line, and the file is never read.
231
+ Console output kept per suite rather than per test (`jest-junit`) names no test, so nothing is read from it.
232
+ For Jest, use Allure below.
233
+
234
+ ### An `allure-results` folder
235
+
236
+ Every Allure adapter (pytest, JUnit 5, TestNG, Playwright, Cypress, Jest, Vitest, WebdriverIO, .NET) writes
237
+ the same folder: a `*-result.json` per test, a `*-container.json` per suite, and the files the tests attached.
238
+ Point `plune run import` at the folder (a folder is read as Allure, no flag needed). Each test arrives with its
239
+ name, its status as Allure shows it (`passed`, `failed`, `broken`, `skipped`), its time, the failure message and
240
+ trace, and its steps; a test run again (same `historyId`) is one test with attempts, the last one counting.
241
+ The files come from the test, from its steps and from its fixtures (`befores`, `afters`), each with the
242
+ `type` Allure wrote, and go the way a JUnit file goes: your bucket, or the result for a picture or a text. A
243
+ `source` counts from the folder, and one that leaves it is refused. A missing file, `--fail-on-missing-attachments`
244
+ and the summary line work as for JUnit above.
245
+
246
+ pytest (`allure-pytest`):
247
+
248
+ ```bash
249
+ pip install allure-pytest
250
+ pytest --alluredir=allure-results
251
+ plune run import allure-results
252
+ ```
253
+
254
+ ```python
255
+ import allure
256
+
257
+ def test_checkout(page):
258
+ with allure.step("pay"):
259
+ allure.attach.file("artifacts/checkout.png", name="checkout", attachment_type=allure.attachment_type.PNG)
260
+ ```
261
+
262
+ Java, JUnit 5 (`allure-junit5`, with the AspectJ agent from Allure's setup; the results folder is
263
+ `target/allure-results` unless `allure.results.directory` says otherwise):
264
+
265
+ ```bash
266
+ mvn test
267
+ plune run import target/allure-results
268
+ ```
269
+
270
+ ```java
271
+ @Test
272
+ void checkout() {
273
+ Allure.addAttachment("checkout", "image/png", new FileInputStream("target/artifacts/checkout.png"), ".png");
274
+ }
275
+ ```
276
+
277
+ Jest has no per-test output in JUnit; `allure-jest` gives it one (`allure.attachment(...)` in a test or a step).
278
+ Tests are matched to Plune cases by the same key as a JUnit report's, `classname#name`, where the adapter's
279
+ names allow it (pytest, JUnit 5, Playwright); for Vitest, Jest and Cypress the key is the runner, the file and the
280
+ test's full name (`vt:test/cart.test.js#cart adds an item`, `jest:…`, `cy:…`). A file whose name starts with `_`
281
+ is not sent: the core hides it as Playwright's own reports do, and Allure has no such convention, so name
282
+ attachments without a leading underscore.
283
+
284
+ Check that the output reaches the report: Gradle writes it only with `reports.junitXml.outputPerTestCase = true`,
285
+ and Maven Surefire moves it out of the XML when `redirectTestOutputToFile` is `true`. As in the Playwright
286
+ reporter, a file whose name starts with an underscore is skipped, and a file several tests name is uploaded once per test.
287
+
168
288
  ### Several jobs, one run
169
289
 
170
290
  Two suites, or a sharded matrix, report into a single run when every job shares a key **and** knows