@allurereport/plugin-testops 3.15.0 → 3.16.0

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/dist/client.js CHANGED
@@ -25,6 +25,49 @@ class TestOpsClientError extends AxiosError {
25
25
  }
26
26
  const CHUNK_SIZE = 100;
27
27
  const BULK_UPLOAD_CHUNK_SIZE = 1000;
28
+ const MAX_REQUEST_RETRIES = 3;
29
+ const RETRY_BASE_DELAY_MS = 500;
30
+ const getAxiosCause = (error) => {
31
+ if (isAxiosError(error)) {
32
+ return error;
33
+ }
34
+ return error instanceof Error && isAxiosError(error.cause) ? error.cause : undefined;
35
+ };
36
+ const isRetryableRequestError = (error) => {
37
+ const cause = getAxiosCause(error);
38
+ if (!cause || cause.code === "ERR_CANCELED" || cause.name === "CanceledError") {
39
+ return false;
40
+ }
41
+ const status = cause.response?.status;
42
+ return status === undefined || status === 408 || status === 429 || status >= 500;
43
+ };
44
+ const retryAfterMs = (error) => {
45
+ const headers = getAxiosCause(error)?.response?.headers;
46
+ const value = typeof headers?.get === "function" ? headers.get("retry-after") : headers?.["retry-after"];
47
+ const normalized = Array.isArray(value) ? value[0] : value;
48
+ if (typeof normalized !== "string" && typeof normalized !== "number") {
49
+ return undefined;
50
+ }
51
+ const seconds = Number(normalized);
52
+ if (Number.isFinite(seconds)) {
53
+ return Math.max(0, seconds * 1000);
54
+ }
55
+ const date = Date.parse(String(normalized));
56
+ return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());
57
+ };
58
+ const retryRequest = async (request) => {
59
+ for (let attempt = 0;; attempt += 1) {
60
+ try {
61
+ return await request();
62
+ }
63
+ catch (error) {
64
+ if (attempt >= MAX_REQUEST_RETRIES || !isRetryableRequestError(error)) {
65
+ throw error;
66
+ }
67
+ await new Promise((resolve) => setTimeout(resolve, retryAfterMs(error) ?? RETRY_BASE_DELAY_MS * 2 ** attempt));
68
+ }
69
+ }
70
+ };
28
71
  export class TestOpsClient {
29
72
  constructor(params) {
30
73
  _TestOpsClient_instances.add(this);
@@ -175,7 +218,7 @@ export class TestOpsClient {
175
218
  throw new Error("Launch isn't created! Call createLaunch first");
176
219
  }
177
220
  __classPrivateFieldGet(this, _TestOpsClient_logger, "f").verbose("Retrieving launch progress status…");
178
- const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").get(`/api/launch/${__classPrivateFieldGet(this, _TestOpsClient_launch, "f").id}/progress`);
221
+ const data = await retryRequest(() => __classPrivateFieldGet(this, _TestOpsClient_client, "f").get(`/api/launch/${__classPrivateFieldGet(this, _TestOpsClient_launch, "f").id}/progress`));
179
222
  return data.ready;
180
223
  }
181
224
  async createSession(environment = {}) {
@@ -247,7 +290,9 @@ export class TestOpsClient {
247
290
  if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
248
291
  throw new Error("Launch isn't created! Call createLaunch first");
249
292
  }
293
+ const launchId = __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id;
250
294
  const formData = new FormData();
295
+ let hasResolvedAttachments = false;
251
296
  for (const attachmentLink of attachments) {
252
297
  const attachment = await attachmentsResolver(attachmentLink);
253
298
  if (!attachment) {
@@ -257,6 +302,10 @@ export class TestOpsClient {
257
302
  filename: attachment.originalFileName,
258
303
  contentType: attachment.contentType,
259
304
  });
305
+ hasResolvedAttachments = true;
306
+ }
307
+ if (!hasResolvedAttachments) {
308
+ return;
260
309
  }
261
310
  await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/attachment", {
262
311
  body: formData,
@@ -265,7 +314,7 @@ export class TestOpsClient {
265
314
  const percent = total > 0 ? Math.min(100, Math.max(0, (progressEvent.loaded / total) * 100)) : 0;
266
315
  onProgress?.(percent, total);
267
316
  },
268
- params: { launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id },
317
+ params: { launchId },
269
318
  headers: formData.getHeaders(),
270
319
  });
