catalyst-core 1.1.0 → 1.2.0-canary.2
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/bin/catalyst.js +54 -6
- package/changelog.md +27 -1
- package/dist/errors/registry.js +306 -18
- package/dist/errors-index.json +273 -70
- package/dist/native/androidProject/app/build.gradle.kts +53 -79
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +1 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CatalystConstants.kt +3 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +32 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +5 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ConfigMappingTest.kt +25 -0
- package/dist/native/androidSetup.js +76 -170
- package/dist/native/androidToolchain.js +642 -0
- package/dist/native/appIcon.js +100 -0
- package/dist/native/buildAndroid/assets.js +29 -5
- package/dist/native/buildAndroid/build.js +110 -223
- package/dist/native/buildAndroid/config.js +57 -65
- package/dist/native/buildAndroid/devices.js +176 -0
- package/dist/native/buildAndroid/index.js +271 -46
- package/dist/native/buildAndroid/output.js +43 -0
- package/dist/native/buildAndroid/signing.js +456 -0
- package/dist/native/buildAppAndroid.js +27 -7
- package/dist/native/buildAppIos.js +139 -20
- package/dist/native/buildIos/assets.js +76 -4
- package/dist/native/buildIos/build.js +31 -181
- package/dist/native/buildIos/config.js +126 -11
- package/dist/native/buildIos/index.js +354 -34
- package/dist/native/buildIos/localhostCert.js +87 -0
- package/dist/native/buildIos/output.js +28 -0
- package/dist/native/buildIos/signing.js +596 -0
- package/dist/native/credentials.js +309 -0
- package/dist/native/exportCredentials.js +51 -0
- package/dist/native/iosToolchain.js +583 -0
- package/dist/native/iosnativeWebView/Configurations/Shared.xcconfig +1 -3
- package/dist/native/iosnativeWebView/iosnativeWebView/Info-Release.plist +2 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/PrivacyInfo.xcprivacy +40 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebView.entitlements +0 -2
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +4 -4
- package/dist/native/localState.js +148 -0
- package/dist/native/nativeConfig.js +621 -0
- package/dist/native/releaseOutput.js +53 -0
- package/dist/native/renameAndroidProject.js +154 -369
- package/dist/native/setupEmulatorIos.js +58 -275
- package/dist/native/setupServer.js +520 -124
- package/dist/native/utils.js +418 -115
- package/dist/vite/resolveDevServerConfig.js +21 -0
- package/mcp_v2/knowledge-base.json +13 -11
- package/mcp_v2/test/config.test.ts +40 -0
- package/mcp_v2/tools/build.js +80 -104
- package/mcp_v2/tools/config.js +181 -174
- package/package.json +1 -1
- package/test/cli/nativeFlags.test.ts +97 -0
- package/test/native/androidDevices.test.ts +230 -0
- package/test/native/androidElfAlignment.test.ts +148 -0
- package/test/native/androidSigning.test.ts +646 -0
- package/test/native/androidToolchain.test.ts +766 -0
- package/test/native/appIcon.test.ts +124 -0
- package/test/native/credentials.test.ts +241 -0
- package/test/native/interaction.test.ts +179 -0
- package/test/native/iosConfigPhase.test.ts +611 -0
- package/test/native/iosSigning.test.ts +1060 -0
- package/test/native/iosToolchain.test.ts +821 -0
- package/test/native/localState.test.ts +80 -0
- package/test/native/nativeConfig.test.ts +602 -0
- package/test/native/setupServer.test.ts +529 -0
- package/test/native/utils.test.ts +102 -127
- package/test/vite/resolveDevServerConfig.test.js +25 -0
- package/dist/native/androidProject/keystore/Untitled +0 -0
- package/dist/native/androidProject/keystore/release-key.jks +0 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/localhost.p12 +0 -0
|
@@ -5,9 +5,15 @@ const {
|
|
|
5
5
|
displayPath
|
|
6
6
|
} = require("../../cli/theme.js");
|
|
7
7
|
const fs = require("fs");
|
|
8
|
+
const {
|
|
9
|
+
execFileSync
|
|
10
|
+
} = require("child_process");
|
|
8
11
|
const {
|
|
9
12
|
runCommand,
|
|
10
|
-
|
|
13
|
+
runFile,
|
|
14
|
+
runInteractiveCommand,
|
|
15
|
+
isInteractive,
|
|
16
|
+
select
|
|
11
17
|
} = require("../utils.js");
|
|
12
18
|
const {
|
|
13
19
|
buildFailure
|
|
@@ -23,18 +29,74 @@ const {
|
|
|
23
29
|
const createConfigPhase = require("./config.js");
|
|
24
30
|
const createAssetsPhase = require("./assets.js");
|
|
25
31
|
const createBuildPhase = require("./build.js");
|
|
32
|
+
const {
|
|
33
|
+
resolveAndroidSigning,
|
|
34
|
+
exportUploadCertificate,
|
|
35
|
+
legacyKeystorePath
|
|
36
|
+
} = require("./signing.js");
|
|
37
|
+
const {
|
|
38
|
+
parseAdbDevices,
|
|
39
|
+
chooseAndroidTarget,
|
|
40
|
+
reachDevServer
|
|
41
|
+
} = require("./devices.js");
|
|
42
|
+
const {
|
|
43
|
+
releaseOutputDir,
|
|
44
|
+
releaseArtifactPaths
|
|
45
|
+
} = require("./output.js");
|
|
46
|
+
const {
|
|
47
|
+
DEFAULT_VERSION_NAME,
|
|
48
|
+
assertReleaseFolderFree
|
|
49
|
+
} = require("../releaseOutput.js");
|
|
50
|
+
const {
|
|
51
|
+
applyJavaHome,
|
|
52
|
+
ensureAndroidSdk,
|
|
53
|
+
ensureJava,
|
|
54
|
+
resolveSdkPath
|
|
55
|
+
} = require("../androidToolchain.js");
|
|
56
|
+
const {
|
|
57
|
+
getLastTarget,
|
|
58
|
+
saveLastTarget
|
|
59
|
+
} = require("../localState.js");
|
|
60
|
+
const {
|
|
61
|
+
ensureDevServer,
|
|
62
|
+
migrateLanAddresses,
|
|
63
|
+
devServerPorts,
|
|
64
|
+
readHmrPort
|
|
65
|
+
} = require("../setupServer.js");
|
|
26
66
|
const catalystCorePath = path.dirname(require.resolve("catalyst-core/package.json"));
|
|
27
67
|
const pwd = path.join(catalystCorePath, "dist/native");
|
|
28
68
|
const ANDROID_PACKAGE = "io.yourname.androidproject";
|
|
29
69
|
const steps = {
|
|
70
|
+
server: "Start dev server",
|
|
30
71
|
config: "Initialize configuration",
|
|
31
|
-
tools: "
|
|
32
|
-
|
|
72
|
+
tools: "Check Java and the Android SDK",
|
|
73
|
+
signing: "Resolve upload key",
|
|
74
|
+
emulator: "Prepare the device",
|
|
33
75
|
copyAssets: "Copy build assets",
|
|
34
76
|
build: "Build and install application",
|
|
35
77
|
aab: "Build signed AAB"
|
|
36
78
|
};
|
|
37
|
-
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {object} config - { WEBVIEW_CONFIG, BUILD_OUTPUT_PATH } from config.json
|
|
82
|
+
* @param {object} [options] - parseNativeArgs()
|
|
83
|
+
* @param {boolean} [options.release] - `--release`: build the signed AAB whatever android.buildType says
|
|
84
|
+
* @param {string} [options.url] - `--url`: the release's production URL, over WEBVIEW_CONFIG.url
|
|
85
|
+
* @param {boolean} [options.device] - `--device`: run on the connected phone, not the emulator
|
|
86
|
+
* @param {boolean} [options.yes] - `--yes`: allow JDK/SDK/emulator installs without a terminal
|
|
87
|
+
* @param {boolean} [options.acceptLicenses] - `--accept-licenses`
|
|
88
|
+
*/
|
|
89
|
+
function createAndroidBuild(config, {
|
|
90
|
+
release: releaseFlag = false,
|
|
91
|
+
url,
|
|
92
|
+
device: wantDevice = false,
|
|
93
|
+
yes = false,
|
|
94
|
+
acceptLicenses = false
|
|
95
|
+
} = {}) {
|
|
96
|
+
const flags = {
|
|
97
|
+
yes,
|
|
98
|
+
acceptLicenses
|
|
99
|
+
};
|
|
38
100
|
const {
|
|
39
101
|
WEBVIEW_CONFIG,
|
|
40
102
|
BUILD_OUTPUT_PATH
|
|
@@ -53,6 +115,7 @@ function createAndroidBuild(config) {
|
|
|
53
115
|
progress,
|
|
54
116
|
ANDROID_PACKAGE,
|
|
55
117
|
runCommand,
|
|
118
|
+
runFile,
|
|
56
119
|
runInteractiveCommand
|
|
57
120
|
};
|
|
58
121
|
const {
|
|
@@ -69,12 +132,9 @@ function createAndroidBuild(config) {
|
|
|
69
132
|
processNotifications
|
|
70
133
|
} = createAssetsPhase(ctx);
|
|
71
134
|
const {
|
|
72
|
-
detectPhysicalDevice,
|
|
73
|
-
testPhysicalDeviceInstallation,
|
|
74
135
|
handleEmulatorSetup,
|
|
75
136
|
buildApp,
|
|
76
137
|
launchApp,
|
|
77
|
-
moveApkToOutputPath,
|
|
78
138
|
buildSignedAAB
|
|
79
139
|
} = createBuildPhase(ctx);
|
|
80
140
|
function syncAIPackageIfEnabled(wvConfig, progress) {
|
|
@@ -106,55 +166,178 @@ function createAndroidBuild(config) {
|
|
|
106
166
|
entry.isDirectory() ? copyDirSync(s, d) : fs.copyFileSync(s, d);
|
|
107
167
|
}
|
|
108
168
|
}
|
|
169
|
+
|
|
170
|
+
/** adb on one SDK, with a bound: a wedged adb server never answers. */
|
|
171
|
+
function adbRunner(ADB_PATH) {
|
|
172
|
+
return args => execFileSync(ADB_PATH, args, {
|
|
173
|
+
encoding: "utf8",
|
|
174
|
+
timeout: 15000,
|
|
175
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function listDevices(ADB_PATH) {
|
|
179
|
+
if (!fs.existsSync(ADB_PATH)) return [];
|
|
180
|
+
try {
|
|
181
|
+
return parseAdbDevices(adbRunner(ADB_PATH)(["devices", "-l"]));
|
|
182
|
+
} catch (error) {
|
|
183
|
+
progress.log(`adb devices failed: ${error.message}`, "warning");
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
109
187
|
async function buildAndroidApp() {
|
|
110
188
|
let androidConfig = null;
|
|
111
189
|
let targetDevice = null;
|
|
190
|
+
let resolved = null;
|
|
191
|
+
let signing = null;
|
|
192
|
+
let artifactPath = null;
|
|
193
|
+
let certificatePath = null;
|
|
112
194
|
try {
|
|
195
|
+
const log = (message, type) => progress.log(message, type);
|
|
196
|
+
const appRoot = process.cwd();
|
|
197
|
+
// Older setups saved this machine's LAN address in config.json.
|
|
198
|
+
// Put localhost back once, before the config is read (never for
|
|
199
|
+
// a release or in CI).
|
|
200
|
+
migrateLanAddresses({
|
|
201
|
+
cwd: appRoot,
|
|
202
|
+
release: releaseFlag,
|
|
203
|
+
platform: "android",
|
|
204
|
+
log
|
|
205
|
+
});
|
|
113
206
|
progress.start("config");
|
|
207
|
+
resolved = await initializeConfig({
|
|
208
|
+
release: releaseFlag,
|
|
209
|
+
url
|
|
210
|
+
});
|
|
114
211
|
const {
|
|
115
212
|
WEBVIEW_CONFIG: wvConfig,
|
|
116
|
-
|
|
117
|
-
|
|
213
|
+
version,
|
|
214
|
+
applicationId
|
|
215
|
+
} = resolved;
|
|
118
216
|
androidConfig = wvConfig.android;
|
|
119
|
-
const
|
|
217
|
+
const release = resolved.release;
|
|
120
218
|
const buildOptimisation = !!androidConfig.buildOptimisation || false;
|
|
219
|
+
progress.log(`Version ${version.versionName || DEFAULT_VERSION_NAME} (${version.buildNumber}), ${applicationId}`, "info");
|
|
220
|
+
// Before any tooling runs: a second release in the same minute
|
|
221
|
+
// would overwrite the first one's bundle.
|
|
222
|
+
if (release) assertReleaseFolderFree(releaseOutputDir({
|
|
223
|
+
appRoot,
|
|
224
|
+
androidConfig,
|
|
225
|
+
version
|
|
226
|
+
}), [".aab"]);
|
|
121
227
|
progress.complete("config");
|
|
228
|
+
|
|
229
|
+
// One-command dev: a debug build starts the dev server when
|
|
230
|
+
// nothing answers on its port, and waits until it does.
|
|
231
|
+
if (resolved.usesDevServer) {
|
|
232
|
+
progress.start("server");
|
|
233
|
+
await ensureDevServer({
|
|
234
|
+
cwd: appRoot,
|
|
235
|
+
log
|
|
236
|
+
});
|
|
237
|
+
progress.complete("server");
|
|
238
|
+
}
|
|
122
239
|
progress.start("tools");
|
|
240
|
+
// Gradle and keytool get JDK 17 to 23 through this process's
|
|
241
|
+
// environment; no shell profile is involved. Missing pieces are
|
|
242
|
+
// installed after a yes (or --yes); the SDK path is read, never written.
|
|
243
|
+
const java = await ensureJava({
|
|
244
|
+
flags,
|
|
245
|
+
log
|
|
246
|
+
});
|
|
247
|
+
applyJavaHome(java);
|
|
248
|
+
progress.log(`Java ${java.version} from ${java.source}`, "info");
|
|
249
|
+
androidConfig.sdkPath = resolveSdkPath(androidConfig);
|
|
250
|
+
const adbPath = path.join(androidConfig.sdkPath, "platform-tools", "adb");
|
|
251
|
+
|
|
252
|
+
// Where a debug build runs: the emulator unless --device, or a
|
|
253
|
+
// person here picks a connected phone.
|
|
254
|
+
const last = getLastTarget("android", {
|
|
255
|
+
cwd: appRoot
|
|
256
|
+
});
|
|
257
|
+
let target = null;
|
|
258
|
+
const pickTarget = async () => chooseAndroidTarget({
|
|
259
|
+
wantDevice,
|
|
260
|
+
devices: listDevices(adbPath),
|
|
261
|
+
last,
|
|
262
|
+
isTTY: isInteractive(),
|
|
263
|
+
select,
|
|
264
|
+
emulatorHint: androidConfig.emulatorName || (last?.target === "emulator" ? last.avd : undefined)
|
|
265
|
+
});
|
|
266
|
+
// Without --device the choice comes first, so a picked phone
|
|
267
|
+
// skips the emulator install. With it, adb may need installing first.
|
|
268
|
+
if (!release && !wantDevice) target = await pickTarget();
|
|
269
|
+
const needEmulator = !release && !wantDevice && target?.target === "emulator";
|
|
270
|
+
const sdk = await ensureAndroidSdk({
|
|
271
|
+
sdkPath: androidConfig.sdkPath,
|
|
272
|
+
emulatorName: androidConfig.emulatorName,
|
|
273
|
+
preferredAvd: last?.target === "emulator" ? last.avd : undefined,
|
|
274
|
+
needEmulator,
|
|
275
|
+
flags,
|
|
276
|
+
log
|
|
277
|
+
});
|
|
278
|
+
if (sdk.installed.length) progress.log(`Installed ${sdk.installed.join(", ")}`, "success");
|
|
279
|
+
if (sdk.createdAvd) progress.log(`Created the "${sdk.emulatorName}" emulator`, "success");
|
|
280
|
+
if (sdk.emulatorName) androidConfig.emulatorName = sdk.emulatorName;
|
|
123
281
|
const {
|
|
124
282
|
ADB_PATH,
|
|
125
283
|
EMULATOR_PATH
|
|
126
|
-
} = validateAndroidTools(androidConfig
|
|
284
|
+
} = validateAndroidTools(androidConfig, {
|
|
285
|
+
needEmulator
|
|
286
|
+
});
|
|
287
|
+
if (!release && wantDevice) target = await pickTarget();
|
|
127
288
|
progress.complete("tools");
|
|
128
|
-
if (
|
|
289
|
+
if (release) {
|
|
290
|
+
progress.start("signing");
|
|
291
|
+
signing = await resolveAndroidSigning({
|
|
292
|
+
appRoot,
|
|
293
|
+
androidConfig,
|
|
294
|
+
isTTY: isInteractive(),
|
|
295
|
+
log,
|
|
296
|
+
// Named from the config as written: appId and appName
|
|
297
|
+
// overwrite packageName and android.appName in androidConfig.
|
|
298
|
+
legacyKeystorePath: legacyKeystorePath(resolved.config?.WEBVIEW_CONFIG?.android, {
|
|
299
|
+
cwd: appRoot
|
|
300
|
+
}),
|
|
301
|
+
commonName: androidConfig.appName
|
|
302
|
+
});
|
|
303
|
+
progress.log(`Upload key: ${signing.source} (alias ${signing.keyAlias})`, "info");
|
|
304
|
+
progress.complete("signing");
|
|
305
|
+
} else {
|
|
129
306
|
progress.start("emulator");
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
targetDevice = await handleEmulatorSetup(ADB_PATH, EMULATOR_PATH, androidConfig);
|
|
144
|
-
}
|
|
307
|
+
if (target.target === "device") {
|
|
308
|
+
targetDevice = {
|
|
309
|
+
type: "physical",
|
|
310
|
+
id: target.serial,
|
|
311
|
+
model: target.model || target.serial
|
|
312
|
+
};
|
|
313
|
+
progress.log(`Using the connected phone ${targetDevice.model}`, "success");
|
|
314
|
+
saveLastTarget("android", {
|
|
315
|
+
target: "device",
|
|
316
|
+
serial: target.serial
|
|
317
|
+
}, {
|
|
318
|
+
cwd: appRoot
|
|
319
|
+
});
|
|
145
320
|
} else {
|
|
146
|
-
|
|
321
|
+
const emulator = await handleEmulatorSetup(ADB_PATH, EMULATOR_PATH, androidConfig);
|
|
322
|
+
targetDevice = {
|
|
323
|
+
...emulator,
|
|
324
|
+
id: emulator.serial
|
|
325
|
+
};
|
|
326
|
+
saveLastTarget("android", {
|
|
327
|
+
target: "emulator",
|
|
328
|
+
avd: emulator.name
|
|
329
|
+
}, {
|
|
330
|
+
cwd: appRoot
|
|
331
|
+
});
|
|
147
332
|
}
|
|
148
333
|
progress.complete("emulator");
|
|
149
|
-
} else {
|
|
150
|
-
progress.log("Skipping device setup for release build", "info");
|
|
151
334
|
}
|
|
152
335
|
progress.start("copyAssets");
|
|
153
336
|
await copyBuildAssets(androidConfig, buildOptimisation);
|
|
154
337
|
await copySplashscreenAssets();
|
|
155
338
|
await copyOfflinePage();
|
|
156
339
|
await copySplashHtml();
|
|
157
|
-
await copyIconAssets();
|
|
340
|
+
await copyIconAssets(androidConfig);
|
|
158
341
|
await configureAppName(androidConfig);
|
|
159
342
|
const pluginConfig = resolvePluginConfig(wvConfig);
|
|
160
343
|
composeAndroidPlugins({
|
|
@@ -167,45 +350,81 @@ function createAndroidBuild(config) {
|
|
|
167
350
|
progress.log(`Build optimization: ${buildOptimisation ? "Enabled" : "Disabled"}`, "info");
|
|
168
351
|
syncAIPackageIfEnabled(wvConfig, progress);
|
|
169
352
|
progress.complete("copyAssets");
|
|
170
|
-
|
|
171
|
-
|
|
353
|
+
const gradleOptions = {
|
|
354
|
+
configPath: resolved.resolvedConfigPath,
|
|
355
|
+
applicationId,
|
|
356
|
+
version
|
|
357
|
+
};
|
|
358
|
+
if (release) {
|
|
172
359
|
progress.start("aab");
|
|
173
|
-
|
|
360
|
+
const outputDir = releaseOutputDir({
|
|
361
|
+
appRoot,
|
|
362
|
+
androidConfig,
|
|
363
|
+
version
|
|
364
|
+
});
|
|
365
|
+
const names = releaseArtifactPaths(outputDir, androidConfig.newProjectName || androidConfig.appName || "app");
|
|
366
|
+
const aab = await buildSignedAAB(androidConfig, {
|
|
367
|
+
...gradleOptions,
|
|
368
|
+
signing,
|
|
369
|
+
buildOptimisation,
|
|
370
|
+
finalAabPath: names.aab
|
|
371
|
+
});
|
|
372
|
+
artifactPath = aab?.finalAabPath || names.aab;
|
|
373
|
+
// The upload certificate beside the bundle (#508): Play asks
|
|
374
|
+
// for it when an upload key is registered or reset.
|
|
375
|
+
certificatePath = exportUploadCertificate(signing, names.certificate);
|
|
174
376
|
progress.complete("aab");
|
|
175
|
-
movedApkPath = await moveApkToOutputPath(buildType, bop, androidConfig.appName);
|
|
176
377
|
} else {
|
|
177
378
|
progress.start("build");
|
|
178
|
-
await buildApp(
|
|
179
|
-
|
|
379
|
+
await buildApp(androidConfig, buildOptimisation, targetDevice.id, gradleOptions);
|
|
380
|
+
// Debug builds load http://localhost:<port>; on the device that
|
|
381
|
+
// is the device itself. Forward every port the app uses to this
|
|
382
|
+
// machine, after the install and before the launch, every run.
|
|
383
|
+
const packageName = `${applicationId}.debug`;
|
|
384
|
+
const ports = devServerPorts(resolved.config, {
|
|
385
|
+
hmrPort: await readHmrPort({
|
|
386
|
+
cwd: appRoot
|
|
387
|
+
})
|
|
388
|
+
});
|
|
389
|
+
reachDevServer(adbRunner(ADB_PATH), targetDevice.id, packageName, ports);
|
|
390
|
+
progress.log(`Forwarded ports ${ports.join(", ")} to this machine (adb reverse)`, "info");
|
|
391
|
+
launchApp(ADB_PATH, targetDevice.id, packageName);
|
|
180
392
|
progress.complete("build");
|
|
181
|
-
movedApkPath = await moveApkToOutputPath(buildType, bop, androidConfig.appName);
|
|
182
393
|
}
|
|
183
394
|
|
|
184
395
|
// Aligned key/value rows, matching the Config tree the setup
|
|
185
396
|
// commands print. printTreeContent draws the branch glyphs.
|
|
186
397
|
const deviceName = targetDevice?.type === "physical" ? targetDevice.model : `${androidConfig.emulatorName} emulator`;
|
|
187
|
-
const summaryItems = [{
|
|
398
|
+
const summaryItems = release ? [] : [{
|
|
188
399
|
text: `device ${deviceName}`,
|
|
189
400
|
color: "gray"
|
|
190
401
|
}];
|
|
191
|
-
if (
|
|
402
|
+
if (artifactPath) {
|
|
192
403
|
summaryItems.push({
|
|
193
|
-
text: `artifact ${displayPath(
|
|
404
|
+
text: `artifact ${displayPath(artifactPath, appRoot)}`,
|
|
194
405
|
color: "gray"
|
|
195
406
|
});
|
|
196
407
|
}
|
|
197
|
-
if (
|
|
408
|
+
if (certificatePath) {
|
|
198
409
|
summaryItems.push({
|
|
199
|
-
text: `
|
|
410
|
+
text: `cert ${displayPath(certificatePath, appRoot)}`,
|
|
200
411
|
color: "gray"
|
|
201
412
|
});
|
|
202
413
|
}
|
|
203
414
|
summaryItems.push({
|
|
204
|
-
text: `
|
|
415
|
+
text: `version ${version.versionName || DEFAULT_VERSION_NAME} (${version.buildNumber})`,
|
|
416
|
+
color: "gray"
|
|
417
|
+
});
|
|
418
|
+
summaryItems.push({
|
|
419
|
+
text: `build ${release ? "release" : "debug"}${buildOptimisation ? ", optimised" : ""}`,
|
|
205
420
|
color: "gray"
|
|
206
421
|
});
|
|
207
422
|
progress.printTreeContent("Build", summaryItems);
|
|
208
|
-
|
|
423
|
+
if (release) {
|
|
424
|
+
progress.summary("Built the signed AAB", "Upload it to Google Play");
|
|
425
|
+
} else {
|
|
426
|
+
progress.summary(`Running on ${deviceName}`, "Edit your app; the dev server reloads it");
|
|
427
|
+
}
|
|
209
428
|
} catch (error) {
|
|
210
429
|
// Mark the step, then show what actually broke. The old handler
|
|
211
430
|
// printed a generic "check your SDK" checklist here, which is
|
|
@@ -218,13 +437,19 @@ function createAndroidBuild(config) {
|
|
|
218
437
|
code: "ANDROID-000"
|
|
219
438
|
}));
|
|
220
439
|
throw error;
|
|
440
|
+
} finally {
|
|
441
|
+
// The unpacked CI credentials and the resolved config are temp files.
|
|
442
|
+
signing?.cleanup();
|
|
443
|
+
resolved?.cleanup();
|
|
221
444
|
}
|
|
222
445
|
}
|
|
223
446
|
async function buildAndroidForTesting() {
|
|
224
447
|
try {
|
|
225
448
|
const {
|
|
226
|
-
WEBVIEW_CONFIG: wvConfig
|
|
449
|
+
WEBVIEW_CONFIG: wvConfig,
|
|
450
|
+
cleanup
|
|
227
451
|
} = await initializeConfig();
|
|
452
|
+
cleanup();
|
|
228
453
|
const androidConfig = wvConfig.android;
|
|
229
454
|
const buildOptimisation = !!androidConfig.buildOptimisation || false;
|
|
230
455
|
await copyBuildAssets(androidConfig, buildOptimisation);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.releaseArtifactPaths = releaseArtifactPaths;
|
|
7
|
+
exports.releaseOutputDir = releaseOutputDir;
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _releaseOutput = require("../releaseOutput.js");
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
/**
|
|
12
|
+
* Where a release puts its files: build-output/android/<version>-<build>/
|
|
13
|
+
* in the app, or <android.outputPath>/<version>-<build>/ when the config
|
|
14
|
+
* sets an output path. One folder per build, so nothing is overwritten.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} options
|
|
17
|
+
* @param {string} [options.appRoot]
|
|
18
|
+
* @param {{ outputPath?: string }} [options.androidConfig]
|
|
19
|
+
* @param {{ versionName?: string, buildNumber: number | string }} options.version - resolveNativeConfig().version
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
function releaseOutputDir({
|
|
23
|
+
appRoot = process.cwd(),
|
|
24
|
+
androidConfig = {},
|
|
25
|
+
version
|
|
26
|
+
}) {
|
|
27
|
+
const root = androidConfig.outputPath ? _path.default.resolve(appRoot, androidConfig.outputPath) : _path.default.join(appRoot, "build-output", "android");
|
|
28
|
+
return _path.default.join(root, (0, _releaseOutput.releaseFolderName)(version));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The release files in that folder: the bundle for Play and the upload
|
|
33
|
+
* certificate (PEM) that identifies the key that signed it.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} dir - releaseOutputDir()
|
|
36
|
+
* @param {string} name - the app's name; made file-name safe here
|
|
37
|
+
*/
|
|
38
|
+
function releaseArtifactPaths(dir, name) {
|
|
39
|
+
return {
|
|
40
|
+
aab: _path.default.join(dir, `${(0, _releaseOutput.artifactBaseName)(name)}.aab`),
|
|
41
|
+
certificate: _path.default.join(dir, "upload_certificate.pem")
|
|
42
|
+
};
|
|
43
|
+
}
|