allure 3.4.1 → 3.6.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.
@@ -0,0 +1,258 @@
1
+ import * as console from "node:console";
2
+ import { randomUUID } from "node:crypto";
3
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join, resolve } from "node:path";
6
+ import process from "node:process";
7
+ import { QualityGateState, stringifyQualityGateResults } from "@allurereport/core";
8
+ import { createTestPlan } from "@allurereport/core-api";
9
+ import { allureResultsDirectoriesWatcher, delayedFileProcessingWatcher, newFilesInDirectoryWatcher, } from "@allurereport/directory-watcher";
10
+ import { BufferResultFile, PathResultFile } from "@allurereport/reader-api";
11
+ import { KnownError } from "@allurereport/service";
12
+ import { red } from "yoctocolors";
13
+ import { logTests, runProcess, terminationOf } from "../../utils/index.js";
14
+ import { logError } from "../../utils/logs.js";
15
+ import { stopProcessTree } from "../../utils/process.js";
16
+ export const executeNestedAllureCommand = async (params) => {
17
+ const nestedProcess = runProcess({
18
+ command: params.command,
19
+ commandArgs: params.commandArgs,
20
+ cwd: params.cwd,
21
+ environmentVariables: params.environmentVariables,
22
+ logs: params.silent ? "ignore" : "inherit",
23
+ });
24
+ return await terminationOf(nestedProcess);
25
+ };
26
+ export const runTests = async (params) => {
27
+ const { allureReport, knownIssues, cwd, command, commandArgs, logs, environmentVariables, environment, withQualityGate, silent, logProcessExit = true, } = params;
28
+ let testProcessStarted = false;
29
+ const allureResultsWatchers = new Map();
30
+ const processWatcher = delayedFileProcessingWatcher(async (path) => {
31
+ await allureReport.readResult(new PathResultFile(path));
32
+ }, {
33
+ indexDelay: 200,
34
+ minProcessingDelay: 1000,
35
+ });
36
+ const allureResultsWatch = allureResultsDirectoriesWatcher(cwd, async (newAllureResults, deletedAllureResults) => {
37
+ for (const delAr of deletedAllureResults) {
38
+ const watcher = allureResultsWatchers.get(delAr);
39
+ if (watcher) {
40
+ await watcher.abort();
41
+ }
42
+ allureResultsWatchers.delete(delAr);
43
+ }
44
+ for (const newAr of newAllureResults) {
45
+ if (allureResultsWatchers.has(newAr)) {
46
+ continue;
47
+ }
48
+ const watcher = newFilesInDirectoryWatcher(newAr, async (path) => {
49
+ await processWatcher.addFile(path);
50
+ }, {
51
+ ignoreInitial: !testProcessStarted,
52
+ indexDelay: 300,
53
+ });
54
+ allureResultsWatchers.set(newAr, watcher);
55
+ await watcher.initialScan();
56
+ }
57
+ }, { indexDelay: 600 });
58
+ await allureResultsWatch.initialScan();
59
+ testProcessStarted = true;
60
+ const beforeProcess = Date.now();
61
+ const testProcess = runProcess({
62
+ command,
63
+ commandArgs,
64
+ cwd,
65
+ environmentVariables,
66
+ logs,
67
+ });
68
+ const qualityGateState = new QualityGateState();
69
+ let qualityGateUnsub;
70
+ let qualityGateResults = [];
71
+ let testProcessStdout = "";
72
+ let testProcessStderr = "";
73
+ if (withQualityGate) {
74
+ qualityGateUnsub = allureReport.realtimeSubscriber.onTestResults(async (testResults) => {
75
+ const trs = await Promise.all(testResults.map((tr) => allureReport.store.testResultById(tr)));
76
+ const filteredTrs = trs.filter((tr) => tr !== undefined);
77
+ if (!filteredTrs.length) {
78
+ return;
79
+ }
80
+ const { results, fastFailed } = await allureReport.validate({
81
+ trs: filteredTrs,
82
+ state: qualityGateState,
83
+ environment,
84
+ knownIssues,
85
+ });
86
+ if (!fastFailed) {
87
+ return;
88
+ }
89
+ allureReport.realtimeDispatcher.sendQualityGateResults(results);
90
+ qualityGateResults = results;
91
+ try {
92
+ await stopProcessTree(testProcess.pid);
93
+ }
94
+ catch (err) {
95
+ if (err.message.includes("kill ESRCH")) {
96
+ return;
97
+ }
98
+ throw err;
99
+ }
100
+ });
101
+ }
102
+ if (logs === "pipe") {
103
+ testProcess.stdout?.setEncoding("utf8").on?.("data", (data) => {
104
+ testProcessStdout += data;
105
+ if (silent) {
106
+ return;
107
+ }
108
+ process.stdout.write(data);
109
+ });
110
+ testProcess.stderr?.setEncoding("utf8").on?.("data", async (data) => {
111
+ testProcessStderr += data;
112
+ if (silent) {
113
+ return;
114
+ }
115
+ process.stderr.write(data);
116
+ });
117
+ }
118
+ const code = await terminationOf(testProcess);
119
+ const afterProcess = Date.now();
120
+ if (logProcessExit) {
121
+ if (code !== null) {
122
+ console.log(`process finished with code ${code} (${afterProcess - beforeProcess}ms)`);
123
+ }
124
+ else {
125
+ console.log(`process terminated (${afterProcess - beforeProcess}ms)`);
126
+ }
127
+ }
128
+ await allureResultsWatch.abort();
129
+ for (const [ar, watcher] of allureResultsWatchers) {
130
+ await watcher.abort();
131
+ allureResultsWatchers.delete(ar);
132
+ }
133
+ await processWatcher.abort();
134
+ qualityGateUnsub?.();
135
+ return {
136
+ code,
137
+ stdout: testProcessStdout,
138
+ stderr: testProcessStderr,
139
+ qualityGateResults,
140
+ };
141
+ };
142
+ export const executeAllureRun = async (params) => {
143
+ const { allureReport, knownIssues, cwd, command, commandArgs, environmentVariables = {}, environment, withQualityGate, silent, logs, ignoreLogs, maxRerun = 0, logProcessExit = true, } = params;
144
+ await allureReport.start();
145
+ const globalExitCode = {
146
+ original: 0,
147
+ actual: undefined,
148
+ };
149
+ let qualityGateResults = [];
150
+ let testProcessResult = null;
151
+ try {
152
+ testProcessResult = await runTests({
153
+ logs,
154
+ silent,
155
+ allureReport,
156
+ knownIssues,
157
+ cwd,
158
+ command,
159
+ commandArgs,
160
+ environment,
161
+ environmentVariables,
162
+ withQualityGate,
163
+ logProcessExit,
164
+ });
165
+ for (let rerun = 0; rerun < maxRerun; rerun++) {
166
+ const failed = await allureReport.store.failedTestResults();
167
+ if (failed.length === 0) {
168
+ console.log("no failed tests is detected.");
169
+ break;
170
+ }
171
+ const testPlan = createTestPlan(failed);
172
+ console.log(`rerun number ${rerun} of ${testPlan.tests.length} tests:`);
173
+ logTests(failed);
174
+ const tmpDir = await mkdtemp(join(tmpdir(), "allure-run-"));
175
+ const testPlanPath = resolve(tmpDir, `${rerun}-testplan.json`);
176
+ await writeFile(testPlanPath, JSON.stringify(testPlan));
177
+ testProcessResult = await runTests({
178
+ silent,
179
+ logs,
180
+ allureReport,
181
+ knownIssues,
182
+ cwd,
183
+ command,
184
+ commandArgs,
185
+ environment,
186
+ environmentVariables: {
187
+ ...environmentVariables,
188
+ ALLURE_TESTPLAN_PATH: testPlanPath,
189
+ ALLURE_RERUN: `${rerun}`,
190
+ },
191
+ withQualityGate,
192
+ logProcessExit,
193
+ });
194
+ await rm(tmpDir, { recursive: true });
195
+ logTests(await allureReport.store.allTestResults());
196
+ }
197
+ const trs = await allureReport.store.allTestResults({ includeHidden: false });
198
+ qualityGateResults = testProcessResult?.qualityGateResults ?? [];
199
+ if (withQualityGate && !qualityGateResults.length) {
200
+ const { results } = await allureReport.validate({
201
+ trs,
202
+ knownIssues,
203
+ environment,
204
+ });
205
+ qualityGateResults = results;
206
+ }
207
+ if (qualityGateResults.length) {
208
+ const qualityGateMessage = stringifyQualityGateResults(qualityGateResults);
209
+ console.error(qualityGateMessage);
210
+ allureReport.realtimeDispatcher.sendQualityGateResults(qualityGateResults);
211
+ }
212
+ globalExitCode.original = testProcessResult?.code ?? -1;
213
+ if (withQualityGate) {
214
+ globalExitCode.actual = qualityGateResults.length > 0 ? 1 : 0;
215
+ }
216
+ }
217
+ catch (error) {
218
+ globalExitCode.actual = 1;
219
+ if (error instanceof KnownError) {
220
+ console.error(red(error.message));
221
+ allureReport.realtimeDispatcher.sendGlobalError({
222
+ message: error.message,
223
+ });
224
+ }
225
+ else {
226
+ await logError("Failed to run tests using Allure due to unexpected error", error);
227
+ allureReport.realtimeDispatcher.sendGlobalError({
228
+ message: error.message,
229
+ trace: error.stack,
230
+ });
231
+ }
232
+ }
233
+ const processFailed = Math.abs(globalExitCode.actual ?? globalExitCode.original) !== 0;
234
+ if (!ignoreLogs && testProcessResult?.stdout) {
235
+ const fileName = randomUUID();
236
+ const stdoutResultFile = new BufferResultFile(Buffer.from(testProcessResult.stdout, "utf8"), `${fileName}`);
237
+ stdoutResultFile.contentType = "text/plain";
238
+ allureReport.realtimeDispatcher.sendGlobalAttachment(stdoutResultFile, "stdout.txt");
239
+ }
240
+ if (!ignoreLogs && testProcessResult?.stderr) {
241
+ const fileName = randomUUID();
242
+ const stderrResultFile = new BufferResultFile(Buffer.from(testProcessResult.stderr, "utf8"), fileName);
243
+ stderrResultFile.contentType = "text/plain";
244
+ allureReport.realtimeDispatcher.sendGlobalAttachment(stderrResultFile, "stderr.txt");
245
+ if (processFailed) {
246
+ allureReport.realtimeDispatcher.sendGlobalError({
247
+ message: "Test process has failed",
248
+ trace: testProcessResult.stderr,
249
+ });
250
+ }
251
+ }
252
+ allureReport.realtimeDispatcher.sendGlobalExitCode(globalExitCode);
253
+ await allureReport.done();
254
+ return {
255
+ globalExitCode,
256
+ testProcessResult,
257
+ };
258
+ };
@@ -2,6 +2,7 @@ export * from "./history.js";
2
2
  export * from "./testplan.js";