271
320
  }
@@ -276,9 +325,10 @@ export class TestOpsClient {
276
325
  if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
277
326
  throw new Error("Launch isn't created! Call createLaunch first");
278
327
  }
328
+ const launchId = __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id;
279
329
  await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/error/bulk", {
280
330
  body: {
281
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
331
+ launchId,
282
332
  items: errors,
283
333
  },
284
334
  onUploadProgress(progressEvent) {
@@ -343,6 +393,7 @@ export class TestOpsClient {
343
393
  if (!__classPrivateFieldGet(this, _TestOpsClient_launch, "f")) {
344
394
  throw new Error("Launch isn't created! Call createLaunch first");
345
395
  }
396
+ const launchId = __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id;
346
397
  const items = results.map((result) => {
347
398
  const item = {
348
399
  name: result.rule,
@@ -354,9 +405,9 @@ export class TestOpsClient {
354
405
  }
355
406
  return item;
356
407
  });
357
- await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/quality-gate/bulk", {
408
+ await retryRequest(() => __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/launch/quality-gate/bulk", {
358
409
  body: {
359
- launchId: __classPrivateFieldGet(this, _TestOpsClient_launch, "f").id,
410
+ launchId,
360
411
  items,
361
412
  },
362
413
  onUploadProgress(progressEvent) {
@@ -364,7 +415,7 @@ export class TestOpsClient {
364
415
  const percent = total > 0 ? Math.min(100, Math.max(0, (progressEvent.loaded / total) * 100)) : 0;
365
416
  onProgress?.(percent, total);
366
417
  },
367
- });
418
+ }));
368
419
  }
369
420
  }
370
421
  _TestOpsClient_baseUrl = new WeakMap(), _TestOpsClient_logger = new WeakMap(), _TestOpsClient_accessToken = new WeakMap(), _TestOpsClient_projectId = new WeakMap(), _TestOpsClient_client = new WeakMap(), _TestOpsClient_launch = new WeakMap(), _TestOpsClient_session = new WeakMap(), _TestOpsClient_uploadInProgress = new WeakMap(), _TestOpsClient_uploadLimit = new WeakMap(), _TestOpsClient_namedEnvsIdsByEnv = new WeakMap(), _TestOpsClient_instances = new WeakSet(), _TestOpsClient_postTestResultsChunk = async function _TestOpsClient_postTestResultsChunk(trsChunk) {
@@ -387,10 +438,10 @@ _TestOpsClient_baseUrl = new WeakMap(), _TestOpsClient_logger = new WeakMap(), _
387
438
  return extendedTestResult;
388
439
  });
389
440
  const body = toUploadResultsDto(__classPrivateFieldGet(this, _TestOpsClient_session, "f").id, extendedChunk);
390
- const data = await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/test-result", {
441
+ const data = await retryRequest(() => __classPrivateFieldGet(this, _TestOpsClient_client, "f").post("/api/upload/test-result", {
391
442
  body,
392
443
  headers: { "Content-Type": "application/json" },
393
- });
444
+ }));
394
445
  const reportIdsToTestOpsIds = {};
