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:
Bohdan Triapitsyn
2026-08-28 23:23:27 +03:00
committed by GitHub
2 changed files with 33 additions and 0 deletions
@@ -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-');