@automatify-au/cli 0.1.10 → 0.1.11
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 +45 -0
- package/dist/automatify.cjs +718 -120
- package/package.json +1 -1
package/dist/automatify.cjs
CHANGED
|
@@ -2894,8 +2894,8 @@ var require_utils = __commonJS({
|
|
|
2894
2894
|
var result = transform[inputType][outputType](input);
|
|
2895
2895
|
return result;
|
|
2896
2896
|
};
|
|
2897
|
-
exports2.resolve = function(
|
|
2898
|
-
var parts =
|
|
2897
|
+
exports2.resolve = function(path14) {
|
|
2898
|
+
var parts = path14.split("/");
|
|
2899
2899
|
var result = [];
|
|
2900
2900
|
for (var index = 0; index < parts.length; index++) {
|
|
2901
2901
|
var part = parts[index];
|
|
@@ -8748,18 +8748,18 @@ var require_object = __commonJS({
|
|
|
8748
8748
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
8749
8749
|
this.files[name] = object;
|
|
8750
8750
|
};
|
|
8751
|
-
var parentFolder = function(
|
|
8752
|
-
if (
|
|
8753
|
-
|
|
8751
|
+
var parentFolder = function(path14) {
|
|
8752
|
+
if (path14.slice(-1) === "/") {
|
|
8753
|
+
path14 = path14.substring(0, path14.length - 1);
|
|
8754
8754
|
}
|
|
8755
|
-
var lastSlash =
|
|
8756
|
-
return lastSlash > 0 ?
|
|
8755
|
+
var lastSlash = path14.lastIndexOf("/");
|
|
8756
|
+
return lastSlash > 0 ? path14.substring(0, lastSlash) : "";
|
|
8757
8757
|
};
|
|
8758
|
-
var forceTrailingSlash = function(
|
|
8759
|
-
if (
|
|
8760
|
-
|
|
8758
|
+
var forceTrailingSlash = function(path14) {
|
|
8759
|
+
if (path14.slice(-1) !== "/") {
|
|
8760
|
+
path14 += "/";
|
|
8761
8761
|
}
|
|
8762
|
-
return
|
|
8762
|
+
return path14;
|
|
8763
8763
|
};
|
|
8764
8764
|
var folderAdd = function(name, createFolders) {
|
|
8765
8765
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -9725,9 +9725,9 @@ var require_load = __commonJS({
|
|
|
9725
9725
|
var require_lib3 = __commonJS({
|
|
9726
9726
|
"../../node_modules/.pnpm/jszip@3.10.1/node_modules/jszip/lib/index.js"(exports2, module2) {
|
|
9727
9727
|
"use strict";
|
|
9728
|
-
function
|
|
9729
|
-
if (!(this instanceof
|
|
9730
|
-
return new
|
|
9728
|
+
function JSZip3() {
|
|
9729
|
+
if (!(this instanceof JSZip3)) {
|
|
9730
|
+
return new JSZip3();
|
|
9731
9731
|
}
|
|
9732
9732
|
if (arguments.length) {
|
|
9733
9733
|
throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");
|
|
@@ -9736,7 +9736,7 @@ var require_lib3 = __commonJS({
|
|
|
9736
9736
|
this.comment = null;
|
|
9737
9737
|
this.root = "";
|
|
9738
9738
|
this.clone = function() {
|
|
9739
|
-
var newObj = new
|
|
9739
|
+
var newObj = new JSZip3();
|
|
9740
9740
|
for (var i in this) {
|
|
9741
9741
|
if (typeof this[i] !== "function") {
|
|
9742
9742
|
newObj[i] = this[i];
|
|
@@ -9745,16 +9745,16 @@ var require_lib3 = __commonJS({
|
|
|
9745
9745
|
return newObj;
|
|
9746
9746
|
};
|
|
9747
9747
|
}
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
return new
|
|
9748
|
+
JSZip3.prototype = require_object();
|
|
9749
|
+
JSZip3.prototype.loadAsync = require_load();
|
|
9750
|
+
JSZip3.support = require_support();
|
|
9751
|
+
JSZip3.defaults = require_defaults();
|
|
9752
|
+
JSZip3.version = "3.10.1";
|
|
9753
|
+
JSZip3.loadAsync = function(content, options) {
|
|
9754
|
+
return new JSZip3().loadAsync(content, options);
|
|
9755
9755
|
};
|
|
9756
|
-
|
|
9757
|
-
module2.exports =
|
|
9756
|
+
JSZip3.external = require_external();
|
|
9757
|
+
module2.exports = JSZip3;
|
|
9758
9758
|
}
|
|
9759
9759
|
});
|
|
9760
9760
|
|
|
@@ -12447,8 +12447,8 @@ function createAutoHandler(deps = {}) {
|
|
|
12447
12447
|
}
|
|
12448
12448
|
|
|
12449
12449
|
// src/allure.ts
|
|
12450
|
-
var
|
|
12451
|
-
var
|
|
12450
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
12451
|
+
var import_node_fs9 = require("node:fs");
|
|
12452
12452
|
|
|
12453
12453
|
// ../../packages/jira-client/src/adf.ts
|
|
12454
12454
|
function paragraph(text = "") {
|
|
@@ -12681,6 +12681,438 @@ async function parseAllureReportZip(zipPath) {
|
|
|
12681
12681
|
};
|
|
12682
12682
|
}
|
|
12683
12683
|
|
|
12684
|
+
// ../../packages/allure-core/src/extractAllureZip.ts
|
|
12685
|
+
var import_node_fs7 = require("node:fs");
|
|
12686
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
12687
|
+
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
12688
|
+
var INDEX_HTML = "index.html";
|
|
12689
|
+
var MISSING_INDEX_ERROR = "Could not find index.html. Please provide a generated Allure HTML report ZIP, not raw allure-results.";
|
|
12690
|
+
function findIndexEntry(paths) {
|
|
12691
|
+
return paths.find((entryPath) => entryPath === INDEX_HTML) ?? paths.find((entryPath) => entryPath === `allure-report/${INDEX_HTML}`) ?? paths.find((entryPath) => entryPath.endsWith(`/${INDEX_HTML}`));
|
|
12692
|
+
}
|
|
12693
|
+
function ensureInsideRoot(rootDir, candidate) {
|
|
12694
|
+
const resolved = import_node_path8.default.resolve(rootDir, candidate);
|
|
12695
|
+
const rootWithSep = rootDir.endsWith(import_node_path8.default.sep) ? rootDir : rootDir + import_node_path8.default.sep;
|
|
12696
|
+
if (resolved !== rootDir && !resolved.startsWith(rootWithSep)) {
|
|
12697
|
+
throw new Error(`Refusing to write zip entry outside extract directory: ${candidate}`);
|
|
12698
|
+
}
|
|
12699
|
+
return resolved;
|
|
12700
|
+
}
|
|
12701
|
+
async function extractAllureReportZip(zipPath, extractDir) {
|
|
12702
|
+
if (!(0, import_node_fs7.existsSync)(zipPath)) {
|
|
12703
|
+
throw new Error(`Allure report ZIP not found: ${zipPath}`);
|
|
12704
|
+
}
|
|
12705
|
+
if (import_node_path8.default.extname(zipPath).toLowerCase() !== ".zip") {
|
|
12706
|
+
throw new Error("Allure report must be a .zip file.");
|
|
12707
|
+
}
|
|
12708
|
+
const zip = await import_jszip2.default.loadAsync((0, import_node_fs7.readFileSync)(zipPath));
|
|
12709
|
+
const entries = Object.entries(zip.files);
|
|
12710
|
+
const filePaths = entries.filter(([, file]) => !file.dir).map(([entryPath]) => entryPath);
|
|
12711
|
+
const indexEntry = findIndexEntry(filePaths);
|
|
12712
|
+
if (!indexEntry) {
|
|
12713
|
+
throw new Error(MISSING_INDEX_ERROR);
|
|
12714
|
+
}
|
|
12715
|
+
const resolvedExtract = import_node_path8.default.resolve(extractDir);
|
|
12716
|
+
(0, import_node_fs7.mkdirSync)(resolvedExtract, { recursive: true });
|
|
12717
|
+
for (const [entryPath, file] of entries) {
|
|
12718
|
+
const target = ensureInsideRoot(resolvedExtract, entryPath);
|
|
12719
|
+
if (file.dir) {
|
|
12720
|
+
(0, import_node_fs7.mkdirSync)(target, { recursive: true });
|
|
12721
|
+
continue;
|
|
12722
|
+
}
|
|
12723
|
+
(0, import_node_fs7.mkdirSync)(import_node_path8.default.dirname(target), { recursive: true });
|
|
12724
|
+
const buffer = await file.async("nodebuffer");
|
|
12725
|
+
(0, import_node_fs7.writeFileSync)(target, buffer);
|
|
12726
|
+
}
|
|
12727
|
+
const indexAbsolute = import_node_path8.default.join(resolvedExtract, indexEntry);
|
|
12728
|
+
const rootDir = import_node_path8.default.dirname(indexAbsolute);
|
|
12729
|
+
return {
|
|
12730
|
+
zipPath,
|
|
12731
|
+
extractDir: resolvedExtract,
|
|
12732
|
+
rootDir,
|
|
12733
|
+
indexPath: indexAbsolute
|
|
12734
|
+
};
|
|
12735
|
+
}
|
|
12736
|
+
|
|
12737
|
+
// src/allureOpen.ts
|
|
12738
|
+
var import_node_fs8 = require("node:fs");
|
|
12739
|
+
var import_promises = require("node:fs/promises");
|
|
12740
|
+
var import_node_http = __toESM(require("node:http"), 1);
|
|
12741
|
+
var import_node_os = require("node:os");
|
|
12742
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
12743
|
+
var import_node_child_process2 = require("node:child_process");
|
|
12744
|
+
function parseArgs2(args) {
|
|
12745
|
+
const positionals = [];
|
|
12746
|
+
const flags = {};
|
|
12747
|
+
const boolFlags = /* @__PURE__ */ new Set();
|
|
12748
|
+
const unknownFlags = [];
|
|
12749
|
+
const valuedFlags = /* @__PURE__ */ new Set(["--port", "--host", "--extract-to"]);
|
|
12750
|
+
const supportedBoolFlags = /* @__PURE__ */ new Set(["--keep", "--no-open", "--json", "--dry-run", "--verbose"]);
|
|
12751
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
12752
|
+
const token = args[i];
|
|
12753
|
+
if (!token.startsWith("--")) {
|
|
12754
|
+
positionals.push(token);
|
|
12755
|
+
continue;
|
|
12756
|
+
}
|
|
12757
|
+
if (supportedBoolFlags.has(token)) {
|
|
12758
|
+
boolFlags.add(token);
|
|
12759
|
+
continue;
|
|
12760
|
+
}
|
|
12761
|
+
if (!valuedFlags.has(token)) {
|
|
12762
|
+
unknownFlags.push(token);
|
|
12763
|
+
continue;
|
|
12764
|
+
}
|
|
12765
|
+
const value = args[i + 1];
|
|
12766
|
+
if (!value || value.startsWith("--")) {
|
|
12767
|
+
unknownFlags.push(token);
|
|
12768
|
+
continue;
|
|
12769
|
+
}
|
|
12770
|
+
flags[token] = value;
|
|
12771
|
+
i += 1;
|
|
12772
|
+
}
|
|
12773
|
+
return { positionals, flags, boolFlags, unknownFlags };
|
|
12774
|
+
}
|
|
12775
|
+
function parsePort(raw) {
|
|
12776
|
+
if (raw === void 0) {
|
|
12777
|
+
return { value: 0 };
|
|
12778
|
+
}
|
|
12779
|
+
const parsed = Number(raw);
|
|
12780
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
|
|
12781
|
+
return { value: 0, error: `Invalid --port value: ${raw}. Must be an integer between 0 and 65535.` };
|
|
12782
|
+
}
|
|
12783
|
+
return { value: parsed };
|
|
12784
|
+
}
|
|
12785
|
+
function normalizeError(error) {
|
|
12786
|
+
return error instanceof Error ? error.message : "Unknown Allure open error.";
|
|
12787
|
+
}
|
|
12788
|
+
var MIME_TYPES = {
|
|
12789
|
+
".html": "text/html; charset=utf-8",
|
|
12790
|
+
".htm": "text/html; charset=utf-8",
|
|
12791
|
+
".js": "application/javascript; charset=utf-8",
|
|
12792
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
12793
|
+
".css": "text/css; charset=utf-8",
|
|
12794
|
+
".json": "application/json; charset=utf-8",
|
|
12795
|
+
".svg": "image/svg+xml",
|
|
12796
|
+
".png": "image/png",
|
|
12797
|
+
".jpg": "image/jpeg",
|
|
12798
|
+
".jpeg": "image/jpeg",
|
|
12799
|
+
".gif": "image/gif",
|
|
12800
|
+
".webp": "image/webp",
|
|
12801
|
+
".ico": "image/x-icon",
|
|
12802
|
+
".woff": "font/woff",
|
|
12803
|
+
".woff2": "font/woff2",
|
|
12804
|
+
".ttf": "font/ttf",
|
|
12805
|
+
".otf": "font/otf",
|
|
12806
|
+
".eot": "application/vnd.ms-fontobject",
|
|
12807
|
+
".map": "application/json; charset=utf-8",
|
|
12808
|
+
".txt": "text/plain; charset=utf-8"
|
|
12809
|
+
};
|
|
12810
|
+
function contentTypeFor(filePath) {
|
|
12811
|
+
return MIME_TYPES[import_node_path9.default.extname(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
12812
|
+
}
|
|
12813
|
+
function resolveRequestedPath(rootDir, urlPath) {
|
|
12814
|
+
let decoded;
|
|
12815
|
+
try {
|
|
12816
|
+
decoded = decodeURIComponent(urlPath.split("?")[0].split("#")[0]);
|
|
12817
|
+
} catch {
|
|
12818
|
+
return void 0;
|
|
12819
|
+
}
|
|
12820
|
+
const normalized = import_node_path9.default.normalize(decoded);
|
|
12821
|
+
const trimmed = normalized.replace(/^[/\\]+/, "");
|
|
12822
|
+
const candidate = import_node_path9.default.resolve(rootDir, trimmed);
|
|
12823
|
+
const rootWithSep = rootDir.endsWith(import_node_path9.default.sep) ? rootDir : rootDir + import_node_path9.default.sep;
|
|
12824
|
+
if (candidate !== rootDir && !candidate.startsWith(rootWithSep)) {
|
|
12825
|
+
return void 0;
|
|
12826
|
+
}
|
|
12827
|
+
return candidate;
|
|
12828
|
+
}
|
|
12829
|
+
function createStaticServerStarter() {
|
|
12830
|
+
return async ({ rootDir, host, port }) => {
|
|
12831
|
+
const server = import_node_http.default.createServer((req, res) => {
|
|
12832
|
+
if (!req.url || req.method !== "GET" && req.method !== "HEAD") {
|
|
12833
|
+
res.statusCode = 405;
|
|
12834
|
+
res.end("Method Not Allowed");
|
|
12835
|
+
return;
|
|
12836
|
+
}
|
|
12837
|
+
const resolved = resolveRequestedPath(rootDir, req.url);
|
|
12838
|
+
if (!resolved) {
|
|
12839
|
+
res.statusCode = 400;
|
|
12840
|
+
res.end("Bad Request");
|
|
12841
|
+
return;
|
|
12842
|
+
}
|
|
12843
|
+
let target = resolved;
|
|
12844
|
+
try {
|
|
12845
|
+
const stat = (0, import_node_fs8.statSync)(target);
|
|
12846
|
+
if (stat.isDirectory()) {
|
|
12847
|
+
target = import_node_path9.default.join(target, "index.html");
|
|
12848
|
+
}
|
|
12849
|
+
} catch {
|
|
12850
|
+
res.statusCode = 404;
|
|
12851
|
+
res.end("Not Found");
|
|
12852
|
+
return;
|
|
12853
|
+
}
|
|
12854
|
+
if (!(0, import_node_fs8.existsSync)(target)) {
|
|
12855
|
+
res.statusCode = 404;
|
|
12856
|
+
res.end("Not Found");
|
|
12857
|
+
return;
|
|
12858
|
+
}
|
|
12859
|
+
res.setHeader("Content-Type", contentTypeFor(target));
|
|
12860
|
+
if (req.method === "HEAD") {
|
|
12861
|
+
res.statusCode = 200;
|
|
12862
|
+
res.end();
|
|
12863
|
+
return;
|
|
12864
|
+
}
|
|
12865
|
+
const stream = (0, import_node_fs8.createReadStream)(target);
|
|
12866
|
+
stream.on("error", () => {
|
|
12867
|
+
res.statusCode = 500;
|
|
12868
|
+
res.end("Internal Server Error");
|
|
12869
|
+
});
|
|
12870
|
+
stream.pipe(res);
|
|
12871
|
+
});
|
|
12872
|
+
await new Promise((resolve, reject) => {
|
|
12873
|
+
const onError = (err) => {
|
|
12874
|
+
server.off("listening", onListening);
|
|
12875
|
+
reject(err);
|
|
12876
|
+
};
|
|
12877
|
+
const onListening = () => {
|
|
12878
|
+
server.off("error", onError);
|
|
12879
|
+
resolve();
|
|
12880
|
+
};
|
|
12881
|
+
server.once("error", onError);
|
|
12882
|
+
server.once("listening", onListening);
|
|
12883
|
+
server.listen(port, host);
|
|
12884
|
+
});
|
|
12885
|
+
const address = server.address();
|
|
12886
|
+
const actualPort = typeof address === "object" && address ? address.port : port;
|
|
12887
|
+
const displayHost = host === "0.0.0.0" ? "127.0.0.1" : host;
|
|
12888
|
+
const url = `http://${displayHost}:${actualPort}/`;
|
|
12889
|
+
return {
|
|
12890
|
+
url,
|
|
12891
|
+
port: actualPort,
|
|
12892
|
+
host,
|
|
12893
|
+
close: () => new Promise((resolve, reject) => {
|
|
12894
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
12895
|
+
})
|
|
12896
|
+
};
|
|
12897
|
+
};
|
|
12898
|
+
}
|
|
12899
|
+
function createOsBrowserOpener() {
|
|
12900
|
+
return async (url) => {
|
|
12901
|
+
const platform = process.platform;
|
|
12902
|
+
let command;
|
|
12903
|
+
let args;
|
|
12904
|
+
if (platform === "darwin") {
|
|
12905
|
+
command = "open";
|
|
12906
|
+
args = [url];
|
|
12907
|
+
} else if (platform === "win32") {
|
|
12908
|
+
command = "cmd";
|
|
12909
|
+
args = ["/c", "start", "", url];
|
|
12910
|
+
} else {
|
|
12911
|
+
command = "xdg-open";
|
|
12912
|
+
args = [url];
|
|
12913
|
+
}
|
|
12914
|
+
try {
|
|
12915
|
+
const child = (0, import_node_child_process2.spawn)(command, args, { stdio: "ignore", detached: true });
|
|
12916
|
+
child.on("error", () => void 0);
|
|
12917
|
+
child.unref();
|
|
12918
|
+
} catch {
|
|
12919
|
+
}
|
|
12920
|
+
};
|
|
12921
|
+
}
|
|
12922
|
+
function waitForProcessSignals() {
|
|
12923
|
+
return new Promise((resolve) => {
|
|
12924
|
+
const cleanup = () => {
|
|
12925
|
+
process.off("SIGINT", onSignal);
|
|
12926
|
+
process.off("SIGTERM", onSignal);
|
|
12927
|
+
resolve();
|
|
12928
|
+
};
|
|
12929
|
+
const onSignal = () => {
|
|
12930
|
+
cleanup();
|
|
12931
|
+
};
|
|
12932
|
+
process.once("SIGINT", onSignal);
|
|
12933
|
+
process.once("SIGTERM", onSignal);
|
|
12934
|
+
});
|
|
12935
|
+
}
|
|
12936
|
+
function buildJsonOutput(params) {
|
|
12937
|
+
const output = {
|
|
12938
|
+
zipPath: params.zipPath,
|
|
12939
|
+
dryRun: params.dryRun,
|
|
12940
|
+
served: params.served,
|
|
12941
|
+
opened: params.opened,
|
|
12942
|
+
keep: params.keep,
|
|
12943
|
+
extractDir: params.extractDir,
|
|
12944
|
+
rootDir: params.rootDir,
|
|
12945
|
+
indexPath: params.indexPath,
|
|
12946
|
+
summary: {
|
|
12947
|
+
total: params.summary.counts.total,
|
|
12948
|
+
passed: params.summary.counts.passed,
|
|
12949
|
+
failed: params.summary.counts.failed,
|
|
12950
|
+
broken: params.summary.counts.broken,
|
|
12951
|
+
skipped: params.summary.counts.skipped,
|
|
12952
|
+
unknown: params.summary.counts.unknown
|
|
12953
|
+
}
|
|
12954
|
+
};
|
|
12955
|
+
if (params.url) {
|
|
12956
|
+
output.url = params.url;
|
|
12957
|
+
}
|
|
12958
|
+
if (params.port !== void 0) {
|
|
12959
|
+
output.port = params.port;
|
|
12960
|
+
}
|
|
12961
|
+
if (params.host !== void 0) {
|
|
12962
|
+
output.host = params.host;
|
|
12963
|
+
}
|
|
12964
|
+
return output;
|
|
12965
|
+
}
|
|
12966
|
+
function createAllureOpenHandler(deps = {}) {
|
|
12967
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
12968
|
+
const parseZip = deps.parseAllureReportZip ?? parseAllureReportZip;
|
|
12969
|
+
const extractZip = deps.extractAllureReportZip ?? extractAllureReportZip;
|
|
12970
|
+
const createTempDir = deps.createTempDir ?? (() => (0, import_promises.mkdtemp)(import_node_path9.default.join((0, import_node_os.tmpdir)(), "automatify-allure-open-")));
|
|
12971
|
+
const startServer = deps.startServer ?? createStaticServerStarter();
|
|
12972
|
+
const openInBrowser = deps.openInBrowser ?? createOsBrowserOpener();
|
|
12973
|
+
const waitForShutdown = deps.waitForShutdown ?? waitForProcessSignals;
|
|
12974
|
+
const removeDir = deps.removeDir ?? ((dir) => (0, import_promises.rm)(dir, { recursive: true, force: true }));
|
|
12975
|
+
const logger = deps.logger ?? console;
|
|
12976
|
+
return async (request) => {
|
|
12977
|
+
const parsed = parseArgs2(request.args);
|
|
12978
|
+
const useJson = parsed.boolFlags.has("--json");
|
|
12979
|
+
const dryRun = parsed.boolFlags.has("--dry-run");
|
|
12980
|
+
const verbose = parsed.boolFlags.has("--verbose");
|
|
12981
|
+
const keep = parsed.boolFlags.has("--keep");
|
|
12982
|
+
const noOpen = parsed.boolFlags.has("--no-open");
|
|
12983
|
+
const userExtractDir = parsed.flags["--extract-to"];
|
|
12984
|
+
if (parsed.unknownFlags.length > 0) {
|
|
12985
|
+
return {
|
|
12986
|
+
exitCode: ExitCode.UsageError,
|
|
12987
|
+
stderr: [`ERROR: Unknown or invalid flags: ${parsed.unknownFlags.join(", ")}`]
|
|
12988
|
+
};
|
|
12989
|
+
}
|
|
12990
|
+
const [zipPathInput] = parsed.positionals;
|
|
12991
|
+
if (!zipPathInput || parsed.positionals.length > 1) {
|
|
12992
|
+
return {
|
|
12993
|
+
exitCode: ExitCode.UsageError,
|
|
12994
|
+
stderr: ["Usage: automatify testops allure open <zipPath> [options]"]
|
|
12995
|
+
};
|
|
12996
|
+
}
|
|
12997
|
+
const portResult = parsePort(parsed.flags["--port"]);
|
|
12998
|
+
if (portResult.error) {
|
|
12999
|
+
return {
|
|
13000
|
+
exitCode: ExitCode.UsageError,
|
|
13001
|
+
stderr: [`ERROR: ${portResult.error}`]
|
|
13002
|
+
};
|
|
13003
|
+
}
|
|
13004
|
+
const host = parsed.flags["--host"] ?? "127.0.0.1";
|
|
13005
|
+
const zipPath = import_node_path9.default.resolve(cwd, zipPathInput);
|
|
13006
|
+
let summary;
|
|
13007
|
+
try {
|
|
13008
|
+
summary = await parseZip(zipPath);
|
|
13009
|
+
} catch (error) {
|
|
13010
|
+
return {
|
|
13011
|
+
exitCode: ExitCode.ValidationError,
|
|
13012
|
+
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
13013
|
+
};
|
|
13014
|
+
}
|
|
13015
|
+
const extractDirRaw = userExtractDir ? import_node_path9.default.resolve(cwd, userExtractDir) : await createTempDir();
|
|
13016
|
+
if (dryRun) {
|
|
13017
|
+
const indexPath = import_node_path9.default.join(extractDirRaw, "index.html");
|
|
13018
|
+
if (useJson) {
|
|
13019
|
+
return {
|
|
13020
|
+
exitCode: ExitCode.Success,
|
|
13021
|
+
stdout: toJsonLine(buildJsonOutput({
|
|
13022
|
+
zipPath,
|
|
13023
|
+
dryRun: true,
|
|
13024
|
+
served: false,
|
|
13025
|
+
opened: false,
|
|
13026
|
+
keep,
|
|
13027
|
+
extractDir: extractDirRaw,
|
|
13028
|
+
rootDir: extractDirRaw,
|
|
13029
|
+
indexPath,
|
|
13030
|
+
summary
|
|
13031
|
+
}))
|
|
13032
|
+
};
|
|
13033
|
+
}
|
|
13034
|
+
return {
|
|
13035
|
+
exitCode: ExitCode.Success,
|
|
13036
|
+
stdout: [
|
|
13037
|
+
`Allure report ZIP: ${zipPath}`,
|
|
13038
|
+
`Total: ${summary.counts.total} (passed ${summary.counts.passed}, failed ${summary.counts.failed}, broken ${summary.counts.broken}, skipped ${summary.counts.skipped}, unknown ${summary.counts.unknown})`,
|
|
13039
|
+
`Dry run: would extract to ${extractDirRaw} and serve on http://${host}:${portResult.value === 0 ? "<auto>" : portResult.value}/`
|
|
13040
|
+
]
|
|
13041
|
+
};
|
|
13042
|
+
}
|
|
13043
|
+
let extractResult;
|
|
13044
|
+
try {
|
|
13045
|
+
extractResult = await extractZip(zipPath, extractDirRaw);
|
|
13046
|
+
} catch (error) {
|
|
13047
|
+
if (!userExtractDir) {
|
|
13048
|
+
await removeDir(extractDirRaw).catch(() => void 0);
|
|
13049
|
+
}
|
|
13050
|
+
return {
|
|
13051
|
+
exitCode: ExitCode.ValidationError,
|
|
13052
|
+
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
13053
|
+
};
|
|
13054
|
+
}
|
|
13055
|
+
let serverHandle;
|
|
13056
|
+
try {
|
|
13057
|
+
serverHandle = await startServer({
|
|
13058
|
+
rootDir: extractResult.rootDir,
|
|
13059
|
+
host,
|
|
13060
|
+
port: portResult.value
|
|
13061
|
+
});
|
|
13062
|
+
} catch (error) {
|
|
13063
|
+
if (!keep && !userExtractDir) {
|
|
13064
|
+
await removeDir(extractResult.extractDir).catch(() => void 0);
|
|
13065
|
+
}
|
|
13066
|
+
return {
|
|
13067
|
+
exitCode: ExitCode.TransportError,
|
|
13068
|
+
stderr: [`ERROR: Could not start static server: ${normalizeError(error)}`]
|
|
13069
|
+
};
|
|
13070
|
+
}
|
|
13071
|
+
let opened = false;
|
|
13072
|
+
if (!noOpen) {
|
|
13073
|
+
try {
|
|
13074
|
+
await openInBrowser(serverHandle.url);
|
|
13075
|
+
opened = true;
|
|
13076
|
+
} catch {
|
|
13077
|
+
opened = false;
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
13080
|
+
if (useJson) {
|
|
13081
|
+
logger.log(JSON.stringify(buildJsonOutput({
|
|
13082
|
+
zipPath,
|
|
13083
|
+
dryRun: false,
|
|
13084
|
+
served: true,
|
|
13085
|
+
opened,
|
|
13086
|
+
keep,
|
|
13087
|
+
extractDir: extractResult.extractDir,
|
|
13088
|
+
rootDir: extractResult.rootDir,
|
|
13089
|
+
indexPath: extractResult.indexPath,
|
|
13090
|
+
url: serverHandle.url,
|
|
13091
|
+
port: serverHandle.port,
|
|
13092
|
+
host: serverHandle.host,
|
|
13093
|
+
summary
|
|
13094
|
+
})));
|
|
13095
|
+
} else {
|
|
13096
|
+
logger.log(`Allure report extracted to ${extractResult.extractDir}.`);
|
|
13097
|
+
if (verbose) {
|
|
13098
|
+
logger.log(`Index: ${extractResult.indexPath}`);
|
|
13099
|
+
}
|
|
13100
|
+
logger.log(`Serving at ${serverHandle.url}`);
|
|
13101
|
+
logger.log(opened ? "Opened in your default browser." : "Browser open skipped.");
|
|
13102
|
+
logger.log("Press Ctrl+C to stop the server.");
|
|
13103
|
+
}
|
|
13104
|
+
await waitForShutdown();
|
|
13105
|
+
try {
|
|
13106
|
+
await serverHandle.close();
|
|
13107
|
+
} catch {
|
|
13108
|
+
}
|
|
13109
|
+
if (!keep && !userExtractDir) {
|
|
13110
|
+
await removeDir(extractResult.extractDir).catch(() => void 0);
|
|
13111
|
+
}
|
|
13112
|
+
return { exitCode: ExitCode.Success };
|
|
13113
|
+
};
|
|
13114
|
+
}
|
|
13115
|
+
|
|
12684
13116
|
// src/allure.ts
|
|
12685
13117
|
var CONFIG_FLAGS2 = /* @__PURE__ */ new Set([
|
|
12686
13118
|
"--config",
|
|
@@ -12691,7 +13123,7 @@ var CONFIG_FLAGS2 = /* @__PURE__ */ new Set([
|
|
|
12691
13123
|
"--jira-email",
|
|
12692
13124
|
"--jira-api-token"
|
|
12693
13125
|
]);
|
|
12694
|
-
function
|
|
13126
|
+
function parseArgs3(args) {
|
|
12695
13127
|
const positionals = [];
|
|
12696
13128
|
const flags = {};
|
|
12697
13129
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
@@ -12742,7 +13174,7 @@ function pickConfigArgs2(parsed) {
|
|
|
12742
13174
|
function normalizeSite2(value) {
|
|
12743
13175
|
return value.trim().replace(/\/+$/, "");
|
|
12744
13176
|
}
|
|
12745
|
-
function
|
|
13177
|
+
function normalizeError2(error) {
|
|
12746
13178
|
return error instanceof Error ? error.message : "Unknown Allure upload error.";
|
|
12747
13179
|
}
|
|
12748
13180
|
function hasCredential(value) {
|
|
@@ -12847,7 +13279,7 @@ function buildDownloadJsonOutput(params) {
|
|
|
12847
13279
|
outputPath: params.outputPath
|
|
12848
13280
|
};
|
|
12849
13281
|
}
|
|
12850
|
-
function
|
|
13282
|
+
function buildJsonOutput2(params) {
|
|
12851
13283
|
const attachment = {
|
|
12852
13284
|
filename: params.attachment.filename
|
|
12853
13285
|
};
|
|
@@ -12887,19 +13319,24 @@ function createAllureHandler(deps = {}) {
|
|
|
12887
13319
|
const createComment = deps.addIssueComment ?? addIssueComment;
|
|
12888
13320
|
const listAttachments = deps.listIssueAttachments ?? listIssueAttachments;
|
|
12889
13321
|
const downloadAttachment = deps.downloadIssueAttachment ?? downloadIssueAttachment;
|
|
12890
|
-
|
|
13322
|
+
const openHandler = createAllureOpenHandler({ cwd });
|
|
13323
|
+
return async (request, context) => {
|
|
12891
13324
|
const [subcommand, ...subArgs] = request.args;
|
|
13325
|
+
if (subcommand === "open") {
|
|
13326
|
+
return openHandler({ ...request, args: subArgs }, context);
|
|
13327
|
+
}
|
|
12892
13328
|
if (subcommand !== "upload" && subcommand !== "download") {
|
|
12893
13329
|
return {
|
|
12894
13330
|
exitCode: ExitCode.UsageError,
|
|
12895
13331
|
stderr: [
|
|
12896
13332
|
"Usage:",
|
|
12897
13333
|
" automatify testops allure upload <issueKey> <zipPath> [options]",
|
|
12898
|
-
" automatify testops allure download <issueKey> [options]"
|
|
13334
|
+
" automatify testops allure download <issueKey> [options]",
|
|
13335
|
+
" automatify testops allure open <zipPath> [options]"
|
|
12899
13336
|
]
|
|
12900
13337
|
};
|
|
12901
13338
|
}
|
|
12902
|
-
const parsed =
|
|
13339
|
+
const parsed = parseArgs3(subArgs);
|
|
12903
13340
|
const useJson = parsed.boolFlags.has("--json");
|
|
12904
13341
|
const dryRun = parsed.boolFlags.has("--dry-run");
|
|
12905
13342
|
const verbose = parsed.boolFlags.has("--verbose");
|
|
@@ -12936,8 +13373,8 @@ function createAllureHandler(deps = {}) {
|
|
|
12936
13373
|
attachmentId: parsed.flags["--attachment-id"],
|
|
12937
13374
|
filename: parsed.flags["--filename"]
|
|
12938
13375
|
});
|
|
12939
|
-
const outputDir =
|
|
12940
|
-
const outputPath =
|
|
13376
|
+
const outputDir = import_node_path10.default.resolve(cwd, parsed.flags["--output-dir"] ?? ".");
|
|
13377
|
+
const outputPath = import_node_path10.default.join(outputDir, selected.filename);
|
|
12941
13378
|
if (dryRun) {
|
|
12942
13379
|
if (useJson) {
|
|
12943
13380
|
return {
|
|
@@ -12960,8 +13397,8 @@ function createAllureHandler(deps = {}) {
|
|
|
12960
13397
|
]
|
|
12961
13398
|
};
|
|
12962
13399
|
}
|
|
12963
|
-
(0,
|
|
12964
|
-
if ((0,
|
|
13400
|
+
(0, import_node_fs9.mkdirSync)(outputDir, { recursive: true });
|
|
13401
|
+
if ((0, import_node_fs9.existsSync)(outputPath) && !force) {
|
|
12965
13402
|
return {
|
|
12966
13403
|
exitCode: ExitCode.ValidationError,
|
|
12967
13404
|
stderr: [`ERROR: Output file already exists: ${outputPath}. Pass --force to overwrite.`]
|
|
@@ -12996,7 +13433,7 @@ function createAllureHandler(deps = {}) {
|
|
|
12996
13433
|
} catch (error) {
|
|
12997
13434
|
return {
|
|
12998
13435
|
exitCode: ExitCode.RemoteError,
|
|
12999
|
-
stderr: [`ERROR: ${
|
|
13436
|
+
stderr: [`ERROR: ${normalizeError2(error)}`]
|
|
13000
13437
|
};
|
|
13001
13438
|
}
|
|
13002
13439
|
}
|
|
@@ -13008,8 +13445,8 @@ function createAllureHandler(deps = {}) {
|
|
|
13008
13445
|
};
|
|
13009
13446
|
}
|
|
13010
13447
|
const resolved = resolveJiraConfig(parsed, env, cwd);
|
|
13011
|
-
const zipPath =
|
|
13012
|
-
const attachmentFilename =
|
|
13448
|
+
const zipPath = import_node_path10.default.resolve(cwd, zipPathInput);
|
|
13449
|
+
const attachmentFilename = import_node_path10.default.basename(zipPath);
|
|
13013
13450
|
if (!resolved.config) {
|
|
13014
13451
|
return {
|
|
13015
13452
|
exitCode: ExitCode.ValidationError,
|
|
@@ -13022,14 +13459,14 @@ function createAllureHandler(deps = {}) {
|
|
|
13022
13459
|
} catch (error) {
|
|
13023
13460
|
return {
|
|
13024
13461
|
exitCode: ExitCode.ValidationError,
|
|
13025
|
-
stderr: [`ERROR: ${
|
|
13462
|
+
stderr: [`ERROR: ${normalizeError2(error)}`]
|
|
13026
13463
|
};
|
|
13027
13464
|
}
|
|
13028
13465
|
if (dryRun) {
|
|
13029
13466
|
if (useJson) {
|
|
13030
13467
|
return {
|
|
13031
13468
|
exitCode: ExitCode.Success,
|
|
13032
|
-
stdout: toJsonLine(
|
|
13469
|
+
stdout: toJsonLine(buildJsonOutput2({
|
|
13033
13470
|
issueKey,
|
|
13034
13471
|
uploaded: false,
|
|
13035
13472
|
commentAdded: false,
|
|
@@ -13072,7 +13509,7 @@ function createAllureHandler(deps = {}) {
|
|
|
13072
13509
|
if (useJson) {
|
|
13073
13510
|
return {
|
|
13074
13511
|
exitCode: ExitCode.Success,
|
|
13075
|
-
stdout: toJsonLine(
|
|
13512
|
+
stdout: toJsonLine(buildJsonOutput2({
|
|
13076
13513
|
issueKey,
|
|
13077
13514
|
uploaded: true,
|
|
13078
13515
|
commentAdded,
|
|
@@ -13096,15 +13533,15 @@ function createAllureHandler(deps = {}) {
|
|
|
13096
13533
|
} catch (error) {
|
|
13097
13534
|
return {
|
|
13098
13535
|
exitCode: ExitCode.RemoteError,
|
|
13099
|
-
stderr: [`ERROR: ${
|
|
13536
|
+
stderr: [`ERROR: ${normalizeError2(error)}`]
|
|
13100
13537
|
};
|
|
13101
13538
|
}
|
|
13102
13539
|
};
|
|
13103
13540
|
}
|
|
13104
13541
|
|
|
13105
13542
|
// src/bdd.ts
|
|
13106
|
-
var
|
|
13107
|
-
var
|
|
13543
|
+
var import_node_fs10 = require("node:fs");
|
|
13544
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
13108
13545
|
var import_yazl = __toESM(require_yazl(), 1);
|
|
13109
13546
|
|
|
13110
13547
|
// src/forgeClient.ts
|
|
@@ -13269,7 +13706,7 @@ var CONFIG_FLAGS3 = /* @__PURE__ */ new Set([
|
|
|
13269
13706
|
"--jira-email",
|
|
13270
13707
|
"--jira-api-token"
|
|
13271
13708
|
]);
|
|
13272
|
-
function
|
|
13709
|
+
function parseArgs4(args) {
|
|
13273
13710
|
const flags = {};
|
|
13274
13711
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
13275
13712
|
const unknownFlags = [];
|
|
@@ -13316,7 +13753,7 @@ function pickConfigArgs3(parsed) {
|
|
|
13316
13753
|
}
|
|
13317
13754
|
return args;
|
|
13318
13755
|
}
|
|
13319
|
-
function
|
|
13756
|
+
function normalizeError3(error) {
|
|
13320
13757
|
if (error instanceof ForgeClientError) {
|
|
13321
13758
|
return `${error.code}: ${error.message}`;
|
|
13322
13759
|
}
|
|
@@ -13408,7 +13845,7 @@ function parseScenarioFeatureFile(raw, filePath) {
|
|
|
13408
13845
|
}
|
|
13409
13846
|
const scenarioTag = tags.map((tag) => tag.match(SCENARIO_METADATA_PATTERN)).find((match) => Boolean(match));
|
|
13410
13847
|
const scenarioKeyFromTag = scenarioTag?.[1]?.trim().toUpperCase() ?? "";
|
|
13411
|
-
const fileKeyMatch =
|
|
13848
|
+
const fileKeyMatch = import_node_path11.default.basename(filePath ?? "").match(/^(SC-\d+)\.feature$/i);
|
|
13412
13849
|
const scenarioKeyFromFile = fileKeyMatch?.[1]?.trim().toUpperCase() ?? "";
|
|
13413
13850
|
const scenarioKey = scenarioKeyFromTag || scenarioKeyFromFile;
|
|
13414
13851
|
if (scenarioKeyFromTag && scenarioKeyFromFile && scenarioKeyFromTag !== scenarioKeyFromFile) {
|
|
@@ -13526,7 +13963,7 @@ function toJsonExportManifestItems(items) {
|
|
|
13526
13963
|
async function defaultCreateZipArchive(archivePath, entries) {
|
|
13527
13964
|
await new Promise((resolve, reject) => {
|
|
13528
13965
|
const zip = new import_yazl.ZipFile();
|
|
13529
|
-
const output = zip.outputStream.pipe((0,
|
|
13966
|
+
const output = zip.outputStream.pipe((0, import_node_fs10.createWriteStream)(archivePath));
|
|
13530
13967
|
output.on("close", () => resolve());
|
|
13531
13968
|
output.on("error", reject);
|
|
13532
13969
|
zip.outputStream.on("error", reject);
|
|
@@ -13556,14 +13993,14 @@ function missingProjectResponse() {
|
|
|
13556
13993
|
function createBddHandler(deps = {}) {
|
|
13557
13994
|
const cwd = deps.cwd ?? process.cwd();
|
|
13558
13995
|
const env = deps.env ?? process.env;
|
|
13559
|
-
const mkdir = deps.mkdir ?? ((targetPath, options) => (0,
|
|
13560
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
13561
|
-
const readDir = deps.readDir ?? ((dirPath) => (0,
|
|
13562
|
-
const writeFile = deps.writeFile ?? ((filePath, content) => (0,
|
|
13996
|
+
const mkdir = deps.mkdir ?? ((targetPath, options) => (0, import_node_fs10.mkdirSync)(targetPath, options));
|
|
13997
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs10.readFileSync)(filePath, "utf8"));
|
|
13998
|
+
const readDir = deps.readDir ?? ((dirPath) => (0, import_node_fs10.readdirSync)(dirPath));
|
|
13999
|
+
const writeFile = deps.writeFile ?? ((filePath, content) => (0, import_node_fs10.writeFileSync)(filePath, content, "utf8"));
|
|
13563
14000
|
const createZipArchive = deps.createZipArchive ?? defaultCreateZipArchive;
|
|
13564
14001
|
return async (request, context) => {
|
|
13565
14002
|
const [subcommand, ...restArgs] = request.args;
|
|
13566
|
-
const parsed =
|
|
14003
|
+
const parsed = parseArgs4(restArgs);
|
|
13567
14004
|
const requestedFormat = (parsed.flags["--format"] ?? "").trim().toLowerCase();
|
|
13568
14005
|
const outputFormat = parsed.boolFlags.has("--json") ? "json" : parsed.boolFlags.has("--feature") ? "feature" : requestedFormat || "text";
|
|
13569
14006
|
const config = resolveCliConfig(pickConfigArgs3(parsed), env, cwd);
|
|
@@ -13603,7 +14040,7 @@ function createBddHandler(deps = {}) {
|
|
|
13603
14040
|
stderr: ["ERROR: Missing required --output-dir for testops bdd features export."]
|
|
13604
14041
|
};
|
|
13605
14042
|
}
|
|
13606
|
-
const outputDir =
|
|
14043
|
+
const outputDir = import_node_path11.default.resolve(cwd, outputDirFlag);
|
|
13607
14044
|
try {
|
|
13608
14045
|
const result = await context.invokeForgeContract("listBddFeatures", {
|
|
13609
14046
|
context: {
|
|
@@ -13639,7 +14076,7 @@ function createBddHandler(deps = {}) {
|
|
|
13639
14076
|
`
|
|
13640
14077
|
}));
|
|
13641
14078
|
for (let index = 0; index < features.length; index += 1) {
|
|
13642
|
-
writeFile(
|
|
14079
|
+
writeFile(import_node_path11.default.join(outputDir, fileNames[index]), exportEntries[index].content);
|
|
13643
14080
|
}
|
|
13644
14081
|
const manifest = {
|
|
13645
14082
|
action: "bdd-features-export",
|
|
@@ -13652,7 +14089,7 @@ function createBddHandler(deps = {}) {
|
|
|
13652
14089
|
};
|
|
13653
14090
|
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
13654
14091
|
`;
|
|
13655
|
-
writeFile(
|
|
14092
|
+
writeFile(import_node_path11.default.join(outputDir, "manifest.json"), manifestContent);
|
|
13656
14093
|
const archivePath = `${outputDir}.zip`;
|
|
13657
14094
|
if (zipRequested) {
|
|
13658
14095
|
await createZipArchive(archivePath, [
|
|
@@ -13691,7 +14128,7 @@ function createBddHandler(deps = {}) {
|
|
|
13691
14128
|
} catch (error) {
|
|
13692
14129
|
return {
|
|
13693
14130
|
exitCode: ExitCode.TransportError,
|
|
13694
|
-
stderr: [`ERROR: ${
|
|
14131
|
+
stderr: [`ERROR: ${normalizeError3(error)}`]
|
|
13695
14132
|
};
|
|
13696
14133
|
}
|
|
13697
14134
|
}
|
|
@@ -13722,7 +14159,7 @@ function createBddHandler(deps = {}) {
|
|
|
13722
14159
|
stderr: ["ERROR: Missing required --output-dir for testops bdd scenarios export."]
|
|
13723
14160
|
};
|
|
13724
14161
|
}
|
|
13725
|
-
const outputDir =
|
|
14162
|
+
const outputDir = import_node_path11.default.resolve(cwd, outputDirFlag);
|
|
13726
14163
|
const zipRequested = parsed.boolFlags.has("--zip");
|
|
13727
14164
|
try {
|
|
13728
14165
|
const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
|
|
@@ -13757,7 +14194,7 @@ function createBddHandler(deps = {}) {
|
|
|
13757
14194
|
const fileName = scenarioToExportFileName(scenario);
|
|
13758
14195
|
const fileContent = `${scenarioToFeatureLines(scenario).join("\n")}
|
|
13759
14196
|
`;
|
|
13760
|
-
writeFile(
|
|
14197
|
+
writeFile(import_node_path11.default.join(outputDir, fileName), fileContent);
|
|
13761
14198
|
return {
|
|
13762
14199
|
scenario,
|
|
13763
14200
|
fileName,
|
|
@@ -13783,7 +14220,7 @@ function createBddHandler(deps = {}) {
|
|
|
13783
14220
|
};
|
|
13784
14221
|
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
13785
14222
|
`;
|
|
13786
|
-
writeFile(
|
|
14223
|
+
writeFile(import_node_path11.default.join(outputDir, "manifest.json"), manifestContent);
|
|
13787
14224
|
const archivePath = `${outputDir}.zip`;
|
|
13788
14225
|
if (zipRequested) {
|
|
13789
14226
|
await createZipArchive(archivePath, [
|
|
@@ -13826,13 +14263,13 @@ function createBddHandler(deps = {}) {
|
|
|
13826
14263
|
} catch (error) {
|
|
13827
14264
|
return {
|
|
13828
14265
|
exitCode: ExitCode.TransportError,
|
|
13829
|
-
stderr: [`ERROR: ${
|
|
14266
|
+
stderr: [`ERROR: ${normalizeError3(error)}`]
|
|
13830
14267
|
};
|
|
13831
14268
|
}
|
|
13832
14269
|
}
|
|
13833
14270
|
if (nested === "import") {
|
|
13834
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
13835
|
-
const inputDir = parsed.flags["--input-dir"] ?
|
|
14271
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path11.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
14272
|
+
const inputDir = parsed.flags["--input-dir"] ? import_node_path11.default.resolve(cwd, parsed.flags["--input-dir"]) : "";
|
|
13836
14273
|
const dryRun = parsed.boolFlags.has("--dry-run");
|
|
13837
14274
|
if (!sourceFile && !inputDir) {
|
|
13838
14275
|
return {
|
|
@@ -13841,7 +14278,7 @@ function createBddHandler(deps = {}) {
|
|
|
13841
14278
|
};
|
|
13842
14279
|
}
|
|
13843
14280
|
try {
|
|
13844
|
-
const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) =>
|
|
14281
|
+
const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) => import_node_path11.default.join(inputDir, entry)).sort((left, right) => left.localeCompare(right));
|
|
13845
14282
|
if (scenarioFiles.length === 0) {
|
|
13846
14283
|
return {
|
|
13847
14284
|
exitCode: ExitCode.ValidationError,
|
|
@@ -13980,7 +14417,7 @@ function createBddHandler(deps = {}) {
|
|
|
13980
14417
|
} catch (error) {
|
|
13981
14418
|
return {
|
|
13982
14419
|
exitCode: ExitCode.TransportError,
|
|
13983
|
-
stderr: [`ERROR: ${
|
|
14420
|
+
stderr: [`ERROR: ${normalizeError3(error)}`]
|
|
13984
14421
|
};
|
|
13985
14422
|
}
|
|
13986
14423
|
}
|
|
@@ -14083,7 +14520,7 @@ function createBddHandler(deps = {}) {
|
|
|
14083
14520
|
} catch (error) {
|
|
14084
14521
|
return {
|
|
14085
14522
|
exitCode: ExitCode.TransportError,
|
|
14086
|
-
stderr: [`ERROR: ${
|
|
14523
|
+
stderr: [`ERROR: ${normalizeError3(error)}`]
|
|
14087
14524
|
};
|
|
14088
14525
|
}
|
|
14089
14526
|
}
|
|
@@ -14136,7 +14573,7 @@ function createBddHandler(deps = {}) {
|
|
|
14136
14573
|
} catch (error) {
|
|
14137
14574
|
return {
|
|
14138
14575
|
exitCode: ExitCode.TransportError,
|
|
14139
|
-
stderr: [`ERROR: ${
|
|
14576
|
+
stderr: [`ERROR: ${normalizeError3(error)}`]
|
|
14140
14577
|
};
|
|
14141
14578
|
}
|
|
14142
14579
|
}
|
|
@@ -14157,7 +14594,7 @@ var CONFIG_FLAGS4 = /* @__PURE__ */ new Set([
|
|
|
14157
14594
|
"--jira-email",
|
|
14158
14595
|
"--jira-api-token"
|
|
14159
14596
|
]);
|
|
14160
|
-
function
|
|
14597
|
+
function parseArgs5(args) {
|
|
14161
14598
|
const flags = {};
|
|
14162
14599
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
14163
14600
|
const unknownFlags = [];
|
|
@@ -14195,7 +14632,7 @@ function pickConfigArgs4(parsed) {
|
|
|
14195
14632
|
}
|
|
14196
14633
|
return args;
|
|
14197
14634
|
}
|
|
14198
|
-
function
|
|
14635
|
+
function normalizeError4(error) {
|
|
14199
14636
|
if (error instanceof ForgeClientError) {
|
|
14200
14637
|
return `${error.code}: ${error.message}`;
|
|
14201
14638
|
}
|
|
@@ -14329,7 +14766,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14329
14766
|
const env = deps.env ?? process.env;
|
|
14330
14767
|
return async (request, context) => {
|
|
14331
14768
|
const [subcommand, ...restArgs] = request.args;
|
|
14332
|
-
const parsed =
|
|
14769
|
+
const parsed = parseArgs5(restArgs);
|
|
14333
14770
|
const useJson = parsed.boolFlags.has("--json");
|
|
14334
14771
|
const config = resolveCliConfig(pickConfigArgs4(parsed), env, cwd);
|
|
14335
14772
|
const projectKey = config.values.projectKey;
|
|
@@ -14376,7 +14813,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14376
14813
|
} catch (error) {
|
|
14377
14814
|
return {
|
|
14378
14815
|
exitCode: ExitCode.TransportError,
|
|
14379
|
-
stderr: [`ERROR: ${
|
|
14816
|
+
stderr: [`ERROR: ${normalizeError4(error)}`]
|
|
14380
14817
|
};
|
|
14381
14818
|
}
|
|
14382
14819
|
}
|
|
@@ -14418,7 +14855,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14418
14855
|
} catch (error) {
|
|
14419
14856
|
return {
|
|
14420
14857
|
exitCode: ExitCode.TransportError,
|
|
14421
|
-
stderr: [`ERROR: ${
|
|
14858
|
+
stderr: [`ERROR: ${normalizeError4(error)}`]
|
|
14422
14859
|
};
|
|
14423
14860
|
}
|
|
14424
14861
|
}
|
|
@@ -14481,7 +14918,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14481
14918
|
} catch (error) {
|
|
14482
14919
|
return {
|
|
14483
14920
|
exitCode: ExitCode.TransportError,
|
|
14484
|
-
stderr: [`ERROR: ${
|
|
14921
|
+
stderr: [`ERROR: ${normalizeError4(error)}`]
|
|
14485
14922
|
};
|
|
14486
14923
|
}
|
|
14487
14924
|
}
|
|
@@ -14544,7 +14981,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14544
14981
|
} catch (error) {
|
|
14545
14982
|
return {
|
|
14546
14983
|
exitCode: ExitCode.TransportError,
|
|
14547
|
-
stderr: [`ERROR: ${
|
|
14984
|
+
stderr: [`ERROR: ${normalizeError4(error)}`]
|
|
14548
14985
|
};
|
|
14549
14986
|
}
|
|
14550
14987
|
}
|
|
@@ -14556,6 +14993,7 @@ function createCasesHandler(deps = {}) {
|
|
|
14556
14993
|
}
|
|
14557
14994
|
|
|
14558
14995
|
// src/doctor.ts
|
|
14996
|
+
var import_node_child_process3 = require("node:child_process");
|
|
14559
14997
|
var CONFIG_FLAGS5 = /* @__PURE__ */ new Set([
|
|
14560
14998
|
"--config",
|
|
14561
14999
|
"--base-url",
|
|
@@ -14565,11 +15003,16 @@ var CONFIG_FLAGS5 = /* @__PURE__ */ new Set([
|
|
|
14565
15003
|
"--jira-email",
|
|
14566
15004
|
"--jira-api-token"
|
|
14567
15005
|
]);
|
|
14568
|
-
|
|
15006
|
+
var DIRECT_JIRA_FLAGS = /* @__PURE__ */ new Set([
|
|
15007
|
+
"--site",
|
|
15008
|
+
"--email",
|
|
15009
|
+
"--api-token"
|
|
15010
|
+
]);
|
|
15011
|
+
function parseArgs6(args) {
|
|
14569
15012
|
const flags = {};
|
|
14570
15013
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
14571
15014
|
const unknownFlags = [];
|
|
14572
|
-
const valuedFlags = /* @__PURE__ */ new Set([...CONFIG_FLAGS5]);
|
|
15015
|
+
const valuedFlags = /* @__PURE__ */ new Set([...CONFIG_FLAGS5, ...DIRECT_JIRA_FLAGS]);
|
|
14573
15016
|
const supportedBoolFlags = /* @__PURE__ */ new Set(["--json", "--check-context"]);
|
|
14574
15017
|
for (let i = 0; i < args.length; i += 1) {
|
|
14575
15018
|
const token = args[i];
|
|
@@ -14635,6 +15078,49 @@ function checkFromServiceResult(result) {
|
|
|
14635
15078
|
message: `Forge endpoint reachable (service returned ${result.error.code}).`
|
|
14636
15079
|
};
|
|
14637
15080
|
}
|
|
15081
|
+
function normalizeSite3(value) {
|
|
15082
|
+
return value.trim().replace(/\/+$/, "");
|
|
15083
|
+
}
|
|
15084
|
+
function hasValue(value) {
|
|
15085
|
+
return value.trim().length > 0;
|
|
15086
|
+
}
|
|
15087
|
+
function resolveAllureJiraConfig(parsed, env, cwd) {
|
|
15088
|
+
const resolution = resolveCliConfig(pickConfigArgs5(parsed), env, cwd);
|
|
15089
|
+
const site = normalizeSite3(parsed.flags["--site"] ?? env.JIRA_SITE ?? resolution.values.baseUrl);
|
|
15090
|
+
const email = (parsed.flags["--email"] ?? resolution.values.jiraEmail).trim();
|
|
15091
|
+
const apiToken = (parsed.flags["--api-token"] ?? resolution.values.jiraApiToken).trim();
|
|
15092
|
+
const issueKey = (parsed.flags["--issue-key"] ?? "").trim();
|
|
15093
|
+
const errors = [];
|
|
15094
|
+
if (!hasValue(site)) {
|
|
15095
|
+
errors.push("Missing Jira site. Pass --site, set JIRA_SITE/JIRA_BASE_URL, or configure baseUrl.");
|
|
15096
|
+
}
|
|
15097
|
+
if (!hasValue(email)) {
|
|
15098
|
+
errors.push("Missing Jira email. Pass --email or set JIRA_EMAIL.");
|
|
15099
|
+
}
|
|
15100
|
+
if (!hasValue(apiToken)) {
|
|
15101
|
+
errors.push("Missing Jira API token. Pass --api-token or set JIRA_API_TOKEN.");
|
|
15102
|
+
}
|
|
15103
|
+
return { site, email, apiToken, issueKey, errors };
|
|
15104
|
+
}
|
|
15105
|
+
function commandCheck(deps, command, args, passMessage, warnMessage) {
|
|
15106
|
+
try {
|
|
15107
|
+
deps.execFileSync(command, [...args], {
|
|
15108
|
+
encoding: "utf8",
|
|
15109
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
15110
|
+
});
|
|
15111
|
+
return {
|
|
15112
|
+
name: command,
|
|
15113
|
+
status: "pass",
|
|
15114
|
+
message: passMessage
|
|
15115
|
+
};
|
|
15116
|
+
} catch {
|
|
15117
|
+
return {
|
|
15118
|
+
name: command,
|
|
15119
|
+
status: "warn",
|
|
15120
|
+
message: warnMessage
|
|
15121
|
+
};
|
|
15122
|
+
}
|
|
15123
|
+
}
|
|
14638
15124
|
function toJsonPayload(summary) {
|
|
14639
15125
|
return {
|
|
14640
15126
|
status: summary.status,
|
|
@@ -14667,9 +15153,11 @@ function toHumanLines2(summary) {
|
|
|
14667
15153
|
function createDoctorHandler(deps = {}) {
|
|
14668
15154
|
const cwd = deps.cwd ?? process.cwd();
|
|
14669
15155
|
const env = deps.env ?? process.env;
|
|
15156
|
+
const runCommand = deps.execFileSync ?? import_node_child_process3.execFileSync;
|
|
15157
|
+
const listAttachments = deps.listIssueAttachments ?? listIssueAttachments;
|
|
14670
15158
|
return async (request, context) => {
|
|
14671
|
-
const [, ...subArgs] = request.args;
|
|
14672
|
-
const parsed =
|
|
15159
|
+
const [subcommand, ...subArgs] = request.args;
|
|
15160
|
+
const parsed = parseArgs6(subArgs);
|
|
14673
15161
|
const useJson = parsed.boolFlags.has("--json");
|
|
14674
15162
|
const enforceContextCheck = parsed.boolFlags.has("--check-context");
|
|
14675
15163
|
const checks = [];
|
|
@@ -14685,6 +15173,70 @@ function createDoctorHandler(deps = {}) {
|
|
|
14685
15173
|
stdout: useJson ? toJsonLine(toJsonPayload(summary2)) : toHumanLines2(summary2)
|
|
14686
15174
|
};
|
|
14687
15175
|
}
|
|
15176
|
+
if (subcommand === "allure") {
|
|
15177
|
+
const config = resolveAllureJiraConfig(parsed, env, cwd);
|
|
15178
|
+
checks.push({
|
|
15179
|
+
name: "allure_jira_credentials",
|
|
15180
|
+
status: config.errors.length === 0 ? "pass" : "fail",
|
|
15181
|
+
message: config.errors.length === 0 ? "Jira site, email, and API token are configured for Allure upload/download." : config.errors.join(" ")
|
|
15182
|
+
});
|
|
15183
|
+
if (config.issueKey && config.errors.length === 0) {
|
|
15184
|
+
try {
|
|
15185
|
+
const attachments = await listAttachments({
|
|
15186
|
+
site: config.site,
|
|
15187
|
+
email: config.email,
|
|
15188
|
+
apiToken: config.apiToken,
|
|
15189
|
+
issueKey: config.issueKey
|
|
15190
|
+
});
|
|
15191
|
+
checks.push({
|
|
15192
|
+
name: "allure_jira_issue_access",
|
|
15193
|
+
status: "pass",
|
|
15194
|
+
message: `Jira issue ${config.issueKey} is reachable; ${attachments.length} attachment(s) visible.`
|
|
15195
|
+
});
|
|
15196
|
+
} catch (error) {
|
|
15197
|
+
checks.push({
|
|
15198
|
+
name: "allure_jira_issue_access",
|
|
15199
|
+
status: "fail",
|
|
15200
|
+
message: normalizeConnectivityError(error)
|
|
15201
|
+
});
|
|
15202
|
+
}
|
|
15203
|
+
} else if (!config.issueKey) {
|
|
15204
|
+
checks.push({
|
|
15205
|
+
name: "allure_jira_issue_access",
|
|
15206
|
+
status: "skip",
|
|
15207
|
+
message: "Issue access check skipped. Pass --issue-key to verify Jira read/download access for a specific issue."
|
|
15208
|
+
});
|
|
15209
|
+
}
|
|
15210
|
+
checks.push(commandCheck(
|
|
15211
|
+
{ execFileSync: runCommand },
|
|
15212
|
+
"unzip",
|
|
15213
|
+
["-v"],
|
|
15214
|
+
"unzip is available for manual ZIP inspection.",
|
|
15215
|
+
"unzip was not found. The future built-in opener can avoid this, but manual inspection will be less convenient."
|
|
15216
|
+
));
|
|
15217
|
+
checks.push(commandCheck(
|
|
15218
|
+
{ execFileSync: runCommand },
|
|
15219
|
+
"java",
|
|
15220
|
+
["-version"],
|
|
15221
|
+
"Java is available for optional raw allure-results workflows.",
|
|
15222
|
+
"Java was not found. This does not block generated Allure HTML ZIP upload/download/open; it only matters for raw allure-results generation."
|
|
15223
|
+
));
|
|
15224
|
+
checks.push(commandCheck(
|
|
15225
|
+
{ execFileSync: runCommand },
|
|
15226
|
+
"allure",
|
|
15227
|
+
["--version"],
|
|
15228
|
+
"Allure CLI is available for optional raw allure-results workflows.",
|
|
15229
|
+
"Allure CLI was not found. This does not block generated Allure HTML ZIP upload/download/open."
|
|
15230
|
+
));
|
|
15231
|
+
const summary2 = {
|
|
15232
|
+
status: computeOverallStatus(checks),
|
|
15233
|
+
checks
|
|
15234
|
+
};
|
|
15235
|
+
return {
|
|
15236
|
+
exitCode: pickDoctorExitCode(summary2),
|
|
15237
|
+
stdout: useJson ? toJsonLine(toJsonPayload(summary2)) : toHumanLines2(summary2)
|
|
15238
|
+
};
|
|
15239
|
+
}
|
|
14688
15240
|
const configArgs = pickConfigArgs5(parsed);
|
|
14689
15241
|
const resolution = resolveCliConfig(configArgs, env, cwd);
|
|
14690
15242
|
const configValidation = validateCliConfigResolution(resolution);
|
|
@@ -14773,8 +15325,8 @@ function createDoctorHandler(deps = {}) {
|
|
|
14773
15325
|
}
|
|
14774
15326
|
|
|
14775
15327
|
// src/ingestFeature.ts
|
|
14776
|
-
var
|
|
14777
|
-
var
|
|
15328
|
+
var import_node_fs11 = require("node:fs");
|
|
15329
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
14778
15330
|
var CONFIG_FLAGS6 = /* @__PURE__ */ new Set([
|
|
14779
15331
|
"--config",
|
|
14780
15332
|
"--base-url",
|
|
@@ -14784,7 +15336,7 @@ var CONFIG_FLAGS6 = /* @__PURE__ */ new Set([
|
|
|
14784
15336
|
"--jira-email",
|
|
14785
15337
|
"--jira-api-token"
|
|
14786
15338
|
]);
|
|
14787
|
-
function
|
|
15339
|
+
function parseArgs7(args) {
|
|
14788
15340
|
const flags = {};
|
|
14789
15341
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
14790
15342
|
const unknownFlags = [];
|
|
@@ -14850,7 +15402,7 @@ function summarizeSuccess(result) {
|
|
|
14850
15402
|
}
|
|
14851
15403
|
return lines;
|
|
14852
15404
|
}
|
|
14853
|
-
function
|
|
15405
|
+
function normalizeError5(error) {
|
|
14854
15406
|
if (error instanceof ForgeClientError) {
|
|
14855
15407
|
return `${error.code}: ${error.message}`;
|
|
14856
15408
|
}
|
|
@@ -14860,18 +15412,18 @@ function normalizeError4(error) {
|
|
|
14860
15412
|
return "Unknown ingest error.";
|
|
14861
15413
|
}
|
|
14862
15414
|
function createIngestFeatureHandler(deps = {}) {
|
|
14863
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
14864
|
-
const readStdin = deps.readStdin ?? (() => (0,
|
|
15415
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs11.readFileSync)(filePath, "utf8"));
|
|
15416
|
+
const readStdin = deps.readStdin ?? (() => (0, import_node_fs11.readFileSync)(0, "utf8"));
|
|
14865
15417
|
const cwd = deps.cwd ?? process.cwd();
|
|
14866
15418
|
const env = deps.env ?? process.env;
|
|
14867
15419
|
return async (request, context) => {
|
|
14868
15420
|
const [, ...subArgs] = request.args;
|
|
14869
|
-
const parsed =
|
|
15421
|
+
const parsed = parseArgs7(subArgs);
|
|
14870
15422
|
const configArgs = pickConfigArgs6(parsed);
|
|
14871
15423
|
const config = resolveCliConfig(configArgs, env, cwd);
|
|
14872
15424
|
const projectKey = config.values.projectKey;
|
|
14873
15425
|
const issueKey = config.values.issueKey;
|
|
14874
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
15426
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path12.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
14875
15427
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
14876
15428
|
const useJson = parsed.boolFlags.has("--json");
|
|
14877
15429
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -14887,7 +15439,7 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
14887
15439
|
} catch (error) {
|
|
14888
15440
|
return {
|
|
14889
15441
|
exitCode: ExitCode.InternalError,
|
|
14890
|
-
stderr: [`ERROR: Failed to read feature source: ${
|
|
15442
|
+
stderr: [`ERROR: Failed to read feature source: ${normalizeError5(error)}`]
|
|
14891
15443
|
};
|
|
14892
15444
|
}
|
|
14893
15445
|
const name = (parsed.flags["--name"] ?? deriveNameFromGherkin(gherkin)).trim();
|
|
@@ -14982,7 +15534,7 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
14982
15534
|
status: "failed",
|
|
14983
15535
|
featureName: name,
|
|
14984
15536
|
source: useStdin ? "stdin" : sourceFile,
|
|
14985
|
-
errorMessage:
|
|
15537
|
+
errorMessage: normalizeError5(error)
|
|
14986
15538
|
})
|
|
14987
15539
|
};
|
|
14988
15540
|
}
|
|
@@ -14993,15 +15545,15 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
14993
15545
|
`Feature: ${name}`,
|
|
14994
15546
|
`Source: ${useStdin ? "stdin" : sourceFile}`
|
|
14995
15547
|
],
|
|
14996
|
-
stderr: [`ERROR: ${
|
|
15548
|
+
stderr: [`ERROR: ${normalizeError5(error)}`]
|
|
14997
15549
|
};
|
|
14998
15550
|
}
|
|
14999
15551
|
};
|
|
15000
15552
|
}
|
|
15001
15553
|
|
|
15002
15554
|
// src/runUpload.ts
|
|
15003
|
-
var
|
|
15004
|
-
var
|
|
15555
|
+
var import_node_fs12 = require("node:fs");
|
|
15556
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
15005
15557
|
var STEP_RESULTS = [
|
|
15006
15558
|
StepResult.Passed,
|
|
15007
15559
|
StepResult.Failed,
|
|
@@ -15017,7 +15569,7 @@ var CONFIG_FLAGS7 = /* @__PURE__ */ new Set([
|
|
|
15017
15569
|
"--jira-email",
|
|
15018
15570
|
"--jira-api-token"
|
|
15019
15571
|
]);
|
|
15020
|
-
function
|
|
15572
|
+
function parseArgs8(args) {
|
|
15021
15573
|
const flags = {};
|
|
15022
15574
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
15023
15575
|
const unknownFlags = [];
|
|
@@ -15063,7 +15615,7 @@ function pickConfigArgs7(parsed) {
|
|
|
15063
15615
|
}
|
|
15064
15616
|
return configArgs;
|
|
15065
15617
|
}
|
|
15066
|
-
function
|
|
15618
|
+
function normalizeError6(error) {
|
|
15067
15619
|
if (error instanceof ForgeClientError) {
|
|
15068
15620
|
return `${error.code}: ${error.message}`;
|
|
15069
15621
|
}
|
|
@@ -15142,19 +15694,19 @@ function summarizeRunResult(result) {
|
|
|
15142
15694
|
return lines;
|
|
15143
15695
|
}
|
|
15144
15696
|
function createRunUploadHandler(deps = {}) {
|
|
15145
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
15146
|
-
const readStdin = deps.readStdin ?? (() => (0,
|
|
15697
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs12.readFileSync)(filePath, "utf8"));
|
|
15698
|
+
const readStdin = deps.readStdin ?? (() => (0, import_node_fs12.readFileSync)(0, "utf8"));
|
|
15147
15699
|
const cwd = deps.cwd ?? process.cwd();
|
|
15148
15700
|
const env = deps.env ?? process.env;
|
|
15149
15701
|
return async (request, context) => {
|
|
15150
15702
|
const [, ...subArgs] = request.args;
|
|
15151
|
-
const parsed =
|
|
15703
|
+
const parsed = parseArgs8(subArgs);
|
|
15152
15704
|
const configArgs = pickConfigArgs7(parsed);
|
|
15153
15705
|
const config = resolveCliConfig(configArgs, env, cwd);
|
|
15154
15706
|
const projectKey = config.values.projectKey;
|
|
15155
15707
|
const issueKey = config.values.issueKey;
|
|
15156
15708
|
const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
|
|
15157
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
15709
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path13.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
15158
15710
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
15159
15711
|
const useJson = parsed.boolFlags.has("--json");
|
|
15160
15712
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -15182,7 +15734,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
15182
15734
|
} catch (error) {
|
|
15183
15735
|
return {
|
|
15184
15736
|
exitCode: ExitCode.InternalError,
|
|
15185
|
-
stderr: [`ERROR: Failed to read run payload source: ${
|
|
15737
|
+
stderr: [`ERROR: Failed to read run payload source: ${normalizeError6(error)}`]
|
|
15186
15738
|
};
|
|
15187
15739
|
}
|
|
15188
15740
|
const payloadFromSource = parseRunPayload(raw);
|
|
@@ -15212,7 +15764,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
15212
15764
|
} catch (error) {
|
|
15213
15765
|
return {
|
|
15214
15766
|
exitCode: ExitCode.TransportError,
|
|
15215
|
-
stderr: [`ERROR: ${
|
|
15767
|
+
stderr: [`ERROR: ${normalizeError6(error)}`]
|
|
15216
15768
|
};
|
|
15217
15769
|
}
|
|
15218
15770
|
}
|
|
@@ -15292,7 +15844,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
15292
15844
|
featureName: runInput.featureName,
|
|
15293
15845
|
scenarioName: runInput.scenarioName,
|
|
15294
15846
|
executedAt: runInput.executedAt,
|
|
15295
|
-
errorMessage:
|
|
15847
|
+
errorMessage: normalizeError6(error)
|
|
15296
15848
|
})
|
|
15297
15849
|
};
|
|
15298
15850
|
}
|
|
@@ -15304,7 +15856,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
15304
15856
|
`Scenario: ${runInput.scenarioName}`,
|
|
15305
15857
|
`ExecutedAt: ${runInput.executedAt}`
|
|
15306
15858
|
],
|
|
15307
|
-
stderr: [`ERROR: ${
|
|
15859
|
+
stderr: [`ERROR: ${normalizeError6(error)}`]
|
|
15308
15860
|
};
|
|
15309
15861
|
}
|
|
15310
15862
|
};
|
|
@@ -15320,7 +15872,7 @@ var CONFIG_FLAGS8 = /* @__PURE__ */ new Set([
|
|
|
15320
15872
|
"--jira-email",
|
|
15321
15873
|
"--jira-api-token"
|
|
15322
15874
|
]);
|
|
15323
|
-
function
|
|
15875
|
+
function parseArgs9(args) {
|
|
15324
15876
|
const flags = {};
|
|
15325
15877
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
15326
15878
|
const unknownFlags = [];
|
|
@@ -15358,7 +15910,7 @@ function pickConfigArgs8(parsed) {
|
|
|
15358
15910
|
}
|
|
15359
15911
|
return args;
|
|
15360
15912
|
}
|
|
15361
|
-
function
|
|
15913
|
+
function normalizeError7(error) {
|
|
15362
15914
|
if (error instanceof ForgeClientError) {
|
|
15363
15915
|
return `${error.code}: ${error.message}`;
|
|
15364
15916
|
}
|
|
@@ -15422,7 +15974,7 @@ function createRunsHandler(deps = {}) {
|
|
|
15422
15974
|
const env = deps.env ?? process.env;
|
|
15423
15975
|
return async (request, context) => {
|
|
15424
15976
|
const [subcommand, ...restArgs] = request.args;
|
|
15425
|
-
const parsed =
|
|
15977
|
+
const parsed = parseArgs9(restArgs);
|
|
15426
15978
|
const useJson = parsed.boolFlags.has("--json");
|
|
15427
15979
|
const config = resolveCliConfig(pickConfigArgs8(parsed), env, cwd);
|
|
15428
15980
|
const projectKey = config.values.projectKey;
|
|
@@ -15476,7 +16028,7 @@ function createRunsHandler(deps = {}) {
|
|
|
15476
16028
|
} catch (error) {
|
|
15477
16029
|
return {
|
|
15478
16030
|
exitCode: ExitCode.TransportError,
|
|
15479
|
-
stderr: [`ERROR: ${
|
|
16031
|
+
stderr: [`ERROR: ${normalizeError7(error)}`]
|
|
15480
16032
|
};
|
|
15481
16033
|
}
|
|
15482
16034
|
}
|
|
@@ -15497,7 +16049,7 @@ var CONFIG_FLAGS9 = /* @__PURE__ */ new Set([
|
|
|
15497
16049
|
"--jira-email",
|
|
15498
16050
|
"--jira-api-token"
|
|
15499
16051
|
]);
|
|
15500
|
-
function
|
|
16052
|
+
function parseArgs10(args) {
|
|
15501
16053
|
const flags = {};
|
|
15502
16054
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
15503
16055
|
const unknownFlags = [];
|
|
@@ -15535,7 +16087,7 @@ function pickConfigArgs9(parsed) {
|
|
|
15535
16087
|
}
|
|
15536
16088
|
return args;
|
|
15537
16089
|
}
|
|
15538
|
-
function
|
|
16090
|
+
function normalizeError8(error) {
|
|
15539
16091
|
if (error instanceof ForgeClientError) {
|
|
15540
16092
|
return `${error.code}: ${error.message}`;
|
|
15541
16093
|
}
|
|
@@ -15617,7 +16169,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
15617
16169
|
const env = deps.env ?? process.env;
|
|
15618
16170
|
return async (request, context) => {
|
|
15619
16171
|
const [subcommand, ...restArgs] = request.args;
|
|
15620
|
-
const parsed =
|
|
16172
|
+
const parsed = parseArgs10(restArgs);
|
|
15621
16173
|
const useJson = parsed.boolFlags.has("--json");
|
|
15622
16174
|
const config = resolveCliConfig(pickConfigArgs9(parsed), env, cwd);
|
|
15623
16175
|
const projectKey = config.values.projectKey;
|
|
@@ -15664,7 +16216,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
15664
16216
|
} catch (error) {
|
|
15665
16217
|
return {
|
|
15666
16218
|
exitCode: ExitCode.TransportError,
|
|
15667
|
-
stderr: [`ERROR: ${
|
|
16219
|
+
stderr: [`ERROR: ${normalizeError8(error)}`]
|
|
15668
16220
|
};
|
|
15669
16221
|
}
|
|
15670
16222
|
}
|
|
@@ -15705,7 +16257,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
15705
16257
|
} catch (error) {
|
|
15706
16258
|
return {
|
|
15707
16259
|
exitCode: ExitCode.TransportError,
|
|
15708
|
-
stderr: [`ERROR: ${
|
|
16260
|
+
stderr: [`ERROR: ${normalizeError8(error)}`]
|
|
15709
16261
|
};
|
|
15710
16262
|
}
|
|
15711
16263
|
}
|
|
@@ -15769,7 +16321,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
15769
16321
|
} catch (error) {
|
|
15770
16322
|
return {
|
|
15771
16323
|
exitCode: ExitCode.TransportError,
|
|
15772
|
-
stderr: [`ERROR: ${
|
|
16324
|
+
stderr: [`ERROR: ${normalizeError8(error)}`]
|
|
15773
16325
|
};
|
|
15774
16326
|
}
|
|
15775
16327
|
}
|
|
@@ -15791,7 +16343,7 @@ var CONFIG_FLAGS10 = /* @__PURE__ */ new Set([
|
|
|
15791
16343
|
"--jira-api-token"
|
|
15792
16344
|
]);
|
|
15793
16345
|
var RECONCILE_CONFIRM_TOKEN = "RECONCILE";
|
|
15794
|
-
function
|
|
16346
|
+
function parseArgs11(args) {
|
|
15795
16347
|
const flags = {};
|
|
15796
16348
|
const boolFlags = /* @__PURE__ */ new Set();
|
|
15797
16349
|
const unknownFlags = [];
|
|
@@ -15829,7 +16381,7 @@ function pickConfigArgs10(parsed) {
|
|
|
15829
16381
|
}
|
|
15830
16382
|
return args;
|
|
15831
16383
|
}
|
|
15832
|
-
function
|
|
16384
|
+
function normalizeError9(error) {
|
|
15833
16385
|
if (error instanceof ForgeClientError) {
|
|
15834
16386
|
return `${error.code}: ${error.message}`;
|
|
15835
16387
|
}
|
|
@@ -15880,7 +16432,7 @@ function createSyncHandler(deps = {}) {
|
|
|
15880
16432
|
const env = deps.env ?? process.env;
|
|
15881
16433
|
return async (request, context) => {
|
|
15882
16434
|
const [subcommand, ...restArgs] = request.args;
|
|
15883
|
-
const parsed =
|
|
16435
|
+
const parsed = parseArgs11(restArgs);
|
|
15884
16436
|
const useJson = parsed.boolFlags.has("--json");
|
|
15885
16437
|
const config = resolveCliConfig(pickConfigArgs10(parsed), env, cwd);
|
|
15886
16438
|
const projectKey = config.values.projectKey;
|
|
@@ -15932,7 +16484,7 @@ function createSyncHandler(deps = {}) {
|
|
|
15932
16484
|
} catch (error) {
|
|
15933
16485
|
return {
|
|
15934
16486
|
exitCode: ExitCode.TransportError,
|
|
15935
|
-
stderr: [`ERROR: ${
|
|
16487
|
+
stderr: [`ERROR: ${normalizeError9(error)}`]
|
|
15936
16488
|
};
|
|
15937
16489
|
}
|
|
15938
16490
|
}
|
|
@@ -15978,7 +16530,7 @@ function createSyncHandler(deps = {}) {
|
|
|
15978
16530
|
} catch (error) {
|
|
15979
16531
|
return {
|
|
15980
16532
|
exitCode: ExitCode.TransportError,
|
|
15981
|
-
stderr: [`ERROR: ${
|
|
16533
|
+
stderr: [`ERROR: ${normalizeError9(error)}`]
|
|
15982
16534
|
};
|
|
15983
16535
|
}
|
|
15984
16536
|
}
|
|
@@ -15993,8 +16545,8 @@ function createSyncHandler(deps = {}) {
|
|
|
15993
16545
|
var COMMAND_REGISTRY = [
|
|
15994
16546
|
{
|
|
15995
16547
|
name: "allure",
|
|
15996
|
-
description: "Allure evidence upload/download commands for Jira issues",
|
|
15997
|
-
subcommands: ["upload", "download"],
|
|
16548
|
+
description: "Allure evidence upload/download/open commands for Jira issues",
|
|
16549
|
+
subcommands: ["upload", "download", "open"],
|
|
15998
16550
|
handler: createAllureHandler()
|
|
15999
16551
|
},
|
|
16000
16552
|
{
|
|
@@ -16049,7 +16601,7 @@ var COMMAND_REGISTRY = [
|
|
|
16049
16601
|
{
|
|
16050
16602
|
name: "doctor",
|
|
16051
16603
|
description: "Preflight and health checks",
|
|
16052
|
-
subcommands: ["check"],
|
|
16604
|
+
subcommands: ["check", "allure"],
|
|
16053
16605
|
handler: createDoctorHandler()
|
|
16054
16606
|
},
|
|
16055
16607
|
{
|
|
@@ -16234,6 +16786,7 @@ function showTopLevelHelp() {
|
|
|
16234
16786
|
"",
|
|
16235
16787
|
"Available products:",
|
|
16236
16788
|
" testops TestOps \u2014 test management, BDD, execution, reporting",
|
|
16789
|
+
" allure Allure evidence diagnostics and local report workflows (doctor, open)",
|
|
16237
16790
|
"",
|
|
16238
16791
|
"Boundary:",
|
|
16239
16792
|
" Thin client over Forge contracts or Jira Cloud APIs.",
|
|
@@ -16243,6 +16796,29 @@ function showTopLevelHelp() {
|
|
|
16243
16796
|
console.log(line);
|
|
16244
16797
|
}
|
|
16245
16798
|
}
|
|
16799
|
+
function showAllureHelp() {
|
|
16800
|
+
const lines = [
|
|
16801
|
+
"Automatify Allure",
|
|
16802
|
+
"",
|
|
16803
|
+
"Usage:",
|
|
16804
|
+
" automatify allure doctor [options]",
|
|
16805
|
+
" automatify allure open <zipPath> [options]",
|
|
16806
|
+
"",
|
|
16807
|
+
"Commands:",
|
|
16808
|
+
" doctor Check local Allure/Jira readiness",
|
|
16809
|
+
" open Extract a generated Allure HTML report ZIP and serve it locally",
|
|
16810
|
+
"",
|
|
16811
|
+
"Examples:",
|
|
16812
|
+
" automatify allure doctor",
|
|
16813
|
+
" automatify allure doctor --json",
|
|
16814
|
+
" automatify allure doctor --issue-key ABC-123",
|
|
16815
|
+
" automatify allure open ./allure-report.zip",
|
|
16816
|
+
" automatify allure open ./allure-report.zip --port 8080 --no-open"
|
|
16817
|
+
];
|
|
16818
|
+
for (const line of lines) {
|
|
16819
|
+
console.log(line);
|
|
16820
|
+
}
|
|
16821
|
+
}
|
|
16246
16822
|
async function main() {
|
|
16247
16823
|
const args = process.argv.slice(2);
|
|
16248
16824
|
const [productArg, ...restArgs] = args;
|
|
@@ -16251,6 +16827,28 @@ async function main() {
|
|
|
16251
16827
|
process.exitCode = 0;
|
|
16252
16828
|
return;
|
|
16253
16829
|
}
|
|
16830
|
+
if (productArg === "allure") {
|
|
16831
|
+
const [commandArg, ...commandRest] = restArgs;
|
|
16832
|
+
if (!commandArg || commandArg === "--help" || commandArg === "-h" || commandArg === "help") {
|
|
16833
|
+
showAllureHelp();
|
|
16834
|
+
process.exitCode = 0;
|
|
16835
|
+
return;
|
|
16836
|
+
}
|
|
16837
|
+
if (commandArg === "doctor") {
|
|
16838
|
+
const exitCode2 = await runCli(["doctor", "allure", ...commandRest]);
|
|
16839
|
+
process.exitCode = exitCode2;
|
|
16840
|
+
return;
|
|
16841
|
+
}
|
|
16842
|
+
if (commandArg === "open") {
|
|
16843
|
+
const exitCode2 = await runCli(["allure", "open", ...commandRest]);
|
|
16844
|
+
process.exitCode = exitCode2;
|
|
16845
|
+
return;
|
|
16846
|
+
}
|
|
16847
|
+
console.error(`Unknown allure command: ${commandArg}`);
|
|
16848
|
+
console.error("Run `automatify allure --help` to see available commands.");
|
|
16849
|
+
process.exitCode = 1;
|
|
16850
|
+
return;
|
|
16851
|
+
}
|
|
16254
16852
|
if (productArg !== "testops") {
|
|
16255
16853
|
console.error(`Unknown product: ${productArg}`);
|
|
16256
16854
|
console.error("Run `automatify --help` to see available products.");
|