@automatify-au/cli 0.1.16 → 0.1.18
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 +37 -21
- package/dist/automatify.cjs +450 -194
- 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(path17) {
|
|
2898
|
+
var parts = path17.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(path17) {
|
|
8752
|
+
if (path17.slice(-1) === "/") {
|
|
8753
|
+
path17 = path17.substring(0, path17.length - 1);
|
|
8754
8754
|
}
|
|
8755
|
-
var lastSlash =
|
|
8756
|
-
return lastSlash > 0 ?
|
|
8755
|
+
var lastSlash = path17.lastIndexOf("/");
|
|
8756
|
+
return lastSlash > 0 ? path17.substring(0, lastSlash) : "";
|
|
8757
8757
|
};
|
|
8758
|
-
var forceTrailingSlash = function(
|
|
8759
|
-
if (
|
|
8760
|
-
|
|
8758
|
+
var forceTrailingSlash = function(path17) {
|
|
8759
|
+
if (path17.slice(-1) !== "/") {
|
|
8760
|
+
path17 += "/";
|
|
8761
8761
|
}
|
|
8762
|
-
return
|
|
8762
|
+
return path17;
|
|
8763
8763
|
};
|
|
8764
8764
|
var folderAdd = function(name, createFolders) {
|
|
8765
8765
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -10720,8 +10720,8 @@ function toJsonLine(data) {
|
|
|
10720
10720
|
}
|
|
10721
10721
|
|
|
10722
10722
|
// src/auto.ts
|
|
10723
|
-
var
|
|
10724
|
-
var
|
|
10723
|
+
var import_node_fs5 = require("node:fs");
|
|
10724
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
10725
10725
|
|
|
10726
10726
|
// ../../packages/shared-types/dist/entitlements.js
|
|
10727
10727
|
var UNLIMITED_ACTIVE_USERS = Number.MAX_SAFE_INTEGER;
|
|
@@ -10764,12 +10764,19 @@ var Priority;
|
|
|
10764
10764
|
})(Priority || (Priority = {}));
|
|
10765
10765
|
|
|
10766
10766
|
// src/config.ts
|
|
10767
|
-
var
|
|
10768
|
-
var
|
|
10767
|
+
var import_node_fs2 = require("node:fs");
|
|
10768
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
10769
10769
|
|
|
10770
10770
|
// src/secureStore.ts
|
|
10771
10771
|
var import_node_child_process = require("node:child_process");
|
|
10772
|
+
var import_node_crypto = require("node:crypto");
|
|
10773
|
+
var import_node_fs = require("node:fs");
|
|
10774
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
10772
10775
|
var KEYCHAIN_SERVICE = "automatify-testops-cli";
|
|
10776
|
+
var LINUX_SECURE_STORE_ENV = "TESTOPS_LINUX_SECURE_STORE";
|
|
10777
|
+
var LINUX_PROTECTED_PREFIX = "linux-aes-gcm-v1";
|
|
10778
|
+
var LINUX_JIRA_ACCOUNT_SUFFIX = ":jiraApiToken";
|
|
10779
|
+
var LINUX_KEY_FILENAME = ".testops-cli.key";
|
|
10773
10780
|
function errorText(error) {
|
|
10774
10781
|
return error instanceof Error && error.message ? error.message : "unknown secure-storage error";
|
|
10775
10782
|
}
|
|
@@ -10809,11 +10816,85 @@ function macOSKeychainWriteInput(account, value) {
|
|
|
10809
10816
|
quoteSecurityInteractiveArg(value)
|
|
10810
10817
|
].join(" ") + "\n";
|
|
10811
10818
|
}
|
|
10819
|
+
function linuxSecureStoreEnabled() {
|
|
10820
|
+
return process.env[LINUX_SECURE_STORE_ENV]?.trim() === "1";
|
|
10821
|
+
}
|
|
10822
|
+
function isLinuxProtectedValue(value) {
|
|
10823
|
+
return Boolean(value?.startsWith(`${LINUX_PROTECTED_PREFIX}.`));
|
|
10824
|
+
}
|
|
10825
|
+
function linuxConfigPathForAccount(account) {
|
|
10826
|
+
const normalized = account.endsWith(LINUX_JIRA_ACCOUNT_SUFFIX) ? account.slice(0, -LINUX_JIRA_ACCOUNT_SUFFIX.length) : account;
|
|
10827
|
+
return import_node_path.default.resolve(normalized);
|
|
10828
|
+
}
|
|
10829
|
+
function linuxKeyPathForAccount(account) {
|
|
10830
|
+
return import_node_path.default.join(import_node_path.default.dirname(linuxConfigPathForAccount(account)), LINUX_KEY_FILENAME);
|
|
10831
|
+
}
|
|
10832
|
+
function readLinuxKey(keyPath) {
|
|
10833
|
+
const key = (0, import_node_fs.readFileSync)(keyPath);
|
|
10834
|
+
if (key.length !== 32) {
|
|
10835
|
+
throw new Error(`Linux secure-store key at ${keyPath} must be exactly 32 bytes.`);
|
|
10836
|
+
}
|
|
10837
|
+
return key;
|
|
10838
|
+
}
|
|
10839
|
+
function readOrCreateLinuxKey(keyPath) {
|
|
10840
|
+
const directory = import_node_path.default.dirname(keyPath);
|
|
10841
|
+
(0, import_node_fs.mkdirSync)(directory, { recursive: true, mode: 448 });
|
|
10842
|
+
(0, import_node_fs.chmodSync)(directory, 448);
|
|
10843
|
+
if ((0, import_node_fs.existsSync)(keyPath)) {
|
|
10844
|
+
(0, import_node_fs.chmodSync)(keyPath, 384);
|
|
10845
|
+
return readLinuxKey(keyPath);
|
|
10846
|
+
}
|
|
10847
|
+
const key = (0, import_node_crypto.randomBytes)(32);
|
|
10848
|
+
try {
|
|
10849
|
+
(0, import_node_fs.writeFileSync)(keyPath, key, { flag: "wx", mode: 384 });
|
|
10850
|
+
} catch (error) {
|
|
10851
|
+
if (error.code !== "EEXIST") {
|
|
10852
|
+
throw error;
|
|
10853
|
+
}
|
|
10854
|
+
}
|
|
10855
|
+
(0, import_node_fs.chmodSync)(keyPath, 384);
|
|
10856
|
+
return readLinuxKey(keyPath);
|
|
10857
|
+
}
|
|
10858
|
+
function protectLinuxSecret(account, value) {
|
|
10859
|
+
const keyPath = linuxKeyPathForAccount(account);
|
|
10860
|
+
const key = readOrCreateLinuxKey(keyPath);
|
|
10861
|
+
const iv = (0, import_node_crypto.randomBytes)(12);
|
|
10862
|
+
const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", key, iv);
|
|
10863
|
+
const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
10864
|
+
const tag = cipher.getAuthTag();
|
|
10865
|
+
const encodedKeyPath = Buffer.from(keyPath, "utf8").toString("base64url");
|
|
10866
|
+
return [
|
|
10867
|
+
LINUX_PROTECTED_PREFIX,
|
|
10868
|
+
encodedKeyPath,
|
|
10869
|
+
iv.toString("base64url"),
|
|
10870
|
+
tag.toString("base64url"),
|
|
10871
|
+
ciphertext.toString("base64url")
|
|
10872
|
+
].join(".");
|
|
10873
|
+
}
|
|
10874
|
+
function unprotectLinuxSecret(protectedValue) {
|
|
10875
|
+
const parts = protectedValue.split(".");
|
|
10876
|
+
if (parts.length !== 5 || parts[0] !== LINUX_PROTECTED_PREFIX) {
|
|
10877
|
+
throw new Error("Unsupported Linux secure-store payload.");
|
|
10878
|
+
}
|
|
10879
|
+
const [, encodedKeyPath, encodedIv, encodedTag, encodedCiphertext] = parts;
|
|
10880
|
+
const keyPath = Buffer.from(encodedKeyPath, "base64url").toString("utf8");
|
|
10881
|
+
const key = readLinuxKey(keyPath);
|
|
10882
|
+
const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, Buffer.from(encodedIv, "base64url"));
|
|
10883
|
+
decipher.setAuthTag(Buffer.from(encodedTag, "base64url"));
|
|
10884
|
+
const plaintext = Buffer.concat([decipher.update(Buffer.from(encodedCiphertext, "base64url")), decipher.final()]);
|
|
10885
|
+
return plaintext.toString("utf8");
|
|
10886
|
+
}
|
|
10812
10887
|
function readSecureSecret(locator, deps = {}) {
|
|
10813
10888
|
const platform = deps.platform ?? process.platform;
|
|
10814
10889
|
const run = deps.execFileSync ?? import_node_child_process.execFileSync;
|
|
10815
10890
|
if (platform === "darwin") {
|
|
10816
10891
|
if (!locator.account) {
|
|
10892
|
+
if (isLinuxProtectedValue(locator.protectedValue)) {
|
|
10893
|
+
return {
|
|
10894
|
+
status: "error",
|
|
10895
|
+
message: "This config contains a Linux encrypted local-store value, but it is being read on macOS. Re-store the secret on this machine."
|
|
10896
|
+
};
|
|
10897
|
+
}
|
|
10817
10898
|
return locator.protectedValue ? {
|
|
10818
10899
|
status: "error",
|
|
10819
10900
|
message: "This config contains a Windows DPAPI value, but it is being read on macOS. Re-store the secret on this machine."
|
|
@@ -10836,6 +10917,12 @@ function readSecureSecret(locator, deps = {}) {
|
|
|
10836
10917
|
}
|
|
10837
10918
|
}
|
|
10838
10919
|
if (platform === "win32") {
|
|
10920
|
+
if (isLinuxProtectedValue(locator.protectedValue)) {
|
|
10921
|
+
return {
|
|
10922
|
+
status: "error",
|
|
10923
|
+
message: "This config contains a Linux encrypted local-store value, but it is being read on Windows. Re-store the secret for the current Windows user."
|
|
10924
|
+
};
|
|
10925
|
+
}
|
|
10839
10926
|
if (!locator.protectedValue) {
|
|
10840
10927
|
return locator.account ? {
|
|
10841
10928
|
status: "error",
|
|
@@ -10855,14 +10942,40 @@ function readSecureSecret(locator, deps = {}) {
|
|
|
10855
10942
|
} catch (error) {
|
|
10856
10943
|
return {
|
|
10857
10944
|
status: "error",
|
|
10858
|
-
message: `Unable to decrypt the Windows DPAPI value for the current user: ${errorText(error)}. Re-store the secret.`
|
|
10945
|
+
message: `Unable to decrypt the Windows DPAPI value for the current user: ${errorText(error)}. Re-store the secret for the current Windows user.`
|
|
10946
|
+
};
|
|
10947
|
+
}
|
|
10948
|
+
}
|
|
10949
|
+
if (platform === "linux" && linuxSecureStoreEnabled()) {
|
|
10950
|
+
if (locator.account && !locator.protectedValue) {
|
|
10951
|
+
return {
|
|
10952
|
+
status: "error",
|
|
10953
|
+
message: "This config references a macOS Keychain secret, but it is being read on Linux. Re-store the secret on this machine."
|
|
10954
|
+
};
|
|
10955
|
+
}
|
|
10956
|
+
if (!locator.protectedValue) {
|
|
10957
|
+
return { status: "missing" };
|
|
10958
|
+
}
|
|
10959
|
+
if (!isLinuxProtectedValue(locator.protectedValue)) {
|
|
10960
|
+
return {
|
|
10961
|
+
status: "error",
|
|
10962
|
+
message: "This config contains a foreign protected value that cannot be decrypted by the Linux local store. Re-store the secret on this machine."
|
|
10963
|
+
};
|
|
10964
|
+
}
|
|
10965
|
+
try {
|
|
10966
|
+
const value = unprotectLinuxSecret(locator.protectedValue);
|
|
10967
|
+
return value ? { status: "available", value, source: "secure-store" } : { status: "error", message: "Linux encrypted local store returned an empty value. Re-store the secret." };
|
|
10968
|
+
} catch (error) {
|
|
10969
|
+
return {
|
|
10970
|
+
status: "error",
|
|
10971
|
+
message: `Unable to decrypt the Linux encrypted local-store value: ${errorText(error)} Re-store the secret.`
|
|
10859
10972
|
};
|
|
10860
10973
|
}
|
|
10861
10974
|
}
|
|
10862
10975
|
if (locator.account || locator.protectedValue) {
|
|
10863
10976
|
return {
|
|
10864
10977
|
status: "error",
|
|
10865
|
-
message: "This config contains local secure-store metadata, but local secure storage is
|
|
10978
|
+
message: "This config contains local secure-store metadata, but local secure storage is disabled on Linux/CI. Use environment variables or explicitly enable TESTOPS_LINUX_SECURE_STORE=1 on a trusted persistent Linux host."
|
|
10866
10979
|
};
|
|
10867
10980
|
}
|
|
10868
10981
|
return { status: "missing" };
|
|
@@ -10898,8 +11011,15 @@ function writeSecureSecret(account, value, deps = {}) {
|
|
|
10898
11011
|
}
|
|
10899
11012
|
return { source: "secure-store", protectedValue };
|
|
10900
11013
|
}
|
|
11014
|
+
if (platform === "linux" && linuxSecureStoreEnabled()) {
|
|
11015
|
+
try {
|
|
11016
|
+
return { source: "secure-store", protectedValue: protectLinuxSecret(account, value) };
|
|
11017
|
+
} catch {
|
|
11018
|
+
throw new Error("Unable to store the secret in the Linux encrypted local store.");
|
|
11019
|
+
}
|
|
11020
|
+
}
|
|
10901
11021
|
throw new Error(
|
|
10902
|
-
"Secure local secret storage is supported on macOS and Windows
|
|
11022
|
+
"Secure local secret storage is supported on macOS and Windows. On trusted persistent Linux hosts, set TESTOPS_LINUX_SECURE_STORE=1; otherwise keep secrets in environment variables."
|
|
10903
11023
|
);
|
|
10904
11024
|
}
|
|
10905
11025
|
function deleteSecureSecret(locator, deps = {}) {
|
|
@@ -10924,6 +11044,9 @@ function deleteSecureSecret(locator, deps = {}) {
|
|
|
10924
11044
|
if (platform === "win32") {
|
|
10925
11045
|
return locator.protectedValue ? { status: "deleted" } : { status: "missing" };
|
|
10926
11046
|
}
|
|
11047
|
+
if (platform === "linux") {
|
|
11048
|
+
return locator.account || locator.protectedValue ? { status: "deleted" } : { status: "missing" };
|
|
11049
|
+
}
|
|
10927
11050
|
return locator.account || locator.protectedValue ? { status: "deleted" } : { status: "missing" };
|
|
10928
11051
|
}
|
|
10929
11052
|
|
|
@@ -10972,11 +11095,11 @@ function firstStringValue(...values) {
|
|
|
10972
11095
|
return "";
|
|
10973
11096
|
}
|
|
10974
11097
|
function readConfigFile(configPath) {
|
|
10975
|
-
if (!(0,
|
|
11098
|
+
if (!(0, import_node_fs2.existsSync)(configPath)) {
|
|
10976
11099
|
return {};
|
|
10977
11100
|
}
|
|
10978
11101
|
try {
|
|
10979
|
-
const raw = (0,
|
|
11102
|
+
const raw = (0, import_node_fs2.readFileSync)(configPath, "utf8");
|
|
10980
11103
|
const parsed = JSON.parse(raw);
|
|
10981
11104
|
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
10982
11105
|
} catch {
|
|
@@ -10984,11 +11107,11 @@ function readConfigFile(configPath) {
|
|
|
10984
11107
|
}
|
|
10985
11108
|
}
|
|
10986
11109
|
function readConfigFileForMutation(configPath) {
|
|
10987
|
-
if (!(0,
|
|
11110
|
+
if (!(0, import_node_fs2.existsSync)(configPath)) {
|
|
10988
11111
|
return { file: {} };
|
|
10989
11112
|
}
|
|
10990
11113
|
try {
|
|
10991
|
-
const raw = (0,
|
|
11114
|
+
const raw = (0, import_node_fs2.readFileSync)(configPath, "utf8");
|
|
10992
11115
|
const parsed = JSON.parse(raw);
|
|
10993
11116
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
10994
11117
|
return {
|
|
@@ -11005,10 +11128,10 @@ function readConfigFileForMutation(configPath) {
|
|
|
11005
11128
|
}
|
|
11006
11129
|
}
|
|
11007
11130
|
function writeConfigFile(configPath, file) {
|
|
11008
|
-
(0,
|
|
11131
|
+
(0, import_node_fs2.writeFileSync)(configPath, `${JSON.stringify(file, null, 2)}
|
|
11009
11132
|
`, "utf8");
|
|
11010
11133
|
if (process.platform !== "win32") {
|
|
11011
|
-
(0,
|
|
11134
|
+
(0, import_node_fs2.chmodSync)(configPath, 384);
|
|
11012
11135
|
}
|
|
11013
11136
|
}
|
|
11014
11137
|
function normalizeBaseUrl(value) {
|
|
@@ -11021,10 +11144,10 @@ function readAuthMode(input) {
|
|
|
11021
11144
|
return input === "api-token" ? "api-token" : "none";
|
|
11022
11145
|
}
|
|
11023
11146
|
function defaultKeychainAccount(configPath) {
|
|
11024
|
-
return
|
|
11147
|
+
return import_node_path2.default.resolve(configPath);
|
|
11025
11148
|
}
|
|
11026
11149
|
function defaultJiraApiTokenKeychainAccount(configPath) {
|
|
11027
|
-
return `${
|
|
11150
|
+
return `${import_node_path2.default.resolve(configPath)}:jiraApiToken`;
|
|
11028
11151
|
}
|
|
11029
11152
|
function valueFromPrecedence(key, flagValue, envValue, fileValue, fallback = "") {
|
|
11030
11153
|
if (flagValue) {
|
|
@@ -11101,9 +11224,9 @@ function clearSecretFields(file, key) {
|
|
|
11101
11224
|
}
|
|
11102
11225
|
function resolveCliConfig(args, env = process.env, cwd = process.cwd()) {
|
|
11103
11226
|
const { flags, unknownFlags } = parseFlags(args);
|
|
11104
|
-
const configPathFlag = flags["--config"] ?
|
|
11227
|
+
const configPathFlag = flags["--config"] ? import_node_path2.default.resolve(cwd, flags["--config"]) : "";
|
|
11105
11228
|
const configPathEnv = toStringValue(env.TESTOPS_CONFIG_PATH);
|
|
11106
|
-
const configPath = configPathFlag || (configPathEnv ?
|
|
11229
|
+
const configPath = configPathFlag || (configPathEnv ? import_node_path2.default.resolve(cwd, configPathEnv) : import_node_path2.default.resolve(cwd, DEFAULT_CONFIG_FILENAME));
|
|
11107
11230
|
const configPathSource = configPathFlag ? "flag" : configPathEnv ? "env" : "default";
|
|
11108
11231
|
const file = readConfigFile(configPath);
|
|
11109
11232
|
const baseUrlResolved = valueFromPrecedence(
|
|
@@ -11194,7 +11317,7 @@ function resolveCliConfig(args, env = process.env, cwd = process.cwd()) {
|
|
|
11194
11317
|
if (unknownFlags.length > 0) {
|
|
11195
11318
|
warnings.push(`Ignored unknown config flags: ${unknownFlags.join(", ")}`);
|
|
11196
11319
|
}
|
|
11197
|
-
if (!(0,
|
|
11320
|
+
if (!(0, import_node_fs2.existsSync)(configPath) && sources.configPath !== "default") {
|
|
11198
11321
|
warnings.push(`Config file not found at ${configPath}; using env/flags/defaults.`);
|
|
11199
11322
|
}
|
|
11200
11323
|
return { values: config, sources, warnings, errors };
|
|
@@ -11458,7 +11581,7 @@ function createConfigHandler(env = process.env, cwd = process.cwd()) {
|
|
|
11458
11581
|
const [key, ...valueParts] = stripConfigPathArgs(subArgs);
|
|
11459
11582
|
const normalizedKey = normalizeConfigSetKey(key ?? "");
|
|
11460
11583
|
const readValueFromStdin = (normalizedKey === "forgeAuthToken" || normalizedKey === "jiraApiToken") && valueParts.length === 1 && valueParts[0] === "--stdin";
|
|
11461
|
-
const value = readValueFromStdin ? (0,
|
|
11584
|
+
const value = readValueFromStdin ? (0, import_node_fs2.readFileSync)(0, "utf8").trim() : valueParts.join(" ").trim();
|
|
11462
11585
|
if (!key || !value) {
|
|
11463
11586
|
return {
|
|
11464
11587
|
exitCode: ExitCode.UsageError,
|
|
@@ -11773,7 +11896,7 @@ function diagExecutionNoWork() {
|
|
|
11773
11896
|
}
|
|
11774
11897
|
|
|
11775
11898
|
// src/autoDiscover.ts
|
|
11776
|
-
var
|
|
11899
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
11777
11900
|
var RESULT_FOLDER_NAMES = /* @__PURE__ */ new Set([
|
|
11778
11901
|
"results",
|
|
11779
11902
|
"result",
|
|
@@ -11785,7 +11908,7 @@ var RESULT_FOLDER_NAMES = /* @__PURE__ */ new Set([
|
|
|
11785
11908
|
"failsafe-reports"
|
|
11786
11909
|
]);
|
|
11787
11910
|
function toPosix2(value) {
|
|
11788
|
-
return value.split(
|
|
11911
|
+
return value.split(import_node_path3.default.sep).join("/");
|
|
11789
11912
|
}
|
|
11790
11913
|
function isJUnitXmlArtifact(filePath) {
|
|
11791
11914
|
const normalized = toPosix2(filePath);
|
|
@@ -11879,8 +12002,8 @@ function discoverFeatureFiles(scannedFiles) {
|
|
|
11879
12002
|
}
|
|
11880
12003
|
|
|
11881
12004
|
// src/autoMapping.ts
|
|
11882
|
-
var
|
|
11883
|
-
var
|
|
12005
|
+
var import_node_fs3 = require("node:fs");
|
|
12006
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
11884
12007
|
var ISSUE_KEY_REGEX = /\b[A-Z][A-Z0-9]+-\d+\b/g;
|
|
11885
12008
|
function normalizeName(value) {
|
|
11886
12009
|
return value.trim().toLowerCase();
|
|
@@ -11890,10 +12013,10 @@ function extractIssueKeysFromText(text) {
|
|
|
11890
12013
|
return [...new Set(found)].sort((a, b) => a.localeCompare(b));
|
|
11891
12014
|
}
|
|
11892
12015
|
function parseFeatureFile(featureAbsolutePath) {
|
|
11893
|
-
if (!(0,
|
|
12016
|
+
if (!(0, import_node_fs3.existsSync)(featureAbsolutePath)) {
|
|
11894
12017
|
return { names: [], issueKeys: [] };
|
|
11895
12018
|
}
|
|
11896
|
-
const raw = (0,
|
|
12019
|
+
const raw = (0, import_node_fs3.readFileSync)(featureAbsolutePath, "utf8");
|
|
11897
12020
|
const lines = raw.split(/\r?\n/);
|
|
11898
12021
|
const names = /* @__PURE__ */ new Set();
|
|
11899
12022
|
const issueKeys = new Set(extractIssueKeysFromText(raw));
|
|
@@ -11951,7 +12074,7 @@ function buildMappingPreview(input) {
|
|
|
11951
12074
|
const localNamesSet = /* @__PURE__ */ new Set();
|
|
11952
12075
|
const issueCandidatesSet = /* @__PURE__ */ new Set();
|
|
11953
12076
|
for (const featurePath of input.featurePaths) {
|
|
11954
|
-
const absolutePath =
|
|
12077
|
+
const absolutePath = import_node_path4.default.join(input.rootPath, featurePath);
|
|
11955
12078
|
const parsed = parseFeatureFile(absolutePath);
|
|
11956
12079
|
for (const name of parsed.names) {
|
|
11957
12080
|
localNamesSet.add(name);
|
|
@@ -12000,8 +12123,8 @@ function buildMappingPreview(input) {
|
|
|
12000
12123
|
}
|
|
12001
12124
|
|
|
12002
12125
|
// src/autoScanner.ts
|
|
12003
|
-
var
|
|
12004
|
-
var
|
|
12126
|
+
var import_node_fs4 = require("node:fs");
|
|
12127
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
12005
12128
|
var DEFAULT_MAX_DEPTH = 5;
|
|
12006
12129
|
var DEFAULT_EXCLUDED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
12007
12130
|
".cache",
|
|
@@ -12016,7 +12139,7 @@ var DEFAULT_EXCLUDED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
|
12016
12139
|
"node_modules"
|
|
12017
12140
|
]);
|
|
12018
12141
|
function normalizeRelativePath(value) {
|
|
12019
|
-
return value.split(
|
|
12142
|
+
return value.split(import_node_path5.default.sep).join("/");
|
|
12020
12143
|
}
|
|
12021
12144
|
function normalizePatterns(values) {
|
|
12022
12145
|
if (!values) {
|
|
@@ -12070,16 +12193,16 @@ function scanProjectFiles(options) {
|
|
|
12070
12193
|
const includePatterns = normalizePatterns(options.includePatterns);
|
|
12071
12194
|
const excludePatterns = normalizePatterns(options.excludePatterns);
|
|
12072
12195
|
const maxDepth = safeMaxDepth(options.maxDepth);
|
|
12073
|
-
const rootPath =
|
|
12196
|
+
const rootPath = import_node_path5.default.resolve(options.rootPath);
|
|
12074
12197
|
const scannedFiles = [];
|
|
12075
12198
|
const visit = (absoluteDirectory, depth) => {
|
|
12076
12199
|
if (depth > maxDepth) {
|
|
12077
12200
|
return;
|
|
12078
12201
|
}
|
|
12079
|
-
const entries = (0,
|
|
12202
|
+
const entries = (0, import_node_fs4.readdirSync)(absoluteDirectory, { withFileTypes: true }).slice().sort((a, b) => a.name.localeCompare(b.name));
|
|
12080
12203
|
for (const entry of entries) {
|
|
12081
|
-
const absoluteEntryPath =
|
|
12082
|
-
const relativeEntryPath = normalizeRelativePath(
|
|
12204
|
+
const absoluteEntryPath = import_node_path5.default.join(absoluteDirectory, entry.name);
|
|
12205
|
+
const relativeEntryPath = normalizeRelativePath(import_node_path5.default.relative(rootPath, absoluteEntryPath));
|
|
12083
12206
|
if (!relativeEntryPath) {
|
|
12084
12207
|
continue;
|
|
12085
12208
|
}
|
|
@@ -12181,10 +12304,10 @@ function resolveRoot(rootFlag, cwd) {
|
|
|
12181
12304
|
if (!rootFlag.trim()) {
|
|
12182
12305
|
return cwd;
|
|
12183
12306
|
}
|
|
12184
|
-
return
|
|
12307
|
+
return import_node_path6.default.resolve(cwd, rootFlag);
|
|
12185
12308
|
}
|
|
12186
12309
|
function countScenariosInFeatureFile(featurePath) {
|
|
12187
|
-
const lines = (0,
|
|
12310
|
+
const lines = (0, import_node_fs5.readFileSync)(featurePath, "utf8").split(/\r?\n/).map((line) => line.trim().toLowerCase());
|
|
12188
12311
|
let count = 0;
|
|
12189
12312
|
for (const line of lines) {
|
|
12190
12313
|
if (line.startsWith("scenario:") || line.startsWith("scenario outline:")) {
|
|
@@ -12196,8 +12319,8 @@ function countScenariosInFeatureFile(featurePath) {
|
|
|
12196
12319
|
function buildScenarioStats(rootPath, featurePaths) {
|
|
12197
12320
|
let scenarios = 0;
|
|
12198
12321
|
for (const relativePath of featurePaths) {
|
|
12199
|
-
const absolutePath =
|
|
12200
|
-
if (!(0,
|
|
12322
|
+
const absolutePath = import_node_path6.default.join(rootPath, relativePath);
|
|
12323
|
+
if (!(0, import_node_fs5.existsSync)(absolutePath)) {
|
|
12201
12324
|
continue;
|
|
12202
12325
|
}
|
|
12203
12326
|
scenarios += countScenariosInFeatureFile(absolutePath);
|
|
@@ -12237,7 +12360,7 @@ function deriveFeatureNameFromGherkin(gherkin, fallbackPath) {
|
|
|
12237
12360
|
return match[1].trim();
|
|
12238
12361
|
}
|
|
12239
12362
|
}
|
|
12240
|
-
return
|
|
12363
|
+
return import_node_path6.default.basename(fallbackPath, import_node_path6.default.extname(fallbackPath));
|
|
12241
12364
|
}
|
|
12242
12365
|
function mapStepStatus(status) {
|
|
12243
12366
|
const normalized = status.trim().toLowerCase();
|
|
@@ -12253,13 +12376,13 @@ function mapStepStatus(status) {
|
|
|
12253
12376
|
return StepResult.Blocked;
|
|
12254
12377
|
}
|
|
12255
12378
|
function parseCucumberRunsFromArtifact(rootPath, artifactPath) {
|
|
12256
|
-
const absolutePath =
|
|
12257
|
-
if (!(0,
|
|
12379
|
+
const absolutePath = import_node_path6.default.join(rootPath, artifactPath);
|
|
12380
|
+
if (!(0, import_node_fs5.existsSync)(absolutePath)) {
|
|
12258
12381
|
return [];
|
|
12259
12382
|
}
|
|
12260
12383
|
let parsed;
|
|
12261
12384
|
try {
|
|
12262
|
-
parsed = JSON.parse((0,
|
|
12385
|
+
parsed = JSON.parse((0, import_node_fs5.readFileSync)(absolutePath, "utf8"));
|
|
12263
12386
|
} catch {
|
|
12264
12387
|
return [];
|
|
12265
12388
|
}
|
|
@@ -12354,15 +12477,15 @@ async function executeUploadFlow(input) {
|
|
|
12354
12477
|
const diagnostics = [];
|
|
12355
12478
|
const orderedFeatures = [...input.featurePaths].sort((a, b) => a.localeCompare(b));
|
|
12356
12479
|
for (const featurePath of orderedFeatures) {
|
|
12357
|
-
const absolutePath =
|
|
12358
|
-
if (!(0,
|
|
12480
|
+
const absolutePath = import_node_path6.default.join(input.rootPath, featurePath);
|
|
12481
|
+
if (!(0, import_node_fs5.existsSync)(absolutePath)) {
|
|
12359
12482
|
featureFailed += 1;
|
|
12360
12483
|
const diagnostic = diagUploadFeatureFailure(featurePath, "missing feature file");
|
|
12361
12484
|
errors.push(diagnostic.message);
|
|
12362
12485
|
diagnostics.push(diagnostic);
|
|
12363
12486
|
continue;
|
|
12364
12487
|
}
|
|
12365
|
-
const gherkin = (0,
|
|
12488
|
+
const gherkin = (0, import_node_fs5.readFileSync)(absolutePath, "utf8");
|
|
12366
12489
|
const name = deriveFeatureNameFromGherkin(gherkin, featurePath);
|
|
12367
12490
|
const payload = {
|
|
12368
12491
|
context: {
|
|
@@ -12701,7 +12824,7 @@ function createAutoHandler(deps = {}) {
|
|
|
12701
12824
|
stderr: ["ERROR: --output must be either 'plain' or 'json'."]
|
|
12702
12825
|
};
|
|
12703
12826
|
}
|
|
12704
|
-
if (!(0,
|
|
12827
|
+
if (!(0, import_node_fs5.existsSync)(rootPath)) {
|
|
12705
12828
|
return {
|
|
12706
12829
|
exitCode: ExitCode.ValidationError,
|
|
12707
12830
|
stderr: [`ERROR: Root path does not exist: ${rootPath}`]
|
|
@@ -12804,8 +12927,8 @@ function createAutoHandler(deps = {}) {
|
|
|
12804
12927
|
}
|
|
12805
12928
|
|
|
12806
12929
|
// src/allure.ts
|
|
12807
|
-
var
|
|
12808
|
-
var
|
|
12930
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
12931
|
+
var import_node_fs10 = require("node:fs");
|
|
12809
12932
|
|
|
12810
12933
|
// ../../packages/jira-client/dist/adf.js
|
|
12811
12934
|
function paragraph(text = "") {
|
|
@@ -12851,8 +12974,8 @@ function buildAllureEvidenceCommentAdf(input) {
|
|
|
12851
12974
|
}
|
|
12852
12975
|
|
|
12853
12976
|
// ../../packages/jira-client/dist/jiraClient.js
|
|
12854
|
-
var
|
|
12855
|
-
var
|
|
12977
|
+
var import_node_fs6 = require("node:fs");
|
|
12978
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
12856
12979
|
function normalizeSite(site) {
|
|
12857
12980
|
return site.trim().replace(/\/+$/, "");
|
|
12858
12981
|
}
|
|
@@ -12865,10 +12988,10 @@ async function readError(response) {
|
|
|
12865
12988
|
}
|
|
12866
12989
|
async function uploadIssueAttachment(params) {
|
|
12867
12990
|
const site = normalizeSite(params.site);
|
|
12868
|
-
const filename =
|
|
12869
|
-
const fileStat = (0,
|
|
12991
|
+
const filename = import_node_path7.default.basename(params.filePath);
|
|
12992
|
+
const fileStat = (0, import_node_fs6.statSync)(params.filePath);
|
|
12870
12993
|
const body = new FormData();
|
|
12871
|
-
const fileBuffer = (0,
|
|
12994
|
+
const fileBuffer = (0, import_node_fs6.readFileSync)(params.filePath);
|
|
12872
12995
|
body.append("file", new Blob([new Uint8Array(fileBuffer)], { type: "application/zip" }), filename);
|
|
12873
12996
|
const response = await fetch(`${site}/rest/api/3/issue/${encodeURIComponent(params.issueKey)}/attachments`, {
|
|
12874
12997
|
method: "POST",
|
|
@@ -12937,7 +13060,7 @@ async function downloadIssueAttachment(params) {
|
|
|
12937
13060
|
throw new Error(`Jira attachment download failed: ${await readError(response)}`);
|
|
12938
13061
|
}
|
|
12939
13062
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
12940
|
-
(0,
|
|
13063
|
+
(0, import_node_fs6.writeFileSync)(params.outputPath, bytes);
|
|
12941
13064
|
return {
|
|
12942
13065
|
filename: params.attachment.filename,
|
|
12943
13066
|
id: params.attachment.id,
|
|
@@ -12977,8 +13100,8 @@ async function addIssueComment(params) {
|
|
|
12977
13100
|
}
|
|
12978
13101
|
|
|
12979
13102
|
// ../../packages/allure-core/dist/parseAllureZip.js
|
|
12980
|
-
var
|
|
12981
|
-
var
|
|
13103
|
+
var import_node_fs7 = require("node:fs");
|
|
13104
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
12982
13105
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
12983
13106
|
var SUMMARY_PATH_SUFFIX = "/widgets/summary.json";
|
|
12984
13107
|
var MISSING_SUMMARY_ERROR = "Could not find widgets/summary.json. Please upload a generated Allure HTML report ZIP, not raw allure-results.";
|
|
@@ -13006,13 +13129,13 @@ function parseCounts(summary) {
|
|
|
13006
13129
|
};
|
|
13007
13130
|
}
|
|
13008
13131
|
async function parseAllureReportZip(zipPath) {
|
|
13009
|
-
if (!(0,
|
|
13132
|
+
if (!(0, import_node_fs7.existsSync)(zipPath)) {
|
|
13010
13133
|
throw new Error(`Allure report ZIP not found: ${zipPath}`);
|
|
13011
13134
|
}
|
|
13012
|
-
if (
|
|
13135
|
+
if (import_node_path8.default.extname(zipPath).toLowerCase() !== ".zip") {
|
|
13013
13136
|
throw new Error("Allure report must be a .zip file.");
|
|
13014
13137
|
}
|
|
13015
|
-
const zip = await import_jszip.default.loadAsync((0,
|
|
13138
|
+
const zip = await import_jszip.default.loadAsync((0, import_node_fs7.readFileSync)(zipPath));
|
|
13016
13139
|
const filePaths = Object.keys(zip.files).filter((entryPath) => !zip.files[entryPath]?.dir);
|
|
13017
13140
|
const summaryPath = findSummaryPath(filePaths);
|
|
13018
13141
|
if (!summaryPath) {
|
|
@@ -13039,8 +13162,8 @@ async function parseAllureReportZip(zipPath) {
|
|
|
13039
13162
|
}
|
|
13040
13163
|
|
|
13041
13164
|
// ../../packages/allure-core/dist/extractAllureZip.js
|
|
13042
|
-
var
|
|
13043
|
-
var
|
|
13165
|
+
var import_node_fs8 = require("node:fs");
|
|
13166
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
13044
13167
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
13045
13168
|
var INDEX_HTML = "index.html";
|
|
13046
13169
|
var MISSING_INDEX_ERROR = "Could not find index.html. Please provide a generated Allure HTML report ZIP, not raw allure-results.";
|
|
@@ -13048,41 +13171,41 @@ function findIndexEntry(paths) {
|
|
|
13048
13171
|
return paths.find((entryPath) => entryPath === INDEX_HTML) ?? paths.find((entryPath) => entryPath === `allure-report/${INDEX_HTML}`) ?? paths.find((entryPath) => entryPath.endsWith(`/${INDEX_HTML}`));
|
|
13049
13172
|
}
|
|
13050
13173
|
function ensureInsideRoot(rootDir, candidate) {
|
|
13051
|
-
const resolved =
|
|
13052
|
-
const rootWithSep = rootDir.endsWith(
|
|
13174
|
+
const resolved = import_node_path9.default.resolve(rootDir, candidate);
|
|
13175
|
+
const rootWithSep = rootDir.endsWith(import_node_path9.default.sep) ? rootDir : rootDir + import_node_path9.default.sep;
|
|
13053
13176
|
if (resolved !== rootDir && !resolved.startsWith(rootWithSep)) {
|
|
13054
13177
|
throw new Error(`Refusing to write zip entry outside extract directory: ${candidate}`);
|
|
13055
13178
|
}
|
|
13056
13179
|
return resolved;
|
|
13057
13180
|
}
|
|
13058
13181
|
async function extractAllureReportZip(zipPath, extractDir) {
|
|
13059
|
-
if (!(0,
|
|
13182
|
+
if (!(0, import_node_fs8.existsSync)(zipPath)) {
|
|
13060
13183
|
throw new Error(`Allure report ZIP not found: ${zipPath}`);
|
|
13061
13184
|
}
|
|
13062
|
-
if (
|
|
13185
|
+
if (import_node_path9.default.extname(zipPath).toLowerCase() !== ".zip") {
|
|
13063
13186
|
throw new Error("Allure report must be a .zip file.");
|
|
13064
13187
|
}
|
|
13065
|
-
const zip = await import_jszip2.default.loadAsync((0,
|
|
13188
|
+
const zip = await import_jszip2.default.loadAsync((0, import_node_fs8.readFileSync)(zipPath));
|
|
13066
13189
|
const entries = Object.entries(zip.files);
|
|
13067
13190
|
const filePaths = entries.filter(([, file]) => !file.dir).map(([entryPath]) => entryPath);
|
|
13068
13191
|
const indexEntry = findIndexEntry(filePaths);
|
|
13069
13192
|
if (!indexEntry) {
|
|
13070
13193
|
throw new Error(MISSING_INDEX_ERROR);
|
|
13071
13194
|
}
|
|
13072
|
-
const resolvedExtract =
|
|
13073
|
-
(0,
|
|
13195
|
+
const resolvedExtract = import_node_path9.default.resolve(extractDir);
|
|
13196
|
+
(0, import_node_fs8.mkdirSync)(resolvedExtract, { recursive: true });
|
|
13074
13197
|
for (const [entryPath, file] of entries) {
|
|
13075
13198
|
const target = ensureInsideRoot(resolvedExtract, entryPath);
|
|
13076
13199
|
if (file.dir) {
|
|
13077
|
-
(0,
|
|
13200
|
+
(0, import_node_fs8.mkdirSync)(target, { recursive: true });
|
|
13078
13201
|
continue;
|
|
13079
13202
|
}
|
|
13080
|
-
(0,
|
|
13203
|
+
(0, import_node_fs8.mkdirSync)(import_node_path9.default.dirname(target), { recursive: true });
|
|
13081
13204
|
const buffer = await file.async("nodebuffer");
|
|
13082
|
-
(0,
|
|
13205
|
+
(0, import_node_fs8.writeFileSync)(target, buffer);
|
|
13083
13206
|
}
|
|
13084
|
-
const indexAbsolute =
|
|
13085
|
-
const rootDir =
|
|
13207
|
+
const indexAbsolute = import_node_path9.default.join(resolvedExtract, indexEntry);
|
|
13208
|
+
const rootDir = import_node_path9.default.dirname(indexAbsolute);
|
|
13086
13209
|
return {
|
|
13087
13210
|
zipPath,
|
|
13088
13211
|
extractDir: resolvedExtract,
|
|
@@ -13095,11 +13218,11 @@ async function extractAllureReportZip(zipPath, extractDir) {
|
|
|
13095
13218
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
13096
13219
|
|
|
13097
13220
|
// src/allureOpen.ts
|
|
13098
|
-
var
|
|
13221
|
+
var import_node_fs9 = require("node:fs");
|
|
13099
13222
|
var import_promises = require("node:fs/promises");
|
|
13100
13223
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
13101
13224
|
var import_node_os = require("node:os");
|
|
13102
|
-
var
|
|
13225
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
13103
13226
|
var import_node_child_process2 = require("node:child_process");
|
|
13104
13227
|
function parseArgs2(args) {
|
|
13105
13228
|
const positionals = [];
|
|
@@ -13168,7 +13291,7 @@ var MIME_TYPES = {
|
|
|
13168
13291
|
".txt": "text/plain; charset=utf-8"
|
|
13169
13292
|
};
|
|
13170
13293
|
function contentTypeFor(filePath) {
|
|
13171
|
-
return MIME_TYPES[
|
|
13294
|
+
return MIME_TYPES[import_node_path10.default.extname(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
13172
13295
|
}
|
|
13173
13296
|
function resolveRequestedPath(rootDir, urlPath) {
|
|
13174
13297
|
let decoded;
|
|
@@ -13177,10 +13300,10 @@ function resolveRequestedPath(rootDir, urlPath) {
|
|
|
13177
13300
|
} catch {
|
|
13178
13301
|
return void 0;
|
|
13179
13302
|
}
|
|
13180
|
-
const normalized =
|
|
13303
|
+
const normalized = import_node_path10.default.normalize(decoded);
|
|
13181
13304
|
const trimmed = normalized.replace(/^[/\\]+/, "");
|
|
13182
|
-
const candidate =
|
|
13183
|
-
const rootWithSep = rootDir.endsWith(
|
|
13305
|
+
const candidate = import_node_path10.default.resolve(rootDir, trimmed);
|
|
13306
|
+
const rootWithSep = rootDir.endsWith(import_node_path10.default.sep) ? rootDir : rootDir + import_node_path10.default.sep;
|
|
13184
13307
|
if (candidate !== rootDir && !candidate.startsWith(rootWithSep)) {
|
|
13185
13308
|
return void 0;
|
|
13186
13309
|
}
|
|
@@ -13202,16 +13325,16 @@ function createStaticServerStarter() {
|
|
|
13202
13325
|
}
|
|
13203
13326
|
let target = resolved;
|
|
13204
13327
|
try {
|
|
13205
|
-
const stat = (0,
|
|
13328
|
+
const stat = (0, import_node_fs9.statSync)(target);
|
|
13206
13329
|
if (stat.isDirectory()) {
|
|
13207
|
-
target =
|
|
13330
|
+
target = import_node_path10.default.join(target, "index.html");
|
|
13208
13331
|
}
|
|
13209
13332
|
} catch {
|
|
13210
13333
|
res.statusCode = 404;
|
|
13211
13334
|
res.end("Not Found");
|
|
13212
13335
|
return;
|
|
13213
13336
|
}
|
|
13214
|
-
if (!(0,
|
|
13337
|
+
if (!(0, import_node_fs9.existsSync)(target)) {
|
|
13215
13338
|
res.statusCode = 404;
|
|
13216
13339
|
res.end("Not Found");
|
|
13217
13340
|
return;
|
|
@@ -13222,7 +13345,7 @@ function createStaticServerStarter() {
|
|
|
13222
13345
|
res.end();
|
|
13223
13346
|
return;
|
|
13224
13347
|
}
|
|
13225
|
-
const stream = (0,
|
|
13348
|
+
const stream = (0, import_node_fs9.createReadStream)(target);
|
|
13226
13349
|
stream.on("error", () => {
|
|
13227
13350
|
res.statusCode = 500;
|
|
13228
13351
|
res.end("Internal Server Error");
|
|
@@ -13327,7 +13450,7 @@ function createAllureOpenHandler(deps = {}) {
|
|
|
13327
13450
|
const cwd = deps.cwd ?? process.cwd();
|
|
13328
13451
|
const parseZip = deps.parseAllureReportZip ?? parseAllureReportZip;
|
|
13329
13452
|
const extractZip = deps.extractAllureReportZip ?? extractAllureReportZip;
|
|
13330
|
-
const createTempDir = deps.createTempDir ?? (() => (0, import_promises.mkdtemp)(
|
|
13453
|
+
const createTempDir = deps.createTempDir ?? (() => (0, import_promises.mkdtemp)(import_node_path10.default.join((0, import_node_os.tmpdir)(), "automatify-allure-open-")));
|
|
13331
13454
|
const startServer = deps.startServer ?? createStaticServerStarter();
|
|
13332
13455
|
const openInBrowser = deps.openInBrowser ?? createOsBrowserOpener();
|
|
13333
13456
|
const waitForShutdown = deps.waitForShutdown ?? waitForProcessSignals;
|
|
@@ -13362,7 +13485,7 @@ function createAllureOpenHandler(deps = {}) {
|
|
|
13362
13485
|
};
|
|
13363
13486
|
}
|
|
13364
13487
|
const host = parsed.flags["--host"] ?? "127.0.0.1";
|
|
13365
|
-
const zipPath =
|
|
13488
|
+
const zipPath = import_node_path10.default.resolve(cwd, zipPathInput);
|
|
13366
13489
|
let summary;
|
|
13367
13490
|
try {
|
|
13368
13491
|
summary = await parseZip(zipPath);
|
|
@@ -13372,9 +13495,9 @@ function createAllureOpenHandler(deps = {}) {
|
|
|
13372
13495
|
stderr: [`ERROR: ${normalizeError(error)}`]
|
|
13373
13496
|
};
|
|
13374
13497
|
}
|
|
13375
|
-
const extractDirRaw = userExtractDir ?
|
|
13498
|
+
const extractDirRaw = userExtractDir ? import_node_path10.default.resolve(cwd, userExtractDir) : await createTempDir();
|
|
13376
13499
|
if (dryRun) {
|
|
13377
|
-
const indexPath =
|
|
13500
|
+
const indexPath = import_node_path10.default.join(extractDirRaw, "index.html");
|
|
13378
13501
|
if (useJson) {
|
|
13379
13502
|
return {
|
|
13380
13503
|
exitCode: ExitCode.Success,
|
|
@@ -13739,8 +13862,8 @@ function createAllureHandler(deps = {}) {
|
|
|
13739
13862
|
attachmentId: parsed.flags["--attachment-id"],
|
|
13740
13863
|
filename: parsed.flags["--filename"]
|
|
13741
13864
|
});
|
|
13742
|
-
const outputDir =
|
|
13743
|
-
const outputPath =
|
|
13865
|
+
const outputDir = import_node_path11.default.resolve(cwd, parsed.flags["--output-dir"] ?? ".");
|
|
13866
|
+
const outputPath = import_node_path11.default.join(outputDir, selected.filename);
|
|
13744
13867
|
if (dryRun) {
|
|
13745
13868
|
if (useJson) {
|
|
13746
13869
|
return {
|
|
@@ -13765,8 +13888,8 @@ function createAllureHandler(deps = {}) {
|
|
|
13765
13888
|
]
|
|
13766
13889
|
};
|
|
13767
13890
|
}
|
|
13768
|
-
(0,
|
|
13769
|
-
if ((0,
|
|
13891
|
+
(0, import_node_fs10.mkdirSync)(outputDir, { recursive: true });
|
|
13892
|
+
if ((0, import_node_fs10.existsSync)(outputPath) && !force) {
|
|
13770
13893
|
return {
|
|
13771
13894
|
exitCode: ExitCode.ValidationError,
|
|
13772
13895
|
stderr: [`ERROR: Output file already exists: ${outputPath}. Pass --force to overwrite.`]
|
|
@@ -13815,8 +13938,8 @@ function createAllureHandler(deps = {}) {
|
|
|
13815
13938
|
};
|
|
13816
13939
|
}
|
|
13817
13940
|
const resolved = resolveJiraConfig(parsed, env, cwd);
|
|
13818
|
-
const zipPath =
|
|
13819
|
-
const attachmentFilename =
|
|
13941
|
+
const zipPath = import_node_path11.default.resolve(cwd, zipPathInput);
|
|
13942
|
+
const attachmentFilename = import_node_path11.default.basename(zipPath);
|
|
13820
13943
|
if (!resolved.config) {
|
|
13821
13944
|
return {
|
|
13822
13945
|
exitCode: ExitCode.ValidationError,
|
|
@@ -13914,7 +14037,7 @@ function createAllureHandler(deps = {}) {
|
|
|
13914
14037
|
}
|
|
13915
14038
|
|
|
13916
14039
|
// src/auth.ts
|
|
13917
|
-
var
|
|
14040
|
+
var import_node_fs11 = require("node:fs");
|
|
13918
14041
|
function parseAuthArgs(args, allowLoginFlags) {
|
|
13919
14042
|
const configArgs = [];
|
|
13920
14043
|
const unknown = [];
|
|
@@ -13980,7 +14103,7 @@ function sourceLabel(source) {
|
|
|
13980
14103
|
case "keychain":
|
|
13981
14104
|
return "macOS Keychain";
|
|
13982
14105
|
case "secure-store":
|
|
13983
|
-
return "
|
|
14106
|
+
return "local secure store";
|
|
13984
14107
|
case "env":
|
|
13985
14108
|
return "environment";
|
|
13986
14109
|
case "file":
|
|
@@ -14059,12 +14182,13 @@ function createLoginResponse(args, env, cwd, readStdin, platform, context) {
|
|
|
14059
14182
|
]
|
|
14060
14183
|
};
|
|
14061
14184
|
}
|
|
14062
|
-
|
|
14185
|
+
const linuxSecureStoreEnabled2 = platform === "linux" && env.TESTOPS_LINUX_SECURE_STORE?.trim() === "1";
|
|
14186
|
+
if (parsed.tokenStdin && platform !== "darwin" && platform !== "win32" && !linuxSecureStoreEnabled2) {
|
|
14063
14187
|
return {
|
|
14064
14188
|
exitCode: ExitCode.UsageError,
|
|
14065
14189
|
stderr: [
|
|
14066
|
-
"Local secure secret storage is
|
|
14067
|
-
"On Linux/CI, set JIRA_API_TOKEN in the environment and run auth login without --token-stdin."
|
|
14190
|
+
"Local secure secret storage is enabled by default only on macOS and Windows.",
|
|
14191
|
+
"On Linux/CI, either set TESTOPS_LINUX_SECURE_STORE=1 on a trusted persistent host or keep JIRA_API_TOKEN in the environment and run auth login without --token-stdin."
|
|
14068
14192
|
]
|
|
14069
14193
|
};
|
|
14070
14194
|
}
|
|
@@ -14091,7 +14215,7 @@ function createLoginResponse(args, env, cwd, readStdin, platform, context) {
|
|
|
14091
14215
|
}
|
|
14092
14216
|
completed.push(step.label);
|
|
14093
14217
|
}
|
|
14094
|
-
const tokenSource = stdinToken ? platform === "darwin" ? "macOS Keychain" : "Windows DPAPI" : sourceLabel(
|
|
14218
|
+
const tokenSource = stdinToken ? platform === "darwin" ? "macOS Keychain" : platform === "win32" ? "Windows DPAPI" : "Linux encrypted local store" : sourceLabel(
|
|
14095
14219
|
current.sources.jiraApiToken === "default" && env.JIRA_API_TOKEN ? "env" : current.sources.jiraApiToken
|
|
14096
14220
|
);
|
|
14097
14221
|
return {
|
|
@@ -14140,7 +14264,7 @@ function createLogoutResponse(args, env, cwd, context) {
|
|
|
14140
14264
|
function createAuthHandler(deps = {}) {
|
|
14141
14265
|
const env = deps.env ?? process.env;
|
|
14142
14266
|
const cwd = deps.cwd ?? process.cwd();
|
|
14143
|
-
const readStdin = deps.readStdin ?? (() => (0,
|
|
14267
|
+
const readStdin = deps.readStdin ?? (() => (0, import_node_fs11.readFileSync)(0, "utf8"));
|
|
14144
14268
|
const platform = deps.platform ?? process.platform;
|
|
14145
14269
|
return (request, context) => {
|
|
14146
14270
|
const [subcommand, ...args] = request.args;
|
|
@@ -14161,8 +14285,8 @@ function createAuthHandler(deps = {}) {
|
|
|
14161
14285
|
}
|
|
14162
14286
|
|
|
14163
14287
|
// src/bdd.ts
|
|
14164
|
-
var
|
|
14165
|
-
var
|
|
14288
|
+
var import_node_fs12 = require("node:fs");
|
|
14289
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
14166
14290
|
var import_yazl = __toESM(require_yazl(), 1);
|
|
14167
14291
|
|
|
14168
14292
|
// src/forgeClient.ts
|
|
@@ -14466,7 +14590,7 @@ function parseScenarioFeatureFile(raw, filePath) {
|
|
|
14466
14590
|
}
|
|
14467
14591
|
const scenarioTag = tags.map((tag) => tag.match(SCENARIO_METADATA_PATTERN)).find((match) => Boolean(match));
|
|
14468
14592
|
const scenarioKeyFromTag = scenarioTag?.[1]?.trim().toUpperCase() ?? "";
|
|
14469
|
-
const fileKeyMatch =
|
|
14593
|
+
const fileKeyMatch = import_node_path12.default.basename(filePath ?? "").match(/^(SC-\d+)\.feature$/i);
|
|
14470
14594
|
const scenarioKeyFromFile = fileKeyMatch?.[1]?.trim().toUpperCase() ?? "";
|
|
14471
14595
|
const scenarioKey = scenarioKeyFromTag || scenarioKeyFromFile;
|
|
14472
14596
|
if (scenarioKeyFromTag && scenarioKeyFromFile && scenarioKeyFromTag !== scenarioKeyFromFile) {
|
|
@@ -14586,7 +14710,7 @@ function toJsonExportManifestItems(items) {
|
|
|
14586
14710
|
async function defaultCreateZipArchive(archivePath, entries) {
|
|
14587
14711
|
await new Promise((resolve, reject) => {
|
|
14588
14712
|
const zip = new import_yazl.ZipFile();
|
|
14589
|
-
const output = zip.outputStream.pipe((0,
|
|
14713
|
+
const output = zip.outputStream.pipe((0, import_node_fs12.createWriteStream)(archivePath));
|
|
14590
14714
|
output.on("close", () => resolve());
|
|
14591
14715
|
output.on("error", reject);
|
|
14592
14716
|
zip.outputStream.on("error", reject);
|
|
@@ -14616,10 +14740,10 @@ function missingProjectResponse() {
|
|
|
14616
14740
|
function createBddHandler(deps = {}) {
|
|
14617
14741
|
const cwd = deps.cwd ?? process.cwd();
|
|
14618
14742
|
const env = deps.env ?? process.env;
|
|
14619
|
-
const mkdir = deps.mkdir ?? ((targetPath, options) => (0,
|
|
14620
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
14621
|
-
const readDir = deps.readDir ?? ((dirPath) => (0,
|
|
14622
|
-
const writeFile = deps.writeFile ?? ((filePath, content) => (0,
|
|
14743
|
+
const mkdir = deps.mkdir ?? ((targetPath, options) => (0, import_node_fs12.mkdirSync)(targetPath, options));
|
|
14744
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs12.readFileSync)(filePath, "utf8"));
|
|
14745
|
+
const readDir = deps.readDir ?? ((dirPath) => (0, import_node_fs12.readdirSync)(dirPath));
|
|
14746
|
+
const writeFile = deps.writeFile ?? ((filePath, content) => (0, import_node_fs12.writeFileSync)(filePath, content, "utf8"));
|
|
14623
14747
|
const createZipArchive = deps.createZipArchive ?? defaultCreateZipArchive;
|
|
14624
14748
|
return async (request, context) => {
|
|
14625
14749
|
const [subcommand, ...restArgs] = request.args;
|
|
@@ -14663,7 +14787,7 @@ function createBddHandler(deps = {}) {
|
|
|
14663
14787
|
stderr: ["ERROR: Missing required --output-dir for testops bdd features export."]
|
|
14664
14788
|
};
|
|
14665
14789
|
}
|
|
14666
|
-
const outputDir =
|
|
14790
|
+
const outputDir = import_node_path12.default.resolve(cwd, outputDirFlag);
|
|
14667
14791
|
try {
|
|
14668
14792
|
const result = await context.invokeForgeContract("listBddFeatures", {
|
|
14669
14793
|
context: {
|
|
@@ -14701,7 +14825,7 @@ function createBddHandler(deps = {}) {
|
|
|
14701
14825
|
`
|
|
14702
14826
|
}));
|
|
14703
14827
|
for (let index = 0; index < features.length; index += 1) {
|
|
14704
|
-
writeFile(
|
|
14828
|
+
writeFile(import_node_path12.default.join(outputDir, fileNames[index]), exportEntries[index].content);
|
|
14705
14829
|
}
|
|
14706
14830
|
const manifest = {
|
|
14707
14831
|
action: "bdd-features-export",
|
|
@@ -14714,7 +14838,7 @@ function createBddHandler(deps = {}) {
|
|
|
14714
14838
|
};
|
|
14715
14839
|
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
14716
14840
|
`;
|
|
14717
|
-
writeFile(
|
|
14841
|
+
writeFile(import_node_path12.default.join(outputDir, "manifest.json"), manifestContent);
|
|
14718
14842
|
const archivePath = `${outputDir}.zip`;
|
|
14719
14843
|
if (zipRequested) {
|
|
14720
14844
|
await createZipArchive(archivePath, [
|
|
@@ -14784,7 +14908,7 @@ function createBddHandler(deps = {}) {
|
|
|
14784
14908
|
stderr: ["ERROR: Missing required --output-dir for testops bdd scenarios export."]
|
|
14785
14909
|
};
|
|
14786
14910
|
}
|
|
14787
|
-
const outputDir =
|
|
14911
|
+
const outputDir = import_node_path12.default.resolve(cwd, outputDirFlag);
|
|
14788
14912
|
const zipRequested = parsed.boolFlags.has("--zip");
|
|
14789
14913
|
try {
|
|
14790
14914
|
const scenariosResult = await context.invokeForgeContract("listBddScenarios", {
|
|
@@ -14821,7 +14945,7 @@ function createBddHandler(deps = {}) {
|
|
|
14821
14945
|
const fileName = scenarioToExportFileName(scenario);
|
|
14822
14946
|
const fileContent = `${scenarioToFeatureLines(scenario).join("\n")}
|
|
14823
14947
|
`;
|
|
14824
|
-
writeFile(
|
|
14948
|
+
writeFile(import_node_path12.default.join(outputDir, fileName), fileContent);
|
|
14825
14949
|
return {
|
|
14826
14950
|
scenario,
|
|
14827
14951
|
fileName,
|
|
@@ -14847,7 +14971,7 @@ function createBddHandler(deps = {}) {
|
|
|
14847
14971
|
};
|
|
14848
14972
|
const manifestContent = `${JSON.stringify(manifest, null, 2)}
|
|
14849
14973
|
`;
|
|
14850
|
-
writeFile(
|
|
14974
|
+
writeFile(import_node_path12.default.join(outputDir, "manifest.json"), manifestContent);
|
|
14851
14975
|
const archivePath = `${outputDir}.zip`;
|
|
14852
14976
|
if (zipRequested) {
|
|
14853
14977
|
await createZipArchive(archivePath, [
|
|
@@ -14895,8 +15019,8 @@ function createBddHandler(deps = {}) {
|
|
|
14895
15019
|
}
|
|
14896
15020
|
}
|
|
14897
15021
|
if (nested === "import") {
|
|
14898
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
14899
|
-
const inputDir = parsed.flags["--input-dir"] ?
|
|
15022
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path12.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
15023
|
+
const inputDir = parsed.flags["--input-dir"] ? import_node_path12.default.resolve(cwd, parsed.flags["--input-dir"]) : "";
|
|
14900
15024
|
const dryRun = parsed.boolFlags.has("--dry-run");
|
|
14901
15025
|
if (!sourceFile && !inputDir) {
|
|
14902
15026
|
return {
|
|
@@ -14905,7 +15029,7 @@ function createBddHandler(deps = {}) {
|
|
|
14905
15029
|
};
|
|
14906
15030
|
}
|
|
14907
15031
|
try {
|
|
14908
|
-
const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) =>
|
|
15032
|
+
const scenarioFiles = sourceFile ? [sourceFile] : readDir(inputDir).filter((entry) => entry.toLowerCase().endsWith(".feature")).map((entry) => import_node_path12.default.join(inputDir, entry)).sort((left, right) => left.localeCompare(right));
|
|
14909
15033
|
if (scenarioFiles.length === 0) {
|
|
14910
15034
|
return {
|
|
14911
15035
|
exitCode: ExitCode.ValidationError,
|
|
@@ -15215,6 +15339,138 @@ function createBddHandler(deps = {}) {
|
|
|
15215
15339
|
};
|
|
15216
15340
|
}
|
|
15217
15341
|
|
|
15342
|
+
// src/bddCommand.ts
|
|
15343
|
+
var CONFIG_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
15344
|
+
"--config",
|
|
15345
|
+
"--base-url",
|
|
15346
|
+
"--project-key",
|
|
15347
|
+
"--issue-key",
|
|
15348
|
+
"--auth-mode",
|
|
15349
|
+
"--jira-email",
|
|
15350
|
+
"--jira-api-token"
|
|
15351
|
+
]);
|
|
15352
|
+
function parseListArgs(args) {
|
|
15353
|
+
let json = false;
|
|
15354
|
+
const configArgs = [];
|
|
15355
|
+
const invalid = [];
|
|
15356
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
15357
|
+
const token = args[index];
|
|
15358
|
+
if (token === "--json") {
|
|
15359
|
+
json = true;
|
|
15360
|
+
continue;
|
|
15361
|
+
}
|
|
15362
|
+
if (!CONFIG_VALUE_FLAGS.has(token)) {
|
|
15363
|
+
invalid.push(token);
|
|
15364
|
+
continue;
|
|
15365
|
+
}
|
|
15366
|
+
const value = args[index + 1];
|
|
15367
|
+
if (!value || value.startsWith("--")) {
|
|
15368
|
+
invalid.push(token);
|
|
15369
|
+
continue;
|
|
15370
|
+
}
|
|
15371
|
+
configArgs.push(token, value);
|
|
15372
|
+
index += 1;
|
|
15373
|
+
}
|
|
15374
|
+
return { json, configArgs, invalid };
|
|
15375
|
+
}
|
|
15376
|
+
function normalizeError4(error) {
|
|
15377
|
+
if (error instanceof ForgeClientError) {
|
|
15378
|
+
return `${error.code}: ${error.message}`;
|
|
15379
|
+
}
|
|
15380
|
+
if (error instanceof Error) {
|
|
15381
|
+
return error.message;
|
|
15382
|
+
}
|
|
15383
|
+
return "Unknown BDD scenario list transport error.";
|
|
15384
|
+
}
|
|
15385
|
+
function scenarioToJson(scenario) {
|
|
15386
|
+
return {
|
|
15387
|
+
id: scenario.id,
|
|
15388
|
+
key: scenario.key ?? null,
|
|
15389
|
+
featureId: scenario.featureId,
|
|
15390
|
+
featureName: scenario.featureName,
|
|
15391
|
+
name: scenario.name,
|
|
15392
|
+
tags: [...scenario.tags],
|
|
15393
|
+
linkedIssueKeys: [...scenario.linkedIssueKeys],
|
|
15394
|
+
stepCount: scenario.steps.length,
|
|
15395
|
+
createdAt: scenario.createdAt,
|
|
15396
|
+
updatedAt: scenario.updatedAt
|
|
15397
|
+
};
|
|
15398
|
+
}
|
|
15399
|
+
function scenarioToLine(scenario) {
|
|
15400
|
+
const selector = scenario.key ?? scenario.id;
|
|
15401
|
+
const issues = scenario.linkedIssueKeys.length > 0 ? scenario.linkedIssueKeys.join(", ") : "none";
|
|
15402
|
+
return `${selector} | ${scenario.name} | Feature: ${scenario.featureName} | Steps: ${scenario.steps.length} | Issues: ${issues}`;
|
|
15403
|
+
}
|
|
15404
|
+
function createBddCommandHandler(deps = {}) {
|
|
15405
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
15406
|
+
const env = deps.env ?? process.env;
|
|
15407
|
+
const delegate = deps.delegate ?? createBddHandler({ cwd, env });
|
|
15408
|
+
return async (request, context) => {
|
|
15409
|
+
if (request.args[0] !== "scenarios" || request.args[1] !== "list") {
|
|
15410
|
+
return delegate(request, context);
|
|
15411
|
+
}
|
|
15412
|
+
const parsed = parseListArgs(request.args.slice(2));
|
|
15413
|
+
if (parsed.invalid.length > 0) {
|
|
15414
|
+
return {
|
|
15415
|
+
exitCode: ExitCode.UsageError,
|
|
15416
|
+
stderr: [`ERROR: Unknown or invalid arguments: ${parsed.invalid.join(", ")}`]
|
|
15417
|
+
};
|
|
15418
|
+
}
|
|
15419
|
+
const config = resolveCliConfig(parsed.configArgs, env, cwd).values;
|
|
15420
|
+
if (!config.projectKey) {
|
|
15421
|
+
return {
|
|
15422
|
+
exitCode: ExitCode.ValidationError,
|
|
15423
|
+
stderr: ["ERROR: Missing project context. Set JIRA_PROJECT_KEY or pass --project-key."]
|
|
15424
|
+
};
|
|
15425
|
+
}
|
|
15426
|
+
try {
|
|
15427
|
+
const result = await context.invokeForgeContract("listBddScenarios", {
|
|
15428
|
+
context: {
|
|
15429
|
+
projectKey: config.projectKey,
|
|
15430
|
+
issueKey: config.issueKey || void 0
|
|
15431
|
+
}
|
|
15432
|
+
});
|
|
15433
|
+
if (!result.ok) {
|
|
15434
|
+
return {
|
|
15435
|
+
exitCode: ExitCode.RemoteError,
|
|
15436
|
+
stderr: [`ERROR: ${result.error.code}: ${result.error.message}`]
|
|
15437
|
+
};
|
|
15438
|
+
}
|
|
15439
|
+
const scenarios = result.data;
|
|
15440
|
+
if (parsed.json) {
|
|
15441
|
+
return {
|
|
15442
|
+
exitCode: ExitCode.Success,
|
|
15443
|
+
stdout: toJsonLine({
|
|
15444
|
+
action: "bdd-scenarios-list",
|
|
15445
|
+
projectKey: config.projectKey,
|
|
15446
|
+
issueKey: config.issueKey || null,
|
|
15447
|
+
count: scenarios.length,
|
|
15448
|
+
items: scenarios.map(scenarioToJson)
|
|
15449
|
+
})
|
|
15450
|
+
};
|
|
15451
|
+
}
|
|
15452
|
+
if (scenarios.length === 0) {
|
|
15453
|
+
return {
|
|
15454
|
+
exitCode: ExitCode.Success,
|
|
15455
|
+
stdout: [`No BDD scenarios found for project ${config.projectKey}.`]
|
|
15456
|
+
};
|
|
15457
|
+
}
|
|
15458
|
+
return {
|
|
15459
|
+
exitCode: ExitCode.Success,
|
|
15460
|
+
stdout: [
|
|
15461
|
+
`BDD scenarios (${scenarios.length}) for project ${config.projectKey}:`,
|
|
15462
|
+
...scenarios.map(scenarioToLine)
|
|
15463
|
+
]
|
|
15464
|
+
};
|
|
15465
|
+
} catch (error) {
|
|
15466
|
+
return {
|
|
15467
|
+
exitCode: ExitCode.TransportError,
|
|
15468
|
+
stderr: [`ERROR: ${normalizeError4(error)}`]
|
|
15469
|
+
};
|
|
15470
|
+
}
|
|
15471
|
+
};
|
|
15472
|
+
}
|
|
15473
|
+
|
|
15218
15474
|
// src/cases.ts
|
|
15219
15475
|
var CONFIG_FLAGS4 = /* @__PURE__ */ new Set([
|
|
15220
15476
|
"--config",
|
|
@@ -15263,7 +15519,7 @@ function pickConfigArgs4(parsed) {
|
|
|
15263
15519
|
}
|
|
15264
15520
|
return args;
|
|
15265
15521
|
}
|
|
15266
|
-
function
|
|
15522
|
+
function normalizeError5(error) {
|
|
15267
15523
|
if (error instanceof ForgeClientError) {
|
|
15268
15524
|
return `${error.code}: ${error.message}`;
|
|
15269
15525
|
}
|
|
@@ -15441,7 +15697,7 @@ function createCasesHandler(deps = {}) {
|
|
|
15441
15697
|
} catch (error) {
|
|
15442
15698
|
return {
|
|
15443
15699
|
exitCode: ExitCode.TransportError,
|
|
15444
|
-
stderr: [`ERROR: ${
|
|
15700
|
+
stderr: [`ERROR: ${normalizeError5(error)}`]
|
|
15445
15701
|
};
|
|
15446
15702
|
}
|
|
15447
15703
|
}
|
|
@@ -15483,7 +15739,7 @@ function createCasesHandler(deps = {}) {
|
|
|
15483
15739
|
} catch (error) {
|
|
15484
15740
|
return {
|
|
15485
15741
|
exitCode: ExitCode.TransportError,
|
|
15486
|
-
stderr: [`ERROR: ${
|
|
15742
|
+
stderr: [`ERROR: ${normalizeError5(error)}`]
|
|
15487
15743
|
};
|
|
15488
15744
|
}
|
|
15489
15745
|
}
|
|
@@ -15546,7 +15802,7 @@ function createCasesHandler(deps = {}) {
|
|
|
15546
15802
|
} catch (error) {
|
|
15547
15803
|
return {
|
|
15548
15804
|
exitCode: ExitCode.TransportError,
|
|
15549
|
-
stderr: [`ERROR: ${
|
|
15805
|
+
stderr: [`ERROR: ${normalizeError5(error)}`]
|
|
15550
15806
|
};
|
|
15551
15807
|
}
|
|
15552
15808
|
}
|
|
@@ -15609,7 +15865,7 @@ function createCasesHandler(deps = {}) {
|
|
|
15609
15865
|
} catch (error) {
|
|
15610
15866
|
return {
|
|
15611
15867
|
exitCode: ExitCode.TransportError,
|
|
15612
|
-
stderr: [`ERROR: ${
|
|
15868
|
+
stderr: [`ERROR: ${normalizeError5(error)}`]
|
|
15613
15869
|
};
|
|
15614
15870
|
}
|
|
15615
15871
|
}
|
|
@@ -15954,8 +16210,8 @@ function createDoctorHandler(deps = {}) {
|
|
|
15954
16210
|
}
|
|
15955
16211
|
|
|
15956
16212
|
// src/ingestFeature.ts
|
|
15957
|
-
var
|
|
15958
|
-
var
|
|
16213
|
+
var import_node_fs13 = require("node:fs");
|
|
16214
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
15959
16215
|
var CONFIG_FLAGS6 = /* @__PURE__ */ new Set([
|
|
15960
16216
|
"--config",
|
|
15961
16217
|
"--base-url",
|
|
@@ -16031,7 +16287,7 @@ function summarizeSuccess(result) {
|
|
|
16031
16287
|
}
|
|
16032
16288
|
return lines;
|
|
16033
16289
|
}
|
|
16034
|
-
function
|
|
16290
|
+
function normalizeError6(error) {
|
|
16035
16291
|
if (error instanceof ForgeClientError) {
|
|
16036
16292
|
return `${error.code}: ${error.message}`;
|
|
16037
16293
|
}
|
|
@@ -16041,8 +16297,8 @@ function normalizeError5(error) {
|
|
|
16041
16297
|
return "Unknown ingest error.";
|
|
16042
16298
|
}
|
|
16043
16299
|
function createIngestFeatureHandler(deps = {}) {
|
|
16044
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
16045
|
-
const readStdin = deps.readStdin ?? (() => (0,
|
|
16300
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs13.readFileSync)(filePath, "utf8"));
|
|
16301
|
+
const readStdin = deps.readStdin ?? (() => (0, import_node_fs13.readFileSync)(0, "utf8"));
|
|
16046
16302
|
const cwd = deps.cwd ?? process.cwd();
|
|
16047
16303
|
const env = deps.env ?? process.env;
|
|
16048
16304
|
return async (request, context) => {
|
|
@@ -16052,7 +16308,7 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
16052
16308
|
const config = resolveCliConfig(configArgs, env, cwd);
|
|
16053
16309
|
const projectKey = config.values.projectKey;
|
|
16054
16310
|
const issueKey = config.values.issueKey;
|
|
16055
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
16311
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path13.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
16056
16312
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
16057
16313
|
const useJson = parsed.boolFlags.has("--json");
|
|
16058
16314
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -16068,7 +16324,7 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
16068
16324
|
} catch (error) {
|
|
16069
16325
|
return {
|
|
16070
16326
|
exitCode: ExitCode.InternalError,
|
|
16071
|
-
stderr: [`ERROR: Failed to read feature source: ${
|
|
16327
|
+
stderr: [`ERROR: Failed to read feature source: ${normalizeError6(error)}`]
|
|
16072
16328
|
};
|
|
16073
16329
|
}
|
|
16074
16330
|
const name = (parsed.flags["--name"] ?? deriveNameFromGherkin(gherkin)).trim();
|
|
@@ -16159,14 +16415,14 @@ function createIngestFeatureHandler(deps = {}) {
|
|
|
16159
16415
|
status: "failed",
|
|
16160
16416
|
featureName: name,
|
|
16161
16417
|
source: useStdin ? "stdin" : sourceFile,
|
|
16162
|
-
errorMessage:
|
|
16418
|
+
errorMessage: normalizeError6(error)
|
|
16163
16419
|
})
|
|
16164
16420
|
};
|
|
16165
16421
|
}
|
|
16166
16422
|
return {
|
|
16167
16423
|
exitCode: ExitCode.TransportError,
|
|
16168
16424
|
stdout: ["Feature ingestion: FAILED", `Feature: ${name}`, `Source: ${useStdin ? "stdin" : sourceFile}`],
|
|
16169
|
-
stderr: [`ERROR: ${
|
|
16425
|
+
stderr: [`ERROR: ${normalizeError6(error)}`]
|
|
16170
16426
|
};
|
|
16171
16427
|
}
|
|
16172
16428
|
};
|
|
@@ -16221,7 +16477,7 @@ function pickConfigArgs7(parsed) {
|
|
|
16221
16477
|
}
|
|
16222
16478
|
return args;
|
|
16223
16479
|
}
|
|
16224
|
-
function
|
|
16480
|
+
function normalizeError7(error) {
|
|
16225
16481
|
if (error instanceof ForgeClientError) {
|
|
16226
16482
|
return `${error.code}: ${error.message}`;
|
|
16227
16483
|
}
|
|
@@ -16364,7 +16620,7 @@ function createProfilesHandler(deps = {}) {
|
|
|
16364
16620
|
} catch (error) {
|
|
16365
16621
|
return {
|
|
16366
16622
|
exitCode: ExitCode.TransportError,
|
|
16367
|
-
stderr: [`ERROR: ${
|
|
16623
|
+
stderr: [`ERROR: ${normalizeError7(error)}`]
|
|
16368
16624
|
};
|
|
16369
16625
|
}
|
|
16370
16626
|
}
|
|
@@ -16450,7 +16706,7 @@ function createProfilesHandler(deps = {}) {
|
|
|
16450
16706
|
} catch (error) {
|
|
16451
16707
|
return {
|
|
16452
16708
|
exitCode: ExitCode.TransportError,
|
|
16453
|
-
stderr: [`ERROR: ${
|
|
16709
|
+
stderr: [`ERROR: ${normalizeError7(error)}`]
|
|
16454
16710
|
};
|
|
16455
16711
|
}
|
|
16456
16712
|
}
|
|
@@ -16548,7 +16804,7 @@ function createProfilesHandler(deps = {}) {
|
|
|
16548
16804
|
} catch (error) {
|
|
16549
16805
|
return {
|
|
16550
16806
|
exitCode: ExitCode.TransportError,
|
|
16551
|
-
stderr: [`ERROR: ${
|
|
16807
|
+
stderr: [`ERROR: ${normalizeError7(error)}`]
|
|
16552
16808
|
};
|
|
16553
16809
|
}
|
|
16554
16810
|
}
|
|
@@ -16659,7 +16915,7 @@ function createProfilesHandler(deps = {}) {
|
|
|
16659
16915
|
} catch (error) {
|
|
16660
16916
|
return {
|
|
16661
16917
|
exitCode: ExitCode.TransportError,
|
|
16662
|
-
stderr: [`ERROR: ${
|
|
16918
|
+
stderr: [`ERROR: ${normalizeError7(error)}`]
|
|
16663
16919
|
};
|
|
16664
16920
|
}
|
|
16665
16921
|
}
|
|
@@ -16671,8 +16927,8 @@ function createProfilesHandler(deps = {}) {
|
|
|
16671
16927
|
}
|
|
16672
16928
|
|
|
16673
16929
|
// src/runUpload.ts
|
|
16674
|
-
var
|
|
16675
|
-
var
|
|
16930
|
+
var import_node_fs14 = require("node:fs");
|
|
16931
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
16676
16932
|
var STEP_RESULTS = [
|
|
16677
16933
|
StepResult.Passed,
|
|
16678
16934
|
StepResult.Failed,
|
|
@@ -16734,7 +16990,7 @@ function pickConfigArgs8(parsed) {
|
|
|
16734
16990
|
}
|
|
16735
16991
|
return configArgs;
|
|
16736
16992
|
}
|
|
16737
|
-
function
|
|
16993
|
+
function normalizeError8(error) {
|
|
16738
16994
|
if (error instanceof ForgeClientError) {
|
|
16739
16995
|
return `${error.code}: ${error.message}`;
|
|
16740
16996
|
}
|
|
@@ -16813,8 +17069,8 @@ function summarizeRunResult(result) {
|
|
|
16813
17069
|
return lines;
|
|
16814
17070
|
}
|
|
16815
17071
|
function createRunUploadHandler(deps = {}) {
|
|
16816
|
-
const readFile = deps.readFile ?? ((filePath) => (0,
|
|
16817
|
-
const readStdin = deps.readStdin ?? (() => (0,
|
|
17072
|
+
const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs14.readFileSync)(filePath, "utf8"));
|
|
17073
|
+
const readStdin = deps.readStdin ?? (() => (0, import_node_fs14.readFileSync)(0, "utf8"));
|
|
16818
17074
|
const cwd = deps.cwd ?? process.cwd();
|
|
16819
17075
|
const env = deps.env ?? process.env;
|
|
16820
17076
|
return async (request, context) => {
|
|
@@ -16825,7 +17081,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
16825
17081
|
const projectKey = config.values.projectKey;
|
|
16826
17082
|
const issueKey = config.values.issueKey;
|
|
16827
17083
|
const testCaseKey = parsed.flags["--test-case-key"]?.trim().toUpperCase() ?? "";
|
|
16828
|
-
const sourceFile = parsed.flags["--file"] ?
|
|
17084
|
+
const sourceFile = parsed.flags["--file"] ? import_node_path14.default.resolve(cwd, parsed.flags["--file"]) : "";
|
|
16829
17085
|
const useStdin = parsed.boolFlags.has("--stdin");
|
|
16830
17086
|
const useJson = parsed.boolFlags.has("--json");
|
|
16831
17087
|
const sourceCount = Number(Boolean(sourceFile)) + Number(useStdin);
|
|
@@ -16853,7 +17109,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
16853
17109
|
} catch (error) {
|
|
16854
17110
|
return {
|
|
16855
17111
|
exitCode: ExitCode.InternalError,
|
|
16856
|
-
stderr: [`ERROR: Failed to read run payload source: ${
|
|
17112
|
+
stderr: [`ERROR: Failed to read run payload source: ${normalizeError8(error)}`]
|
|
16857
17113
|
};
|
|
16858
17114
|
}
|
|
16859
17115
|
const payloadFromSource = parseRunPayload(raw);
|
|
@@ -16883,7 +17139,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
16883
17139
|
} catch (error) {
|
|
16884
17140
|
return {
|
|
16885
17141
|
exitCode: ExitCode.TransportError,
|
|
16886
|
-
stderr: [`ERROR: ${
|
|
17142
|
+
stderr: [`ERROR: ${normalizeError8(error)}`]
|
|
16887
17143
|
};
|
|
16888
17144
|
}
|
|
16889
17145
|
}
|
|
@@ -16963,7 +17219,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
16963
17219
|
featureName: runInput.featureName,
|
|
16964
17220
|
scenarioName: runInput.scenarioName,
|
|
16965
17221
|
executedAt: runInput.executedAt,
|
|
16966
|
-
errorMessage:
|
|
17222
|
+
errorMessage: normalizeError8(error)
|
|
16967
17223
|
})
|
|
16968
17224
|
};
|
|
16969
17225
|
}
|
|
@@ -16975,7 +17231,7 @@ function createRunUploadHandler(deps = {}) {
|
|
|
16975
17231
|
`Scenario: ${runInput.scenarioName}`,
|
|
16976
17232
|
`ExecutedAt: ${runInput.executedAt}`
|
|
16977
17233
|
],
|
|
16978
|
-
stderr: [`ERROR: ${
|
|
17234
|
+
stderr: [`ERROR: ${normalizeError8(error)}`]
|
|
16979
17235
|
};
|
|
16980
17236
|
}
|
|
16981
17237
|
};
|
|
@@ -17029,7 +17285,7 @@ function pickConfigArgs9(parsed) {
|
|
|
17029
17285
|
}
|
|
17030
17286
|
return args;
|
|
17031
17287
|
}
|
|
17032
|
-
function
|
|
17288
|
+
function normalizeError9(error) {
|
|
17033
17289
|
if (error instanceof ForgeClientError) {
|
|
17034
17290
|
return `${error.code}: ${error.message}`;
|
|
17035
17291
|
}
|
|
@@ -17147,7 +17403,7 @@ function createRunsHandler(deps = {}) {
|
|
|
17147
17403
|
} catch (error) {
|
|
17148
17404
|
return {
|
|
17149
17405
|
exitCode: ExitCode.TransportError,
|
|
17150
|
-
stderr: [`ERROR: ${
|
|
17406
|
+
stderr: [`ERROR: ${normalizeError9(error)}`]
|
|
17151
17407
|
};
|
|
17152
17408
|
}
|
|
17153
17409
|
}
|
|
@@ -17159,16 +17415,16 @@ function createRunsHandler(deps = {}) {
|
|
|
17159
17415
|
}
|
|
17160
17416
|
|
|
17161
17417
|
// src/setup.ts
|
|
17162
|
-
var
|
|
17163
|
-
var
|
|
17418
|
+
var import_node_fs16 = require("node:fs");
|
|
17419
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
17164
17420
|
|
|
17165
17421
|
// src/githubSetupProvider.ts
|
|
17166
17422
|
var import_node_child_process4 = require("node:child_process");
|
|
17167
17423
|
|
|
17168
17424
|
// src/setupPlan.ts
|
|
17169
|
-
var
|
|
17170
|
-
var
|
|
17171
|
-
var
|
|
17425
|
+
var import_node_crypto2 = require("node:crypto");
|
|
17426
|
+
var import_node_fs15 = require("node:fs");
|
|
17427
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
17172
17428
|
var SETUP_PLAN_SCHEMA_VERSION = "automatify.testops.setup/v1";
|
|
17173
17429
|
var SETUP_PLAN_KIND = "AutomatifyTestOpsSetupPlan";
|
|
17174
17430
|
var ACTIONS = [
|
|
@@ -17192,7 +17448,7 @@ var ACTIONS = [
|
|
|
17192
17448
|
}
|
|
17193
17449
|
];
|
|
17194
17450
|
function sha256(value) {
|
|
17195
|
-
return (0,
|
|
17451
|
+
return (0, import_node_crypto2.createHash)("sha256").update(value, "utf8").digest("hex");
|
|
17196
17452
|
}
|
|
17197
17453
|
function sortJsonValue(value) {
|
|
17198
17454
|
if (Array.isArray(value)) {
|
|
@@ -17237,8 +17493,8 @@ function normalizeRepoPart(value, field) {
|
|
|
17237
17493
|
return normalized;
|
|
17238
17494
|
}
|
|
17239
17495
|
function normalizeWorkflowPath(value) {
|
|
17240
|
-
const normalized =
|
|
17241
|
-
if (
|
|
17496
|
+
const normalized = import_node_path15.default.posix.normalize(requireNonEmpty(value, "workflow path").replaceAll("\\", "/"));
|
|
17497
|
+
if (import_node_path15.default.posix.isAbsolute(normalized) || normalized.startsWith("../") || !normalized.startsWith(".github/workflows/") || !/\.ya?ml$/i.test(normalized)) {
|
|
17242
17498
|
throw new Error("workflow path must be a relative .github/workflows/*.yml or *.yaml path without '..'.");
|
|
17243
17499
|
}
|
|
17244
17500
|
return normalized;
|
|
@@ -17263,7 +17519,7 @@ function buildGitHubSetupPlan(input) {
|
|
|
17263
17519
|
if (endpointSecretName === tokenSecretName) {
|
|
17264
17520
|
throw new Error("callback endpoint and auth token secret names must be different.");
|
|
17265
17521
|
}
|
|
17266
|
-
const workflowContent = (0,
|
|
17522
|
+
const workflowContent = (0, import_node_fs15.readFileSync)(input.workflowSourcePath, "utf8");
|
|
17267
17523
|
if (!workflowContent.trim()) {
|
|
17268
17524
|
throw new Error("workflow source file is empty.");
|
|
17269
17525
|
}
|
|
@@ -17296,7 +17552,7 @@ function buildGitHubSetupPlan(input) {
|
|
|
17296
17552
|
workflowId,
|
|
17297
17553
|
workflowFile: {
|
|
17298
17554
|
path: workflowPath,
|
|
17299
|
-
sourcePath:
|
|
17555
|
+
sourcePath: import_node_path15.default.resolve(input.workflowSourcePath),
|
|
17300
17556
|
sha256: sha256(workflowContent)
|
|
17301
17557
|
},
|
|
17302
17558
|
requiredSecrets: [
|
|
@@ -17897,8 +18153,8 @@ var AzureDevOpsSetupProvider = class {
|
|
|
17897
18153
|
};
|
|
17898
18154
|
|
|
17899
18155
|
// src/azureDevOpsSetupPlan.ts
|
|
17900
|
-
var
|
|
17901
|
-
var digest = (v) => `sha256:${(0,
|
|
18156
|
+
var import_node_crypto3 = require("node:crypto");
|
|
18157
|
+
var digest = (v) => `sha256:${(0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(v)).digest("hex")}`;
|
|
17902
18158
|
var required = (value, field) => {
|
|
17903
18159
|
const result = value.trim();
|
|
17904
18160
|
if (!result) throw new Error(`${field} is required.`);
|
|
@@ -18206,10 +18462,10 @@ function errorCodeForError(error, fallback) {
|
|
|
18206
18462
|
return error instanceof SetupCommandError ? error.cliCode : fallback;
|
|
18207
18463
|
}
|
|
18208
18464
|
function loadPlan(planPath, cwd) {
|
|
18209
|
-
const absolute =
|
|
18465
|
+
const absolute = import_node_path16.default.resolve(cwd, planPath);
|
|
18210
18466
|
let parsed;
|
|
18211
18467
|
try {
|
|
18212
|
-
parsed = JSON.parse((0,
|
|
18468
|
+
parsed = JSON.parse((0, import_node_fs16.readFileSync)(absolute, "utf8"));
|
|
18213
18469
|
} catch (error) {
|
|
18214
18470
|
throw new SetupCommandError(
|
|
18215
18471
|
"PLAN_READ_ERROR",
|
|
@@ -18434,9 +18690,9 @@ function rollbackFor(plan, actionId) {
|
|
|
18434
18690
|
return plan.rollback.find((item) => item.actionId === actionId)?.strategy ?? "Review the plan rollback section.";
|
|
18435
18691
|
}
|
|
18436
18692
|
function resolveWorkflowTarget(plan, repoRoot) {
|
|
18437
|
-
const resolvedRoot =
|
|
18438
|
-
const target =
|
|
18439
|
-
if (target !== resolvedRoot && !target.startsWith(`${resolvedRoot}${
|
|
18693
|
+
const resolvedRoot = import_node_path16.default.resolve(repoRoot);
|
|
18694
|
+
const target = import_node_path16.default.resolve(resolvedRoot, plan.github.workflowFile.path);
|
|
18695
|
+
if (target !== resolvedRoot && !target.startsWith(`${resolvedRoot}${import_node_path16.default.sep}`)) {
|
|
18440
18696
|
throw new SetupCommandError(
|
|
18441
18697
|
"WORKFLOW_PATH_ERROR",
|
|
18442
18698
|
"Workflow target escapes the approved repository root.",
|
|
@@ -18448,7 +18704,7 @@ function resolveWorkflowTarget(plan, repoRoot) {
|
|
|
18448
18704
|
function applyWorkflowFile(plan, repoRoot, dryRun) {
|
|
18449
18705
|
const action = plan.actions.find((item) => item.scope === "workflow-file");
|
|
18450
18706
|
const target = resolveWorkflowTarget(plan, repoRoot);
|
|
18451
|
-
const sourceContent = (0,
|
|
18707
|
+
const sourceContent = (0, import_node_fs16.readFileSync)(plan.github.workflowFile.sourcePath, "utf8");
|
|
18452
18708
|
if (hashSetupContent(sourceContent) !== plan.github.workflowFile.sha256) {
|
|
18453
18709
|
throw new SetupCommandError(
|
|
18454
18710
|
"WORKFLOW_SOURCE_CHANGED",
|
|
@@ -18456,8 +18712,8 @@ function applyWorkflowFile(plan, repoRoot, dryRun) {
|
|
|
18456
18712
|
ExitCode.ValidationError
|
|
18457
18713
|
);
|
|
18458
18714
|
}
|
|
18459
|
-
const existed = (0,
|
|
18460
|
-
const previousContent = existed ? (0,
|
|
18715
|
+
const existed = (0, import_node_fs16.existsSync)(target);
|
|
18716
|
+
const previousContent = existed ? (0, import_node_fs16.readFileSync)(target, "utf8") : void 0;
|
|
18461
18717
|
const matches = previousContent !== void 0 && hashSetupContent(previousContent) === plan.github.workflowFile.sha256;
|
|
18462
18718
|
if (matches) {
|
|
18463
18719
|
return {
|
|
@@ -18469,8 +18725,8 @@ function applyWorkflowFile(plan, repoRoot, dryRun) {
|
|
|
18469
18725
|
};
|
|
18470
18726
|
}
|
|
18471
18727
|
if (!dryRun) {
|
|
18472
|
-
(0,
|
|
18473
|
-
(0,
|
|
18728
|
+
(0, import_node_fs16.mkdirSync)(import_node_path16.default.dirname(target), { recursive: true });
|
|
18729
|
+
(0, import_node_fs16.writeFileSync)(target, sourceContent, { encoding: "utf8", mode: 420 });
|
|
18474
18730
|
}
|
|
18475
18731
|
return {
|
|
18476
18732
|
id: action.id,
|
|
@@ -18640,14 +18896,14 @@ async function inspectPlan(plan, repoRoot, secrets, context, deps) {
|
|
|
18640
18896
|
const checks = [];
|
|
18641
18897
|
let forgeTransportFailure = false;
|
|
18642
18898
|
const target = resolveWorkflowTarget(plan, repoRoot);
|
|
18643
|
-
if (!(0,
|
|
18899
|
+
if (!(0, import_node_fs16.existsSync)(target)) {
|
|
18644
18900
|
checks.push({
|
|
18645
18901
|
id: "workflow-local",
|
|
18646
18902
|
status: "fail",
|
|
18647
18903
|
message: `Local workflow file ${plan.github.workflowFile.path} does not exist.`
|
|
18648
18904
|
});
|
|
18649
18905
|
} else {
|
|
18650
|
-
const localHash = hashSetupContent((0,
|
|
18906
|
+
const localHash = hashSetupContent((0, import_node_fs16.readFileSync)(target, "utf8"));
|
|
18651
18907
|
checks.push({
|
|
18652
18908
|
id: "workflow-local",
|
|
18653
18909
|
status: localHash === plan.github.workflowFile.sha256 ? "pass" : "fail",
|
|
@@ -18783,7 +19039,7 @@ function planCommand(args, deps) {
|
|
|
18783
19039
|
ref: parsed.flags["--ref"] ?? "main",
|
|
18784
19040
|
workflowId: parsed.flags["--workflow-id"] ?? "scenario-dispatch.yml",
|
|
18785
19041
|
workflowPath: parsed.flags["--workflow-path"] ?? ".github/workflows/scenario-dispatch.yml",
|
|
18786
|
-
workflowSourcePath:
|
|
19042
|
+
workflowSourcePath: import_node_path16.default.resolve(deps.cwd, parsed.flags["--workflow-source"] ?? ""),
|
|
18787
19043
|
profileLabel: parsed.flags["--profile-label"] ?? "GitHub Actions",
|
|
18788
19044
|
enabled: !parsed.boolFlags.has("--disabled"),
|
|
18789
19045
|
setProjectDefault: parsed.boolFlags.has("--set-default"),
|
|
@@ -18823,7 +19079,7 @@ async function applyCommand(args, context, deps) {
|
|
|
18823
19079
|
return await applyAzureCommand(plan, parsed, context, deps, secrets);
|
|
18824
19080
|
}
|
|
18825
19081
|
const scopes = approvedScopes(plan, parsed, dryRun);
|
|
18826
|
-
const repoRoot =
|
|
19082
|
+
const repoRoot = import_node_path16.default.resolve(deps.cwd, parsed.flags["--repo-root"] ?? ".");
|
|
18827
19083
|
const rotateSecrets = parsed.boolFlags.has("--rotate-secrets");
|
|
18828
19084
|
const rotateProviderToken = parsed.boolFlags.has("--rotate-provider-token");
|
|
18829
19085
|
const state = await prepareState(plan, scopes, secrets, context, deps, dryRun, rotateSecrets, rotateProviderToken);
|
|
@@ -19115,7 +19371,7 @@ async function doctorCommand(args, context, deps) {
|
|
|
19115
19371
|
exitCode
|
|
19116
19372
|
);
|
|
19117
19373
|
}
|
|
19118
|
-
const repoRoot =
|
|
19374
|
+
const repoRoot = import_node_path16.default.resolve(deps.cwd, parsed.flags["--repo-root"] ?? ".");
|
|
19119
19375
|
const summary = await inspectPlan(plan, repoRoot, secrets, context, deps);
|
|
19120
19376
|
return jsonResponse(summary, summary.exitCode);
|
|
19121
19377
|
} catch (error) {
|
|
@@ -19199,7 +19455,7 @@ function pickConfigArgs10(parsed) {
|
|
|
19199
19455
|
}
|
|
19200
19456
|
return args;
|
|
19201
19457
|
}
|
|
19202
|
-
function
|
|
19458
|
+
function normalizeError10(error) {
|
|
19203
19459
|
if (error instanceof ForgeClientError) {
|
|
19204
19460
|
return `${error.code}: ${error.message}`;
|
|
19205
19461
|
}
|
|
@@ -19325,7 +19581,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
19325
19581
|
} catch (error) {
|
|
19326
19582
|
return {
|
|
19327
19583
|
exitCode: ExitCode.TransportError,
|
|
19328
|
-
stderr: [`ERROR: ${
|
|
19584
|
+
stderr: [`ERROR: ${normalizeError10(error)}`]
|
|
19329
19585
|
};
|
|
19330
19586
|
}
|
|
19331
19587
|
}
|
|
@@ -19366,7 +19622,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
19366
19622
|
} catch (error) {
|
|
19367
19623
|
return {
|
|
19368
19624
|
exitCode: ExitCode.TransportError,
|
|
19369
|
-
stderr: [`ERROR: ${
|
|
19625
|
+
stderr: [`ERROR: ${normalizeError10(error)}`]
|
|
19370
19626
|
};
|
|
19371
19627
|
}
|
|
19372
19628
|
}
|
|
@@ -19430,7 +19686,7 @@ function createSuitesHandler(deps = {}) {
|
|
|
19430
19686
|
} catch (error) {
|
|
19431
19687
|
return {
|
|
19432
19688
|
exitCode: ExitCode.TransportError,
|
|
19433
|
-
stderr: [`ERROR: ${
|
|
19689
|
+
stderr: [`ERROR: ${normalizeError10(error)}`]
|
|
19434
19690
|
};
|
|
19435
19691
|
}
|
|
19436
19692
|
}
|
|
@@ -19490,7 +19746,7 @@ function pickConfigArgs11(parsed) {
|
|
|
19490
19746
|
}
|
|
19491
19747
|
return args;
|
|
19492
19748
|
}
|
|
19493
|
-
function
|
|
19749
|
+
function normalizeError11(error) {
|
|
19494
19750
|
if (error instanceof ForgeClientError) {
|
|
19495
19751
|
return `${error.code}: ${error.message}`;
|
|
19496
19752
|
}
|
|
@@ -19593,7 +19849,7 @@ function createSyncHandler(deps = {}) {
|
|
|
19593
19849
|
} catch (error) {
|
|
19594
19850
|
return {
|
|
19595
19851
|
exitCode: ExitCode.TransportError,
|
|
19596
|
-
stderr: [`ERROR: ${
|
|
19852
|
+
stderr: [`ERROR: ${normalizeError11(error)}`]
|
|
19597
19853
|
};
|
|
19598
19854
|
}
|
|
19599
19855
|
}
|
|
@@ -19639,7 +19895,7 @@ function createSyncHandler(deps = {}) {
|
|
|
19639
19895
|
} catch (error) {
|
|
19640
19896
|
return {
|
|
19641
19897
|
exitCode: ExitCode.TransportError,
|
|
19642
|
-
stderr: [`ERROR: ${
|
|
19898
|
+
stderr: [`ERROR: ${normalizeError11(error)}`]
|
|
19643
19899
|
};
|
|
19644
19900
|
}
|
|
19645
19901
|
}
|
|
@@ -19673,9 +19929,9 @@ var COMMAND_REGISTRY = [
|
|
|
19673
19929
|
},
|
|
19674
19930
|
{
|
|
19675
19931
|
name: "bdd",
|
|
19676
|
-
description: "BDD scenario inspection and feature export commands",
|
|
19932
|
+
description: "BDD scenario listing, inspection, and feature export commands",
|
|
19677
19933
|
subcommands: ["features", "scenarios"],
|
|
19678
|
-
handler:
|
|
19934
|
+
handler: createBddCommandHandler()
|
|
19679
19935
|
},
|
|
19680
19936
|
{
|
|
19681
19937
|
name: "cases",
|