3
3
  export * from "./classic.js";
4
4
  export * from "./allure2.js";
5
+ export * from "./agent.js";
5
6
  export * from "./awesome.js";
6
7
  export * from "./csv.js";
7
8
  export * from "./history.js";
@@ -2,6 +2,7 @@ export * from "./history.js";
2
2
  export * from "./testplan.js";
3
3
  export * from "./classic.js";
4
4
  export * from "./allure2.js";
5
+ export * from "./agent.js";
5
6
  export * from "./awesome.js";
6
7
  export * from "./csv.js";
7
8
  export * from "./history.js";
@@ -1,11 +1,4 @@
1
- import type { QualityGateValidationResult } from "@allurereport/plugin-api";
2
1
  import { Command } from "clipanion";
3
- export type TestProcessResult = {
4
- code: number | null;
5
- stdout: string;
6
- stderr: string;
7
- qualityGateResults: QualityGateValidationResult[];
8
- };
9
2
  export declare class RunCommand extends Command {
10
3
  static paths: string[][];
11
4
  static usage: import("clipanion").Usage;
@@ -1,136 +1,16 @@
1
1
  import * as console from "node:console";
2
- import { randomUUID } from "node:crypto";
3
- import { mkdtemp, realpath, rm, writeFile } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join, resolve } from "node:path";
2
+ import { realpath, rm } from "node:fs/promises";
3
+ import { resolve } from "node:path";
6
4
  import process, { exit } from "node:process";
