@allurereport/core 3.8.0 → 3.8.2
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/report.js +220 -154
- package/dist/store/store.js +6 -4
- package/package.json +20 -20
package/dist/report.js
CHANGED
|
@@ -22,7 +22,7 @@ import { normalizeCategoriesConfig } from "@allurereport/core-api";
|
|
|
22
22
|
import { AllureStoreDumpFiles, } from "@allurereport/plugin-api";
|
|
23
23
|
import { allure1, allure2, attachments, cucumberjson, junitXml, readXcResultBundle } from "@allurereport/reader";
|
|
24
24
|
import { PathResultFile } from "@allurereport/reader-api";
|
|
25
|
-
import {
|
|
25
|
+
import { AllureRemoteHistory, AllureServiceClient, KnownError, UnknownError, } from "@allurereport/service";
|
|
26
26
|
import { generateSummary } from "@allurereport/summary";
|
|
27
27
|
import { glob } from "glob";
|
|
28
28
|
import ZipReadStream from "node-stream-zip";
|
|
@@ -44,6 +44,11 @@ const remoteReportParams = (ci) => {
|
|
|
44
44
|
const branch = ci?.jobRunBranch;
|
|
45
45
|
return repo && branch ? { repo, branch } : {};
|
|
46
46
|
};
|
|
47
|
+
const REMOTE_UPLOAD_CONCURRENCY = 50;
|
|
48
|
+
const REMOTE_UPLOAD_MAX_ATTEMPTS = 5;
|
|
49
|
+
const REMOTE_UPLOAD_MAX_SIMULTANEOUS_FAILED = 5;
|
|
50
|
+
const errorDetails = (err) => (err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
51
|
+
const isAbortError = (err) => typeof err === "object" && err !== null && "name" in err && err?.name === "AbortError";
|
|
47
52
|
export class AllureReport {
|
|
48
53
|
constructor(opts) {
|
|
49
54
|
_AllureReport_instances.add(this);
|
|
@@ -300,125 +305,152 @@ export class AllureReport {
|
|
|
300
305
|
this.restoreState = async (dumps) => {
|
|
301
306
|
for (const dump of dumps) {
|
|
302
307
|
if (!existsSync(dump)) {
|
|
308
|
+
console.error(`Failed to restore state from "${dump}", continuing without it`);
|
|
309
|
+
console.error("Dump file does not exist");
|
|
303
310
|
continue;
|
|
304
311
|
}
|
|
305
|
-
const dumpArchive = new ZipReadStream.async({
|
|
306
|
-
file: dump,
|
|
307
|
-
});
|
|
308
312
|
try {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
const dumpArchive = new ZipReadStream.async({
|
|
314
|
+
file: dump,
|
|
315
|
+
});
|
|
316
|
+
let restoreError;
|
|
317
|
+
try {
|
|
318
|
+
const dumpEntries = await dumpArchive.entries();
|
|
319
|
+
const dumpEntriesList = Object.entries(dumpEntries);
|
|
320
|
+
const requiredEntryData = async (entryName) => {
|
|
321
|
+
if (!dumpEntries[entryName]) {
|
|
322
|
+
throw new Error(`Missing required dump entry "${entryName}"`);
|
|
323
|
+
}
|
|
324
|
+
return dumpArchive.entryData(entryName);
|
|
325
|
+
};
|
|
326
|
+
const optionalEntryData = async (entryName) => dumpEntries[entryName] ? dumpArchive.entryData(entryName) : undefined;
|
|
327
|
+
if (!dumpEntries[AllureStoreDumpFiles.TestResults]) {
|
|
328
|
+
const nestedDumpEntries = dumpEntriesList.filter(([entryName, entry]) => !entry.isDirectory &&
|
|
329
|
+
!entryName.startsWith("__MACOSX/") &&
|
|
330
|
+
!basename(entryName).startsWith("._") &&
|
|
331
|
+
entryName.toLowerCase().endsWith(".zip"));
|
|
332
|
+
if (nestedDumpEntries.length > 0) {
|
|
333
|
+
const nestedDumpsTempDir = await mkdtemp(join(tmpdir(), `${basename(dump, ".zip")}-nested-`));
|
|
334
|
+
const nestedDumpPaths = [];
|
|
335
|
+
__classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(nestedDumpsTempDir);
|
|
336
|
+
for (const [entryName] of nestedDumpEntries) {
|
|
337
|
+
const nestedDumpPath = join(nestedDumpsTempDir, `${nestedDumpPaths.length}-${basename(entryName)}`);
|
|
338
|
+
await writeFile(nestedDumpPath, await dumpArchive.entryData(entryName));
|
|
339
|
+
nestedDumpPaths.push(nestedDumpPath);
|
|
340
|
+
}
|
|
341
|
+
await this.restoreState(nestedDumpPaths);
|
|
342
|
+
continue;
|
|
325
343
|
}
|
|
326
|
-
await this.restoreState(nestedDumpPaths);
|
|
327
|
-
continue;
|
|
328
344
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
case AllureStoreDumpFiles.QualityGateResults:
|
|
367
|
-
return acc;
|
|
368
|
-
default:
|
|
369
|
-
if (entry.isDirectory || !attachmentsLinks[entryName] || attachmentsLinks[entryName].missed) {
|
|
345
|
+
const testResultsEntry = await requiredEntryData(AllureStoreDumpFiles.TestResults);
|
|
346
|
+
const testCasesEntry = await requiredEntryData(AllureStoreDumpFiles.TestCases);
|
|
347
|
+
const fixturesEntry = await requiredEntryData(AllureStoreDumpFiles.Fixtures);
|
|
348
|
+
const attachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Attachments);
|
|
349
|
+
const checkResultsEntry = await optionalEntryData(AllureStoreDumpFiles.CheckResults);
|
|
350
|
+
const environmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Environments);
|
|
351
|
+
const reportVariablesEntry = await requiredEntryData(AllureStoreDumpFiles.ReportVariables);
|
|
352
|
+
const globalAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalAttachments);
|
|
353
|
+
const globalErrorsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalErrors);
|
|
354
|
+
const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
|
|
355
|
+
const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
|
|
356
|
+
const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
|
|
357
|
+
const indexLatestEnvTestResultsByHistoryIdEntry = await requiredEntryData(AllureStoreDumpFiles.IndexLatestEnvTestResultsByHistoryId);
|
|
358
|
+
const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
|
|
359
|
+
const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
|
|
360
|
+
const indexKnownByHistoryIdEntry = await requiredEntryData(AllureStoreDumpFiles.IndexKnownByHistoryId);
|
|
361
|
+
const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
|
|
362
|
+
const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
|
|
363
|
+
const attachmentsEntries = dumpEntriesList.reduce((acc, [entryName, entry]) => {
|
|
364
|
+
switch (entryName) {
|
|
365
|
+
case AllureStoreDumpFiles.Attachments:
|
|
366
|
+
case AllureStoreDumpFiles.CheckResults:
|
|
367
|
+
case AllureStoreDumpFiles.TestResults:
|
|
368
|
+
case AllureStoreDumpFiles.TestCases:
|
|
369
|
+
case AllureStoreDumpFiles.Fixtures:
|
|
370
|
+
case AllureStoreDumpFiles.Environments:
|
|
371
|
+
case AllureStoreDumpFiles.ReportVariables:
|
|
372
|
+
case AllureStoreDumpFiles.GlobalAttachments:
|
|
373
|
+
case AllureStoreDumpFiles.GlobalErrors:
|
|
374
|
+
case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
|
|
375
|
+
case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
|
|
376
|
+
case AllureStoreDumpFiles.IndexTestResultsByTestCase:
|
|
377
|
+
case AllureStoreDumpFiles.IndexLatestEnvTestResultsByHistoryId:
|
|
378
|
+
case AllureStoreDumpFiles.IndexAttachmentsByFixture:
|
|
379
|
+
case AllureStoreDumpFiles.IndexFixturesByTestResult:
|
|
380
|
+
case AllureStoreDumpFiles.IndexKnownByHistoryId:
|
|
381
|
+
case AllureStoreDumpFiles.QualityGateResults:
|
|
370
382
|
return acc;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
383
|
+
default:
|
|
384
|
+
if (entry.isDirectory || !attachmentsLinks[entryName] || attachmentsLinks[entryName].missed) {
|
|
385
|
+
return acc;
|
|
386
|
+
}
|
|
387
|
+
return Object.assign(acc, {
|
|
388
|
+
[entryName]: entry,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}, {});
|
|
392
|
+
const dumpState = {
|
|
393
|
+
testResults: JSON.parse(testResultsEntry.toString("utf8")),
|
|
394
|
+
testCases: JSON.parse(testCasesEntry.toString("utf8")),
|
|
395
|
+
fixtures: JSON.parse(fixturesEntry.toString("utf8")),
|
|
396
|
+
attachments: attachmentsLinks,
|
|
397
|
+
checkResults: checkResultsEntry ? JSON.parse(checkResultsEntry.toString("utf8")) : [],
|
|
398
|
+
environments: JSON.parse(environmentsEntry.toString("utf8")),
|
|
399
|
+
reportVariables: JSON.parse(reportVariablesEntry.toString("utf8")),
|
|
400
|
+
globalAttachmentIds: JSON.parse(globalAttachmentsEntry.toString("utf8")),
|
|
401
|
+
globalErrors: JSON.parse(globalErrorsEntry.toString("utf8")),
|
|
402
|
+
indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
|
|
403
|
+
indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
|
|
404
|
+
indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
|
|
405
|
+
indexLatestEnvTestResultByHistoryId: JSON.parse(indexLatestEnvTestResultsByHistoryIdEntry.toString("utf8")),
|
|
406
|
+
indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
|
|
407
|
+
indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
|
|
408
|
+
indexKnownByHistoryId: JSON.parse(indexKnownByHistoryIdEntry.toString("utf8")),
|
|
409
|
+
qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
|
|
410
|
+
};
|
|
411
|
+
const dumpTempDir = await mkdtemp(join(tmpdir(), basename(dump, ".zip")));
|
|
412
|
+
const resultsAttachments = {};
|
|
413
|
+
__classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(dumpTempDir);
|
|
414
|
+
try {
|
|
415
|
+
for (const [attachmentId] of Object.entries(attachmentsEntries)) {
|
|
416
|
+
const attachmentContentEntry = await dumpArchive.entryData(attachmentId);
|
|
417
|
+
const attachmentFilePath = resolveDumpAttachmentPath(dumpTempDir, attachmentId);
|
|
418
|
+
await writeFile(attachmentFilePath, attachmentContentEntry);
|
|
419
|
+
resultsAttachments[attachmentId] = new PathResultFile(attachmentFilePath, attachmentId);
|
|
420
|
+
}
|
|
375
421
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
globalAttachmentIds: JSON.parse(globalAttachmentsEntry.toString("utf8")),
|
|
386
|
-
globalErrors: JSON.parse(globalErrorsEntry.toString("utf8")),
|
|
387
|
-
indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
|
|
388
|
-
indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
|
|
389
|
-
indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
|
|
390
|
-
indexLatestEnvTestResultByHistoryId: JSON.parse(indexLatestEnvTestResultsByHistoryIdEntry.toString("utf8")),
|
|
391
|
-
indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
|
|
392
|
-
indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
|
|
393
|
-
indexKnownByHistoryId: JSON.parse(indexKnownByHistoryIdEntry.toString("utf8")),
|
|
394
|
-
qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
|
|
395
|
-
};
|
|
396
|
-
const dumpTempDir = await mkdtemp(join(tmpdir(), basename(dump, ".zip")));
|
|
397
|
-
const resultsAttachments = {};
|
|
398
|
-
__classPrivateFieldGet(this, _AllureReport_dumpTempDirs, "f").push(dumpTempDir);
|
|
399
|
-
try {
|
|
400
|
-
for (const [attachmentId] of Object.entries(attachmentsEntries)) {
|
|
401
|
-
const attachmentContentEntry = await dumpArchive.entryData(attachmentId);
|
|
402
|
-
const attachmentFilePath = resolveDumpAttachmentPath(dumpTempDir, attachmentId);
|
|
403
|
-
await writeFile(attachmentFilePath, attachmentContentEntry);
|
|
404
|
-
resultsAttachments[attachmentId] = new PathResultFile(attachmentFilePath, attachmentId);
|
|
422
|
+
catch (err) {
|
|
423
|
+
if (err instanceof UnsafeDumpPathError) {
|
|
424
|
+
console.error(`Cannot restore dump from "${dump}": the archive lists attachment paths that would write outside the extract directory (unsafe zip paths such as "../" or absolute names).`);
|
|
425
|
+
console.error(err.message);
|
|
426
|
+
console.error("Only use dump archives produced by this tool; do not load untrusted or third-party --dump zip files.");
|
|
427
|
+
throw err;
|
|
428
|
+
}
|
|
429
|
+
console.error(`Can't restore attachment contents from "${dump}", continuing without them`);
|
|
430
|
+
console.error(errorDetails(err));
|
|
405
431
|
}
|
|
432
|
+
await __classPrivateFieldGet(this, _AllureReport_store, "f").restoreState(dumpState, resultsAttachments);
|
|
433
|
+
console.info(`Successfully restored state from "${dump}"`);
|
|
406
434
|
}
|
|
407
435
|
catch (err) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
436
|
+
restoreError = err;
|
|
437
|
+
throw err;
|
|
438
|
+
}
|
|
439
|
+
finally {
|
|
440
|
+
try {
|
|
441
|
+
await dumpArchive.close();
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
if (!restoreError) {
|
|
445
|
+
console.error(`Failed to close dump archive "${dump}"`);
|
|
446
|
+
console.error(errorDetails(err));
|
|
447
|
+
}
|
|
413
448
|
}
|
|
414
|
-
console.error(`Can't restore state from "${dump}", continuing without it`);
|
|
415
|
-
console.error(err);
|
|
416
449
|
}
|
|
417
|
-
await __classPrivateFieldGet(this, _AllureReport_store, "f").restoreState(dumpState, resultsAttachments);
|
|
418
|
-
console.info(`Successfully restored state from "${dump}"`);
|
|
419
450
|
}
|
|
420
|
-
|
|
421
|
-
|
|
451
|
+
catch (err) {
|
|
452
|
+
console.error(`Failed to restore state from "${dump}", continuing without it`);
|
|
453
|
+
console.error(errorDetails(err));
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
456
|
};
|
|
@@ -427,6 +459,8 @@ export class AllureReport {
|
|
|
427
459
|
const remoteHrefs = new Set();
|
|
428
460
|
const remoteHrefsByPluginId = {};
|
|
429
461
|
const cancelledPluginsIds = new Set();
|
|
462
|
+
let remoteCleanupFailed = false;
|
|
463
|
+
const getSuccessfulPublishedPlugins = () => __classPrivateFieldGet(this, _AllureReport_plugins, "f").filter(({ enabled, id, options }) => enabled && !!options?.publish && !cancelledPluginsIds.has(id));
|
|
430
464
|
if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
|
|
431
465
|
throw new Error(initRequired);
|
|
432
466
|
}
|
|
@@ -458,59 +492,97 @@ export class AllureReport {
|
|
|
458
492
|
width: 20,
|
|
459
493
|
})
|
|
460
494
|
: undefined;
|
|
461
|
-
const limitFn = pLimit(
|
|
495
|
+
const limitFn = pLimit(REMOTE_UPLOAD_CONCURRENCY);
|
|
462
496
|
const uploadAbortController = new AbortController();
|
|
463
|
-
const
|
|
464
|
-
|
|
497
|
+
const failedUploads = new Set();
|
|
498
|
+
let terminalUploadError;
|
|
499
|
+
let remoteReportDeleted = false;
|
|
500
|
+
let fns = [];
|
|
501
|
+
const cleanupFailedPluginUpload = async (err) => {
|
|
502
|
+
if (remoteReportDeleted) {
|
|
465
503
|
return;
|
|
466
504
|
}
|
|
467
|
-
|
|
468
|
-
|
|
505
|
+
remoteReportDeleted = true;
|
|
506
|
+
cancelledPluginsIds.add(context.id);
|
|
507
|
+
uploadAbortController.abort();
|
|
508
|
+
await Promise.allSettled(fns);
|
|
509
|
+
const pluginRemoteHref = remoteHrefsByPluginId[context.id];
|
|
510
|
+
if (pluginRemoteHref) {
|
|
511
|
+
remoteHrefs.delete(pluginRemoteHref);
|
|
512
|
+
delete remoteHrefsByPluginId[context.id];
|
|
513
|
+
}
|
|
514
|
+
try {
|
|
515
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").deleteReport({
|
|
469
516
|
reportUuid: this.reportUuid,
|
|
470
517
|
pluginId: context.id,
|
|
471
|
-
filename,
|
|
472
|
-
filepath,
|
|
473
|
-
signal: uploadAbortController.signal,
|
|
474
518
|
});
|
|
475
|
-
if (cancelledPluginsIds.has(context.id) || uploadAbortController.signal.aborted) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
if (filename === "index.html") {
|
|
479
|
-
remoteHrefsByPluginId[context.id] = uploadedFileUrl;
|
|
480
|
-
remoteHrefs.add(uploadedFileUrl);
|
|
481
|
-
}
|
|
482
519
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
signal: uploadAbortController.signal,
|
|
488
|
-
});
|
|
520
|
+
catch (cleanupErr) {
|
|
521
|
+
remoteCleanupFailed = true;
|
|
522
|
+
console.error(`Plugin "${context.id}" upload cleanup has failed, the remote report won't be completed`);
|
|
523
|
+
console.error(cleanupErr);
|
|
489
524
|
}
|
|
525
|
+
console.error(`Plugin "${context.id}" upload has failed, the plugin won't be published`);
|
|
526
|
+
console.error(err);
|
|
527
|
+
};
|
|
528
|
+
fns = pluginFilesEntries.map(([filename, filepath]) => limitFn(async () => {
|
|
490
529
|
if (cancelledPluginsIds.has(context.id) || uploadAbortController.signal.aborted) {
|
|
491
530
|
return;
|
|
492
531
|
}
|
|
493
|
-
|
|
532
|
+
for (let attempt = 1; attempt <= REMOTE_UPLOAD_MAX_ATTEMPTS; attempt++) {
|
|
533
|
+
if (cancelledPluginsIds.has(context.id) || uploadAbortController.signal.aborted) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
try {
|
|
537
|
+
if (/^(data|widgets|index\.html$|summary\.json$)/.test(filename)) {
|
|
538
|
+
const uploadedFileUrl = await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportFile({
|
|
539
|
+
reportUuid: this.reportUuid,
|
|
540
|
+
pluginId: context.id,
|
|
541
|
+
filename,
|
|
542
|
+
filepath,
|
|
543
|
+
signal: uploadAbortController.signal,
|
|
544
|
+
});
|
|
545
|
+
if (cancelledPluginsIds.has(context.id) || uploadAbortController.signal.aborted) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (filename === "index.html") {
|
|
549
|
+
remoteHrefsByPluginId[context.id] = uploadedFileUrl;
|
|
550
|
+
remoteHrefs.add(uploadedFileUrl);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportAsset({
|
|
555
|
+
filename,
|
|
556
|
+
filepath,
|
|
557
|
+
signal: uploadAbortController.signal,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
failedUploads.delete(filename);
|
|
561
|
+
progressBar?.tick?.();
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
if (cancelledPluginsIds.has(context.id) || uploadAbortController.signal.aborted) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (isAbortError(err)) {
|
|
569
|
+
throw err;
|
|
570
|
+
}
|
|
571
|
+
failedUploads.add(filename);
|
|
572
|
+
if (failedUploads.size > REMOTE_UPLOAD_MAX_SIMULTANEOUS_FAILED ||
|
|
573
|
+
attempt >= REMOTE_UPLOAD_MAX_ATTEMPTS) {
|
|
574
|
+
terminalUploadError ?? (terminalUploadError = err);
|
|
575
|
+
throw terminalUploadError;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
494
579
|
}));
|
|
495
580
|
progressBar?.render?.();
|
|
496
581
|
try {
|
|
497
582
|
await Promise.all(fns);
|
|
498
583
|
}
|
|
499
584
|
catch (err) {
|
|
500
|
-
|
|
501
|
-
uploadAbortController.abort();
|
|
502
|
-
await Promise.allSettled(fns);
|
|
503
|
-
const pluginRemoteHref = remoteHrefsByPluginId[context.id];
|
|
504
|
-
if (pluginRemoteHref) {
|
|
505
|
-
remoteHrefs.delete(pluginRemoteHref);
|
|
506
|
-
delete remoteHrefsByPluginId[context.id];
|
|
507
|
-
}
|
|
508
|
-
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").deleteReport({
|
|
509
|
-
reportUuid: this.reportUuid,
|
|
510
|
-
pluginId: context.id,
|
|
511
|
-
});
|
|
512
|
-
console.error(`Plugin "${context.id}" upload has failed, the plugin won't be published`);
|
|
513
|
-
console.error(err);
|
|
585
|
+
await cleanupFailedPluginUpload(terminalUploadError ?? err);
|
|
514
586
|
}
|
|
515
587
|
}
|
|
516
588
|
const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
@@ -535,9 +607,7 @@ export class AllureReport {
|
|
|
535
607
|
});
|
|
536
608
|
if (summaries.length > 1) {
|
|
537
609
|
const summaryPath = await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries);
|
|
538
|
-
const publishedReports =
|
|
539
|
-
.map((plugin) => !!plugin?.options?.publish && !cancelledPluginsIds.has(plugin.id))
|
|
540
|
-
.filter(Boolean);
|
|
610
|
+
const publishedReports = getSuccessfulPublishedPlugins();
|
|
541
611
|
if (__classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get) && summaryPath && publishedReports.length > 1) {
|
|
542
612
|
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")?.addReportFile({
|
|
543
613
|
reportUuid: this.reportUuid,
|
|
@@ -546,7 +616,8 @@ export class AllureReport {
|
|
|
546
616
|
});
|
|
547
617
|
}
|
|
548
618
|
}
|
|
549
|
-
|
|
619
|
+
const publishedReports = getSuccessfulPublishedPlugins();
|
|
620
|
+
if (__classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get) && !remoteCleanupFailed && publishedReports.length > 0) {
|
|
550
621
|
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")?.completeReport({
|
|
551
622
|
reportUuid: this.reportUuid,
|
|
552
623
|
historyPoint: historyDataPoint,
|
|
@@ -595,7 +666,7 @@ export class AllureReport {
|
|
|
595
666
|
}
|
|
596
667
|
}
|
|
597
668
|
}
|
|
598
|
-
if (remoteHrefs.size > 0) {
|
|
669
|
+
if (!remoteCleanupFailed && remoteHrefs.size > 0) {
|
|
599
670
|
console.info("Next reports have been published:");
|
|
600
671
|
remoteHrefs.forEach((href) => {
|
|
601
672
|
console.info(`- ${href}`);
|
|
@@ -659,12 +730,7 @@ export class AllureReport {
|
|
|
659
730
|
});
|
|
660
731
|
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], known, reportFiles, realTime, historyPath, historyLimit, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, dump, categories, allureService: allureServiceConfig, globalAttachments, } = opts;
|
|
661
732
|
if (allureServiceConfig?.accessToken) {
|
|
662
|
-
|
|
663
|
-
__classPrivateFieldSet(this, _AllureReport_allureServiceClient, new AllureLegacyServiceClient(allureServiceConfig), "f");
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
__classPrivateFieldSet(this, _AllureReport_allureServiceClient, new AllureServiceClient(allureServiceConfig), "f");
|
|
667
|
-
}
|
|
733
|
+
__classPrivateFieldSet(this, _AllureReport_allureServiceClient, new AllureServiceClient(allureServiceConfig), "f");
|
|
668
734
|
}
|
|
669
735
|
this.reportUuid = randomUUID();
|
|
670
736
|
__classPrivateFieldSet(this, _AllureReport_ci, detect(), "f");
|
package/dist/store/store.js
CHANGED
|
@@ -11,7 +11,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
11
11
|
};
|
|
12
12
|
var _DefaultAllureStore_instances, _DefaultAllureStore_testResults, _DefaultAllureStore_environmentDisplayNames, _DefaultAllureStore_environmentNameToId, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_known, _DefaultAllureStore_fixtures, _DefaultAllureStore_defaultLabels, _DefaultAllureStore_environment, _DefaultAllureStore_environmentsConfig, _DefaultAllureStore_reportVariables, _DefaultAllureStore_realtimeDispatcher, _DefaultAllureStore_realtimeSubscriber, _DefaultAllureStore_allowedEnvironmentIds, _DefaultAllureStore_globalAttachmentIds, _DefaultAllureStore_globalAttachmentIdsByEnv, _DefaultAllureStore_globalErrors, _DefaultAllureStore_globalErrorsByEnv, _DefaultAllureStore_globalExitCode, _DefaultAllureStore_checkResults, _DefaultAllureStore_qualityGateResults, _DefaultAllureStore_historyPoints, _DefaultAllureStore_environments, _DefaultAllureStore_mergeEnvironmentIdentity, _DefaultAllureStore_environmentIdForLookup, _DefaultAllureStore_addEnvironments, _DefaultAllureStore_environmentIdByName, _DefaultAllureStore_setTestResultEnvironmentId, _DefaultAllureStore_assertAllowedEnvironmentId, _DefaultAllureStore_assertAllowedStoredEnvironment, _DefaultAllureStore_environmentIdByTestResult, _DefaultAllureStore_resolveGlobalEnvironmentIdentity, _DefaultAllureStore_globalAttachmentId, _DefaultAllureStore_indexGlobalError, _DefaultAllureStore_addGlobalError, _DefaultAllureStore_indexGlobalAttachment, _DefaultAllureStore_addGlobalAttachment, _DefaultAllureStore_restoreAttachmentContent, _DefaultAllureStore_relinkRestoredAttachmentSteps;
|
|
13
13
|
import { extname } from "node:path";
|
|
14
|
-
import { DEFAULT_ENVIRONMENT, DEFAULT_ENVIRONMENT_IDENTITY, compareBy, createDictionary, getHistoryIdCandidates, getWorstStatus, nullsLast, ordinal, reverse, selectHistoryTestResults, validateEnvironmentId, validateEnvironmentName, } from "@allurereport/core-api";
|
|
14
|
+
import { DEFAULT_ENVIRONMENT, DEFAULT_ENVIRONMENT_IDENTITY, compareBy, createDictionary, getHistoryIdCandidates, getWorstStatus, nullsLast, normalizeHistoryDataPoint, ordinal, reverse, selectHistoryTestResults, validateEnvironmentId, validateEnvironmentName, } from "@allurereport/core-api";
|
|
15
15
|
import { md5, } from "@allurereport/plugin-api";
|
|
16
16
|
import { environmentIdentityById, normalizeEnvironmentDescriptorMap, resolveEnvironmentIdentity, resolveStoredEnvironmentIdentity, validateAllowedEnvironmentId, } from "../utils/environment.js";
|
|
17
17
|
import { isFlaky } from "../utils/flaky.js";
|
|
@@ -196,7 +196,9 @@ export class DefaultAllureStore {
|
|
|
196
196
|
if (!__classPrivateFieldGet(this, _DefaultAllureStore_history, "f")) {
|
|
197
197
|
return [];
|
|
198
198
|
}
|
|
199
|
-
__classPrivateFieldSet(this, _DefaultAllureStore_historyPoints, (await __classPrivateFieldGet(this, _DefaultAllureStore_history, "f").readHistory()) ?? []
|
|
199
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_historyPoints, ((await __classPrivateFieldGet(this, _DefaultAllureStore_history, "f").readHistory()) ?? [])
|
|
200
|
+
.filter((historyPoint) => typeof historyPoint === "object" && historyPoint !== null)
|
|
201
|
+
.map(normalizeHistoryDataPoint), "f");
|
|
200
202
|
__classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").sort(compareBy("timestamp", reverse(ordinal())));
|
|
201
203
|
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f");
|
|
202
204
|
}
|
|
@@ -488,7 +490,7 @@ export class DefaultAllureStore {
|
|
|
488
490
|
}
|
|
489
491
|
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").reduce((result, dp) => {
|
|
490
492
|
const filteredTestResults = [];
|
|
491
|
-
for (const tr of Object.values(dp.testResults)) {
|
|
493
|
+
for (const tr of Object.values(dp.testResults ?? {})) {
|
|
492
494
|
const storedEnvironmentKey = typeof tr.environment === "string" ? tr.environment : undefined;
|
|
493
495
|
const trEnvId = (storedEnvironmentKey ? __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByName).call(this, storedEnvironmentKey) : undefined) ??
|
|
494
496
|
resolveStoredEnvironmentIdentity({
|
|
@@ -526,7 +528,7 @@ export class DefaultAllureStore {
|
|
|
526
528
|
if (allHistoryDps.length === 0) {
|
|
527
529
|
return Array.from(__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").values());
|
|
528
530
|
}
|
|
529
|
-
const historicalIds = new Set(allHistoryDps.flatMap((dp) => Object.keys(dp.testResults)));
|
|
531
|
+
const historicalIds = new Set(allHistoryDps.flatMap((dp) => Object.keys(dp.testResults ?? {})));
|
|
530
532
|
const newTrs = [];
|
|
531
533
|
for (const [, tr] of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f")) {
|
|
532
534
|
if (tr.hidden) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.2",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -25,25 +25,25 @@
|
|
|
25
25
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@allurereport/ci": "3.8.
|
|
29
|
-
"@allurereport/core-api": "3.8.
|
|
30
|
-
"@allurereport/plugin-agent": "3.8.
|
|
31
|
-
"@allurereport/plugin-allure2": "3.8.
|
|
32
|
-
"@allurereport/plugin-api": "3.8.
|
|
33
|
-
"@allurereport/plugin-awesome": "3.8.
|
|
34
|
-
"@allurereport/plugin-classic": "3.8.
|
|
35
|
-
"@allurereport/plugin-csv": "3.8.
|
|
36
|
-
"@allurereport/plugin-dashboard": "3.8.
|
|
37
|
-
"@allurereport/plugin-jira": "3.8.
|
|
38
|
-
"@allurereport/plugin-log": "3.8.
|
|
39
|
-
"@allurereport/plugin-progress": "3.8.
|
|
40
|
-
"@allurereport/plugin-slack": "3.8.
|
|
41
|
-
"@allurereport/plugin-testops": "3.8.
|
|
42
|
-
"@allurereport/plugin-testplan": "3.8.
|
|
43
|
-
"@allurereport/reader": "3.8.
|
|
44
|
-
"@allurereport/reader-api": "3.8.
|
|
45
|
-
"@allurereport/service": "3.8.
|
|
46
|
-
"@allurereport/summary": "3.8.
|
|
28
|
+
"@allurereport/ci": "3.8.2",
|
|
29
|
+
"@allurereport/core-api": "3.8.2",
|
|
30
|
+
"@allurereport/plugin-agent": "3.8.2",
|
|
31
|
+
"@allurereport/plugin-allure2": "3.8.2",
|
|
32
|
+
"@allurereport/plugin-api": "3.8.2",
|
|
33
|
+
"@allurereport/plugin-awesome": "3.8.2",
|
|
34
|
+
"@allurereport/plugin-classic": "3.8.2",
|
|
35
|
+
"@allurereport/plugin-csv": "3.8.2",
|
|
36
|
+
"@allurereport/plugin-dashboard": "3.8.2",
|
|
37
|
+
"@allurereport/plugin-jira": "3.8.2",
|
|
38
|
+
"@allurereport/plugin-log": "3.8.2",
|
|
39
|
+
"@allurereport/plugin-progress": "3.8.2",
|
|
40
|
+
"@allurereport/plugin-slack": "3.8.2",
|
|
41
|
+
"@allurereport/plugin-testops": "3.8.2",
|
|
42
|
+
"@allurereport/plugin-testplan": "3.8.2",
|
|
43
|
+
"@allurereport/reader": "3.8.2",
|
|
44
|
+
"@allurereport/reader-api": "3.8.2",
|
|
45
|
+
"@allurereport/service": "3.8.2",
|
|
46
|
+
"@allurereport/summary": "3.8.2",
|
|
47
47
|
"glob": "^13.0.6",
|
|
48
48
|
"handlebars": "^4.7.9",
|
|
49
49
|
"node-stream-zip": "^1.15.0",
|