bitrise-api-cli 0.0.3 → 0.0.6

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
@@ -1,4 +1,4 @@
1
- # Bitrise API CLI [![npm version](https://badge.fury.io/js/bitrise-api-cli.svg)](https://www.npmjs.com/package/bitrise-api-cli)
1
+ # Bitrise API CLI [![npm][npm-image]][npm-url] ![npm][npm-dl-stats]
2
2
 
3
3
  <div align="center">
4
4
  🚀 An unofficial CLI tool to interact with Bitrise API, making artifact downloads a breeze.
@@ -23,7 +23,7 @@ npx bitrise-api-cli@latest download --token <BITRISE_TOKEN> --workflow <WORKFLOW
23
23
  npx bitrise-api-cli@latest download \
24
24
  --token <BITRISE_TOKEN> \
25
25
  --workflow <WORKFLOW_NAME> \
26
- --app-slug <APP_SLUG>
26
+ --slug <APP_SLUG>
27
27
  ```
28
28
 
29
29
  ## 🔐 Configuration
@@ -40,11 +40,12 @@ npx bitrise-api-cli@latest download \
40
40
 
41
41
  ```bash
42
42
  Options:
43
- -t, --token <TOKEN> Bitrise API token
44
- -w, --workflow <NAME> Workflow name
45
- -s, --app-slug <SLUG> Bitrise app slug
46
- -d, --debug Enable debug logging
47
- -h, --help Display help information
43
+ -t, --token <TOKEN> bitrise api token (or $BITRISE_API_CLI_TOKEN)
44
+ -w, --workflow <WORKFLOW_NAME> workflow to get apk from (or $BITRISE_API_CLI_WORKFLOW)
45
+ -s, --slug <APP_SLUG> bitrise app slug (or $BITRISE_APP_SLUG) see bitrise project url to get slug
46
+ -a, --artifact <ARTIFACT_TYPE> bitrise artifact type "ios-ipa" or "android-apk"
47
+ -d, --debug output extra debugging (default: false)
48
+ -h, --help display help for command
48
49
  ```
49
50
 
50
51
  ## 💡 Examples
@@ -56,7 +57,7 @@ Options:
56
57
  npx bitrise-api-cli@latest download \
57
58
  --token abc123 \
58
59
  --workflow android-release \
59
- --app-slug a1b2c3d4e5f6
60
+ --slug a1b2c3d4e5f6
60
61
 
61
62
  # Enable debug logging
62
63
  npx bitrise-api-cli@latest download --debug \
@@ -100,7 +101,7 @@ Download the latest artifacts to test without building:
100
101
  npx bitrise-api-cli@latest download \
101
102
  --token $BITRISE_API_TOKEN \
102
103
  --workflow android-release \
103
- --app-slug $BITRISE_APP_SLUG
104
+ --slug $BITRISE_APP_SLUG
104
105
  ```
105
106
 
106
107
  ## 📝 License
@@ -117,3 +118,8 @@ This project is [MIT](LICENSE) licensed.
117
118
  <div align="center">
118
119
  <p>Found this project useful? Give it a ⭐️!</p>
119
120
  </div>
