fix(server): bound login-shell probes so a slow rc file cannot stall startup (#1742)
fix(cli): detect brew-installed opencode on macOS (#1720)
This commit is contained in:
@@ -5,6 +5,12 @@ import path from 'node:path';
|
||||
import { clearAppImageArgv0FromProcessEnv } from '../inherited-env.js';
|
||||
import { mergePathValues } from './path-utils.js';
|
||||
|
||||
// Login-shell probes source the user's rc files. A slow or interactive rc
|
||||
// (nvm, pyenv, a prompt waiting for input) must not hold server startup
|
||||
// hostage: a probe that overruns is abandoned and resolution falls through
|
||||
// to the next candidate. Electron's own login-shell probe uses the same bound.
|
||||
const SHELL_PROBE_TIMEOUT_MS = 5_000;
|
||||
|
||||
export const createOpenCodeEnvRuntime = (deps) => {
|
||||
const {
|
||||
state,
|
||||
@@ -208,6 +214,7 @@ export const createOpenCodeEnvRuntime = (deps) => {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
windowsHide: true,
|
||||
timeout: SHELL_PROBE_TIMEOUT_MS,
|
||||
});
|
||||
|
||||
if (result.status !== 0) {
|
||||
@@ -460,6 +467,7 @@ export const createOpenCodeEnvRuntime = (deps) => {
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
windowsHide: true,
|
||||
timeout: SHELL_PROBE_TIMEOUT_MS,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
const found = (result.stdout || '').trim().split(/\s+/).pop() || '';
|
||||
@@ -527,6 +535,7 @@ export const createOpenCodeEnvRuntime = (deps) => {
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
windowsHide: true,
|
||||
timeout: SHELL_PROBE_TIMEOUT_MS,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
const found = (result.stdout || '').trim().split(/\s+/).pop() || '';
|
||||
@@ -608,6 +617,7 @@ export const createOpenCodeEnvRuntime = (deps) => {
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
windowsHide: true,
|
||||
timeout: SHELL_PROBE_TIMEOUT_MS,
|
||||
});
|
||||
if (result.status === 0) {
|
||||
const found = (result.stdout || '').trim().split(/\s+/).pop() || '';
|
||||
|
||||
@@ -334,6 +334,29 @@ describe('OpenCode env runtime', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('bounds every login-shell probe and falls through when one overruns', () => {
|
||||
setPlatform('darwin');
|
||||
process.env.PATH = createTempDir('openchamber-empty-path-');
|
||||
process.env.SHELL = '/bin/zsh';
|
||||
delete process.env.OPENCODE_BINARY;
|
||||
const shellCalls = [];
|
||||
const { runtime } = createRuntime({}, {
|
||||
homedir: () => createTempDir('openchamber-empty-home-'),
|
||||
spawnSync: (command, args, options) => {
|
||||
shellCalls.push({ command, args, options });
|
||||
// What spawnSync reports when `timeout` fires: no status, an error.
|
||||
return { status: null, signal: 'SIGTERM', error: new Error('spawnSync ETIMEDOUT'), stdout: '', stderr: '' };
|
||||
},
|
||||
});
|
||||
|
||||
expect(runtime.resolveOpencodeCliPath()).toBeNull();
|
||||
expect(shellCalls.length).toBeGreaterThan(0);
|
||||
for (const call of shellCalls) {
|
||||
expect(call.args).toContain('-lic');
|
||||
expect(call.options.timeout).toBe(5_000);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not auto-detect the Windows OpenCode desktop app as a CLI', () => {
|
||||
setPlatform('win32');
|
||||
const localAppData = createTempDir('openchamber-localappdata-');
|
||||
|
||||
Reference in New Issue
Block a user