lim 0.13.2 → 0.14.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/dist/commands/ios/create.js +1 -1
- package/dist/commands/ios/create.js.map +1 -1
- package/dist/commands/run.d.ts +1 -8
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +22 -121
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/xcode/rbe/install.d.ts +18 -0
- package/dist/commands/xcode/rbe/install.d.ts.map +1 -0
- package/dist/commands/xcode/rbe/install.js +118 -0
- package/dist/commands/xcode/rbe/install.js.map +1 -0
- package/dist/commands/xcode/rbe.d.ts +71 -0
- package/dist/commands/xcode/rbe.d.ts.map +1 -0
- package/dist/commands/xcode/rbe.js +559 -0
- package/dist/commands/xcode/rbe.js.map +1 -0
- package/dist/lib/progress.d.ts +18 -0
- package/dist/lib/progress.d.ts.map +1 -0
- package/dist/lib/progress.js +125 -0
- package/dist/lib/progress.js.map +1 -0
- package/dist/lib/rbe-session.d.ts +72 -0
- package/dist/lib/rbe-session.d.ts.map +1 -0
- package/dist/lib/rbe-session.js +188 -0
- package/dist/lib/rbe-session.js.map +1 -0
- package/dist/lib/rbe-workspace.d.ts +132 -0
- package/dist/lib/rbe-workspace.d.ts.map +1 -0
- package/dist/lib/rbe-workspace.js +356 -0
- package/dist/lib/rbe-workspace.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const core_1 = require("@oclif/core");
|
|
10
|
+
const api_1 = require("@limrun/api");
|
|
11
|
+
const base_command_1 = require("../../base-command");
|
|
12
|
+
const config_1 = require("../../lib/config");
|
|
13
|
+
const progress_1 = require("../../lib/progress");
|
|
14
|
+
const rbe_workspace_1 = require("../../lib/rbe-workspace");
|
|
15
|
+
const rbe_session_1 = require("../../lib/rbe-session");
|
|
16
|
+
class XcodeRbe extends base_command_1.BaseCommand {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.reporter = new progress_1.ProgressReporter(() => this.shouldSuppressInfo());
|
|
20
|
+
}
|
|
21
|
+
async run() {
|
|
22
|
+
const { flags } = await this.parse(XcodeRbe);
|
|
23
|
+
this.setParsedFlags(flags);
|
|
24
|
+
// Serve mode: the detached child. The parent already started the stack and
|
|
25
|
+
// generated the workspace config; this process only holds the tunnel and
|
|
26
|
+
// tears the stack down on exit. Requires --id (the parent always passes it).
|
|
27
|
+
if (flags.serve) {
|
|
28
|
+
if (!flags.id) {
|
|
29
|
+
this.error('--serve requires --id (it is set automatically by the background launcher).');
|
|
30
|
+
}
|
|
31
|
+
await this.withAuth(async () => {
|
|
32
|
+
const target = await this.resolveXcodeTarget(flags.id);
|
|
33
|
+
const client = await this.resolveXcodeClient(target);
|
|
34
|
+
await this.runTunnel(client, flags.port);
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Resolve the Bazel workspace root before touching auth or instances:
|
|
39
|
+
// `.limrun/` and the try-import must live at the workspace root, and failing
|
|
40
|
+
// here avoids creating an instance when run outside a workspace. Walk up
|
|
41
|
+
// like Bazel does, so the command works from any subdirectory.
|
|
42
|
+
const workspaceRoot = (0, rbe_workspace_1.findBazelWorkspaceRoot)(process.cwd());
|
|
43
|
+
if (!workspaceRoot) {
|
|
44
|
+
this.error('Not inside a Bazel workspace. Run `lim xcode rbe` from within the workspace you want ' +
|
|
45
|
+
'to build (a directory tree containing MODULE.bazel, WORKSPACE, or WORKSPACE.bazel).');
|
|
46
|
+
}
|
|
47
|
+
if (flags.stop) {
|
|
48
|
+
await this.stopBackgroundTunnel(workspaceRoot);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// If a background tunnel is already running for this workspace, don't start a
|
|
52
|
+
// second one (and don't fail with a cryptic "port in use"); point at --stop.
|
|
53
|
+
const existing = (0, rbe_session_1.readRbePidFile)(workspaceRoot);
|
|
54
|
+
if (existing && (0, rbe_session_1.isProcessAlive)(existing.pid)) {
|
|
55
|
+
this.info(`A background tunnel is already running for this workspace (PID ${existing.pid}, ` +
|
|
56
|
+
`grpc://127.0.0.1:${existing.port}).`);
|
|
57
|
+
this.info('Stop it with `lim xcode rbe --stop`, then re-run to start fresh.');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (existing) {
|
|
61
|
+
// Stale pid from a crashed/old tunnel. If it was an --ios daemon, its
|
|
62
|
+
// simulator (an independent server-side instance) is still running and only
|
|
63
|
+
// recorded here — reap it before dropping the pidfile, else it's orphaned.
|
|
64
|
+
// If the delete fails, surface the id (the pidfile is gone after this) so
|
|
65
|
+
// the user can clean it up; otherwise it idles out on its own.
|
|
66
|
+
if (existing.simInstanceId) {
|
|
67
|
+
if (await this.deleteSim(existing.simInstanceId)) {
|
|
68
|
+
this.info(`Reaped the simulator ${existing.simInstanceId} from a previous tunnel.`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.info(`Could not delete the previous simulator ${existing.simInstanceId}; it will idle out on its own.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot);
|
|
75
|
+
}
|
|
76
|
+
await this.withAuth(async () => {
|
|
77
|
+
// The already-running guard above handles a tracked tunnel; if the port is
|
|
78
|
+
// still busy here it's an orphan (pidfile gone) or another process, so
|
|
79
|
+
// point at --stop in addition to --port.
|
|
80
|
+
await (0, rbe_session_1.assertLocalPortFree)(flags.port).catch(() => this.error(`Local port ${flags.port} is already in use. If a previous tunnel is still running, ` +
|
|
81
|
+
'stop it with `lim xcode rbe --stop`; otherwise pass --port to choose another.'));
|
|
82
|
+
// Resolve an instance and start the stack. An auto-resolved instance (no
|
|
83
|
+
// --id) may be a stale cache pointer to an instance that still exists but
|
|
84
|
+
// whose limbuild lacks /rbe; in that case drop it and create a fresh one
|
|
85
|
+
// (once). A user-pinned --id is never silently swapped.
|
|
86
|
+
let client;
|
|
87
|
+
let instanceId;
|
|
88
|
+
let xcodeVersion;
|
|
89
|
+
for (let attempt = 0;; attempt++) {
|
|
90
|
+
const target = await this.resolveXcodeTargetOrCreate(flags.id);
|
|
91
|
+
instanceId = typeof target === 'string' ? target : target.id;
|
|
92
|
+
client = await this.resolveXcodeClient(target);
|
|
93
|
+
// resolveXcodeClient validates an iOS-backed target via iosInstances.get,
|
|
94
|
+
// but a cached standalone Xcode target is trusted without a round-trip.
|
|
95
|
+
// Validate it so a deleted instance throws NotFoundError here (→ withAuth
|
|
96
|
+
// clears the cache and recreates) rather than a misleading /rbe 404.
|
|
97
|
+
if (typeof target !== 'string' && target.type === 'xcode') {
|
|
98
|
+
await this.client.xcodeInstances.get(instanceId);
|
|
99
|
+
}
|
|
100
|
+
// Start the stack (retrying transient gateway blips right after instance
|
|
101
|
+
// creation) and poll to running. From here the stack may be (partially)
|
|
102
|
+
// up: any failure before the tunnel owner takes over best-effort stops it
|
|
103
|
+
// so we never leak a running stack with no client attached.
|
|
104
|
+
this.reporter.start('Starting remote build execution');
|
|
105
|
+
try {
|
|
106
|
+
const initial = await (0, rbe_session_1.retryTransient)(() => client.startRbe(), {
|
|
107
|
+
log: (m) => this.reporter.appendLog(m),
|
|
108
|
+
});
|
|
109
|
+
const status = await (0, rbe_session_1.waitForRbeRunning)(client, initial);
|
|
110
|
+
xcodeVersion = status.xcodeVersion;
|
|
111
|
+
this.reporter.stop('success', `Remote build execution ready (Xcode ${xcodeVersion})`);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.reporter.stop('failure');
|
|
116
|
+
if (err instanceof api_1.RbeUnsupportedError && !flags.id && attempt === 0) {
|
|
117
|
+
this.info('That Xcode instance does not support remote build execution; creating a fresh one...');
|
|
118
|
+
(0, config_1.clearLastInstanceId)(instanceId);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
await client.stopRbe().catch(() => { });
|
|
122
|
+
this.error(err instanceof Error ? err.message : String(err));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let generated;
|
|
126
|
+
try {
|
|
127
|
+
generated = (0, rbe_workspace_1.writeRbeWorkspaceFiles)(workspaceRoot, xcodeVersion, flags.port);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
await client.stopRbe().catch(() => { });
|
|
131
|
+
this.error(`Failed to generate .limrun config: ${err instanceof Error ? err.message : String(err)}`);
|
|
132
|
+
}
|
|
133
|
+
this.reporter.success(`Generated .limrun/ config${generated.bazelrcUpdated ? ' (try-import wired into .bazelrc)' : ''}`);
|
|
134
|
+
// --digest_function=sha256 is required on Bazel 9 (BLAKE3 default) and on
|
|
135
|
+
// any workspace configured for BLAKE3, and is a harmless no-op where SHA256
|
|
136
|
+
// is already the default — so always emit it. It is a startup flag (can't
|
|
137
|
+
// live in --config=limrun, and would change the digest for ALL the user's
|
|
138
|
+
// builds if put in .bazelrc), hence it precedes `build` in the command.
|
|
139
|
+
// Infer a real app target so the printed command is runnable as-is; fall
|
|
140
|
+
// back to a placeholder when there's no single obvious target.
|
|
141
|
+
const target = (0, rbe_workspace_1.inferBuildTarget)(workspaceRoot) ?? '//your:target';
|
|
142
|
+
const buildCmd = `bazelisk --digest_function=sha256 build --config=limrun ${target}`;
|
|
143
|
+
// --ios: create + attach a simulator so `lim xcode rbe install` installs on
|
|
144
|
+
// it and the stream URL is printed. Recorded in the pidfile so --stop tears
|
|
145
|
+
// it down too.
|
|
146
|
+
let simInstanceId;
|
|
147
|
+
if (flags.ios) {
|
|
148
|
+
try {
|
|
149
|
+
simInstanceId = await this.createAndAttachSimulator(client);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
// The stack is already up; a simulator-setup failure must stop it, else
|
|
153
|
+
// it keeps running with no tunnel or pidfile owner (createAndAttachSimulator
|
|
154
|
+
// already deleted the sim itself on an attach failure).
|
|
155
|
+
await client.stopRbe().catch(() => { });
|
|
156
|
+
this.error(`Failed to set up the iOS simulator: ${err instanceof Error ? err.message : String(err)}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (flags.daemon) {
|
|
160
|
+
try {
|
|
161
|
+
await this.spawnBackgroundTunnel({
|
|
162
|
+
client,
|
|
163
|
+
simInstanceId,
|
|
164
|
+
workspaceRoot,
|
|
165
|
+
instanceId,
|
|
166
|
+
port: flags.port,
|
|
167
|
+
xcodeVersion,
|
|
168
|
+
generated,
|
|
169
|
+
buildCmd,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
// spawnBackgroundTunnel records simInstanceId in the pidfile only after
|
|
174
|
+
// it confirms readiness; on a spawn/readiness failure nothing on disk
|
|
175
|
+
// references the sim, so --stop could never reap it. Delete it here.
|
|
176
|
+
await this.deleteSim(simInstanceId);
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Foreground (--no-daemon): open the tunnel here, print, then block.
|
|
182
|
+
this.reporter.start('Opening tunnel');
|
|
183
|
+
let tunnel;
|
|
184
|
+
try {
|
|
185
|
+
tunnel = await this.openTunnel(client, flags.port);
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
this.reporter.stop('failure');
|
|
189
|
+
await client.stopRbe().catch(() => { });
|
|
190
|
+
// Foreground never writes a pidfile, so the sim created above can only be
|
|
191
|
+
// reaped here; the steady-state finally below isn't reached on this path.
|
|
192
|
+
await this.deleteSim(simInstanceId);
|
|
193
|
+
this.error(`Failed to open the remote-execution tunnel: ${err instanceof Error ? err.message : String(err)}`);
|
|
194
|
+
}
|
|
195
|
+
this.reporter.stop('success', `Tunnel open on grpc://127.0.0.1:${flags.port}`);
|
|
196
|
+
this.printReady({
|
|
197
|
+
port: flags.port,
|
|
198
|
+
workspaceRoot,
|
|
199
|
+
xcodeVersion,
|
|
200
|
+
generated,
|
|
201
|
+
buildCmd,
|
|
202
|
+
instanceId,
|
|
203
|
+
background: false,
|
|
204
|
+
});
|
|
205
|
+
try {
|
|
206
|
+
await this.awaitTunnel(tunnel, client);
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
await this.deleteSim(simInstanceId);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Stop the background tunnel recorded for this workspace. SIGTERM lets the
|
|
215
|
+
* child close the tunnel and best-effort stop the remote stack; we then clear
|
|
216
|
+
* the pidfile. No auth needed — this is a local process stop.
|
|
217
|
+
*/
|
|
218
|
+
async stopBackgroundTunnel(workspaceRoot) {
|
|
219
|
+
const info = (0, rbe_session_1.readRbePidFile)(workspaceRoot);
|
|
220
|
+
if (!info || !(0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
221
|
+
// The daemon already died (crash, reboot, or `kill -9`). Its --ios sim is an
|
|
222
|
+
// independent server-side instance, still running and recorded only in the
|
|
223
|
+
// pidfile — reap it before clearing the pidfile, else it can never be reaped.
|
|
224
|
+
// If the delete fails, surface the id (the pidfile is gone after this) so the
|
|
225
|
+
// user can clean it up; otherwise it idles out on its own.
|
|
226
|
+
if (info?.simInstanceId) {
|
|
227
|
+
if (await this.deleteSim(info.simInstanceId)) {
|
|
228
|
+
this.info(`Deleted the attached simulator ${info.simInstanceId}.`);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.info(`Could not delete simulator ${info.simInstanceId}; it will idle out on its own.`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot);
|
|
235
|
+
this.info('No background tunnel is running in this workspace.');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
this.reporter.start(`Stopping background tunnel (PID ${info.pid})`);
|
|
239
|
+
// SIGTERM first: the child closes the tunnel and stops the remote stack via
|
|
240
|
+
// DELETE /rbe, whose server-side teardown (tearing down the bb workers/store)
|
|
241
|
+
// takes ~20s. Allow a generous grace so the stack is actually stopped rather
|
|
242
|
+
// than orphaned to idle-out; the spinner keeps this from looking hung.
|
|
243
|
+
const signalled = signalIfAlive(info.pid, 'SIGTERM');
|
|
244
|
+
if (signalled) {
|
|
245
|
+
for (let i = 0; i < 300 && (0, rbe_session_1.isProcessAlive)(info.pid); i++) {
|
|
246
|
+
await (0, rbe_session_1.defaultSleep)(100); // up to ~30s for graceful teardown
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Escalate to SIGKILL if it's wedged (e.g. stuck stopping the remote stack),
|
|
250
|
+
// so --stop always frees the port instead of leaving an orphan.
|
|
251
|
+
let forced = false;
|
|
252
|
+
if ((0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
253
|
+
forced = signalIfAlive(info.pid, 'SIGKILL');
|
|
254
|
+
for (let i = 0; i < 20 && (0, rbe_session_1.isProcessAlive)(info.pid); i++) {
|
|
255
|
+
await (0, rbe_session_1.defaultSleep)(100); // up to ~2s
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Only drop the pidfile once the process is actually gone — otherwise a
|
|
259
|
+
// re-run of --stop would wrongly report "no tunnel running" while the orphan
|
|
260
|
+
// keeps holding the port.
|
|
261
|
+
if ((0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
262
|
+
this.reporter.stop('failure');
|
|
263
|
+
this.error(`Tunnel process ${info.pid} did not exit. Force it with: kill -9 ${info.pid}`);
|
|
264
|
+
}
|
|
265
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot);
|
|
266
|
+
if (forced) {
|
|
267
|
+
this.reporter.stop('success', `Force-stopped background tunnel (PID ${info.pid})`);
|
|
268
|
+
this.info('It was killed before it could stop the remote stack; the instance will idle out on its own.');
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
this.reporter.stop('success', `Stopped background tunnel (PID ${info.pid})`);
|
|
272
|
+
}
|
|
273
|
+
// Tear down the simulator `--ios` created (best-effort; needs auth, unlike
|
|
274
|
+
// the local process stop above).
|
|
275
|
+
if (info.simInstanceId) {
|
|
276
|
+
if (await this.deleteSim(info.simInstanceId)) {
|
|
277
|
+
this.info(`Deleted the attached simulator ${info.simInstanceId}.`);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
this.info(`Could not delete simulator ${info.simInstanceId}; it will idle out on its own.`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Create an iOS simulator and attach it to the RBE Xcode instance, so
|
|
286
|
+
* `lim xcode rbe install` installs on it and the user can watch it live. Prints
|
|
287
|
+
* the stream URL and returns the new simulator's instance id (recorded in the
|
|
288
|
+
* pidfile for --stop teardown).
|
|
289
|
+
*/
|
|
290
|
+
async createAndAttachSimulator(client) {
|
|
291
|
+
this.reporter.start('Creating iOS simulator');
|
|
292
|
+
// The SDK creates + attaches and deletes the sim itself if attach fails, so we
|
|
293
|
+
// never leak an orphan the pidfile never recorded.
|
|
294
|
+
const { iosInstanceId, simulator } = await client.attachNewSimulator();
|
|
295
|
+
this.reporter.stop('success', `Simulator ${iosInstanceId} created and attached`);
|
|
296
|
+
const streamUrl = this.signedStreamUrl(simulator.status) ?? this.consoleStreamUrl(iosInstanceId);
|
|
297
|
+
this.info(`Watch the simulator: ${streamUrl}`);
|
|
298
|
+
return iosInstanceId;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Best-effort delete of a simulator instance `--ios` created, so a failure
|
|
302
|
+
* before the pidfile records it (or a teardown when the daemon is already gone)
|
|
303
|
+
* doesn't leave a billed, un-reapable simulator. Never throws — cleanup must
|
|
304
|
+
* not mask the original error or block a restart. Deletes directly rather than
|
|
305
|
+
* through withAuth: a 404 (the sim already idled out, common at the stale-pid
|
|
306
|
+
* reap) would otherwise trip withAuth's NotFound recovery and spawn a
|
|
307
|
+
* replacement instance during cleanup — the opposite of the leak fix. If the
|
|
308
|
+
* session has expired the delete just fails and the sim idles out on its own.
|
|
309
|
+
* Returns whether the delete succeeded.
|
|
310
|
+
*/
|
|
311
|
+
async deleteSim(id) {
|
|
312
|
+
if (!id)
|
|
313
|
+
return false;
|
|
314
|
+
try {
|
|
315
|
+
await this.client.iosInstances.delete(id);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Spawn the detached child that holds the tunnel, redirect its output to
|
|
324
|
+
* `.limrun/rbe.log`, confirm it came up, then print and return the terminal.
|
|
325
|
+
*/
|
|
326
|
+
async spawnBackgroundTunnel(opts) {
|
|
327
|
+
const apiKey = this.parsedFlags?.['api-key'];
|
|
328
|
+
const logPath = path_1.default.join(opts.workspaceRoot, rbe_workspace_1.LIMRUN_DIR, 'rbe.log');
|
|
329
|
+
this.reporter.start('Starting background tunnel');
|
|
330
|
+
const logFd = fs_1.default.openSync(logPath, 'w');
|
|
331
|
+
const child = (0, child_process_1.spawn)(process.execPath, (0, rbe_session_1.buildServeChildArgs)({
|
|
332
|
+
scriptPath: process.argv[1],
|
|
333
|
+
id: opts.instanceId,
|
|
334
|
+
port: opts.port,
|
|
335
|
+
apiKey,
|
|
336
|
+
}), { detached: true, stdio: ['ignore', logFd, logFd] });
|
|
337
|
+
fs_1.default.closeSync(logFd);
|
|
338
|
+
child.unref();
|
|
339
|
+
const pid = child.pid;
|
|
340
|
+
if (pid === undefined) {
|
|
341
|
+
await opts.client.stopRbe().catch(() => { });
|
|
342
|
+
this.error('Failed to spawn the background tunnel process.');
|
|
343
|
+
}
|
|
344
|
+
// Readiness check: wait until the child's local listener actually accepts a
|
|
345
|
+
// connection (startRbeTunnel binds the port only once openTunnel resolves),
|
|
346
|
+
// rather than trusting a fixed delay — otherwise we'd advertise the endpoint
|
|
347
|
+
// before it's bound and an immediate bazel run could hit connection-refused.
|
|
348
|
+
// Loop exits on: port open (success), child exit (startup failure), or the
|
|
349
|
+
// overall deadline (a child that never binds).
|
|
350
|
+
let childExit;
|
|
351
|
+
child.once('exit', (code) => {
|
|
352
|
+
childExit = code ?? 0;
|
|
353
|
+
});
|
|
354
|
+
let ready = false;
|
|
355
|
+
const deadline = Date.now() + 15000;
|
|
356
|
+
while (childExit === undefined && Date.now() < deadline) {
|
|
357
|
+
if (await (0, rbe_session_1.probePortOpen)(opts.port)) {
|
|
358
|
+
ready = true;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
await (0, rbe_session_1.defaultSleep)(200);
|
|
362
|
+
}
|
|
363
|
+
if (!ready) {
|
|
364
|
+
this.reporter.stop('failure');
|
|
365
|
+
await opts.client.stopRbe().catch(() => { });
|
|
366
|
+
if (childExit !== undefined) {
|
|
367
|
+
this.error(`The background tunnel exited during startup (code ${childExit}).\n` +
|
|
368
|
+
`${readLogTail(logPath)}\nSee ${logPath} for details.`);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
// Alive but never bound the port within the deadline: reap it so it
|
|
372
|
+
// doesn't linger holding nothing, then fail.
|
|
373
|
+
signalIfAlive(pid, 'SIGKILL');
|
|
374
|
+
this.error(`The background tunnel did not become ready on port ${opts.port} in time.\n` +
|
|
375
|
+
`${readLogTail(logPath)}\nSee ${logPath} for details.`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
this.reporter.stop('success', `Tunnel running in background (PID ${pid})`);
|
|
379
|
+
(0, rbe_session_1.writeRbePidFile)(opts.workspaceRoot, {
|
|
380
|
+
pid,
|
|
381
|
+
instanceId: opts.instanceId,
|
|
382
|
+
port: opts.port,
|
|
383
|
+
...(opts.simInstanceId ? { simInstanceId: opts.simInstanceId } : {}),
|
|
384
|
+
});
|
|
385
|
+
this.printReady({
|
|
386
|
+
port: opts.port,
|
|
387
|
+
workspaceRoot: opts.workspaceRoot,
|
|
388
|
+
xcodeVersion: opts.xcodeVersion,
|
|
389
|
+
generated: opts.generated,
|
|
390
|
+
buildCmd: opts.buildCmd,
|
|
391
|
+
instanceId: opts.instanceId,
|
|
392
|
+
background: true,
|
|
393
|
+
pid,
|
|
394
|
+
logPath,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
/** Open the tunnel to the instance's RBE frontend. */
|
|
398
|
+
async openTunnel(client, port) {
|
|
399
|
+
return client.startRbeTunnel({
|
|
400
|
+
port,
|
|
401
|
+
logLevel: this.isJsonEnabled() || this.isQuietEnabled() ? 'none' : 'info',
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Open the tunnel, then block until SIGINT/SIGTERM, closing the tunnel and
|
|
406
|
+
* best-effort stopping the remote stack on exit. Used by the `--serve` child.
|
|
407
|
+
*
|
|
408
|
+
* Opening the tunnel happens BEFORE awaitTunnel's steady-state finally, so a
|
|
409
|
+
* failure here must stop the stack itself: the parent detached and only reaps
|
|
410
|
+
* the child if it exits within a short liveness window, so a slow tunnel-open
|
|
411
|
+
* failure would otherwise leave the remote stack running with no owner.
|
|
412
|
+
*/
|
|
413
|
+
async runTunnel(client, port) {
|
|
414
|
+
let tunnel;
|
|
415
|
+
try {
|
|
416
|
+
tunnel = await this.openTunnel(client, port);
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
await client.stopRbe().catch(() => { });
|
|
420
|
+
this.error(`Failed to open the remote-execution tunnel: ${err instanceof Error ? err.message : String(err)}`);
|
|
421
|
+
}
|
|
422
|
+
await this.awaitTunnel(tunnel, client);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Block on an already-open tunnel until a stop signal, then close it and
|
|
426
|
+
* best-effort stop the remote stack. Rejects if the tunnel reports a terminal
|
|
427
|
+
* disconnect (after its own reconnect attempts are exhausted).
|
|
428
|
+
*/
|
|
429
|
+
async awaitTunnel(tunnel, client) {
|
|
430
|
+
try {
|
|
431
|
+
await new Promise((resolve, reject) => {
|
|
432
|
+
const keepAlive = setInterval(() => { }, 1 << 30);
|
|
433
|
+
let stopping = false;
|
|
434
|
+
const cleanup = () => {
|
|
435
|
+
clearInterval(keepAlive);
|
|
436
|
+
unsubscribe();
|
|
437
|
+
process.off('SIGINT', shutdown);
|
|
438
|
+
process.off('SIGTERM', shutdown);
|
|
439
|
+
};
|
|
440
|
+
const shutdown = () => {
|
|
441
|
+
stopping = true;
|
|
442
|
+
cleanup();
|
|
443
|
+
this.info('Stopping the remote-execution tunnel...');
|
|
444
|
+
resolve();
|
|
445
|
+
};
|
|
446
|
+
const unsubscribe = tunnel.onConnectionStateChange((state) => {
|
|
447
|
+
if (state === 'disconnected' && !stopping) {
|
|
448
|
+
cleanup();
|
|
449
|
+
reject(new Error('Remote-execution tunnel disconnected unexpectedly'));
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
process.once('SIGINT', shutdown);
|
|
453
|
+
process.once('SIGTERM', shutdown);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
finally {
|
|
457
|
+
tunnel.close();
|
|
458
|
+
await client.stopRbe().catch(() => { });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/** Print the ready banner (or JSON) for both foreground and background modes. */
|
|
462
|
+
printReady(opts) {
|
|
463
|
+
if (this.isJsonEnabled()) {
|
|
464
|
+
this.outputJson({
|
|
465
|
+
instanceId: opts.instanceId,
|
|
466
|
+
port: opts.port,
|
|
467
|
+
xcodeVersion: opts.xcodeVersion,
|
|
468
|
+
workspaceRoot: opts.workspaceRoot,
|
|
469
|
+
generatedConfig: {
|
|
470
|
+
buildFile: opts.generated.buildFile,
|
|
471
|
+
bazelrcFragment: opts.generated.bazelrcFragment,
|
|
472
|
+
},
|
|
473
|
+
buildCommand: opts.buildCmd,
|
|
474
|
+
...(opts.background ? { pid: opts.pid, logPath: opts.logPath } : {}),
|
|
475
|
+
});
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
// The build command goes to stdout (copy-paste friendly); status/checkmarks
|
|
479
|
+
// already went to stderr via the reporter.
|
|
480
|
+
this.output('');
|
|
481
|
+
this.output('Build with:');
|
|
482
|
+
this.output(` ${opts.buildCmd}`);
|
|
483
|
+
this.output('');
|
|
484
|
+
this.output(`Endpoint: grpc://127.0.0.1:${opts.port}`);
|
|
485
|
+
if (opts.background) {
|
|
486
|
+
this.output(`Logs: ${opts.logPath}`);
|
|
487
|
+
this.output(`Stop: lim xcode rbe --stop (or: kill ${opts.pid})`);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
this.output('');
|
|
491
|
+
this.info('Tunnel is running. Press Ctrl+C to stop.');
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
XcodeRbe.summary = 'Serve a local Bazel remote-execution endpoint backed by a Limrun Xcode instance';
|
|
496
|
+
XcodeRbe.description = 'Start the embedded Bazel Remote Build Execution stack on an Xcode instance and bridge it to a ' +
|
|
497
|
+
'local TCP port. Point bazel at it with --remote_executor=grpc://127.0.0.1:<port> and actions ' +
|
|
498
|
+
'execute on the remote macOS instance. Run from the root of a Bazel workspace. By default the ' +
|
|
499
|
+
'tunnel runs in the background and the terminal is returned; stop it with `kill <pid>` (printed ' +
|
|
500
|
+
'on start) or by deleting the instance. Pass --no-daemon to keep it in the foreground.';
|
|
501
|
+
XcodeRbe.examples = [
|
|
502
|
+
'<%= config.bin %> xcode rbe',
|
|
503
|
+
'<%= config.bin %> xcode rbe --no-daemon',
|
|
504
|
+
'<%= config.bin %> xcode rbe --id <xcode-instance-ID>',
|
|
505
|
+
'<%= config.bin %> xcode rbe --port 9980',
|
|
506
|
+
];
|
|
507
|
+
XcodeRbe.flags = {
|
|
508
|
+
...base_command_1.BaseCommand.baseFlags,
|
|
509
|
+
id: core_1.Flags.string({
|
|
510
|
+
description: 'Xcode instance ID to target. Defaults to the most recent standalone Xcode target, creating one if needed.',
|
|
511
|
+
}),
|
|
512
|
+
port: core_1.Flags.integer({
|
|
513
|
+
description: 'Local TCP port to serve the remote-execution endpoint on.',
|
|
514
|
+
default: api_1.DEFAULT_RBE_TUNNEL_PORT,
|
|
515
|
+
}),
|
|
516
|
+
daemon: core_1.Flags.boolean({
|
|
517
|
+
description: 'Run the tunnel as a background process and return the terminal. Use --no-daemon to keep it in the foreground (for CI or debugging).',
|
|
518
|
+
default: true,
|
|
519
|
+
allowNo: true,
|
|
520
|
+
}),
|
|
521
|
+
stop: core_1.Flags.boolean({
|
|
522
|
+
description: 'Stop the background tunnel running for this workspace.',
|
|
523
|
+
default: false,
|
|
524
|
+
}),
|
|
525
|
+
ios: core_1.Flags.boolean({
|
|
526
|
+
description: 'Also create an iOS simulator and attach it, so `lim xcode rbe install` installs on it and you can watch it live. The simulator is torn down on --stop.',
|
|
527
|
+
default: false,
|
|
528
|
+
}),
|
|
529
|
+
serve: core_1.Flags.boolean({
|
|
530
|
+
hidden: true,
|
|
531
|
+
default: false,
|
|
532
|
+
description: 'Internal: run only the tunnel serve loop (used by the detached background process).',
|
|
533
|
+
}),
|
|
534
|
+
};
|
|
535
|
+
exports.default = XcodeRbe;
|
|
536
|
+
/** Sends `signal` to `pid`, ignoring "already gone". Returns false if the process was absent. */
|
|
537
|
+
function signalIfAlive(pid, signal) {
|
|
538
|
+
try {
|
|
539
|
+
process.kill(pid, signal);
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
catch {
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/** Reads the last `lines` lines of a log file for error surfacing; best-effort. */
|
|
547
|
+
function readLogTail(logPath, lines = 20) {
|
|
548
|
+
try {
|
|
549
|
+
const content = fs_1.default.readFileSync(logPath, 'utf8').trimEnd();
|
|
550
|
+
if (!content) {
|
|
551
|
+
return '(log file is empty)';
|
|
552
|
+
}
|
|
553
|
+
return content.split('\n').slice(-lines).join('\n');
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
return '(no log output captured)';
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
//# sourceMappingURL=rbe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbe.js","sourceRoot":"","sources":["../../../src/commands/xcode/rbe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class ProgressReporter {
|
|
2
|
+
private readonly suppressed;
|
|
3
|
+
private progress?;
|
|
4
|
+
private readonly tailLines;
|
|
5
|
+
constructor(suppressed: () => boolean, opts?: {
|
|
6
|
+
tailLines?: number;
|
|
7
|
+
});
|
|
8
|
+
/** Print a standalone green ✔ line (no spinner). */
|
|
9
|
+
success(message: string): void;
|
|
10
|
+
/** Run `fn` under a spinner, resolving to a ✔ (or ✖ on throw). */
|
|
11
|
+
withProgress<T>(message: string, fn: () => Promise<T>, successMessage?: string): Promise<T>;
|
|
12
|
+
start(message: string): void;
|
|
13
|
+
stop(result?: 'success' | 'failure', message?: string): void;
|
|
14
|
+
appendLog(chunk: string): void;
|
|
15
|
+
private render;
|
|
16
|
+
private clear;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/lib/progress.ts"],"names":[],"mappings":"AAyBA,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAJ7B,OAAO,CAAC,QAAQ,CAAC,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,UAAU,EAAE,MAAM,OAAO,EAC1C,IAAI,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;IAKnC,oDAAoD;IACpD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO9B,kEAAkE;IAC5D,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAYjG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAY5B,IAAI,CAAC,MAAM,GAAE,SAAS,GAAG,SAAqB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAcvE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiB9B,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,KAAK;CAYd"}
|