maestro-manager 0.0.0 → 0.0.1
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 +178 -1
- package/dist/build-info.json +3 -0
- package/dist/cli.js +4458 -0
- package/package.json +40 -7
package/README.md
CHANGED
|
@@ -1 +1,178 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Maestro Manager
|
|
2
|
+
|
|
3
|
+
Daemonless iOS Maestro test runner with a shared simulator pool. The CLI creates
|
|
4
|
+
named simulator slots, leases them to concurrent test runs, and records run
|
|
5
|
+
state under the current pool prefix.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- macOS with Xcode command line tools and simulator support available through
|
|
10
|
+
`xcrun simctl`.
|
|
11
|
+
- Bun `>=1.3.14` and Node.js `>=24.16.0`.
|
|
12
|
+
- Maestro installed on `PATH` as `maestro`.
|
|
13
|
+
- A built iOS `.app` bundle and Maestro flow YAML files.
|
|
14
|
+
|
|
15
|
+
Install dependencies:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
bun install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Create `maestro-manager.config.json` at the repo root, pass it with
|
|
24
|
+
`--config <path>`, or set `MAESTRO_MANAGER_CONFIG=<path>`. Without either
|
|
25
|
+
override, the CLI walks up from the current directory until it finds the config.
|
|
26
|
+
|
|
27
|
+
Minimal shape:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"pool": {
|
|
32
|
+
"prefix": "my-project-e2e",
|
|
33
|
+
"deviceType": "iPhone 16",
|
|
34
|
+
"default": 2,
|
|
35
|
+
"max": 4
|
|
36
|
+
},
|
|
37
|
+
"app": {
|
|
38
|
+
"appId": "com.example.MyApp",
|
|
39
|
+
"glob": "~/Library/Developer/Xcode/DerivedData/*/Build/Products/*-iphonesimulator/*.app",
|
|
40
|
+
"searchDirs": ["~/Library/Developer/Xcode/DerivedData"]
|
|
41
|
+
},
|
|
42
|
+
"flowsDir": "maestro/flows",
|
|
43
|
+
"warmupDeepLink": "myapp://e2e/warmup",
|
|
44
|
+
"java": {
|
|
45
|
+
"home": null,
|
|
46
|
+
"autodetect": ["JAVA_HOME", "mise", "/usr/libexec/java_home"]
|
|
47
|
+
},
|
|
48
|
+
"recordingsDir": "recordings",
|
|
49
|
+
"hooks": {
|
|
50
|
+
"pruneAccounts": ""
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Notes:
|
|
56
|
+
|
|
57
|
+
- `pool.prefix` becomes part of simulator names and the state path. Keep it
|
|
58
|
+
project-specific and safe: start with a letter or number, then use only
|
|
59
|
+
letters, numbers, dots, underscores, and hyphens.
|
|
60
|
+
- `pool.default` is the normal warm pool size. `pool.max` is the hard concurrency
|
|
61
|
+
cap and must be `<= 8`. Keep `pool.max <= 4` until the downstream project has
|
|
62
|
+
proved its backend is stable at the higher concurrency.
|
|
63
|
+
- `flowsDir`, `recordingsDir`, and entries in `app.searchDirs` resolve relative
|
|
64
|
+
to the config file directory, with `~` expanded.
|
|
65
|
+
- App resolution order is `--app`, then `app.path`, then `app.glob`, then
|
|
66
|
+
scanning `app.searchDirs` for the newest `.app` matching `app.appId`.
|
|
67
|
+
`app.glob` supports `*` and `?` within path segments and `~` expansion.
|
|
68
|
+
- `hooks.pruneAccounts` is an optional shell command run by
|
|
69
|
+
`clean --prune-accounts`.
|
|
70
|
+
|
|
71
|
+
## Common Workflows
|
|
72
|
+
|
|
73
|
+
Warm the default simulator pool:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
maestro-manager up --app path/to/MyApp.app
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
By default, simulators boot headless: Maestro can run against them without
|
|
80
|
+
opening Simulator.app. Use `--headed` when you want to watch the pool or a run:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
maestro-manager up --headed --app path/to/MyApp.app
|
|
84
|
+
maestro-manager test --headed --sims 2
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`--headless` is also accepted explicitly and conflicts with `--headed`.
|
|
88
|
+
|
|
89
|
+
Show pool slots, active leases, and recent runs:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
maestro-manager status
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Run all configured flows on two simulators:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
maestro-manager test --sims 2
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Stop this worktree's active leases but keep the pool:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
maestro-manager stop
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Reclaim stale leases and shut down idle simulators:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
maestro-manager clean --idle-shutdown 30
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`clean` runs a stateless reaper, even with no flags:
|
|
114
|
+
|
|
115
|
+
- **Reap orphaned runs.** When a `test` worker is `SIGKILL`ed or crashes, no signal
|
|
116
|
+
trap fires, so its detached `maestro` process group — and the simulator's (often
|
|
117
|
+
hung) app — keep running and burning CPU. The stale-lease reclaim deliberately
|
|
118
|
+
refuses to reclaim such a slot while its `maestro` child is still alive (so it
|
|
119
|
+
never yanks a simulator a live run is driving). `clean` detects this case — owner
|
|
120
|
+
dead, heartbeat stale, `maestro` still alive — kills the orphaned `maestro` group,
|
|
121
|
+
shuts the simulator down (killing the hung app), and reclaims the slot.
|
|
122
|
+
- **Reclaim stale leases** whose owner and `maestro` child are both dead, shutting
|
|
123
|
+
those simulators down too.
|
|
124
|
+
|
|
125
|
+
Live-leased simulators (a live owner) are never touched.
|
|
126
|
+
|
|
127
|
+
Add `--delete-unavailable` to also run `xcrun simctl delete unavailable`, removing
|
|
128
|
+
broken-runtime CoreSimulator devices left behind by Xcode upgrades, removed
|
|
129
|
+
runtimes, or other tools. This is **global** — it is NOT scoped to this pool's
|
|
130
|
+
prefix — so it is opt-in and off by default:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
maestro-manager clean --idle-shutdown 30 --delete-unavailable
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Stop all leases, delete pool simulators, and clear pool state:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
maestro-manager down
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`test` runs all `.yaml` and `.yml` files in `flowsDir` when no flow paths are
|
|
143
|
+
provided. Use `--include-tags` and `--exclude-tags` for manager-side tag
|
|
144
|
+
selection, and put Maestro passthrough arguments after a literal `--`.
|
|
145
|
+
|
|
146
|
+
## State And Logs
|
|
147
|
+
|
|
148
|
+
State is scoped by `pool.prefix` under:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
~/.maestro-manager/<prefix>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Important paths include:
|
|
155
|
+
|
|
156
|
+
- `config-snapshot.json` for the last config snapshot written by `up`.
|
|
157
|
+
- `sims/<sim-name>/udid`, `lastused`, and `lease/record.json` for pool slots and
|
|
158
|
+
lease ownership.
|
|
159
|
+
- `waiters/<runId>/ticket.json` for queued work.
|
|
160
|
+
- `runs/index.json`, `runs/<runId>/run.json`, and `runs/<runId>/<flow>.log` for
|
|
161
|
+
run history and per-flow Maestro output.
|
|
162
|
+
|
|
163
|
+
`maestro-manager down` runs `stop --all`, deletes all pool simulators it can
|
|
164
|
+
resolve, then removes `~/.maestro-manager/<prefix>`.
|
|
165
|
+
|
|
166
|
+
## Verification
|
|
167
|
+
|
|
168
|
+
Run the full local check:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
bun run check
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Run the no-excuse audit baseline check:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
bash scripts/check-no-excuse-baseline.sh src
|
|
178
|
+
```
|