395
446
  for (const { id, uuid } of data.results ?? []) {
396
447
  if (typeof uuid === "string" && typeof id === "number") {
@@ -451,7 +502,7 @@ _TestOpsClient_baseUrl = new WeakMap(), _TestOpsClient_logger = new WeakMap(), _
451
502
  if (fixtures.length === 0)
452
503
  return;
453
504
  const body = toUploadFixturesResultsDto(fixtures);
454
- await __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/test-fixture-result`, {
505
+ await retryRequest(() => __classPrivateFieldGet(this, _TestOpsClient_client, "f").post(`/api/upload/test-result/${testOpsResultId}/test-fixture-result`, {
455
506
  body,
456
- });
507
+ }));
457
508
  };
package/dist/logger.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ type LogLevel = "silent" | "verbose" | "debug" | "info" | "warn" | "error";
1
2
  type JSONMessage = Record<string, unknown> | Array<unknown>;
2
3
  export declare class Logger {
3
4
  #private;
4
5
  private readonly loggerName;
5
- constructor(loggerName: string);
6
+ constructor(loggerName: string, logLevel?: LogLevel);
7
+ setLogLevel(logLevel: LogLevel): void;
6
8
  verbose(message: string | JSONMessage): void;
7
9
  debug(message: string | JSONMessage): void;
8
10
  newLine(): void;
package/dist/logger.js CHANGED
@@ -35,13 +35,17 @@ function getLogLevelFromEnv() {
35
35
  return "info";
36
36
  }
37
37
  export class Logger {
38
- constructor(loggerName) {
38
+ constructor(loggerName, logLevel) {
39
39
  _Logger_instances.add(this);
40
40
  this.loggerName = loggerName;
41
- _Logger_level.set(this, getLogLevelFromEnv());
41
+ _Logger_level.set(this, void 0);
42
42
  _Logger_prefix.set(this, void 0);
43
+ __classPrivateFieldSet(this, _Logger_level, logLevel ?? getLogLevelFromEnv(), "f");
43
44
  __classPrivateFieldSet(this, _Logger_prefix, cyan(bold(`[${this.loggerName}]:`)), "f");
44
45
  }
46
+ setLogLevel(logLevel) {
47
+ __classPrivateFieldSet(this, _Logger_level, logLevel, "f");
48
+ }
45
49
  verbose(message) {
46
50
  if (!__classPrivateFieldGet(this, _Logger_instances, "m", _Logger_isLogLevel).call(this, "verbose")) {
47
51
  return;
package/dist/plugin.js CHANGED
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client, _TestOpsPlugin_launchName, _TestOpsPlugin_launchTags, _TestOpsPlugin_uploadedTestResultsIds, _TestOpsPlugin_autocloseLaunch, _TestOpsPlugin_launchStarted, _TestOpsPlugin_gitFlow, _TestOpsPlugin_enabledByConfig, _TestOpsPlugin_uploadQualityGateResults, _TestOpsPlugin_uploadGlobalErrors, _TestOpsPlugin_uploadGlobalAttachments, _TestOpsPlugin_uploadTestResults, _TestOpsPlugin_upload, _TestOpsPlugin_trsToUpload, _TestOpsPlugin_enrichWithCategories, _TestOpsPlugin_syncLaunchCategories, _TestOpsPlugin_collectCategoryNamesByExternalId, _TestOpsPlugin_assignCreatedCategoryIds, _TestOpsPlugin_startUpload, _TestOpsPlugin_stopUpload;
12
+ var _TestOpsPlugin_instances, _TestOpsPlugin_logger, _TestOpsPlugin_ci, _TestOpsPlugin_client, _TestOpsPlugin_launchName, _TestOpsPlugin_launchTags, _TestOpsPlugin_uploadedTestResultsIds, _TestOpsPlugin_uploadedGlobalAttachmentIds, _TestOpsPlugin_uploadedGlobalErrors, _TestOpsPlugin_autocloseLaunch, _TestOpsPlugin_launchStarted, _TestOpsPlugin_gitFlow, _TestOpsPlugin_enabledByConfig, _TestOpsPlugin_uploadQualityGateResults, _TestOpsPlugin_uploadGlobalErrors, _TestOpsPlugin_uploadGlobalAttachments, _TestOpsPlugin_uploadTestResults, _TestOpsPlugin_upload, _TestOpsPlugin_trsToUpload, _TestOpsPlugin_enrichWithCategories, _TestOpsPlugin_syncLaunchCategories, _TestOpsPlugin_collectCategoryNamesByExternalId, _TestOpsPlugin_assignCreatedCategoryIds, _TestOpsPlugin_startUpload, _TestOpsPlugin_stopUpload;
13
13
  import { env } from "node:process";
14
14
  import { detect, isLocalCiDescriptor } from "@allurereport/ci";
15
15
  import { createProgressLogger } from "@allurereport/cli-commons";
@@ -38,6 +38,8 @@ export class TestOpsPlugin {
38
38
  _TestOpsPlugin_launchName.set(this, "");
39
39
  _TestOpsPlugin_launchTags.set(this, []);
40
40
  _TestOpsPlugin_uploadedTestResultsIds.set(this, new Set());
41
+ _TestOpsPlugin_uploadedGlobalAttachmentIds.set(this, new Set());
42
+ _TestOpsPlugin_uploadedGlobalErrors.set(this, new Set());
41
43
  _TestOpsPlugin_autocloseLaunch.set(this, false);
42
44
  _TestOpsPlugin_launchStarted.set(this, false);
43
45
  _TestOpsPlugin_gitFlow.set(this, void 0);
@@ -106,6 +108,9 @@ export class TestOpsPlugin {
106
108
  if (!this.enabled) {
107
109
  return;
108
110
  }
111
+ if (context.realTime) {
112
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").setLogLevel("info");
113
+ }
109
114
  __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("Starting upload…");
110
115
  if (!(await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_startUpload).call(this))) {
111
116
  return;
@@ -209,7 +214,7 @@ export class TestOpsPlugin {
209
214
  return summary;
210
215
  }
211
216
  }
212
- _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = new WeakMap(), _TestOpsPlugin_launchName = new WeakMap(), _TestOpsPlugin_launchTags = new WeakMap(), _TestOpsPlugin_uploadedTestResultsIds = new WeakMap(), _TestOpsPlugin_autocloseLaunch = new WeakMap(), _TestOpsPlugin_launchStarted = new WeakMap(), _TestOpsPlugin_gitFlow = new WeakMap(), _TestOpsPlugin_enabledByConfig = new WeakMap(), _TestOpsPlugin_instances = new WeakSet(), _TestOpsPlugin_uploadQualityGateResults = async function _TestOpsPlugin_uploadQualityGateResults(store) {
217
+ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestOpsPlugin_client = new WeakMap(), _TestOpsPlugin_launchName = new WeakMap(), _TestOpsPlugin_launchTags = new WeakMap(), _TestOpsPlugin_uploadedTestResultsIds = new WeakMap(), _TestOpsPlugin_uploadedGlobalAttachmentIds = new WeakMap(), _TestOpsPlugin_uploadedGlobalErrors = new WeakMap(), _TestOpsPlugin_autocloseLaunch = new WeakMap(), _TestOpsPlugin_launchStarted = new WeakMap(), _TestOpsPlugin_gitFlow = new WeakMap(), _TestOpsPlugin_enabledByConfig = new WeakMap(), _TestOpsPlugin_instances = new WeakSet(), _TestOpsPlugin_uploadQualityGateResults = async function _TestOpsPlugin_uploadQualityGateResults(store) {
213
218
  const results = await store.qualityGateResults();
214
219
  const uniqueResults = uniqBy(results.filter(({ success }) => !success), ({ rule, environment }) => `${rule}-${environment}`);
215
220
  if (uniqueResults.length === 0) {
@@ -251,10 +256,9 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
251
256
  finally {
252
257
  progressLogger.cancel?.();
253
258
  }
254
- }, _TestOpsPlugin_uploadGlobalErrors = async function _TestOpsPlugin_uploadGlobalErrors(store) {
255
- const results = await store.allGlobalErrors();
259
+ }, _TestOpsPlugin_uploadGlobalErrors = async function _TestOpsPlugin_uploadGlobalErrors(results) {
256
260
  if (results.length === 0) {
257
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("No global errors to upload");
261
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("No new global errors to upload");
258
262
  return;
259
263
  }
260
264
  const progressLogger = createProgressLogger({
@@ -275,6 +279,9 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
275
279
  if (!completed) {
276
280
  progressLogger.increment();
277
281
  }
282
+ results.forEach((error) => {
283
+ __classPrivateFieldGet(this, _TestOpsPlugin_uploadedGlobalErrors, "f").add(error);
284
+ });
278
285
  progressLogger.log(true);
279
286
  }
280
287
  catch (error) {
@@ -292,10 +299,9 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
292
299
  finally {
293
300
  progressLogger.cancel?.();
294
301
  }
295
- }, _TestOpsPlugin_uploadGlobalAttachments = async function _TestOpsPlugin_uploadGlobalAttachments(store) {
296
- const attachments = await store.allGlobalAttachments();
302
+ }, _TestOpsPlugin_uploadGlobalAttachments = async function _TestOpsPlugin_uploadGlobalAttachments(store, attachments) {
297
303
  if (attachments.length === 0) {
298
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").debug("No global attachments to upload");
304
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").debug("No new global attachments to upload");
299
305
  return;
300
306
  }
301
307
  const progressLogger = createProgressLogger({
@@ -332,6 +338,9 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
332
338
  if (!completed) {
333
339
  progressLogger.increment();
334
340
  }
341
+ attachments.forEach((attachment) => {
342
+ __classPrivateFieldGet(this, _TestOpsPlugin_uploadedGlobalAttachmentIds, "f").add(attachment.id);
343
+ });
335
344
  progressLogger.log(true);
336
345
  }
337
346
  catch (error) {
@@ -349,36 +358,35 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
349
358
  finally {
350
359
  progressLogger.cancel?.();
351
360
  }
352
- }, _TestOpsPlugin_uploadTestResults = async function _TestOpsPlugin_uploadTestResults(store, trsToUpload, environments) {
361
+ }, _TestOpsPlugin_uploadTestResults = async function _TestOpsPlugin_uploadTestResults(store, trsToUpload, environments, options) {
353
362
  const totalCount = trsToUpload.length;
354
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Preparing to upload ${bold(totalCount.toString())} ${totalCount > 1 ? "test results" : "test result"}`);
363
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose(`Preparing to upload ${bold(totalCount.toString())} ${totalCount > 1 ? "test results" : "test result"}`);
355
364
  const progressLogger = createProgressLogger({
356
365
  total: totalCount,
357
366
  message: "Uploading test results",
358
367
  unitLabel: totalCount === 1 ? "test result uploaded" : "test results uploaded",
359
368
  prefix: "[TestOpsPlugin]",
369
+ silent: !!options?.silent,
360
370
  });
361
- const logProgress = progressLogger.log;
362
- const incrementProgress = progressLogger.increment;
363
371
  try {
364
- logProgress(true);
372
+ progressLogger.log(true);
365
373
  const uploadedTrs = await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").uploadTestResults({
366
374
  attachmentsResolver: attachmentsResolverFactory(store),
367
375
  fixturesResolver: fixturesResolverFactory(store),
368
376
  environments,
369
377
  trs: trsToUpload,
370
- onProgress: () => incrementProgress(),
378
+ onProgress: () => progressLogger.increment(),
371
379
  });
