allure 3.14.3 → 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/README.md +34 -10
- package/dist/commands/agent-run.d.ts +1 -0
- package/dist/commands/agent-run.js +11 -6
- package/dist/commands/agent.d.ts +1 -0
- package/dist/commands/agent.js +19 -8
- package/dist/commands/allure2.js +10 -10
- package/dist/commands/awesome.js +10 -10
- package/dist/commands/check.js +1 -1
- package/dist/commands/classic.js +10 -10
- package/dist/commands/commons/generate.d.ts +1 -1
- package/dist/commands/commons/generate.js +7 -3
- package/dist/commands/commons/resultsDiscovery.d.ts +5 -0
- package/dist/commands/commons/resultsDiscovery.js +17 -0
- package/dist/commands/commons/run.d.ts +3 -0
- package/dist/commands/commons/run.js +60 -27
- package/dist/commands/csv.js +10 -10
- package/dist/commands/dashboard.js +9 -9
- package/dist/commands/generate.d.ts +1 -0
- package/dist/commands/generate.js +7 -3
- package/dist/commands/history.js +6 -4
- package/dist/commands/index.d.ts +0 -1
- package/dist/commands/index.js +0 -1
- package/dist/commands/jira/clear.js +1 -1
- package/dist/commands/log.js +9 -9
- package/dist/commands/open.js +9 -5
- package/dist/commands/qualityGate.js +7 -7
- package/dist/commands/results/pack.d.ts +1 -0
- package/dist/commands/results/pack.js +12 -14
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +24 -8
- package/dist/commands/slack.js +9 -9
- package/dist/commands/testplan.js +7 -5
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +75 -26
- package/dist/index.js +1 -2
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/process.js +1 -0
- package/dist/utils/resultsPatterns.d.ts +12 -0
- package/dist/utils/resultsPatterns.js +37 -0
- package/dist/utils/signals.d.ts +18 -0
- package/dist/utils/signals.js +52 -0
- package/package.json +22 -22
- package/dist/commands/knownIssue.d.ts +0 -8
- package/dist/commands/knownIssue.js +0 -59
|
@@ -7,12 +7,14 @@ import process from "node:process";
|
|
|
7
7
|
import { QualityGateState, stringifyQualityGateResults } from "@allurereport/core";
|
|
8
8
|
import { createTestPlan } from "@allurereport/core-api";
|
|
9
9
|
import { allureResultsDirectoriesWatcher, delayedFileProcessingWatcher, newFilesInDirectoryWatcher, } from "@allurereport/directory-watcher";
|
|
10
|
+
import { formatProcessLogAttachmentName } from "@allurereport/plugin-agent";
|
|
10
11
|
import { BufferResultFile, PathResultFile } from "@allurereport/reader-api";
|
|
11
12
|
import { KnownError } from "@allurereport/service";
|
|
12
13
|
import { red } from "yoctocolors";
|
|
13
14
|
import { logTests, runProcess, terminationOf } from "../../utils/index.js";
|
|
14
15
|
import { logError } from "../../utils/logs.js";
|
|
15
16
|
import { stopProcessTree } from "../../utils/process.js";
|
|
17
|
+
import { allureResultsDirectoriesGlobWatcher } from "./resultsDiscovery.js";
|
|
16
18
|
export const executeNestedAllureCommand = async (params) => {
|
|
17
19
|
const nestedProcess = runProcess({
|
|
18
20
|
command: params.command,
|
|
@@ -23,8 +25,16 @@ export const executeNestedAllureCommand = async (params) => {
|
|
|
23
25
|
});
|
|
24
26
|
return await terminationOf(nestedProcess);
|
|
25
27
|
};
|
|
28
|
+
const attachResultsDirectoryWatchers = (params) => {
|
|
29
|
+
if (params.resultsPatterns.length > 0) {
|
|
30
|
+
return allureResultsDirectoriesGlobWatcher(params.cwd, params.resultsPatterns, params.onUpdate, {
|
|
31
|
+
indexDelay: 600,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return allureResultsDirectoriesWatcher(params.cwd, params.onUpdate, { indexDelay: 600 });
|
|
35
|
+
};
|
|
26
36
|
export const runTests = async (params) => {
|
|
27
|
-
const { allureReport, knownIssues, cwd, command, commandArgs, logs, environmentVariables, environment, withQualityGate, silent, logProcessExit = true, } = params;
|
|
37
|
+
const { allureReport, knownIssues, cwd, command, commandArgs, logs, environmentVariables, environment, withQualityGate, silent, logProcessExit = true, resultsPatterns = [], } = params;
|
|
28
38
|
let testProcessStarted = false;
|
|
29
39
|
const allureResultsWatchers = new Map();
|
|
30
40
|
const processWatcher = delayedFileProcessingWatcher(async (path) => {
|
|
@@ -33,28 +43,32 @@ export const runTests = async (params) => {
|
|
|
33
43
|
indexDelay: 200,
|
|
34
44
|
minProcessingDelay: 1000,
|
|
35
45
|
});
|
|
36
|
-
const allureResultsWatch =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
const allureResultsWatch = attachResultsDirectoryWatchers({
|
|
47
|
+
cwd,
|
|
48
|
+
resultsPatterns,
|
|
49
|
+
onUpdate: async (newAllureResults, deletedAllureResults) => {
|
|
50
|
+
for (const delAr of deletedAllureResults) {
|
|
51
|
+
const watcher = allureResultsWatchers.get(delAr);
|
|
52
|
+
if (watcher) {
|
|
53
|
+
await watcher.abort();
|
|
54
|
+
}
|
|
55
|
+
allureResultsWatchers.delete(delAr);
|
|
41
56
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
for (const newAr of newAllureResults) {
|
|
58
|
+
if (allureResultsWatchers.has(newAr)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const watcher = newFilesInDirectoryWatcher(newAr, async (path) => {
|
|
62
|
+
await processWatcher.addFile(path);
|
|
63
|
+
}, {
|
|
64
|
+
ignoreInitial: !testProcessStarted,
|
|
65
|
+
indexDelay: 300,
|
|
66
|
+
});
|
|
67
|
+
allureResultsWatchers.set(newAr, watcher);
|
|
68
|
+
await watcher.initialScan();
|
|
47
69
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}, {
|
|
51
|
-
ignoreInitial: !testProcessStarted,
|
|
52
|
-
indexDelay: 300,
|
|
53
|
-
});
|
|
54
|
-
allureResultsWatchers.set(newAr, watcher);
|
|
55
|
-
await watcher.initialScan();
|
|
56
|
-
}
|
|
57
|
-
}, { indexDelay: 600 });
|
|
70
|
+
},
|
|
71
|
+
});
|
|
58
72
|
await allureResultsWatch.initialScan();
|
|
59
73
|
testProcessStarted = true;
|
|
60
74
|
const beforeProcess = Date.now();
|
|
@@ -68,10 +82,14 @@ export const runTests = async (params) => {
|
|
|
68
82
|
const qualityGateState = new QualityGateState();
|
|
69
83
|
let qualityGateUnsub;
|
|
70
84
|
let qualityGateResults = [];
|
|
85
|
+
let fastFailTriggered = false;
|
|
71
86
|
let testProcessStdout = "";
|
|
72
87
|
let testProcessStderr = "";
|
|
73
88
|
if (withQualityGate) {
|
|
74
89
|
qualityGateUnsub = allureReport.realtimeSubscriber.onTestResults(async (testResults) => {
|
|
90
|
+
if (fastFailTriggered) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
75
93
|
const trs = await Promise.all(testResults.map((tr) => allureReport.store.testResultById(tr)));
|
|
76
94
|
const filteredTrs = trs.filter((tr) => tr !== undefined);
|
|
77
95
|
if (!filteredTrs.length) {
|
|
@@ -86,8 +104,10 @@ export const runTests = async (params) => {
|
|
|
86
104
|
if (!fastFailed) {
|
|
87
105
|
return;
|
|
88
106
|
}
|
|
89
|
-
|
|
107
|
+
qualityGateUnsub?.();
|
|
108
|
+
fastFailTriggered = true;
|
|
90
109
|
qualityGateResults = results;
|
|
110
|
+
qualityGateUnsub = undefined;
|
|
91
111
|
try {
|
|
92
112
|
await stopProcessTree(testProcess.pid);
|
|
93
113
|
}
|
|
@@ -137,10 +157,11 @@ export const runTests = async (params) => {
|
|
|
137
157
|
stdout: testProcessStdout,
|
|
138
158
|
stderr: testProcessStderr,
|
|
139
159
|
qualityGateResults,
|
|
160
|
+
fastFailed: fastFailTriggered,
|
|
140
161
|
};
|
|
141
162
|
};
|
|
142
163
|
export const executeAllureRun = async (params) => {
|
|
143
|
-
const { allureReport, knownIssues, cwd, command, commandArgs, environmentVariables = {}, environment, withQualityGate, silent, logs, ignoreLogs, maxRerun = 0, logProcessExit = true, } = params;
|
|
164
|
+
const { allureReport, knownIssues, cwd, command, commandArgs, environmentVariables = {}, environment, withQualityGate, silent, logs, ignoreLogs, maxRerun = 0, logProcessExit = true, resultsPatterns = [], } = params;
|
|
144
165
|
await allureReport.start();
|
|
145
166
|
const globalExitCode = {
|
|
146
167
|
original: 0,
|
|
@@ -161,9 +182,15 @@ export const executeAllureRun = async (params) => {
|
|
|
161
182
|
environmentVariables,
|
|
162
183
|
withQualityGate,
|
|
163
184
|
logProcessExit,
|
|
185
|
+
resultsPatterns,
|
|
164
186
|
});
|
|
165
|
-
|
|
166
|
-
|
|
187
|
+
const allFailuresAfterInitialRun = await allureReport.store.failedTestResults();
|
|
188
|
+
const blockingFailuresAfterInitialRun = await allureReport.store.blockingFailedTestResults();
|
|
189
|
+
if (allFailuresAfterInitialRun.length > 0 && blockingFailuresAfterInitialRun.length === 0 && testProcessResult) {
|
|
190
|
+
globalExitCode.actual = 0;
|
|
191
|
+
}
|
|
192
|
+
for (let rerun = 0; rerun < maxRerun && testProcessResult && !testProcessResult.fastFailed; rerun++) {
|
|
193
|
+
const failed = await allureReport.store.blockingFailedTestResults();
|
|
167
194
|
if (failed.length === 0) {
|
|
168
195
|
console.log("no failed tests is detected.");
|
|
169
196
|
break;
|
|
@@ -190,10 +217,16 @@ export const executeAllureRun = async (params) => {
|
|
|
190
217
|
},
|
|
191
218
|
withQualityGate,
|
|
192
219
|
logProcessExit,
|
|
220
|
+
resultsPatterns,
|
|
193
221
|
});
|
|
194
222
|
await rm(tmpDir, { recursive: true });
|
|
195
223
|
logTests(await allureReport.store.allTestResults());
|
|
196
224
|
}
|
|
225
|
+
const allFailuresAfterReruns = await allureReport.store.failedTestResults();
|
|
226
|
+
const blockingFailuresAfterReruns = await allureReport.store.blockingFailedTestResults();
|
|
227
|
+
if (allFailuresAfterReruns.length > 0 && blockingFailuresAfterReruns.length === 0 && testProcessResult) {
|
|
228
|
+
globalExitCode.actual = 0;
|
|
229
|
+
}
|
|
197
230
|
const trs = await allureReport.store.allTestResults({ includeRetries: false });
|
|
198
231
|
qualityGateResults = testProcessResult?.qualityGateResults ?? [];
|
|
199
232
|
if (withQualityGate && !qualityGateResults.length) {
|
|
@@ -235,13 +268,13 @@ export const executeAllureRun = async (params) => {
|
|
|
235
268
|
const fileName = randomUUID();
|
|
236
269
|
const stdoutResultFile = new BufferResultFile(Buffer.from(testProcessResult.stdout, "utf8"), `${fileName}`);
|
|
237
270
|
stdoutResultFile.contentType = "text/plain";
|
|
238
|
-
allureReport.realtimeDispatcher.sendGlobalAttachment(stdoutResultFile,
|
|
271
|
+
allureReport.realtimeDispatcher.sendGlobalAttachment(stdoutResultFile, formatProcessLogAttachmentName([command, ...commandArgs].join(" "), "stdout"));
|
|
239
272
|
}
|
|
240
273
|
if (!ignoreLogs && testProcessResult?.stderr) {
|
|
241
274
|
const fileName = randomUUID();
|
|
242
275
|
const stderrResultFile = new BufferResultFile(Buffer.from(testProcessResult.stderr, "utf8"), fileName);
|
|
243
276
|
stderrResultFile.contentType = "text/plain";
|
|
244
|
-
allureReport.realtimeDispatcher.sendGlobalAttachment(stderrResultFile,
|
|
277
|
+
allureReport.realtimeDispatcher.sendGlobalAttachment(stderrResultFile, formatProcessLogAttachmentName([command, ...commandArgs].join(" "), "stderr"));
|
|
245
278
|
if (processFailed) {
|
|
246
279
|
allureReport.realtimeDispatcher.sendGlobalError({
|
|
247
280
|
message: "Test process has failed",
|
package/dist/commands/csv.js
CHANGED
|
@@ -6,15 +6,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
6
6
|
import CsvPlugin from "@allurereport/plugin-csv";
|
|
7
7
|
import { Command, Option } from "clipanion";
|
|
8
8
|
import { red } from "yoctocolors";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
10
10
|
export class CsvCommand extends Command {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.resultsDir = Option.Rest({
|
|
14
|
-
name: "Patterns to match test results directories
|
|
14
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
15
15
|
});
|
|
16
16
|
this.config = Option.String("--config,-c", {
|
|
17
|
-
description: "The path Allure config file",
|
|
17
|
+
description: "The path to Allure config file",
|
|
18
18
|
});
|
|
19
19
|
this.cwd = Option.String("--cwd", {
|
|
20
20
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -29,17 +29,11 @@ export class CsvCommand extends Command {
|
|
|
29
29
|
description: "The csv separator",
|
|
30
30
|
});
|
|
31
31
|
this.knownIssues = Option.String("--known-issues", {
|
|
32
|
-
description: "Path to
|
|
32
|
+
description: "Path to known issues file",
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
async execute() {
|
|
36
36
|
const cwd = await realpath(this.cwd ?? process.cwd());
|
|
37
|
-
const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
|
|
38
|
-
if (!resultDirectories.length) {
|
|
39
|
-
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
40
|
-
exit(1);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
37
|
const before = new Date().getTime();
|
|
44
38
|
const defaultCsvOptions = {
|
|
45
39
|
separator: this.separator ?? ",",
|
|
@@ -49,6 +43,12 @@ export class CsvCommand extends Command {
|
|
|
49
43
|
const config = await readConfig(cwd, this.config, {
|
|
50
44
|
knownIssuesPath: this.knownIssues,
|
|
51
45
|
});
|
|
46
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
47
|
+
if (!resultDirectories.length) {
|
|
48
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
49
|
+
exit(1);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
52
|
config.plugins = [
|
|
53
53
|
{
|
|
54
54
|
id: "csv",
|
|
@@ -5,15 +5,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
5
5
|
import DashboardPlugin from "@allurereport/plugin-dashboard";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
9
9
|
export class DashboardCommand extends Command {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
12
|
this.resultsDir = Option.Rest({
|
|
13
|
-
name: "Patterns to match test results directories
|
|
13
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
14
14
|
});
|
|
15
15
|
this.config = Option.String("--config,-c", {
|
|
16
|
-
description: "The path Allure config file",
|
|
16
|
+
description: "The path to Allure config file",
|
|
17
17
|
});
|
|
18
18
|
this.cwd = Option.String("--cwd", {
|
|
19
19
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -39,12 +39,6 @@ export class DashboardCommand extends Command {
|
|
|
39
39
|
}
|
|
40
40
|
async execute() {
|
|
41
41
|
const cwd = await realpath(this.cwd ?? process.cwd());
|
|
42
|
-
const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
|
|
43
|
-
if (!resultDirectories.length) {
|
|
44
|
-
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
45
|
-
exit(1);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
42
|
const before = new Date().getTime();
|
|
49
43
|
const defaultDashboardOptions = {
|
|
50
44
|
singleFile: this.singleFile ?? false,
|
|
@@ -56,6 +50,12 @@ export class DashboardCommand extends Command {
|
|
|
56
50
|
output: this.output,
|
|
57
51
|
name: this.reportName,
|
|
58
52
|
});
|
|
53
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
54
|
+
if (!resultDirectories.length) {
|
|
55
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
56
|
+
exit(1);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
59
|
config.plugins = [
|
|
60
60
|
{
|
|
61
61
|
id: "dashboard",
|
|
@@ -7,10 +7,10 @@ export class GenerateCommand extends Command {
|
|
|
7
7
|
constructor() {
|
|
8
8
|
super(...arguments);
|
|
9
9
|
this.resultsDir = Option.Rest({
|
|
10
|
-
name: "Patterns to match test results directories
|
|
10
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
11
11
|
});
|
|
12
12
|
this.config = Option.String("--config,-c", {
|
|
13
|
-
description: "The path Allure config file",
|
|
13
|
+
description: "The path to Allure config file",
|
|
14
14
|
});
|
|
15
15
|
this.output = Option.String("--output,-o", {
|
|
16
16
|
description: "The output directory name. Absolute paths are accepted as well (default: allure-report)",
|
|
@@ -38,6 +38,9 @@ export class GenerateCommand extends Command {
|
|
|
38
38
|
this.hideLabels = Option.Array("--hide-labels", {
|
|
39
39
|
description: "Hide labels by exact name in generated reports. Repeat the option for multiple labels",
|
|
40
40
|
});
|
|
41
|
+
this.knownIssues = Option.String("--known-issues", {
|
|
42
|
+
description: "Path to known issues file",
|
|
43
|
+
});
|
|
41
44
|
}
|
|
42
45
|
async execute() {
|
|
43
46
|
const cwd = this.cwd ?? processCwd();
|
|
@@ -48,7 +51,8 @@ export class GenerateCommand extends Command {
|
|
|
48
51
|
open: this.open,
|
|
49
52
|
port: this.port,
|
|
50
53
|
hideLabels,
|
|
51
|
-
historyLimit: this.historyLimit ? parseInt(this.historyLimit, 10) : undefined,
|
|
54
|
+
historyLimit: this.historyLimit !== undefined ? parseInt(this.historyLimit, 10) : undefined,
|
|
55
|
+
knownIssuesPath: this.knownIssues,
|
|
52
56
|
});
|
|
53
57
|
await generate({
|
|
54
58
|
dump: this.dump,
|
package/dist/commands/history.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as console from "node:console";
|
|
2
2
|
import process, { exit } from "node:process";
|
|
3
|
-
import { AllureReport, resolveConfig } from "@allurereport/core";
|
|
3
|
+
import { AllureReport, readRawConfig, resolveConfig } from "@allurereport/core";
|
|
4
4
|
import { Command, Option } from "clipanion";
|
|
5
5
|
import { red } from "yoctocolors";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
7
7
|
export class HistoryCommand extends Command {
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments);
|
|
10
10
|
this.resultsDir = Option.Rest({
|
|
11
|
-
name: "Patterns to match test results directories
|
|
11
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
12
12
|
});
|
|
13
13
|
this.historyPath = Option.String("--history-path,-h", {
|
|
14
14
|
description: "The path to history file",
|
|
@@ -21,7 +21,9 @@ export class HistoryCommand extends Command {
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
async execute() {
|
|
24
|
-
const
|
|
24
|
+
const cwd = process.cwd();
|
|
25
|
+
const rawConfig = await readRawConfig(cwd);
|
|
26
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, rawConfig.resultsDir);
|
|
25
27
|
if (!resultDirectories.length) {
|
|
26
28
|
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
27
29
|
exit(1);
|
package/dist/commands/index.d.ts
CHANGED
package/dist/commands/index.js
CHANGED
|
@@ -8,7 +8,7 @@ class BaseJiraCommand extends Command {
|
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments);
|
|
10
10
|
this.config = Option.String("--config,-c", {
|
|
11
|
-
description: "The path Allure config file",
|
|
11
|
+
description: "The path to Allure config file",
|
|
12
12
|
});
|
|
13
13
|
this.cwd = Option.String("--cwd", {
|
|
14
14
|
description: "The working directory for the command to run (default: current working directory)",
|
package/dist/commands/log.js
CHANGED
|
@@ -5,15 +5,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
5
5
|
import LogPlugin from "@allurereport/plugin-log";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
9
9
|
export class LogCommand extends Command {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
12
|
this.resultsDir = Option.Rest({
|
|
13
|
-
name: "Patterns to match test results directories
|
|
13
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
14
14
|
});
|
|
15
15
|
this.config = Option.String("--config,-c", {
|
|
16
|
-
description: "The path Allure config file",
|
|
16
|
+
description: "The path to Allure config file",
|
|
17
17
|
});
|
|
18
18
|
this.cwd = Option.String("--cwd", {
|
|
19
19
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -30,12 +30,6 @@ export class LogCommand extends Command {
|
|
|
30
30
|
}
|
|
31
31
|
async execute() {
|
|
32
32
|
const cwd = await realpath(this.cwd ?? process.cwd());
|
|
33
|
-
const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
|
|
34
|
-
if (!resultDirectories.length) {
|
|
35
|
-
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
36
|
-
exit(1);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
33
|
const before = new Date().getTime();
|
|
40
34
|
const defaultLogOptions = {
|
|
41
35
|
allSteps: this.allSteps ?? false,
|
|
@@ -43,6 +37,12 @@ export class LogCommand extends Command {
|
|
|
43
37
|
groupBy: this.groupBy ?? "suite",
|
|
44
38
|
};
|
|
45
39
|
const config = await readConfig(cwd, this.config);
|
|
40
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
41
|
+
if (!resultDirectories.length) {
|
|
42
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
43
|
+
exit(1);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
46
|
config.plugins = [
|
|
47
47
|
{
|
|
48
48
|
id: "log",
|
package/dist/commands/open.js
CHANGED
|
@@ -8,15 +8,17 @@ import { serve } from "@allurereport/static-server";
|
|
|
8
8
|
import { Command, Option } from "clipanion";
|
|
9
9
|
import { red } from "yoctocolors";
|
|
10
10
|
import { findFilesByGlobs } from "./../utils/fileSystem.js";
|
|
11
|
+
import { resolveResultsPatterns } from "./../utils/resultsPatterns.js";
|
|
12
|
+
import { notifySignals, waitForAbort } from "./../utils/signals.js";
|
|
11
13
|
import { generate } from "./commons/generate.js";
|
|
12
14
|
export class OpenCommand extends Command {
|
|
13
15
|
constructor() {
|
|
14
16
|
super(...arguments);
|
|
15
17
|
this.resultsDir = Option.Rest({
|
|
16
|
-
name: "A report to open or
|
|
18
|
+
name: "A report path to open, or results patterns. Overrides config.resultsDir. Empty Rest serves the configured output.",
|
|
17
19
|
});
|
|
18
20
|
this.config = Option.String("--config,-c", {
|
|
19
|
-
description: "The path Allure config file",
|
|
21
|
+
description: "The path to Allure config file",
|
|
20
22
|
});
|
|
21
23
|
this.port = Option.String("--port", {
|
|
22
24
|
description: "The port to serve the reports on. If not set, the server starts on a random port",
|
|
@@ -35,6 +37,7 @@ export class OpenCommand extends Command {
|
|
|
35
37
|
port: this.port,
|
|
36
38
|
});
|
|
37
39
|
const servePath = this.resolveReportPath(cwd, this.resultsDir, config.output);
|
|
40
|
+
const resolvedPatterns = resolveResultsPatterns(this.resultsDir, config.resultsDir);
|
|
38
41
|
if (await this.reportExists(servePath)) {
|
|
39
42
|
await serve({
|
|
40
43
|
port: config.port ? parseInt(config.port, 10) : undefined,
|
|
@@ -42,7 +45,7 @@ export class OpenCommand extends Command {
|
|
|
42
45
|
open: true,
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
|
-
else if (
|
|
48
|
+
else if (resolvedPatterns.length) {
|
|
46
49
|
const tmpDir = await mkdtemp(join(tmpdir(), "allure-report-"));
|
|
47
50
|
const config = await readConfig(cwd, this.config, {
|
|
48
51
|
port: this.port,
|
|
@@ -54,12 +57,13 @@ export class OpenCommand extends Command {
|
|
|
54
57
|
cwd,
|
|
55
58
|
config,
|
|
56
59
|
});
|
|
57
|
-
|
|
60
|
+
const notifier = notifySignals(["SIGINT", "SIGTERM"]);
|
|
61
|
+
void waitForAbort(notifier.signal).then(async () => {
|
|
58
62
|
try {
|
|
59
63
|
await rm(config.output, { recursive: true });
|
|
60
64
|
}
|
|
61
65
|
catch { }
|
|
62
|
-
process.exit(0);
|
|
66
|
+
process.exit(notifier.info()?.code ?? 0);
|
|
63
67
|
});
|
|
64
68
|
await serve({
|
|
65
69
|
port: config.port ? parseInt(config.port, 10) : undefined,
|
|
@@ -6,15 +6,15 @@ import { Command, Option } from "clipanion";
|
|
|
6
6
|
import * as typanion from "typanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
8
|
import { environmentNameOption, environmentOption, normalizeCommandEnvironmentOptions, resolveCommandEnvironment, } from "../utils/environment.js";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
10
10
|
export class QualityGateCommand extends Command {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.resultsDir = Option.Rest({
|
|
14
|
-
name: "Patterns to match test results directories
|
|
14
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
15
15
|
});
|
|
16
16
|
this.config = Option.String("--config,-c", {
|
|
17
|
-
description: "The path Allure config file",
|
|
17
|
+
description: "The path to Allure config file",
|
|
18
18
|
});
|
|
19
19
|
this.fastFail = Option.Boolean("--fast-fail", {
|
|
20
20
|
description: "Force the command to fail if there are any rule failures",
|
|
@@ -32,7 +32,7 @@ export class QualityGateCommand extends Command {
|
|
|
32
32
|
validator: typanion.isNumber(),
|
|
33
33
|
});
|
|
34
34
|
this.knownIssues = Option.String("--known-issues", {
|
|
35
|
-
description: "Path to
|
|
35
|
+
description: "Path to known issues file",
|
|
36
36
|
});
|
|
37
37
|
this.environment = environmentOption();
|
|
38
38
|
this.environmentName = environmentNameOption();
|
|
@@ -47,9 +47,9 @@ export class QualityGateCommand extends Command {
|
|
|
47
47
|
};
|
|
48
48
|
normalizeCommandEnvironmentOptions(environmentOptions);
|
|
49
49
|
const cwd = await realpath(this.cwd ?? processCwd());
|
|
50
|
-
const { maxFailures, minTestsCount, successRate, fastFail
|
|
50
|
+
const { maxFailures, minTestsCount, successRate, fastFail } = this;
|
|
51
51
|
const config = await readConfig(cwd, this.config, {
|
|
52
|
-
knownIssuesPath,
|
|
52
|
+
knownIssuesPath: this.knownIssues,
|
|
53
53
|
});
|
|
54
54
|
const resolvedEnvironment = resolveCommandEnvironment(config, environmentOptions);
|
|
55
55
|
const rules = {};
|
|
@@ -81,7 +81,7 @@ export class QualityGateCommand extends Command {
|
|
|
81
81
|
exit(-1);
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
|
-
const { resultDirectories, patterns } = await
|
|
84
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
85
85
|
if (!resultDirectories.length) {
|
|
86
86
|
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
87
87
|
exit(1);
|
|
@@ -9,44 +9,42 @@ import * as fs from "node:fs/promises";
|
|
|
9
9
|
import { realpath } from "node:fs/promises";
|
|
10
10
|
import { basename, join, resolve } from "node:path";
|
|
11
11
|
import { exit } from "node:process";
|
|
12
|
+
import { readRawConfig } from "@allurereport/core";
|
|
12
13
|
import AdmZip from "adm-zip";
|
|
13
14
|
import { Command, Option } from "clipanion";
|
|
14
|
-
import { glob } from "glob";
|
|
15
15
|
import { green, red } from "yoctocolors";
|
|
16
|
+
import { resolveAndFindResultsDirs } from "../../utils/resultsPatterns.js";
|
|
16
17
|
export class ResultsPackCommand extends Command {
|
|
17
18
|
constructor() {
|
|
18
19
|
super(...arguments);
|
|
19
20
|
_ResultsPackCommand_instances.add(this);
|
|
20
21
|
this.resultsDir = Option.String({
|
|
21
22
|
required: false,
|
|
22
|
-
name: "Pattern to match test results directories
|
|
23
|
+
name: "Pattern to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
23
24
|
});
|
|
24
25
|
this.name = Option.String("--name", {
|
|
25
26
|
description: "The archive name (default: allure-results.zip)",
|
|
26
27
|
});
|
|
28
|
+
this.config = Option.String("--config,-c", {
|
|
29
|
+
description: "The path to Allure config file",
|
|
30
|
+
});
|
|
27
31
|
this.cwd = Option.String("--cwd", {
|
|
28
32
|
description: "The working directory for the command to run (default: current working directory)",
|
|
29
33
|
});
|
|
30
34
|
}
|
|
31
35
|
async execute() {
|
|
32
36
|
const cwd = await realpath(this.cwd ?? process.cwd());
|
|
33
|
-
const
|
|
37
|
+
const rawConfig = await readRawConfig(cwd, this.config);
|
|
38
|
+
const cliPatterns = this.resultsDir ? [this.resultsDir] : [];
|
|
39
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, cliPatterns, rawConfig.resultsDir);
|
|
34
40
|
const archiveName = this.name ?? "allure-results.zip";
|
|
35
|
-
const resultsDirectories = (await glob(resultsDir, {
|
|
36
|
-
mark: true,
|
|
37
|
-
nodir: false,
|
|
38
|
-
dot: true,
|
|
39
|
-
absolute: true,
|
|
40
|
-
windowsPathsNoEscape: true,
|
|
41
|
-
cwd,
|
|
42
|
-
})).filter((p) => /(\/|\\)$/.test(p));
|
|
43
41
|
const resultsFiles = new Set();
|
|
44
|
-
if (
|
|
45
|
-
console.error(red(`No test results directories found matching pattern: ${
|
|
42
|
+
if (resultDirectories.length === 0) {
|
|
43
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
46
44
|
exit(1);
|
|
47
45
|
return;
|
|
48
46
|
}
|
|
49
|
-
for (const dir of
|
|
47
|
+
for (const dir of resultDirectories) {
|
|
50
48
|
const files = await fs.readdir(dir);
|
|
51
49
|
if (files.length === 0) {
|
|
52
50
|
continue;
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export declare class RunCommand extends Command {
|
|
|
16
16
|
environmentName: string | undefined;
|
|
17
17
|
historyLimit: string | undefined;
|
|
18
18
|
hideLabels: string[] | undefined;
|
|
19
|
+
knownIssues: string | undefined;
|
|
20
|
+
resultsDir: string[] | undefined;
|
|
19
21
|
commandToRun: string[];
|
|
20
22
|
get logs(): "pipe" | "inherit" | "ignore";
|
|
21
23
|
execute(): Promise<void>;
|