allure 3.18.0 → 3.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/commons/generate.d.ts +6 -1
- package/dist/commands/commons/generate.js +18 -0
- package/dist/commands/gitlab/generate.d.ts +15 -0
- package/dist/commands/gitlab/generate.js +137 -0
- package/dist/commands/gitlab/index.d.ts +1 -0
- package/dist/commands/gitlab/index.js +1 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/log.d.ts +1 -0
- package/dist/commands/log.js +4 -0
- package/dist/index.js +2 -1
- package/package.json +21 -21
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { type ReportContext } from "@allurereport/ci";
|
|
1
2
|
import type { FullConfig } from "@allurereport/core";
|
|
3
|
+
export type GenerateResult = {
|
|
4
|
+
summary?: ReportContext;
|
|
5
|
+
};
|
|
2
6
|
export declare const generate: (params: {
|
|
3
7
|
cwd: string;
|
|
4
8
|
config: FullConfig;
|
|
5
9
|
resultsDir?: string[];
|
|
6
10
|
dump?: string[];
|
|
7
|
-
|
|
11
|
+
collectSummary?: boolean;
|
|
12
|
+
}) => Promise<GenerateResult | undefined>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { exit } from "node:process";
|
|
2
|
+
import { createReportContext } from "@allurereport/ci";
|
|
2
3
|
import { AllureReport } from "@allurereport/core";
|
|
3
4
|
import { KnownError } from "@allurereport/service";
|
|
4
5
|
import { red } from "yoctocolors";
|
|
@@ -26,6 +27,23 @@ export const generate = async (params) => {
|
|
|
26
27
|
await allureReport.readDirectory(dir);
|
|
27
28
|
}
|
|
28
29
|
await allureReport.done();
|
|
30
|
+
if (!params.collectSummary) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const result = {};
|
|
34
|
+
try {
|
|
35
|
+
const summary = await createReportContext(params.config.output, {
|
|
36
|
+
onError: (message) => console.warn(message),
|
|
37
|
+
});
|
|
38
|
+
if (!summary.testResults && summary.reports.length === 0) {
|
|
39
|
+
throw new Error("no report context data found");
|
|
40
|
+
}
|
|
41
|
+
result.summary = summary;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.warn(`Report summary skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
29
47
|
}
|
|
30
48
|
catch (error) {
|
|
31
49
|
if (error instanceof KnownError) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from "clipanion";
|
|
2
|
+
export declare class GitlabGenerateCommand extends Command {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
static usage: import("clipanion").Usage;
|
|
5
|
+
resultsDir: string[];
|
|
6
|
+
config: string | undefined;
|
|
7
|
+
output: string | undefined;
|
|
8
|
+
reportName: string | undefined;
|
|
9
|
+
dump: string[] | undefined;
|
|
10
|
+
historyPath: string | undefined;
|
|
11
|
+
historyLimit: string | undefined;
|
|
12
|
+
historyBaseUrl: string | undefined;
|
|
13
|
+
gitlabToken: string | undefined;
|
|
14
|
+
execute(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { cwd as processCwd } from "node:process";
|
|
4
|
+
import { restoreGitlabHistory, upsertGitlabJobNote, detect } from "@allurereport/ci";
|
|
5
|
+
import { readConfig } from "@allurereport/core";
|
|
6
|
+
import { CiType } from "@allurereport/core-api";
|
|
7
|
+
import { Command, Option } from "clipanion";
|
|
8
|
+
import { generate } from "../commons/generate.js";
|
|
9
|
+
const DEFAULT_HISTORY_LIMIT = 100;
|
|
10
|
+
const isDecimalString = (value) => /^[0-9]+$/.test(value);
|
|
11
|
+
const parseHistoryLimit = (value) => {
|
|
12
|
+
if (typeof value === "string") {
|
|
13
|
+
if (!isDecimalString(value)) {
|
|
14
|
+
return DEFAULT_HISTORY_LIMIT;
|
|
15
|
+
}
|
|
16
|
+
const parsed = Number(value);
|
|
17
|
+
return Number.isFinite(parsed) && Number.isInteger(parsed) && parsed >= 0 ? parsed : DEFAULT_HISTORY_LIMIT;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === "number") {
|
|
20
|
+
return Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : DEFAULT_HISTORY_LIMIT;
|
|
21
|
+
}
|
|
22
|
+
return DEFAULT_HISTORY_LIMIT;
|
|
23
|
+
};
|
|
24
|
+
const reportBaseUrl = (historyBaseUrl, output) => {
|
|
25
|
+
const gitlab = detect();
|
|
26
|
+
const isGitlabCiDescriptor = (ci) => ci.type === CiType.Gitlab;
|
|
27
|
+
if (!isGitlabCiDescriptor(gitlab)) {
|
|
28
|
+
throw new Error("GitLab CI environment was not detected");
|
|
29
|
+
}
|
|
30
|
+
if (isAbsolute(output)) {
|
|
31
|
+
const projectDirectory = resolve(gitlab.projectDirectory);
|
|
32
|
+
const absoluteOutput = resolve(output);
|
|
33
|
+
if (absoluteOutput !== projectDirectory && !absoluteOutput.startsWith(join(projectDirectory, sep))) {
|
|
34
|
+
throw new Error("Absolute output path must be within CI_PROJECT_DIR");
|
|
35
|
+
}
|
|
36
|
+
output = relative(projectDirectory, absoluteOutput).split(sep).join("/");
|
|
37
|
+
}
|
|
38
|
+
return historyBaseUrl || `${gitlab.jobArtifactsUrlBase}/${output}`;
|
|
39
|
+
};
|
|
40
|
+
export class GitlabGenerateCommand extends Command {
|
|
41
|
+
constructor() {
|
|
42
|
+
super(...arguments);
|
|
43
|
+
this.resultsDir = Option.Rest({
|
|
44
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
45
|
+
});
|
|
46
|
+
this.config = Option.String("--config,-c", {
|
|
47
|
+
description: "The path to Allure config file",
|
|
48
|
+
});
|
|
49
|
+
this.output = Option.String("--output,-o", {
|
|
50
|
+
description: "The output directory name. Absolute paths are accepted as well (default: allure-report)",
|
|
51
|
+
});
|
|
52
|
+
this.reportName = Option.String("--report-name,--name", {
|
|
53
|
+
description: "The report name (default: Allure Report)",
|
|
54
|
+
});
|
|
55
|
+
this.dump = Option.Array("--dump", {
|
|
56
|
+
description: "Path or pattern that matches one or more archives created by `allure run --dump ...`. " +
|
|
57
|
+
"Allure loads the matched archives before generating the report. " +
|
|
58
|
+
"This option can be specified multiple times.",
|
|
59
|
+
});
|
|
60
|
+
this.historyPath = Option.String("--history-path", {
|
|
61
|
+
description: "History file path",
|
|
62
|
+
});
|
|
63
|
+
this.historyLimit = Option.String("--history-limit", {
|
|
64
|
+
description: "Limits the number of history entries to keep (default: 100)",
|
|
65
|
+
});
|
|
66
|
+
this.historyBaseUrl = Option.String("--history-base-url", {
|
|
67
|
+
description: "The public base URL of the generated report directory",
|
|
68
|
+
});
|
|
69
|
+
this.gitlabToken = Option.String("--gitlab-token", {
|
|
70
|
+
description: "GitLab api token with api write permissions",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async execute() {
|
|
74
|
+
const cwd = processCwd();
|
|
75
|
+
const token = this.gitlabToken?.trim() || process.env.GITLAB_TOKEN?.trim() || undefined;
|
|
76
|
+
const output = this.output ?? "allure-report";
|
|
77
|
+
const configPath = this.config && existsSync(this.config) ? this.config : undefined;
|
|
78
|
+
const historyPath = this.historyPath === undefined ? "history.jsonl" : this.historyPath;
|
|
79
|
+
const config = await readConfig(cwd, configPath, {
|
|
80
|
+
output,
|
|
81
|
+
name: this.reportName,
|
|
82
|
+
historyPath: historyPath,
|
|
83
|
+
historyBaseUrl: reportBaseUrl(this.historyBaseUrl, output),
|
|
84
|
+
historyLimit: parseHistoryLimit(this.historyLimit),
|
|
85
|
+
});
|
|
86
|
+
const runGitlabOperation = async (errPrefix, operation) => {
|
|
87
|
+
try {
|
|
88
|
+
await operation();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error(`${errPrefix}: ${error instanceof Error ? error.message : String(error)}`);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
console.log("Generating allure report");
|
|
95
|
+
if (!config.allureService?.accessToken) {
|
|
96
|
+
console.log(" fetching previous run history");
|
|
97
|
+
await runGitlabOperation(" history fetch failed", () => restoreGitlabHistory({
|
|
98
|
+
token,
|
|
99
|
+
historyPath,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
const result = await generate({
|
|
103
|
+
cwd,
|
|
104
|
+
config,
|
|
105
|
+
dump: this.dump,
|
|
106
|
+
resultsDir: this.resultsDir,
|
|
107
|
+
collectSummary: true,
|
|
108
|
+
});
|
|
109
|
+
if (!result) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const reportUrl = `${config.historyBaseUrl}/index.html`;
|
|
113
|
+
console.log(`GitLab report URL: ${reportUrl}`);
|
|
114
|
+
if (result.summary && existsSync(join(config.output, "index.html"))) {
|
|
115
|
+
console.log("Posting report summary comment");
|
|
116
|
+
if (!token) {
|
|
117
|
+
console.log(" no API token provided, skipping");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const { summary } = result;
|
|
121
|
+
await runGitlabOperation(" failed to add summary comment", () => upsertGitlabJobNote({
|
|
122
|
+
token,
|
|
123
|
+
summary,
|
|
124
|
+
reportUrl,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
GitlabGenerateCommand.paths = [["gitlab"]];
|
|
130
|
+
GitlabGenerateCommand.usage = Command.Usage({
|
|
131
|
+
category: "Integrations",
|
|
132
|
+
description: "Generate test report and post report summary in merge request comments",
|
|
133
|
+
details: "This command generates a report from the provided Allure Results directories. When api access token is configured, " +
|
|
134
|
+
"integration will post summary as comment for merge request pipelines and attempt to lookup history file from previously executed job ." +
|
|
135
|
+
"This integration is designed to be executed from within GitLab CI job.",
|
|
136
|
+
examples: [["gitlab ./allure-results", "Generate a report from the ./allure-results directory"]],
|
|
137
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./generate.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./generate.js";
|
package/dist/commands/index.d.ts
CHANGED
package/dist/commands/index.js
CHANGED
package/dist/commands/log.d.ts
CHANGED
package/dist/commands/log.js
CHANGED
|
@@ -31,6 +31,9 @@ export class LogCommand extends Command {
|
|
|
31
31
|
this.qualityGateResults = Option.Boolean("--quality-gate-results", true, {
|
|
32
32
|
description: "Print quality gate validation results after tests (default: true). Pass --no-quality-gate-results to hide them",
|
|
33
33
|
});
|
|
34
|
+
this.allQualityGateResults = Option.Boolean("--all-quality-gate-results", false, {
|
|
35
|
+
description: "Include successful quality gate validation results in addition to failures",
|
|
36
|
+
});
|
|
34
37
|
}
|
|
35
38
|
async execute() {
|
|
36
39
|
const cwd = await realpath(this.cwd ?? process.cwd());
|
|
@@ -40,6 +43,7 @@ export class LogCommand extends Command {
|
|
|
40
43
|
withTrace: this.withTrace ?? false,
|
|
41
44
|
groupBy: this.groupBy ?? "suite",
|
|
42
45
|
qualityGateResults: this.qualityGateResults,
|
|
46
|
+
qualityGateFilter: this.allQualityGateResults ? () => true : undefined,
|
|
43
47
|
};
|
|
44
48
|
const config = await readConfig(cwd, this.config);
|
|
45
49
|
const resolvedEnvironment = resolveCommandEnvironment(config, {});
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import process, { argv } from "node:process";
|
|
3
3
|
import { Builtins, Cli } from "clipanion";
|
|
4
|
-
import { AgentCommand, AGENT_TASK_MAP_HELP, AgentCapabilitiesCommand, AgentInspectCommand, AgentLatestCommand, AgentQueryCommand, AgentSelectCommand, AgentStateDirCommand, Allure2Command, AwesomeCommand, CheckCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, HistoryCommand, JiraClearCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestOpsPlanCommand, TestPlanCommand, WatchCommand, isAgentTaskMapHelpRequest, } from "./commands/index.js";
|
|
4
|
+
import { AgentCommand, AGENT_TASK_MAP_HELP, AgentCapabilitiesCommand, AgentInspectCommand, AgentLatestCommand, AgentQueryCommand, AgentSelectCommand, AgentStateDirCommand, Allure2Command, AwesomeCommand, CheckCommand, ClassicCommand, CsvCommand, DashboardCommand, GenerateCommand, GitlabGenerateCommand, HistoryCommand, JiraClearCommand, LogCommand, OpenCommand, QualityGateCommand, ResultsPackCommand, ResultsUnpackCommand, RunCommand, SlackCommand, TestOpsPlanCommand, TestPlanCommand, WatchCommand, isAgentTaskMapHelpRequest, } 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({
|
|
@@ -35,6 +35,7 @@ cli.register(TestPlanCommand);
|
|
|
35
35
|
cli.register(WatchCommand);
|
|
36
36
|
cli.register(ResultsPackCommand);
|
|
37
37
|
cli.register(ResultsUnpackCommand);
|
|
38
|
+
cli.register(GitlabGenerateCommand);
|
|
38
39
|
cli.register(Builtins.HelpCommand);
|
|
39
40
|
cli.register(Builtins.VersionCommand);
|
|
40
41
|
void cli
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allure",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.0",
|
|
4
4
|
"description": "Allure Commandline Tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -32,26 +32,26 @@
|
|
|
32
32
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@allurereport/charts-api": "3.
|
|
36
|
-
"@allurereport/ci": "3.
|
|
37
|
-
"@allurereport/core": "3.
|
|
38
|
-
"@allurereport/core-api": "3.
|
|
39
|
-
"@allurereport/directory-watcher": "3.
|
|
40
|
-
"@allurereport/plugin-agent": "3.
|
|
41
|
-
"@allurereport/plugin-allure2": "3.
|
|
42
|
-
"@allurereport/plugin-api": "3.
|
|
43
|
-
"@allurereport/plugin-awesome": "3.
|
|
44
|
-
"@allurereport/plugin-classic": "3.
|
|
45
|
-
"@allurereport/plugin-csv": "3.
|
|
46
|
-
"@allurereport/plugin-dashboard": "3.
|
|
47
|
-
"@allurereport/plugin-jira": "3.
|
|
48
|
-
"@allurereport/plugin-log": "3.
|
|
49
|
-
"@allurereport/plugin-progress": "3.
|
|
50
|
-
"@allurereport/plugin-server-reload": "3.
|
|
51
|
-
"@allurereport/plugin-slack": "3.
|
|
52
|
-
"@allurereport/reader-api": "3.
|
|
53
|
-
"@allurereport/service": "3.
|
|
54
|
-
"@allurereport/static-server": "3.
|
|
35
|
+
"@allurereport/charts-api": "3.19.0",
|
|
36
|
+
"@allurereport/ci": "3.19.0",
|
|
37
|
+
"@allurereport/core": "3.19.0",
|
|
38
|
+
"@allurereport/core-api": "3.19.0",
|
|
39
|
+
"@allurereport/directory-watcher": "3.19.0",
|
|
40
|
+
"@allurereport/plugin-agent": "3.19.0",
|
|
41
|
+
"@allurereport/plugin-allure2": "3.19.0",
|
|
42
|
+
"@allurereport/plugin-api": "3.19.0",
|
|
43
|
+
"@allurereport/plugin-awesome": "3.19.0",
|
|
44
|
+
"@allurereport/plugin-classic": "3.19.0",
|
|
45
|
+
"@allurereport/plugin-csv": "3.19.0",
|
|
46
|
+
"@allurereport/plugin-dashboard": "3.19.0",
|
|
47
|
+
"@allurereport/plugin-jira": "3.19.0",
|
|
48
|
+
"@allurereport/plugin-log": "3.19.0",
|
|
49
|
+
"@allurereport/plugin-progress": "3.19.0",
|
|
50
|
+
"@allurereport/plugin-server-reload": "3.19.0",
|
|
51
|
+
"@allurereport/plugin-slack": "3.19.0",
|
|
52
|
+
"@allurereport/reader-api": "3.19.0",
|
|
53
|
+
"@allurereport/service": "3.19.0",
|
|
54
|
+
"@allurereport/static-server": "3.19.0",
|
|
55
55
|
"adm-zip": "^0.6.0",
|
|
56
56
|
"clipanion": "^4.0.0-rc.4",
|
|
57
57
|
"glob": "^13.0.6",
|