7
- import { AllureReport, QualityGateState, isFileNotFoundError, readConfig, stringifyQualityGateResults, } from "@allurereport/core";
8
- import { createTestPlan } from "@allurereport/core-api";
9
- import { allureResultsDirectoriesWatcher, delayedFileProcessingWatcher, newFilesInDirectoryWatcher, } from "@allurereport/directory-watcher";
5
+ import { AllureReport, isFileNotFoundError, readConfig } from "@allurereport/core";
10
6
  import Awesome from "@allurereport/plugin-awesome";
11
- import { BufferResultFile, PathResultFile } from "@allurereport/reader-api";
12
- import { KnownError } from "@allurereport/service";
13
7
  import { serve } from "@allurereport/static-server";
14
8
  import { Command, Option, UsageError } from "clipanion";
15
9
  import { red } from "yoctocolors";
16
10
  import { environmentNameOption, environmentOption, normalizeCommandEnvironmentOptions, resolveCommandEnvironment, } from "../utils/environment.js";
17
- import { logTests, runProcess, terminationOf } from "../utils/index.js";
18
- import { logError } from "../utils/logs.js";
19
- import { stopProcessTree } from "../utils/process.js";
20
- const runTests = async (params) => {
21
- const { allureReport, knownIssues, cwd, command, commandArgs, logs, environmentVariables, environment, withQualityGate, silent, } = params;
22
- let testProcessStarted = false;
23
- const allureResultsWatchers = new Map();
24
- const processWatcher = delayedFileProcessingWatcher(async (path) => {
25
- await allureReport.readResult(new PathResultFile(path));
26
- }, {
27
- indexDelay: 200,
28
- minProcessingDelay: 1000,
29
- });
30
- const allureResultsWatch = allureResultsDirectoriesWatcher(cwd, async (newAllureResults, deletedAllureResults) => {
31
- for (const delAr of deletedAllureResults) {
32
- const watcher = allureResultsWatchers.get(delAr);
33
- if (watcher) {
34
- await watcher.abort();
35
- }
36
- allureResultsWatchers.delete(delAr);
37
- }
38
- for (const newAr of newAllureResults) {
39
- if (allureResultsWatchers.has(newAr)) {
40
- continue;
41
- }
42
- const watcher = newFilesInDirectoryWatcher(newAr, async (path) => {
43
- await processWatcher.addFile(path);
44
- }, {
45
- ignoreInitial: !testProcessStarted,
46
- indexDelay: 300,
47
- });
48
- allureResultsWatchers.set(newAr, watcher);
49
- await watcher.initialScan();
50
- }
51
- }, { indexDelay: 600 });
52
- await allureResultsWatch.initialScan();
53
- testProcessStarted = true;
54
- const beforeProcess = Date.now();
55
- const testProcess = runProcess({
56
- command,
57
- commandArgs,
58
- cwd,
59
- environmentVariables,
60
- logs,
61
- });
62
- const qualityGateState = new QualityGateState();
63
- let qualityGateUnsub;
64
- let qualityGateResults = [];
65
- let testProcessStdout = "";
66
- let testProcessStderr = "";
67
- if (withQualityGate) {
68
- qualityGateUnsub = allureReport.realtimeSubscriber.onTestResults(async (testResults) => {
69
- const trs = await Promise.all(testResults.map((tr) => allureReport.store.testResultById(tr)));
70
- const filteredTrs = trs.filter((tr) => tr !== undefined);
71
- if (!filteredTrs.length) {
72
- return;
73
- }
74
- const { results, fastFailed } = await allureReport.validate({
75
- trs: filteredTrs,
76
- state: qualityGateState,
77
- environment,
78
- knownIssues,
79
- });
80
- if (!fastFailed) {
81
- return;
82
- }
83
- allureReport.realtimeDispatcher.sendQualityGateResults(results);
84
- qualityGateResults = results;
85
- try {
86
- await stopProcessTree(testProcess.pid);
87
- }
88
- catch (err) {
89
- if (err.message.includes("kill ESRCH")) {
90
- return;
91
- }
92
- throw err;
93
- }
94
- });
95
- }
96
- if (logs === "pipe") {
97
- testProcess.stdout?.setEncoding("utf8").on?.("data", (data) => {
98
- testProcessStdout += data;
99
- if (silent) {
100
- return;
101
- }
102
- process.stdout.write(data);
103
- });
104
- testProcess.stderr?.setEncoding("utf8").on?.("data", async (data) => {
105
- testProcessStderr += data;
106
- if (silent) {
107
- return;
108
- }
109
- process.stderr.write(data);
110
- });
111
- }
112
- const code = await terminationOf(testProcess);
113
- const afterProcess = Date.now();
114
- if (code !== null) {
115
- console.log(`process finished with code ${code} (${afterProcess - beforeProcess}ms)`);
116
- }
117
- else {
118
- console.log(`process terminated (${afterProcess - beforeProcess}ms)`);
119
- }
120
- await allureResultsWatch.abort();
121
- for (const [ar, watcher] of allureResultsWatchers) {
122
- await watcher.abort();
123
- allureResultsWatchers.delete(ar);
124
- }
125
- await processWatcher.abort();
126
- qualityGateUnsub?.();
127
- return {
128
- code,
129
- stdout: testProcessStdout,
130
- stderr: testProcessStderr,
131
- qualityGateResults,
132
- };
133
- };
11
+ import { createChildAllureCliEnvironment, getActiveAllureCliCommand } from "../utils/execution-context.js";
12
+ import { executeAgentMode } from "./agent.js";
13
+ import { executeAllureRun, executeNestedAllureCommand } from "./commons/run.js";
134
14
  export class RunCommand extends Command {
135
15
  constructor() {
136
16
  super(...arguments);
@@ -185,11 +65,22 @@ export class RunCommand extends Command {
185
65
  if (!args || !args.length) {
186
66
  throw new UsageError("expecting command to be specified after --, e.g. allure run -- npm run test");
187
67
  }
188
- const environmentOptions = {
189
- environment: this.environment,
190
- environmentName: this.environmentName,
191
- };
192
- normalizeCommandEnvironmentOptions(environmentOptions);
68
+ const legacyAgentOutput = process.env.ALLURE_AGENT_OUTPUT;
69
+ if (legacyAgentOutput) {
70
+ await executeAgentMode({
71
+ configPath: this.config,
72
+ cwd: this.cwd,
73
+ output: resolve(process.cwd(), legacyAgentOutput),
74
+ expectations: process.env.ALLURE_AGENT_EXPECTATIONS
75
+ ? resolve(process.cwd(), process.env.ALLURE_AGENT_EXPECTATIONS)
76
+ : undefined,
77
+ environment: this.environment,
78
+ environmentName: this.environmentName,
79
+ silent: this.silent,
80
+ args,
81
+ });
82
+ return;
83
+ }
193
84
  const before = new Date().getTime();
194
85
  process.on("exit", (exitCode) => {
195
86
  const after = new Date().getTime();
@@ -200,6 +91,21 @@ export class RunCommand extends Command {
200
91
  const cwd = await realpath(this.cwd ?? process.cwd());
201
92
  const hideLabels = this.hideLabels?.length ? this.hideLabels : undefined;
202
93
  console.log(`${command} ${commandArgs.join(" ")}`);
94
+ if (getActiveAllureCliCommand()) {
95
+ const exitCode = await executeNestedAllureCommand({
96
+ command,
97
+ commandArgs,
98
+ cwd,
99
+ silent: this.silent,
100
+ });
101
+ exit(exitCode ?? -1);
102
+ return;
103
+ }
104
+ const environmentOptions = {
105
+ environment: this.environment,
106
+ environmentName: this.environmentName,
107
+ };
108
+ normalizeCommandEnvironmentOptions(environmentOptions);
203
109
  const maxRerun = this.rerun ? parseInt(this.rerun, 10) : 0;
204
110
  const config = await readConfig(cwd, this.config, {
205
111
  output: this.output,
@@ -246,113 +152,20 @@ export class RunCommand extends Command {
246
152
  ],
247
153
  });
248
154
  const knownIssues = await allureReport.store.allKnownIssues();
249
- await allureReport.start();
250
- const globalExitCode = {
251
- original: 0,
252
- actual: undefined,
253
- };
254
- let qualityGateResults;
255
- let testProcessResult = null;
256
- try {
257
- testProcessResult = await runTests({
258
- logs: this.logs,
259
- silent: this.silent,
260
- allureReport,
261
- knownIssues,
262
- cwd,
263
- command,
264
- commandArgs,
265
- environment: resolvedEnvironment?.id,
266
- environmentVariables: {},
267
- withQualityGate,
268
- });
269
- for (let rerun = 0; rerun < maxRerun; rerun++) {
270
- const failed = await allureReport.store.failedTestResults();
271
- if (failed.length === 0) {
272
- console.log("no failed tests is detected.");
273
- break;
274
- }
275
- const testPlan = createTestPlan(failed);
276
- console.log(`rerun number ${rerun} of ${testPlan.tests.length} tests:`);
277
- logTests(failed);
278
- const tmpDir = await mkdtemp(join(tmpdir(), "allure-run-"));
279
- const testPlanPath = resolve(tmpDir, `${rerun}-testplan.json`);
280
- await writeFile(testPlanPath, JSON.stringify(testPlan));
281
- testProcessResult = await runTests({
282
- silent: this.silent,
283
- logs: this.logs,
284
- allureReport,
285
- knownIssues,
286
- cwd,
287
- command,
288
- commandArgs,
289
- environment: resolvedEnvironment?.id,
290
- environmentVariables: {
291
- ALLURE_TESTPLAN_PATH: testPlanPath,
292
- ALLURE_RERUN: `${rerun}`,
293
- },
294
- withQualityGate,
295
- });
296
- await rm(tmpDir, { recursive: true });
297
- logTests(await allureReport.store.allTestResults());
298
- }
299
- const trs = await allureReport.store.allTestResults({ includeHidden: false });
300
- qualityGateResults = testProcessResult?.qualityGateResults ?? [];
301
- if (withQualityGate && !qualityGateResults?.length) {
302
- const { results } = await allureReport.validate({
303
- trs,
304
- knownIssues,
305
- environment: resolvedEnvironment?.id,
306
- });
307
- qualityGateResults = results;
308
- }
309
- if (qualityGateResults?.length) {
310
- const qualityGateMessage = stringifyQualityGateResults(qualityGateResults);
311
- console.error(qualityGateMessage);
312
- allureReport.realtimeDispatcher.sendQualityGateResults(qualityGateResults);
313
- }
314
- globalExitCode.original = testProcessResult?.code ?? -1;
315
- if (withQualityGate) {
316
- globalExitCode.actual = qualityGateResults.length > 0 ? 1 : 0;
317
- }
318
- }
319
- catch (error) {
320
- globalExitCode.actual = 1;
321
- if (error instanceof KnownError) {
322
- console.error(red(error.message));
323
- allureReport.realtimeDispatcher.sendGlobalError({
324
- message: error.message,
325
- });
326
- }
327
- else {
328
- await logError("Failed to run tests using Allure due to unexpected error", error);
329
- allureReport.realtimeDispatcher.sendGlobalError({
330
- message: error.message,
331
- trace: error.stack,
332
- });
333
- }
334
- }
335
- const processFailed = Math.abs(globalExitCode.actual ?? globalExitCode.original) !== 0;
336
- if (!this.ignoreLogs && testProcessResult?.stdout) {
337
- const fileName = randomUUID();
338
- const stdoutResultFile = new BufferResultFile(Buffer.from(testProcessResult.stdout, "utf8"), `${fileName}`);
339
- stdoutResultFile.contentType = "text/plain";
340
- allureReport.realtimeDispatcher.sendGlobalAttachment(stdoutResultFile, "stdout.txt");
341
- }
342
- if (!this.ignoreLogs && testProcessResult?.stderr) {
343
- const fileName = randomUUID();
344
- const stderrResultFile = new BufferResultFile(Buffer.from(testProcessResult.stderr, "utf8"), fileName);
345
- stderrResultFile.contentType = "text/plain";
346
- allureReport.realtimeDispatcher.sendGlobalAttachment(stderrResultFile, "stderr.txt");
347
- if (processFailed) {
348
- allureReport.realtimeDispatcher.sendGlobalError({
349
- message: "Test process has failed",
350
- trace: testProcessResult.stderr,
351
- });
352
- }
353
- }
354
- allureReport.realtimeDispatcher.sendGlobalExitCode(globalExitCode);
355
- await allureReport.done();
155
+ const { globalExitCode } = await executeAllureRun({
156
+ allureReport,
157
+ knownIssues,
158
+ cwd,
159
+ command,
160
+ commandArgs,
161
+ environmentVariables: createChildAllureCliEnvironment("run"),
162
+ environment: resolvedEnvironment?.id,
163
+ withQualityGate,
164
+ logs: this.logs,
165
+ silent: this.silent,
166
+ ignoreLogs: this.ignoreLogs,
167
+ maxRerun,
168
+ });
356
169
  if (config.open) {
357
170
  await serve({
358
171
  port: config.port ? parseInt(config.port, 10) : undefined,
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { argv } from "node:process";
3
3
  import { Builtins, Cli } from "clipanion";
4
- import { Allure2Command, AwesomeCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, HistoryCommand, JiraClearCommand, KnownIssueCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestPlanCommand, WatchCommand, WhoamiCommand, } from "./commands/index.js";
4
+ import { AgentCommand, AgentLatestCommand, AgentSelectCommand, AgentStateDirCommand, Allure2Command, AwesomeCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, HistoryCommand, JiraClearCommand, KnownIssueCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestPlanCommand, WatchCommand, WhoamiCommand, } from "./commands/index.js";
5
5
  const [node, app, ...args] = argv;
6
6
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
7
7
  const cli = new Cli({
@@ -11,6 +11,10 @@ const cli = new Cli({
11
11
  });
12
12
  cli.register(AwesomeCommand);
13
13
  cli.register(Allure2Command);
14
+ cli.register(AgentLatestCommand);
15
+ cli.register(AgentSelectCommand);
16
+ cli.register(AgentStateDirCommand);
17
+ cli.register(AgentCommand);
14
18
  cli.register(ClassicCommand);
15
19
  cli.register(CsvCommand);
16
20
  cli.register(DashboardCommand);
@@ -0,0 +1,41 @@
1
+ import type { TestPlan } from "@allurereport/core-api";
2
+ import { type AgentTestManifestLine } from "@allurereport/plugin-agent";
3
+ export type AgentRerunPreset = "review" | "failed" | "unsuccessful" | "all";
4
+ export type AgentLabelFilter = {
5
+ name: string;
6
+ value: string;
7
+ };
8
+ export type AgentSelectionResult = {
9
+ outputDir: string;
10
+ preset: AgentRerunPreset;
11
+ selectedTests: AgentTestManifestLine[];
12
+ testPlan: TestPlan;
13
+ };
14
+ export type AgentTestPlanContext = {
15
+ outputDir: string;
16
+ preset: AgentRerunPreset;
17
+ selectedCount: number;
18
+ testPlanPath: string;
19
+ cleanup: () => Promise<void>;
20
+ };
21
+ export declare const normalizeAgentRerunPreset: (value?: string) => AgentRerunPreset;
22
+ export declare const parseAgentLabelFilters: (values?: string[]) => AgentLabelFilter[];
23
+ export declare const resolveAgentSelectionOutputDir: (params: {
24
+ cwd: string;
25
+ from?: string;
26
+ latest?: boolean;
27
+ }) => Promise<string>;
28
+ export declare const selectAgentTestPlan: (params: {
29
+ outputDir: string;
30
+ preset?: AgentRerunPreset;
31
+ environments?: string[];
32
+ labelFilters?: AgentLabelFilter[];
33
+ }) => Promise<AgentSelectionResult>;
34
+ export declare const createAgentTestPlanContext: (params: {
35
+ cwd: string;
36
+ from?: string;
37
+ latest?: boolean;
38
+ preset?: AgentRerunPreset;
39
+ environments?: string[];
40
+ labelFilters?: AgentLabelFilter[];
41
+ }) => Promise<AgentTestPlanContext | undefined>;