stim 1.10.1 → 1.11.0
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/{build-progress-BXx-ZBe4.mjs → activity-BtG4Va9l.mjs} +8 -182
- package/dist/{android-DPov-fv2.mjs → android-BA2i_KAV.mjs} +1 -1
- package/dist/{android-Bu4mbDzc.mjs → android-C1q4l523.mjs} +376 -99
- package/dist/{android-787HhP5w.mjs → android-C4zG2Tuc.mjs} +63 -18
- package/dist/{android-cas-CITmIeWY.mjs → android-cas-DfJkwCXW.mjs} +3 -3
- package/dist/{app-install-Cfmqr3TQ.mjs → app-install-DHut6JnV.mjs} +1 -1
- package/dist/{budget-nDCEwtJv.mjs → budget-De3P2rq_.mjs} +9 -9
- package/dist/{dev-client-DExzPiOa.mjs → build-plan-CeAYgKAx.mjs} +415 -24
- package/dist/build-progress-CDwogz6R.mjs +179 -0
- package/dist/cli.mjs +14 -14
- package/dist/collector-run.mjs +1 -1
- package/dist/{deps-DP4eWqea.mjs → deps-OF7CD5Dx.mjs} +2 -2
- package/dist/{device-Czh5kO8A.mjs → device-BwH2iI3O.mjs} +47 -9
- package/dist/{device-lease-CbEaIk7b.mjs → device-lease-D83nqeMX.mjs} +51 -51
- package/dist/{device-pool-BBWLAr55.mjs → device-pool-DHj7cdPy.mjs} +2 -2
- package/dist/{device-remote-powUHdbK.mjs → device-remote-BQZSnnmE.mjs} +7 -7
- package/dist/{doctor-CmqK1LcQ.mjs → doctor-D8QdMRMf.mjs} +12 -12
- package/dist/{error-diagnostics-xxWKNO3-.mjs → error-diagnostics-UYFSQwRy.mjs} +3 -3
- package/dist/{gc-zCDpmdHU.mjs → gc-COZteyiq.mjs} +27 -253
- package/dist/{guide-DwmaD_Wa.mjs → guide-NDvTmMi-.mjs} +336 -48
- package/dist/{idle--jn7pBNe.mjs → idle-NETbeNiQ.mjs} +4 -3
- package/dist/{in-use-CNIWU-r-.mjs → in-use-DVhlSoyn.mjs} +4 -4
- package/dist/{ios-CbdqTqOc.mjs → ios-CQLKpNfr.mjs} +294 -81
- package/dist/{ios-COGcGEcN.mjs → ios-DArbmwer.mjs} +2 -1
- package/dist/{ios-device-DNjPXBnb.mjs → ios-device-CwDZo0X4.mjs} +1 -1
- package/dist/{launch-verify-BhgkYAws.mjs → launch-verify-CuPDGXdr.mjs} +1 -1
- package/dist/logs-B44a1UeU.mjs +485 -0
- package/dist/merge-state-DDxS-XIZ.mjs +232 -0
- package/dist/{named-ports-DiTfSz6p.mjs → named-ports-Dc7neAlc.mjs} +1 -1
- package/dist/native-run-D7yB_AsB.mjs +143 -0
- package/dist/{ownership-BfPNRf3-.mjs → ownership-BiojdtAp.mjs} +3 -3
- package/dist/{ports-CLSSFOuz.mjs → ports-DwBaRFJs.mjs} +1 -1
- package/dist/{reload-CymyF6Kk.mjs → reload-By9Dwsrt.mjs} +4 -4
- package/dist/{server-bare-DVbb7kXH.mjs → server-bare-D_RK1RCj.mjs} +1 -1
- package/dist/server-expo-B-CCUJZj.mjs +2 -0
- package/dist/{server-expo-BvOCeakp.mjs → server-expo-o6H5gcBc.mjs} +1 -1
- package/dist/{settings-DOugPlPz.mjs → settings-B5oFZEri.mjs} +12 -3
- package/dist/{settings-EWYNwe72.mjs → settings-C0ugALSC.mjs} +1 -1
- package/dist/settings.schema.json +52 -0
- package/dist/{simslim-DZUxzsjq.mjs → simslim-CIR3IYJO.mjs} +150 -95
- package/dist/{slot-launch-Dk4oTREM.mjs → slot-launch-rggO1Esw.mjs} +2 -2
- package/dist/{spawn-claims-CUleC2cM.mjs → spawn-claims-BJwXTMPt.mjs} +24 -1
- package/dist/{start-RbmFPeZ7.mjs → start-BSsf2tUs.mjs} +4 -4
- package/dist/{start-qWapeB4W.mjs → start-i8zc9VmS.mjs} +1 -1
- package/dist/{status-Zp8kvexe.mjs → status-CitcBRsC.mjs} +227 -22
- package/dist/{status-Dr4fRkym.mjs → status-Q-WDEGCB.mjs} +20 -6
- package/dist/{stop-DcEv5sk-.mjs → stop-DIhrvu0B.mjs} +188 -27
- package/dist/stop-rst5mL14.mjs +3 -0
- package/dist/supervisor-run.mjs +7 -7
- package/dist/{workspace-process-lock-BXA96myD.mjs → workspace-process-lock-Cx74RSDZ.mjs} +9 -4
- package/dist/{workspaces-wrH6dXfu.mjs → workspaces-COD2xCz-.mjs} +15 -5
- package/dist/{worktree-DEG2o9F8.mjs → worktree-DhxDTK44.mjs} +1 -1
- package/dist/{worktree-Bd4dRvx7.mjs → worktree-KOjMX3zA.mjs} +8 -8
- package/dist/{xcode-B2tBkf0m.mjs → xcode-B5SPD--o.mjs} +3 -3
- package/package.json +5 -5
- package/dist/logs-MARIy6m9.mjs +0 -209
- package/dist/server-expo-DBVTdult.mjs +0 -2
- package/dist/stop-DI4BG4Os.mjs +0 -3
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
import { L as deviceSlotFileKey, R as deviceSlotKey, S as setDevice, T as withConfigLock, V as parseDeviceSlotOption, W as validateDeviceSlot, f as getProject, g as loadConfig, k as ownership_claim_exports, l as getConcurrencyLimits, w as upsertProject, x as saveConfig, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
|
|
1
|
+
import { L as deviceSlotFileKey, R as deviceSlotKey, S as setDevice, T as withConfigLock$1, V as parseDeviceSlotOption, W as validateDeviceSlot, f as getProject, g as loadConfig$1, k as ownership_claim_exports, l as getConcurrencyLimits, w as upsertProject, x as saveConfig, z as deviceSlotPlatforms } from "./config-BEq0Qw_a.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
3
|
import { r as createNdjsonWriter } from "./ndjson-CDY9IkVC.mjs";
|
|
4
|
-
import { O as workspaceDir, b as emulatorLogFile, c as signalProcessTree, h as recordWorkspaceUse, i as pidExists, j as workspaceLogsDir, m as readWorkspaceState, s as resolveProjectMetro, y as writeWorkspaceState } from "./metro-BWLOJ_Wr.mjs";
|
|
4
|
+
import { O as workspaceDir, b as emulatorLogFile, c as signalProcessTree, h as recordWorkspaceUse, i as pidExists, j as workspaceLogsDir, m as readWorkspaceState$1, s as resolveProjectMetro, y as writeWorkspaceState } from "./metro-BWLOJ_Wr.mjs";
|
|
5
5
|
import { D as makeTemporaryDirectory, O as removeTemporaryEntry, s as gitCommonDir, y as repoRoot } from "./worktree-BlizKDpZ.mjs";
|
|
6
|
-
import { a as detectIsExpo, i as detectBundleId, l as projectShortcut, n as appProjectProblem, o as findProjectRoot, r as detectAndroidPackage } from "./project-BXZzOABt.mjs";
|
|
6
|
+
import { a as detectIsExpo, i as detectBundleId, l as projectShortcut, n as appProjectProblem, o as findProjectRoot, r as detectAndroidPackage, t as NO_PROJECT_REFUSAL } from "./project-BXZzOABt.mjs";
|
|
7
7
|
import { n as MODE_EXPO, p as writeWorkspaceLaunch, t as MODE_BARE } from "./state-WGdIbi_d.mjs";
|
|
8
|
-
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BXA96myD.mjs";
|
|
9
8
|
import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
10
9
|
import { _ as stepTimer, c as launchErrorReport, f as refuseNoProject, g as stepClock, i as formatDuration, l as phaseLine, m as shortHash, n as appReadinessMessage, v as launchErrorPreview } from "./command-output-D5z2_bcF.mjs";
|
|
11
|
-
import { A as resolveBuild, C as
|
|
12
|
-
import { n as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { a as acquireBuildSlot, s as releaseBuildSlot } from "./in-use-
|
|
10
|
+
import { A as resolveBuild, C as filesystemBuildCapability, D as providerDownloadPath, E as prepareProviderDownloadDir, F as untrackedNativeFiles, I as assetDiffReason, L as captureAssetManifest, M as storedAssetManifest, O as providerUploadOutcome, P as untrackedMissLine, R as compareAssetManifests, T as fingerprintProject, _ as waitForBuild, b as buildCacheKey, g as releaseBuildLock, j as storeBuild, k as refingerprintAfterMutation, m as acquireBuildLock, v as waitForSharedBuild, w as fingerprintDiffRecord, z as readAssetManifest } from "./device-lease-D83nqeMX.mjs";
|
|
11
|
+
import { A as memoizeEmulatorProbe, B as probeEmulatorSerial, C as hostSystemImageArch, D as listAvds, E as listAvdDeviceProfiles, H as resolveOwnedAvdSerial, L as ownedAvdSystemImage, N as ownedAvdDirectory, O as listInstalledSystemImages, Q as configuredAndroidEmulatorApp, R as physicalDeviceModel, T as listAdbDevices, U as resolvePhysicalDevice, V as resetAdoptedAvd, a as androidPoolCandidates, b as extractEmulatorFailure, c as androidToolCwd, i as androidHome, n as androidBuildToolName, o as androidPoolNoCandidatesRefusal, q as waitForBoot, r as androidDeviceAbi, s as androidSystemImageAbi, v as emulatorDiskSpaceRemedy, x as findBuildTool, y as emulatorFailureRemedy, z as pickDefaultSystemImage } from "./android-C4zG2Tuc.mjs";
|
|
12
|
+
import { A as resolveCacheProviderConfig, E as publicUrlSetting, H as compilerCacheFallbackMessage, I as tunnelModeSetting, L as unknownSettingKeys, M as settingFile, O as remoteAndroidSetting, P as settingShapeErrors, S as metroWarmupUrlSetting, U as optimizationBuildProfile, V as artifactCachePolicy, W as resolveOptimizations, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, j as resolveSettings, r as REMOTE_DEVICE_BACKENDS, s as androidAvdConfigSettingError, u as androidDataPartitionSizeGbSettingError, z as detectProviders } from "./settings-B5oFZEri.mjs";
|
|
13
|
+
import { y as parkedMaxSetting } from "./ownership-BiojdtAp.mjs";
|
|
14
|
+
import { c as startBuildProgress, n as NO_BUILD_PROGRESS } from "./build-progress-CDwogz6R.mjs";
|
|
15
|
+
import { a as acquireBuildSlot, s as releaseBuildSlot } from "./in-use-DVhlSoyn.mjs";
|
|
17
16
|
import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-D2xbLVoz.mjs";
|
|
18
|
-
import { t as cleanLine } from "./server-expo-
|
|
19
|
-
import { A as UPLOAD_TIMEOUT_MS, B as resolveRemote, F as isEasAuthFailureText, I as loadProjectProvider, M as checkEasAuth, N as easAuthNote, P as exitAfterFlush, V as uploadRemote, a as ensureMetroReachable, c as remoteAndroidDeps, j as cacheLevel, k as RESOLVE_TIMEOUT_MS, n as binOnPath, o as ensureRemoteBootOwned, u as resolveRemoteContext, w as ownedSessionName, z as resolveEasCliBin } from "./device-remote-
|
|
20
|
-
import { _ as launchAndroidReleaseApp, d as deviceShellArg, f as installAndroidApp, g as launchAndroidApp, o as androidAppProcess, p as installConflictKind, r as DEFAULT_METRO_PORT, s as androidDevClientUrl, t as ADB_INSTALL_TIMEOUT_MS } from "./app-install-
|
|
21
|
-
import { a as VERIFY_TIMEOUT_MS, d as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unverifiedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as verifyAndroidReleaseLaunch } from "./launch-verify-
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { t as
|
|
26
|
-
import {
|
|
17
|
+
import { t as cleanLine } from "./server-expo-o6H5gcBc.mjs";
|
|
18
|
+
import { A as UPLOAD_TIMEOUT_MS, B as resolveRemote, F as isEasAuthFailureText, I as loadProjectProvider, M as checkEasAuth, N as easAuthNote, P as exitAfterFlush, V as uploadRemote, a as ensureMetroReachable, c as remoteAndroidDeps, j as cacheLevel, k as RESOLVE_TIMEOUT_MS, n as binOnPath, o as ensureRemoteBootOwned, u as resolveRemoteContext, w as ownedSessionName, z as resolveEasCliBin } from "./device-remote-BQZSnnmE.mjs";
|
|
19
|
+
import { _ as launchAndroidReleaseApp, d as deviceShellArg, f as installAndroidApp, g as launchAndroidApp, o as androidAppProcess, p as installConflictKind, r as DEFAULT_METRO_PORT, s as androidDevClientUrl, t as ADB_INSTALL_TIMEOUT_MS } from "./app-install-DHut6JnV.mjs";
|
|
20
|
+
import { a as VERIFY_TIMEOUT_MS, d as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unverifiedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as verifyAndroidReleaseLaunch } from "./launch-verify-CuPDGXdr.mjs";
|
|
21
|
+
import { f as isEasBuildFailure, m as resolveEasDevelopmentBuild, o as unknownAndroidDeviceProfileRefusal, p as planEasDevelopmentBuild, r as checkDeviceCapacity, s as unknownAndroidSystemImageRefusal } from "./simslim-CIR3IYJO.mjs";
|
|
22
|
+
import { d as withNativeBuildRun, r as cancelledFailure, u as runCancellation } from "./native-run-D7yB_AsB.mjs";
|
|
23
|
+
import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-DHj7cdPy.mjs";
|
|
24
|
+
import { C as ensureDevServer, E as launchOutcomeRecord, O as warmMetro, T as isPhysicalDeviceRequest, _ as staleNativeDirRefusal, a as refusePlan, b as AvdBootError, c as skippedMissReason, f as detectEntryFile, g as runPrebuild, h as recordPrebuild, i as printPlan, l as devClientScheme, m as planPrebuild, n as planFlagRefusal, o as explainBuildMiss, r as planPayload, s as fingerprintErrorMissReason, t as planCachedBuild, u as pickDevClientScheme, v as ensureBooted, w as ensureWorkspaceStorageSafely, x as AvdRecoveryError, y as ensureOwnedDevice } from "./build-plan-CeAYgKAx.mjs";
|
|
25
|
+
import { t as budgetGate } from "./budget-De3P2rq_.mjs";
|
|
26
|
+
import { f as spawnEntry, s as startDevServer } from "./start-BSsf2tUs.mjs";
|
|
27
27
|
import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BAgJaLA4.mjs";
|
|
28
|
-
import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-
|
|
29
|
-
import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-
|
|
30
|
-
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-
|
|
31
|
-
import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
28
|
+
import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-DfJkwCXW.mjs";
|
|
29
|
+
import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B5SPD--o.mjs";
|
|
30
|
+
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-rggO1Esw.mjs";
|
|
31
|
+
import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-UYFSQwRy.mjs";
|
|
32
32
|
import { constants, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
33
33
|
import { InvalidArgumentError } from "commander";
|
|
34
|
+
import { LAST_BUILD_KEYS } from "@stim-cli/core/state";
|
|
34
35
|
import { basename, dirname, isAbsolute, join, relative } from "node:path";
|
|
35
36
|
import chalk from "chalk";
|
|
36
37
|
import { createWarnOnce, loadCacheProvider, resolveTieredBuild, storeTieredBuild } from "@stim-cli/cache";
|
|
@@ -436,6 +437,36 @@ function systemImageRefusal({ slot, flag, resolved, physical, remoteBackend, lis
|
|
|
436
437
|
remedy: refusal.remedy
|
|
437
438
|
} : null;
|
|
438
439
|
}
|
|
440
|
+
function resolveDeviceProfile(flag, settings) {
|
|
441
|
+
const fromFlag = typeof flag === "string" && flag.trim() !== "" ? flag.trim() : null;
|
|
442
|
+
const android = settings?.["android"];
|
|
443
|
+
const raw = android && typeof android === "object" && !Array.isArray(android) ? android["deviceProfile"] : void 0;
|
|
444
|
+
return fromFlag || (typeof raw === "string" && raw.trim() !== "" ? raw.trim() : null);
|
|
445
|
+
}
|
|
446
|
+
function deviceProfileRefusal({ flag, resolved, physical, remoteBackend, listProfiles }) {
|
|
447
|
+
if (typeof flag === "string" && flag.trim() === "") return {
|
|
448
|
+
code: "STIM_BAD_ARG",
|
|
449
|
+
message: "--device-profile was given an empty id.",
|
|
450
|
+
remedy: "Pass `--device-profile <id>` with an id `avdmanager list device -c` prints, e.g. \"pixel_fold\"."
|
|
451
|
+
};
|
|
452
|
+
if (physical || remoteBackend || !resolved) return null;
|
|
453
|
+
let profiles;
|
|
454
|
+
try {
|
|
455
|
+
profiles = listProfiles();
|
|
456
|
+
} catch (error) {
|
|
457
|
+
return {
|
|
458
|
+
code: NO_DEVICE,
|
|
459
|
+
message: `Could not list the Android hardware profiles with avdmanager: ${error?.message || error}`,
|
|
460
|
+
remedy: "Check that JAVA_HOME and ANDROID_HOME are set and the SDK command-line tools are installed, then try again."
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const refusal = unknownAndroidDeviceProfileRefusal(resolved, profiles);
|
|
464
|
+
return refusal ? {
|
|
465
|
+
code: "STIM_BAD_ARG",
|
|
466
|
+
message: refusal.message,
|
|
467
|
+
remedy: refusal.remedy
|
|
468
|
+
} : null;
|
|
469
|
+
}
|
|
439
470
|
function isReleaseVariant(variant) {
|
|
440
471
|
return typeof variant === "string" && /release$/i.test(variant.trim());
|
|
441
472
|
}
|
|
@@ -723,11 +754,16 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
723
754
|
hash = computed?.hash ?? "";
|
|
724
755
|
fingerprintSources = computed?.sources ?? [];
|
|
725
756
|
} catch (err) {
|
|
726
|
-
|
|
757
|
+
const message = String(err?.message || err);
|
|
758
|
+
record.cacheSkipped = !useBuildCache;
|
|
759
|
+
record.missReason = fingerprintErrorMissReason(message);
|
|
760
|
+
phaseFailure = fail$1(NO_FINGERPRINT, `@expo/fingerprint could not fingerprint ${root}: ${message}`, "Fix the @expo/fingerprint error above, then retry.", { lastBuildStatus: true });
|
|
727
761
|
return false;
|
|
728
762
|
}
|
|
729
763
|
if (!hash) {
|
|
730
|
-
|
|
764
|
+
record.cacheSkipped = !useBuildCache;
|
|
765
|
+
record.missReason = fingerprintErrorMissReason("no hash");
|
|
766
|
+
phaseFailure = fail$1(NO_FINGERPRINT, `@expo/fingerprint returned no hash for ${root}, so the build cache cannot be addressed.`, "Check the project native inputs and the @expo/fingerprint error above, then retry.", { lastBuildStatus: true });
|
|
731
767
|
return false;
|
|
732
768
|
}
|
|
733
769
|
record.fingerprint = hash;
|
|
@@ -757,29 +793,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
757
793
|
const cached = found?.tier === "local" ? found.path : null;
|
|
758
794
|
record.cacheHit = cached ? "local" : false;
|
|
759
795
|
record.cacheSkipped = !useBuildCache;
|
|
760
|
-
|
|
761
|
-
let missUntracked = null;
|
|
762
|
-
if (!cached) {
|
|
763
|
-
const lastBuild = readState(root)?.lastBuild ?? null;
|
|
764
|
-
const miss = describeFingerprintMiss({
|
|
765
|
-
platform: PLATFORM,
|
|
766
|
-
current: {
|
|
767
|
-
hash,
|
|
768
|
-
sources: fingerprintSources
|
|
769
|
-
},
|
|
770
|
-
lastBuild
|
|
771
|
-
});
|
|
772
|
-
if (miss) {
|
|
773
|
-
missDiff = fingerprintDiffSuffix(miss.changed);
|
|
774
|
-
writer.write(fingerprintDiffRecord({
|
|
775
|
-
changed: miss.changed,
|
|
776
|
-
previousHash: miss.previousHash,
|
|
777
|
-
hash
|
|
778
|
-
}));
|
|
779
|
-
} else if (useBuildCache) missUntracked = untrackedMissLine(untracked({ projectRoot: root }));
|
|
780
|
-
}
|
|
781
|
-
phase("fingerprint", `${shortHash(hash)} ${cached ? "hit" : "miss"}${useBuildCache ? "" : !requestedBuildCache ? " (--no-build-cache)" : " (cache reuse off in config)"} ${fingerprintTimer()}${missDiff}`);
|
|
782
|
-
if (missUntracked) phase("fingerprint", chalk.dim(missUntracked));
|
|
796
|
+
phase("fingerprint", `${shortHash(hash)} ${cached ? "hit" : "miss"}${useBuildCache ? "" : !requestedBuildCache ? " (--no-build-cache)" : " (cache reuse off in config)"} ${fingerprintTimer()}`);
|
|
783
797
|
if (found?.tier === "provider") {
|
|
784
798
|
record.cacheHit = "remote";
|
|
785
799
|
providerName = found.providerName ?? null;
|
|
@@ -909,6 +923,34 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
909
923
|
}
|
|
910
924
|
}
|
|
911
925
|
}
|
|
926
|
+
function explainMiss(rekeyedBy) {
|
|
927
|
+
if (swapFellBack) record.missReason = skippedMissReason("the cached APK could not be reused, so this run built it fresh");
|
|
928
|
+
else if (!useBuildCache) record.missReason = skippedMissReason(requestedBuildCache ? "cache reuse off in config" : "cache reuse turned off by --no-build-cache");
|
|
929
|
+
else {
|
|
930
|
+
const current = {
|
|
931
|
+
hash: storeHash,
|
|
932
|
+
sources: storeSources
|
|
933
|
+
};
|
|
934
|
+
const explained = explainBuildMiss({
|
|
935
|
+
root,
|
|
936
|
+
platform: PLATFORM,
|
|
937
|
+
current,
|
|
938
|
+
rekeyedBy,
|
|
939
|
+
baselineDeps: { readState }
|
|
940
|
+
});
|
|
941
|
+
record.missReason = explained.reason;
|
|
942
|
+
if (explained.previousHash && explained.changedNames.length) writer.write(fingerprintDiffRecord({
|
|
943
|
+
changed: explained.changedNames,
|
|
944
|
+
previousHash: explained.previousHash,
|
|
945
|
+
hash: current.hash
|
|
946
|
+
}));
|
|
947
|
+
}
|
|
948
|
+
phase("cache", `miss: ${record.missReason.summary}`);
|
|
949
|
+
if (record.missReason.kind === "no-baseline") {
|
|
950
|
+
const line = untrackedMissLine(untracked({ projectRoot: root }));
|
|
951
|
+
if (line) phase("fingerprint", chalk.dim(line));
|
|
952
|
+
}
|
|
953
|
+
}
|
|
912
954
|
async function buildArtifact() {
|
|
913
955
|
if (!apkPath) try {
|
|
914
956
|
if (maxBuilds) try {
|
|
@@ -926,6 +968,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
926
968
|
}
|
|
927
969
|
phase("build", chalk.yellow(`could not take a build slot: ${err?.message || err}; building anyway`));
|
|
928
970
|
}
|
|
971
|
+
const rekeyedBy = [];
|
|
929
972
|
const prebuildPlan = planPrebuildFor(root, PLATFORM, {
|
|
930
973
|
isExpo,
|
|
931
974
|
fingerprint: hash,
|
|
@@ -962,6 +1005,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
962
1005
|
});
|
|
963
1006
|
if (after) recordPrebuild(root, PLATFORM, after.hash);
|
|
964
1007
|
if (after?.moved) {
|
|
1008
|
+
rekeyedBy.push("prebuild");
|
|
965
1009
|
storeHash = after.hash;
|
|
966
1010
|
storeSources = after.sources;
|
|
967
1011
|
storeKey = buildCacheKey(PLATFORM, after.hash, buildRunOptions);
|
|
@@ -984,6 +1028,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
984
1028
|
}
|
|
985
1029
|
}
|
|
986
1030
|
if (!apkPath) {
|
|
1031
|
+
explainMiss(rekeyedBy);
|
|
987
1032
|
step("compile");
|
|
988
1033
|
phase("build", `compiling ${variant || "debug"} with Gradle`);
|
|
989
1034
|
const built = await build({
|
|
@@ -1115,7 +1160,7 @@ function tail(lines, n = FALLBACK_LINES) {
|
|
|
1115
1160
|
}
|
|
1116
1161
|
//#endregion
|
|
1117
1162
|
//#region src/commands/android/result.ts
|
|
1118
|
-
function androidFacts({ slot, serial, avdName = null, deviceName = null, systemImage = null, fingerprint, cacheKey = null, variant = null, metroPort = null, cacheHit, cacheSkipped = false, waitedForBuild = null, appPath, bundleId, installSkipped = false, launched, ccache = CCACHE_UNAVAILABLE, logs, debugHttpHost = null, debugHttpHostNote = null, devClientUrl = null, durationMs, lease, devServer = null }) {
|
|
1163
|
+
function androidFacts({ slot, serial, avdName = null, deviceName = null, systemImage = null, deviceProfile = null, fingerprint, cacheKey = null, variant = null, metroPort = null, cacheHit, cacheSkipped = false, waitedForBuild = null, appPath, bundleId, installSkipped = false, launched, ccache = CCACHE_UNAVAILABLE, logs, debugHttpHost = null, debugHttpHostNote = null, devClientUrl = null, durationMs, lease, devServer = null }) {
|
|
1119
1164
|
return {
|
|
1120
1165
|
platform: PLATFORM,
|
|
1121
1166
|
...slot && slot !== "default" ? { slot } : {},
|
|
@@ -1123,6 +1168,7 @@ function androidFacts({ slot, serial, avdName = null, deviceName = null, systemI
|
|
|
1123
1168
|
avdName: avdName ?? null,
|
|
1124
1169
|
deviceName: deviceName ?? avdName ?? null,
|
|
1125
1170
|
systemImage: systemImage ?? null,
|
|
1171
|
+
deviceProfile: deviceProfile ?? null,
|
|
1126
1172
|
fingerprint: fingerprint ?? null,
|
|
1127
1173
|
cacheKey: cacheKey ?? null,
|
|
1128
1174
|
variant: variant ?? null,
|
|
@@ -1147,7 +1193,7 @@ function androidFacts({ slot, serial, avdName = null, deviceName = null, systemI
|
|
|
1147
1193
|
...devServer ? { devServer } : {}
|
|
1148
1194
|
};
|
|
1149
1195
|
}
|
|
1150
|
-
function lastBuildRecord({ fingerprint, cacheKey, cacheHit, cacheSkipped = false, durationMs, appPath, bundleId, startedAt, status, errorCode = null, avdName = null, deviceName = null }) {
|
|
1196
|
+
function lastBuildRecord({ fingerprint, cacheKey, cacheHit, cacheSkipped = false, durationMs, appPath, bundleId, startedAt, status, errorCode = null, avdName = null, deviceName = null, missReason = null }) {
|
|
1151
1197
|
const record = {
|
|
1152
1198
|
platform: PLATFORM,
|
|
1153
1199
|
avdName: avdName ?? null,
|
|
@@ -1163,6 +1209,7 @@ function lastBuildRecord({ fingerprint, cacheKey, cacheHit, cacheSkipped = false
|
|
|
1163
1209
|
status
|
|
1164
1210
|
};
|
|
1165
1211
|
if (errorCode) record.errorCode = errorCode;
|
|
1212
|
+
if (missReason && !cacheLevel(cacheHit)) record.missReason = missReason;
|
|
1166
1213
|
return record;
|
|
1167
1214
|
}
|
|
1168
1215
|
async function finishAndroidUpload(uploadPending, remote, phase) {
|
|
@@ -1195,6 +1242,7 @@ function reportAndroidResult({ slot, json, useBuildCache, variant, release, metr
|
|
|
1195
1242
|
avdName: record.avdName,
|
|
1196
1243
|
deviceName: record.deviceName,
|
|
1197
1244
|
systemImage: record.systemImage,
|
|
1245
|
+
deviceProfile: record.deviceProfile,
|
|
1198
1246
|
debugHttpHost: launched.debugHttpHost ?? null,
|
|
1199
1247
|
debugHttpHostNote: launched.debugHttpHostNote ?? null,
|
|
1200
1248
|
devClientUrl: launched.devClientUrl ?? null,
|
|
@@ -1252,7 +1300,10 @@ function persistLastBuild({ writeState, root, record, startedAt, durationMs, sta
|
|
|
1252
1300
|
errorCode
|
|
1253
1301
|
});
|
|
1254
1302
|
try {
|
|
1255
|
-
writeState(root, {
|
|
1303
|
+
writeState(root, {
|
|
1304
|
+
lastBuild,
|
|
1305
|
+
[LAST_BUILD_KEYS[PLATFORM]]: lastBuild
|
|
1306
|
+
});
|
|
1256
1307
|
} catch (err) {
|
|
1257
1308
|
out(phaseLine("state", chalk.yellow(`could not record lastBuild: ${err?.message || err}`)));
|
|
1258
1309
|
}
|
|
@@ -1471,8 +1522,8 @@ async function resolveInstallSerial({ root, slot, device, physical, remoteDevice
|
|
|
1471
1522
|
phase("device", `reopen agent-device on ${resolved.serial}`);
|
|
1472
1523
|
}
|
|
1473
1524
|
const consolePort = Number(resolved.serial.replace(/^emulator-/, ""));
|
|
1474
|
-
withConfigLock(() => {
|
|
1475
|
-
const current = deviceSlotPlatforms(loadConfig()?.projects?.[root], slot)?.android;
|
|
1525
|
+
withConfigLock$1(() => {
|
|
1526
|
+
const current = deviceSlotPlatforms(loadConfig$1()?.projects?.[root], slot)?.android;
|
|
1476
1527
|
if (!current?.owned || current.avdName !== device.avdName) throw new Error("The owned emulator assignment changed before installation.");
|
|
1477
1528
|
if (current.consolePort !== consolePort) setDevice(root, PLATFORM, {
|
|
1478
1529
|
...current,
|
|
@@ -1558,8 +1609,8 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
|
|
|
1558
1609
|
return fail(installed.code || "STIM_INSTALL_FAILED", installed.reason, installRemedy, { lastBuildStatus: true });
|
|
1559
1610
|
}
|
|
1560
1611
|
if (adopting) try {
|
|
1561
|
-
withConfigLock(() => {
|
|
1562
|
-
const config = loadConfig();
|
|
1612
|
+
withConfigLock$1(() => {
|
|
1613
|
+
const config = loadConfig$1();
|
|
1563
1614
|
const current = deviceSlotPlatforms(config?.projects?.[root], slot)?.android;
|
|
1564
1615
|
if (!config || !current || current.avdName !== device.avdName) throw new Error("The adopted emulator assignment changed during installation.");
|
|
1565
1616
|
delete current.adoptionPending;
|
|
@@ -1850,7 +1901,7 @@ function androidCompilerCache({ root, optimizations, settingsContext }) {
|
|
|
1850
1901
|
})}`
|
|
1851
1902
|
};
|
|
1852
1903
|
}
|
|
1853
|
-
function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, variant: variantFlag, systemImage: systemImageFlag, device: deviceFlag, wait: waitFlag, waitConflict, remote: commandRemoteBackend, buildCache: requestedBuildCache }, { warn, resolveCompilerCache = androidCompilerCache, resolveCacheProvider = resolveCacheProviderConfig, validateAvdConfig = androidAvdConfigSettingError, readFlavors = readProductFlavors, detectExpo = detectIsExpo, listSystemImages = listInstalledSystemImages, parkedLimit = parkedMaxSetting }) {
|
|
1904
|
+
function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, variant: variantFlag, systemImage: systemImageFlag, deviceProfile: deviceProfileFlag, device: deviceFlag, wait: waitFlag, waitConflict, remote: commandRemoteBackend, buildCache: requestedBuildCache }, { warn, resolveCompilerCache = androidCompilerCache, resolveCacheProvider = resolveCacheProviderConfig, validateAvdConfig = androidAvdConfigSettingError, readFlavors = readProductFlavors, detectExpo = detectIsExpo, listSystemImages = listInstalledSystemImages, listDeviceProfiles = listAvdDeviceProfiles, parkedLimit = parkedMaxSetting }) {
|
|
1854
1905
|
const root = settingsContext.projectPath;
|
|
1855
1906
|
const [shapeError, ...moreShapeErrors] = [parkedLimit("android").error, ...settingShapeErrors(settings)].filter((error) => Boolean(error));
|
|
1856
1907
|
if (shapeError) return fail("STIM_BAD_ARG", shapeError, SETTING_SHAPE_REMEDY, { lines: moreShapeErrors });
|
|
@@ -1878,6 +1929,7 @@ function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, va
|
|
|
1878
1929
|
const avdConfigError = validateAvdConfig(settings, root);
|
|
1879
1930
|
if (avdConfigError) return fail("STIM_BAD_ARG", avdConfigError, "Use only documented android.avdConfig keys, or an android.avdConfigFile fragment contained by the app directory.");
|
|
1880
1931
|
const systemImage = resolveSystemImage(systemImageFlag, settings);
|
|
1932
|
+
const deviceProfile = resolveDeviceProfile(deviceProfileFlag, settings);
|
|
1881
1933
|
const variant = easProfile !== void 0 ? "debug" : resolveVariant(variantFlag, settings);
|
|
1882
1934
|
const flavorRefusal = productFlavorRefusal({
|
|
1883
1935
|
flavors: readFlavors(root),
|
|
@@ -1907,6 +1959,14 @@ function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, va
|
|
|
1907
1959
|
listImages: listSystemImages
|
|
1908
1960
|
});
|
|
1909
1961
|
if (imageRefusal) return fail(imageRefusal.code, imageRefusal.message, imageRefusal.remedy);
|
|
1962
|
+
const profileRefusal = deviceProfileRefusal({
|
|
1963
|
+
flag: deviceProfileFlag,
|
|
1964
|
+
resolved: deviceProfile,
|
|
1965
|
+
physical,
|
|
1966
|
+
remoteBackend,
|
|
1967
|
+
listProfiles: listDeviceProfiles
|
|
1968
|
+
});
|
|
1969
|
+
if (profileRefusal) return fail(profileRefusal.code, profileRefusal.message, profileRefusal.remedy);
|
|
1910
1970
|
const target = physical ? {
|
|
1911
1971
|
kind: "physical",
|
|
1912
1972
|
serial: typeof deviceFlag === "string" ? deviceFlag : null,
|
|
@@ -1917,10 +1977,12 @@ function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, va
|
|
|
1917
1977
|
} : remoteBackend ? {
|
|
1918
1978
|
kind: "remote",
|
|
1919
1979
|
backend: remoteBackend,
|
|
1920
|
-
systemImage
|
|
1980
|
+
systemImage,
|
|
1981
|
+
deviceProfile
|
|
1921
1982
|
} : {
|
|
1922
1983
|
kind: "emulator",
|
|
1923
|
-
systemImage
|
|
1984
|
+
systemImage,
|
|
1985
|
+
deviceProfile
|
|
1924
1986
|
};
|
|
1925
1987
|
return {
|
|
1926
1988
|
ok: true,
|
|
@@ -1944,21 +2006,213 @@ function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, va
|
|
|
1944
2006
|
};
|
|
1945
2007
|
}
|
|
1946
2008
|
//#endregion
|
|
2009
|
+
//#region src/commands/android/next-build.ts
|
|
2010
|
+
const DEFAULT_PLAN_DEPS = {
|
|
2011
|
+
findRoot: findProjectRoot,
|
|
2012
|
+
fingerprint: fingerprintProject,
|
|
2013
|
+
listSystemImages: listInstalledSystemImages,
|
|
2014
|
+
avdSystemImage: ownedAvdSystemImage,
|
|
2015
|
+
avdDirectory: ownedAvdDirectory,
|
|
2016
|
+
listAvds,
|
|
2017
|
+
loadCacheProvider,
|
|
2018
|
+
loadProjectProvider,
|
|
2019
|
+
checkEasAuth,
|
|
2020
|
+
resolveRemote,
|
|
2021
|
+
planPrebuild
|
|
2022
|
+
};
|
|
2023
|
+
function note(line) {
|
|
2024
|
+
console.error(line);
|
|
2025
|
+
}
|
|
2026
|
+
function runOnlyFlag(opts) {
|
|
2027
|
+
if (isPhysicalDeviceRequest(opts.device)) return "--device";
|
|
2028
|
+
if (opts.remote) return "--remote";
|
|
2029
|
+
if (opts.wait !== void 0) return opts.wait === false ? "--no-wait" : "--wait";
|
|
2030
|
+
if (opts.metroCheck === false) return "--no-metro-check";
|
|
2031
|
+
return null;
|
|
2032
|
+
}
|
|
2033
|
+
function emulatorImage(root, slot, requested, deps) {
|
|
2034
|
+
const record = deviceSlotPlatforms(getProject(root), slot)?.android;
|
|
2035
|
+
if (record?.avdName && !record.setupIncomplete) {
|
|
2036
|
+
if (record.owned && deps.avdDirectory(record.avdName)) return { systemImage: deps.avdSystemImage(record.avdName) };
|
|
2037
|
+
if (!record.owned && avdListed(record.avdName, deps.listAvds)) return { systemImage: null };
|
|
2038
|
+
}
|
|
2039
|
+
let images;
|
|
2040
|
+
try {
|
|
2041
|
+
images = deps.listSystemImages();
|
|
2042
|
+
} catch (error) {
|
|
2043
|
+
return { refusal: {
|
|
2044
|
+
code: NO_DEVICE,
|
|
2045
|
+
message: `Could not read the installed Android system images: ${error?.message || error}`,
|
|
2046
|
+
remedy: "Check that ANDROID_HOME points at a readable SDK, then try again."
|
|
2047
|
+
} };
|
|
2048
|
+
}
|
|
2049
|
+
const picked = pickDefaultSystemImage(images, requested ? { systemImage: requested } : {});
|
|
2050
|
+
if (picked) return { systemImage: picked.pkg };
|
|
2051
|
+
const arch = hostSystemImageArch();
|
|
2052
|
+
return { refusal: {
|
|
2053
|
+
code: NO_DEVICE,
|
|
2054
|
+
message: `No ${arch} Android system image is installed, so the emulator build's ABI and cache key are unknown.`,
|
|
2055
|
+
remedy: `Install one, e.g.: sdkmanager "system-images;android-36;google_apis;${arch}", then try again.`
|
|
2056
|
+
} };
|
|
2057
|
+
}
|
|
2058
|
+
function avdListed(avdName, list) {
|
|
2059
|
+
try {
|
|
2060
|
+
return list({ timeoutMs: 1e4 }).includes(avdName);
|
|
2061
|
+
} catch {
|
|
2062
|
+
return false;
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
async function planAndroid(opts, overrides = {}) {
|
|
2066
|
+
const deps = {
|
|
2067
|
+
...DEFAULT_PLAN_DEPS,
|
|
2068
|
+
...overrides
|
|
2069
|
+
};
|
|
2070
|
+
const json = Boolean(opts.json);
|
|
2071
|
+
const refuse = (refusal, lines = []) => refusePlan(refusal, json, lines);
|
|
2072
|
+
const flag = runOnlyFlag(opts);
|
|
2073
|
+
if (flag) return refuse(planFlagRefusal(flag));
|
|
2074
|
+
const root = deps.findRoot(process.cwd());
|
|
2075
|
+
if (!root) return refuse(NO_PROJECT_REFUSAL);
|
|
2076
|
+
const projectProblem = appProjectProblem(root);
|
|
2077
|
+
if (projectProblem) return refuse({
|
|
2078
|
+
code: "STIM_NO_PROJECT",
|
|
2079
|
+
...projectProblem
|
|
2080
|
+
});
|
|
2081
|
+
const slot = validateDeviceSlot(opts.slot);
|
|
2082
|
+
const settingsContext = {
|
|
2083
|
+
projectPath: root,
|
|
2084
|
+
gitCommonDir: gitCommonDir(root),
|
|
2085
|
+
repoRoot: repoRoot(root)
|
|
2086
|
+
};
|
|
2087
|
+
const planned = resolveAndroidRunPlan({
|
|
2088
|
+
settings: resolveSettings(settingsContext),
|
|
2089
|
+
settingsContext,
|
|
2090
|
+
slot,
|
|
2091
|
+
easProfile: opts.easProfile,
|
|
2092
|
+
variant: opts.variant ?? null,
|
|
2093
|
+
systemImage: opts.systemImage ?? null,
|
|
2094
|
+
device: null,
|
|
2095
|
+
wait: void 0,
|
|
2096
|
+
waitConflict: false,
|
|
2097
|
+
remote: null,
|
|
2098
|
+
buildCache: opts.buildCache !== false
|
|
2099
|
+
}, {
|
|
2100
|
+
warn: (label, message) => note(phaseLine(label, chalk.yellow(message))),
|
|
2101
|
+
resolveCompilerCache: ({ optimizations }) => ({
|
|
2102
|
+
cas: null,
|
|
2103
|
+
optimizations,
|
|
2104
|
+
warning: null
|
|
2105
|
+
}),
|
|
2106
|
+
listSystemImages: deps.listSystemImages
|
|
2107
|
+
});
|
|
2108
|
+
if (!planned.ok) return refuse(planned, planned.lines);
|
|
2109
|
+
const { build, target, isExpo, cacheProviderConfig } = planned.plan;
|
|
2110
|
+
const planTarget = {
|
|
2111
|
+
platform: PLATFORM,
|
|
2112
|
+
slot,
|
|
2113
|
+
root,
|
|
2114
|
+
projectKey: statsProjectKey({
|
|
2115
|
+
root,
|
|
2116
|
+
commonDir: settingsContext.gitCommonDir,
|
|
2117
|
+
repoRoot: settingsContext.repoRoot
|
|
2118
|
+
})
|
|
2119
|
+
};
|
|
2120
|
+
if (opts.easProfile !== void 0) {
|
|
2121
|
+
const eas = await planEasDevelopmentBuild({
|
|
2122
|
+
root,
|
|
2123
|
+
platform: PLATFORM,
|
|
2124
|
+
profile: opts.easProfile,
|
|
2125
|
+
note,
|
|
2126
|
+
isExpo,
|
|
2127
|
+
selectors: [opts.variant],
|
|
2128
|
+
buildCache: opts.buildCache
|
|
2129
|
+
});
|
|
2130
|
+
if (!eas.ok) return refuse(eas);
|
|
2131
|
+
return printPlan(planPayload(planTarget, {
|
|
2132
|
+
fingerprint: eas.fingerprint,
|
|
2133
|
+
cacheKey: eas.cacheKey,
|
|
2134
|
+
cacheHit: eas.buildId ? "remote" : false,
|
|
2135
|
+
provider: "eas",
|
|
2136
|
+
cacheSkipped: false,
|
|
2137
|
+
prebuild: null,
|
|
2138
|
+
refusal: eas.missing
|
|
2139
|
+
}), json);
|
|
2140
|
+
}
|
|
2141
|
+
if (target.kind !== "emulator") {
|
|
2142
|
+
if (target.kind === "physical") return refuse(planFlagRefusal("--device"));
|
|
2143
|
+
return refuse({
|
|
2144
|
+
code: "STIM_BAD_ARG",
|
|
2145
|
+
message: `android.remote routes this workspace's runs to a ${target.backend} device, whose ABI --plan cannot read without a session.`,
|
|
2146
|
+
remedy: "Run `stim android` to build for the remote device, or unset android.remote to plan the owned emulator."
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
if (build.compilerCache === "cas") return refuse({
|
|
2150
|
+
code: "STIM_BAD_ARG",
|
|
2151
|
+
message: "The experimental Android compiler CAS keys builds by a toolchain Stim sets up, which --plan does not.",
|
|
2152
|
+
remedy: "Run `stim android` to build with the CAS, or set optimizations.android.compilerCache to ccache."
|
|
2153
|
+
});
|
|
2154
|
+
const image = build.targetAbiOnly && !build.release ? emulatorImage(root, slot, target.systemImage, deps) : { systemImage: null };
|
|
2155
|
+
if ("refusal" in image) return refuse(image.refusal);
|
|
2156
|
+
const { abi, runOptions, remoteRunOptions } = androidBuildOptions({
|
|
2157
|
+
release: build.release,
|
|
2158
|
+
physical: false,
|
|
2159
|
+
device: { systemImage: image.systemImage },
|
|
2160
|
+
variant: build.variant,
|
|
2161
|
+
deviceAbi: () => null,
|
|
2162
|
+
buildProfile: build.profile,
|
|
2163
|
+
targetAbiOnly: build.targetAbiOnly
|
|
2164
|
+
});
|
|
2165
|
+
let fingerprint;
|
|
2166
|
+
try {
|
|
2167
|
+
fingerprint = await deps.fingerprint(root, { platform: PLATFORM });
|
|
2168
|
+
} catch (error) {
|
|
2169
|
+
return refuse({
|
|
2170
|
+
code: NO_FINGERPRINT,
|
|
2171
|
+
message: `@expo/fingerprint could not fingerprint ${root}: ${error?.message || error}`,
|
|
2172
|
+
remedy: "Fix the @expo/fingerprint error above, then retry."
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
if (!fingerprint?.hash) return refuse({
|
|
2176
|
+
code: NO_FINGERPRINT,
|
|
2177
|
+
message: `@expo/fingerprint returned no hash for ${root}, so the build cache cannot be addressed.`,
|
|
2178
|
+
remedy: "Check the project native inputs and the @expo/fingerprint error above, then retry."
|
|
2179
|
+
});
|
|
2180
|
+
const plan = await planCachedBuild({
|
|
2181
|
+
...planTarget,
|
|
2182
|
+
isExpo,
|
|
2183
|
+
fingerprint: fingerprint.hash,
|
|
2184
|
+
sources: fingerprint.sources ?? [],
|
|
2185
|
+
cacheKey: buildCacheKey(PLATFORM, fingerprint.hash, runOptions),
|
|
2186
|
+
cachePolicy: build.cache,
|
|
2187
|
+
providerConfig: cacheProviderConfig,
|
|
2188
|
+
expoRemote: abi || build.profile || !build.cache.remote ? null : { runOptions: remoteRunOptions }
|
|
2189
|
+
}, {
|
|
2190
|
+
...deps,
|
|
2191
|
+
note
|
|
2192
|
+
});
|
|
2193
|
+
printPlan(plan, json);
|
|
2194
|
+
}
|
|
2195
|
+
//#endregion
|
|
1947
2196
|
//#region src/commands/android.ts
|
|
1948
2197
|
function androidCommand(program) {
|
|
1949
2198
|
registerAndroid(program);
|
|
1950
2199
|
}
|
|
1951
2200
|
function registerAndroid(program) {
|
|
1952
|
-
program.command("android").description("Build (or install from the shared cache), install and launch this workspace's Android app on its owned emulator, wired to the reserved Metro port. A Debug run starts the dev server when it is not running.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--no-metro-check", "Skip the reserved-port Metro health check and do not start it (the app will load no bundle unless something else serves it)").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--variant <name>", "Gradle variant to assemble and install (e.g. productionDebug on a flavored project); overrides the android.variant setting. A variant ending in Release embeds the JS bundle and skips Metro entirely. Default: debug").option("--system-image <id>", "Android system image to create this workspace's owned AVD from, as the sdkmanager package id (e.g. \"system-images;android-36;google_apis;arm64-v8a\"). Overrides the android.systemImage setting for this invocation. An unknown id refuses with STIM_BAD_ARG and prints the installed images.").option("--device [serial]", "Install and launch on a connected physical device instead of this workspace's owned emulator. With no serial, the first connected device this workspace can lease is used. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
|
|
2201
|
+
program.command("android").description("Build (or install from the shared cache), install and launch this workspace's Android app on its owned emulator, wired to the reserved Metro port. A Debug run starts the dev server when it is not running.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--plan", "Predict the next build without building, booting or installing: resolve the fingerprint, check the local then remote cache, and print the expected cache result and duration. Writes no Stim state.").option("--no-metro-check", "Skip the reserved-port Metro health check and do not start it (the app will load no bundle unless something else serves it)").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--variant <name>", "Gradle variant to assemble and install (e.g. productionDebug on a flavored project); overrides the android.variant setting. A variant ending in Release embeds the JS bundle and skips Metro entirely. Default: debug").option("--system-image <id>", "Android system image to create this workspace's owned AVD from, as the sdkmanager package id (e.g. \"system-images;android-36;google_apis;arm64-v8a\"). Overrides the android.systemImage setting for this invocation. An unknown id refuses with STIM_BAD_ARG and prints the installed images.").option("--device-profile <id>", "Hardware profile to create this workspace's owned AVD with, as an `avdmanager list device -c` id (e.g. \"pixel_fold\", \"pixel_tablet\"). Overrides the android.deviceProfile setting for this invocation. An unknown id refuses with STIM_BAD_ARG and prints the available ids.").option("--device [serial]", "Install and launch on a connected physical device instead of this workspace's owned emulator. With no serial, the first connected device this workspace can lease is used. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
|
|
1953
2202
|
if (REMOTE_DEVICE_BACKENDS.includes(value)) return value;
|
|
1954
2203
|
throw new InvalidArgumentError(`expected one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}`);
|
|
1955
2204
|
}).option("--wait <seconds>", "How long to wait for another workspace to release the device it leases, before refusing with STIM_DEVICE_BUSY (default 60, 0 refuses at once). Only with --device.").option("--no-wait", "Install on a device another workspace leases instead of waiting: this run takes no lease and, when both workspaces build the same app id, the install terminates the holder's running app. Only with --device.").action(async (opts) => {
|
|
2205
|
+
if (opts.plan) return planAndroid(opts);
|
|
1956
2206
|
const root = findProjectRoot(process.cwd());
|
|
1957
2207
|
if (!root) {
|
|
1958
2208
|
refuseNoProject({ json: Boolean(opts.json) });
|
|
1959
2209
|
return;
|
|
1960
2210
|
}
|
|
1961
|
-
if (!(await
|
|
2211
|
+
if (!(await withNativeBuildRun(root, {
|
|
2212
|
+
command: "android",
|
|
2213
|
+
platform: "android",
|
|
2214
|
+
slot: opts.slot ?? "default"
|
|
2215
|
+
}, async (claim) => {
|
|
1962
2216
|
recordWorkspaceUse(root);
|
|
1963
2217
|
const progress = startBuildProgress({
|
|
1964
2218
|
root,
|
|
@@ -1977,6 +2231,7 @@ function registerAndroid(program) {
|
|
|
1977
2231
|
useBuildCache: opts.buildCache !== false,
|
|
1978
2232
|
variant: opts.variant ?? null,
|
|
1979
2233
|
systemImage: opts.systemImage ?? null,
|
|
2234
|
+
deviceProfile: opts.deviceProfile ?? null,
|
|
1980
2235
|
remoteDevice: opts.remote ?? null,
|
|
1981
2236
|
device: opts.device ?? null,
|
|
1982
2237
|
wait: opts.wait,
|
|
@@ -1986,14 +2241,10 @@ function registerAndroid(program) {
|
|
|
1986
2241
|
} finally {
|
|
1987
2242
|
progress.clear();
|
|
1988
2243
|
}
|
|
1989
|
-
}, {
|
|
1990
|
-
external: true,
|
|
1991
|
-
waitMs: 18e5,
|
|
1992
|
-
declareSpawns: true
|
|
1993
|
-
})).ok) process.exit(1);
|
|
2244
|
+
}, { write: (line) => console.error(chalk.dim(phaseLine("lock", line))) })).ok) process.exit(runCancellation() ? 130 : 1);
|
|
1994
2245
|
});
|
|
1995
2246
|
}
|
|
1996
|
-
function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRemoteBackend = null, resolveSettingsFor = resolveSettings, resolveRemoteDeviceContext = resolveRemoteContext, remoteDeviceDeps: makeRemoteDeviceDeps = remoteAndroidDeps, resolveEasBin = resolveEasCliBin, ensureMetroReachable: ensureRemoteMetro = ensureMetroReachable, ensureRemoteBootOwned: ensureRemoteOwned = ensureRemoteBootOwned, detectRemoteProviders = detectProviders, metroCheck = true, useBuildCache = true, easProfile, resolveEasDevelopmentBuild: resolveEasBuild = resolveEasDevelopmentBuild, variant: variantFlag = null, systemImage: systemImageFlag = null, device: deviceFlag = null, wait: waitFlag = void 0, waitConflict = false, acquireLease = acquireRunLease, makeRunLease = runLease, selectPool = selectFromPool, onLeaseSignal = releaseLeaseOnSignal, listDevices = listAdbDevices, deviceModel = physicalDeviceModel, deviceAbi = androidDeviceAbi, isEmulatorDevice = probeEmulatorSerial, readApkPackage = (apkPath) => apkPackage(dumpApkManifest(apkPath)), getLimits = getConcurrencyLimits, checkCapacity = checkDeviceCapacity, acquireSlot = acquireBuildSlot, releaseSlot = releaseBuildSlot, ensureDevice = ensureOwnedDevice, listSystemImages = listInstalledSystemImages, ensureDeviceBooted = ensureBooted, resolveAvdSerial = resolveOwnedAvdSerial, waitForDeviceBoot = waitForBoot, resolveMetro = resolveProjectMetro, warmMetro: prewarmMetro = warmMetro, startServer = startDevServer, readState = readWorkspaceState, pidAlive = pidExists, verifyCollector = verifyCollectorOwnership, verifyLaunched = verifyLaunch, ensureStorage = ensureWorkspaceStorageSafely, fingerprint = fingerprintProject, untracked = untrackedNativeFiles, resolveCached = resolveBuild, storeCached = storeBuild, storedAssets = storedAssetManifest, captureAssets = captureAssetManifest, acquireLock = acquireBuildLock, releaseLock = releaseBuildLock, waitForBuild: waitForBuild$1 = waitForBuild, loadProvider = loadProjectProvider, easAuth = checkEasAuth, resolveRemoteBuild = resolveRemote, uploadRemoteBuild = uploadRemote, resolveCacheProvider = resolveCacheProviderConfig, loadCacheProviderModule = loadCacheProvider, planPrebuildFor = planPrebuild, prebuild = runPrebuild, build = buildAndroid, ccacheFor = resolveCcache, install = installAndroidApp, launch = launchAndroidApp, launchRelease = launchAndroidReleaseApp, verifyReleaseLaunched = verifyAndroidReleaseLaunch, swapApk = swapApkBundle, resolveDevClientScheme = androidDevClientScheme, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), createWriter = createNdjsonWriter, writeLaunch = writeWorkspaceLaunch, writeState = writeWorkspaceState, recordStats = recordRunStats, readEstimates = readRunEstimates, now = Date.now, out = (line) => console.error(line), emit = (line) => console.log(line) } = {}) {
|
|
2247
|
+
function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRemoteBackend = null, resolveSettingsFor = resolveSettings, resolveRemoteDeviceContext = resolveRemoteContext, remoteDeviceDeps: makeRemoteDeviceDeps = remoteAndroidDeps, resolveEasBin = resolveEasCliBin, ensureMetroReachable: ensureRemoteMetro = ensureMetroReachable, ensureRemoteBootOwned: ensureRemoteOwned = ensureRemoteBootOwned, detectRemoteProviders = detectProviders, metroCheck = true, useBuildCache = true, easProfile, resolveEasDevelopmentBuild: resolveEasBuild = resolveEasDevelopmentBuild, variant: variantFlag = null, systemImage: systemImageFlag = null, deviceProfile: deviceProfileFlag, device: deviceFlag = null, wait: waitFlag = void 0, waitConflict = false, acquireLease = acquireRunLease, makeRunLease = runLease, selectPool = selectFromPool, onLeaseSignal = releaseLeaseOnSignal, listDevices = listAdbDevices, deviceModel = physicalDeviceModel, deviceAbi = androidDeviceAbi, isEmulatorDevice = probeEmulatorSerial, readApkPackage = (apkPath) => apkPackage(dumpApkManifest(apkPath)), getLimits = getConcurrencyLimits, checkCapacity = checkDeviceCapacity, acquireSlot = acquireBuildSlot, releaseSlot = releaseBuildSlot, ensureDevice = ensureOwnedDevice, listSystemImages = listInstalledSystemImages, listDeviceProfiles, ensureDeviceBooted = ensureBooted, resolveAvdSerial = resolveOwnedAvdSerial, waitForDeviceBoot = waitForBoot, resolveMetro = resolveProjectMetro, warmMetro: prewarmMetro = warmMetro, startServer = startDevServer, readState = readWorkspaceState$1, pidAlive = pidExists, verifyCollector = verifyCollectorOwnership, verifyLaunched = verifyLaunch, ensureStorage = ensureWorkspaceStorageSafely, fingerprint = fingerprintProject, untracked = untrackedNativeFiles, resolveCached = resolveBuild, storeCached = storeBuild, storedAssets = storedAssetManifest, captureAssets = captureAssetManifest, acquireLock = acquireBuildLock, releaseLock = releaseBuildLock, waitForBuild: waitForBuild$1 = waitForBuild, loadProvider = loadProjectProvider, easAuth = checkEasAuth, resolveRemoteBuild = resolveRemote, uploadRemoteBuild = uploadRemote, resolveCacheProvider = resolveCacheProviderConfig, loadCacheProviderModule = loadCacheProvider, planPrebuildFor = planPrebuild, prebuild = runPrebuild, build = buildAndroid, ccacheFor = resolveCcache, install = installAndroidApp, launch = launchAndroidApp, launchRelease = launchAndroidReleaseApp, verifyReleaseLaunched = verifyAndroidReleaseLaunch, swapApk = swapApkBundle, resolveDevClientScheme = androidDevClientScheme, spawn = (cmd, args, opts) => getExecutor().spawn(cmd, args, opts), kill = (pid, signal) => process.kill(pid, signal), createWriter = createNdjsonWriter, writeLaunch = writeWorkspaceLaunch, writeState = writeWorkspaceState, recordStats = recordRunStats, readEstimates = readRunEstimates, now = Date.now, out = (line) => console.error(line), emit = (line) => console.log(line) } = {}) {
|
|
1997
2248
|
return {
|
|
1998
2249
|
root,
|
|
1999
2250
|
json,
|
|
@@ -2011,6 +2262,7 @@ function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRem
|
|
|
2011
2262
|
resolveEasBuild,
|
|
2012
2263
|
variantFlag,
|
|
2013
2264
|
systemImageFlag,
|
|
2265
|
+
deviceProfileFlag,
|
|
2014
2266
|
deviceFlag,
|
|
2015
2267
|
waitFlag,
|
|
2016
2268
|
waitConflict,
|
|
@@ -2029,6 +2281,7 @@ function resolveRunAndroidOptions({ root, json = false, remoteDevice: commandRem
|
|
|
2029
2281
|
releaseSlot,
|
|
2030
2282
|
ensureDevice,
|
|
2031
2283
|
listSystemImages,
|
|
2284
|
+
listDeviceProfiles,
|
|
2032
2285
|
ensureDeviceBooted,
|
|
2033
2286
|
resolveAvdSerial,
|
|
2034
2287
|
waitForDeviceBoot,
|
|
@@ -2130,7 +2383,7 @@ function avdSetupFailure(error, root, logFile) {
|
|
|
2130
2383
|
};
|
|
2131
2384
|
}
|
|
2132
2385
|
async function runAndroid(options = {}) {
|
|
2133
|
-
let { root, json, commandRemoteBackend, resolveSettingsFor, resolveRemoteDeviceContext, makeRemoteDeviceDeps, resolveEasBin, ensureRemoteMetro, ensureRemoteOwned, detectRemoteProviders, metroCheck, useBuildCache: requestedBuildCache, easProfile, resolveEasBuild, variantFlag, systemImageFlag, deviceFlag, waitFlag, waitConflict, acquireLease, makeRunLease, selectPool, onLeaseSignal, listDevices, deviceModel, deviceAbi, isEmulatorDevice, readApkPackage, getLimits, checkCapacity, acquireSlot, releaseSlot, ensureDevice, listSystemImages, ensureDeviceBooted, resolveAvdSerial, waitForDeviceBoot, resolveMetro, prewarmMetro, startServer, readState, pidAlive, verifyCollector, verifyLaunched, ensureStorage, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, resolveCacheProvider, loadCacheProviderModule, planPrebuildFor, prebuild, build, ccacheFor, install, launch, launchRelease, verifyReleaseLaunched, swapApk, resolveDevClientScheme, spawn, kill, createWriter, writeLaunch, writeState, recordStats, readEstimates, now, out, emit } = androidSlotOptions(options);
|
|
2386
|
+
let { root, json, commandRemoteBackend, resolveSettingsFor, resolveRemoteDeviceContext, makeRemoteDeviceDeps, resolveEasBin, ensureRemoteMetro, ensureRemoteOwned, detectRemoteProviders, metroCheck, useBuildCache: requestedBuildCache, easProfile, resolveEasBuild, variantFlag, systemImageFlag, deviceProfileFlag, deviceFlag, waitFlag, waitConflict, acquireLease, makeRunLease, selectPool, onLeaseSignal, listDevices, deviceModel, deviceAbi, isEmulatorDevice, readApkPackage, getLimits, checkCapacity, acquireSlot, releaseSlot, ensureDevice, listSystemImages, listDeviceProfiles, ensureDeviceBooted, resolveAvdSerial, waitForDeviceBoot, resolveMetro, prewarmMetro, startServer, readState, pidAlive, verifyCollector, verifyLaunched, ensureStorage, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, resolveCacheProvider, loadCacheProviderModule, planPrebuildFor, prebuild, build, ccacheFor, install, launch, launchRelease, verifyReleaseLaunched, swapApk, resolveDevClientScheme, spawn, kill, createWriter, writeLaunch, writeState, recordStats, readEstimates, now, out, emit } = androidSlotOptions(options);
|
|
2134
2387
|
const progress = options.progress ?? NO_BUILD_PROGRESS;
|
|
2135
2388
|
const slot = validateDeviceSlot(options.slot);
|
|
2136
2389
|
const started = now();
|
|
@@ -2203,6 +2456,11 @@ async function runAndroid(options = {}) {
|
|
|
2203
2456
|
let ccacheActivity = CCACHE_NOT_RUN;
|
|
2204
2457
|
let reclaimed = [];
|
|
2205
2458
|
const fail = (code, message, remedy, { lastBuildStatus = false, diagnostics = [], lines = [], logPath = null, lease } = {}) => {
|
|
2459
|
+
const cancellation = cancelledFailure(PLATFORM, {
|
|
2460
|
+
code,
|
|
2461
|
+
message
|
|
2462
|
+
});
|
|
2463
|
+
if (cancellation) ({code, message, remedy, lines} = cancellation);
|
|
2206
2464
|
if (lastBuildStatus) persistLastBuild({
|
|
2207
2465
|
writeState,
|
|
2208
2466
|
root,
|
|
@@ -2266,6 +2524,7 @@ async function runAndroid(options = {}) {
|
|
|
2266
2524
|
easProfile,
|
|
2267
2525
|
variant: variantFlag,
|
|
2268
2526
|
systemImage: systemImageFlag,
|
|
2527
|
+
deviceProfile: deviceProfileFlag,
|
|
2269
2528
|
device: deviceFlag,
|
|
2270
2529
|
wait: waitFlag,
|
|
2271
2530
|
waitConflict,
|
|
@@ -2274,6 +2533,7 @@ async function runAndroid(options = {}) {
|
|
|
2274
2533
|
}, {
|
|
2275
2534
|
resolveCacheProvider,
|
|
2276
2535
|
listSystemImages,
|
|
2536
|
+
listDeviceProfiles,
|
|
2277
2537
|
warn: (label, message) => out(phaseLine(label, chalk.yellow(message)))
|
|
2278
2538
|
});
|
|
2279
2539
|
if (!planned.ok) return fail(planned.code, planned.message, planned.remedy, { lines: planned.lines });
|
|
@@ -2373,6 +2633,7 @@ async function runAndroid(options = {}) {
|
|
|
2373
2633
|
let device;
|
|
2374
2634
|
let bootDuration = "";
|
|
2375
2635
|
let bootPromise;
|
|
2636
|
+
let startRemoteBoot = null;
|
|
2376
2637
|
if (target.kind === "physical" && !target.serial) {
|
|
2377
2638
|
const pooled = await pooledAndroidDevice({
|
|
2378
2639
|
root,
|
|
@@ -2404,6 +2665,11 @@ async function runAndroid(options = {}) {
|
|
|
2404
2665
|
serial: resolved.serial
|
|
2405
2666
|
});
|
|
2406
2667
|
} else {
|
|
2668
|
+
if (!remoteDevice) try {
|
|
2669
|
+
configuredAndroidEmulatorApp();
|
|
2670
|
+
} catch (err) {
|
|
2671
|
+
return fail("STIM_BAD_ARG", err.message, "Run `stim settings set androidEmulatorApp emulator` or `stim settings set androidEmulatorApp stim-desktop`.");
|
|
2672
|
+
}
|
|
2407
2673
|
const capacity = checkCapacity({
|
|
2408
2674
|
platform: PLATFORM,
|
|
2409
2675
|
project,
|
|
@@ -2418,7 +2684,10 @@ async function runAndroid(options = {}) {
|
|
|
2418
2684
|
projectPath: root,
|
|
2419
2685
|
settingsRoot,
|
|
2420
2686
|
settings,
|
|
2421
|
-
flags: {
|
|
2687
|
+
flags: {
|
|
2688
|
+
systemImage: target.systemImage,
|
|
2689
|
+
deviceProfile: target.deviceProfile
|
|
2690
|
+
},
|
|
2422
2691
|
note: out,
|
|
2423
2692
|
out,
|
|
2424
2693
|
logFile: emuLog
|
|
@@ -2429,7 +2698,6 @@ async function runAndroid(options = {}) {
|
|
|
2429
2698
|
}
|
|
2430
2699
|
const prepareMs = prepare();
|
|
2431
2700
|
if (device.created || prepareMs >= 2e3) phase("device", `${device.avdName || device.deviceName || label} ${device.created ? "created" : "prepared"} (${formatDuration(prepareMs)})`);
|
|
2432
|
-
const bootTimer = stepTimer(now);
|
|
2433
2701
|
const boot = () => Promise.resolve(ensureDeviceBooted({
|
|
2434
2702
|
platform: PLATFORM,
|
|
2435
2703
|
device,
|
|
@@ -2441,41 +2709,31 @@ async function runAndroid(options = {}) {
|
|
|
2441
2709
|
reason: String(e?.message || e),
|
|
2442
2710
|
serial: void 0
|
|
2443
2711
|
}));
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
if (remoteDevice) {
|
|
2461
|
-
const booted = await bootPromise;
|
|
2462
|
-
if (booted.failed) {
|
|
2463
|
-
if (booted.code) return fail(booted.code, booted.reason ?? "The remote device did not boot.", booted.remedy ?? null);
|
|
2464
|
-
const diag = noDeviceDiagnostic({
|
|
2465
|
-
reason: booted.reason ?? "The remote device did not boot.",
|
|
2466
|
-
logFile: emuLog,
|
|
2467
|
-
remedy: "Run `stim status` to inspect the remote device, then retry the command.",
|
|
2468
|
-
localEmulator: false
|
|
2469
|
-
});
|
|
2470
|
-
return fail(NO_DEVICE, diag.message, diag.remedy, {
|
|
2471
|
-
lines: diag.lines,
|
|
2472
|
-
logPath: diag.logPath ? displayPath(root, diag.logPath) : null
|
|
2712
|
+
const startBoot = () => {
|
|
2713
|
+
const bootTimer = stepTimer(now);
|
|
2714
|
+
return (remoteDevice?.ctx.backend === "eas" ? ensureRemoteOwned({
|
|
2715
|
+
root,
|
|
2716
|
+
platform: PLATFORM,
|
|
2717
|
+
sessionName: ownedSessionName(remoteDevice.ctx.label),
|
|
2718
|
+
startedAt: new Date(now()).toISOString(),
|
|
2719
|
+
boot,
|
|
2720
|
+
createdSessionId: remoteDevice.createdSessionId,
|
|
2721
|
+
abandonCreatedSession: remoteDevice.abandonCreatedSession,
|
|
2722
|
+
webPreviewUrl: remoteDevice.webPreviewUrl,
|
|
2723
|
+
writeState,
|
|
2724
|
+
register: registerProject
|
|
2725
|
+
}) : boot()).then((result) => {
|
|
2726
|
+
bootDuration = bootTimer();
|
|
2727
|
+
return result;
|
|
2473
2728
|
});
|
|
2474
|
-
}
|
|
2729
|
+
};
|
|
2730
|
+
if (remoteDevice) startRemoteBoot = startBoot;
|
|
2731
|
+
else bootPromise = startBoot();
|
|
2475
2732
|
}
|
|
2476
2733
|
record.avdName = device.avdName ?? null;
|
|
2477
2734
|
record.deviceName = device.deviceName ?? device.avdName ?? null;
|
|
2478
2735
|
record.systemImage = device.systemImage;
|
|
2736
|
+
record.deviceProfile = device.deviceProfile;
|
|
2479
2737
|
const runFromFingerprint = async () => {
|
|
2480
2738
|
if (metroCheck && metroPort !== null && plan.metroWarmup) prewarmMetro({
|
|
2481
2739
|
port: metroPort,
|
|
@@ -2542,6 +2800,25 @@ async function runAndroid(options = {}) {
|
|
|
2542
2800
|
ccacheActivity = artifact.ccache;
|
|
2543
2801
|
androidPackage = artifact.androidPackage;
|
|
2544
2802
|
record.appPath = apkPath;
|
|
2803
|
+
if (runCancellation()) return fail("STIM_CANCELLED", "before install");
|
|
2804
|
+
if (startRemoteBoot) {
|
|
2805
|
+
progress.step("install");
|
|
2806
|
+
bootPromise = startRemoteBoot();
|
|
2807
|
+
const booted = await bootPromise;
|
|
2808
|
+
if (booted.failed) {
|
|
2809
|
+
if (booted.code) return fail(booted.code, booted.reason ?? "The remote device did not boot.", booted.remedy ?? null);
|
|
2810
|
+
const diag = noDeviceDiagnostic({
|
|
2811
|
+
reason: booted.reason ?? "The remote device did not boot.",
|
|
2812
|
+
logFile: emuLog,
|
|
2813
|
+
remedy: "Run `stim status` to inspect the remote device, then retry the command.",
|
|
2814
|
+
localEmulator: false
|
|
2815
|
+
});
|
|
2816
|
+
return fail(NO_DEVICE, diag.message, diag.remedy, {
|
|
2817
|
+
lines: diag.lines,
|
|
2818
|
+
logPath: diag.logPath ? displayPath(root, diag.logPath) : null
|
|
2819
|
+
});
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2545
2822
|
let leaseHandle = null;
|
|
2546
2823
|
let stopLeaseSignals = null;
|
|
2547
2824
|
const releaseLease = () => {
|