@deeeed/metamask-harness 0.92.24 → 0.92.26
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/CHANGELOG.md +16 -0
- package/dist/adapters/mobile/provision.js +70 -6
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.92.26 - 2026-10-18
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Pin `@farmslot/recipe-runner` 0.39.1, with the aligned `@farmslot/adapter-sdk` 0.18.1, `adapter-node` 0.1.35, `adapter-rn` 0.22.24, `adapter-web` 0.10.16, `agent-runtime` 0.29.1 and `recipe-cli` 0.23.2. Network capture summaries now redact credential-like path segments (20 or more base64url characters mixing letters and digits), so a client write key in a request path no longer reaches `network/run-summary.json`. Long resource ids in a path, such as UUIDs and hashes, are redacted as well.
|
|
10
|
+
|
|
11
|
+
## 0.92.25 - 2026-10-18
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Pin `@farmslot/handoff` to 0.3.2 exactly, like the other `@farmslot` packages. The `^0.3.1` range let a global install resolve 0.3.2 while CI tested the locked 0.3.1. 0.3.2 no longer treats opaque diagnostic session IDs or underscore-bearing recipe identifiers as secrets when it scrubs a learning package.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Mobile: `provision runway` (and `install --runway`, which uses it) leaves the simulator in the power state it found. A simulator that simctl reported Shutdown is booted for the install and shut down again afterwards, also when the install fails; one that was already booted, booting or in an unknown state is left running. Before, every provisioned simulator stayed booted until something stopped it, which kept idle simulators running on farm machines for days. The installed-app check now reads a Shutdown simulator's installed bundles from its data directory, since simctl cannot look inside a Shutdown device, so the identity-match skip and doctor's `app-installed-deps-pending` keep working on a simulator provisioning left off.
|
|
20
|
+
|
|
5
21
|
## 0.92.24 - 2026-10-18
|
|
6
22
|
|
|
7
23
|
### Fixed
|
|
@@ -115,10 +115,17 @@ async function provisionRunwayMobile(target, options) {
|
|
|
115
115
|
const cacheRoot = options.cacheRoot ?? defaultRunwayCacheRoot();
|
|
116
116
|
const cache = ensureCachedArtifact(repo, resolved.branch, resolved.runId, cacheRoot, options);
|
|
117
117
|
log(options, `runway: installing ${cache.artifact.appPath} on ${sim.name}`);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
const device = sim.udid ?? sim.name;
|
|
119
|
+
const wasBooted = simulatorBooted(device);
|
|
120
|
+
let baselinePath;
|
|
121
|
+
try {
|
|
122
|
+
bootSimulator(device, options);
|
|
123
|
+
execFileSync("xcrun", ["simctl", "install", device, cache.artifact.appPath], { stdio: ["ignore", "ignore", "pipe"] });
|
|
124
|
+
preapproveDeepLinkScheme(device, RUNWAY_IOS_METADATA.bundleId, options);
|
|
125
|
+
baselinePath = writeRunwayBaseline(resolvedTarget, slot, platform, resolved, cache.artifact, sim, false, options.runtimeDir);
|
|
126
|
+
} finally {
|
|
127
|
+
if (!wasBooted) shutdownSimulator(device, options);
|
|
128
|
+
}
|
|
122
129
|
return {
|
|
123
130
|
schemaVersion: 1,
|
|
124
131
|
command: "provision",
|
|
@@ -444,6 +451,21 @@ function bootSimulator(device, options) {
|
|
|
444
451
|
log(options, `runway: bootstatus wait for ${device} did not confirm; continuing to install`);
|
|
445
452
|
}
|
|
446
453
|
}
|
|
454
|
+
function simulatorBooted(device) {
|
|
455
|
+
try {
|
|
456
|
+
return findSimulator(device)?.state !== "Shutdown";
|
|
457
|
+
} catch {
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function shutdownSimulator(device, options) {
|
|
462
|
+
try {
|
|
463
|
+
execFileSync("xcrun", ["simctl", "shutdown", device], { stdio: ["ignore", "ignore", "ignore"], timeout: 3e4 });
|
|
464
|
+
log(options, `runway: shut ${device} down again; it was off before provisioning`);
|
|
465
|
+
} catch (error) {
|
|
466
|
+
log(options, `runway: could not shut ${device} down again (${errorMessage(error)}); it may still be running`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
447
469
|
function restartSimulator(device, options) {
|
|
448
470
|
log(options, `runway: simulator ${device} did not answer the app probe; restarting it once`);
|
|
449
471
|
execFileSync("xcrun", ["simctl", "shutdown", device], {
|
|
@@ -495,12 +517,15 @@ function ensureSimulator(name, runtime, deviceType) {
|
|
|
495
517
|
const udid = execFileSync("xcrun", ["simctl", "create", name, resolvedDeviceType, resolvedRuntime], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
496
518
|
return { name, udid: udid || name, created: true, runtime: resolvedRuntime, deviceType: resolvedDeviceType };
|
|
497
519
|
}
|
|
498
|
-
function
|
|
520
|
+
function listSimulatorDevices() {
|
|
499
521
|
const data = execJson(
|
|
500
522
|
"xcrun",
|
|
501
523
|
["simctl", "list", "devices", "--json"]
|
|
502
524
|
);
|
|
503
|
-
|
|
525
|
+
return Object.values(data.devices ?? {}).flat().filter((device) => device.isAvailable !== false && Boolean(device.name && device.udid));
|
|
526
|
+
}
|
|
527
|
+
function findSimulator(target) {
|
|
528
|
+
const devices = listSimulatorDevices();
|
|
504
529
|
const exact = devices.find((device) => device.udid.toLowerCase() === target.toLowerCase());
|
|
505
530
|
if (exact) return exact;
|
|
506
531
|
const matches = target === "booted" ? devices.filter((device) => device.state === "Booted") : devices.filter((device) => device.name === target);
|
|
@@ -588,6 +613,8 @@ function readInstalledBaselineArtifact(target, sim, runtimeDir) {
|
|
|
588
613
|
return { runId, record };
|
|
589
614
|
}
|
|
590
615
|
function appInstalled(device) {
|
|
616
|
+
const shutdown = shutdownSimulatorData(device);
|
|
617
|
+
if (shutdown) return bundleInstalledOnDisk(shutdown, RUNWAY_IOS_METADATA.bundleId);
|
|
591
618
|
try {
|
|
592
619
|
execFileSync("xcrun", ["simctl", "get_app_container", device, RUNWAY_IOS_METADATA.bundleId, "app"], {
|
|
593
620
|
stdio: ["ignore", "ignore", "ignore"],
|
|
@@ -601,6 +628,43 @@ function appInstalled(device) {
|
|
|
601
628
|
return false;
|
|
602
629
|
}
|
|
603
630
|
}
|
|
631
|
+
function shutdownSimulatorData(device) {
|
|
632
|
+
let sim;
|
|
633
|
+
try {
|
|
634
|
+
sim = findSimulator(device);
|
|
635
|
+
} catch {
|
|
636
|
+
return void 0;
|
|
637
|
+
}
|
|
638
|
+
return sim?.state === "Shutdown" ? sim.dataPath : void 0;
|
|
639
|
+
}
|
|
640
|
+
function bundleInstalledOnDisk(dataPath, bundleId) {
|
|
641
|
+
const root = path.join(dataPath, "Containers", "Bundle", "Application");
|
|
642
|
+
if (!fs.existsSync(root)) return false;
|
|
643
|
+
for (const container of fs.readdirSync(root)) {
|
|
644
|
+
const dir = path.join(root, container);
|
|
645
|
+
let entries;
|
|
646
|
+
try {
|
|
647
|
+
entries = fs.readdirSync(dir);
|
|
648
|
+
} catch {
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
for (const app of entries.filter((entry) => entry.endsWith(".app"))) {
|
|
652
|
+
const plist = path.join(dir, app, "Info.plist");
|
|
653
|
+
if (!fs.existsSync(plist)) continue;
|
|
654
|
+
try {
|
|
655
|
+
const id = execFileSync("plutil", ["-extract", "CFBundleIdentifier", "raw", "-o", "-", plist], {
|
|
656
|
+
encoding: "utf8",
|
|
657
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
658
|
+
timeout: 5e3
|
|
659
|
+
}).trim();
|
|
660
|
+
if (id === bundleId) return true;
|
|
661
|
+
} catch {
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return false;
|
|
667
|
+
}
|
|
604
668
|
function appInstalledWithRecovery(device, options) {
|
|
605
669
|
try {
|
|
606
670
|
return appInstalled(device);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deeeed/metamask-harness",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mm-harness": "bin/mm-harness"
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
"check:syntax": "find . -name '*.mjs' -print0 | xargs -0 -n1 node --check"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@farmslot/adapter-node": "0.1.
|
|
25
|
-
"@farmslot/adapter-rn": "0.22.
|
|
26
|
-
"@farmslot/adapter-sdk": "0.18.
|
|
27
|
-
"@farmslot/adapter-web": "0.10.
|
|
28
|
-
"@farmslot/agent-runtime": "0.29.
|
|
29
|
-
"@farmslot/handoff": "
|
|
24
|
+
"@farmslot/adapter-node": "0.1.35",
|
|
25
|
+
"@farmslot/adapter-rn": "0.22.24",
|
|
26
|
+
"@farmslot/adapter-sdk": "0.18.1",
|
|
27
|
+
"@farmslot/adapter-web": "0.10.16",
|
|
28
|
+
"@farmslot/agent-runtime": "0.29.1",
|
|
29
|
+
"@farmslot/handoff": "0.3.2",
|
|
30
30
|
"@farmslot/protocol": "0.54.0",
|
|
31
|
-
"@farmslot/recipe-cli": "0.23.
|
|
32
|
-
"@farmslot/recipe-runner": "0.39.
|
|
31
|
+
"@farmslot/recipe-cli": "0.23.2",
|
|
32
|
+
"@farmslot/recipe-runner": "0.39.1",
|
|
33
33
|
"agent-device": "0.19.3",
|
|
34
34
|
"commander": "^12.0.0",
|
|
35
35
|
"esbuild": "0.28.1",
|