121
+
122
+
123
+ [npm-image]: https://img.shields.io/npm/v/bitrise-api-cli
124
+ [npm-url]: https://www.npmjs.com/package/bitrise-api-cli
125
+ [npm-dl-stats]: https://img.shields.io/npm/dm/bitrise-api-cli
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ app,
4
+ buildContext
5
+ } from "./chunk-SUHWPUKK.js";
6
+ import "./chunk-CF25N4TY.js";
7
+
8
+ // src/cli/bin/bash-complete.ts
9
+ import { proposeCompletions } from "@stricli/core";
10
+ var inputs = process.argv.slice(3);
11
+ if (process.env["COMP_LINE"]?.endsWith(" ")) {
12
+ inputs.push("");
13
+ }
14
+ await proposeCompletions(app, inputs, buildContext(process));
15
+ try {
16
+ for (const { completion } of await proposeCompletions(app, inputs, buildContext(process))) {
17
+ process.stdout.write(`${completion}
18
+ `);
19
+ }
20
+ } catch {
21
+ }
@@ -0,0 +1,6 @@
1
+ // src/cliOptions.types.ts
2
+ var validArtifactTypes = ["android-apk", "ios-ipa"];
3
+
4
+ export {
5
+ validArtifactTypes
6
+ };
@@ -0,0 +1,94 @@
1
+ import {
2
+ validArtifactTypes
3
+ } from "./chunk-CF25N4TY.js";
4
+
5
+ // src/cli/app.ts
6
+ import { buildApplication, buildCommand, buildRouteMap } from "@stricli/core";
7
+
8
+ // package.json
9
+ var name = "bitrise-api-cli";
10
+ var version = "0.0.6";
11
+ var description = "bitrise api CLI wrapper";
12
+
13
+ // src/cli/app.ts
14
+ var downloadCommand = buildCommand({
15
+ loader: async () => import("./impl-ESKLIOQY.js"),
16
+ parameters: {
17
+ flags: {
18
+ artifact: {
19
+ kind: "enum",
20
+ brief: 'bitrise artifact type "ios-ipa" or "android-apk"',
21
+ default: "android-apk",
22
+ values: validArtifactTypes
23
+ },
24
+ debug: {
25
+ kind: "boolean",
26
+ brief: "Number of times to say hello",
27
+ default: false
28
+ },
29
+ slug: {
30
+ kind: "parsed",
31
+ brief: "bitrise app slug (or $BITRISE_APP_SLUG) see bitrise project url to get slug",
32
+ default: process.env["BITRISE_APP_SLUG"],
33
+ parse: String,
34
+ placeholder: "APP_SLUG"
35
+ },
36
+ token: {
37
+ kind: "parsed",
38
+ brief: "bitrise api token (or $BITRISE_API_CLI_TOKEN)",
39
+ default: process.env["BITRISE_API_CLI_TOKEN"],
40
+ parse: String,
41
+ placeholder: "API_TOKEN"
42
+ },
43
+ workflow: {
44
+ kind: "parsed",
45
+ brief: "workflow to get apk from (or $BITRISE_API_CLI_WORKFLOW)",
46
+ default: process.env["BITRISE_API_CLI_WORKFLOW"],
47
+ parse: String,
48
+ placeholder: "WORKFLOW_NAME"
49
+ }
50
+ },
51
+ aliases: {
52
+ a: "artifact",
53
+ d: "debug",
54
+ s: "slug",
55
+ t: "token",
56
+ w: "workflow"
57
+ }
58
+ },
59
+ docs: {
60
+ brief: "Download bitrise artifacts. Most parameters can be set via environment variables."
61
+ }
62
+ });
63
+ var root = buildRouteMap({
64
+ routes: {
65
+ download: downloadCommand
66
+ },
67
+ docs: {
68
+ brief: description
69
+ }
70
+ });
71
+ var app = buildApplication(root, {
72
+ name,
73
+ versionInfo: {
74
+ currentVersion: version
75
+ }
76
+ });
77
+
78
+ // src/cli/context.ts
79
+ import fs from "node:fs";
80
+ import os from "node:os";
81
+ import path from "node:path";
82
+ function buildContext(process2) {
83
+ return {
84
+ process: process2,
85
+ os,
86
+ fs,
87
+ path
88
+ };
89
+ }
90
+
91
+ export {
92
+ app,
93
+ buildContext
94
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ app,
4
+ buildContext
5
+ } from "./chunk-SUHWPUKK.js";
6
+ import "./chunk-CF25N4TY.js";
7
+
8
+ // src/cli/bin/cli.ts
9
+ import { run } from "@stricli/core";
10
+ await run(app, process.argv.slice(2), buildContext(process));
@@ -1,18 +1,21 @@
1
- #!/usr/bin/env node
2
-
3
- // src/bin.ts
4
- import { Command } from "commander";
1
+ import {
2
+ validArtifactTypes
3
+ } from "./chunk-CF25N4TY.js";
5
4
 
6
5
  // src/bitrise/env.ts
7
6
  var ENV = {
7
+ debug: false,
8
8
  appSlug: "",
9
9
  token: "",
10
- workflow: ""
10
+ workflow: "",
11
+ artifactType: "android-apk"
11
12
  };
