stim 1.16.0 → 1.17.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/{activity-BxwdD81S.mjs → activity-IRvJY_ru.mjs} +23 -3
- package/dist/{agent-device-usage-output-Dpih1Tfa.mjs → agent-device-usage-output-BK41vnzN.mjs} +3 -3
- package/dist/{android-Ift4kVvt.mjs → android--GorydsK.mjs} +679 -317
- package/dist/{android-B_NumVyQ.mjs → android-B_YNZy61.mjs} +7 -43
- package/dist/{android-r2rBL8kV.mjs → android-DE4v59Mb.mjs} +12 -3
- package/dist/{android-cas-8U4DPqeR.mjs → android-cas-ZFpjJBL_.mjs} +6 -5
- package/dist/{app-install-CKWdbXIX.mjs → app-install-VPkI5WEg.mjs} +6 -5
- package/dist/{budget-DjrURfQn.mjs → budget-DM984mnd.mjs} +34 -18
- package/dist/{build-plan-DjeSb2Xl.mjs → build-plan-CmQCoyT-.mjs} +345 -86
- package/dist/{build-slots-rUk77xqh.mjs → build-slots-41v_d2x9.mjs} +35 -25
- package/dist/{cli-BkYZ_6hy.mjs → cli-Daxug5-K.mjs} +17 -17
- package/dist/cli.mjs +1 -1
- package/dist/collector-run.mjs +3 -3
- package/dist/{command-output-DnJMdEY-.mjs → command-output-CDAIFD-8.mjs} +3 -3
- package/dist/{created-devices-D5owjN4C.mjs → created-devices-CpvzBL25.mjs} +1 -1
- package/dist/{dependency-state-B6cMXZab.mjs → dependency-state-CLcBHH2M.mjs} +1 -1
- package/dist/{deps-urbmfXig.mjs → deps-DNWaQs4V.mjs} +1 -1
- package/dist/{dev-client-CroAIjjj.mjs → dev-client-B-XC4uRH.mjs} +2 -2
- package/dist/{device-DZQjF7H5.mjs → device-C8IOoJPv.mjs} +7 -7
- package/dist/device-capacity-D0GWHnTM.mjs +580 -0
- package/dist/device-host-worker.mjs +436 -154
- package/dist/{device-ios-BadmeL2V.mjs → device-ios-Bc7vbGwl.mjs} +75 -44
- package/dist/{device-lease-D-hLqx1b.mjs → device-lease-DpoS36_u.mjs} +2 -2
- package/dist/{device-lease-run-CqjShqWW.mjs → device-lease-run-B8YltIH_.mjs} +3 -3
- package/dist/{device-pool-CUaEWMMm.mjs → device-pool-3o7s5lo4.mjs} +2 -2
- package/dist/{device-remote-D5WVWqOq.mjs → device-remote-hFSkpfQu.mjs} +12 -12
- package/dist/{doctor-Cimf-gGB.mjs → doctor-Cnk9d7Hm.mjs} +32 -51
- package/dist/{error-diagnostics-B9L4Ae0x.mjs → error-diagnostics-C-NMnhrk.mjs} +7 -7
- package/dist/{gc-Bqy4bjEu.mjs → gc-DxCL2A46.mjs} +308 -26
- package/dist/{gradle-BsO1MdsH.mjs → gradle-D7-L2Th3.mjs} +3 -3
- package/dist/{guide-B_uyKTxW.mjs → guide-DjrTQGik.mjs} +1662 -565
- package/dist/{guide-status-CjEZMAD4.mjs → guide-status-Du-ZQ3FD.mjs} +1 -1
- package/dist/hosted-android-DwLS4Mse.mjs +32 -0
- package/dist/{hosted-client-a-WmqE2L.mjs → hosted-client-wk1W_CNW.mjs} +2 -3
- package/dist/hosted-ios-aMo7Cljf.mjs +15 -0
- package/dist/{hosted-logs-D5g041Q3.mjs → hosted-logs-DqYmWtXc.mjs} +16 -16
- package/dist/{hosted-macos-BSZyIb3y.mjs → hosted-macos-dlHXEeF5.mjs} +4 -4
- package/dist/{hosted-ios-CIWelIqf.mjs → hosted-native-C9xJ9rpA.mjs} +77 -42
- package/dist/{idle-DYVymG92.mjs → idle-B2m-Ovod.mjs} +122 -58
- package/dist/{idle-shutdown-CTsDnAde.mjs → idle-shutdown-_3oOV1V_.mjs} +25 -17
- package/dist/{in-use-DvBw0Kxo.mjs → in-use-CvGOUn-x.mjs} +11 -11
- package/dist/{ios-aq3QoGI3.mjs → ios-DE6duQoz.mjs} +170 -88
- package/dist/{ios-BaInn3sW.mjs → ios-DSfnPfse.mjs} +4 -4
- package/dist/{ios-device-FfCN_C8p.mjs → ios-device-pAN4t54-.mjs} +1 -1
- package/dist/ios-state-8L3lgum6.mjs +89 -0
- package/dist/{launch-verify-2DBRizjo.mjs → launch-verify-lTnWZikR.mjs} +2 -2
- package/dist/{logs-CHEVK8zD.mjs → logs-DUoKlDoS.mjs} +36 -23
- package/dist/{client-BTY686R6.mjs → machines-C2XiNwh9.mjs} +278 -20
- package/dist/{macos-CSYEAFmF.mjs → macos-32po3kUq.mjs} +14 -14
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +2 -2
- package/dist/{metro-BeK1ZPz1.mjs → metro-g8NqiJp-.mjs} +1 -1
- package/dist/{metro-gateway-BJ-rxQAB.mjs → metro-gateway-DmslUM30.mjs} +22 -3
- package/dist/{named-ports-Bk_YXEmE.mjs → named-ports-C8m8EQs2.mjs} +2 -2
- package/dist/{native-run-NaBrRFtQ.mjs → native-run-D1Q56rAD.mjs} +17 -6
- package/dist/{native-runtime-DBzRnEKS.mjs → native-runtime-DhJI3IVQ.mjs} +6 -6
- package/dist/offload-worker.mjs +8 -8
- package/dist/{teardown-CL6vDs2Y.mjs → ownership-BMLqyBgJ.mjs} +603 -26
- package/dist/{ownership-DiA16AsN.mjs → ownership-DyRQru0q.mjs} +2 -2
- package/dist/{ports-R2k4Knz3.mjs → ports-4nYqxPWC.mjs} +2 -2
- package/dist/{prebuild-D2fsca_Z.mjs → prebuild-D7RUMkwN.mjs} +3 -3
- package/dist/{preview-DhVbvPAZ.mjs → preview-CxPRIEht.mjs} +7 -7
- package/dist/{project-Du91Ilvc.mjs → project-D47Rh0ly.mjs} +7 -2
- package/dist/{recordings-BIXOzVnr.mjs → recordings-BNgsD1Tr.mjs} +1 -1
- package/dist/{reload-rM9jV1fz.mjs → reload-qZei6iWn.mjs} +62 -35
- package/dist/{remote-cache-C8-V13XN.mjs → remote-cache-Ci4DQYYj.mjs} +3 -3
- package/dist/{run-f4vI6EnK.mjs → run-CkE9y0nc.mjs} +1 -1
- package/dist/{server-bare-CpPGmnmO.mjs → server-bare-BkrSxSsZ.mjs} +1 -1
- package/dist/{server-expo-MC0rHlOC.mjs → server-expo-CHTyXD0G.mjs} +2 -2
- package/dist/server-expo-CeakhI8P.mjs +2 -0
- package/dist/{settings-oTSkkNrM.mjs → settings-Cfd-0r2d.mjs} +10 -9
- package/dist/{settings-ZkDzkzvB.mjs → settings-SR9OmW9h.mjs} +3 -3
- package/dist/settings.schema.json +42 -13
- package/dist/{simslim-B8-7AoTI.mjs → simslim-BWNrc3M3.mjs} +3 -3
- package/dist/{slot-launch-B8VrHxn1.mjs → slot-launch-DmjBmpQV.mjs} +8 -8
- package/dist/{start-CX8Ig-U2.mjs → start-BopZcr4n.mjs} +1 -1
- package/dist/{start-ClDfwXa4.mjs → start-uee1wWjY.mjs} +11 -11
- package/dist/{state-DcW6vOd_.mjs → state-BKa8wNN5.mjs} +1 -1
- package/dist/{state-3DwSQIBK.mjs → state-DyaNTgfR.mjs} +1 -1
- package/dist/{state-C1jB7Q8q.mjs → state-PeQiJuIu.mjs} +2 -2
- package/dist/{stats-CEZ_i5je.mjs → stats-Bq4fJOdB.mjs} +7 -4
- package/dist/{status-BuvBFeII.mjs → status-CzS4bPO9.mjs} +4 -4
- package/dist/{status-Cs7VLg9D.mjs → status-dXX2JX1C.mjs} +125 -35
- package/dist/{stop-Dt_dM16A.mjs → stop-BCwvvs7F.mjs} +2 -2
- package/dist/{stop-Bffozsac.mjs → stop-BjizrQwv.mjs} +48 -27
- package/dist/{stop-B0Yxtmiy.mjs → stop-Cr1d8DSE.mjs} +4 -4
- package/dist/{stop-cause-CidxIqup.mjs → stop-cause-rhmGfwvt.mjs} +1 -1
- package/dist/supervisor-run.d.mts +7 -4
- package/dist/supervisor-run.mjs +26 -28
- package/dist/{support-D4aYJniO.mjs → support-BJPgYCu-.mjs} +44 -19
- package/dist/{support-CAP8qDUF.mjs → support-F9-sr0Oi.mjs} +6 -6
- package/dist/{toolchain-DkUflduf.mjs → toolchain-CNIBTIOv.mjs} +7 -7
- package/dist/{warm-progress-CpGv3Wb6.mjs → warm-progress-DF4JRvYI.mjs} +3 -3
- package/dist/watchman-APYjXSQa.mjs +48 -0
- package/dist/{web-DWUaMp8P.mjs → web-exQtGkoc.mjs} +12 -13
- package/dist/web-run.mjs +4 -4
- package/dist/{workspace-process-lock-BL7Q0HCO.mjs → workspace-process-lock-2mNzOlaB.mjs} +3 -2
- package/dist/{workspace-state-B8-aJ1_5.mjs → workspace-state-DqcCbpE7.mjs} +2 -2
- package/dist/{workspaces-BV4pdHFz.mjs → workspaces-Bcib97-6.mjs} +3 -3
- package/dist/{worktree-jnG8Iph5.mjs → worktree-Dc98cE6_.mjs} +1 -1
- package/dist/{worktree-K-xj9Db0.mjs → worktree-ZpZR3S1k.mjs} +141 -40
- package/package.json +5 -5
- package/dist/device-capacity-BHwxNBlu.mjs +0 -136
- package/dist/ios-state-DS5UpYTH.mjs +0 -48
- package/dist/machines-BIBUdhpj.mjs +0 -265
- package/dist/ownership-hCkPzGmr.mjs +0 -571
- package/dist/server-expo-CVqO2c35.mjs +0 -2
|
@@ -1,62 +1,15 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-CaErVv7t.mjs";
|
|
2
1
|
import { D as withConfigLock$1, H as projectDeviceSlots } from "./config-D0DbpZtM.mjs";
|
|
3
2
|
import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
4
|
-
import { a as formatElapsed, o as formatLongDuration, u as plural } from "./command-output-
|
|
5
|
-
import { a as updateWorkspaceState, r as readWorkspaceState$1, t as clearWorkspaceStateKey } from "./workspace-state-
|
|
6
|
-
import { i as recordGcResult } from "./in-use-
|
|
7
|
-
import { o as idleForMs, r as createActivityReader } from "./activity-
|
|
8
|
-
import { z as ownedAvdSerialResolver } from "./android-
|
|
9
|
-
import {
|
|
3
|
+
import { a as formatElapsed, o as formatLongDuration, u as plural } from "./command-output-CDAIFD-8.mjs";
|
|
4
|
+
import { a as updateWorkspaceState, r as readWorkspaceState$1, t as clearWorkspaceStateKey } from "./workspace-state-DqcCbpE7.mjs";
|
|
5
|
+
import { i as recordGcResult } from "./in-use-CvGOUn-x.mjs";
|
|
6
|
+
import { o as idleForMs, r as createActivityReader } from "./activity-IRvJY_ru.mjs";
|
|
7
|
+
import { z as ownedAvdSerialResolver } from "./android-B_YNZy61.mjs";
|
|
8
|
+
import { g as teardownOwnedIosSim, m as teardownOwnedAvd } from "./ownership-BMLqyBgJ.mjs";
|
|
10
9
|
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
11
10
|
import { dirname } from "node:path";
|
|
12
|
-
import { BUILD_HISTORY_KEY, BUILD_HISTORY_LIMIT, BUILD_PHASES, LAST_BUILD_KEYS, STATS_VERSION, decodeStats, parseMissReason, readRunEstimates, readStats as readStats$1, statsFile, statsProjectKey as statsProjectKey$1, trimSamples, wholePhases, workspaceBuildDetailFile } from "@stim-cli/core/state";
|
|
11
|
+
import { BUILD_HISTORY_KEY, BUILD_HISTORY_LIMIT, BUILD_PHASES, LAST_BUILD_KEYS, STATS_VERSION, decodeStats, isJsonObject, parseMissReason, readRunEstimates, readStats as readStats$1, statsFile, statsProjectKey as statsProjectKey$1, trimCapacityRefusals, trimCapacityWaits, trimSamples, wholePhases, workspaceBuildDetailFile } from "@stim-cli/core/state";
|
|
13
12
|
import chalk from "chalk";
|
|
14
|
-
//#region src/watchman.ts
|
|
15
|
-
/** Runs one watchman command with `--no-spawn`, so Stim never starts a daemon, and parses its JSON answer. */
|
|
16
|
-
const runWatchman = async (args, timeoutMs) => JSON.parse(await getExecutor().runFileAsync("watchman", ["--no-spawn", ...args], { timeoutMs }));
|
|
17
|
-
function parseWatchRoots(payload) {
|
|
18
|
-
const roots = payload?.roots;
|
|
19
|
-
if (!Array.isArray(roots)) return null;
|
|
20
|
-
return roots.filter((root) => typeof root === "string");
|
|
21
|
-
}
|
|
22
|
-
function parseSubscriberNames(payload) {
|
|
23
|
-
if (!payload || typeof payload !== "object" || "error" in payload) return null;
|
|
24
|
-
const subscribers = payload.subscribers;
|
|
25
|
-
if (subscribers === void 0) return [];
|
|
26
|
-
if (!Array.isArray(subscribers)) return null;
|
|
27
|
-
const names = [];
|
|
28
|
-
for (const subscriber of subscribers) {
|
|
29
|
-
const name = subscriber?.info?.name;
|
|
30
|
-
if (typeof name !== "string") return null;
|
|
31
|
-
names.push(name);
|
|
32
|
-
}
|
|
33
|
-
return names;
|
|
34
|
-
}
|
|
35
|
-
function parseTriggerCount(payload) {
|
|
36
|
-
const triggers = payload?.triggers;
|
|
37
|
-
return Array.isArray(triggers) ? triggers.length : null;
|
|
38
|
-
}
|
|
39
|
-
function parseWatchmanPid(payload) {
|
|
40
|
-
const pid = payload?.pid;
|
|
41
|
-
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
42
|
-
}
|
|
43
|
-
/** The connected clients in a `debug-status` answer, or null when the answer does not list them. */
|
|
44
|
-
function parseWatchmanClients(payload) {
|
|
45
|
-
if (!payload || typeof payload !== "object" || "error" in payload) return null;
|
|
46
|
-
const clients = payload.clients;
|
|
47
|
-
if (!Array.isArray(clients)) return null;
|
|
48
|
-
const parsed = [];
|
|
49
|
-
for (const client of clients) {
|
|
50
|
-
const peer = client?.peer;
|
|
51
|
-
if (typeof peer?.pid !== "number") return null;
|
|
52
|
-
parsed.push({
|
|
53
|
-
pid: peer.pid,
|
|
54
|
-
name: typeof peer.name === "string" ? peer.name : null
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
return parsed;
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
13
|
//#region src/engine/stats.ts
|
|
61
14
|
const PLACEMENT_MAX_AGE_MS = 6048e5;
|
|
62
15
|
function emptyStats() {
|
|
@@ -116,12 +69,16 @@ function updateStats(record, run, now) {
|
|
|
116
69
|
[placement.machine]: applyPlacement(buildMachines?.[placement.machine], placement)
|
|
117
70
|
};
|
|
118
71
|
}
|
|
72
|
+
const capacityRefusals = trimCapacityRefusals(record.capacityRefusals ?? [], now);
|
|
73
|
+
const capacityWaits = trimCapacityWaits(record.capacityWaits ?? [], now);
|
|
119
74
|
return {
|
|
120
75
|
version: STATS_VERSION,
|
|
121
76
|
machine,
|
|
122
77
|
projects,
|
|
123
78
|
...Object.keys(history).length ? { history } : {},
|
|
124
79
|
...placements?.length ? { placements } : {},
|
|
80
|
+
...capacityRefusals.length ? { capacityRefusals } : {},
|
|
81
|
+
...capacityWaits.length ? { capacityWaits } : {},
|
|
125
82
|
...buildMachines && Object.keys(buildMachines).length ? { buildMachines } : {}
|
|
126
83
|
};
|
|
127
84
|
}
|
|
@@ -130,6 +87,7 @@ function buildPlacement(run, before, at) {
|
|
|
130
87
|
const buildMs = wholeMs(placement.decision === "offloaded" ? placement.buildMs : run.coldBuildMs);
|
|
131
88
|
const localEstimateMs = wholeMs(before?.lastColdBuildMs);
|
|
132
89
|
const slotWaitMs = wholeMs(placement.slotWaitMs);
|
|
90
|
+
const deviceSlotWaitMs = wholeMs(placement.deviceSlotWaitMs);
|
|
133
91
|
return {
|
|
134
92
|
at,
|
|
135
93
|
project: run.projectKey,
|
|
@@ -139,6 +97,7 @@ function buildPlacement(run, before, at) {
|
|
|
139
97
|
...placement.machine ? { machine: placement.machine } : {},
|
|
140
98
|
...buildMs > 0 ? { buildMs } : {},
|
|
141
99
|
...slotWaitMs > 0 ? { slotWaitMs } : {},
|
|
100
|
+
...deviceSlotWaitMs > 0 ? { deviceSlotWaitMs } : {},
|
|
142
101
|
...localEstimateMs > 0 ? { localEstimateMs } : {},
|
|
143
102
|
...run.failed ? { failed: true } : {}
|
|
144
103
|
};
|
|
@@ -179,12 +138,53 @@ function recordRunStats(run, now) {
|
|
|
179
138
|
};
|
|
180
139
|
});
|
|
181
140
|
}
|
|
141
|
+
function recordCapacityRefusal(event, now) {
|
|
142
|
+
try {
|
|
143
|
+
withConfigLock$1(() => {
|
|
144
|
+
const path = statsFile();
|
|
145
|
+
const loaded = loadForUpdate(path, now, false);
|
|
146
|
+
if (!loaded.record || loaded.newerVersion !== null) return;
|
|
147
|
+
const capacityRefusals = trimCapacityRefusals([...loaded.record.capacityRefusals ?? [], {
|
|
148
|
+
...event,
|
|
149
|
+
at: new Date(now).toISOString(),
|
|
150
|
+
kind: "device"
|
|
151
|
+
}], now);
|
|
152
|
+
writeStats(path, {
|
|
153
|
+
...loaded.record,
|
|
154
|
+
capacityRefusals
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
} catch {}
|
|
158
|
+
}
|
|
159
|
+
function recordCapacityWait(event, now) {
|
|
160
|
+
try {
|
|
161
|
+
withConfigLock$1(() => {
|
|
162
|
+
const path = statsFile();
|
|
163
|
+
const loaded = loadForUpdate(path, now, false);
|
|
164
|
+
if (!loaded.record || loaded.newerVersion !== null) return;
|
|
165
|
+
const capacityWaits = trimCapacityWaits([...loaded.record.capacityWaits ?? [], {
|
|
166
|
+
platform: event.platform,
|
|
167
|
+
max: event.max,
|
|
168
|
+
workspace: event.workspace,
|
|
169
|
+
ms: wholeMs(event.ms),
|
|
170
|
+
...event.reclaimed && Number.isInteger(event.reclaimed) && event.reclaimed > 0 ? { reclaimed: event.reclaimed } : {},
|
|
171
|
+
at: new Date(now).toISOString(),
|
|
172
|
+
kind: "device-wait"
|
|
173
|
+
}], now);
|
|
174
|
+
writeStats(path, {
|
|
175
|
+
...loaded.record,
|
|
176
|
+
capacityWaits
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
} catch {}
|
|
180
|
+
}
|
|
182
181
|
function createRunRecorder({ platform, write, now, note, phases, deviceSetup }) {
|
|
183
182
|
let projectKey = null;
|
|
184
183
|
let cacheKey = null;
|
|
185
184
|
let coldBuildMs = 0;
|
|
186
185
|
let podsMs = 0;
|
|
187
186
|
let placement = null;
|
|
187
|
+
let deviceSlotWaitMs = 0;
|
|
188
188
|
let recorded = false;
|
|
189
189
|
return {
|
|
190
190
|
setProject(key) {
|
|
@@ -199,6 +199,12 @@ function createRunRecorder({ platform, write, now, note, phases, deviceSetup })
|
|
|
199
199
|
setPodsMs(ms) {
|
|
200
200
|
podsMs = wholeMs(ms);
|
|
201
201
|
},
|
|
202
|
+
addDeviceSlotWaitMs(ms) {
|
|
203
|
+
deviceSlotWaitMs += wholeMs(ms);
|
|
204
|
+
},
|
|
205
|
+
deviceSlotWaitMs() {
|
|
206
|
+
return deviceSlotWaitMs || void 0;
|
|
207
|
+
},
|
|
202
208
|
setPlacement(next) {
|
|
203
209
|
placement = next;
|
|
204
210
|
},
|
|
@@ -219,7 +225,10 @@ function createRunRecorder({ platform, write, now, note, phases, deviceSetup })
|
|
|
219
225
|
...podsMs > 0 ? { podsMs } : {},
|
|
220
226
|
...Object.keys(ran).length ? { phases: ran } : {},
|
|
221
227
|
...failed || deviceSetup?.() === void 0 ? {} : { deviceSetup: deviceSetup() },
|
|
222
|
-
...placement ? { placement
|
|
228
|
+
...placement ? { placement: {
|
|
229
|
+
...placement,
|
|
230
|
+
...deviceSlotWaitMs > 0 ? { deviceSlotWaitMs } : {}
|
|
231
|
+
} } : {}
|
|
223
232
|
}, now());
|
|
224
233
|
if (outcome?.note) note(outcome.note);
|
|
225
234
|
} catch (error) {
|
|
@@ -228,7 +237,7 @@ function createRunRecorder({ platform, write, now, note, phases, deviceSetup })
|
|
|
228
237
|
}
|
|
229
238
|
};
|
|
230
239
|
}
|
|
231
|
-
function loadForUpdate(path, now) {
|
|
240
|
+
function loadForUpdate(path, now, recoverCorrupt = true) {
|
|
232
241
|
let text;
|
|
233
242
|
try {
|
|
234
243
|
text = readFileSync(path, "utf-8");
|
|
@@ -241,6 +250,11 @@ function loadForUpdate(path, now) {
|
|
|
241
250
|
}
|
|
242
251
|
const parsed = decodeStats(text);
|
|
243
252
|
if (!parsed.record && parsed.newerVersion === null) {
|
|
253
|
+
if (!recoverCorrupt) return {
|
|
254
|
+
record: null,
|
|
255
|
+
note: null,
|
|
256
|
+
newerVersion: null
|
|
257
|
+
};
|
|
244
258
|
const aside = `${path}.corrupt-${now}`;
|
|
245
259
|
renameSync(path, aside);
|
|
246
260
|
return {
|
|
@@ -469,6 +483,7 @@ const NO_BUILD_PROGRESS = {
|
|
|
469
483
|
deviceSetupKnown: () => void 0,
|
|
470
484
|
place: () => {},
|
|
471
485
|
waitingOn: () => {},
|
|
486
|
+
waitingFor: () => {},
|
|
472
487
|
output: () => {},
|
|
473
488
|
durations: () => ({}),
|
|
474
489
|
clear: () => {}
|
|
@@ -578,6 +593,7 @@ function startBuildProgress({ root, platform, slot, claim, now = Date.now, note
|
|
|
578
593
|
record.outcome = outcome;
|
|
579
594
|
if (projectKey) record.estimate = estimateBuild(projectHistory(projectKey), platform, outcome, record.deviceSetup);
|
|
580
595
|
};
|
|
596
|
+
const waits = /* @__PURE__ */ new Map();
|
|
581
597
|
return {
|
|
582
598
|
step(phase) {
|
|
583
599
|
if (phase === record.phase) return;
|
|
@@ -636,6 +652,15 @@ function startBuildProgress({ root, platform, slot, claim, now = Date.now, note
|
|
|
636
652
|
};
|
|
637
653
|
write();
|
|
638
654
|
},
|
|
655
|
+
waitingFor(info, kind) {
|
|
656
|
+
if (info) waits.set(info.kind, info);
|
|
657
|
+
else if (kind) waits.delete(kind);
|
|
658
|
+
else waits.clear();
|
|
659
|
+
const first = [...waits.values()].toSorted((a, b) => Date.parse(a.since) - Date.parse(b.since))[0];
|
|
660
|
+
if (first) record.waitingFor = first;
|
|
661
|
+
else delete record.waitingFor;
|
|
662
|
+
write();
|
|
663
|
+
},
|
|
639
664
|
waitingOn(holder) {
|
|
640
665
|
if (holder === null) {
|
|
641
666
|
if (!record.waitingOn) return;
|
|
@@ -684,6 +709,7 @@ function completedPhaseDurations(phases) {
|
|
|
684
709
|
return Object.keys(durations).length ? durations : void 0;
|
|
685
710
|
}
|
|
686
711
|
const HISTORY_FIELDS = [
|
|
712
|
+
"devicePlacement",
|
|
687
713
|
"platform",
|
|
688
714
|
"status",
|
|
689
715
|
"configuration",
|
|
@@ -728,6 +754,28 @@ function recordFinishedBuild(root, record, { update = updateWorkspaceState, now
|
|
|
728
754
|
slot: own?.slot ?? "default",
|
|
729
755
|
phases: own ? phaseDurations(own.phases, now()) : {}
|
|
730
756
|
};
|
|
757
|
+
const slot = own?.slot ?? "default";
|
|
758
|
+
const slots = isJsonObject(state.deviceSlots) ? state.deviceSlots : {};
|
|
759
|
+
const savedSlot = isJsonObject(slots[slot]) ? slots[slot] : {};
|
|
760
|
+
const savedDevice = slot === "default" ? state[platform] : savedSlot[platform];
|
|
761
|
+
if (record.devicePlacement || isJsonObject(savedDevice)) {
|
|
762
|
+
const device = isJsonObject(savedDevice) ? { ...savedDevice } : {};
|
|
763
|
+
if (record.devicePlacement) device.devicePlacement = record.devicePlacement;
|
|
764
|
+
else delete device.devicePlacement;
|
|
765
|
+
state = slot === "default" ? {
|
|
766
|
+
...state,
|
|
767
|
+
[platform]: device
|
|
768
|
+
} : {
|
|
769
|
+
...state,
|
|
770
|
+
deviceSlots: {
|
|
771
|
+
...slots,
|
|
772
|
+
[slot]: {
|
|
773
|
+
...savedSlot,
|
|
774
|
+
[platform]: device
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
}
|
|
731
779
|
return withHistoryEntry({
|
|
732
780
|
...state,
|
|
733
781
|
lastBuild: record,
|
|
@@ -770,6 +818,7 @@ function parseActiveBuild(value) {
|
|
|
770
818
|
const missReason = parseMissReason(record.missReason);
|
|
771
819
|
const placement = parsePlacement(record.placement);
|
|
772
820
|
const waitingOn = parseWaitingOn(record.waitingOn);
|
|
821
|
+
const waitingFor = parseWaitingFor(record.waitingFor);
|
|
773
822
|
const estimate = parseEstimate(record.estimate);
|
|
774
823
|
return {
|
|
775
824
|
platform: record.platform,
|
|
@@ -782,6 +831,7 @@ function parseActiveBuild(value) {
|
|
|
782
831
|
...missReason && record.missProvisional === true ? { missProvisional: true } : {},
|
|
783
832
|
...placement ? { placement } : {},
|
|
784
833
|
...waitingOn ? { waitingOn } : {},
|
|
834
|
+
...waitingFor ? { waitingFor } : {},
|
|
785
835
|
...typeof record.deviceSetup === "boolean" ? { deviceSetup: record.deviceSetup } : {},
|
|
786
836
|
...record.outcome === "hit" || record.outcome === "cold" ? { outcome: record.outcome } : {},
|
|
787
837
|
...estimate ? { estimate } : {},
|
|
@@ -809,6 +859,19 @@ function parsePlacement(value) {
|
|
|
809
859
|
phaseStartedAt
|
|
810
860
|
};
|
|
811
861
|
}
|
|
862
|
+
function parseWaitingFor(value) {
|
|
863
|
+
if (!value || typeof value !== "object") return null;
|
|
864
|
+
const { kind, inUse, max, since } = value;
|
|
865
|
+
if (kind !== "build-slot" && kind !== "device-slot") return null;
|
|
866
|
+
if (!Number.isInteger(inUse) || inUse < 0 || !Number.isInteger(max) || max <= 0) return null;
|
|
867
|
+
if (typeof since !== "string" || !Number.isFinite(Date.parse(since))) return null;
|
|
868
|
+
return {
|
|
869
|
+
kind,
|
|
870
|
+
inUse,
|
|
871
|
+
max,
|
|
872
|
+
since
|
|
873
|
+
};
|
|
874
|
+
}
|
|
812
875
|
function parseWaitingOn(value) {
|
|
813
876
|
const path = value?.path;
|
|
814
877
|
return typeof path === "string" && path ? { path } : null;
|
|
@@ -910,7 +973,8 @@ function buildReport(record, { state, history }) {
|
|
|
910
973
|
...record.missReason ? { missReason: record.missReason } : {},
|
|
911
974
|
...record.missReason && record.missProvisional ? { missProvisional: true } : {},
|
|
912
975
|
placement: record.placement ?? "local",
|
|
913
|
-
...record.waitingOn ? { waitingOn: record.waitingOn } : {}
|
|
976
|
+
...record.waitingOn ? { waitingOn: record.waitingOn } : {},
|
|
977
|
+
...record.waitingFor ? { waitingFor: record.waitingFor } : {}
|
|
914
978
|
};
|
|
915
979
|
}
|
|
916
980
|
function remainingText(remainingMs) {
|
|
@@ -1096,4 +1160,4 @@ function shutDownIdleDevices(devices, idleMs, recollect) {
|
|
|
1096
1160
|
};
|
|
1097
1161
|
}
|
|
1098
1162
|
//#endregion
|
|
1099
|
-
export {
|
|
1163
|
+
export { recordRunStats as C, recordCapacityWait as S, tapBuildLog as _, parseIdleDuration as a, readStats$1 as b, ACTIVE_BUILD_KEY as c, buildReport as d, buildStatusLine as f, startBuildProgress as g, recordFinishedBuild as h, idleShutdownCandidates as i, NO_BUILD_PROGRESS as l, parseActiveBuild as m, collectOwnedDeviceActivity as n, shutDownIdleDevices as o, estimateBuild as p, idleDeviceLines as r, workspaceBuildInProgress as s, collectIdleDevices as t, activeBuildState as u, createRunRecorder as v, statsProjectKey$1 as w, recordCapacityRefusal as x, readRunEstimates as y };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { R as deviceSlotKey, _ as loadConfig$1 } from "./config-D0DbpZtM.mjs";
|
|
2
|
-
import { o as formatLongDuration } from "./command-output-
|
|
3
|
-
import { a as updateWorkspaceState, r as readWorkspaceState$1 } from "./workspace-state-
|
|
4
|
-
import { o as canonicalPath } from "./in-use-
|
|
5
|
-
import {
|
|
6
|
-
import { u as listAllIosSims } from "./ios-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { o as formatLongDuration } from "./command-output-CDAIFD-8.mjs";
|
|
3
|
+
import { a as updateWorkspaceState, r as readWorkspaceState$1 } from "./workspace-state-DqcCbpE7.mjs";
|
|
4
|
+
import { o as canonicalPath } from "./in-use-CvGOUn-x.mjs";
|
|
5
|
+
import { m as workspaceDeviceLastUseAt } from "./activity-IRvJY_ru.mjs";
|
|
6
|
+
import { u as listAllIosSims } from "./ios-DSfnPfse.mjs";
|
|
7
|
+
import { g as teardownOwnedIosSim, m as teardownOwnedAvd } from "./ownership-BMLqyBgJ.mjs";
|
|
8
|
+
import { n as collectOwnedDeviceActivity, s as workspaceBuildInProgress } from "./idle-B2m-Ovod.mjs";
|
|
9
|
+
import { DEVICE_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, readDeviceIdleShutdowns } from "@stim-cli/core/state";
|
|
9
10
|
//#region src/devices/idle-shutdown.ts
|
|
10
11
|
const SIM_LIST_TIMEOUT_MS = 1e4;
|
|
11
12
|
const MINUTE_MS = 6e4;
|
|
@@ -30,21 +31,26 @@ function listSims() {
|
|
|
30
31
|
return [];
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
|
-
/**
|
|
34
|
+
/** Booted owned devices idle for `idleMs`, in one workspace or all registered workspaces when root is absent. */
|
|
34
35
|
function dueIdleDevices(root, idleMs, now = Date.now()) {
|
|
35
36
|
const config = loadConfig$1();
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
if (!config) return [];
|
|
38
|
+
const self = root === void 0 ? void 0 : canonicalPath(root);
|
|
39
|
+
const projects = Object.fromEntries(Object.entries(config.projects).filter(([path]) => {
|
|
40
|
+
if (self !== void 0 && canonicalPath(path) !== self) return false;
|
|
41
|
+
const usedAt = workspaceDeviceLastUseAt(path);
|
|
42
|
+
return !Number.isFinite(usedAt) || now - usedAt >= idleMs;
|
|
43
|
+
}));
|
|
44
|
+
if (!Object.keys(projects).length) return [];
|
|
45
|
+
const builds = new Map(Object.keys(projects).map((path) => [path, workspaceBuildInProgress(path)]));
|
|
40
46
|
return collectOwnedDeviceActivity({
|
|
41
47
|
...config,
|
|
42
|
-
projects
|
|
48
|
+
projects
|
|
43
49
|
}, listSims(), now).flatMap((device) => {
|
|
44
50
|
const idleForMs = idleShutdownDueMs(device.activity, {
|
|
45
51
|
idleMs,
|
|
46
52
|
now,
|
|
47
|
-
buildInProgress
|
|
53
|
+
buildInProgress: builds.get(device.project) ?? true
|
|
48
54
|
});
|
|
49
55
|
return idleForMs === null ? [] : [{
|
|
50
56
|
device,
|
|
@@ -57,9 +63,10 @@ function dueIdleDevices(root, idleMs, now = Date.now()) {
|
|
|
57
63
|
* and records why. The caller holds the workspace's native-run lock, so no `ios` or `android` run is booting or
|
|
58
64
|
* installing on them.
|
|
59
65
|
*/
|
|
60
|
-
function shutDownIdleDevices(root, idleMs, log, now = Date.now()) {
|
|
66
|
+
function shutDownIdleDevices(root, idleMs, log, now = Date.now(), { only, reason } = {}) {
|
|
61
67
|
let shutDown = 0;
|
|
62
68
|
for (const { device, idleForMs } of dueIdleDevices(root, idleMs, now)) {
|
|
69
|
+
if (only && (device.kind !== only.kind || device.id !== only.id || device.project !== only.project || device.slot !== only.slot)) continue;
|
|
63
70
|
const what = `${device.kind === "ios" ? "simulator" : "emulator"} ${device.name}`;
|
|
64
71
|
const outcome = device.kind === "ios" ? teardownOwnedIosSim(device.id, {
|
|
65
72
|
label: device.name,
|
|
@@ -81,7 +88,8 @@ function shutDownIdleDevices(root, idleMs, log, now = Date.now()) {
|
|
|
81
88
|
...readDeviceIdleShutdowns(state),
|
|
82
89
|
[deviceSlotKey(device.kind, device.slot)]: {
|
|
83
90
|
at: new Date(now).toISOString(),
|
|
84
|
-
idleMinutes
|
|
91
|
+
idleMinutes,
|
|
92
|
+
...reason ? { reason } : {}
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
95
|
}));
|
|
@@ -95,7 +103,7 @@ function shutDownIdleDevices(root, idleMs, log, now = Date.now()) {
|
|
|
95
103
|
log({
|
|
96
104
|
level: "info",
|
|
97
105
|
event: "device_idle_shutdown",
|
|
98
|
-
msg: `shut down ${what}, idle ${formatLongDuration(idleForMs)}`
|
|
106
|
+
msg: `shut down ${what}, idle ${formatLongDuration(idleForMs)}${reason === DEVICE_RECLAIM_REASON ? ", reclaimed for a waiting run" : ""}`
|
|
99
107
|
});
|
|
100
108
|
} else if (outcome.status !== "missing") log({
|
|
101
109
|
level: "warn",
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { p as getProject } from "./config-D0DbpZtM.mjs";
|
|
2
2
|
import { n as ownership_claim_exports } from "./process-identity-BmRm1qV0.mjs";
|
|
3
|
-
import { r as readWorkspaceState$1, v as workspaceDir } from "./workspace-state-
|
|
4
|
-
import { o as readWebRecord, u as webFacts } from "./state-
|
|
5
|
-
import { h as listBuildLocks } from "./device-lease-
|
|
6
|
-
import { n as listBuildSlots } from "./build-slots-
|
|
7
|
-
import { n as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { r as readWorkspaceState$1, v as workspaceDir } from "./workspace-state-DqcCbpE7.mjs";
|
|
4
|
+
import { o as readWebRecord, u as webFacts } from "./state-PeQiJuIu.mjs";
|
|
5
|
+
import { h as listBuildLocks } from "./device-lease-DpoS36_u.mjs";
|
|
6
|
+
import { n as listBuildSlots } from "./build-slots-41v_d2x9.mjs";
|
|
7
|
+
import { n as managedLockHolders, t as resolveSupervisorTarget } from "./ownership-BMLqyBgJ.mjs";
|
|
8
|
+
import { n as workspaceProcessLockError, r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-2mNzOlaB.mjs";
|
|
9
|
+
import { i as macosRuntimeClaim } from "./state-DyaNTgfR.mjs";
|
|
10
10
|
import { lstatSync, readdirSync, rmSync, rmdirSync, unlinkSync } from "node:fs";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { realpathSync as realpathSync$1 } from "fs";
|
|
13
13
|
import { resolve as resolve$1 } from "path";
|
|
14
|
-
import {
|
|
14
|
+
import { hostedNativeRecords, macosAppState, parseHostedNativePlacement, readMacosRecord, unreadableHostedNative } from "@stim-cli/core/state";
|
|
15
15
|
//#region src/commands/gc/paths.ts
|
|
16
16
|
function canonicalPath(p) {
|
|
17
17
|
try {
|
|
@@ -67,9 +67,9 @@ function workspaceInUse(root, { supervisor = true, managedLocks = true, hosted =
|
|
|
67
67
|
if (claims.live.length) reasons.push(NATIVE_RUN_HELD);
|
|
68
68
|
else if (claims.unresolved[0]) reasons.push(`its native-run.lock cannot be resolved: ${claims.unresolved[0].reason}`);
|
|
69
69
|
}
|
|
70
|
-
for (const [slot, record] of Object.entries(hosted ?
|
|
71
|
-
const placement =
|
|
72
|
-
reasons.push(placement ? `its iOS simulator runs on ${placement.machine}` :
|
|
70
|
+
for (const platform of ["ios", "android"]) for (const [slot, record] of Object.entries(hosted ? hostedNativeRecords(readWorkspaceState$1(root), platform) : {})) {
|
|
71
|
+
const placement = parseHostedNativePlacement(record, platform);
|
|
72
|
+
reasons.push(placement ? `its ${platform === "ios" ? "iOS simulator" : "Android emulator"} runs on ${placement.machine}` : unreadableHostedNative(slot, platform));
|
|
73
73
|
}
|
|
74
74
|
const self = canonicalPath(root);
|
|
75
75
|
for (const [kind, entries] of [["build lock", listBuildLocks()], ["build slot", listBuildSlots()]]) for (const entry of entries) {
|