stim 1.17.2 → 1.19.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/README.md +50 -1
- package/dist/{activity-IRvJY_ru.mjs → activity-BSw0x84R.mjs} +4 -4
- package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-Bjxu_VmX.mjs} +8 -8
- package/dist/{android-B9yaNKwa.mjs → android-BXc6BmEi.mjs} +658 -404
- package/dist/{android-B_YNZy61.mjs → android-BdQC6zs1.mjs} +9 -9
- package/dist/android-BvV1gGdN.mjs +4 -0
- package/dist/{android-DE4v59Mb.mjs → android-DE5g_5gv.mjs} +2 -2
- package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-C87geAg-.mjs} +5 -5
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/api-DIf_s86s.mjs +150 -0
- package/dist/api-run.d.mts +1 -0
- package/dist/api-run.mjs +145 -0
- package/dist/api.d.mts +218 -0
- package/dist/api.mjs +2 -0
- package/dist/{app-install-VPkI5WEg.mjs → app-install-CFI4ptUL.mjs} +33 -13
- package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
- package/dist/{web-Dl0KSRHf.mjs → browser-web-CDhqQxhv.mjs} +138 -176
- package/dist/{budget-DfcgFdQB.mjs → budget-Dz-kyXLv.mjs} +1391 -58
- package/dist/build-facts-B87vo-Im.d.mts +142 -0
- package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-DiwKSyv9.mjs} +3 -3
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-BrcVWQyD.mjs → chrome-BTUOo8p2.mjs} +1 -1
- package/dist/cli-C9Zvgbdc.mjs +68 -0
- package/dist/cli.mjs +1 -1
- package/dist/{client-SvBdgObD.mjs → client-CuUo8Nvg.mjs} +381 -49
- package/dist/collector-run.d.mts +6 -0
- package/dist/collector-run.mjs +9 -9
- package/dist/{command-output-CDAIFD-8.mjs → command-output-Bt8ygHE7.mjs} +2 -2
- package/dist/{config-D0DbpZtM.mjs → config-DC5jEtd1.mjs} +9 -5
- package/dist/{created-devices-CpvzBL25.mjs → created-devices-D0s26Hx5.mjs} +2 -2
- package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-DKaS1OM9.mjs} +2 -2
- package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-pB_IPfV4.mjs} +1 -1
- package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CDY_zAmD.mjs} +2 -2
- package/dist/{device-C8IOoJPv.mjs → device-BHw0WlHl.mjs} +8 -8
- package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-BoN1jQkO.mjs} +25 -14
- package/dist/device-host-worker.mjs +19 -19
- package/dist/{gradle-dJpre3Yn.mjs → device-ios-B2ruohE-.mjs} +661 -107
- package/dist/{device-lease-DpoS36_u.mjs → device-lease-Cu7PtQpZ.mjs} +9 -9
- package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-D38SnZtt.mjs} +4 -4
- package/dist/{device-pool-3o7s5lo4.mjs → device-pool-CP4rAsHx.mjs} +3 -3
- package/dist/{device-remote-hFSkpfQu.mjs → device-remote-B5GiUifk.mjs} +15 -16
- package/dist/{doctor-CFv1fCrF.mjs → doctor-PRJH94v6.mjs} +61 -34
- package/dist/doctor-watchman-wZhyTdp4.mjs +259 -0
- package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics--v5HGOU0.mjs} +11 -11
- package/dist/{exec-CaErVv7t.mjs → exec-i8GDPwq9.mjs} +93 -6
- package/dist/{gc-DEmkg3Xh.mjs → gc-CyHMcKcn.mjs} +25 -471
- package/dist/{guide-CSmhMTf8.mjs → guide-dRaQJJk9.mjs} +681 -507
- package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bs7fytj7.mjs} +3 -3
- package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C5G4h_OJ.mjs} +2 -2
- package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-Bik035eL.mjs} +1 -1
- package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-CI9Az9a4.mjs} +9 -9
- package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-DABm3ScO.mjs} +5 -5
- package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DbV2aUVw.mjs} +13 -9
- package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-DYiMBn34.mjs} +7 -8
- package/dist/{ios-DSfnPfse.mjs → ios-BWbHFZVz.mjs} +19 -7
- package/dist/{ios-Cr1h5gnO.mjs → ios-DCrkgXEM.mjs} +1 -1
- package/dist/ios-DYUr9LGc.mjs +8 -0
- package/dist/ios-ITYno9rO.mjs +2241 -0
- package/dist/{ios-device-pAN4t54-.mjs → ios-device-CJ_ZOGky.mjs} +3 -3
- package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-CrW8aMb5.mjs} +1 -1
- package/dist/{ios-state-8L3lgum6.mjs → ios-state-By0XuLTQ.mjs} +1 -1
- package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-DCveSE6d.mjs} +5 -5
- package/dist/{logs-BAaS7gS2.mjs → logs-Bao1HOMy.mjs} +13 -13
- package/dist/{macos-BIRQS90f.mjs → macos-ciyBdTY5.mjs} +194 -132
- package/dist/macos-nIOATJmR.mjs +2 -0
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +349 -47
- package/dist/manifest-CX0d1IkZ.mjs +148 -0
- package/dist/{metro-g8NqiJp-.mjs → metro-DI2AjPF_.mjs} +196 -43
- package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-BxpJLIwh.mjs} +4 -4
- package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
- package/dist/{build-plan-BDsSi09V.mjs → miss-reason-CjQCOKqq.mjs} +207 -249
- package/dist/{named-ports-C8m8EQs2.mjs → named-ports-B4iWH4E-.mjs} +70 -8
- package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-BGxsbfny.mjs} +6 -6
- package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
- package/dist/offload-worker.d.mts +3 -45
- package/dist/offload-worker.mjs +11 -11
- package/dist/{ownership-DyRQru0q.mjs → ownership-EB0ySdGK.mjs} +3 -3
- package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
- package/dist/placement-log-Dxe34rJm.mjs +88 -0
- package/dist/plan-placement-BVY59qa8.mjs +290 -0
- package/dist/{ports-4nYqxPWC.mjs → ports-ByPc0_97.mjs} +3 -3
- package/dist/{prebuild-D7RUMkwN.mjs → prebuild-BKJ3wJI1.mjs} +5 -5
- package/dist/preview-BbSottmO.mjs +986 -0
- package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
- package/dist/project-B5eQ1USs.mjs +612 -0
- package/dist/{pull-request-pxnDCQzn.mjs → pull-request-IHNdMnG8.mjs} +1 -1
- package/dist/pull-requests.mjs +1 -1
- package/dist/react-native-ios-BMh2i25I.mjs +2 -0
- package/dist/react-native-ios-CSpIxexZ.mjs +2083 -0
- package/dist/{recordings-BNgsD1Tr.mjs → recordings-Bv8McZN4.mjs} +1 -1
- package/dist/{reload-DcRxj3qG.mjs → reload-rAPdqeRR.mjs} +14 -15
- package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-N3hAEaAL.mjs} +5 -5
- package/dist/{run-CkE9y0nc.mjs → run-lAkle1-c.mjs} +5 -5
- package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-CkIjnegq.mjs} +5 -6
- package/dist/server-expo-DGsdUGX2.mjs +2 -0
- package/dist/{server-expo-CHTyXD0G.mjs → server-expo-n3tUi3Em.mjs} +5 -6
- package/dist/{settings-SR9OmW9h.mjs → settings-2am7TSxp.mjs} +5 -5
- package/dist/{settings-Cfd-0r2d.mjs → settings-CxgngUZk.mjs} +116 -103
- package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
- package/dist/settings.schema.json +198 -9
- package/dist/{simslim-BWNrc3M3.mjs → simslim-D9LkJxIO.mjs} +7 -7
- package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-HV_KtPIw.mjs} +6 -6
- package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
- package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
- package/dist/{stage-CzaiwFsI.mjs → stage-BgaZJVZY.mjs} +14 -3
- package/dist/{start-AlfCPRVU.mjs → start-D8NbxNBb.mjs} +1 -1
- package/dist/{start-DUz3mYdb.mjs → start-DtxthMfI.mjs} +34 -27
- package/dist/{state-PeQiJuIu.mjs → state-D2KtnALG.mjs} +4 -4
- package/dist/{state-DyaNTgfR.mjs → state-Tp4uImDS.mjs} +5 -3
- package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
- package/dist/{stats-Bq4fJOdB.mjs → stats-8EJ5ivFT.mjs} +6 -6
- package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
- package/dist/{status-BA2pehwf.mjs → status-BOyp0CUl.mjs} +31 -34
- package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-C65jk_q2.mjs} +1 -1
- package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-DbmUjsLv.mjs} +1 -1
- package/dist/stop-D0UIpZuh.mjs +72 -0
- package/dist/{stop-zF1y04f2.mjs → stop-DRipAg-e.mjs} +2 -2
- package/dist/{stop-DQIasgKp.mjs → stop-zDlknFoz.mjs} +79 -33
- package/dist/supervisor-run.d.mts +24 -22
- package/dist/supervisor-run.mjs +21 -22
- package/dist/{support-CsJNVfOc.mjs → support-CNqYkV0y.mjs} +7 -7
- package/dist/{support-WvD__tSV.mjs → support-DsNaFg6D.mjs} +5 -5
- package/dist/swiftpm-macos-aJzPAj1t.mjs +119 -0
- package/dist/{toolchain-DNyR3NPq.mjs → toolchain-C3xSoyUl.mjs} +475 -269
- package/dist/{trigger-Bemu8ytw.mjs → trigger-CAhmG-4s.mjs} +6 -6
- package/dist/trigger-CoalsMTV.mjs +2 -0
- package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-pFLB2e6P.mjs} +135 -38
- package/dist/{status-CzS4bPO9.mjs → watchman-BL1IdOtq.mjs} +75 -7
- package/dist/web-DFpFeZu5.mjs +2 -0
- package/dist/web-DbbrPUn0.mjs +127 -0
- package/dist/web-run.mjs +10 -10
- package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-CR9X86xJ.mjs} +3 -3
- package/dist/{ownership-BMLqyBgJ.mjs → workspaces-Djb2gfi9.mjs} +661 -23
- package/dist/{worktree-Be_7NLKy.mjs → worktree-BL4M1rhB.mjs} +252 -50
- package/dist/{worktree-j3IcFAI5.mjs → worktree-DV-A0LNL.mjs} +1 -1
- package/package.json +10 -5
- package/shim/bundle-response.cjs +2 -1
- package/shim/bundle-response.d.cts +1 -1
- package/shim/expo-metro-config.cjs +1 -1
- package/dist/build-progress-D0WkjCPd.mjs +0 -1036
- package/dist/build-slots-41v_d2x9.mjs +0 -142
- package/dist/cli-CYXb29oE.mjs +0 -51
- package/dist/deps-iKw0eD4P.mjs +0 -438
- package/dist/device-ios-C2Um-XUR.mjs +0 -412
- package/dist/errors-B6W7FkxQ.mjs +0 -15
- package/dist/guide-status-Du-ZQ3FD.mjs +0 -125
- package/dist/idle-BXG__1BA.mjs +0 -176
- package/dist/in-use-CvGOUn-x.mjs +0 -130
- package/dist/ios-BJ4XUSe1.mjs +0 -3867
- package/dist/native-run-D1Q56rAD.mjs +0 -158
- package/dist/preview-B-g9d7kV.mjs +0 -318
- package/dist/process-identity-BmRm1qV0.mjs +0 -12
- package/dist/project-D47Rh0ly.mjs +0 -276
- package/dist/server-expo-CeakhI8P.mjs +0 -2
- package/dist/state-BKa8wNN5.mjs +0 -148
- package/dist/stop-BIiM49EY.mjs +0 -48
- package/dist/stop-cause-rhmGfwvt.mjs +0 -97
- package/dist/trigger-CXts6qt1.mjs +0 -2
- package/dist/watchman-APYjXSQa.mjs +0 -48
- package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
- package/dist/workspaces-Bcib97-6.mjs +0 -306
|
@@ -1,53 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { n as ownership_claim_exports } from "./process-identity-Biv3arCO.mjs";
|
|
2
|
+
import { t as getExecutor } from "./exec-i8GDPwq9.mjs";
|
|
3
|
+
import { t as spawnEntry } from "./spawn-entry-Dcb7sDUz.mjs";
|
|
4
4
|
import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
5
|
-
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-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { m as
|
|
14
|
-
import { $ as trimAndroidCaches, A as listAvds, B as ownedAvdSystemImage, D as hostSystemImageArch, F as ownedAvdDeviceProfile, G as probeEmulatorSerial, I as ownedAvdDirectory, J as resolveOwnedAvdSerial, K as profileNeedsFoldFeature, O as listAdbDevices, Q as systemImageSupportsFold, T as findBuildTool, U as physicalDeviceModel, W as pickDefaultSystemImage, Y as resolvePhysicalDevice, a as androidDeviceAbi, ft as parkedMaxSetting, i as androidDataFreeBytes, j as listInstalledSystemImages, k as listAvdDeviceProfiles, q as resetAdoptedAvd, r as androidBuildToolName, rt as configuredAndroidEmulatorApp, t as DEFAULT_AVD_DEVICE_PROFILE, tt as waitForBoot, u as androidToolCwd } from "./android-
|
|
15
|
-
import { a as workspaceLinks, i as workspaceLinkLine } from "./stim-desktop-
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { r as
|
|
19
|
-
import {
|
|
20
|
-
import { t as
|
|
21
|
-
import {
|
|
22
|
-
import { r as hostedMetroSettings } from "./metro-gateway-
|
|
23
|
-
import {
|
|
24
|
-
import { n as
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import { t as
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { a as
|
|
31
|
-
import { a as
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import { a as
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import { i as
|
|
42
|
-
import { t as
|
|
43
|
-
import {
|
|
44
|
-
import { n as resolveAndroidCas, r as resolveAndroidCompilerCache } from "./android-cas-ZFpjJBL_.mjs";
|
|
5
|
+
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-Bt8ygHE7.mjs";
|
|
6
|
+
import { C as saveConfig, D as withConfigLock$1, E as upsertProject, L as deviceSlotFileKey, R as deviceSlotKey, V as parseDeviceSlotOption, W as validateDeviceSlot, _ as loadConfig$1, j as formatBytes, p as getProject, u as getConcurrencyLimits, w as setDevice, z as deviceSlotPlatforms } from "./config-DC5jEtd1.mjs";
|
|
7
|
+
import { c as writeWorkspaceState, g as workspaceAgentDeviceDir, i as recordWorkspaceUse, l as emulatorLogFile, r as readWorkspaceState$1, v as workspaceDir, x as workspaceLogsDir$1 } from "./workspace-state-CR9X86xJ.mjs";
|
|
8
|
+
import { M as writeWorkspaceLaunch, b as MODE_EXPO, c as projectShortcut, p as detectIsExpo, r as findProjectRoot, s as projectProblem, t as NO_PROJECT_REFUSAL, y as MODE_BARE } from "./project-B5eQ1USs.mjs";
|
|
9
|
+
import { A as publicUrlSetting, B as settingShapeErrors, C as metroWarmupUrlSetting, Ct as removeTemporaryEntry, Dt as optimizationBuildProfile, Et as compilerCacheFallbackMessage, F as resolveCacheProviderConfig, H as settingsLayers, I as resolveSettings, L as settingFile, M as remoteAndroidSetting, N as remoteEasFallbackSetting, Ot as resolveOptimizations, St as makeTemporaryDirectory, T as parseIosRemote, Tt as artifactCachePolicy, U as tunnelModeSetting, W as unknownSettingKeys, i as SETTING_SHAPE_REMEDY, l as androidDataPartitionSizeGbSettingError, mt as repoRoot, nt as gitCommonDir, o as androidAvdConfigSettingError, q as detectProviders, u as cacheProviderSettingError, x as metroPortSetting, z as settingOriginScope } from "./settings-CxgngUZk.mjs";
|
|
10
|
+
import { d as signalProcessTree, s as pidExists, u as resolveProjectMetro } from "./metro-DI2AjPF_.mjs";
|
|
11
|
+
import { F as recordFinishedBuild, I as startBuildProgress, L as tapBuildLog, O as NO_BUILD_PROGRESS, R as createRunRecorder, U as recordRunStats, V as recordCapacityRefusal, W as statsProjectKey$1, t as budgetGate, z as readRunEstimates } from "./budget-Dz-kyXLv.mjs";
|
|
12
|
+
import { D as teardownOwnedAvd, M as acquireBuildSlot, P as releaseBuildSlot } from "./workspaces-Djb2gfi9.mjs";
|
|
13
|
+
import { A as providerDownloadPath, B as captureAssetManifest, D as fingerprintProject, E as fingerprintDiffRecord, F as storedAssetManifest, H as readAssetManifest, L as untrackedMissLine, M as refingerprintAfterMutation, N as resolveBuild, O as inputsChangedDuringBuild, P as storeBuild, R as untrackedNativeFiles, S as configInputsChanged, T as filesystemBuildCapability, V as compareAssetManifests, _ as waitForBuild, b as buildCacheKey, g as releaseBuildLock, j as providerUploadOutcome, k as prepareProviderDownloadDir, m as acquireBuildLock, v as waitForSharedBuild, x as changedDuringBuildLine, z as assetDiffReason } from "./device-lease-Cu7PtQpZ.mjs";
|
|
14
|
+
import { $ as trimAndroidCaches, A as listAvds, B as ownedAvdSystemImage, D as hostSystemImageArch, F as ownedAvdDeviceProfile, G as probeEmulatorSerial, I as ownedAvdDirectory, J as resolveOwnedAvdSerial, K as profileNeedsFoldFeature, O as listAdbDevices, Q as systemImageSupportsFold, T as findBuildTool, U as physicalDeviceModel, W as pickDefaultSystemImage, Y as resolvePhysicalDevice, a as androidDeviceAbi, ft as parkedMaxSetting, i as androidDataFreeBytes, j as listInstalledSystemImages, k as listAvdDeviceProfiles, l as androidSystemImageAbi, q as resetAdoptedAvd, r as androidBuildToolName, rt as configuredAndroidEmulatorApp, t as DEFAULT_AVD_DEVICE_PROFILE, tt as waitForBoot, u as androidToolCwd } from "./android-BdQC6zs1.mjs";
|
|
15
|
+
import { a as workspaceLinks, i as workspaceLinkLine } from "./stim-desktop-C65jk_q2.mjs";
|
|
16
|
+
import { r as createNdjsonWriter } from "./ndjson-LGZAMsqa.mjs";
|
|
17
|
+
import { A as resolveBuildPlacement, C as setRemoteLogSink, D as parseBuildMachineOption, E as namedBuildMachine, O as requireLocalBuild, S as withNativeBuildRun, a as offloadBuild, b as runCancellation, c as placementLoad, i as closeOffload, l as remotePhaseText, n as buildPlacementCandidates, p as cancelledFailure, r as chooseBuildMachine, s as offloadPlacement, w as OffloadRefusal, x as runCancellationSignal } from "./client-CuUo8Nvg.mjs";
|
|
18
|
+
import { n as DeviceAdmissionRefusal, r as checkDeviceCapacity, t as DEFAULT_DEVICE_SLOT_WAIT_MS } from "./device-capacity-BoN1jQkO.mjs";
|
|
19
|
+
import { i as ccacheActivityLine, n as CCACHE_NOT_RUN, r as CCACHE_UNAVAILABLE, s as resolveCcache } from "./manifest-CX0d1IkZ.mjs";
|
|
20
|
+
import { E as startBuildHeartbeat, O as tailLines, h as HEARTBEAT_INTERVAL_MS, n as androidToolchain, t as androidRequirements } from "./toolchain-C3xSoyUl.mjs";
|
|
21
|
+
import { t as cleanLine } from "./server-expo-n3tUi3Em.mjs";
|
|
22
|
+
import { r as hostedMetroSettings } from "./metro-gateway-BxpJLIwh.mjs";
|
|
23
|
+
import { a as writeHostedAndroid, i as writeDevicePlacement, t as readHostedAndroid } from "./ios-state-By0XuLTQ.mjs";
|
|
24
|
+
import { _ as devicePlacementLine, a as UPDATES_MANIFEST_NAME, d as ensureOwnedDevice, f as AvdBootError, g as automaticDevicePlacement, h as checkEasFallback, i as skippedMissReason, l as didSetUpDevice, m as warmMetro, n as fingerprintErrorMissReason, o as detectEntryFile, p as AvdRecoveryError, s as refreshUpdatesManifestFile, t as explainBuildMiss, u as ensureBooted } from "./miss-reason-CjQCOKqq.mjs";
|
|
25
|
+
import { n as devicePlacementRecord, t as buildPlacementRecord } from "./placement-log-Dxe34rJm.mjs";
|
|
26
|
+
import { n as prepareHostedAndroid, t as placeHostedAndroid } from "./hosted-android-Bs7fytj7.mjs";
|
|
27
|
+
import { S as restartedAppNote, b as launchAndroidReleaseApp, c as androidDevClientUrl, g as installConflictKind, h as installAndroidApp, r as DEFAULT_METRO_PORT, s as androidAppProcess, t as ADB_INSTALL_TIMEOUT_MS, y as launchAndroidApp } from "./app-install-CFI4ptUL.mjs";
|
|
28
|
+
import { n as nativeRunCommand, r as siblingPlatformSlots, t as launchSlotScope } from "./slot-launch-HV_KtPIw.mjs";
|
|
29
|
+
import { a as VERIFY_TIMEOUT_MS, d as verifyAndroidReleaseLaunch, f as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unattributedLaunchLines, n as LAUNCH_FATAL, r as LAUNCH_UNVERIFIED, t as LAUNCH_BUNDLING, u as unverifiedLaunchLines } from "./launch-verify-DCveSE6d.mjs";
|
|
30
|
+
import { a as easAuthNote, c as loadProjectProvider, f as resolveEasCliBin, i as checkEasAuth, m as uploadRemote, n as UPLOAD_TIMEOUT_MS, o as exitAfterFlush, p as resolveRemote, r as cacheLevel, s as isEasAuthFailureText, t as RESOLVE_TIMEOUT_MS } from "./remote-cache-N3hAEaAL.mjs";
|
|
31
|
+
import { C as resolveSystemImage, S as resolveDeviceProfile, T as systemImageRefusal, _ as isReleaseVariant, a as PLATFORM, b as pooledAndroidDevice, d as apkPackage, f as deviceProfileRefusal, g as foldableImageRefusal, i as NO_FINGERPRINT, m as dumpApkManifest, n as LAUNCH_FAILED, o as androidBuildOptions, p as displayPath, r as NO_DEVICE, s as androidDevClientScheme, t as INSTALL_FAILED, v as noDeviceDiagnostic, w as resolveVariant, x as remoteAvdFlagRefusal } from "./support-DsNaFg6D.mjs";
|
|
32
|
+
import { d as productFlavorRefusal, f as readProductFlavors, h as formatDiagnostic, o as buildAndroid } from "./device-ios-B2ruohE-.mjs";
|
|
33
|
+
import { T as ownedSessionName, a as ensureMetroReachable, c as remoteAndroidDeps, n as binOnPath, o as ensureRemoteBootOwned, u as resolveRemoteContext } from "./device-remote-B5GiUifk.mjs";
|
|
34
|
+
import { a as isEasBuildFailure, o as planEasDevelopmentBuild, s as resolveEasDevelopmentBuild } from "./simslim-D9LkJxIO.mjs";
|
|
35
|
+
import { c as startDevServer, m as detectAppIds, p as detectAndroidPackage } from "./start-DtxthMfI.mjs";
|
|
36
|
+
import { a as acquireRunLease, c as lostRefusal, d as runLease, f as waitFlagConflict, l as parseDeviceWait, o as leaseExpiryText, s as lostLine, t as DEBUG_VERIFY_STEP_MS, u as releaseLeaseOnSignal } from "./device-lease-run-D38SnZtt.mjs";
|
|
37
|
+
import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-EB0ySdGK.mjs";
|
|
38
|
+
import { i as launchOutcomeRecord, n as ensureWorkspaceStorageSafely, r as isPhysicalDeviceRequest, t as ensureDevServer } from "./native-runtime-BGxsbfny.mjs";
|
|
39
|
+
import { t as selectFromPool } from "./device-pool-CP4rAsHx.mjs";
|
|
40
|
+
import { i as staleNativeDirRefusal, n as recordPrebuild, r as runPrebuild, t as planPrebuild } from "./prebuild-BKJ3wJI1.mjs";
|
|
41
|
+
import { a as printPlan, i as planPayload, n as planCachedBuild, o as refusePlan, r as planFlagRefusal, s as runArtifactLifecycle, t as planHostedDevice } from "./plan-placement-BVY59qa8.mjs";
|
|
42
|
+
import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics--v5HGOU0.mjs";
|
|
43
|
+
import { n as resolveAndroidCas, r as resolveAndroidCompilerCache } from "./android-cas-C87geAg-.mjs";
|
|
45
44
|
import { constants, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync } from "node:fs";
|
|
46
45
|
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
47
|
-
import { workspaceId } from "@stim-cli/core";
|
|
48
|
-
import { InvalidArgumentError } from "commander";
|
|
49
46
|
import { buildDiagnostics, hostedAndroidStatus, machineCapacity, parseMachine } from "@stim-cli/core/state";
|
|
50
47
|
import chalk from "chalk";
|
|
48
|
+
import { InvalidArgumentError } from "commander";
|
|
49
|
+
import { workspaceId } from "@stim-cli/core";
|
|
51
50
|
import { createWarnOnce, loadCacheProvider, resolveTieredBuild, storeTieredBuild } from "@stim-cli/cache";
|
|
52
51
|
//#region src/commands/android/remote.ts
|
|
53
52
|
async function connectAndroidHosting({ root, slot, machine, release, metroCheck, selectors, read = readHostedAndroid, resolveSerial = resolveOwnedAvdSerial, prepare = prepareHostedAndroid }) {
|
|
@@ -93,7 +92,7 @@ async function connectAndroidHosting({ root, slot, machine, release, metroCheck,
|
|
|
93
92
|
} };
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
|
-
async function selectAndroidPlacement({ target: selected, automatic = automaticDevicePlacement, checkBudget = budgetGate, note, phase, noWait, buildMachine, localSelectors, ...args }) {
|
|
95
|
+
async function selectAndroidPlacement({ target: selected, automatic = automaticDevicePlacement, checkBudget = budgetGate, note, phase, log, fromFlag, noWait, buildMachine, localSelectors, eas, ...args }) {
|
|
97
96
|
const selectors = selected.kind === "hosted" ? {
|
|
98
97
|
...selected.systemImage ? { systemImage: selected.systemImage } : {},
|
|
99
98
|
...selected.deviceProfile ? { deviceProfile: selected.deviceProfile } : {}
|
|
@@ -127,9 +126,31 @@ async function selectAndroidPlacement({ target: selected, automatic = automaticD
|
|
|
127
126
|
platform: "android",
|
|
128
127
|
selectors,
|
|
129
128
|
buildMachine,
|
|
130
|
-
noWait
|
|
129
|
+
noWait,
|
|
130
|
+
...eas ? { eas } : {}
|
|
131
131
|
});
|
|
132
132
|
phase("placement:", devicePlacementLine(placed.placement, placed.skipped));
|
|
133
|
+
log?.(devicePlacementRecord({
|
|
134
|
+
platform: "android",
|
|
135
|
+
fromFlag,
|
|
136
|
+
easFallback: Boolean(eas),
|
|
137
|
+
placed
|
|
138
|
+
}));
|
|
139
|
+
if (placed.placement.decision === "eas") return {
|
|
140
|
+
target: {
|
|
141
|
+
kind: "remote",
|
|
142
|
+
backend: "eas",
|
|
143
|
+
systemImage: selected.systemImage,
|
|
144
|
+
deviceProfile: selected.deviceProfile
|
|
145
|
+
},
|
|
146
|
+
hostedTarget: null,
|
|
147
|
+
selectors,
|
|
148
|
+
budget: await checkBudget({
|
|
149
|
+
root: args.root,
|
|
150
|
+
note
|
|
151
|
+
}),
|
|
152
|
+
devicePlacement: placed.placement
|
|
153
|
+
};
|
|
133
154
|
if (placed.target && !args.release && !args.metroCheck) return { failure: {
|
|
134
155
|
code: "STIM_BAD_ARG",
|
|
135
156
|
message: "Hosted Debug runs require the local Metro supervisor; --no-metro-check cannot be used.",
|
|
@@ -340,7 +361,7 @@ function persistLastBuild({ recordBuild = recordFinishedBuild, root, record, sta
|
|
|
340
361
|
}
|
|
341
362
|
//#endregion
|
|
342
363
|
//#region src/commands/android/hosted.ts
|
|
343
|
-
async function finishHostedAndroidRun({ target, artifact, root, slot = "default", release, isExpo, metroPort, logsDir, selectors, place, writePlacement, verifyLaunch: verify, writeLaunch, readApkPackage, resolveDevClientScheme, now, started, startedAt, fail, phase, out, recordBuild, ...report }) {
|
|
364
|
+
async function finishHostedAndroidRun({ target, artifact, root, slot = "default", release, isExpo, metroPort, logsDir, selectors, place, writePlacement, verifyLaunch: verify, writeLaunch, readApkPackage, resolveDevClientScheme, now, started, startedAt, fail, phase, enterPhase, out, recordBuild, ...report }) {
|
|
344
365
|
const packageName = artifact.androidPackage ?? readApkPackage(artifact.apkPath);
|
|
345
366
|
if (!artifact.apkPath || !packageName) return fail("STIM_INSTALL_FAILED", "The built APK has no package identity.");
|
|
346
367
|
const launchedAt = now();
|
|
@@ -356,7 +377,8 @@ async function finishHostedAndroidRun({ target, artifact, root, slot = "default"
|
|
|
356
377
|
selectors,
|
|
357
378
|
...!release && isExpo ? { devClientScheme: resolveDevClientScheme(root, artifact.apkPath) ?? void 0 } : {},
|
|
358
379
|
reserved: (placement) => writePlacement(root, slot, placement),
|
|
359
|
-
note: out
|
|
380
|
+
note: out,
|
|
381
|
+
enterPhase
|
|
360
382
|
});
|
|
361
383
|
writePlacement(root, slot, run.placement);
|
|
362
384
|
writeLaunch(root, "android", {
|
|
@@ -803,14 +825,33 @@ function fail$1(code, message, remedy, extra = {}) {
|
|
|
803
825
|
extra
|
|
804
826
|
};
|
|
805
827
|
}
|
|
828
|
+
var ArtifactRefusal = class extends Error {
|
|
829
|
+
failure;
|
|
830
|
+
constructor(failure) {
|
|
831
|
+
super(failure.message ?? failure.code);
|
|
832
|
+
this.failure = failure;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
806
835
|
async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo, device, physical, hostedAbi, remote: remoteTarget, buildPlan, cacheProviderConfig, requestedBuildCache, easBuild, androidPackage: initialPackage, record, maxBuilds, progress }, { deviceAbi, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, loadCacheProviderModule, acquireSlot, releaseSlot, planPrebuildFor, prebuild, build, ccacheFor, swapApk, readState, now }) {
|
|
807
836
|
const { phase, out, estimates, stats, step, miss, hit: lateHit, place, waitingOn, waitingFor } = progress;
|
|
808
837
|
let fallbackMachine = null;
|
|
809
838
|
let hereReason = "no remote Mac is paired";
|
|
810
839
|
let slotWaitMs;
|
|
811
840
|
const buildMachine = record.buildMachine ?? "auto";
|
|
812
|
-
const fallBack = (reason, line = reason) => {
|
|
841
|
+
const fallBack = (reason, line = reason, info = {}) => {
|
|
842
|
+
writer.write(buildPlacementRecord({
|
|
843
|
+
platform: PLATFORM,
|
|
844
|
+
buildMachine,
|
|
845
|
+
candidates: info.candidates,
|
|
846
|
+
event: "placement_fallback",
|
|
847
|
+
fallback: {
|
|
848
|
+
code: info.code ?? "fallback",
|
|
849
|
+
reason,
|
|
850
|
+
machine: info.machine
|
|
851
|
+
}
|
|
852
|
+
}));
|
|
813
853
|
if (namedBuildMachine(buildMachine)) throw new OffloadRefusal(buildMachine, reason);
|
|
854
|
+
requireLocalBuild(buildMachine);
|
|
814
855
|
record.offloadFallback = reason;
|
|
815
856
|
phase("build", `${line} -> building here`);
|
|
816
857
|
};
|
|
@@ -819,11 +860,6 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
819
860
|
let androidPackage = initialPackage;
|
|
820
861
|
let ccacheActivity = CCACHE_NOT_RUN;
|
|
821
862
|
let phaseFailure = null;
|
|
822
|
-
const refused = () => ({
|
|
823
|
-
ok: false,
|
|
824
|
-
failure: phaseFailure,
|
|
825
|
-
ccache: ccacheActivity
|
|
826
|
-
});
|
|
827
863
|
let buildLock = null;
|
|
828
864
|
const releaseHeldLock = () => {
|
|
829
865
|
if (!buildLock) return;
|
|
@@ -942,7 +978,6 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
942
978
|
apkPath = found?.path ?? null;
|
|
943
979
|
return true;
|
|
944
980
|
}
|
|
945
|
-
if (!await resolveInitialFingerprint()) return refused();
|
|
946
981
|
let remote = null;
|
|
947
982
|
let abandonedRemote = false;
|
|
948
983
|
let uploadPending = null;
|
|
@@ -994,13 +1029,9 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
994
1029
|
} else phase("cache", `remote miss (${remote.name}) ${remoteTimer()}`);
|
|
995
1030
|
}
|
|
996
1031
|
}
|
|
997
|
-
if (!easBuild) {
|
|
998
|
-
await resolveRemoteArtifact();
|
|
999
|
-
if (!apkPath) miss(reasonForMiss([]).reason);
|
|
1000
|
-
}
|
|
1001
1032
|
let waitedForBuild = null;
|
|
1002
1033
|
let releasedWait = null;
|
|
1003
|
-
|
|
1034
|
+
async function awaitSharedBuild() {
|
|
1004
1035
|
const shared = await waitForSharedBuild({
|
|
1005
1036
|
platform: PLATFORM,
|
|
1006
1037
|
key: cacheKey,
|
|
@@ -1022,7 +1053,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1022
1053
|
if (shared.refusal) {
|
|
1023
1054
|
const { code, message, remedy } = shared.refusal;
|
|
1024
1055
|
phaseFailure = fail$1(code, message, remedy, { lastBuildStatus: true });
|
|
1025
|
-
|
|
1056
|
+
throw new ArtifactRefusal(phaseFailure);
|
|
1026
1057
|
}
|
|
1027
1058
|
buildLock = shared.lock;
|
|
1028
1059
|
releasedWait = shared.released;
|
|
@@ -1031,6 +1062,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1031
1062
|
record.cacheHit = "local";
|
|
1032
1063
|
waitedForBuild = shared.hit.waited;
|
|
1033
1064
|
}
|
|
1065
|
+
return apkPath;
|
|
1034
1066
|
}
|
|
1035
1067
|
let swapDir = null;
|
|
1036
1068
|
const installableCachedApk = async (key, cachedPath) => {
|
|
@@ -1056,15 +1088,13 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1056
1088
|
swapFellBack = true;
|
|
1057
1089
|
return null;
|
|
1058
1090
|
};
|
|
1059
|
-
async function prepareCachedArtifact() {
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
record.cacheHit = false;
|
|
1065
|
-
waitedForBuild = null;
|
|
1066
|
-
}
|
|
1091
|
+
async function prepareCachedArtifact(cachedPath) {
|
|
1092
|
+
const prepared = await installableCachedApk(cacheKey, cachedPath);
|
|
1093
|
+
if (!prepared) {
|
|
1094
|
+
record.cacheHit = false;
|
|
1095
|
+
waitedForBuild = null;
|
|
1067
1096
|
}
|
|
1097
|
+
return prepared;
|
|
1068
1098
|
}
|
|
1069
1099
|
function reasonForMiss(rekeyedBy) {
|
|
1070
1100
|
if (swapFellBack) return {
|
|
@@ -1107,9 +1137,11 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1107
1137
|
}
|
|
1108
1138
|
}
|
|
1109
1139
|
async function takeBuildSlot() {
|
|
1140
|
+
requireLocalBuild(buildMachine);
|
|
1110
1141
|
if (!maxBuilds) return true;
|
|
1111
1142
|
try {
|
|
1112
1143
|
buildSlot = await acquireSlot({
|
|
1144
|
+
automatic: buildMachine === "auto",
|
|
1113
1145
|
max: maxBuilds,
|
|
1114
1146
|
root,
|
|
1115
1147
|
logFile: buildLog,
|
|
@@ -1118,6 +1150,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1118
1150
|
});
|
|
1119
1151
|
slotWaitMs = buildSlot.slotWaitMs;
|
|
1120
1152
|
} catch (err) {
|
|
1153
|
+
requireLocalBuild(buildMachine);
|
|
1121
1154
|
const refusal = (0, ownership_claim_exports.claimFailure)(err, "stim android");
|
|
1122
1155
|
if (refusal) {
|
|
1123
1156
|
phaseFailure = fail$1(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
@@ -1129,12 +1162,13 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1129
1162
|
}
|
|
1130
1163
|
/** Whether this build should leave this Mac, before any machine is asked; null builds here. */
|
|
1131
1164
|
function placeBuild() {
|
|
1132
|
-
const { mode, machines } = buildPlacementCandidates(buildMachine);
|
|
1133
|
-
if (machines.length === 0 && !namedBuildMachine(buildMachine) && buildMachine !== "local") return null;
|
|
1165
|
+
const { mode, machines, localEnabled } = buildPlacementCandidates(buildMachine);
|
|
1166
|
+
if (localEnabled && machines.length === 0 && !namedBuildMachine(buildMachine) && buildMachine !== "local") return null;
|
|
1134
1167
|
const unsupported = physical ? "device builds build here" : remoteTarget ? "remote device builds build here" : release ? `${variant} builds build here` : cas ? "Apple Clang CAS builds build here" : !cachePolicy.write ? "the build cache is off" : null;
|
|
1135
1168
|
const here = machineCapacity();
|
|
1136
1169
|
const placement = offloadPlacement({
|
|
1137
1170
|
mode,
|
|
1171
|
+
localEnabled,
|
|
1138
1172
|
machines: machines.length,
|
|
1139
1173
|
here,
|
|
1140
1174
|
unsupported,
|
|
@@ -1142,12 +1176,21 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1142
1176
|
});
|
|
1143
1177
|
if (!placement.offload) {
|
|
1144
1178
|
hereReason = placement.reason;
|
|
1179
|
+
writer.write(buildPlacementRecord({
|
|
1180
|
+
platform: PLATFORM,
|
|
1181
|
+
buildMachine,
|
|
1182
|
+
stays: {
|
|
1183
|
+
code: placement.code,
|
|
1184
|
+
reason: placement.reason
|
|
1185
|
+
}
|
|
1186
|
+
}));
|
|
1145
1187
|
if (mode !== "off") phase("build", `placement: here (${placement.reason})`);
|
|
1146
1188
|
return null;
|
|
1147
1189
|
}
|
|
1148
1190
|
return {
|
|
1149
1191
|
mode,
|
|
1150
1192
|
here,
|
|
1193
|
+
code: placement.code,
|
|
1151
1194
|
reason: placement.reason,
|
|
1152
1195
|
machines
|
|
1153
1196
|
};
|
|
@@ -1155,6 +1198,7 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1155
1198
|
const openOffload = { choice: null };
|
|
1156
1199
|
/** Asks the paired machines once the post-mutation key is known; null builds here. */
|
|
1157
1200
|
async function chooseMachine(candidate) {
|
|
1201
|
+
let asked = [];
|
|
1158
1202
|
const choice = await chooseBuildMachine({
|
|
1159
1203
|
projectRoot: root,
|
|
1160
1204
|
target: {
|
|
@@ -1166,22 +1210,46 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1166
1210
|
here: candidate.here,
|
|
1167
1211
|
note: (line) => phase("build", chalk.dim(`offload: ${line}`)),
|
|
1168
1212
|
machines: candidate.machines,
|
|
1169
|
-
selected: buildMachine
|
|
1213
|
+
selected: buildMachine,
|
|
1214
|
+
onCandidates: (each) => asked = each
|
|
1170
1215
|
});
|
|
1171
1216
|
if (typeof choice === "string") {
|
|
1172
1217
|
const only = candidate.machines.length === 1 ? candidate.machines[0].machine : null;
|
|
1173
1218
|
if (only && choice.startsWith(`${only}: `)) fallbackMachine = only;
|
|
1174
|
-
fallBack(choice
|
|
1219
|
+
fallBack(choice, choice, {
|
|
1220
|
+
code: "no-remote-mac-took-it",
|
|
1221
|
+
candidates: asked
|
|
1222
|
+
});
|
|
1175
1223
|
return null;
|
|
1176
1224
|
}
|
|
1177
1225
|
openOffload.choice = choice;
|
|
1226
|
+
writer.write(buildPlacementRecord({
|
|
1227
|
+
platform: PLATFORM,
|
|
1228
|
+
buildMachine,
|
|
1229
|
+
candidates: asked,
|
|
1230
|
+
chose: {
|
|
1231
|
+
machine: choice.machine,
|
|
1232
|
+
reason: `${candidate.reason}${placementLoad(choice)}`
|
|
1233
|
+
}
|
|
1234
|
+
}));
|
|
1178
1235
|
phase("build", `placement: ${choice.machine} (${candidate.reason}${placementLoad(choice)})`);
|
|
1179
1236
|
return choice;
|
|
1180
1237
|
}
|
|
1181
1238
|
/** Builds on the chosen machine and stores the APK under the post-mutation key; false builds here instead unless a machine was named. */
|
|
1182
1239
|
async function compileElsewhere(choice, candidate) {
|
|
1183
1240
|
if (!storeKey || !storeHash) {
|
|
1184
|
-
|
|
1241
|
+
const reason = "the build fingerprint or cache key is unavailable";
|
|
1242
|
+
if (namedBuildMachine(buildMachine)) fallBack(reason, reason, { machine: choice.machine });
|
|
1243
|
+
else writer.write(buildPlacementRecord({
|
|
1244
|
+
platform: PLATFORM,
|
|
1245
|
+
buildMachine,
|
|
1246
|
+
event: "placement_fallback",
|
|
1247
|
+
fallback: {
|
|
1248
|
+
code: "fallback",
|
|
1249
|
+
reason,
|
|
1250
|
+
machine: choice.machine
|
|
1251
|
+
}
|
|
1252
|
+
}));
|
|
1185
1253
|
return false;
|
|
1186
1254
|
}
|
|
1187
1255
|
const stagingDir = join(workspaceDir(root), "offload", PLATFORM);
|
|
@@ -1245,7 +1313,10 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1245
1313
|
if (!outcome.ok || !stored) {
|
|
1246
1314
|
const why = reason ?? "the APK was not stored";
|
|
1247
1315
|
fallbackMachine = choice.machine;
|
|
1248
|
-
fallBack(`${choice.machine}: ${why}`, `offload failed: ${why}
|
|
1316
|
+
fallBack(`${choice.machine}: ${why}`, `offload failed: ${why}`, {
|
|
1317
|
+
code: "offload-failed",
|
|
1318
|
+
machine: choice.machine
|
|
1319
|
+
});
|
|
1249
1320
|
writer.write({
|
|
1250
1321
|
src: "build",
|
|
1251
1322
|
level: "warn",
|
|
@@ -1278,228 +1349,284 @@ async function acquireAndroidArtifact({ root, buildLog, writer, settings, isExpo
|
|
|
1278
1349
|
});
|
|
1279
1350
|
return true;
|
|
1280
1351
|
}
|
|
1281
|
-
async function
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1352
|
+
async function prepareSource() {
|
|
1353
|
+
const rekeyedBy = [];
|
|
1354
|
+
const prebuildPlan = planPrebuildFor(root, PLATFORM, {
|
|
1355
|
+
isExpo,
|
|
1356
|
+
fingerprint: hash,
|
|
1357
|
+
sources: fingerprintSources
|
|
1358
|
+
});
|
|
1359
|
+
const prebuildRan = prebuildPlan === "generate" || prebuildPlan === "regenerate";
|
|
1360
|
+
if (prebuildPlan === "refuse") {
|
|
1361
|
+
const refusal = staleNativeDirRefusal(PLATFORM);
|
|
1362
|
+
phaseFailure = fail$1(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
1363
|
+
throw new ArtifactRefusal(phaseFailure);
|
|
1364
|
+
}
|
|
1365
|
+
if (prebuildRan) {
|
|
1366
|
+
miss(reasonForMiss([]).reason, true);
|
|
1367
|
+
step("prebuild");
|
|
1368
|
+
recordPrebuild(root, PLATFORM, null);
|
|
1369
|
+
const pre = await prebuild(root, PLATFORM, writer, {
|
|
1288
1370
|
isExpo,
|
|
1289
|
-
|
|
1290
|
-
sources: fingerprintSources
|
|
1371
|
+
clean: prebuildPlan === "regenerate"
|
|
1291
1372
|
});
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
}
|
|
1298
|
-
if (prebuildRan) {
|
|
1299
|
-
miss(reasonForMiss([]).reason, true);
|
|
1300
|
-
step("prebuild");
|
|
1301
|
-
recordPrebuild(root, PLATFORM, null);
|
|
1302
|
-
const pre = await prebuild(root, PLATFORM, writer, {
|
|
1303
|
-
isExpo,
|
|
1304
|
-
clean: prebuildPlan === "regenerate"
|
|
1305
|
-
});
|
|
1306
|
-
if (pre.failed) {
|
|
1307
|
-
phaseFailure = fail$1(pre.code, pre.reason, pre.remedy, {
|
|
1308
|
-
lastBuildStatus: true,
|
|
1309
|
-
lines: tail(pre.lastLines),
|
|
1310
|
-
logPath: displayPath(root, buildLog)
|
|
1311
|
-
});
|
|
1312
|
-
return false;
|
|
1313
|
-
}
|
|
1314
|
-
phase("prebuild", `${prebuildPlan === "generate" ? "android/ generated" : "android/ not generated from this fingerprint -> regenerated with --clean"} (${formatDuration(pre.durationMs)})`);
|
|
1315
|
-
androidPackage = detectAndroidPackage(root) || androidPackage;
|
|
1316
|
-
record.bundleId = androidPackage;
|
|
1317
|
-
const after = await refingerprintAfterMutation({
|
|
1318
|
-
projectRoot: root,
|
|
1319
|
-
platform: PLATFORM,
|
|
1320
|
-
previousHash: hash,
|
|
1321
|
-
fingerprint
|
|
1373
|
+
if (pre.failed) {
|
|
1374
|
+
phaseFailure = fail$1(pre.code, pre.reason, pre.remedy, {
|
|
1375
|
+
lastBuildStatus: true,
|
|
1376
|
+
lines: tail(pre.lastLines),
|
|
1377
|
+
logPath: displayPath(root, buildLog)
|
|
1322
1378
|
});
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1379
|
+
throw new ArtifactRefusal(phaseFailure);
|
|
1380
|
+
}
|
|
1381
|
+
phase("prebuild", `${prebuildPlan === "generate" ? "android/ generated" : "android/ not generated from this fingerprint -> regenerated with --clean"} (${formatDuration(pre.durationMs)})`);
|
|
1382
|
+
androidPackage = detectAndroidPackage(root) || androidPackage;
|
|
1383
|
+
record.bundleId = androidPackage;
|
|
1384
|
+
}
|
|
1385
|
+
return {
|
|
1386
|
+
prebuildRan,
|
|
1387
|
+
rekeyedBy,
|
|
1388
|
+
editedConfig: []
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
async function revalidateSource(preparation) {
|
|
1392
|
+
const { prebuildRan, rekeyedBy } = preparation;
|
|
1393
|
+
if (prebuildRan) {
|
|
1394
|
+
const after = await refingerprintAfterMutation({
|
|
1395
|
+
projectRoot: root,
|
|
1396
|
+
platform: PLATFORM,
|
|
1397
|
+
previousHash: hash,
|
|
1398
|
+
fingerprint
|
|
1399
|
+
});
|
|
1400
|
+
preparation.editedConfig = after ? configInputsChanged(fingerprintSources, after.sources, { prebuildRan }) : [];
|
|
1401
|
+
const { editedConfig } = preparation;
|
|
1402
|
+
if (after && !editedConfig.length) recordPrebuild(root, PLATFORM, after.hash);
|
|
1403
|
+
if (after?.moved && !editedConfig.length) {
|
|
1404
|
+
rekeyedBy.push("prebuild");
|
|
1405
|
+
storeHash = after.hash;
|
|
1406
|
+
storeSources = after.sources;
|
|
1407
|
+
storeKey = buildCacheKey(PLATFORM, after.hash, buildRunOptions);
|
|
1408
|
+
record.fingerprint = storeHash;
|
|
1409
|
+
record.cacheKey = storeKey;
|
|
1410
|
+
phase("fingerprint", chalk.dim(`${shortHash(hash)} -> ${shortHash(storeHash)} (after prebuild)`));
|
|
1411
|
+
const late = useBuildCache ? resolveCached(PLATFORM, storeKey) : null;
|
|
1412
|
+
if (late) {
|
|
1413
|
+
const prepared = await installableCachedApk(storeKey, late);
|
|
1414
|
+
if (prepared) {
|
|
1415
|
+
apkPath = prepared;
|
|
1416
|
+
record.cacheHit = "local";
|
|
1417
|
+
lateHit();
|
|
1418
|
+
phase("cache", `hit ${shortHash(storeHash)} (post-prebuild key)`);
|
|
1419
|
+
if (releasedWait) {
|
|
1420
|
+
waitedForBuild = releasedWait.facts;
|
|
1421
|
+
phase("build", `waited ${formatDuration(waitedForBuild.ms)} for ${releasedWait.who}'s build -> installed from cache -- stim guide lifecycle concurrency`);
|
|
1345
1422
|
}
|
|
1346
1423
|
}
|
|
1347
1424
|
}
|
|
1348
1425
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
} catch (err) {
|
|
1472
|
-
phase("cache", chalk.yellow(`could not store the build: ${err?.message || err}`));
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
if (remote) uploadPending = uploadRemoteBuild({
|
|
1476
|
-
logWriter: writer,
|
|
1477
|
-
provider: remote.provider,
|
|
1478
|
-
platform: PLATFORM,
|
|
1426
|
+
}
|
|
1427
|
+
return apkPath ? { ready: apkPath } : null;
|
|
1428
|
+
}
|
|
1429
|
+
async function acquireRemoteArtifact(offload, { rekeyedBy, editedConfig }) {
|
|
1430
|
+
explainMiss(rekeyedBy);
|
|
1431
|
+
step("compile");
|
|
1432
|
+
if (editedConfig.length) fallBack("prebuild changed config inputs, so the APK cannot be cached", "offload failed: prebuild changed config inputs, so the APK cannot be cached");
|
|
1433
|
+
else {
|
|
1434
|
+
const choice = await chooseMachine(offload);
|
|
1435
|
+
if (choice) await compileElsewhere(choice, offload);
|
|
1436
|
+
}
|
|
1437
|
+
return apkPath ? { ready: apkPath } : null;
|
|
1438
|
+
}
|
|
1439
|
+
async function compileHere(offload, { rekeyedBy }) {
|
|
1440
|
+
if (!offload) {
|
|
1441
|
+
explainMiss(rekeyedBy);
|
|
1442
|
+
step("compile");
|
|
1443
|
+
}
|
|
1444
|
+
if (offload) stats.setPlacement({
|
|
1445
|
+
decision: "fell-back",
|
|
1446
|
+
slotWaitMs,
|
|
1447
|
+
deviceSlotWaitMs: stats.deviceSlotWaitMs(),
|
|
1448
|
+
reason: record.offloadFallback ?? "offload failed",
|
|
1449
|
+
...fallbackMachine ? { machine: fallbackMachine } : {}
|
|
1450
|
+
});
|
|
1451
|
+
else stats.setPlacement({
|
|
1452
|
+
decision: "here",
|
|
1453
|
+
reason: hereReason,
|
|
1454
|
+
slotWaitMs,
|
|
1455
|
+
deviceSlotWaitMs: stats.deviceSlotWaitMs()
|
|
1456
|
+
});
|
|
1457
|
+
requireLocalBuild(buildMachine);
|
|
1458
|
+
record.builtOn = "here";
|
|
1459
|
+
phase("build", `compiling ${variant || "debug"} with Gradle`);
|
|
1460
|
+
const built = await build({
|
|
1461
|
+
root,
|
|
1462
|
+
logWriter: writer,
|
|
1463
|
+
variant,
|
|
1464
|
+
abi: buildAbi
|
|
1465
|
+
}, {
|
|
1466
|
+
estimateMs: estimates().coldBuildMs,
|
|
1467
|
+
ccache: buildPlan.compilerCache === "ccache" ? ccacheFor({
|
|
1468
|
+
root,
|
|
1469
|
+
onNote: out
|
|
1470
|
+
}) : null,
|
|
1471
|
+
cas,
|
|
1472
|
+
buildCache: buildPlan.gradleBuildCache,
|
|
1473
|
+
pch: buildPlan.pch,
|
|
1474
|
+
compilerCacheDisabled: buildPlan.compilerCache === "none"
|
|
1475
|
+
});
|
|
1476
|
+
ccacheActivity = built.ccache ?? CCACHE_UNAVAILABLE;
|
|
1477
|
+
phase("cache", `compilation cache ${ccacheActivityLine(ccacheActivity)}`);
|
|
1478
|
+
if (!built.ok) {
|
|
1479
|
+
const diagnostics = built.diagnostics;
|
|
1480
|
+
for (const diag of diagnostics) writer.write({
|
|
1481
|
+
src: "build",
|
|
1482
|
+
level: "error",
|
|
1483
|
+
event: "gradle_diagnostic",
|
|
1484
|
+
msg: formatDiagnostic(diag)
|
|
1485
|
+
});
|
|
1486
|
+
phase("build", chalk.red(`FAILED after ${formatDuration(built.durationMs)}`));
|
|
1487
|
+
const extracted = diagnostics.map(formatDiagnostic);
|
|
1488
|
+
if (built.truncated > 0) extracted.push(`... and ${built.truncated} more diagnostic(s) in the log`);
|
|
1489
|
+
phaseFailure = fail$1(built.code, built.reason, diagnostics.find((d) => d.remedy)?.remedy || built.remedy || null, {
|
|
1490
|
+
lastBuildStatus: true,
|
|
1491
|
+
diagnostics: extracted,
|
|
1492
|
+
buildDiagnostics: diagnostics,
|
|
1493
|
+
lines: extracted.length ? [] : tail(built.lastLines),
|
|
1494
|
+
logPath: displayPath(root, buildLog)
|
|
1495
|
+
});
|
|
1496
|
+
throw new ArtifactRefusal(phaseFailure);
|
|
1497
|
+
}
|
|
1498
|
+
apkPath = built.apkPath;
|
|
1499
|
+
stats.setBuildMs(built.durationMs);
|
|
1500
|
+
phase("build", `ok (${formatDuration(built.durationMs)})`);
|
|
1501
|
+
if (built.apkNote) phase("build", chalk.yellow(built.apkNote));
|
|
1502
|
+
return apkPath;
|
|
1503
|
+
}
|
|
1504
|
+
async function validateCompiled({ prebuildRan, editedConfig }) {
|
|
1505
|
+
const beforeBuildHash = storeHash;
|
|
1506
|
+
const afterBuild = editedConfig.length ? null : await refingerprintAfterMutation({
|
|
1507
|
+
projectRoot: root,
|
|
1508
|
+
platform: PLATFORM,
|
|
1509
|
+
previousHash: beforeBuildHash,
|
|
1510
|
+
fingerprint
|
|
1511
|
+
});
|
|
1512
|
+
const changedDuringBuild = afterBuild ? inputsChangedDuringBuild({
|
|
1513
|
+
platform: PLATFORM,
|
|
1514
|
+
lookup: fingerprintSources,
|
|
1515
|
+
prebuildRan,
|
|
1516
|
+
compiled: storeSources,
|
|
1517
|
+
current: afterBuild.sources
|
|
1518
|
+
}) : editedConfig;
|
|
1519
|
+
if (!afterBuild || changedDuringBuild.length) {
|
|
1520
|
+
record.fingerprint = null;
|
|
1521
|
+
record.cacheKey = null;
|
|
1522
|
+
phase("fingerprint", chalk.yellow(changedDuringBuild.length ? changedDuringBuildLine(changedDuringBuild) : "unavailable after Gradle; the build will be installed but not cached"));
|
|
1523
|
+
return "uncacheable";
|
|
1524
|
+
}
|
|
1525
|
+
if (afterBuild.moved) {
|
|
1526
|
+
storeHash = afterBuild.hash;
|
|
1527
|
+
storeSources = afterBuild.sources;
|
|
1528
|
+
storeKey = buildCacheKey(PLATFORM, afterBuild.hash, buildRunOptions);
|
|
1529
|
+
record.fingerprint = storeHash;
|
|
1530
|
+
record.cacheKey = storeKey;
|
|
1531
|
+
phase("fingerprint", chalk.dim(`${shortHash(beforeBuildHash)} -> ${shortHash(storeHash)} (after Gradle)`));
|
|
1532
|
+
}
|
|
1533
|
+
return "cacheable";
|
|
1534
|
+
}
|
|
1535
|
+
async function storeArtifact(artifactPath) {
|
|
1536
|
+
if (cachePolicy.write) {
|
|
1537
|
+
const assetManifest = release ? captureAssets(root, { variant }) : null;
|
|
1538
|
+
try {
|
|
1539
|
+
const stored = await storeTieredBuild({
|
|
1540
|
+
local: filesystemBuildCapability({
|
|
1541
|
+
resolve: resolveCached,
|
|
1542
|
+
store: storeCached,
|
|
1543
|
+
sources: storeSources,
|
|
1544
|
+
assetManifest
|
|
1545
|
+
}),
|
|
1546
|
+
loadProvider: loadTieredProvider,
|
|
1547
|
+
target: {
|
|
1479
1548
|
projectRoot: root,
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1549
|
+
platform: PLATFORM,
|
|
1550
|
+
key: storeKey
|
|
1551
|
+
},
|
|
1552
|
+
sourcePath: artifactPath,
|
|
1553
|
+
overwrite: !useBuildCache || swapFellBack,
|
|
1554
|
+
warn: cacheWarn
|
|
1555
|
+
});
|
|
1556
|
+
providerUpload = stored.providerUpload;
|
|
1557
|
+
providerName = stored.providerName ?? providerName;
|
|
1558
|
+
} catch (err) {
|
|
1559
|
+
phase("cache", chalk.yellow(`could not store the build: ${err?.message || err}`));
|
|
1485
1560
|
}
|
|
1486
|
-
} catch (error) {
|
|
1487
|
-
if (!(error instanceof OffloadRefusal)) throw error;
|
|
1488
|
-
const refusal = error;
|
|
1489
|
-
phaseFailure = fail$1(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
1490
|
-
return false;
|
|
1491
|
-
} finally {
|
|
1492
|
-
if (openOffload.choice) closeOffload(openOffload.choice);
|
|
1493
|
-
releaseHeldLock();
|
|
1494
|
-
releaseHeldSlot();
|
|
1495
1561
|
}
|
|
1496
|
-
|
|
1562
|
+
if (remote) uploadPending = uploadRemoteBuild({
|
|
1563
|
+
logWriter: writer,
|
|
1564
|
+
provider: remote.provider,
|
|
1565
|
+
platform: PLATFORM,
|
|
1566
|
+
projectRoot: root,
|
|
1567
|
+
fingerprintHash: storeHash,
|
|
1568
|
+
buildPath: artifactPath,
|
|
1569
|
+
runOptions: remoteRunOptions
|
|
1570
|
+
});
|
|
1497
1571
|
}
|
|
1498
|
-
|
|
1499
|
-
await
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1572
|
+
try {
|
|
1573
|
+
apkPath = await runArtifactLifecycle({
|
|
1574
|
+
resolve: async () => {
|
|
1575
|
+
if (!await resolveInitialFingerprint()) throw new ArtifactRefusal(phaseFailure);
|
|
1576
|
+
if (easBuild) return {
|
|
1577
|
+
kind: "ready",
|
|
1578
|
+
artifact: apkPath
|
|
1579
|
+
};
|
|
1580
|
+
await resolveRemoteArtifact();
|
|
1581
|
+
if (apkPath) return {
|
|
1582
|
+
kind: "cached",
|
|
1583
|
+
artifact: apkPath
|
|
1584
|
+
};
|
|
1585
|
+
miss(reasonForMiss([]).reason);
|
|
1586
|
+
return { kind: "miss" };
|
|
1587
|
+
},
|
|
1588
|
+
claim: useBuildCache ? awaitSharedBuild : void 0,
|
|
1589
|
+
reuse: async (cached) => {
|
|
1590
|
+
apkPath = await prepareCachedArtifact(cached);
|
|
1591
|
+
if (apkPath) lateHit();
|
|
1592
|
+
else if (swapFellBack) miss(reasonForMiss([]).reason);
|
|
1593
|
+
return apkPath;
|
|
1594
|
+
},
|
|
1595
|
+
build: {
|
|
1596
|
+
placement: {
|
|
1597
|
+
select: placeBuild,
|
|
1598
|
+
acquire: acquireRemoteArtifact
|
|
1599
|
+
},
|
|
1600
|
+
admit: async () => {
|
|
1601
|
+
if (!await takeBuildSlot()) throw new ArtifactRefusal(phaseFailure);
|
|
1602
|
+
},
|
|
1603
|
+
prepare: prepareSource,
|
|
1604
|
+
revalidate: revalidateSource,
|
|
1605
|
+
compile: compileHere,
|
|
1606
|
+
validate: validateCompiled,
|
|
1607
|
+
store: storeArtifact
|
|
1608
|
+
},
|
|
1609
|
+
release: () => {
|
|
1610
|
+
if (openOffload.choice) closeOffload(openOffload.choice);
|
|
1611
|
+
releaseHeldLock();
|
|
1612
|
+
releaseHeldSlot();
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
} catch (error) {
|
|
1616
|
+
if (error instanceof OffloadRefusal) {
|
|
1617
|
+
const { code, message, remedy } = error;
|
|
1618
|
+
return {
|
|
1619
|
+
ok: false,
|
|
1620
|
+
failure: fail$1(code, message, remedy, { lastBuildStatus: true }),
|
|
1621
|
+
ccache: ccacheActivity
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
if (error instanceof ArtifactRefusal) return {
|
|
1625
|
+
ok: false,
|
|
1626
|
+
failure: error.failure,
|
|
1627
|
+
ccache: ccacheActivity
|
|
1628
|
+
};
|
|
1629
|
+
throw error;
|
|
1503
1630
|
}
|
|
1504
1631
|
return {
|
|
1505
1632
|
ok: true,
|
|
@@ -1603,11 +1730,41 @@ async function startCollector({ root, slot = "default", serial, packageName, spa
|
|
|
1603
1730
|
}
|
|
1604
1731
|
//#endregion
|
|
1605
1732
|
//#region src/commands/android/launch.ts
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1733
|
+
function androidProcessRuntime(prepare) {
|
|
1734
|
+
return {
|
|
1735
|
+
prepare,
|
|
1736
|
+
scheme: () => void 0,
|
|
1737
|
+
verificationWaitMs: RELEASE_VERIFY_WAIT_MS,
|
|
1738
|
+
launch: async (_prepared, { serial, androidPackage, remoteDevice, launchRelease }) => remoteDevice ? remoteDevice.launch({
|
|
1739
|
+
serial,
|
|
1740
|
+
packageName: androidPackage,
|
|
1741
|
+
metroPort: null
|
|
1742
|
+
}) : launchRelease({
|
|
1743
|
+
serial,
|
|
1744
|
+
packageName: androidPackage
|
|
1745
|
+
}),
|
|
1746
|
+
verify: async (_prepared, context) => verifyAndroidProcessRun(context)
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
function androidMetroRuntime(prepare) {
|
|
1750
|
+
return {
|
|
1751
|
+
prepare,
|
|
1752
|
+
scheme: (root, apkPath, resolve) => resolve(root, apkPath),
|
|
1753
|
+
verificationWaitMs: DEBUG_VERIFY_STEP_MS,
|
|
1754
|
+
launch: async ({ metroPort }, { serial, androidPackage, scheme, physical, launch }) => launch({
|
|
1755
|
+
serial,
|
|
1756
|
+
packageName: androidPackage,
|
|
1757
|
+
metroPort: metroPort ?? 8081,
|
|
1758
|
+
devClientScheme: scheme,
|
|
1759
|
+
physical
|
|
1760
|
+
}),
|
|
1761
|
+
verify: async ({ metroPort }, context) => verifyAndroidMetroRun({
|
|
1762
|
+
...context,
|
|
1763
|
+
metroPort
|
|
1764
|
+
})
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
async function verifyAndroidProcessRun({ root, slot, remoteDevice, verifyReleaseLaunched, serial, androidPackage, variant, logsDir, launchedAt, phase }) {
|
|
1611
1768
|
const readNativeCrashes = () => remoteDevice ? [] : captureNativeCrashes({
|
|
1612
1769
|
root,
|
|
1613
1770
|
slot,
|
|
@@ -1616,30 +1773,42 @@ async function verifyAndroidRun({ root, slot, release, remoteRelease, remoteDevi
|
|
|
1616
1773
|
appId: androidPackage,
|
|
1617
1774
|
since: launchedAt
|
|
1618
1775
|
}, logsDir);
|
|
1619
|
-
if (
|
|
1776
|
+
if (remoteDevice) {
|
|
1620
1777
|
phase("verify", chalk.yellow("UNVERIFIED: remote adapter launch accepted; process verification is unavailable"));
|
|
1621
1778
|
return { state: LAUNCH_UNVERIFIED };
|
|
1622
1779
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
return { state: true };
|
|
1632
|
-
}
|
|
1633
|
-
if (processCheck?.reason === "probe-failed" && !crashes.length) {
|
|
1634
|
-
phase("verify", chalk.yellow("UNVERIFIED: the app process check failed"));
|
|
1635
|
-
return { state: LAUNCH_UNVERIFIED };
|
|
1636
|
-
}
|
|
1637
|
-
for (const line of launchErrorPreview(crashes, root)) phase("launch", chalk.red(line));
|
|
1638
|
-
if (!crashes.length) phase("logs", "Process missing; no attributable native crash report captured. Read `stim logs --source device` for available output.");
|
|
1639
|
-
phase("verify", chalk.yellow(crashes.length ? "FATAL: the app reported a native crash" : `FATAL: no ${androidPackage} process on ${serial} ${formatDuration(processCheck?.waitedMs ?? 0)} after launch`));
|
|
1640
|
-
phase("", chalk.yellow("A release process exited before readiness. Run `stim logs --errors` for captured crash reports, or `stim logs --source device` for the full device output."));
|
|
1641
|
-
return { state: LAUNCH_FATAL };
|
|
1780
|
+
const processCheck = await verifyReleaseLaunched({
|
|
1781
|
+
serial,
|
|
1782
|
+
packageName: androidPackage
|
|
1783
|
+
});
|
|
1784
|
+
const crashes = readNativeCrashes();
|
|
1785
|
+
if (processCheck?.verified && !crashes.length) {
|
|
1786
|
+
phase("verify", `process alive ${formatDuration(processCheck.waitedMs ?? 0)} after launch (${variant}: no bundle fetch to observe)`);
|
|
1787
|
+
return { state: true };
|
|
1642
1788
|
}
|
|
1789
|
+
if (processCheck?.reason === "probe-failed" && !crashes.length) {
|
|
1790
|
+
phase("verify", chalk.yellow("UNVERIFIED: the app process check failed"));
|
|
1791
|
+
return { state: LAUNCH_UNVERIFIED };
|
|
1792
|
+
}
|
|
1793
|
+
for (const line of launchErrorPreview(crashes, root)) phase("launch", chalk.red(line));
|
|
1794
|
+
if (!crashes.length) phase("logs", "Process missing; no attributable native crash report captured. Read `stim logs --source device` for available output.");
|
|
1795
|
+
phase("verify", chalk.yellow(crashes.length ? "FATAL: the app reported a native crash" : `FATAL: no ${androidPackage} process on ${serial} ${formatDuration(processCheck?.waitedMs ?? 0)} after launch`));
|
|
1796
|
+
phase("", chalk.yellow("A release process exited before readiness. Run `stim logs --errors` for captured crash reports, or `stim logs --source device` for the full device output."));
|
|
1797
|
+
return { state: LAUNCH_FATAL };
|
|
1798
|
+
}
|
|
1799
|
+
async function verifyAndroidMetroRun({ root, slot, remoteDevice, verifyLaunched, serial, androidPackage, metroCheck, logsDir, launchedAt, metroPort, isExpo, physical, device, scheme, component = null, phase }) {
|
|
1800
|
+
const runCommand = nativeRunCommand("android", slot, {
|
|
1801
|
+
physical,
|
|
1802
|
+
deviceId: serial
|
|
1803
|
+
});
|
|
1804
|
+
const readNativeCrashes = () => remoteDevice ? [] : captureNativeCrashes({
|
|
1805
|
+
root,
|
|
1806
|
+
slot,
|
|
1807
|
+
platform: "android",
|
|
1808
|
+
deviceId: serial,
|
|
1809
|
+
appId: androidPackage,
|
|
1810
|
+
since: launchedAt
|
|
1811
|
+
}, logsDir);
|
|
1643
1812
|
const freshEmulator = Boolean((device.created || device.adoptionPending) && device.owned && !remoteDevice);
|
|
1644
1813
|
const timeoutMs = freshEmulator ? 6e4 : VERIFY_TIMEOUT_MS;
|
|
1645
1814
|
if (metroCheck && freshEmulator) phase("verify", `waiting up to 60s for bundle load (${device.created ? "new" : "adopted"} emulator)`);
|
|
@@ -1814,7 +1983,7 @@ async function resolveInstallSerial({ root, slot, device, physical, remoteDevice
|
|
|
1814
1983
|
});
|
|
1815
1984
|
return resolved.serial;
|
|
1816
1985
|
}
|
|
1817
|
-
async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, apkPath, androidPackage: initialPackage, swapDir, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, recordBuild, now, out, emit, recordRun, reclaimed, devServer, enterPhase, rebootDevice, dataFreeBytes = androidDataFreeBytes, trimCaches = trimAndroidCaches, wipeDevice = teardownOwnedAvd }) {
|
|
1986
|
+
async function finishAndroidRun({ runtime, runtimePreparation, lease, releaseLease, root, slot, json, metroCheck, useBuildCache, variant, release, isExpo, metroPort, logsDir, emuLog, device, physical, remoteDevice, bootPromise, resolveAvdSerial, waitForDeviceBoot, bootDuration, apkPath, androidPackage: initialPackage, swapDir, record, waitedForBuild, ccache, uploadPending, providerUpload, providerName, remote, abandonedRemote: remoteWasAbandoned, started, startedAt, writer, phase, fail, readApkPackage, install, launch, launchRelease, resolveDevClientScheme, verifyLaunched, verifyReleaseLaunched, spawn, kill, pidAlive, verifyCollector, writeLaunch, recordBuild, now, out, emit, recordRun, reclaimed, devServer, enterPhase, rebootDevice, dataFreeBytes = androidDataFreeBytes, trimCaches = trimAndroidCaches, wipeDevice = teardownOwnedAvd }) {
|
|
1818
1987
|
let androidPackage = initialPackage;
|
|
1819
1988
|
let leaseWarned = false;
|
|
1820
1989
|
const raiseLeaseFor = (boundMs, beforeInstall) => {
|
|
@@ -1946,7 +2115,7 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
|
|
|
1946
2115
|
record.bundleId = androidPackage;
|
|
1947
2116
|
if (!androidPackage) return fail(LAUNCH_FAILED, "Could not determine this app's Android package name, so there is nothing to launch.", "Set `expo.android.package` in app.json / app.config.js, or `namespace` in android/app/build.gradle.", { lastBuildStatus: true });
|
|
1948
2117
|
if (physical) raiseLeaseFor(0, false);
|
|
1949
|
-
const scheme =
|
|
2118
|
+
const scheme = runtime.scheme(root, apkPath, resolveDevClientScheme);
|
|
1950
2119
|
enterPhase("launch");
|
|
1951
2120
|
const launchTimer = stepTimer(now);
|
|
1952
2121
|
const launchedAt = now();
|
|
@@ -1963,19 +2132,14 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
|
|
|
1963
2132
|
physical,
|
|
1964
2133
|
msg: `launching ${androidPackage} on ${serial}`
|
|
1965
2134
|
});
|
|
1966
|
-
const launched =
|
|
1967
|
-
serial,
|
|
1968
|
-
packageName: androidPackage,
|
|
1969
|
-
metroPort: null
|
|
1970
|
-
}) : launchRelease({
|
|
2135
|
+
const launched = await runtime.launch(runtimePreparation, {
|
|
1971
2136
|
serial,
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
physical
|
|
2137
|
+
androidPackage,
|
|
2138
|
+
scheme,
|
|
2139
|
+
physical,
|
|
2140
|
+
remoteDevice,
|
|
2141
|
+
launch,
|
|
2142
|
+
launchRelease
|
|
1979
2143
|
});
|
|
1980
2144
|
if (launched.failed) {
|
|
1981
2145
|
printNativeCrashReport({
|
|
@@ -2066,12 +2230,10 @@ async function finishAndroidRun({ lease, releaseLease, root, slot, json, metroCh
|
|
|
2066
2230
|
});
|
|
2067
2231
|
phase("logs", `${displayPath(root, logsDir)}${collectorPid ? ` (collector pid ${collectorPid})` : ""}`);
|
|
2068
2232
|
}
|
|
2069
|
-
if (physical) raiseLeaseFor(
|
|
2070
|
-
const { state: launchState, warning: launchWarning, unattributed } = await
|
|
2233
|
+
if (physical) raiseLeaseFor(runtime.verificationWaitMs, false);
|
|
2234
|
+
const { state: launchState, warning: launchWarning, unattributed } = await runtime.verify(runtimePreparation, {
|
|
2071
2235
|
root,
|
|
2072
2236
|
slot,
|
|
2073
|
-
release,
|
|
2074
|
-
remoteRelease,
|
|
2075
2237
|
remoteDevice: Boolean(remoteDevice),
|
|
2076
2238
|
verifyReleaseLaunched,
|
|
2077
2239
|
verifyLaunched,
|
|
@@ -2394,7 +2556,7 @@ function androidDeviceSelectorRefusal({ settingsContext, slot, systemImageFlag,
|
|
|
2394
2556
|
//#endregion
|
|
2395
2557
|
//#region src/commands/android/next-build.ts
|
|
2396
2558
|
const DEFAULT_PLAN_DEPS = {
|
|
2397
|
-
findRoot: findProjectRoot
|
|
2559
|
+
findRoot: findProjectRoot,
|
|
2398
2560
|
fingerprint: fingerprintProject,
|
|
2399
2561
|
listSystemImages: listInstalledSystemImages,
|
|
2400
2562
|
avdSystemImage: ownedAvdSystemImage,
|
|
@@ -2459,10 +2621,10 @@ async function planAndroid(opts, overrides = {}) {
|
|
|
2459
2621
|
if (flag) return refuse(planFlagRefusal(flag));
|
|
2460
2622
|
const root = deps.findRoot(process.cwd());
|
|
2461
2623
|
if (!root) return refuse(NO_PROJECT_REFUSAL);
|
|
2462
|
-
const
|
|
2463
|
-
if (
|
|
2624
|
+
const problem = projectProblem(root, "android");
|
|
2625
|
+
if (problem) return refuse({
|
|
2464
2626
|
code: "STIM_NO_PROJECT",
|
|
2465
|
-
...
|
|
2627
|
+
...problem
|
|
2466
2628
|
});
|
|
2467
2629
|
const slot = validateDeviceSlot(opts.slot);
|
|
2468
2630
|
const settingsContext = {
|
|
@@ -2470,8 +2632,9 @@ async function planAndroid(opts, overrides = {}) {
|
|
|
2470
2632
|
gitCommonDir: gitCommonDir(root),
|
|
2471
2633
|
repoRoot: repoRoot(root)
|
|
2472
2634
|
};
|
|
2635
|
+
const settings = resolveSettings(settingsContext);
|
|
2473
2636
|
const planned = resolveAndroidRunPlan({
|
|
2474
|
-
settings
|
|
2637
|
+
settings,
|
|
2475
2638
|
settingsContext,
|
|
2476
2639
|
slot,
|
|
2477
2640
|
easProfile: opts.easProfile,
|
|
@@ -2524,20 +2687,59 @@ async function planAndroid(opts, overrides = {}) {
|
|
|
2524
2687
|
refusal: eas.missing
|
|
2525
2688
|
}), json);
|
|
2526
2689
|
}
|
|
2527
|
-
if (target.kind
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
});
|
|
2534
|
-
}
|
|
2690
|
+
if (target.kind === "physical") return refuse(planFlagRefusal("--device"));
|
|
2691
|
+
if (target.kind === "remote") return refuse({
|
|
2692
|
+
code: "STIM_BAD_ARG",
|
|
2693
|
+
message: `android.remote is ${target.backend}, whose ABI --plan cannot read without a session.`,
|
|
2694
|
+
remedy: "Run `stim android` to build for the remote device, or unset android.remote to plan the owned emulator."
|
|
2695
|
+
});
|
|
2535
2696
|
if (build.compilerCache === "cas") return refuse({
|
|
2536
2697
|
code: "STIM_BAD_ARG",
|
|
2537
2698
|
message: "The experimental Android compiler CAS keys builds by a toolchain Stim sets up, which --plan does not.",
|
|
2538
2699
|
remedy: "Run `stim android` to build with the CAS, or set optimizations.android.compilerCache to ccache."
|
|
2539
2700
|
});
|
|
2540
|
-
const
|
|
2701
|
+
const abiKeyed = build.targetAbiOnly && !build.release;
|
|
2702
|
+
const localImage = () => abiKeyed ? emulatorImage(root, slot, target.systemImage, deps) : { systemImage: null };
|
|
2703
|
+
let image;
|
|
2704
|
+
let hostedAbi = null;
|
|
2705
|
+
let placement;
|
|
2706
|
+
if (target.kind === "hosted") {
|
|
2707
|
+
const hostedPlan = await planHostedDevice({
|
|
2708
|
+
root,
|
|
2709
|
+
slot,
|
|
2710
|
+
platform: "android",
|
|
2711
|
+
machine: target.machine,
|
|
2712
|
+
selectors: {
|
|
2713
|
+
...target.systemImage ? { systemImage: target.systemImage } : {},
|
|
2714
|
+
...target.deviceProfile ? { deviceProfile: target.deviceProfile } : {}
|
|
2715
|
+
},
|
|
2716
|
+
sameKey: (choice) => {
|
|
2717
|
+
if (build.targetAbiOnly && build.release) return !("architecture" in choice && choice.architecture);
|
|
2718
|
+
if (!abiKeyed) return true;
|
|
2719
|
+
const local = localImage();
|
|
2720
|
+
if ("refusal" in local || !("systemImage" in choice)) return null;
|
|
2721
|
+
return androidSystemImageAbi(local.systemImage) === androidSystemImageAbi(choice.systemImage);
|
|
2722
|
+
},
|
|
2723
|
+
...remoteEasFallbackSetting(settings) ? { eas: () => checkEasFallback({
|
|
2724
|
+
root,
|
|
2725
|
+
platform: "android",
|
|
2726
|
+
slot,
|
|
2727
|
+
release: build.release,
|
|
2728
|
+
isExpo,
|
|
2729
|
+
tunnelMode: tunnelModeSetting(settings),
|
|
2730
|
+
publicUrl: publicUrlSetting(settings),
|
|
2731
|
+
localOnlyFlags: typeof opts.systemImage === "string" ? ["--system-image"] : []
|
|
2732
|
+
}) } : {}
|
|
2733
|
+
});
|
|
2734
|
+
if (hostedPlan.kind === "unknown") return refuse({
|
|
2735
|
+
code: "STIM_BAD_ARG",
|
|
2736
|
+
message: `android.remote is ${target.machine}, and its emulator ABI is unknown here: ${hostedPlan.reason}.`,
|
|
2737
|
+
remedy: "Run `stim android` to build for the remote device, or unset android.remote to plan the owned emulator."
|
|
2738
|
+
});
|
|
2739
|
+
placement = hostedPlan.placement;
|
|
2740
|
+
if (hostedPlan.kind === "hosted" && "architecture" in hostedPlan.choice) hostedAbi = hostedPlan.choice.architecture ?? null;
|
|
2741
|
+
image = hostedPlan.kind === "hosted" ? { systemImage: abiKeyed && "systemImage" in hostedPlan.choice ? hostedPlan.choice.systemImage : null } : localImage();
|
|
2742
|
+
} else image = localImage();
|
|
2541
2743
|
if ("refusal" in image) return refuse(image.refusal);
|
|
2542
2744
|
const { abi, runOptions, remoteRunOptions } = androidBuildOptions({
|
|
2543
2745
|
release: build.release,
|
|
@@ -2546,7 +2748,8 @@ async function planAndroid(opts, overrides = {}) {
|
|
|
2546
2748
|
variant: build.variant,
|
|
2547
2749
|
deviceAbi: () => null,
|
|
2548
2750
|
buildProfile: build.profile,
|
|
2549
|
-
targetAbiOnly: build.targetAbiOnly
|
|
2751
|
+
targetAbiOnly: build.targetAbiOnly,
|
|
2752
|
+
hostedAbi
|
|
2550
2753
|
});
|
|
2551
2754
|
let fingerprint;
|
|
2552
2755
|
try {
|
|
@@ -2576,7 +2779,10 @@ async function planAndroid(opts, overrides = {}) {
|
|
|
2576
2779
|
...deps,
|
|
2577
2780
|
note
|
|
2578
2781
|
});
|
|
2579
|
-
printPlan(
|
|
2782
|
+
printPlan(placement ? {
|
|
2783
|
+
...plan,
|
|
2784
|
+
placement
|
|
2785
|
+
} : plan, json);
|
|
2580
2786
|
}
|
|
2581
2787
|
//#endregion
|
|
2582
2788
|
//#region src/commands/android.ts
|
|
@@ -2584,52 +2790,58 @@ function androidCommand(program) {
|
|
|
2584
2790
|
registerAndroid(program);
|
|
2585
2791
|
}
|
|
2586
2792
|
function registerAndroid(program) {
|
|
2587
|
-
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("--remote-build <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).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 <target>", "Run on eas, proxy, or a named approved Mac from remote.machines; auto places on an approved Mac when this Mac is full or busy", (value) => {
|
|
2588
|
-
if (!parseMachine(value)) throw new InvalidArgumentError("expected eas, proxy, auto, or a tailnet machine name");
|
|
2793
|
+
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("--remote-build <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).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 <target>", "Run on eas, proxy, or a named approved Mac from remote.machines; auto places on an approved Mac when this Mac is full or busy; local runs here, whatever android.remote says", (value) => {
|
|
2794
|
+
if (!parseMachine(value)) throw new InvalidArgumentError("expected eas, proxy, auto, local, or a tailnet machine name");
|
|
2589
2795
|
return value;
|
|
2590
2796
|
}).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). Without --device, wait for an owned-device slot (default 600 seconds; --no-wait refuses immediately).").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. Without --device, refuse a full device cap or existing slot queue immediately.").action(async (opts) => {
|
|
2591
2797
|
if (opts.plan) return planAndroid(opts);
|
|
2592
|
-
const root = findProjectRoot
|
|
2798
|
+
const root = findProjectRoot(process.cwd());
|
|
2593
2799
|
if (!root) {
|
|
2594
2800
|
refuseNoProject({ json: Boolean(opts.json) });
|
|
2595
2801
|
return;
|
|
2596
2802
|
}
|
|
2597
|
-
if (!(await
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2803
|
+
if (!(await runAndroidOperation(root, {
|
|
2804
|
+
...opts,
|
|
2805
|
+
waitConflict: waitFlagConflict(process.argv)
|
|
2806
|
+
})).ok) process.exit(runCancellation() ? 130 : 1);
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
function runAndroidOperation(root, opts = {}) {
|
|
2810
|
+
return withNativeBuildRun(root, {
|
|
2811
|
+
command: "android",
|
|
2812
|
+
platform: PLATFORM,
|
|
2813
|
+
slot: opts.slot ?? "default"
|
|
2814
|
+
}, async (claim) => {
|
|
2815
|
+
recordWorkspaceUse(root);
|
|
2816
|
+
const progress = startBuildProgress({
|
|
2817
|
+
root,
|
|
2818
|
+
platform: PLATFORM,
|
|
2819
|
+
slot: opts.slot ?? "default",
|
|
2820
|
+
claim,
|
|
2821
|
+
note: (line) => console.error(chalk.dim(line))
|
|
2822
|
+
});
|
|
2823
|
+
try {
|
|
2824
|
+
return await runAndroid({
|
|
2604
2825
|
root,
|
|
2605
|
-
|
|
2606
|
-
slot: opts.slot
|
|
2607
|
-
|
|
2608
|
-
|
|
2826
|
+
buildMachine: opts.remoteBuild,
|
|
2827
|
+
slot: opts.slot,
|
|
2828
|
+
easProfile: opts.easProfile,
|
|
2829
|
+
json: Boolean(opts.json),
|
|
2830
|
+
metroCheck: opts.metroCheck !== false,
|
|
2831
|
+
useBuildCache: opts.buildCache !== false,
|
|
2832
|
+
variant: opts.variant ?? null,
|
|
2833
|
+
systemImage: opts.systemImage ?? null,
|
|
2834
|
+
deviceProfile: opts.deviceProfile ?? null,
|
|
2835
|
+
remoteDevice: opts.remote ?? null,
|
|
2836
|
+
device: opts.device ?? null,
|
|
2837
|
+
wait: opts.wait,
|
|
2838
|
+
waitConflict: opts.waitConflict,
|
|
2839
|
+
progress
|
|
2609
2840
|
});
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
slot: opts.slot,
|
|
2615
|
-
easProfile: opts.easProfile,
|
|
2616
|
-
json: Boolean(opts.json),
|
|
2617
|
-
metroCheck: opts.metroCheck !== false,
|
|
2618
|
-
useBuildCache: opts.buildCache !== false,
|
|
2619
|
-
variant: opts.variant ?? null,
|
|
2620
|
-
systemImage: opts.systemImage ?? null,
|
|
2621
|
-
deviceProfile: opts.deviceProfile ?? null,
|
|
2622
|
-
remoteDevice: opts.remote ?? null,
|
|
2623
|
-
device: opts.device ?? null,
|
|
2624
|
-
wait: opts.wait,
|
|
2625
|
-
waitConflict: waitFlagConflict(process.argv),
|
|
2626
|
-
progress
|
|
2627
|
-
});
|
|
2628
|
-
} finally {
|
|
2629
|
-
progress.clear();
|
|
2630
|
-
}
|
|
2631
|
-
}, { write: (line) => console.error(chalk.dim(phaseLine("lock", line))) })).ok) process.exit(runCancellation() ? 130 : 1);
|
|
2632
|
-
});
|
|
2841
|
+
} finally {
|
|
2842
|
+
progress.clear();
|
|
2843
|
+
}
|
|
2844
|
+
}, { write: (line) => console.error(chalk.dim(phaseLine("lock", line))) });
|
|
2633
2845
|
}
|
|
2634
2846
|
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, dataFreeBytes, trimCaches, wipeDevice, 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, recordBuild, recordStats = recordRunStats, recordCapacityRefusal: recordRefusal, readEstimates = readRunEstimates, now = Date.now, out = (line) => console.error(line), emit = (line) => console.log(line) } = {}) {
|
|
2635
2847
|
return {
|
|
@@ -2785,9 +2997,9 @@ async function runAndroid(options = {}) {
|
|
|
2785
2997
|
const slot = validateDeviceSlot(options.slot);
|
|
2786
2998
|
const started = now();
|
|
2787
2999
|
const startedAt = new Date(started).toISOString();
|
|
2788
|
-
const
|
|
2789
|
-
if (
|
|
2790
|
-
const { message, remedy } =
|
|
3000
|
+
const problem = projectProblem(root, "android");
|
|
3001
|
+
if (problem) {
|
|
3002
|
+
const { message, remedy } = problem;
|
|
2791
3003
|
out(phaseLine("error", chalk.red(`STIM_NO_PROJECT: ${message}`)));
|
|
2792
3004
|
out(phaseLine("remedy", remedy));
|
|
2793
3005
|
if (json) emit(JSON.stringify({
|
|
@@ -2835,6 +3047,7 @@ async function runAndroid(options = {}) {
|
|
|
2835
3047
|
slot
|
|
2836
3048
|
}
|
|
2837
3049
|
}), progress);
|
|
3050
|
+
setRemoteLogSink((entry) => writer.write(entry));
|
|
2838
3051
|
const record = {
|
|
2839
3052
|
fingerprint: null,
|
|
2840
3053
|
cacheKey: null,
|
|
@@ -2949,6 +3162,7 @@ async function runAndroid(options = {}) {
|
|
|
2949
3162
|
if (!planned.ok) return fail(planned.code, planned.message, planned.remedy, { lines: planned.lines });
|
|
2950
3163
|
const { plan } = planned;
|
|
2951
3164
|
const deviceSlotWait = {
|
|
3165
|
+
automatic: plan.target.kind === "hosted" && plan.target.machine === "auto",
|
|
2952
3166
|
signal: runCancellationSignal(),
|
|
2953
3167
|
waitMs: plan.deviceSlotWaitMs,
|
|
2954
3168
|
displayName: basename(root),
|
|
@@ -2974,6 +3188,16 @@ async function runAndroid(options = {}) {
|
|
|
2974
3188
|
resolveSerial: resolveAvdSerial,
|
|
2975
3189
|
prepare: options.prepareHostedAndroid,
|
|
2976
3190
|
automatic: options.automaticDevicePlacement,
|
|
3191
|
+
...remoteEasFallbackSetting(settings) ? { eas: () => (options.checkEasFallback ?? checkEasFallback)({
|
|
3192
|
+
root,
|
|
3193
|
+
platform: PLATFORM,
|
|
3194
|
+
slot,
|
|
3195
|
+
release,
|
|
3196
|
+
isExpo,
|
|
3197
|
+
tunnelMode: tunnelModeSetting(settings),
|
|
3198
|
+
publicUrl: publicUrlSetting(settings),
|
|
3199
|
+
localOnlyFlags: [...typeof systemImageFlag === "string" ? ["--system-image"] : [], ...typeof deviceProfileFlag === "string" ? ["--device-profile"] : []]
|
|
3200
|
+
}) } : {},
|
|
2977
3201
|
localSelectors: (target) => androidDeviceSelectorRefusal({
|
|
2978
3202
|
settingsContext,
|
|
2979
3203
|
slot,
|
|
@@ -2989,7 +3213,9 @@ async function runAndroid(options = {}) {
|
|
|
2989
3213
|
}),
|
|
2990
3214
|
checkBudget: options.checkBudget,
|
|
2991
3215
|
note: out,
|
|
2992
|
-
phase
|
|
3216
|
+
phase,
|
|
3217
|
+
log: (entry) => writer.write(entry),
|
|
3218
|
+
fromFlag: commandRemoteBackend !== null
|
|
2993
3219
|
});
|
|
2994
3220
|
if ("failure" in hosting) return fail(hosting.failure.code, hosting.failure.message, hosting.failure.remedy);
|
|
2995
3221
|
const { target, hostedTarget, budget, selectors } = hosting;
|
|
@@ -3036,10 +3262,8 @@ async function runAndroid(options = {}) {
|
|
|
3036
3262
|
const reservedPort = project?.metroPort ?? null;
|
|
3037
3263
|
let metroPort = null;
|
|
3038
3264
|
let devServer = null;
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
if (release) phase("metro", `skipped (${variant}: the JS bundle is embedded, no dev server is used)`);
|
|
3042
|
-
else if (metroCheck) {
|
|
3265
|
+
async function prepareMetro() {
|
|
3266
|
+
if (metroCheck) {
|
|
3043
3267
|
const gate = await ensureDevServer({
|
|
3044
3268
|
root,
|
|
3045
3269
|
port: reservedPort,
|
|
@@ -3051,27 +3275,54 @@ async function runAndroid(options = {}) {
|
|
|
3051
3275
|
readState
|
|
3052
3276
|
});
|
|
3053
3277
|
reclaimed = [...reclaimed, ...gate.reclaimed];
|
|
3054
|
-
if (!gate.ok) {
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3278
|
+
if (!gate.ok) return {
|
|
3279
|
+
ok: false,
|
|
3280
|
+
error: {
|
|
3281
|
+
code: gate.code,
|
|
3282
|
+
message: gate.message,
|
|
3283
|
+
remedy: gate.remedy,
|
|
3284
|
+
lines: gate.lines
|
|
3285
|
+
}
|
|
3286
|
+
};
|
|
3058
3287
|
metroPort = gate.port;
|
|
3059
3288
|
devServer = gate.devServer;
|
|
3060
3289
|
phase("metro", `port ${metroPort} (${devServer ? `started: ${devServer.reason}` : `pid ${gate.pid ?? "unknown, started outside Stim"}`})`);
|
|
3061
|
-
return
|
|
3290
|
+
return {
|
|
3291
|
+
ok: true,
|
|
3292
|
+
prepared: { metroPort }
|
|
3293
|
+
};
|
|
3062
3294
|
} else {
|
|
3063
3295
|
const pin = metroPortSetting(root);
|
|
3064
|
-
if (pin.error) {
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3296
|
+
if (pin.error) return {
|
|
3297
|
+
ok: false,
|
|
3298
|
+
error: {
|
|
3299
|
+
code: "STIM_BAD_ARG",
|
|
3300
|
+
message: pin.error,
|
|
3301
|
+
remedy: SETTING_SHAPE_REMEDY
|
|
3302
|
+
}
|
|
3303
|
+
};
|
|
3068
3304
|
metroPort = pin.port ?? reservedPort ?? 8081;
|
|
3069
3305
|
phase("metro", pin.port ?? reservedPort ? `port ${metroPort} (not checked)` : `no reservation; using ${DEFAULT_METRO_PORT} (not checked)`);
|
|
3070
3306
|
}
|
|
3071
|
-
|
|
3072
|
-
|
|
3307
|
+
return {
|
|
3308
|
+
ok: true,
|
|
3309
|
+
prepared: { metroPort }
|
|
3310
|
+
};
|
|
3073
3311
|
}
|
|
3074
|
-
|
|
3312
|
+
const runtime = options.runtimePlan ?? (release ? androidProcessRuntime(async () => {
|
|
3313
|
+
phase("metro", `skipped (${variant}: the JS bundle is embedded, no dev server is used)`);
|
|
3314
|
+
return {
|
|
3315
|
+
ok: true,
|
|
3316
|
+
prepared: { metroPort: null }
|
|
3317
|
+
};
|
|
3318
|
+
}) : androidMetroRuntime(prepareMetro));
|
|
3319
|
+
const preparation = await runtime.prepare();
|
|
3320
|
+
if (!preparation.ok) {
|
|
3321
|
+
const { code, message, remedy, lines } = preparation.error;
|
|
3322
|
+
return fail(code, message, remedy, { lines });
|
|
3323
|
+
}
|
|
3324
|
+
const runtimePreparation = preparation.prepared;
|
|
3325
|
+
metroPort = runtimePreparation.metroPort;
|
|
3075
3326
|
if (remoteContext) {
|
|
3076
3327
|
remoteDevice = makeRemoteDeviceDeps(remoteContext.ctx);
|
|
3077
3328
|
if (metroPort !== null) {
|
|
@@ -3312,6 +3563,7 @@ async function runAndroid(options = {}) {
|
|
|
3312
3563
|
record,
|
|
3313
3564
|
fail,
|
|
3314
3565
|
phase,
|
|
3566
|
+
enterPhase: progress.step,
|
|
3315
3567
|
out,
|
|
3316
3568
|
json,
|
|
3317
3569
|
useBuildCache,
|
|
@@ -3386,6 +3638,8 @@ async function runAndroid(options = {}) {
|
|
|
3386
3638
|
}
|
|
3387
3639
|
try {
|
|
3388
3640
|
return await finishAndroidRun({
|
|
3641
|
+
runtime,
|
|
3642
|
+
runtimePreparation,
|
|
3389
3643
|
slot,
|
|
3390
3644
|
lease: leaseHandle,
|
|
3391
3645
|
releaseLease,
|
|
@@ -3475,4 +3729,4 @@ async function runAndroid(options = {}) {
|
|
|
3475
3729
|
}
|
|
3476
3730
|
}
|
|
3477
3731
|
//#endregion
|
|
3478
|
-
export {
|
|
3732
|
+
export { collectorLogFile as a, androidFacts as c, runAndroidOperation as i, lastBuildRecord as l, registerAndroid as n, killPreviousCollector as o, runAndroid as r, startCollector as s, androidCommand as t };
|