lim 0.13.1 → 0.14.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/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 +27 -122
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/xcode/rbe.d.ts +51 -0
- package/dist/commands/xcode/rbe.d.ts.map +1 -0
- package/dist/commands/xcode/rbe.js +439 -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 +70 -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 +110 -0
- package/dist/lib/rbe-workspace.d.ts.map +1 -0
- package/dist/lib/rbe-workspace.js +263 -0
- package/dist/lib/rbe-workspace.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,439 @@
|
|
|
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
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot); // stale pid from a crashed/old tunnel
|
|
62
|
+
}
|
|
63
|
+
await this.withAuth(async () => {
|
|
64
|
+
// The already-running guard above handles a tracked tunnel; if the port is
|
|
65
|
+
// still busy here it's an orphan (pidfile gone) or another process, so
|
|
66
|
+
// point at --stop in addition to --port.
|
|
67
|
+
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, ` +
|
|
68
|
+
'stop it with `lim xcode rbe --stop`; otherwise pass --port to choose another.'));
|
|
69
|
+
// Resolve an instance and start the stack. An auto-resolved instance (no
|
|
70
|
+
// --id) may be a stale cache pointer to an instance that still exists but
|
|
71
|
+
// whose limbuild lacks /rbe; in that case drop it and create a fresh one
|
|
72
|
+
// (once). A user-pinned --id is never silently swapped.
|
|
73
|
+
let client;
|
|
74
|
+
let instanceId;
|
|
75
|
+
let xcodeVersion;
|
|
76
|
+
for (let attempt = 0;; attempt++) {
|
|
77
|
+
const target = await this.resolveXcodeTargetOrCreate(flags.id);
|
|
78
|
+
instanceId = typeof target === 'string' ? target : target.id;
|
|
79
|
+
client = await this.resolveXcodeClient(target);
|
|
80
|
+
// resolveXcodeClient validates an iOS-backed target via iosInstances.get,
|
|
81
|
+
// but a cached standalone Xcode target is trusted without a round-trip.
|
|
82
|
+
// Validate it so a deleted instance throws NotFoundError here (→ withAuth
|
|
83
|
+
// clears the cache and recreates) rather than a misleading /rbe 404.
|
|
84
|
+
if (typeof target !== 'string' && target.type === 'xcode') {
|
|
85
|
+
await this.client.xcodeInstances.get(instanceId);
|
|
86
|
+
}
|
|
87
|
+
// Start the stack (retrying transient gateway blips right after instance
|
|
88
|
+
// creation) and poll to running. From here the stack may be (partially)
|
|
89
|
+
// up: any failure before the tunnel owner takes over best-effort stops it
|
|
90
|
+
// so we never leak a running stack with no client attached.
|
|
91
|
+
this.reporter.start('Starting remote build execution');
|
|
92
|
+
try {
|
|
93
|
+
const initial = await (0, rbe_session_1.retryTransient)(() => client.startRbe(), {
|
|
94
|
+
log: (m) => this.reporter.appendLog(m),
|
|
95
|
+
});
|
|
96
|
+
const status = await (0, rbe_session_1.waitForRbeRunning)(client, initial);
|
|
97
|
+
xcodeVersion = status.xcodeVersion;
|
|
98
|
+
this.reporter.stop('success', `Remote build execution ready (Xcode ${xcodeVersion})`);
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
this.reporter.stop('failure');
|
|
103
|
+
if (err instanceof api_1.RbeUnsupportedError && !flags.id && attempt === 0) {
|
|
104
|
+
this.info('That Xcode instance does not support remote build execution; creating a fresh one...');
|
|
105
|
+
(0, config_1.clearLastInstanceId)(instanceId);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
await client.stopRbe().catch(() => { });
|
|
109
|
+
this.error(err instanceof Error ? err.message : String(err));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let generated;
|
|
113
|
+
try {
|
|
114
|
+
generated = (0, rbe_workspace_1.writeRbeWorkspaceFiles)(workspaceRoot, xcodeVersion, flags.port);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
await client.stopRbe().catch(() => { });
|
|
118
|
+
this.error(`Failed to generate .limrun config: ${err instanceof Error ? err.message : String(err)}`);
|
|
119
|
+
}
|
|
120
|
+
this.reporter.success(`Generated .limrun/ config${generated.bazelrcUpdated ? ' (try-import wired into .bazelrc)' : ''}`);
|
|
121
|
+
// --digest_function=sha256 is required on Bazel 9 (BLAKE3 default) and on
|
|
122
|
+
// any workspace configured for BLAKE3, and is a harmless no-op where SHA256
|
|
123
|
+
// is already the default — so always emit it. It is a startup flag (can't
|
|
124
|
+
// live in --config=limrun, and would change the digest for ALL the user's
|
|
125
|
+
// builds if put in .bazelrc), hence it precedes `build` in the command.
|
|
126
|
+
const buildCmd = 'bazelisk --digest_function=sha256 build --config=limrun //your:target';
|
|
127
|
+
if (flags.daemon) {
|
|
128
|
+
await this.spawnBackgroundTunnel({
|
|
129
|
+
client,
|
|
130
|
+
workspaceRoot,
|
|
131
|
+
instanceId,
|
|
132
|
+
port: flags.port,
|
|
133
|
+
xcodeVersion,
|
|
134
|
+
generated,
|
|
135
|
+
buildCmd,
|
|
136
|
+
});
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Foreground (--no-daemon): open the tunnel here, print, then block.
|
|
140
|
+
this.reporter.start('Opening tunnel');
|
|
141
|
+
let tunnel;
|
|
142
|
+
try {
|
|
143
|
+
tunnel = await this.openTunnel(client, flags.port);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
this.reporter.stop('failure');
|
|
147
|
+
await client.stopRbe().catch(() => { });
|
|
148
|
+
this.error(`Failed to open the remote-execution tunnel: ${err instanceof Error ? err.message : String(err)}`);
|
|
149
|
+
}
|
|
150
|
+
this.reporter.stop('success', `Tunnel open on grpc://127.0.0.1:${flags.port}`);
|
|
151
|
+
this.printReady({
|
|
152
|
+
port: flags.port,
|
|
153
|
+
workspaceRoot,
|
|
154
|
+
xcodeVersion,
|
|
155
|
+
generated,
|
|
156
|
+
buildCmd,
|
|
157
|
+
instanceId,
|
|
158
|
+
background: false,
|
|
159
|
+
});
|
|
160
|
+
await this.awaitTunnel(tunnel, client);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Stop the background tunnel recorded for this workspace. SIGTERM lets the
|
|
165
|
+
* child close the tunnel and best-effort stop the remote stack; we then clear
|
|
166
|
+
* the pidfile. No auth needed — this is a local process stop.
|
|
167
|
+
*/
|
|
168
|
+
async stopBackgroundTunnel(workspaceRoot) {
|
|
169
|
+
const info = (0, rbe_session_1.readRbePidFile)(workspaceRoot);
|
|
170
|
+
if (!info || !(0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
171
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot);
|
|
172
|
+
this.info('No background tunnel is running in this workspace.');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.reporter.start(`Stopping background tunnel (PID ${info.pid})`);
|
|
176
|
+
// SIGTERM first: the child closes the tunnel and stops the remote stack via
|
|
177
|
+
// DELETE /rbe, whose server-side teardown (tearing down the bb workers/store)
|
|
178
|
+
// takes ~20s. Allow a generous grace so the stack is actually stopped rather
|
|
179
|
+
// than orphaned to idle-out; the spinner keeps this from looking hung.
|
|
180
|
+
const signalled = signalIfAlive(info.pid, 'SIGTERM');
|
|
181
|
+
if (signalled) {
|
|
182
|
+
for (let i = 0; i < 300 && (0, rbe_session_1.isProcessAlive)(info.pid); i++) {
|
|
183
|
+
await (0, rbe_session_1.defaultSleep)(100); // up to ~30s for graceful teardown
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Escalate to SIGKILL if it's wedged (e.g. stuck stopping the remote stack),
|
|
187
|
+
// so --stop always frees the port instead of leaving an orphan.
|
|
188
|
+
let forced = false;
|
|
189
|
+
if ((0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
190
|
+
forced = signalIfAlive(info.pid, 'SIGKILL');
|
|
191
|
+
for (let i = 0; i < 20 && (0, rbe_session_1.isProcessAlive)(info.pid); i++) {
|
|
192
|
+
await (0, rbe_session_1.defaultSleep)(100); // up to ~2s
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Only drop the pidfile once the process is actually gone — otherwise a
|
|
196
|
+
// re-run of --stop would wrongly report "no tunnel running" while the orphan
|
|
197
|
+
// keeps holding the port.
|
|
198
|
+
if ((0, rbe_session_1.isProcessAlive)(info.pid)) {
|
|
199
|
+
this.reporter.stop('failure');
|
|
200
|
+
this.error(`Tunnel process ${info.pid} did not exit. Force it with: kill -9 ${info.pid}`);
|
|
201
|
+
}
|
|
202
|
+
(0, rbe_session_1.clearRbePidFile)(workspaceRoot);
|
|
203
|
+
if (forced) {
|
|
204
|
+
this.reporter.stop('success', `Force-stopped background tunnel (PID ${info.pid})`);
|
|
205
|
+
this.info('It was killed before it could stop the remote stack; the instance will idle out on its own.');
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
this.reporter.stop('success', `Stopped background tunnel (PID ${info.pid})`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Spawn the detached child that holds the tunnel, redirect its output to
|
|
213
|
+
* `.limrun/rbe.log`, confirm it came up, then print and return the terminal.
|
|
214
|
+
*/
|
|
215
|
+
async spawnBackgroundTunnel(opts) {
|
|
216
|
+
const apiKey = this.parsedFlags?.['api-key'];
|
|
217
|
+
const logPath = path_1.default.join(opts.workspaceRoot, rbe_workspace_1.LIMRUN_DIR, 'rbe.log');
|
|
218
|
+
this.reporter.start('Starting background tunnel');
|
|
219
|
+
const logFd = fs_1.default.openSync(logPath, 'w');
|
|
220
|
+
const child = (0, child_process_1.spawn)(process.execPath, (0, rbe_session_1.buildServeChildArgs)({
|
|
221
|
+
scriptPath: process.argv[1],
|
|
222
|
+
id: opts.instanceId,
|
|
223
|
+
port: opts.port,
|
|
224
|
+
apiKey,
|
|
225
|
+
}), { detached: true, stdio: ['ignore', logFd, logFd] });
|
|
226
|
+
fs_1.default.closeSync(logFd);
|
|
227
|
+
child.unref();
|
|
228
|
+
const pid = child.pid;
|
|
229
|
+
if (pid === undefined) {
|
|
230
|
+
await opts.client.stopRbe().catch(() => { });
|
|
231
|
+
this.error('Failed to spawn the background tunnel process.');
|
|
232
|
+
}
|
|
233
|
+
// Readiness check: wait until the child's local listener actually accepts a
|
|
234
|
+
// connection (startRbeTunnel binds the port only once openTunnel resolves),
|
|
235
|
+
// rather than trusting a fixed delay — otherwise we'd advertise the endpoint
|
|
236
|
+
// before it's bound and an immediate bazel run could hit connection-refused.
|
|
237
|
+
// Loop exits on: port open (success), child exit (startup failure), or the
|
|
238
|
+
// overall deadline (a child that never binds).
|
|
239
|
+
let childExit;
|
|
240
|
+
child.once('exit', (code) => {
|
|
241
|
+
childExit = code ?? 0;
|
|
242
|
+
});
|
|
243
|
+
let ready = false;
|
|
244
|
+
const deadline = Date.now() + 15000;
|
|
245
|
+
while (childExit === undefined && Date.now() < deadline) {
|
|
246
|
+
if (await (0, rbe_session_1.probePortOpen)(opts.port)) {
|
|
247
|
+
ready = true;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
await (0, rbe_session_1.defaultSleep)(200);
|
|
251
|
+
}
|
|
252
|
+
if (!ready) {
|
|
253
|
+
this.reporter.stop('failure');
|
|
254
|
+
await opts.client.stopRbe().catch(() => { });
|
|
255
|
+
if (childExit !== undefined) {
|
|
256
|
+
this.error(`The background tunnel exited during startup (code ${childExit}).\n` +
|
|
257
|
+
`${readLogTail(logPath)}\nSee ${logPath} for details.`);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// Alive but never bound the port within the deadline: reap it so it
|
|
261
|
+
// doesn't linger holding nothing, then fail.
|
|
262
|
+
signalIfAlive(pid, 'SIGKILL');
|
|
263
|
+
this.error(`The background tunnel did not become ready on port ${opts.port} in time.\n` +
|
|
264
|
+
`${readLogTail(logPath)}\nSee ${logPath} for details.`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
this.reporter.stop('success', `Tunnel running in background (PID ${pid})`);
|
|
268
|
+
(0, rbe_session_1.writeRbePidFile)(opts.workspaceRoot, { pid, instanceId: opts.instanceId, port: opts.port });
|
|
269
|
+
this.printReady({
|
|
270
|
+
port: opts.port,
|
|
271
|
+
workspaceRoot: opts.workspaceRoot,
|
|
272
|
+
xcodeVersion: opts.xcodeVersion,
|
|
273
|
+
generated: opts.generated,
|
|
274
|
+
buildCmd: opts.buildCmd,
|
|
275
|
+
instanceId: opts.instanceId,
|
|
276
|
+
background: true,
|
|
277
|
+
pid,
|
|
278
|
+
logPath,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/** Open the tunnel to the instance's RBE frontend. */
|
|
282
|
+
async openTunnel(client, port) {
|
|
283
|
+
return client.startRbeTunnel({
|
|
284
|
+
port,
|
|
285
|
+
logLevel: this.isJsonEnabled() || this.isQuietEnabled() ? 'none' : 'info',
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Open the tunnel, then block until SIGINT/SIGTERM, closing the tunnel and
|
|
290
|
+
* best-effort stopping the remote stack on exit. Used by the `--serve` child.
|
|
291
|
+
*
|
|
292
|
+
* Opening the tunnel happens BEFORE awaitTunnel's steady-state finally, so a
|
|
293
|
+
* failure here must stop the stack itself: the parent detached and only reaps
|
|
294
|
+
* the child if it exits within a short liveness window, so a slow tunnel-open
|
|
295
|
+
* failure would otherwise leave the remote stack running with no owner.
|
|
296
|
+
*/
|
|
297
|
+
async runTunnel(client, port) {
|
|
298
|
+
let tunnel;
|
|
299
|
+
try {
|
|
300
|
+
tunnel = await this.openTunnel(client, port);
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
await client.stopRbe().catch(() => { });
|
|
304
|
+
this.error(`Failed to open the remote-execution tunnel: ${err instanceof Error ? err.message : String(err)}`);
|
|
305
|
+
}
|
|
306
|
+
await this.awaitTunnel(tunnel, client);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Block on an already-open tunnel until a stop signal, then close it and
|
|
310
|
+
* best-effort stop the remote stack. Rejects if the tunnel reports a terminal
|
|
311
|
+
* disconnect (after its own reconnect attempts are exhausted).
|
|
312
|
+
*/
|
|
313
|
+
async awaitTunnel(tunnel, client) {
|
|
314
|
+
try {
|
|
315
|
+
await new Promise((resolve, reject) => {
|
|
316
|
+
const keepAlive = setInterval(() => { }, 1 << 30);
|
|
317
|
+
let stopping = false;
|
|
318
|
+
const cleanup = () => {
|
|
319
|
+
clearInterval(keepAlive);
|
|
320
|
+
unsubscribe();
|
|
321
|
+
process.off('SIGINT', shutdown);
|
|
322
|
+
process.off('SIGTERM', shutdown);
|
|
323
|
+
};
|
|
324
|
+
const shutdown = () => {
|
|
325
|
+
stopping = true;
|
|
326
|
+
cleanup();
|
|
327
|
+
this.info('Stopping the remote-execution tunnel...');
|
|
328
|
+
resolve();
|
|
329
|
+
};
|
|
330
|
+
const unsubscribe = tunnel.onConnectionStateChange((state) => {
|
|
331
|
+
if (state === 'disconnected' && !stopping) {
|
|
332
|
+
cleanup();
|
|
333
|
+
reject(new Error('Remote-execution tunnel disconnected unexpectedly'));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
process.once('SIGINT', shutdown);
|
|
337
|
+
process.once('SIGTERM', shutdown);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
tunnel.close();
|
|
342
|
+
await client.stopRbe().catch(() => { });
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/** Print the ready banner (or JSON) for both foreground and background modes. */
|
|
346
|
+
printReady(opts) {
|
|
347
|
+
if (this.isJsonEnabled()) {
|
|
348
|
+
this.outputJson({
|
|
349
|
+
instanceId: opts.instanceId,
|
|
350
|
+
port: opts.port,
|
|
351
|
+
xcodeVersion: opts.xcodeVersion,
|
|
352
|
+
workspaceRoot: opts.workspaceRoot,
|
|
353
|
+
generatedConfig: {
|
|
354
|
+
buildFile: opts.generated.buildFile,
|
|
355
|
+
bazelrcFragment: opts.generated.bazelrcFragment,
|
|
356
|
+
},
|
|
357
|
+
buildCommand: opts.buildCmd,
|
|
358
|
+
...(opts.background ? { pid: opts.pid, logPath: opts.logPath } : {}),
|
|
359
|
+
});
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
// The build command goes to stdout (copy-paste friendly); status/checkmarks
|
|
363
|
+
// already went to stderr via the reporter.
|
|
364
|
+
this.output('');
|
|
365
|
+
this.output('Build with:');
|
|
366
|
+
this.output(` ${opts.buildCmd}`);
|
|
367
|
+
this.output('');
|
|
368
|
+
this.output(`Endpoint: grpc://127.0.0.1:${opts.port}`);
|
|
369
|
+
if (opts.background) {
|
|
370
|
+
this.output(`Logs: ${opts.logPath}`);
|
|
371
|
+
this.output(`Stop: lim xcode rbe --stop (or: kill ${opts.pid})`);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
this.output('');
|
|
375
|
+
this.info('Tunnel is running. Press Ctrl+C to stop.');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
XcodeRbe.summary = 'Serve a local Bazel remote-execution endpoint backed by a Limrun Xcode instance';
|
|
380
|
+
XcodeRbe.description = 'Start the embedded Bazel Remote Build Execution stack on an Xcode instance and bridge it to a ' +
|
|
381
|
+
'local TCP port. Point bazel at it with --remote_executor=grpc://127.0.0.1:<port> and actions ' +
|
|
382
|
+
'execute on the remote macOS instance. Run from the root of a Bazel workspace. By default the ' +
|
|
383
|
+
'tunnel runs in the background and the terminal is returned; stop it with `kill <pid>` (printed ' +
|
|
384
|
+
'on start) or by deleting the instance. Pass --no-daemon to keep it in the foreground.';
|
|
385
|
+
XcodeRbe.examples = [
|
|
386
|
+
'<%= config.bin %> xcode rbe',
|
|
387
|
+
'<%= config.bin %> xcode rbe --no-daemon',
|
|
388
|
+
'<%= config.bin %> xcode rbe --id <xcode-instance-ID>',
|
|
389
|
+
'<%= config.bin %> xcode rbe --port 9980',
|
|
390
|
+
];
|
|
391
|
+
XcodeRbe.flags = {
|
|
392
|
+
...base_command_1.BaseCommand.baseFlags,
|
|
393
|
+
id: core_1.Flags.string({
|
|
394
|
+
description: 'Xcode instance ID to target. Defaults to the most recent standalone Xcode target, creating one if needed.',
|
|
395
|
+
}),
|
|
396
|
+
port: core_1.Flags.integer({
|
|
397
|
+
description: 'Local TCP port to serve the remote-execution endpoint on.',
|
|
398
|
+
default: api_1.DEFAULT_RBE_TUNNEL_PORT,
|
|
399
|
+
}),
|
|
400
|
+
daemon: core_1.Flags.boolean({
|
|
401
|
+
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).',
|
|
402
|
+
default: true,
|
|
403
|
+
allowNo: true,
|
|
404
|
+
}),
|
|
405
|
+
stop: core_1.Flags.boolean({
|
|
406
|
+
description: 'Stop the background tunnel running for this workspace.',
|
|
407
|
+
default: false,
|
|
408
|
+
}),
|
|
409
|
+
serve: core_1.Flags.boolean({
|
|
410
|
+
hidden: true,
|
|
411
|
+
default: false,
|
|
412
|
+
description: 'Internal: run only the tunnel serve loop (used by the detached background process).',
|
|
413
|
+
}),
|
|
414
|
+
};
|
|
415
|
+
exports.default = XcodeRbe;
|
|
416
|
+
/** Sends `signal` to `pid`, ignoring "already gone". Returns false if the process was absent. */
|
|
417
|
+
function signalIfAlive(pid, signal) {
|
|
418
|
+
try {
|
|
419
|
+
process.kill(pid, signal);
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/** Reads the last `lines` lines of a log file for error surfacing; best-effort. */
|
|
427
|
+
function readLogTail(logPath, lines = 20) {
|
|
428
|
+
try {
|
|
429
|
+
const content = fs_1.default.readFileSync(logPath, 'utf8').trimEnd();
|
|
430
|
+
if (!content) {
|
|
431
|
+
return '(log file is empty)';
|
|
432
|
+
}
|
|
433
|
+
return content.split('\n').slice(-lines).join('\n');
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
return '(no log output captured)';
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
//# 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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProgressReporter = void 0;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
/**
|
|
6
|
+
* Spinner + checkmark progress reporting on stderr, shared across commands so
|
|
7
|
+
* they all look the same (e.g. `lim run`, `lim xcode rbe`). Renders a live
|
|
8
|
+
* spinner with an optional tail of streamed log lines on a TTY, and prints a
|
|
9
|
+
* green ✔ / red ✖ line on completion. All output is suppressed when the owning
|
|
10
|
+
* command is in --json/--quiet mode (via the injected `suppressed` predicate),
|
|
11
|
+
* and falls back to no-op animation when stderr is not a TTY.
|
|
12
|
+
*/
|
|
13
|
+
const SPINNER_FRAMES = process.platform === 'win32' ? ['-', '\\', '|', '/'] : ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
14
|
+
const SUCCESS_ICON = process.platform === 'win32' ? '√' : '✔';
|
|
15
|
+
const FAILURE_ICON = process.platform === 'win32' ? '×' : '✖';
|
|
16
|
+
const DEFAULT_TAIL_LINES = 10;
|
|
17
|
+
class ProgressReporter {
|
|
18
|
+
constructor(suppressed, opts = {}) {
|
|
19
|
+
this.suppressed = suppressed;
|
|
20
|
+
this.tailLines = opts.tailLines ?? DEFAULT_TAIL_LINES;
|
|
21
|
+
}
|
|
22
|
+
/** Print a standalone green ✔ line (no spinner). */
|
|
23
|
+
success(message) {
|
|
24
|
+
if (this.suppressed()) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
process.stderr.write(`${core_1.ux.colorize('green', SUCCESS_ICON)} ${message}\n`);
|
|
28
|
+
}
|
|
29
|
+
/** Run `fn` under a spinner, resolving to a ✔ (or ✖ on throw). */
|
|
30
|
+
async withProgress(message, fn, successMessage) {
|
|
31
|
+
this.start(message);
|
|
32
|
+
try {
|
|
33
|
+
const result = await fn();
|
|
34
|
+
this.stop('success', successMessage);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.stop('failure');
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
start(message) {
|
|
43
|
+
if (this.suppressed()) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.progress = { frame: 0, logLines: [], message, renderedRows: 0 };
|
|
47
|
+
if (process.stderr.isTTY) {
|
|
48
|
+
this.progress.timer = setInterval(() => this.render(), process.platform === 'win32' ? 500 : 100);
|
|
49
|
+
this.progress.timer.unref();
|
|
50
|
+
this.render();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
stop(result = 'success', message) {
|
|
54
|
+
if (this.suppressed() || !this.progress) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const progress = this.progress;
|
|
58
|
+
if (progress.timer) {
|
|
59
|
+
clearInterval(progress.timer);
|
|
60
|
+
}
|
|
61
|
+
this.progress = undefined;
|
|
62
|
+
this.clear(progress);
|
|
63
|
+
const icon = result === 'success' ? core_1.ux.colorize('green', SUCCESS_ICON) : core_1.ux.colorize('red', FAILURE_ICON);
|
|
64
|
+
process.stderr.write(`${icon} ${message ?? progress.message}\n`);
|
|
65
|
+
}
|
|
66
|
+
appendLog(chunk) {
|
|
67
|
+
if (this.suppressed() || !this.progress) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const lines = String(chunk)
|
|
71
|
+
.replace(/\r/g, '\n')
|
|
72
|
+
.split('\n')
|
|
73
|
+
.map((line) => line.trimEnd())
|
|
74
|
+
.filter((line) => line.length > 0);
|
|
75
|
+
if (lines.length === 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.progress.logLines.push(...lines);
|
|
79
|
+
this.progress.logLines = this.progress.logLines.slice(-this.tailLines);
|
|
80
|
+
this.render();
|
|
81
|
+
}
|
|
82
|
+
render() {
|
|
83
|
+
if (!this.progress || !process.stderr.isTTY) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const frame = SPINNER_FRAMES[this.progress.frame % SPINNER_FRAMES.length];
|
|
87
|
+
this.progress.frame += 1;
|
|
88
|
+
const lines = [
|
|
89
|
+
progressLine(`${core_1.ux.colorize('magenta', frame)} ${this.progress.message}`),
|
|
90
|
+
...this.progress.logLines.map((line) => core_1.ux.colorize('dim', ` ${truncateTerminalLine(line, 2)}`)),
|
|
91
|
+
];
|
|
92
|
+
this.clear(this.progress);
|
|
93
|
+
this.progress.renderedRows = lines.length;
|
|
94
|
+
process.stderr.write(lines.join('\n'));
|
|
95
|
+
}
|
|
96
|
+
clear(progress) {
|
|
97
|
+
if (!process.stderr.isTTY) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
process.stderr.clearLine(0);
|
|
101
|
+
process.stderr.cursorTo(0);
|
|
102
|
+
for (let i = 1; i < progress.renderedRows; i += 1) {
|
|
103
|
+
process.stderr.moveCursor(0, -1);
|
|
104
|
+
process.stderr.clearLine(0);
|
|
105
|
+
process.stderr.cursorTo(0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.ProgressReporter = ProgressReporter;
|
|
110
|
+
function progressLine(line) {
|
|
111
|
+
const width = process.stderr.columns;
|
|
112
|
+
if (!width || line.length < width - 1) {
|
|
113
|
+
return line;
|
|
114
|
+
}
|
|
115
|
+
return `${line.slice(0, Math.max(0, width - 4))}...`;
|
|
116
|
+
}
|
|
117
|
+
function truncateTerminalLine(line, indent = 0) {
|
|
118
|
+
const width = process.stderr.columns;
|
|
119
|
+
const max = width ? width - indent - 1 : undefined;
|
|
120
|
+
if (!max || line.length < max) {
|
|
121
|
+
return line;
|
|
122
|
+
}
|
|
123
|
+
return `${line.slice(0, Math.max(0, max - 3))}...`;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/lib/progress.ts"],"names":[],"mappings":"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"}
|