From 5aa660219efb869b1a638aed6b60f4afba213a44 Mon Sep 17 00:00:00 2001 From: haelyra <49814733+haelyra@users.noreply.github.com> Date: Tue, 25 Aug 2026 12:37:39 -0400 Subject: [PATCH] test(opencode): isolate environment regression processes --- tests/lib/install-targets.test.js | 48 ++++++++++++++++++++----------- tests/lib/mcp-inventory.test.js | 37 +++++++++++++++++------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/tests/lib/install-targets.test.js b/tests/lib/install-targets.test.js index e0ef595cc..f8ddebf6a 100644 --- a/tests/lib/install-targets.test.js +++ b/tests/lib/install-targets.test.js @@ -6,12 +6,14 @@ const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); +const { spawnSync } = require('child_process'); const { getInstallTargetAdapter, listInstallTargetAdapters, planInstallTargetScaffold, } = require('../../scripts/lib/install-targets/registry'); +const { resolveInvocationEnvironment } = require('../../scripts/lib/invocation-environment'); function normalizedRelativePath(value) { return String(value || '').replace(/\\/g, '/'); @@ -669,24 +671,38 @@ function runTests() { })) passed++; else failed++; if (test('opencode adapter isolates an explicit home from ambient config overrides', () => { - const adapter = getInstallTargetAdapter('opencode'); const homeDir = '/Users/isolated'; - const originalRoot = process.env.OPENCODE_CONFIG_DIR; - const originalXdg = process.env.XDG_CONFIG_HOME; + const registryPath = path.join(__dirname, '..', '..', 'scripts', 'lib', 'install-targets', 'registry.js'); + const child = spawnSync(process.execPath, ['-e', [ + 'const { getInstallTargetAdapter } = require(process.env.ECC_TEST_REGISTRY);', + 'const root = getInstallTargetAdapter(\'opencode\').resolveRoot({ homeDir: process.env.ECC_TEST_HOME });', + 'process.stdout.write(JSON.stringify(root));', + ].join('\n')], { + encoding: 'utf8', + env: { + ...process.env, + ECC_TEST_REGISTRY: registryPath, + ECC_TEST_HOME: homeDir, + OPENCODE_CONFIG_DIR: '/runner/global/opencode', + XDG_CONFIG_HOME: '/runner/global/xdg', + }, + }); - try { - process.env.OPENCODE_CONFIG_DIR = '/runner/global/opencode'; - process.env.XDG_CONFIG_HOME = '/runner/global/xdg'; - assert.strictEqual( - adapter.resolveRoot({ homeDir }), - path.join(homeDir, '.config', 'opencode') - ); - } finally { - if (originalRoot === undefined) delete process.env.OPENCODE_CONFIG_DIR; - else process.env.OPENCODE_CONFIG_DIR = originalRoot; - if (originalXdg === undefined) delete process.env.XDG_CONFIG_HOME; - else process.env.XDG_CONFIG_HOME = originalXdg; - } + assert.strictEqual(child.status, 0, child.stderr); + assert.strictEqual( + JSON.parse(child.stdout), + path.join(homeDir, '.config', 'opencode') + ); + })) passed++; else failed++; + + if (test('invocation environments are immutable snapshots', () => { + const source = { OPENCODE_CONFIG_DIR: '/custom/opencode' }; + const selected = resolveInvocationEnvironment({ env: source }); + const ambient = resolveInvocationEnvironment(); + assert.notStrictEqual(selected, source); + assert.notStrictEqual(ambient, process.env); + selected.OPENCODE_CONFIG_DIR = '/mutated'; + assert.strictEqual(source.OPENCODE_CONFIG_DIR, '/custom/opencode'); })) passed++; else failed++; if (test('qwen adapter supports lookup by target and adapter id', () => { diff --git a/tests/lib/mcp-inventory.test.js b/tests/lib/mcp-inventory.test.js index 50a580432..4bc5631d3 100644 --- a/tests/lib/mcp-inventory.test.js +++ b/tests/lib/mcp-inventory.test.js @@ -4,6 +4,7 @@ const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); +const { spawnSync } = require('child_process'); const { MCP_SCHEMA_VERSION, @@ -228,18 +229,32 @@ test('opencode reader isolates an explicit home from ambient config overrides', fs.writeFileSync(path.join(ambientRoot, 'opencode.json'), JSON.stringify({ mcp: { leaked: { type: 'local', command: ['node'] } }, }), 'utf8'); - const originalRoot = process.env.OPENCODE_CONFIG_DIR; + const readerPath = path.join( + __dirname, + '..', + '..', + 'scripts', + 'lib', + 'mcp-inventory', + 'readers', + 'opencode.js' + ); + const child = spawnSync(process.execPath, ['-e', [ + 'const { readOpencodeMcp } = require(process.env.ECC_TEST_READER);', + 'const names = readOpencodeMcp({ homeDir: process.env.ECC_TEST_HOME }).map(record => record.name);', + 'process.stdout.write(JSON.stringify(names));', + ].join('\n')], { + encoding: 'utf8', + env: { + ...process.env, + ECC_TEST_READER: readerPath, + ECC_TEST_HOME: home, + OPENCODE_CONFIG_DIR: ambientRoot, + }, + }); - try { - process.env.OPENCODE_CONFIG_DIR = ambientRoot; - assert.deepStrictEqual( - readOpencodeMcp({ homeDir: home }).map(record => record.name), - ['isolated'] - ); - } finally { - if (originalRoot === undefined) delete process.env.OPENCODE_CONFIG_DIR; - else process.env.OPENCODE_CONFIG_DIR = originalRoot; - } + assert.strictEqual(child.status, 0, child.stderr); + assert.deepStrictEqual(JSON.parse(child.stdout), ['isolated']); }); test('collectMcpInventory merges harnesses, detects fragmentation + drift, redacts secrets', () => {