allure 3.20.1 → 3.21.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.
Files changed (41) hide show
  1. package/README.md +25 -1
  2. package/dist/commands/{agent.js → agents/index.js} +13 -109
  3. package/dist/commands/agents/lifecycle.d.ts +20 -0
  4. package/dist/commands/agents/lifecycle.js +91 -0
  5. package/dist/commands/{agent-run.d.ts → agents/run.d.ts} +1 -13
  6. package/dist/commands/{agent-run.js → agents/run.js} +12 -67
  7. package/dist/commands/commons/generate.d.ts +1 -0
  8. package/dist/commands/commons/generate.js +28 -2
  9. package/dist/commands/generate.d.ts +2 -0
  10. package/dist/commands/generate.js +19 -1
  11. package/dist/commands/index.d.ts +2 -1
  12. package/dist/commands/index.js +2 -1
  13. package/dist/commands/migrate.d.ts +6 -0
  14. package/dist/commands/migrate.js +15 -0
  15. package/dist/commands/open.d.ts +1 -0
  16. package/dist/commands/open.js +12 -2
  17. package/dist/commands/qualityGate.js +11 -1
  18. package/dist/commands/run.d.ts +4 -0
  19. package/dist/commands/run.js +27 -5
  20. package/dist/commands/slack.d.ts +3 -2
  21. package/dist/commands/slack.js +17 -5
  22. package/dist/commands/testopsPlan.js +4 -4
  23. package/dist/commands/watch.d.ts +1 -0
  24. package/dist/commands/watch.js +10 -1
  25. package/dist/index.js +30 -9
  26. package/dist/utils/allure2Hints.d.ts +8 -0
  27. package/dist/utils/allure2Hints.js +90 -0
  28. package/dist/utils/cleanOutput.d.ts +9 -0
  29. package/dist/utils/cleanOutput.js +62 -0
  30. package/dist/utils/fileSystem.d.ts +4 -1
  31. package/dist/utils/fileSystem.js +3 -3
  32. package/dist/utils/serverOptions.d.ts +5 -0
  33. package/dist/utils/serverOptions.js +4 -0
  34. package/dist/utils/updateNotifier.d.ts +6 -0
  35. package/dist/utils/updateNotifier.js +58 -0
  36. package/dist/utils/verbosity.d.ts +7 -0
  37. package/dist/utils/verbosity.js +32 -0
  38. package/package.json +28 -23
  39. /package/dist/commands/{agent-human-report.d.ts → agents/human-report.d.ts} +0 -0
  40. /package/dist/commands/{agent-human-report.js → agents/human-report.js} +0 -0
  41. /package/dist/commands/{agent.d.ts → agents/index.d.ts} +0 -0
package/README.md CHANGED
@@ -73,6 +73,22 @@ Set `ALLURE_LOG_LEVEL=debug` to include details such as selected tests and tempo
73
73
  the generic `LOG_LEVEL` environment variable. Use `--silent` to hide the nested test process output while keeping
74
74
  Allure lifecycle messages visible.
75
75
 
76
+ ### Verbosity flags
77
+
78
+ `-v/--verbose` and `-q/--quiet` are global flags accepted by every command (place them before `--` in `allure run`;
79
+ everything after `--` is passed to your test command untouched).
80
+
81
+ | Flag | Allure log level | `allure run` test process output |
82
+ | --- | --- | --- |
83
+ | _(none)_ | `ALLURE_LOG_LEVEL`, default `info` | printed |
84
+ | `--verbose`, `-v` | `verbose` | printed |
85
+ | `--quiet`, `-q` | `error` (errors only) | hidden, same as `--silent` |
86
+
87
+ - The flags override `ALLURE_LOG_LEVEL`. `--verbose` and `--quiet` cannot be combined.
88
+ - `--quiet` implies `--silent`. Logs are still collected into the report unless `--ignore-logs` is set.
89
+ - `--silent` and `--ignore-logs` keep their meaning and are independent of `--verbose`.
90
+ - A lone `allure -v` still prints the version.
91
+
76
92
  ### Running Tests In Agent Mode
77
93
 
78
94
  When you need agent-friendly markdown output for review, debugging, or scope validation, use the `agent` command:
@@ -103,7 +119,7 @@ option writes the agentic output directory.
103
119
 
104
120
  `allure agent` and `allure agent inspect` use `--report auto` by default. This writes the agent-readable artifacts and, when the stored visible result count is 1000 or fewer, also writes a single-file Awesome report at `awesome/index.html` inside the agent output directory. Runs above that threshold skip the human report to avoid excessive output, and the status is recorded in `index.md`, `manifest/run.json`, and `manifest/human-report.json`.
105
121
 
