fix: preserve user PATH for managed opencode
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const spawnMock = vi.fn();
|
||||
|
||||
vi.mock('node:child_process', () => ({
|
||||
spawn: spawnMock,
|
||||
spawnSync: vi.fn(),
|
||||
}));
|
||||
|
||||
const { createOpenCodeLifecycleRuntime } = await import('./lifecycle.js');
|
||||
|
||||
const originalOpencodeBinary = process.env.OPENCODE_BINARY;
|
||||
|
||||
afterEach(() => {
|
||||
spawnMock.mockReset();
|
||||
if (typeof originalOpencodeBinary === 'string') {
|
||||
process.env.OPENCODE_BINARY = originalOpencodeBinary;
|
||||
return;
|
||||
}
|
||||
delete process.env.OPENCODE_BINARY;
|
||||
});
|
||||
|
||||
const createMockChild = () => {
|
||||
const child = new EventEmitter();
|
||||
child.stdout = new EventEmitter();
|
||||
child.stderr = new EventEmitter();
|
||||
child.exitCode = null;
|
||||
child.signalCode = null;
|
||||
child.pid = 12345;
|
||||
child.kill = vi.fn(() => {
|
||||
child.signalCode = 'SIGTERM';
|
||||
queueMicrotask(() => child.emit('close', null, 'SIGTERM'));
|
||||
return true;
|
||||
});
|
||||
return child;
|
||||
};
|
||||
|
||||
const createRuntime = (overrides = {}) => {
|
||||
const state = {
|
||||
openCodeWorkingDirectory: '/tmp/project',
|
||||
openCodeProcess: null,
|
||||
openCodePort: null,
|
||||
openCodeBaseUrl: null,
|
||||
currentRestartPromise: null,
|
||||
isRestartingOpenCode: false,
|
||||
openCodeApiPrefix: '',
|
||||
openCodeApiPrefixDetected: false,
|
||||
openCodeApiDetectionTimer: null,
|
||||
lastOpenCodeError: null,
|
||||
isOpenCodeReady: false,
|
||||
openCodeNotReadySince: 0,
|
||||
isExternalOpenCode: false,
|
||||
isShuttingDown: false,
|
||||
healthCheckInterval: null,
|
||||
expressApp: null,
|
||||
useWslForOpencode: false,
|
||||
resolvedWslBinary: null,
|
||||
resolvedWslOpencodePath: null,
|
||||
resolvedWslDistro: null,
|
||||
};
|
||||
|
||||
return createOpenCodeLifecycleRuntime({
|
||||
state,
|
||||
env: {
|
||||
ENV_CONFIGURED_OPENCODE_PORT: 45678,
|
||||
ENV_CONFIGURED_OPENCODE_HOST: null,
|
||||
ENV_EFFECTIVE_PORT: 3001,
|
||||
ENV_CONFIGURED_OPENCODE_HOSTNAME: '127.0.0.1',
|
||||
ENV_SKIP_OPENCODE_START: false,
|
||||
},
|
||||
syncToHmrState: vi.fn(),
|
||||
syncFromHmrState: vi.fn(),
|
||||
getOpenCodeAuthHeaders: () => ({}),
|
||||
buildOpenCodeUrl: (route) => `http://127.0.0.1:45678${route}`,
|
||||
waitForReady: vi.fn(async () => true),
|
||||
normalizeApiPrefix: vi.fn(() => ''),
|
||||
applyOpencodeBinaryFromSettings: vi.fn(async () => null),
|
||||
ensureOpencodeCliEnv: vi.fn(),
|
||||
ensureLocalOpenCodeServerPassword: vi.fn(async () => 'password'),
|
||||
buildWslExecArgs: vi.fn((args) => args),
|
||||
resolveWslExecutablePath: vi.fn(),
|
||||
resolveManagedOpenCodeLaunchSpec: vi.fn((binary) => ({ binary, args: [], wrapperType: null })),
|
||||
setOpenCodePort: vi.fn((port) => {
|
||||
state.openCodePort = port;
|
||||
}),
|
||||
setDetectedOpenCodeApiPrefix: vi.fn(),
|
||||
setupProxy: vi.fn(),
|
||||
ensureOpenCodeApiPrefix: vi.fn(),
|
||||
clearResolvedOpenCodeBinary: vi.fn(),
|
||||
buildAugmentedPath: vi.fn(() => '/home/user/.bun/bin:/usr/local/bin:/usr/bin'),
|
||||
buildManagedOpenCodePath: vi.fn(() => '/home/user/.bun/bin:/usr/local/bin:/usr/bin'),
|
||||
...overrides,
|
||||
});
|
||||
};
|
||||
|
||||
describe('OpenCode lifecycle', () => {
|
||||
it('launches managed OpenCode with the managed PATH', async () => {
|
||||
delete process.env.OPENCODE_BINARY;
|
||||
const child = createMockChild();
|
||||
spawnMock.mockImplementationOnce(() => {
|
||||
queueMicrotask(() => {
|
||||
child.stdout.emit('data', 'opencode server listening on http://127.0.0.1:45678\n');
|
||||
});
|
||||
return child;
|
||||
});
|
||||
|
||||
const runtime = createRuntime();
|
||||
const server = await runtime.startOpenCode();
|
||||
const [binary, args, options] = spawnMock.mock.calls[0];
|
||||
|
||||
expect(binary).toBe('opencode');
|
||||
expect(args).toEqual(['serve', '--hostname', '127.0.0.1', '--port', '45678']);
|
||||
expect(options.env.PATH).toBe('/home/user/.bun/bin:/usr/local/bin:/usr/bin');
|
||||
expect(options.env.OPENCODE_SERVER_PASSWORD).toBe('password');
|
||||
|
||||
await server.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user