372
- logProgress(true);
380
+ progressLogger.log(true);
373
381
  uploadedTrs.forEach((tr) => {
374
382
  __classPrivateFieldGet(this, _TestOpsPlugin_uploadedTestResultsIds, "f").add(tr.id);
375
383
  });
376
384
  const uploadedCount = uploadedTrs.length;
377
385
  if (uploadedCount === 0) {
378
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").warn("No test results were uploaded");
386
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("No test results were uploaded");
379
387
  return;
380
388
  }
381
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info(`Uploaded ${uploadedCount} ${uploadedCount > 1 ? "test results" : "test result"}`);
389
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose(`Uploaded ${uploadedCount} ${uploadedCount > 1 ? "test results" : "test result"}`);
382
390
  }
383
391
  finally {
384
392
  progressLogger.cancel?.();
@@ -386,14 +394,30 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
386
394
  }, _TestOpsPlugin_upload = async function _TestOpsPlugin_upload(store, options = {}) {
387
395
  const { context, stage } = options;
388
396
  const trsToUpload = await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_trsToUpload).call(this, store);
397
+ const shouldUploadGlobalArtifacts = stage === "done" || !context?.realTime;
398
+ let globalErrors = [];
399
+ let globalAttachments = [];
400
+ if (shouldUploadGlobalArtifacts) {
401
+ const [allGlobalErrors, allGlobalAttachments] = await Promise.all([
402
+ store.allGlobalErrors(),
403
+ store.allGlobalAttachments(),
404
+ ]);
405
+ globalErrors = allGlobalErrors.filter((error) => !__classPrivateFieldGet(this, _TestOpsPlugin_uploadedGlobalErrors, "f").has(error));
406
+ globalAttachments = allGlobalAttachments.filter((attachment) => !__classPrivateFieldGet(this, _TestOpsPlugin_uploadedGlobalAttachmentIds, "f").has(attachment.id));
407
+ }
389
408
  if (trsToUpload.length === 0) {
390
409
  if (stage == "update") {
391
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info("No new test results to upload");
410
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("No new test results to upload");
392
411
  }
393
412
  if (stage === "done") {
394
- __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").info("No test results to upload");
413
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose("No test results to upload");
414
+ }
415
+ if (globalErrors.length === 0 && globalAttachments.length === 0) {
416
+ return;
395
417
  }
396
- return;
418
+ }
419
+ if (stage === "update" && trsToUpload.length > 0) {
420
+ __classPrivateFieldGet(this, _TestOpsPlugin_logger, "f").verbose(`Found ${bold(trsToUpload.length.toString())} new test ${trsToUpload.length > 1 ? "results" : "result"}, uploading…`);
397
421
  }