12
13
  var saveOptions = (options) => {
13
- ENV.appSlug = options?.app ?? process.env.BITRISE_APP_SLUG ?? "";
14
- ENV.token = options?.token ?? process.env.BITRISE_API_CLI_TOKEN ?? "";
15
- ENV.workflow = options?.workflow ?? process.env.BITRISE_API_CLI_WORKFLOW ?? "";
14
+ ENV.debug = options.debug;
15
+ ENV.appSlug = options.slug;
16
+ ENV.token = options.token;
17
+ ENV.workflow = options.workflow;
18
+ ENV.artifactType = options.artifact;
16
19
  };
17
20
  var isEnvValid = () => {
18
21
  if (ENV.appSlug.length < 1) {
@@ -27,6 +30,10 @@ var isEnvValid = () => {
27
30
  console.log("No workflow provided! (see --help for more information)");
28
31
  return false;
29
32
  }
33
+ if (!validArtifactTypes.includes(ENV.artifactType)) {
34
+ console.log(`Invalid artifact type "${ENV.artifactType}"! (see --help for more information)`);
35
+ return false;
36
+ }
30
37
  return true;
31
38
  };
32
39
 
@@ -1426,58 +1433,73 @@ var api = {
1426
1433
  builds: () => new BuildsApi(getApiConfig())
1427
1434
  };
1428
1435
 
1436
+ // src/helper/debugLog.ts
1437
+ var debugLog = (label, data) => console.log(`${label}: ${JSON.stringify(data, void 0, 2)}`);
1438
+
1429
1439
  // src/bitrise/fetchArtifact.ts
1430
1440
  var fetchArtifact = async ({ artifactSlug, buildSlug }) => {
1431
1441
  const { data } = await api.buildArtifact().artifactShow({ appSlug: ENV.appSlug, artifactSlug, buildSlug });
1432
1442
  if (!data) throw new Error("buildArtifact().artifactShow returned no data");
1443
+ if (ENV.debug) debugLog("artifact", data);
1433
1444
  return data;
1434
1445
  };
1435
1446
 
1436
- // src/helper/formatBytes.ts
1437
- var decimals = 0;
1438
- var formatBytes = (bytes) => {
1439
- if (bytes === 0) return "0 Bytes";
1440
- const k = 1024;
1441
- const dm = decimals || 2;
1442
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1443
- const i = Math.floor(Math.log(bytes) / Math.log(k));
1444
- const formattedSize = Number.parseFloat((bytes / k ** i).toFixed(dm));
1445
- return `${formattedSize} ${sizes[i]}`;
1446
- };
1447
-
1448
- // src/downloadLatestArtifacts.ts
1449
- import { oraPromise } from "ora";
1450
-
1451
1447
  // src/bitrise/fetchArtifactList.ts
1452
1448
  var fetchArtifactList = async (buildSlug) => {
1453
1449
  const { data } = await api.buildArtifact().artifactList({ appSlug: ENV.appSlug, buildSlug });
1454
1450
  if (!data) throw new Error("buildArtifact().artifactList returned no data");
1455
1451
  return data;
1456
1452
  };
1457
-
1458
- // src/helper/debugLog.ts
1459
- var debugLog = (label, data) => console.log(`${label}: ${JSON.stringify(data, void 0, 2)}`);
1453
+ var fetchArtifactByType = async (buildSlug) => {
1454
+ const artifactInfo = await fetchArtifactList(buildSlug);
1455
+ const artifactMetadata = artifactInfo.find((artifact) => artifact.artifactType === ENV.artifactType);
1456
+ if (!artifactMetadata || !artifactMetadata.slug)
1457
+ throw new Error(`Found no ${ENV.artifactType} in build Slug: ${buildSlug}`);
1458
+ if (ENV.debug) debugLog("artifactMetadata", artifactMetadata);
1459
+ return artifactMetadata;
1460
+ };
1460
1461
 
1461
1462
  // src/bitrise/fetchBuilds.ts
1462
1463
  var getAllBuilds = async () => {
1463
- const { data } = await api.builds().buildList({ appSlug: ENV.appSlug });
1464
+ const { data } = await api.builds().buildList({ appSlug: ENV.appSlug, status: 1 });
1464
1465
  if (!data) throw Error("no build data");
1465
1466
  return data;
1466
1467
  };
1467
- var getLatestBuild = async (options) => {
1468
+ var getLatestBuild = async () => {
1468
1469
  const builds = await getAllBuilds();
1469
1470
  const latestBuild = builds.find((build) => build.triggeredWorkflow === ENV.workflow);
1470
1471
  if (!latestBuild) throw `Found no build with the workflow: "${ENV.workflow}"`;
1471
- if (options.debug) debugLog("latestBuild", latestBuild);
1472
+ if (ENV.debug) debugLog("latestBuild", latestBuild);
1472
1473
  return latestBuild;
1473
1474
  };
1474
1475
 
1476
+ // src/helper/formatBytes.ts
1477
+ var decimals = 0;
1478
+ var formatBytes = (bytes) => {
1479
+ if (bytes === 0) return "0 Bytes";
1480
+ const k = 1024;
1481
+ const dm = decimals || 2;
1482
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1483
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1484
+ const formattedSize = Number.parseFloat((bytes / k ** i).toFixed(dm));
1485
+ return `${formattedSize} ${sizes[i]}`;
1486
+ };
1487
+
1488
+ // src/downloadLatestArtifacts.ts
1489
+ import { oraPromise } from "ora";
1490
+
1475
1491
  // src/helper/downloadFile.ts
1476
1492
  import { createWriteStream } from "node:fs";
1477
1493
  import { get } from "node:https";
1478
1494
  import { pipeline } from "node:stream/promises";
1479
1495
  import { URL } from "node:url";
1496
+
1497
+ // src/helper/formatTime.ts
1498
+ var formatTime = (timeMs) => `${(timeMs / 1e3).toFixed(1)}s`;
1499
+
1500
+ // src/helper/downloadFile.ts
1480
1501
  var downloadFile = async (fileUrl, outputLocationPath) => {
1502
+ const startTime = Date.now();
1481
1503
  const url = new URL(fileUrl);
1482
1504
  const response = await new Promise((resolve, reject) => {
1483
1505
  get(url, (res) => {
@@ -1489,46 +1511,40 @@ var downloadFile = async (fileUrl, outputLocationPath) => {
1489
1511
  }).on("error", reject);
1490
1512
  });
1491
1513
  await pipeline(response, createWriteStream(outputLocationPath));
1514
+ return { duration: formatTime(Date.now() - startTime) };
1492
1515
  };
1493
1516
 
1494
1517
  // src/downloadLatestArtifacts.ts
1495
- var targetArtifactType = "android-apk";
1496
1518
  var downloadLatestArtifacts = async (options) => {
1497
1519
  saveOptions(options);
1498
1520
  if (!isEnvValid()) return process.exit(1);
1499
- const latestBuild = await oraPromise(getLatestBuild(options), {
1521
+ const latestBuild = await oraPromise(getLatestBuild(), {
1500
1522
  text: "fetching latest build",
1501
1523
  failText: (error) => `fetching latest build failed with error: ${error}`
1502
1524
  });
1503
- if (!latestBuild.slug) {
1504
- console.log("Latest build contained no Slug");
1505
- return process.exit(1);
1506
- }
1507
- const artifactInfo = await oraPromise(fetchArtifactList(latestBuild.slug), { text: "fetching artifact list" });
1508
- const artifactMetadata = artifactInfo.find((artifact2) => artifact2.artifactType === targetArtifactType);
1509
- if (!artifactMetadata || !artifactMetadata.slug)
1510
- throw new Error(`Found no apk in build #${latestBuild.buildNumber}`);
1511
- if (options.debug) debugLog("artifactMetadata", artifactMetadata);
1525
+ if (!latestBuild.slug) throw Error("Latest build contained no Slug");
1526
+ const artifactMetadata = await oraPromise(fetchArtifactByType(latestBuild.slug), {
1527
+ text: "fetching artifact list",
1528
+ failText: (error) => `fetching artifact list failed with error: ${error}`
1529
+ });
1530
+ if (!artifactMetadata.slug || !artifactMetadata.title) throw Error("Artifact was Invalid");
1512
1531
  const artifact = await oraPromise(
1513
- fetchArtifact({
1514
- artifactSlug: artifactMetadata.slug,
1515
- buildSlug: latestBuild.slug
1516
- }),
1532
+ fetchArtifact({ artifactSlug: artifactMetadata.slug, buildSlug: latestBuild.slug }),
1517
1533
  { text: "fetching artifact metadata" }
1518
1534
  );
1519
- if (options.debug) debugLog("artifact", artifact);
1520
- if (!artifact || !artifact.expiringDownloadUrl || !artifactMetadata.title) {
1521
- console.log("Artifact is missing data");
1522
- return process.exit(1);
1523
- }
1535
+ if (!artifact.expiringDownloadUrl) throw Error("Artifact is missing expiringDownloadUrl");
1524
1536
  const fileSize = formatBytes(artifact.fileSizeBytes ?? 0);
1525
1537
  await oraPromise(downloadFile(artifact.expiringDownloadUrl, artifactMetadata.title), {
1526
- text: `downloading apk file (${fileSize})`
1538
+ text: `downloading apk file (${fileSize})`,
1539
+ successText: ({ duration }) => `downloading apk file took ${duration}`
1527
1540
  });
1528
1541
  };
1529
1542
 
1530
- // src/bin.ts
1531
- var program = new Command();
1532
- program.version("0.0.3");
1533
- program.command("download").option("-t, --token <TOKEN>", "bitrise api token (or $BITRISE_API_CLI_TOKEN)").option("-w, --workflow <WORKFLOW_NAME>", "workflow to get apk from (or $BITRISE_API_CLI_WORKFLOW)").option("-a, --app <APP_SLUG>", "bitrise app slug (or $BITRISE_APP_SLUG) see bitrise project url to get slug").option("-d, --debug", "output extra debugging", false).description("Download bitrise artifacts").action((options) => downloadLatestArtifacts(options).catch(() => process.exit(1)));
1534
- program.parse(process.argv);
1543
+ // src/cli/impl.ts
1544
+ async function impl_default(flags) {
1545
+ if (flags.debug) console.log(JSON.stringify(flags, null, 2));
1546
+ return downloadLatestArtifacts(flags);
1547
+ }
1548
+ export {
1549
+ impl_default as default
1550
+ };
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "bitrise-api-cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "bitrise api CLI wrapper",
5
5
  "module": "index",
6
6
  "type": "module",
7
7
  "bin": {
8
- "bitrise-api-cli": "./dist/bin.js"
8
+ "bitrise-api-cli": "./dist/cli.js",
9
+ "__bitrise-api-cli_bash_complete": "dist/bash-complete.js"
9
10
  },
10
- "keywords": ["bitrise", "bitriseio"],
11
+ "keywords": ["bitrise", "bitriseio", "apk", "downloader"],
11
12
  "license": "MIT",
12
- "main": "dist/bin.js",
13
+ "main": "dist/cli.js",
13
14
  "files": ["dist"],
14
15
  "scripts": {
15
16
  "build": "tsup",
16
- "build:dev": "tsup --watch",
17
+ "build:dev": "tsup --watch --clean false",
17
18
  "lint": "bunx biome check --fix",
18
19
  "lint:CI": "bunx biome check",
19
20
  "typecheck": "tsc",
@@ -22,14 +23,15 @@
22
23
  "prepublishOnly": "bun i && bun run lint:CI && tsc && bun run build"
23
24
  },
24
25
  "dependencies": {
25
- "commander": "13.1.0",
26
+ "@stricli/core": "1.1.1",
27
+ "@stricli/auto-complete": "1.1.1",
26
28
  "ora": "8.2.0"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@biomejs/biome": "1.9.4",
30
32
  "@openapitools/openapi-generator-cli": "2.16.3",
31
33
  "@types/bun": "latest",
32
- "tsup": "8.3.5",
34
+ "tsup": "8.3.6",
33
35
  "typescript": "5.7.3"
34
36
  }
35
37
  }