CodeNomad/scripts/test-opencode-install-native.mjs
Pascal André 419fe6a60e
fix(opencode): close managed setup activation and publication races
Keep activation explicit after optional upgrades while reconnecting backend authority to the newly selected executable. Supported running daemons remain usable and new workspaces can open when restart is deferred. Recheck executable selection and execution-host eligibility before mutating the shared service.

Publish verified installations with immutable, exclusive version receipts. Concurrent older installs cannot downgrade a newer selection, and same-version Windows publishers no longer replace an open receipt. Continue reading previous current markers.

Cover the gatekeeper findings with real manager/shared-service ownership regressions, browser recovery tests, and concurrent installer tests. Extend native migration to beta and stable seeds, same-version Forms durability controls and historical provider connections. Provide the POSIX shell explicitly in the no-system-Node fixture, fixing Linux/macOS installation CI isolation.
2026-09-20 16:42:01 +02:00

37 lines
2.5 KiB
JavaScript

// Downloads only into a fresh fixture. No global npm install or shared daemon.
import assert from "node:assert/strict"
import { mkdtemp, mkdir, cp, copyFile, chmod, rm, symlink } from "node:fs/promises"
import path from "node:path"
import os from "node:os"
import { execFileSync } from "node:child_process"
import { tsImport } from "tsx/esm/api"
const { bundledNpm, installManagedOpenCode, readManagedExecutable } = await tsImport("../packages/server/src/opencode-update/managed-installation.ts", import.meta.url)
const { MINIMUM_OPENCODE_VERSION } = await tsImport("../packages/server/src/opencode/runtime-support.ts", import.meta.url)
const parent = path.join(os.tmpdir(), "opencode")
await mkdir(parent, { recursive: true })
const root = await mkdtemp(path.join(parent, "codenomad-install-native-"))
const runtime = path.join(root, "runtime")
await mkdir(runtime)
const node = path.join(runtime, process.platform === "win32" ? "node.exe" : "bin/node")
await mkdir(path.dirname(node), { recursive: true })
await copyFile(process.execPath, node)
await chmod(node, 0o755)
const npm = bundledNpm()
assert.ok(npm, "Fixture requires the npm from its Node installation")
const npmRoot = path.resolve(npm, "../..")
await cp(npmRoot, path.join(runtime, process.platform === "win32" ? "node_modules/npm" : "lib/node_modules/npm"), { recursive: true })
const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => !/^(PATH|OPENCODE_|XDG_|npm_)/i.test(key)))
const tools = path.join(root, "tools")
await mkdir(tools)
// npm invokes the OS shell for package lifecycle scripts; provide that shell
// explicitly without admitting /usr/bin/node or any other system Node to PATH.
if (process.platform !== "win32") await symlink("/bin/sh", path.join(tools, "sh"))
Object.assign(env, { HOME: root, USERPROFILE: root, LOCALAPPDATA: root,
npm_config_cache: path.join(root, "npm-cache"), npm_config_userconfig: path.join(root, "npmrc"),
PATH: process.platform === "win32" ? `${process.env.SystemRoot}\\System32` : tools })
try {
const binary = await installManagedOpenCode(MINIMUM_OPENCODE_VERSION, { root: path.join(root, "install"), node, env })
assert.equal(readManagedExecutable(path.join(root, "install")), binary)
assert.match(execFileSync(binary, ["--version"], { encoding: "utf8", env }), new RegExp(MINIMUM_OPENCODE_VERSION.replaceAll(".", "\\.")))
console.log(`PASS: native npm installation with isolated bundled Node, no system Node PATH, verified executable (${MINIMUM_OPENCODE_VERSION})`)
} finally { await rm(root, { recursive: true, force: true }) }