bitrise-api-cli 0.0.7 → 0.0.9-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bash-complete.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
// src/cli/commands/download/command.ts
|
|
6
6
|
import { buildCommand } from "@stricli/core";
|
|
7
7
|
var downloadCommand = buildCommand({
|
|
8
|
-
loader: async () => import("./impl-
|
|
8
|
+
loader: async () => import("./impl-YQ6WYRXO.js"),
|
|
9
9
|
parameters: {
|
|
10
10
|
flags: {
|
|
11
11
|
artifact: {
|
|
@@ -42,7 +42,7 @@ var downloadCommand = buildCommand({
|
|
|
42
42
|
},
|
|
43
43
|
install: {
|
|
44
44
|
kind: "boolean",
|
|
45
|
-
brief: "Install the downloaded artifact [android only]",
|
|
45
|
+
brief: "Install the downloaded apk/aab artifact [android only]",
|
|
46
46
|
default: false
|
|
47
47
|
}
|
|
48
48
|
},
|
|
@@ -65,7 +65,7 @@ import { buildApplication, buildRouteMap } from "@stricli/core";
|
|
|
65
65
|
|
|
66
66
|
// package.json
|
|
67
67
|
var name = "bitrise-api-cli";
|
|
68
|
-
var version = "0.0.
|
|
68
|
+
var version = "0.0.9-beta";
|
|
69
69
|
var description = "bitrise api CLI wrapper";
|
|
70
70
|
|
|
71
71
|
// src/cli/app.ts
|
|
@@ -85,15 +85,9 @@ var app = buildApplication(root, {
|
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
// src/cli/context.ts
|
|
88
|
-
import fs from "node:fs";
|
|
89
|
-
import os from "node:os";
|
|
90
|
-
import path from "node:path";
|
|
91
88
|
function buildContext(process2) {
|
|
92
89
|
return {
|
|
93
|
-
process: process2
|
|
94
|
-
os,
|
|
95
|
-
fs,
|
|
96
|
-
path
|
|
90
|
+
process: process2
|
|
97
91
|
};
|
|
98
92
|
}
|
|
99
93
|
|
package/dist/cli.js
CHANGED
|
@@ -2,31 +2,6 @@ import {
|
|
|
2
2
|
validArtifactTypes
|
|
3
3
|
} from "./chunk-CF25N4TY.js";
|
|
4
4
|
|
|
5
|
-
// src/device/install/android.ts
|
|
6
|
-
import { exec } from "teen_process";
|
|
7
|
-
var adbPath = `${process.env.ANDROID_HOME}/platform-tools/adb`;
|
|
8
|
-
var installApk = async (apkPath) => {
|
|
9
|
-
const { stdout, stderr, code } = await exec(adbPath, ["install", "-r", "-d", apkPath]);
|
|
10
|
-
if (code !== 0) {
|
|
11
|
-
console.log(stderr);
|
|
12
|
-
throw new Error(`Failed to install apk: ${stderr}`);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// src/device/install/run.ts
|
|
17
|
-
import { oraPromise } from "ora";
|
|
18
|
-
var installApp = async ({ file, flags }) => {
|
|
19
|
-
if (flags.artifact === "android-apk") {
|
|
20
|
-
if (!file.endsWith(".apk")) return console.log("Artifact is not an APK file");
|
|
21
|
-
await oraPromise(installApk(file), {
|
|
22
|
-
text: "installing APK",
|
|
23
|
-
failText: (error) => `installing APK failed with error: ${error}`
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
26
|
-
return console.log("Installing on iOS is not supported yet");
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
5
|
// src/bitrise/env.ts
|
|
31
6
|
var ENV = {
|
|
32
7
|
debug: false,
|
|
@@ -61,6 +36,122 @@ var isEnvValid = () => {
|
|
|
61
36
|
}
|
|
62
37
|
return true;
|
|
63
38
|
};
|
|
39
|
+
var setupEnv = (flags) => {
|
|
40
|
+
if (flags.debug) console.log(JSON.stringify(flags, null, 2));
|
|
41
|
+
saveOptions(flags);
|
|
42
|
+
return isEnvValid();
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/device/install/android.ts
|
|
46
|
+
import { exec } from "teen_process";
|
|
47
|
+
var adbPath = `${process.env.ANDROID_HOME}/platform-tools/adb`;
|
|
48
|
+
var installApk = async (apkPath) => {
|
|
49
|
+
const startTime = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
const { stdout, stderr, code } = await exec(adbPath, ["install", "-r", "-d", apkPath]);
|
|
52
|
+
if (code !== 0) throw new Error(`Failed to install apk error code: ${code}`);
|
|
53
|
+
return { duration: Date.now() - startTime };
|
|
54
|
+
} catch (e) {
|
|
55
|
+
if (e instanceof Error && "stderr" in e) throw new Error(`${e.stderr}`);
|
|
56
|
+
throw new Error("unknown Error");
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var installSplitApk = async (apkFolder) => {
|
|
60
|
+
const startTime = Date.now();
|
|
61
|
+
try {
|
|
62
|
+
const { stdout, stderr, code } = await exec(adbPath, ["install-multiple", "-r", "-d", `${apkFolder}/*`], {
|
|
63
|
+
shell: true
|
|
64
|
+
});
|
|
65
|
+
if (code !== 0) throw new Error(`Failed to install split apk error code: ${code}`);
|
|
66
|
+
return { duration: Date.now() - startTime };
|
|
67
|
+
} catch (e) {
|
|
68
|
+
if (e instanceof Error && "stderr" in e) throw new Error(`${e.stderr}`);
|
|
69
|
+
throw new Error("unknown Error");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/device/install/convertAabToApk.ts
|
|
74
|
+
import fs2 from "node:fs/promises";
|
|
75
|
+
import path2 from "node:path";
|
|
76
|
+
|
|
77
|
+
// src/helper/tempDir.ts
|
|
78
|
+
import fs from "node:fs/promises";
|
|
79
|
+
import { tmpdir } from "node:os";
|
|
80
|
+
import path from "node:path";
|
|
81
|
+
var createTempDir = async (prefix) => {
|
|
82
|
+
const tmpDir = path.join(tmpdir(), `${prefix}-${Date.now()}`);
|
|
83
|
+
await fs.mkdir(tmpDir, { recursive: true });
|
|
84
|
+
return tmpDir;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/device/install/convertAabToApk.ts
|
|
88
|
+
import { exec as exec2 } from "teen_process";
|
|
89
|
+
var convertAabToApk = async (aabPath) => {
|
|
90
|
+
const startTime = Date.now();
|
|
91
|
+
try {
|
|
92
|
+
const tempDir = await createTempDir("bitrise-api-cli");
|
|
93
|
+
const fileName = path2.basename(aabPath, ".aab");
|
|
94
|
+
const outPath = path2.join(tempDir, `${fileName}.apks`);
|
|
95
|
+
const zipPath = path2.join(tempDir, `${fileName}.zip`);
|
|
96
|
+
const { code } = await exec2("bundletool", [
|
|
97
|
+
"build-apks",
|
|
98
|
+
"--connected-device",
|
|
99
|
+
`--bundle=${fileName}.aab`,
|
|
100
|
+
`--output=${outPath}`
|
|
101
|
+
]);
|
|
102
|
+
if (code !== 0) throw new Error(`Failed to convert aab to apk: ${code}`);
|
|
103
|
+
await fs2.rename(outPath, zipPath);
|
|
104
|
+
const { code: code2 } = await exec2("unzip", ["-o", zipPath, "-d", tempDir]);
|
|
105
|
+
if (code2 !== 0) throw new Error(`Failed to unzip ${code2}`);
|
|
106
|
+
return { apkFolder: path2.join(tempDir, "./splits"), duration: Date.now() - startTime };
|
|
107
|
+
} catch (e) {
|
|
108
|
+
if (e instanceof Error && "stderr" in e) throw new Error(`${e.stderr}`);
|
|
109
|
+
throw new Error("unknown Error");
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/helper/formatTime.ts
|
|
114
|
+
var formatTime = (timeMs) => {
|
|
115
|
+
if (timeMs < 1e3) return `${timeMs}ms`;
|
|
116
|
+
return `${(timeMs / 1e3).toFixed(1)}s`;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// src/helper/typeHelper.ts
|
|
120
|
+
var isFetchError = (e) => {
|
|
121
|
+
if (typeof e !== "object" || !e) return false;
|
|
122
|
+
return "response" in e && typeof e.response === "object" && !!e.response && "status" in e.response && "statusText" in e.response;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/helper/oraHelper.ts
|
|
126
|
+
var getOraTexts = (label) => ({
|
|
127
|
+
text: label,
|
|
128
|
+
failText: (error) => {
|
|
129
|
+
if (isFetchError(error))
|
|
130
|
+
return `${label} failed with HTTP Error ${error.response.status} ${error.response.statusText}`;
|
|
131
|
+
return `${label} failed with error: ${error.message}`;
|
|
132
|
+
},
|
|
133
|
+
successText: (data) => {
|
|
134
|
+
if (data && typeof data === "object" && "duration" in data && typeof data.duration === "number") {
|
|
135
|
+
return `${label} [took ${formatTime(data.duration)}]`;
|
|
136
|
+
}
|
|
137
|
+
return label;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// src/device/install/run.ts
|
|
142
|
+
import { oraPromise } from "ora";
|
|
143
|
+
var installApp = async ({ file, flags }) => {
|
|
144
|
+
if (flags.artifact === "android-apk" && file.endsWith(".aab")) {
|
|
145
|
+
const { apkFolder } = await oraPromise(convertAabToApk(file), getOraTexts("Convert AAB to Split APK"));
|
|
146
|
+
await oraPromise(installSplitApk(apkFolder), getOraTexts("installing Split APK"));
|
|
147
|
+
} else if (flags.artifact === "android-apk" && file.endsWith(".apk")) {
|
|
148
|
+
await oraPromise(installApk(file), getOraTexts("installing APK"));
|
|
149
|
+
} else if (flags.artifact === "android-apk") {
|
|
150
|
+
throw Error("Artifact is not an APK or AAB file");
|
|
151
|
+
} else {
|
|
152
|
+
return console.log("Installing on iOS is not supported yet");
|
|
153
|
+
}
|
|
154
|
+
};
|
|
64
155
|
|
|
65
156
|
// src/generated_api/runtime.ts
|
|
66
157
|
var BASE_PATH = "https://api.bitrise.io/v0.1".replace(/\/+$/, "");
|
|
@@ -737,6 +828,7 @@ function V0BuildTriggerParamsBuildParamsToJSONTyped(value, ignoreDiscriminator =
|
|
|
737
828
|
"environments": value["environments"] == null ? void 0 : value["environments"].map(V0BuildParamsEnvironmentToJSON),
|
|
738
829
|
"head_repository_url": value["headRepositoryUrl"],
|
|
739
830
|
"pipeline_id": value["pipelineId"],
|
|
831
|
+
"priority": value["priority"],
|
|
740
832
|
"pull_request_author": value["pullRequestAuthor"],
|
|
741
833
|
"pull_request_head_branch": value["pullRequestHeadBranch"],
|
|
742
834
|
"pull_request_id": value["pullRequestId"],
|
|
@@ -1051,6 +1143,12 @@ var BuildsApi = class extends BaseAPI {
|
|
|
1051
1143
|
'Required parameter "before" was null or undefined when calling archivedBuildsList().'
|
|
1052
1144
|
);
|
|
1053
1145
|
}
|
|
1146
|
+
if (requestParameters["limit"] == null) {
|
|
1147
|
+
throw new RequiredError(
|
|
1148
|
+
"limit",
|
|
1149
|
+
'Required parameter "limit" was null or undefined when calling archivedBuildsList().'
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1054
1152
|
const queryParameters = {};
|
|
1055
1153
|
if (requestParameters["after"] != null) {
|
|
1056
1154
|
queryParameters["after"] = requestParameters["after"];
|
|
@@ -1058,6 +1156,9 @@ var BuildsApi = class extends BaseAPI {
|
|
|
1058
1156
|
if (requestParameters["before"] != null) {
|
|
1059
1157
|
queryParameters["before"] = requestParameters["before"];
|
|
1060
1158
|
}
|
|
1159
|
+
if (requestParameters["limit"] != null) {
|
|
1160
|
+
queryParameters["limit"] = requestParameters["limit"];
|
|
1161
|
+
}
|
|
1061
1162
|
const headerParameters = {};
|
|
1062
1163
|
if (this.configuration && this.configuration.apiKey) {
|
|
1063
1164
|
headerParameters["Bitrise-Addon-Auth-Token"] = await this.configuration.apiKey("Bitrise-Addon-Auth-Token");
|
|
@@ -1461,12 +1562,20 @@ var api = {
|
|
|
1461
1562
|
// src/helper/debugLog.ts
|
|
1462
1563
|
var debugLog = (label, data) => console.log(`${label}: ${JSON.stringify(data, void 0, 2)}`);
|
|
1463
1564
|
|
|
1565
|
+
// src/helper/ensureMandatoryFields.ts
|
|
1566
|
+
var ensureMandatoryFields = (input, mandatory) => {
|
|
1567
|
+
for (const field of mandatory) {
|
|
1568
|
+
if (!input[field]) throw new Error(`Missing mandatory field: ${String(field)}`);
|
|
1569
|
+
}
|
|
1570
|
+
return input;
|
|
1571
|
+
};
|
|
1572
|
+
|
|
1464
1573
|
// src/bitrise/fetchArtifact.ts
|
|
1465
1574
|
var fetchArtifact = async ({ artifactSlug, buildSlug }) => {
|
|
1466
1575
|
const { data } = await api.buildArtifact().artifactShow({ appSlug: ENV.appSlug, artifactSlug, buildSlug });
|
|
1467
1576
|
if (!data) throw new Error("buildArtifact().artifactShow returned no data");
|
|
1468
1577
|
if (ENV.debug) debugLog("artifact", data);
|
|
1469
|
-
return data;
|
|
1578
|
+
return ensureMandatoryFields(data, ["expiringDownloadUrl"]);
|
|
1470
1579
|
};
|
|
1471
1580
|
|
|
1472
1581
|
// src/bitrise/fetchArtifactList.ts
|
|
@@ -1478,10 +1587,9 @@ var fetchArtifactList = async (buildSlug) => {
|
|
|
1478
1587
|
var fetchArtifactByType = async (buildSlug) => {
|
|
1479
1588
|
const artifactInfo = await fetchArtifactList(buildSlug);
|
|
1480
1589
|
const artifactMetadata = artifactInfo.find((artifact) => artifact.artifactType === ENV.artifactType);
|
|
1481
|
-
if (!artifactMetadata || !artifactMetadata.slug)
|
|
1482
|
-
throw new Error(`Found no ${ENV.artifactType} in build Slug: ${buildSlug}`);
|
|
1483
1590
|
if (ENV.debug) debugLog("artifactMetadata", artifactMetadata);
|
|
1484
|
-
|
|
1591
|
+
if (!artifactMetadata) throw new Error(`Found no ${ENV.artifactType} in build Slug: ${buildSlug}`);
|
|
1592
|
+
return ensureMandatoryFields(artifactMetadata, ["slug", "title"]);
|
|
1485
1593
|
};
|
|
1486
1594
|
|
|
1487
1595
|
// src/bitrise/fetchBuilds.ts
|
|
@@ -1495,7 +1603,7 @@ var getLatestBuild = async () => {
|
|
|
1495
1603
|
const latestBuild = builds.find((build) => build.triggeredWorkflow === ENV.workflow);
|
|
1496
1604
|
if (!latestBuild) throw `Found no build with the workflow: "${ENV.workflow}"`;
|
|
1497
1605
|
if (ENV.debug) debugLog("latestBuild", latestBuild);
|
|
1498
|
-
return latestBuild;
|
|
1606
|
+
return ensureMandatoryFields(latestBuild, ["slug"]);
|
|
1499
1607
|
};
|
|
1500
1608
|
|
|
1501
1609
|
// src/helper/formatBytes.ts
|
|
@@ -1518,11 +1626,6 @@ import { createWriteStream } from "node:fs";
|
|
|
1518
1626
|
import { get } from "node:https";
|
|
1519
1627
|
import { pipeline } from "node:stream/promises";
|
|
1520
1628
|
import { URL } from "node:url";
|
|
1521
|
-
|
|
1522
|
-
// src/helper/formatTime.ts
|
|
1523
|
-
var formatTime = (timeMs) => `${(timeMs / 1e3).toFixed(1)}s`;
|
|
1524
|
-
|
|
1525
|
-
// src/helper/downloadFile.ts
|
|
1526
1629
|
var downloadFile = async (fileUrl, outputLocationPath) => {
|
|
1527
1630
|
const startTime = Date.now();
|
|
1528
1631
|
const url = new URL(fileUrl);
|
|
@@ -1536,42 +1639,34 @@ var downloadFile = async (fileUrl, outputLocationPath) => {
|
|
|
1536
1639
|
}).on("error", reject);
|
|
1537
1640
|
});
|
|
1538
1641
|
await pipeline(response, createWriteStream(outputLocationPath));
|
|
1539
|
-
return { file: outputLocationPath, duration:
|
|
1642
|
+
return { file: outputLocationPath, duration: Date.now() - startTime };
|
|
1540
1643
|
};
|
|
1541
1644
|
|
|
1542
1645
|
// src/downloadLatestArtifacts.ts
|
|
1543
1646
|
var downloadLatestArtifacts = async (options) => {
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
});
|
|
1550
|
-
if (!latestBuild.slug) throw Error("Latest build contained no Slug");
|
|
1551
|
-
const artifactMetadata = await oraPromise2(fetchArtifactByType(latestBuild.slug), {
|
|
1552
|
-
text: "fetching artifact list",
|
|
1553
|
-
failText: (error) => `fetching artifact list failed with error: ${error}`
|
|
1554
|
-
});
|
|
1555
|
-
if (!artifactMetadata.slug || !artifactMetadata.title) throw Error("Artifact was Invalid");
|
|
1647
|
+
const latestBuild = await oraPromise2(getLatestBuild(), getOraTexts("fetching latest build"));
|
|
1648
|
+
const artifactMetadata = await oraPromise2(
|
|
1649
|
+
fetchArtifactByType(latestBuild.slug),
|
|
1650
|
+
getOraTexts("fetching artifact list")
|
|
1651
|
+
);
|
|
1556
1652
|
const artifact = await oraPromise2(
|
|
1557
1653
|
fetchArtifact({ artifactSlug: artifactMetadata.slug, buildSlug: latestBuild.slug }),
|
|
1558
|
-
|
|
1654
|
+
getOraTexts("fetching artifact metadata")
|
|
1559
1655
|
);
|
|
1560
|
-
if (!artifact.expiringDownloadUrl) throw Error("Artifact is missing expiringDownloadUrl");
|
|
1561
|
-
const fileSize = formatBytes(artifact.fileSizeBytes ?? 0);
|
|
1562
1656
|
const { file } = await oraPromise2(downloadFile(artifact.expiringDownloadUrl, artifactMetadata.title), {
|
|
1563
|
-
|
|
1564
|
-
|
|
1657
|
+
...getOraTexts("downloading apk file"),
|
|
1658
|
+
text: `downloading apk file [${formatBytes(artifact.fileSizeBytes ?? 0)}]`
|
|
1565
1659
|
});
|
|
1566
1660
|
return file;
|
|
1567
1661
|
};
|
|
1568
1662
|
|
|
1569
1663
|
// src/cli/commands/download/impl.ts
|
|
1570
1664
|
async function impl_default(flags) {
|
|
1571
|
-
if (flags
|
|
1665
|
+
if (!setupEnv(flags)) return process.exit(1);
|
|
1572
1666
|
const file = await downloadLatestArtifacts(flags);
|
|
1573
1667
|
if (flags.install) {
|
|
1574
|
-
await installApp({ file, flags })
|
|
1668
|
+
await installApp({ file, flags }).catch(() => {
|
|
1669
|
+
});
|
|
1575
1670
|
}
|
|
1576
1671
|
}
|
|
1577
1672
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bitrise-api-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9-beta",
|
|
4
4
|
"description": "bitrise api CLI wrapper",
|
|
5
5
|
"module": "index",
|
|
6
6
|
"type": "module",
|
|
@@ -23,17 +23,16 @@
|
|
|
23
23
|
"prepublishOnly": "bun i && bun run lint:CI && tsc && bun run build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@stricli/auto-complete": "1.1.1",
|
|
27
26
|
"@stricli/core": "1.1.1",
|
|
28
27
|
"ora": "8.2.0",
|
|
29
|
-
"teen_process": "2.
|
|
28
|
+
"teen_process": "2.3.1"
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
31
|
"@biomejs/biome": "1.9.4",
|
|
33
|
-
"@openapitools/openapi-generator-cli": "2.
|
|
32
|
+
"@openapitools/openapi-generator-cli": "2.18.4",
|
|
34
33
|
"@types/bun": "latest",
|
|
35
34
|
"@types/teen_process": "^2.0.4",
|
|
36
35
|
"tsup": "8.4.0",
|
|
37
|
-
"typescript": "5.
|
|
36
|
+
"typescript": "5.8.2"
|
|
38
37
|
}
|
|
39
38
|
}
|