@automatify-au/cli 0.1.9 → 0.1.10

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 CHANGED
@@ -142,6 +142,7 @@ All TestOps commands are invoked as `automatify testops <command>`:
142
142
  - `allure`
143
143
  - `automatify testops allure upload ABC-123 ./allure-report.zip --dry-run`
144
144
  - `automatify testops allure upload ABC-123 ./allure-report.zip`
145
+ - `automatify testops allure download ABC-123 --output-dir ./downloads`
145
146
  - `auto`
146
147
  - `automatify testops auto --dry-run`
147
148
  - `automatify testops auto`
@@ -150,6 +151,7 @@ All TestOps commands are invoked as `automatify testops <command>`:
150
151
 
151
152
  Purpose:
152
153
  - upload an already generated Allure HTML report ZIP to a Jira issue as evidence.
154
+ - download an uploaded Allure HTML report ZIP from a Jira issue for local inspection.
153
155
  - parse `widgets/summary.json` from the ZIP and add a concise Jira comment with result counts.
154
156
  - keep the flow Java-free and backend-free; this command does not generate Allure reports from raw `allure-results`.
155
157
 
@@ -216,6 +218,22 @@ After a real upload, JSON output includes Jira attachment metadata when Jira ret
216
218
  }
217
219
  ```
218
220
 
221
+ Download the latest Allure report ZIP attachment from a Jira issue:
222
+ ```bash
223
+ automatify testops allure download ABC-123 --output-dir ./downloads
224
+ ```
225
+
226
+ Download selection rules:
227
+ - `--attachment-id <id>` downloads one exact Jira attachment.
228
+ - `--filename <name>` downloads the newest attachment with that filename.
229
+ - without either flag, the CLI chooses the newest `allure-report*.zip` attachment, then falls back to the newest `.zip` attachment.
230
+ - existing local files are not overwritten unless `--force` is passed.
231
+
232
+ Download dry run / JSON:
233
+ ```bash
234
+ automatify testops allure download ABC-123 --dry-run --json
235
+ ```
236
+
219
237
  ### Optional gated maintenance commands
220
238
 
221
239
  - `sync`
@@ -12448,6 +12448,7 @@ function createAutoHandler(deps = {}) {
12448
12448
 
12449
12449
  // src/allure.ts
12450
12450
  var import_node_path8 = __toESM(require("node:path"), 1);
12451
+ var import_node_fs7 = require("node:fs");
12451
12452
 
12452
12453
  // ../../packages/jira-client/src/adf.ts
12453
12454
  function paragraph(text = "") {
@@ -12533,6 +12534,62 @@ async function uploadIssueAttachment(params) {
12533
12534
  size: typeof first?.size === "number" ? first.size : fileStat.size
12534
12535
  };
12535
12536
  }
12537
+ function parseIssueAttachment(value) {
12538
+ if (!value || typeof value !== "object") {
12539
+ return void 0;
12540
+ }
12541
+ const item = value;
12542
+ if (typeof item.id !== "string" || typeof item.filename !== "string") {
12543
+ return void 0;
12544
+ }
12545
+ return {
12546
+ id: item.id,
12547
+ filename: item.filename,
12548
+ self: typeof item.self === "string" ? item.self : void 0,
12549
+ content: typeof item.content === "string" ? item.content : void 0,
12550
+ size: typeof item.size === "number" ? item.size : void 0,
12551
+ created: typeof item.created === "string" ? item.created : void 0
12552
+ };
12553
+ }
12554
+ async function listIssueAttachments(params) {
12555
+ const site = normalizeSite(params.site);
12556
+ const response = await fetch(`${site}/rest/api/3/issue/${encodeURIComponent(params.issueKey)}?fields=attachment`, {
12557
+ headers: {
12558
+ authorization: authHeader(params.email, params.apiToken),
12559
+ accept: "application/json"
12560
+ }
12561
+ });
12562
+ if (!response.ok) {
12563
+ throw new Error(`Jira attachment listing failed: ${await readError(response)}`);
12564
+ }
12565
+ const parsed = await response.json();
12566
+ const attachments = Array.isArray(parsed.fields?.attachment) ? parsed.fields.attachment : [];
12567
+ return attachments.map(parseIssueAttachment).filter((item) => Boolean(item));
12568
+ }
12569
+ async function downloadIssueAttachment(params) {
12570
+ const url = params.attachment.content;
12571
+ if (!url) {
12572
+ throw new Error(`Jira attachment ${params.attachment.id} does not include a downloadable URL.`);
12573
+ }
12574
+ const response = await fetch(url, {
12575
+ headers: {
12576
+ authorization: authHeader(params.email, params.apiToken)
12577
+ }
12578
+ });
12579
+ if (!response.ok) {
12580
+ throw new Error(`Jira attachment download failed: ${await readError(response)}`);
12581
+ }
12582
+ const bytes = new Uint8Array(await response.arrayBuffer());
12583
+ (0, import_node_fs5.writeFileSync)(params.outputPath, bytes);
12584
+ return {
12585
+ filename: params.attachment.filename,
12586
+ id: params.attachment.id,
12587
+ outputPath: params.outputPath,
12588
+ self: params.attachment.self,
12589
+ content: params.attachment.content,
12590
+ size: bytes.byteLength
12591
+ };
12592
+ }
12536
12593
  async function addIssueComment(params) {
12537
12594
  const site = normalizeSite(params.site);
12538
12595
  const response = await fetch(`${site}/rest/api/3/issue/${encodeURIComponent(params.issueKey)}/comment`, {
@@ -12643,9 +12700,12 @@ function parseArgs2(args) {
12643
12700
  "--site",
12644
12701
  "--email",
12645
12702
  "--api-token",
12703
+ "--attachment-id",
12704
+ "--filename",
12705
+ "--output-dir",
12646
12706
  ...CONFIG_FLAGS2
12647
12707
  ]);
12648
- const supportedBoolFlags = /* @__PURE__ */ new Set(["--no-comment", "--comment", "--json", "--dry-run", "--verbose"]);
12708
+ const supportedBoolFlags = /* @__PURE__ */ new Set(["--no-comment", "--comment", "--json", "--dry-run", "--verbose", "--force"]);
12649
12709
  for (let i = 0; i < args.length; i += 1) {
12650
12710
  const token = args[i];
12651
12711
  if (!token.startsWith("--")) {
@@ -12688,6 +12748,23 @@ function normalizeError(error) {
12688
12748
  function hasCredential(value) {
12689
12749
  return value.trim().length > 0;
12690
12750
  }
12751
+ function resolveJiraConfig(parsed, env, cwd) {
12752
+ const config = resolveCliConfig(pickConfigArgs2(parsed), env, cwd);
12753
+ const site = normalizeSite2(parsed.flags["--site"] ?? env.JIRA_SITE ?? config.values.baseUrl);
12754
+ const email = (parsed.flags["--email"] ?? config.values.jiraEmail).trim();
12755
+ const apiToken = (parsed.flags["--api-token"] ?? config.values.jiraApiToken).trim();
12756
+ const errors = [];
12757
+ if (!hasCredential(site)) {
12758
+ errors.push("Missing Jira site. Pass --site, set JIRA_SITE/JIRA_BASE_URL, or configure baseUrl.");
12759
+ }
12760
+ if (!hasCredential(email)) {
12761
+ errors.push("Missing Jira email. Pass --email or set JIRA_EMAIL.");
12762
+ }
12763
+ if (!hasCredential(apiToken)) {
12764
+ errors.push("Missing Jira API token. Pass --api-token or set JIRA_API_TOKEN.");
12765
+ }
12766
+ return errors.length > 0 ? { errors } : { config: { site, email, apiToken }, errors: [] };
12767
+ }
12691
12768
  function formatHumanSummary(summary) {
12692
12769
  const counts = summary.counts;
12693
12770
  return [
@@ -12712,6 +12789,64 @@ function formatHumanAttachment(attachment) {
12712
12789
  }
12713
12790
  return lines;
12714
12791
  }
12792
+ function isAllureReportZip(attachment) {
12793
+ const filename = attachment.filename.toLowerCase();
12794
+ return filename.endsWith(".zip") && filename.includes("allure-report");
12795
+ }
12796
+ function isZip(attachment) {
12797
+ return attachment.filename.toLowerCase().endsWith(".zip");
12798
+ }
12799
+ function sortNewestFirst(attachments) {
12800
+ return [...attachments].sort((left, right) => {
12801
+ const leftTime = left.created ? Date.parse(left.created) : 0;
12802
+ const rightTime = right.created ? Date.parse(right.created) : 0;
12803
+ if (rightTime !== leftTime) {
12804
+ return rightTime - leftTime;
12805
+ }
12806
+ return right.id.localeCompare(left.id);
12807
+ });
12808
+ }
12809
+ function selectAllureAttachment(params) {
12810
+ const { attachments, attachmentId, filename } = params;
12811
+ if (attachmentId) {
12812
+ const match = attachments.find((attachment) => attachment.id === attachmentId);
12813
+ if (!match) {
12814
+ throw new Error(`Could not find Jira attachment with id ${attachmentId}.`);
12815
+ }
12816
+ return match;
12817
+ }
12818
+ if (filename) {
12819
+ const matches = sortNewestFirst(attachments.filter((attachment) => attachment.filename === filename));
12820
+ if (matches.length === 0) {
12821
+ throw new Error(`Could not find Jira attachment named ${filename}.`);
12822
+ }
12823
+ return matches[0];
12824
+ }
12825
+ const allureMatches = sortNewestFirst(attachments.filter(isAllureReportZip));
12826
+ if (allureMatches.length > 0) {
12827
+ return allureMatches[0];
12828
+ }
12829
+ const zipMatches = sortNewestFirst(attachments.filter(isZip));
12830
+ if (zipMatches.length > 0) {
12831
+ return zipMatches[0];
12832
+ }
12833
+ throw new Error("Could not find an Allure report ZIP attachment on this Jira issue.");
12834
+ }
12835
+ function buildDownloadJsonOutput(params) {
12836
+ return {
12837
+ issueKey: params.issueKey,
12838
+ dryRun: params.dryRun,
12839
+ downloaded: params.downloaded,
12840
+ attachment: {
12841
+ filename: params.attachment.filename,
12842
+ id: params.attachment.id,
12843
+ ...params.attachment.self ? { self: params.attachment.self } : {},
12844
+ ...params.attachment.content ? { content: params.attachment.content } : {},
12845
+ ...typeof params.attachment.size === "number" ? { size: params.attachment.size } : {}
12846
+ },
12847
+ outputPath: params.outputPath
12848
+ };
12849
+ }
12715
12850
  function buildJsonOutput(params) {
12716
12851
  const attachment = {
12717
12852
  filename: params.attachment.filename
@@ -12750,12 +12885,18 @@ function createAllureHandler(deps = {}) {
12750
12885
  const parseZip = deps.parseAllureReportZip ?? parseAllureReportZip;
12751
12886
  const uploadAttachment = deps.uploadIssueAttachment ?? uploadIssueAttachment;
12752
12887
  const createComment = deps.addIssueComment ?? addIssueComment;
12888
+ const listAttachments = deps.listIssueAttachments ?? listIssueAttachments;
12889
+ const downloadAttachment = deps.downloadIssueAttachment ?? downloadIssueAttachment;
12753
12890
  return async (request) => {
12754
12891
  const [subcommand, ...subArgs] = request.args;
12755
- if (subcommand !== "upload") {
12892
+ if (subcommand !== "upload" && subcommand !== "download") {
12756
12893
  return {
12757
12894
  exitCode: ExitCode.UsageError,
12758
- stderr: ["Usage: automatify testops allure upload <issueKey> <zipPath> [options]"]
12895
+ stderr: [
12896
+ "Usage:",
12897
+ " automatify testops allure upload <issueKey> <zipPath> [options]",
12898
+ " automatify testops allure download <issueKey> [options]"
12899
+ ]
12759
12900
  };
12760
12901
  }
12761
12902
  const parsed = parseArgs2(subArgs);
@@ -12763,12 +12904,102 @@ function createAllureHandler(deps = {}) {
12763
12904
  const dryRun = parsed.boolFlags.has("--dry-run");
12764
12905
  const verbose = parsed.boolFlags.has("--verbose");
12765
12906
  const addComment = !parsed.boolFlags.has("--no-comment");
12907
+ const force = parsed.boolFlags.has("--force");
12766
12908
  if (parsed.unknownFlags.length > 0) {
12767
12909
  return {
12768
12910
  exitCode: ExitCode.UsageError,
12769
12911
  stderr: [`ERROR: Unknown or invalid flags: ${parsed.unknownFlags.join(", ")}`]
12770
12912
  };
12771
12913
  }
12914
+ if (subcommand === "download") {
12915
+ const [issueKey2] = parsed.positionals;
12916
+ if (!issueKey2 || parsed.positionals.length > 1) {
12917
+ return {
12918
+ exitCode: ExitCode.UsageError,
12919
+ stderr: ["Usage: automatify testops allure download <issueKey> [options]"]
12920
+ };
12921
+ }
12922
+ const resolved2 = resolveJiraConfig(parsed, env, cwd);
12923
+ if (!resolved2.config) {
12924
+ return {
12925
+ exitCode: ExitCode.ValidationError,
12926
+ stderr: resolved2.errors.map((line) => `ERROR: ${line}`)
12927
+ };
12928
+ }
12929
+ try {
12930
+ const attachments = await listAttachments({
12931
+ ...resolved2.config,
12932
+ issueKey: issueKey2
12933
+ });
12934
+ const selected = selectAllureAttachment({
12935
+ attachments,
12936
+ attachmentId: parsed.flags["--attachment-id"],
12937
+ filename: parsed.flags["--filename"]
12938
+ });
12939
+ const outputDir = import_node_path8.default.resolve(cwd, parsed.flags["--output-dir"] ?? ".");
12940
+ const outputPath = import_node_path8.default.join(outputDir, selected.filename);
12941
+ if (dryRun) {
12942
+ if (useJson) {
12943
+ return {
12944
+ exitCode: ExitCode.Success,
12945
+ stdout: toJsonLine(buildDownloadJsonOutput({
12946
+ issueKey: issueKey2,
12947
+ dryRun: true,
12948
+ downloaded: false,
12949
+ attachment: selected,
12950
+ outputPath
12951
+ }))
12952
+ };
12953
+ }
12954
+ return {
12955
+ exitCode: ExitCode.Success,
12956
+ stdout: [
12957
+ `Selected Jira attachment ${selected.filename} (${selected.id}) from issue ${issueKey2}.`,
12958
+ ...verbose && selected.created ? [`Created: ${selected.created}`] : [],
12959
+ `Dry run: would download to ${outputPath}.`
12960
+ ]
12961
+ };
12962
+ }
12963
+ (0, import_node_fs7.mkdirSync)(outputDir, { recursive: true });
12964
+ if ((0, import_node_fs7.existsSync)(outputPath) && !force) {
12965
+ return {
12966
+ exitCode: ExitCode.ValidationError,
12967
+ stderr: [`ERROR: Output file already exists: ${outputPath}. Pass --force to overwrite.`]
12968
+ };
12969
+ }
12970
+ const downloaded = await downloadAttachment({
12971
+ ...resolved2.config,
12972
+ attachment: selected,
12973
+ outputPath
12974
+ });
12975
+ if (useJson) {
12976
+ return {
12977
+ exitCode: ExitCode.Success,
12978
+ stdout: toJsonLine(buildDownloadJsonOutput({
12979
+ issueKey: issueKey2,
12980
+ dryRun: false,
12981
+ downloaded: true,
12982
+ attachment: downloaded,
12983
+ outputPath
12984
+ }))
12985
+ };
12986
+ }
12987
+ return {
12988
+ exitCode: ExitCode.Success,
12989
+ stdout: [
12990
+ `Downloaded Allure report attachment from Jira issue ${issueKey2}.`,
12991
+ `Attachment: ${downloaded.filename}`,
12992
+ `Attachment ID: ${downloaded.id}`,
12993
+ `Saved to: ${downloaded.outputPath}`
12994
+ ]
12995
+ };
12996
+ } catch (error) {
12997
+ return {
12998
+ exitCode: ExitCode.RemoteError,
12999
+ stderr: [`ERROR: ${normalizeError(error)}`]
13000
+ };
13001
+ }
13002
+ }
12772
13003
  const [issueKey, zipPathInput] = parsed.positionals;
12773
13004
  if (!issueKey || !zipPathInput || parsed.positionals.length > 2) {
12774
13005
  return {
@@ -12776,26 +13007,13 @@ function createAllureHandler(deps = {}) {
12776
13007
  stderr: ["Usage: automatify testops allure upload <issueKey> <zipPath> [options]"]
12777
13008
  };
12778
13009
  }
12779
- const config = resolveCliConfig(pickConfigArgs2(parsed), env, cwd);
12780
- const site = normalizeSite2(parsed.flags["--site"] ?? env.JIRA_SITE ?? config.values.baseUrl);
12781
- const email = (parsed.flags["--email"] ?? config.values.jiraEmail).trim();
12782
- const apiToken = (parsed.flags["--api-token"] ?? config.values.jiraApiToken).trim();
13010
+ const resolved = resolveJiraConfig(parsed, env, cwd);
12783
13011
  const zipPath = import_node_path8.default.resolve(cwd, zipPathInput);
12784
13012
  const attachmentFilename = import_node_path8.default.basename(zipPath);
12785
- const credentialErrors = [];
12786
- if (!hasCredential(site)) {
12787
- credentialErrors.push("Missing Jira site. Pass --site, set JIRA_SITE/JIRA_BASE_URL, or configure baseUrl.");
12788
- }
12789
- if (!hasCredential(email)) {
12790
- credentialErrors.push("Missing Jira email. Pass --email or set JIRA_EMAIL.");
12791
- }
12792
- if (!hasCredential(apiToken)) {
12793
- credentialErrors.push("Missing Jira API token. Pass --api-token or set JIRA_API_TOKEN.");
12794
- }
12795
- if (credentialErrors.length > 0) {
13013
+ if (!resolved.config) {
12796
13014
  return {
12797
13015
  exitCode: ExitCode.ValidationError,
12798
- stderr: credentialErrors.map((line) => `ERROR: ${line}`)
13016
+ stderr: resolved.errors.map((line) => `ERROR: ${line}`)
12799
13017
  };
12800
13018
  }
12801
13019
  let summary;
@@ -12834,18 +13052,14 @@ function createAllureHandler(deps = {}) {
12834
13052
  }
12835
13053
  try {
12836
13054
  const attachment = await uploadAttachment({
12837
- site,
12838
- email,
12839
- apiToken,
13055
+ ...resolved.config,
12840
13056
  issueKey,
12841
13057
  filePath: zipPath
12842
13058
  });
12843
13059
  let commentAdded = false;
12844
13060
  if (addComment) {
12845
13061
  await createComment({
12846
- site,
12847
- email,
12848
- apiToken,
13062
+ ...resolved.config,
12849
13063
  issueKey,
12850
13064
  body: buildAllureEvidenceCommentAdf({
12851
13065
  counts: summary.counts,
@@ -12889,7 +13103,7 @@ function createAllureHandler(deps = {}) {
12889
13103
  }
12890
13104
 
12891
13105
  // src/bdd.ts
12892
- var import_node_fs7 = require("node:fs");
13106
+ var import_node_fs8 = require("node:fs");
12893
13107
  var import_node_path9 = __toESM(require("node:path"), 1);
12894
13108
  var import_yazl = __toESM(require_yazl(), 1);
12895
13109
 
@@ -13312,7 +13526,7 @@ function toJsonExportManifestItems(items) {
13312
13526
  async function defaultCreateZipArchive(archivePath, entries) {
13313
13527
  await new Promise((resolve, reject) => {
13314
13528
  const zip = new import_yazl.ZipFile();
13315
- const output = zip.outputStream.pipe((0, import_node_fs7.createWriteStream)(archivePath));
13529
+ const output = zip.outputStream.pipe((0, import_node_fs8.createWriteStream)(archivePath));
13316
13530
  output.on("close", () => resolve());
13317
13531
  output.on("error", reject);
13318
13532
  zip.outputStream.on("error", reject);
@@ -13342,10 +13556,10 @@ function missingProjectResponse() {
13342
13556
  function createBddHandler(deps = {}) {
13343
13557
  const cwd = deps.cwd ?? process.cwd();
13344
13558
  const env = deps.env ?? process.env;
13345
- const mkdir = deps.mkdir ?? ((targetPath, options) => (0, import_node_fs7.mkdirSync)(targetPath, options));
13346
- const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs7.readFileSync)(filePath, "utf8"));
13347
- const readDir = deps.readDir ?? ((dirPath) => (0, import_node_fs7.readdirSync)(dirPath));
13348
- const writeFile = deps.writeFile ?? ((filePath, content) => (0, import_node_fs7.writeFileSync)(filePath, content, "utf8"));
13559
+ const mkdir = deps.mkdir ?? ((targetPath, options) => (0, import_node_fs8.mkdirSync)(targetPath, options));
13560
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
13561
+ const readDir = deps.readDir ?? ((dirPath) => (0, import_node_fs8.readdirSync)(dirPath));
13562
+ const writeFile = deps.writeFile ?? ((filePath, content) => (0, import_node_fs8.writeFileSync)(filePath, content, "utf8"));
13349
13563
  const createZipArchive = deps.createZipArchive ?? defaultCreateZipArchive;
13350
13564
  return async (request, context) => {
13351
13565
  const [subcommand, ...restArgs] = request.args;
@@ -14559,7 +14773,7 @@ function createDoctorHandler(deps = {}) {
14559
14773
  }
14560
14774
 
14561
14775
  // src/ingestFeature.ts
14562
- var import_node_fs8 = require("node:fs");
14776
+ var import_node_fs9 = require("node:fs");
14563
14777
  var import_node_path10 = __toESM(require("node:path"), 1);
14564
14778
  var CONFIG_FLAGS6 = /* @__PURE__ */ new Set([
14565
14779
  "--config",
@@ -14646,8 +14860,8 @@ function normalizeError4(error) {
14646
14860
  return "Unknown ingest error.";
14647
14861
  }
14648
14862
  function createIngestFeatureHandler(deps = {}) {
14649
- const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs8.readFileSync)(filePath, "utf8"));
14650
- const readStdin = deps.readStdin ?? (() => (0, import_node_fs8.readFileSync)(0, "utf8"));
14863
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs9.readFileSync)(filePath, "utf8"));
14864
+ const readStdin = deps.readStdin ?? (() => (0, import_node_fs9.readFileSync)(0, "utf8"));
14651
14865
  const cwd = deps.cwd ?? process.cwd();
14652
14866
  const env = deps.env ?? process.env;
14653
14867
  return async (request, context) => {
@@ -14786,7 +15000,7 @@ function createIngestFeatureHandler(deps = {}) {
14786
15000
  }
14787
15001
 
14788
15002
  // src/runUpload.ts
14789
- var import_node_fs9 = require("node:fs");
15003
+ var import_node_fs10 = require("node:fs");
14790
15004
  var import_node_path11 = __toESM(require("node:path"), 1);
14791
15005
  var STEP_RESULTS = [
14792
15006
  StepResult.Passed,
@@ -14928,8 +15142,8 @@ function summarizeRunResult(result) {
14928
15142
  return lines;
14929
15143
  }
14930
15144
  function createRunUploadHandler(deps = {}) {
14931
- const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs9.readFileSync)(filePath, "utf8"));
14932
- const readStdin = deps.readStdin ?? (() => (0, import_node_fs9.readFileSync)(0, "utf8"));
15145
+ const readFile = deps.readFile ?? ((filePath) => (0, import_node_fs10.readFileSync)(filePath, "utf8"));
15146
+ const readStdin = deps.readStdin ?? (() => (0, import_node_fs10.readFileSync)(0, "utf8"));
14933
15147
  const cwd = deps.cwd ?? process.cwd();
14934
15148
  const env = deps.env ?? process.env;
14935
15149
  return async (request, context) => {
@@ -15779,8 +15993,8 @@ function createSyncHandler(deps = {}) {
15779
15993
  var COMMAND_REGISTRY = [
15780
15994
  {
15781
15995
  name: "allure",
15782
- description: "Allure evidence upload commands for Jira issues",
15783
- subcommands: ["upload"],
15996
+ description: "Allure evidence upload/download commands for Jira issues",
15997
+ subcommands: ["upload", "download"],
15784
15998
  handler: createAllureHandler()
15785
15999
  },
15786
16000
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automatify-au/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Forge-first CLI for Automatify Jira TestOps",
5
5
  "type": "module",
6
6
  "bin": {