@deeeed/metamask-harness 0.7.2 → 0.7.3

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.3
4
+
5
+ ### Fixed
6
+ - **`provision runway` gates its install-skip on artifact identity.** The baseline now records the installed artifact identity (run id, branch, digest) at install time and a skip preserves it; provisioning skips ONLY when the recorded identity matches the requested (or probe-resolved) run — a different or unknown installed app is reinstalled from the cache instead of being silently kept. Previously any installed MetaMask.app suppressed the install, so a stale binary could be served against a newer JS bundle.
7
+ - **Provision decisions are machine-readable**: the --json envelope carries `reason` (`identity-match` | `identity-mismatch` | `unknown-identity` | `fresh-install` | `forced`) and a skip envelope includes the matched artifact identity.
8
+
3
9
  ## 0.7.2
4
10
 
5
11
  ### Added
@@ -71,25 +71,43 @@ async function provisionRunwayMobile(target, options) {
71
71
  };
72
72
  }
73
73
  const sim = ensureSimulator(simulator, runtime, deviceType);
74
+ let resolved;
75
+ let reason = options.force ? "forced" : "fresh-install";
74
76
  if (!options.force && appInstalled(sim.udid ?? sim.name)) {
75
- const baselinePath2 = writeRunwayBaseline(resolvedTarget, slot, platform, void 0, void 0, sim, true, options.runtimeDir);
76
- return {
77
- schemaVersion: 1,
78
- command: "provision",
79
- adapter: "mobile",
80
- target: resolvedTarget,
81
- platform,
82
- status: "pass",
83
- exitCode: 0,
84
- slot,
85
- simulator: sim,
86
- skipped: true,
87
- installed: false,
88
- baselinePath: baselinePath2
89
- };
77
+ const installed = readInstalledBaselineArtifact(resolvedTarget, sim, options.runtimeDir);
78
+ let requestedRunId = options.run;
79
+ if (installed && !requestedRunId) {
80
+ log(options, `runway: resolving Runway artifact for ${branch} (default ${defaultBranch})`);
81
+ resolved = resolveArtifactRun(repo, branch, defaultBranch, void 0);
82
+ requestedRunId = resolved.runId;
83
+ }
84
+ if (installed && installed.runId === requestedRunId) {
85
+ const baselinePath2 = writeRunwayBaseline(resolvedTarget, slot, platform, void 0, void 0, sim, true, options.runtimeDir, installed.record);
86
+ return {
87
+ schemaVersion: 1,
88
+ command: "provision",
89
+ adapter: "mobile",
90
+ target: resolvedTarget,
91
+ platform,
92
+ status: "pass",
93
+ exitCode: 0,
94
+ slot,
95
+ // State WHAT matched: the recorded artifact identity the skip trusted.
96
+ artifact: installed.record,
97
+ simulator: sim,
98
+ skipped: true,
99
+ installed: false,
100
+ baselinePath: baselinePath2,
101
+ reason: "identity-match"
102
+ };
103
+ }
104
+ reason = installed ? "identity-mismatch" : "unknown-identity";
105
+ log(options, installed ? `runway: installed app is run ${installed.runId} but run ${requestedRunId} is requested; reinstalling` : "runway: installed app has no recorded Runway identity; installing the requested artifact");
106
+ }
107
+ if (!resolved) {
108
+ log(options, `runway: resolving Runway artifact for ${branch} (default ${defaultBranch})`);
109
+ resolved = resolveArtifactRun(repo, branch, defaultBranch, options.run);
90
110
  }
91
- log(options, `runway: resolving Runway artifact for ${branch} (default ${defaultBranch})`);
92
- const resolved = resolveArtifactRun(repo, branch, defaultBranch, options.run);
93
111
  const cacheRoot = options.cacheRoot ?? defaultRunwayCacheRoot();
94
112
  const cache = ensureCachedArtifact(repo, resolved.branch, resolved.runId, cacheRoot, options);
95
113
  log(options, `runway: installing ${cache.artifact.appPath} on ${sim.name}`);
@@ -111,7 +129,8 @@ async function provisionRunwayMobile(target, options) {
111
129
  simulator: sim,
112
130
  installed: true,
113
131
  skipped: false,
114
- baselinePath
132
+ baselinePath,
133
+ reason
115
134
  };
116
135
  } catch (error) {
117
136
  return fail(resolvedTarget, platform, "PROVISION_FAILED", errorMessage(error), command, slot);
@@ -465,6 +484,22 @@ function baselineSimulatorCandidates(data, current) {
465
484
  }
466
485
  return [...new Set(candidates)];
467
486
  }
487
+ function readInstalledBaselineArtifact(target, sim, runtimeDir) {
488
+ let data;
489
+ try {
490
+ data = JSON.parse(fs.readFileSync(runwayBaselinePath(target, runtimeDir), "utf8"));
491
+ } catch {
492
+ return void 0;
493
+ }
494
+ if (data.appInstalled !== true) return void 0;
495
+ const record = data.artifact;
496
+ if (!record || typeof record !== "object" || Array.isArray(record)) return void 0;
497
+ const runId = record.runId;
498
+ if (typeof runId !== "string" || !runId) return void 0;
499
+ const recordedSims = baselineSimulatorCandidates(data, {});
500
+ if (!recordedSims.includes(sim.name) && (!sim.udid || !recordedSims.includes(sim.udid))) return void 0;
501
+ return { runId, record };
502
+ }
468
503
  function appInstalled(device) {
469
504
  try {
470
505
  execFileSync("xcrun", ["simctl", "get_app_container", device, RUNWAY_IOS_METADATA.bundleId, "app"], { stdio: ["ignore", "ignore", "ignore"] });
@@ -473,7 +508,7 @@ function appInstalled(device) {
473
508
  return false;
474
509
  }
475
510
  }
476
- function writeRunwayBaseline(target, slot, platform, resolved, artifact, simulator, alreadyInstalled, runtimeDir) {
511
+ function writeRunwayBaseline(target, slot, platform, resolved, artifact, simulator, alreadyInstalled, runtimeDir, preservedArtifact) {
477
512
  const file = runwayBaselinePath(target, runtimeDir);
478
513
  fs.mkdirSync(path.dirname(file), { recursive: true });
479
514
  fs.writeFileSync(file, `${JSON.stringify({
@@ -484,7 +519,7 @@ function writeRunwayBaseline(target, slot, platform, resolved, artifact, simulat
484
519
  slotId: slot.slotId ?? null,
485
520
  watcherPort: slot.watcherPort ?? null,
486
521
  simulator,
487
- artifact: resolved && artifact ? { ...resolved, path: artifact.appPath, sizeBytes: artifact.sizeBytes, sha256: artifact.sha256 } : null,
522
+ artifact: resolved && artifact ? { ...resolved, path: artifact.appPath, sizeBytes: artifact.sizeBytes, sha256: artifact.sha256 } : preservedArtifact ?? null,
488
523
  alreadyInstalled,
489
524
  recordedAt: (/* @__PURE__ */ new Date()).toISOString()
490
525
  }, null, 2)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"