mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-27 12:44:22 +01:00
fix: resolve bun/pnpm global install failures on Windows (#4275)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
@@ -66,11 +66,11 @@ const allTargets: {
|
|||||||
avx2: false,
|
avx2: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
os: "windows",
|
os: "win32",
|
||||||
arch: "x64",
|
arch: "x64",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
os: "windows",
|
os: "win32",
|
||||||
arch: "x64",
|
arch: "x64",
|
||||||
avx2: false,
|
avx2: false,
|
||||||
},
|
},
|
||||||
@@ -88,7 +88,8 @@ await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parc
|
|||||||
for (const item of targets) {
|
for (const item of targets) {
|
||||||
const name = [
|
const name = [
|
||||||
pkg.name,
|
pkg.name,
|
||||||
item.os,
|
// changing to win32 flags npm for some reason
|
||||||
|
item.os === "win32" ? "windows" : item.os,
|
||||||
item.arch,
|
item.arch,
|
||||||
item.avx2 === false ? "baseline" : undefined,
|
item.avx2 === false ? "baseline" : undefined,
|
||||||
item.abi === undefined ? undefined : item.abi,
|
item.abi === undefined ? undefined : item.abi,
|
||||||
@@ -127,7 +128,7 @@ for (const item of targets) {
|
|||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
version: Script.version,
|
version: Script.version,
|
||||||
os: [item.os === "windows" ? "win32" : item.os],
|
os: [item.os],
|
||||||
cpu: [item.arch],
|
cpu: [item.arch],
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
|
|||||||
@@ -85,18 +85,6 @@ function prepareBinDirectory(binaryName) {
|
|||||||
return { binDir, targetPath }
|
return { binDir, targetPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyBinary(sourcePath, binaryName) {
|
|
||||||
const { targetPath } = prepareBinDirectory(binaryName)
|
|
||||||
|
|
||||||
fs.copyFileSync(sourcePath, targetPath)
|
|
||||||
console.log(`opencode binary installed: ${targetPath}`)
|
|
||||||
|
|
||||||
// Verify the file exists after operation
|
|
||||||
if (!fs.existsSync(targetPath)) {
|
|
||||||
throw new Error(`Failed to copy binary to ${targetPath}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function symlinkBinary(sourcePath, binaryName) {
|
function symlinkBinary(sourcePath, binaryName) {
|
||||||
const { targetPath } = prepareBinDirectory(binaryName)
|
const { targetPath } = prepareBinDirectory(binaryName)
|
||||||
|
|
||||||
@@ -109,64 +97,12 @@ function symlinkBinary(sourcePath, binaryName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function regenerateWindowsCmdWrappers() {
|
|
||||||
console.log("Windows + npm detected: Forcing npm to rebuild bin links")
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { execSync } = require("child_process")
|
|
||||||
const pkgPath = path.join(__dirname, "..")
|
|
||||||
|
|
||||||
// npm_config_global is string | undefined
|
|
||||||
// if it exists, the value is true
|
|
||||||
const isGlobal = process.env.npm_config_global === "true" || pkgPath.includes(path.join("npm", "node_modules"))
|
|
||||||
|
|
||||||
// The npm rebuild command does 2 things - Execute lifecycle scripts and rebuild bin links
|
|
||||||
// We want to skip lifecycle scripts to avoid infinite loops, so we use --ignore-scripts
|
|
||||||
const cmd = `npm rebuild opencode-ai --ignore-scripts${isGlobal ? " -g" : ""}`
|
|
||||||
const opts = {
|
|
||||||
stdio: "inherit",
|
|
||||||
shell: true,
|
|
||||||
...(isGlobal ? {} : { cwd: path.join(pkgPath, "..", "..") }), // For local, run from project root
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Running: ${cmd}`)
|
|
||||||
execSync(cmd, opts)
|
|
||||||
console.log("Successfully rebuilt npm bin links")
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error rebuilding npm links:", error.message)
|
|
||||||
console.error("npm rebuild failed. You may need to manually run: npm rebuild opencode-ai --ignore-scripts")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
if (os.platform() === "win32") {
|
if (os.platform() === "win32") {
|
||||||
// NPM eg format - npm/11.4.2 node/v24.4.1 win32 x64
|
// On Windows, the .exe is already included in the package and bin field points to it
|
||||||
// Bun eg format - bun/1.2.19 npm/? node/v24.3.0 win32 x64
|
// No postinstall setup needed
|
||||||
// pnpm eg format - pnpm/8.10.0 npm/? node/v20.10.0 win32 x64
|
console.log("Windows detected: binary setup not needed (using packaged .exe)")
|
||||||
const userAgent = process.env.npm_config_user_agent || ""
|
|
||||||
|
|
||||||
if (userAgent.startsWith("npm")) {
|
|
||||||
await regenerateWindowsCmdWrappers()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userAgent.startsWith("bun")) {
|
|
||||||
console.log("Windows + bun detected: Setting up binary")
|
|
||||||
const { binaryPath, binaryName } = findBinary()
|
|
||||||
copyBinary(binaryPath, binaryName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userAgent.startsWith("pnpm")) {
|
|
||||||
console.log("Windows + pnpm detected: Setting up binary")
|
|
||||||
const { binaryPath, binaryName } = findBinary()
|
|
||||||
copyBinary(binaryPath, binaryName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unknown package manager on Windows
|
|
||||||
console.log("Windows detected but unknown package manager, skipping postinstall")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
import pkg from "../package.json"
|
import pkg from "../package.json"
|
||||||
import { Script } from "@opencode-ai/script"
|
import { Script } from "@opencode-ai/script"
|
||||||
|
import { fileURLToPath } from "url"
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
const dir = new URL("..", import.meta.url).pathname
|
const dir = fileURLToPath(new URL("..", import.meta.url))
|
||||||
process.chdir(dir)
|
process.chdir(dir)
|
||||||
|
|
||||||
const { binaries } = await import("./build.ts")
|
const { binaries } = await import("./build.ts")
|
||||||
@@ -15,14 +17,29 @@ const { binaries } = await import("./build.ts")
|
|||||||
|
|
||||||
await $`mkdir -p ./dist/${pkg.name}`
|
await $`mkdir -p ./dist/${pkg.name}`
|
||||||
await $`cp -r ./bin ./dist/${pkg.name}/bin`
|
await $`cp -r ./bin ./dist/${pkg.name}/bin`
|
||||||
|
|
||||||
|
// Copy Windows .exe if any Windows binaries were built
|
||||||
|
let hasWindowsBinary = false
|
||||||
|
for (const binaryName of Object.keys(binaries)) {
|
||||||
|
if (binaryName.includes("win32")) {
|
||||||
|
const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe`
|
||||||
|
if (fs.existsSync(winBinaryPath)) {
|
||||||
|
await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe`
|
||||||
|
hasWindowsBinary = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs`
|
await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs`
|
||||||
await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs`
|
await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs`
|
||||||
|
|
||||||
await Bun.file(`./dist/${pkg.name}/package.json`).write(
|
await Bun.file(`./dist/${pkg.name}/package.json`).write(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
{
|
{
|
||||||
name: pkg.name + "-ai",
|
name: pkg.name + "-ai",
|
||||||
bin: {
|
bin: {
|
||||||
[pkg.name]: `./bin/${pkg.name}`,
|
[pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`,
|
||||||
},
|
},
|
||||||
scripts: {
|
scripts: {
|
||||||
preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs",
|
preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs",
|
||||||
@@ -36,7 +53,15 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
for (const [name] of Object.entries(binaries)) {
|
for (const [name] of Object.entries(binaries)) {
|
||||||
await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${Script.channel}`
|
try {
|
||||||
|
process.chdir(`./dist/${name}`)
|
||||||
|
if (process.platform !== "win32") {
|
||||||
|
await $`chmod 755 -R .`
|
||||||
|
}
|
||||||
|
await $`bun publish --access public --tag ${Script.channel}`
|
||||||
|
} finally {
|
||||||
|
process.chdir(dir)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.channel}`
|
await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.channel}`
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user