@oxy.so/doctor 1.3.0 → 1.4.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 +17 -0
- package/package.json +3 -2
- package/src/emulator-preflight.mjs +50 -0
package/README.md
CHANGED
|
@@ -46,3 +46,20 @@ Use Renovate with a shared organisation preset for grouped, reviewable updates.
|
|
|
46
46
|
Require normal tests and typecheck before merging; never use `latest` ranges or
|
|
47
47
|
mutate dependencies during application startup or CI. Renovate proposes
|
|
48
48
|
changes; Doctor detects drift and duplicate installations.
|
|
49
|
+
|
|
50
|
+
## Android emulator preflight
|
|
51
|
+
|
|
52
|
+
`oxy-emulator-preflight --serial emulator-5554` checks that the explicitly
|
|
53
|
+
selected serial occurs exactly once as an online device in `adb devices -l`,
|
|
54
|
+
then asks its emulator console for the AVD name. It prints only the serial on
|
|
55
|
+
success and exits nonzero on invalid input, offline or ambiguous devices, an
|
|
56
|
+
unavailable ADB, or a missing AVD response. It never starts an emulator or runs
|
|
57
|
+
shell, installation, clearing, or uninstallation commands on a device.
|
|
58
|
+
|
|
59
|
+
The caller must carry the returned serial into every subsequent command, for
|
|
60
|
+
example using `adb -s "$serial" ...`; never rely on ADB's default selection.
|
|
61
|
+
Run the preflight immediately before the operation and fail on errors. This is a
|
|
62
|
+
read-only selection check, not an atomic device lock: devices can disconnect or
|
|
63
|
+
change between commands. It does not prove the AVD is disposable, has no user
|
|
64
|
+
data, or is isolated from production networks. Those are separate prerequisites
|
|
65
|
+
for an isolated mobile test.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxy.so/doctor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Read-only health checks for Oxy ecosystem repositories",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
11
|
"bin": {
|
|
12
|
-
"oxy-doctor": "./src/cli.mjs"
|
|
12
|
+
"oxy-doctor": "./src/cli.mjs",
|
|
13
|
+
"oxy-emulator-preflight": "./src/emulator-preflight.mjs"
|
|
13
14
|
},
|
|
14
15
|
"exports": {
|
|
15
16
|
".": "./src/checks.mjs"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
|
|
4
|
+
const usage = 'Usage: oxy-emulator-preflight --serial emulator-<port>';
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
if (args.length === 1 && (args[0] === '--help' || args[0] === '-h')) {
|
|
7
|
+
console.log(usage);
|
|
8
|
+
process.exit(0);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function fail(message) {
|
|
12
|
+
console.error(`Emulator preflight failed: ${message}`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (args.length !== 2 || args[0] !== '--serial' || !/^emulator-\d{4,5}$/.test(args[1] ?? '')) {
|
|
17
|
+
fail(`an explicit emulator serial is required. ${usage}`);
|
|
18
|
+
}
|
|
19
|
+
const serial = args[1];
|
|
20
|
+
|
|
21
|
+
function adb(...arguments_) {
|
|
22
|
+
const result = spawnSync('adb', arguments_, {
|
|
23
|
+
encoding: 'utf8',
|
|
24
|
+
timeout: 10_000,
|
|
25
|
+
maxBuffer: 1_000_000,
|
|
26
|
+
});
|
|
27
|
+
if (result.error || result.status !== 0) {
|
|
28
|
+
fail(`adb ${arguments_[0]} failed or timed out`);
|
|
29
|
+
}
|
|
30
|
+
return result.stdout;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const lines = adb('devices', '-l').split(/\r?\n/);
|
|
34
|
+
if (!lines.some((line) => line.trim() === 'List of devices attached')) {
|
|
35
|
+
fail('unrecognized adb devices output');
|
|
36
|
+
}
|
|
37
|
+
const matches = lines
|
|
38
|
+
.map((line) => line.trim().split(/\s+/))
|
|
39
|
+
.filter(([candidate]) => candidate === serial);
|
|
40
|
+
if (matches.length !== 1 || matches[0][1] !== 'device') {
|
|
41
|
+
fail('the selected emulator must appear exactly once and be online');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A serial-shaped name alone is not proof that adb is talking to an emulator.
|
|
45
|
+
// The console command is read-only and must return one AVD name followed by OK.
|
|
46
|
+
const reply = adb('-s', serial, 'emu', 'avd', 'name').trim().split(/\r?\n/);
|
|
47
|
+
if (reply.length !== 2 || !/^[A-Za-z0-9_.-]+$/.test(reply[0]) || reply[1] !== 'OK') {
|
|
48
|
+
fail('the selected device did not identify itself as an Android AVD');
|
|
49
|
+
}
|
|
50
|
+
console.log(serial);
|