398
422
  try {
399
423
  await __classPrivateFieldGet(this, _TestOpsPlugin_client, "f").createSession(env);
@@ -411,14 +435,19 @@ _TestOpsPlugin_logger = new WeakMap(), _TestOpsPlugin_ci = new WeakMap(), _TestO
411
435
  }
412
436
  return;
413
437
  }
414
- await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalAttachments).call(this, store);
415
- await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalErrors).call(this, store);
438
+ await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalAttachments).call(this, store, globalAttachments);
439
+ await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadGlobalErrors).call(this, globalErrors);
440
+ if (trsToUpload.length === 0) {
441
+ return;
442
+ }
416
443
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadQualityGateResults).call(this, store);
417
444
  const environments = await store.allEnvironmentIdentities();
418
445
  const contextCategories = context?.categories ?? [];
419
446
  const trsEnrichedWithCategories = await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_enrichWithCategories).call(this, store, trsToUpload, contextCategories);
420
447
  await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_syncLaunchCategories).call(this, trsEnrichedWithCategories, contextCategories);
421
- await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadTestResults).call(this, store, trsEnrichedWithCategories, environments);
448
+ await __classPrivateFieldGet(this, _TestOpsPlugin_instances, "m", _TestOpsPlugin_uploadTestResults).call(this, store, trsEnrichedWithCategories, environments, {
449
+ silent: !!context?.realTime,
450
+ });
422
451
  }, _TestOpsPlugin_trsToUpload = async function _TestOpsPlugin_trsToUpload(store) {
423
452
  const filter = this.options.filter ?? stubTrue;
424
453
  const filteredTrs = await store.allTestResults({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-testops",
3
- "version": "3.15.0",
3
+ "version": "3.16.0",
4
4
  "description": "Allure Plugin TestOps",
5
5
  "keywords": [
6
6
  "allure",
@@ -32,13 +32,13 @@
32
32
  "lint:fix": "oxlint --import-plugin --fix src test features stories"
33
33
  },
34
34
  "dependencies": {
35
- "@allurereport/ci": "3.15.0",
36
- "@allurereport/cli-commons": "3.15.0",
37
- "@allurereport/core-api": "3.15.0",
38
- "@allurereport/git": "3.15.0",
39
- "@allurereport/plugin-api": "3.15.0",
40
- "@allurereport/reader-api": "3.15.0",
41
- "@allurereport/service": "3.15.0",
35
+ "@allurereport/ci": "3.16.0",
36
+ "@allurereport/cli-commons": "3.16.0",
37
+ "@allurereport/core-api": "3.16.0",
38
+ "@allurereport/git": "3.16.0",
39
+ "@allurereport/plugin-api": "3.16.0",
40
+ "@allurereport/reader-api": "3.16.0",
41
+ "@allurereport/service": "3.16.0",
42
42
  "axios": "^1.18.1",
43
43
  "form-data": "^4.0.6",
44
44
  "lodash-es": "^4.18.1",