106
- Use `--report off` for agent-only artifacts, `--report awesome` to force the single-file Awesome report regardless of result count, or `--report config` to force the configured non-agent report plugins inside the agent output directory. Configured presentation or export plugins such as Dashboard or TestOps are otherwise ignored for agent runs.
122
+ Use `--report off` for agent-only artifacts, `--report awesome` to force the single-file Awesome report regardless of result count, or `--report config` to force the configured non-agent report plugins inside the agent output directory. Configured presentation or export plugins such as Dashboard or Allure TestOps are otherwise ignored for agent runs.
107
123
 
108
124
  If you need the human-readable report from the most recent agent run, first run `npx allure agent latest` when the output directory is unknown. Then check `<output>/manifest/human-report.json`; when its status is `generated`, open `<output>/<path>` from that manifest, usually `<output>/awesome/index.html`.
109
125
 
@@ -176,6 +192,14 @@ To check your installed version of Allure 3, use:
176
192
  npx allure --version
177
193
  ```
178
194
 
195
+ For direct interactive CLI invocations, Allure checks the npm registry for a newer version alongside the command.
196
+ Each eligible invocation makes one request with a one-second timeout; no update state is stored on disk. Missing
197
+ package metadata and network errors are silently ignored. The check is skipped for `allure agent`, help and version
198
+ output, quiet mode, CI, non-interactive terminals, and invocations through npm or Yarn. Disable it with `--no-update-notifier`
199
+ (for example, `allure --no-update-notifier generate ./allure-results`), or set `NO_UPDATE_NOTIFIER` for the environment.
200
+ Numbered prerelease versions (such as `3.21.0-beta.2`) check their matching npm dist-tag instead of the stable `latest`
201
+ tag. Unrecognized version formats are silently skipped.
202
+
179
203
  ## Configuration
180
204
 
181
205
  Allure 3 uses an `allurerc.ts`, `allurerc.mts`, `allurerc.cts`, `allurerc.mjs`, or `allurerc.js` configuration file to manage report settings, including the report name, output directory, and plugin options.
@@ -1,25 +1,16 @@
1
1
  import * as console from "node:console";
2
- import { randomUUID } from "node:crypto";
3
- import { mkdir, mkdtemp, realpath, writeFile } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { dirname, join, resolve } from "node:path";
2
+ import { mkdir, realpath, writeFile } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
6
4
  import process, { exit } from "node:process";
7
- import { AGENT_FINDING_CATEGORIES, AGENT_FINDING_SEVERITIES, AGENT_TASK_MAP_HELP, AGENT_TEST_STATUSES, AgentExpectationUsageError, assertExplicitAgentOutputDirIsSafe, buildAgentInlineExpectations, buildAgentQueryPayload, cleanupAgentRunState, cleanupStaleAgentRunStates, createAgentCapabilities, formatAgentOutputLinks, isAgentExpectationUsageError, isAgentTaskMapHelpRequest, isAgentUsageError, loadAgentOutput, normalizeAgentQueryLimit, normalizeAgentQueryView, normalizeAgentRerunPreset, normalizeRepeatedEnumValues, normalizeRepeatedStringValues, parseAgentLabelFilters, readLatestAgentState, resolveAgentSelectionOutputDir, resolveAgentStateDir, selectAgentTestPlan, validateAgentExpectationsFile, writeAgentRunState, writeInvalidAgentExpectationOutput, } from "@allurereport/plugin-agent";
5
+ import { AGENT_FINDING_CATEGORIES, AGENT_FINDING_SEVERITIES, AGENT_TASK_MAP_HELP, AGENT_TEST_STATUSES, AgentExpectationUsageError, assertExplicitAgentOutputDirIsSafe, buildAgentInlineExpectations, buildAgentQueryPayload, createAgentCapabilities, isAgentExpectationUsageError, isAgentTaskMapHelpRequest, isAgentUsageError, loadAgentOutput, normalizeAgentQueryLimit, normalizeAgentQueryView, normalizeAgentRerunPreset, normalizeRepeatedEnumValues, normalizeRepeatedStringValues, parseAgentLabelFilters, readLatestAgentState, resolveAgentSelectionOutputDir, resolveAgentStateDir, selectAgentTestPlan, validateAgentExpectationsFile, } from "@allurereport/plugin-agent";
8
6
  import { Command, Option, UsageError } from "clipanion";
9
- import { parseRunCommand } from "../utils/resultsPatterns.js";
7
+ import { parseRunCommand } from "../../utils/resultsPatterns.js";
8
+ import { formatAgentCommand, formatAgentInspectCommand, printAgentOutputLinks, writeInvalidAgentExpectationRun, } from "./lifecycle.js";
10
9
  export { AGENT_TASK_MAP_HELP, createAgentCapabilities, isAgentTaskMapHelpRequest };
11
10
  const readOptionalString = (value) => (typeof value === "string" ? value : undefined);
12
11
  const readOptionalBoolean = (value) => value === true;
13
12
  const readOptionalStringArray = (value) => (Array.isArray(value) ? value : undefined);
14
- const formatAgentCommand = (args) => args.join(" ");
15
13
  const AGENT_HUMAN_REPORT_MODES = ["auto", "off", "awesome", "config"];
16
- const formatAgentInspectCommand = (params) => [
17
- "allure",
18
- "agent",
19
- "inspect",
20
- ...(params.dumps ?? []).flatMap((dump) => ["--dump", dump]),
21
- ...(params.resultsDir ?? []),
22
- ].join(" ");
23
14
  const buildInlineExpectationsFromOptions = (options) => buildAgentInlineExpectations({
24
15
  goal: options.goal,
25
16
  taskId: options.taskId,
@@ -34,53 +25,6 @@ const buildInlineExpectationsFromOptions = (options) => buildAgentInlineExpectat
34
25
  expectAttachments: options.expectAttachments,
35
26
  expectAttachmentFilters: readOptionalStringArray(options.expectAttachmentFilters),
36
27
  });
37
- const printAgentOutputLinks = (outputDir) => {
38
- for (const line of formatAgentOutputLinks(outputDir)) {
39
- console.log(line);
40
- }
41
- };
42
- const persistAgentRunState = async (value) => {
43
- try {
44
- await writeAgentRunState(value);
45
- }
46
- catch (error) {
47
- console.error(`Could not update agent state in ${resolveAgentStateDir(value.cwd)}: ${error.message}`);
48
- }
49
- };
50
- const logAgentCleanupFailures = (failures) => {
51
- for (const failure of failures) {
52
- console.error(`Could not clean stale agent output ${failure.state.outputDir}: ${failure.error.message}`);
53
- }
54
- };
55
- const logAgentOrphanCleanupFailures = (failures) => {
56
- for (const failure of failures) {
57
- console.error(`Could not clean stale agent output ${failure.outputDir}: ${failure.error.message}`);
58
- }
59
- };
60
- const cleanupManagedAgentOutputs = async (params) => {
61
- try {
62
- const result = await cleanupAgentRunState({
63
- cwd: params.cwd,
64
- currentRunId: params.runId,
65
- keepManagedRuns: params.managedOutput ? 1 : 0,
66
- });
67
- logAgentCleanupFailures(result.failed);
68
- }
69
- catch (error) {
70
- console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
71
- }
72
- try {
73
- const staleResult = await cleanupStaleAgentRunStates({
74
- cwd: params.cwd,
75
- currentRunId: params.runId,
76
- });
77
- logAgentCleanupFailures(staleResult.failed);
78
- logAgentOrphanCleanupFailures(staleResult.orphaned.failed);
79
- }
80
- catch (error) {
81
- console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
82
- }
83
- };
84
28
  const agentEnvironmentOption = () => Option.String("--environment,--env", {
85
29
  description: "Force specific environment ID to all tests in the run. Given environment has higher priority than the one defined in the config file (default: empty string)",
86
30
  });
@@ -238,7 +182,7 @@ export class AgentCommand extends Command {
238
182
  output,
239
183
  expectations,
240
184
  });
241
- const { executeAgentMode } = await import("./agent-run.js");
185
+ const { executeAgentMode } = await import("./run.js");
242
186
  await executeAgentMode({
243
187
  configPath,
244
188
  cwd: configuredCwd,
@@ -263,33 +207,13 @@ export class AgentCommand extends Command {
263
207
  throwCliUsageError(error);
264
208
  }
265
209
  const expectationError = error;
266
- const cwd = await realpath(configuredCwd ?? process.cwd());
267
- const runId = randomUUID();
268
- const managedOutput = !output;
269
- const outputDir = output ? resolve(cwd, output) : await mkdtemp(join(tmpdir(), "allure-agent-"));
270
210
  const commandString = formatAgentCommand(args);
271
- const { generatedAt } = await writeInvalidAgentExpectationOutput({
272
- outputDir,
211
+ await writeInvalidAgentExpectationRun({
212
+ configuredCwd,
213
+ output,
273
214
  command: commandString,
274
215
  error: expectationError,
275
216
  });
276
- const generatedAtMs = Date.parse(generatedAt);
277
- const generatedAtTimestamp = Number.isFinite(generatedAtMs) ? generatedAtMs : Date.now();
278
- await persistAgentRunState({
279
- runId,
280
- cwd,
281
- outputDir,
282
- managedOutput,
283
- command: commandString,
284
- startedAt: generatedAtTimestamp,
285
- finishedAt: generatedAtTimestamp,
286
- status: "finished",
287
- exitCode: 1,
288
- pid: process.pid,
289
- });
290
- await cleanupManagedAgentOutputs({ cwd, runId, managedOutput });
291
- printAgentOutputLinks(outputDir);
292
- console.error(expectationError.message);
293
217
  exit(1);
294
218
  }
295
219
  }
@@ -428,7 +352,7 @@ export class AgentInspectCommand extends Command {
428
352
  output,
429
353
  expectations,
430
354
  });
431
- const { executeAgentInspectMode } = await import("./agent-run.js");
355
+ const { executeAgentInspectMode } = await import("./run.js");
432
356
  await executeAgentInspectMode({
433
357
  configPath,
434
358
  cwd: configuredCwd,
@@ -452,33 +376,13 @@ export class AgentInspectCommand extends Command {
452
376
  throwCliUsageError(error);
453
377
  }
454
378
  const expectationError = error;
455
- const cwd = await realpath(configuredCwd ?? process.cwd());
456
- const runId = randomUUID();
457
- const managedOutput = !output;
458
- const outputDir = output ? resolve(cwd, output) : await mkdtemp(join(tmpdir(), "allure-agent-"));
459
379
  const commandString = formatAgentInspectCommand({ dumps, resultsDir });
460
- const { generatedAt } = await writeInvalidAgentExpectationOutput({
461
- outputDir,
380
+ await writeInvalidAgentExpectationRun({
381
+ configuredCwd,
382
+ output,
462
383
  command: commandString,
463
384
  error: expectationError,
464
385
  });
465
- const generatedAtMs = Date.parse(generatedAt);
466
- const generatedAtTimestamp = Number.isFinite(generatedAtMs) ? generatedAtMs : Date.now();
467
- await persistAgentRunState({
468
- runId,
469
- cwd,
470
- outputDir,
471
- managedOutput,
472
- command: commandString,
473
- startedAt: generatedAtTimestamp,
474
- finishedAt: generatedAtTimestamp,
475
- status: "finished",
476
- exitCode: 1,
477
- pid: process.pid,
478
- });
479
- await cleanupManagedAgentOutputs({ cwd, runId, managedOutput });
480
- printAgentOutputLinks(outputDir);
481
- console.error(expectationError.message);
482
386
  exit(1);
483
387
  }
484
388
  }
@@ -0,0 +1,20 @@
1
+ import { writeAgentRunState, type AgentExpectationUsageError } from "@allurereport/plugin-agent";
2
+ export declare const formatAgentCommand: (args: string[]) => string;
3
+ export declare const formatAgentInspectCommand: (params: {
4
+ dumps?: string[];
5
+ resultsDir?: string[];
6
+ }) => string;
7
+ export declare const resolveAgentOutputDir: (cwd: string, output?: string) => string | Promise<string>;
8
+ export declare const printAgentOutputLinks: (outputDir: string) => void;
9
+ export declare const persistAgentRunState: (value: Parameters<typeof writeAgentRunState>[0]) => Promise<void>;
10
+ export declare const cleanupManagedAgentOutputs: (params: {
11
+ cwd: string;
12
+ runId: string;
13
+ managedOutput: boolean;
14
+ }) => Promise<void>;
15
+ export declare const writeInvalidAgentExpectationRun: (params: {
16
+ configuredCwd?: string;
17
+ output?: string;
18
+ command: string;
19
+ error: AgentExpectationUsageError;
20
+ }) => Promise<void>;
@@ -0,0 +1,91 @@
1
+ import * as console from "node:console";
2
+ import { randomUUID } from "node:crypto";
3
+ import { mkdtemp, realpath } 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 { cleanupAgentRunState, cleanupStaleAgentRunStates, formatAgentOutputLinks, resolveAgentStateDir, writeAgentRunState, writeInvalidAgentExpectationOutput, } from "@allurereport/plugin-agent";
8
+ export const formatAgentCommand = (args) => args.join(" ");
9
+ export const formatAgentInspectCommand = (params) => [
10
+ "allure",
11
+ "agent",
12
+ "inspect",
13
+ ...(params.dumps ?? []).flatMap((dump) => ["--dump", dump]),
14
+ ...(params.resultsDir ?? []),
15
+ ].join(" ");
16
+ export const resolveAgentOutputDir = (cwd, output) => output ? resolve(cwd, output) : mkdtemp(join(tmpdir(), "allure-agent-"));
17
+ export const printAgentOutputLinks = (outputDir) => {
18
+ for (const line of formatAgentOutputLinks(outputDir)) {
19
+ console.log(line);
20
+ }
21
+ };
22
+ export const persistAgentRunState = async (value) => {
23
+ try {
24
+ await writeAgentRunState(value);
25
+ }
26
+ catch (error) {
27
+ console.error(`Could not update agent state in ${resolveAgentStateDir(value.cwd)}: ${error.message}`);
28
+ }
29
+ };
30
+ const logAgentCleanupFailures = (failures) => {
31
+ for (const failure of failures) {
32
+ console.error(`Could not clean stale agent output ${failure.state.outputDir}: ${failure.error.message}`);
33
+ }
34
+ };
35
+ const logAgentOrphanCleanupFailures = (failures) => {
36
+ for (const failure of failures) {
37
+ console.error(`Could not clean stale agent output ${failure.outputDir}: ${failure.error.message}`);
38
+ }
39
+ };
40
+ export const cleanupManagedAgentOutputs = async (params) => {
41
+ try {
42
+ const result = await cleanupAgentRunState({
43
+ cwd: params.cwd,
44
+ currentRunId: params.runId,
45
+ keepManagedRuns: params.managedOutput ? 1 : 0,
46
+ });
47
+ logAgentCleanupFailures(result.failed);
48
+ }
49
+ catch (error) {
50
+ console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
51
+ }
52
+ try {
53
+ const staleResult = await cleanupStaleAgentRunStates({
54
+ cwd: params.cwd,
55
+ currentRunId: params.runId,
56
+ });
57
+ logAgentCleanupFailures(staleResult.failed);
58
+ logAgentOrphanCleanupFailures(staleResult.orphaned.failed);
59
+ }
60
+ catch (error) {
61
+ console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
62
+ }
63
+ };
64
+ export const writeInvalidAgentExpectationRun = async (params) => {
65
+ const cwd = await realpath(params.configuredCwd ?? process.cwd());
66
+ const runId = randomUUID();
67
+ const managedOutput = !params.output;
68
+ const outputDir = await resolveAgentOutputDir(cwd, params.output);
69
+ const { generatedAt } = await writeInvalidAgentExpectationOutput({
70
+ outputDir,
71
+ command: params.command,
72
+ error: params.error,
73
+ });
74
+ const generatedAtMs = Date.parse(generatedAt);
75
+ const generatedAtTimestamp = Number.isFinite(generatedAtMs) ? generatedAtMs : Date.now();
76
+ await persistAgentRunState({
77
+ runId,
78
+ cwd,
79
+ outputDir,
80
+ managedOutput,
81
+ command: params.command,
82
+ startedAt: generatedAtTimestamp,
83
+ finishedAt: generatedAtTimestamp,
84
+ status: "finished",
85
+ exitCode: 1,
86
+ pid: process.pid,
87
+ });
88
+ await cleanupManagedAgentOutputs({ cwd, runId, managedOutput });
89
+ printAgentOutputLinks(outputDir);
90
+ console.error(params.error.message);
91
+ };
@@ -1,21 +1,9 @@
1
- import { writeAgentRunState, type AgentExpectationsInput, type AgentHumanReportMode } from "@allurereport/plugin-agent";
2
- export declare const formatAgentCommand: (args: string[]) => string;
3
- export declare const formatAgentInspectCommand: (params: {
4
- dumps?: string[];
5
- resultsDir?: string[];
6
- }) => string;
7
- export declare const printAgentOutputLinks: (outputDir: string) => void;
1
+ import { type AgentExpectationsInput, type AgentHumanReportMode } from "@allurereport/plugin-agent";
8
2
  export declare const printAgentRunStart: (outputDir: string, commandString: string) => void;
9
3
  export declare const printAgentRunSummary: (outputDir: string, options?: {
10
4
  durationMs?: number;
11
5
  rerunCommand?: string;
12
6
  }) => Promise<void>;
13
- export declare const persistAgentRunState: (value: Parameters<typeof writeAgentRunState>[0]) => Promise<void>;
14
- export declare const cleanupManagedAgentOutputs: (params: {
15
- cwd: string;
16
- runId: string;
17
- managedOutput: boolean;
18
- }) => Promise<void>;
19
7
  export type ExecuteAgentModeParams = {
20
8
  configPath?: string;
21
9
  cwd?: string;
@@ -1,30 +1,17 @@
1
1
  import * as console from "node:console";
2
2
  import { randomUUID } from "node:crypto";
3
- import { mkdtemp, realpath, rm } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join, resolve } from "node:path";
3
+ import { realpath, rm } from "node:fs/promises";
4
+ import { resolve } from "node:path";
6
5
  import process, { exit } from "node:process";
7
6
  import { AllureReport, isFileNotFoundError, readConfig } from "@allurereport/core";
8
- import { createAgentTestPlanContext, AgentUsageError, assertExplicitAgentOutputDirIsSafe, formatAgentOutputLinks, formatAgentRunSummary, isPathInside, loadAgentOutput, normalizeAgentRerunPreset, parseAgentLabelFilters, cleanupAgentRunState, cleanupStaleAgentRunStates, resolveAgentStateDir, writeAgentRunState, } from "@allurereport/plugin-agent";
9
- import { normalizeCommandEnvironmentOptions, resolveCommandEnvironment } from "../utils/environment.js";
10
- import { createChildAllureCliEnvironment, getActiveAllureCliCommand } from "../utils/execution-context.js";
11
- import { findFilesByGlobs } from "../utils/fileSystem.js";
12
- import { resolveAndFindResultsDirs, resolveResultsPatterns } from "../utils/resultsPatterns.js";
13
- import { createAgentHumanReportConfig } from "./agent-human-report.js";
14
- import { executeAllureRun, executeNestedAllureCommand } from "./commons/run.js";
15
- export const formatAgentCommand = (args) => args.join(" ");
16
- export const formatAgentInspectCommand = (params) => [
17
- "allure",
18
- "agent",
19
- "inspect",
20
- ...(params.dumps ?? []).flatMap((dump) => ["--dump", dump]),
21
- ...(params.resultsDir ?? []),
22
- ].join(" ");
23
- export const printAgentOutputLinks = (outputDir) => {
24
- for (const line of formatAgentOutputLinks(outputDir)) {
25
- console.log(line);
26
- }
27
- };
7
+ import { createAgentTestPlanContext, AgentUsageError, assertExplicitAgentOutputDirIsSafe, formatAgentRunSummary, isPathInside, loadAgentOutput, normalizeAgentRerunPreset, parseAgentLabelFilters, } from "@allurereport/plugin-agent";
8
+ import { normalizeCommandEnvironmentOptions, resolveCommandEnvironment } from "../../utils/environment.js";
9
+ import { createChildAllureCliEnvironment, getActiveAllureCliCommand } from "../../utils/execution-context.js";
10
+ import { findFilesByGlobs } from "../../utils/fileSystem.js";
11
+ import { resolveAndFindResultsDirs, resolveResultsPatterns } from "../../utils/resultsPatterns.js";
12
+ import { executeAllureRun, executeNestedAllureCommand } from "../commons/run.js";
13
+ import { createAgentHumanReportConfig } from "./human-report.js";
14
+ import { cleanupManagedAgentOutputs, formatAgentCommand, formatAgentInspectCommand, persistAgentRunState, printAgentOutputLinks, resolveAgentOutputDir, } from "./lifecycle.js";
28
15
  export const printAgentRunStart = (outputDir, commandString) => {
29
16
  console.log(`agent output: ${outputDir}`);
30
17
  console.log(commandString);
@@ -48,48 +35,6 @@ export const printAgentRunSummary = async (outputDir, options = {}) => {
48
35
  printAgentOutputLinks(outputDir);
49
36
  }
50
37
  };
51
- export const persistAgentRunState = async (value) => {
52
- try {
53
- await writeAgentRunState(value);
54
- }
55
- catch (error) {
56
- console.error(`Could not update agent state in ${resolveAgentStateDir(value.cwd)}: ${error.message}`);
57
- }
58
- };
59
- const logAgentCleanupFailures = (failures) => {
60
- for (const failure of failures) {
61
- console.error(`Could not clean stale agent output ${failure.state.outputDir}: ${failure.error.message}`);
62
- }
63
- };
64
- const logAgentOrphanCleanupFailures = (failures) => {
65
- for (const failure of failures) {
66
- console.error(`Could not clean stale agent output ${failure.outputDir}: ${failure.error.message}`);
67
- }
68
- };
69
- export const cleanupManagedAgentOutputs = async (params) => {
70
- try {
71
- const result = await cleanupAgentRunState({
72
- cwd: params.cwd,
73
- currentRunId: params.runId,
74
- keepManagedRuns: params.managedOutput ? 1 : 0,
75
- });
76
- logAgentCleanupFailures(result.failed);
77
- }
78
- catch (error) {
79
- console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
80
- }
81
- try {
82
- const staleResult = await cleanupStaleAgentRunStates({
83
- cwd: params.cwd,
84
- currentRunId: params.runId,
85
- });
86
- logAgentCleanupFailures(staleResult.failed);
87
- logAgentOrphanCleanupFailures(staleResult.orphaned.failed);
88
- }
89
- catch (error) {
90
- console.error(`Could not clean agent state in ${resolveAgentStateDir(params.cwd)}: ${error.message}`);
91
- }
92
- };
93
38
  export const executeAgentMode = async (params) => {
94
39
  const { configPath, cwd: configuredCwd, output, expectations, inlineExpectations, environment, environmentName, silent, rerunFrom, rerunLatest, rerunPreset, rerunEnvironments, rerunLabels, reportMode, args, resultsPatterns: cliResultsPatterns = [], } = params;
95
40
  const command = args[0];
@@ -131,7 +76,7 @@ export const executeAgentMode = async (params) => {
131
76
  }
132
77
  const runId = randomUUID();
133
78
  const managedOutput = !output;
134
- const outputDir = output ? resolve(cwd, output) : await mkdtemp(join(tmpdir(), "allure-agent-"));
79
+ const outputDir = await resolveAgentOutputDir(cwd, output);
135
80
  const expectationsPath = expectations ? resolve(cwd, expectations) : undefined;
136
81
  const environmentOptions = {
137
82
  environment,
@@ -256,7 +201,7 @@ export const executeAgentInspectMode = async (params) => {
256
201
  }
257
202
  const runId = randomUUID();
258
203
  const managedOutput = !output;
259
- const outputDir = output ? resolve(cwd, output) : await mkdtemp(join(tmpdir(), "allure-agent-"));
204
+ const outputDir = await resolveAgentOutputDir(cwd, output);
260
205
  const expectationsPath = expectations ? resolve(cwd, expectations) : undefined;
261
206
  const commandString = formatAgentInspectCommand({ dumps: dumpFiles, resultsDir: resultDirectories });
262
207
  const hiddenLabels = hideLabels?.length ? hideLabels : undefined;
@@ -10,4 +10,5 @@ export declare const generate: (params: {
10
10
  resultsDir?: string[];
11
11
  dump?: string[];
12
12
  collectSummary?: boolean;
13
+ clean?: boolean;
13
14
  }) => Promise<GenerateResult | undefined>;
@@ -1,8 +1,9 @@
1
- import { exit } from "node:process";
1
+ import { cwd as processCwd, exit } from "node:process";
2
2
  import { createReportContext } from "@allurereport/ci";
3
3
  import { AllureReport, filterFailedQualityGateResults, stringifyQualityGateResults } from "@allurereport/core";
4
4
  import { KnownError } from "@allurereport/service";
5
- import { red } from "yoctocolors";
5
+ import { red, yellow } from "yoctocolors";
6
+ import { cleanOutputDirectory, isOutputDirectoryNotEmpty } from "../../utils/cleanOutput.js";
6
7
  import { findFilesByGlobs } from "../../utils/fileSystem.js";
7
8
  import { logError } from "../../utils/logs.js";
8
9
  import { resolveAndFindResultsDirs, resolveResultsPatterns } from "../../utils/resultsPatterns.js";
@@ -19,6 +20,31 @@ export const generate = async (params) => {
19
20
  exit(1);
20
21
  return;
21
22
  }
23
+ if (params.clean) {
24
+ try {
25
+ const globalAttachments = await findFilesByGlobs(params.config.cwd ?? processCwd(), params.config.globalAttachments ?? [], { dot: false, windowsPathsNoEscape: false });
26
+ await cleanOutputDirectory({
27
+ output: params.config.output,
28
+ cwd: params.cwd,
29
+ resultsDirs: resultDirectories,
30
+ inputs: [
31
+ ...dumpFiles,
32
+ ...globalAttachments,
33
+ params.config.historyPath,
34
+ params.config.resolutions?.knownIssuesPath,
35
+ ].filter((path) => !!path),
36
+ });
37
+ }
38
+ catch (error) {
39
+ console.error(red(error instanceof Error ? error.message : String(error)));
40
+ exit(1);
41
+ return;
42
+ }
43
+ }
44
+ if (!params.clean && params.config.output && (await isOutputDirectoryNotEmpty(params.cwd, params.config.output))) {
45
+ console.warn(yellow(`The output directory "${params.config.output}" is not empty. Files of a previous report may break the layout ` +
46
+ "of the new one. Use the --clean option to remove the directory before generating."));
47
+ }
22
48
  try {
23
49
  const allureReport = new AllureReport(params.config);
24
50
  await allureReport.restoreState(Array.from(dumpFiles));
@@ -8,8 +8,10 @@ export declare class GenerateCommand extends Command {
8
8
  cwd: string | undefined;
9
9
  reportName: string | undefined;
10
10
  dump: string[] | undefined;
11
+ clean: boolean | undefined;
11
12
  open: boolean | undefined;
12
13
  port: string | undefined;
14
+ host: string | undefined;
13
15
  historyLimit: string | undefined;
14
16
  historyBaseUrl: string | undefined;
15
17
  hideLabels: string[] | undefined;
@@ -2,6 +2,7 @@ import { cwd as processCwd } from "node:process";
2
2
  import { readConfig } from "@allurereport/core";
3
3
  import { serve } from "@allurereport/static-server";
4
4
  import { Command, Option } from "clipanion";
5
+ import { serverOptionsFromConfig } from "../utils/serverOptions.js";
5
6
  import { generate } from "./commons/generate.js";
6
7
  export class GenerateCommand extends Command {
7
8
  constructor() {
@@ -26,12 +27,19 @@ export class GenerateCommand extends Command {
26
27
  "Allure loads the matched archives before generating the report. " +
27
28
  "This option can be specified multiple times.",
28
29
  });
30
+ this.clean = Option.Boolean("--clean", {
31
+ description: "Remove the output directory before generating the report (default: false). " +
32
+ "Refuses to remove the working directory, the home directory, a filesystem root, or the results directories",
33
+ });
29
34
  this.open = Option.Boolean("--open", {
30
35
  description: "Open the report in the default browser after generation (default: false)",
31
36
  });
32
37
  this.port = Option.String("--port", {
33
38
  description: "The port to serve the reports on. If not set, the server starts on a random port",
34
39
  });
40
+ this.host = Option.String("--host", {
41
+ description: "The host (network interface) to serve the reports on, e.g. 127.0.0.1 or 0.0.0.0 (default: all interfaces)",
42
+ });
35
43
  this.historyLimit = Option.String("--history-limit", {
36
44
  description: "Limits the number of history entries to keep (default: unlimited)",
37
45
  });
@@ -54,6 +62,7 @@ export class GenerateCommand extends Command {
54
62
  output: this.output,
55
63
  open: this.open,
56
64
  port: this.port,
65
+ host: this.host,
57
66
  hideLabels,
58
67
  historyLimit: this.historyLimit !== undefined ? parseInt(this.historyLimit, 10) : undefined,
59
68
  ...(this.historyBaseUrl !== undefined ? { historyBaseUrl: this.historyBaseUrl } : {}),
@@ -64,13 +73,14 @@ export class GenerateCommand extends Command {
64
73
  resultsDir: this.resultsDir,
65
74
  cwd,
66
75
  config,
76
+ clean: this.clean,
67
77
  });
68
78
  if (!result) {
69
79
  return;
70
80
  }
71
81
  if (config.open) {
72
82
  await serve({
73
- port: config.port ? parseInt(config.port, 10) : undefined,
83
+ ...serverOptionsFromConfig(config),
74
84
  servePath: config.output,
75
85
  open: true,
76
86
  });
@@ -84,11 +94,19 @@ GenerateCommand.usage = Command.Usage({
84
94
  details: "This command generates a report from the provided Allure Results directories. " +
85
95
  "When a quality gate is configured, the command validates the loaded results and finishes writing the report or dump before returning its status.",
86
96
  examples: [
97
+ [
98
+ "generate ./allure-results --open --host 0.0.0.0",
99
+ "Generate a report and serve it on all network interfaces after generation",
100
+ ],
87
101
  ["generate ./allure-results", "Generate a report from the ./allure-results directory"],
88
102
  [
89
103
  "generate ./allure-results --output custom-report",
90
104
  "Generate a report from the ./allure-results directory to the custom-report directory",
91
105
  ],
106
+ [
107
+ "generate ./allure-results --clean",
108
+ "Remove the existing report directory before generating a fresh report from ./allure-results",
109
+ ],
92
110
  [
93
111
  "generate --dump=windows.zip --dump=macos.zip ./allure-results",
94
112
  "Generate a report using data from windows.zip and macos.zip archives and using results from the ./allure-results directory",
@@ -2,7 +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
+ export * from "./agents/index.js";
6
6
  export * from "./awesome.js";
7
7
  export * from "./csv.js";
8
8
  export * from "./check.js";
@@ -20,3 +20,4 @@ export * from "./dashboard.js";
20
20
  export * from "./results/index.js";
21
21
  export * from "./jira/index.js";
22
22
  export * from "./gitlab/index.js";
23
+ export * from "./migrate.js";
@@ -2,7 +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
+ export * from "./agents/index.js";
6
6
  export * from "./awesome.js";
7
7
  export * from "./csv.js";
8
8
  export * from "./check.js";
@@ -20,3 +20,4 @@ export * from "./dashboard.js";
20
20
  export * from "./results/index.js";
21
21
  export * from "./jira/index.js";
22
22
  export * from "./gitlab/index.js";
23
+ export * from "./migrate.js";
@@ -0,0 +1,6 @@
1
+ import { Command } from "clipanion";
2
+ export declare class MigrateCommand extends Command {
3
+ static paths: string[][];
4
+ static usage: import("clipanion").Usage;
5
+ execute(): Promise<void>;
6
+ }
@@ -0,0 +1,15 @@
1
+ import { Command } from "clipanion";
2
+ import { renderAllure2CommandMap } from "../utils/allure2Hints.js";
3
+ export class MigrateCommand extends Command {
4
+ async execute() {
5
+ this.context.stdout.write(`${renderAllure2CommandMap()}\n`);
6
+ }
7
+ }
8
+ MigrateCommand.paths = [["migrate"]];
9
+ MigrateCommand.usage = Command.Usage({
10
+ category: "Reports",
11
+ description: "Shows how Allure 2 commands map to Allure 3",
12
+ details: "This command prints the Allure 3 equivalents of the Allure 2 commands and options " +
13
+ "(serve, generate --clean, --host, --profile, etc.) for users who are moving from Allure 2.",
14
+ examples: [["migrate", "Print the Allure 2 to Allure 3 command mapping"]],
15
+ });