fix: windows install (#4293)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Aiden Cline
2025-11-13 10:22:07 -08:00
committed by GitHub
parent 73443585e5
commit ff462dfd7a
5 changed files with 83 additions and 179 deletions

View File

@@ -4,7 +4,7 @@ on:
push: push:
branches: branches:
- dev - dev
- opentui - windows
- v0 - v0
concurrency: ${{ github.workflow }}-${{ github.ref }} concurrency: ${{ github.workflow }}-${{ github.ref }}

View File

@@ -1,61 +1,84 @@
#!/bin/sh #!/usr/bin/env node
set -e
if [ -n "$OPENCODE_BIN_PATH" ]; then const childProcess = require("child_process")
resolved="$OPENCODE_BIN_PATH" const fs = require("fs")
else const path = require("path")
# Get the real path of this script, resolving any symlinks const os = require("os")
script_path="$0"
while [ -L "$script_path" ]; do
link_target="$(readlink "$script_path")"
case "$link_target" in
/*) script_path="$link_target" ;;
*) script_path="$(dirname "$script_path")/$link_target" ;;
esac
done
script_dir="$(dirname "$script_path")"
script_dir="$(cd "$script_dir" && pwd)"
# Map platform names
case "$(uname -s)" in
Darwin) platform="darwin" ;;
Linux) platform="linux" ;;
MINGW*|CYGWIN*|MSYS*) platform="win32" ;;
*) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;;
esac
# Map architecture names
case "$(uname -m)" in
x86_64|amd64) arch="x64" ;;
aarch64) arch="arm64" ;;
armv7l) arch="arm" ;;
*) arch="$(uname -m)" ;;
esac
name="opencode-${platform}-${arch}"
binary="opencode"
[ "$platform" = "win32" ] && binary="opencode.exe"
# Search for the binary starting from real script location
resolved=""
current_dir="$script_dir"
while [ "$current_dir" != "/" ]; do
candidate="$current_dir/node_modules/$name/bin/$binary"
if [ -f "$candidate" ]; then
resolved="$candidate"
break
fi
current_dir="$(dirname "$current_dir")"
done
if [ -z "$resolved" ]; then
printf "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"%s\" package\n" "$name" >&2
exit 1
fi
fi
# Handle SIGINT gracefully function run(target) {
trap '' INT const result = childProcess.spawnSync(target, process.argv.slice(2), {
stdio: "inherit",
})
if (result.error) {
console.error(result.error.message)
process.exit(1)
}
const code = typeof result.status === "number" ? result.status : 0
process.exit(code)
}
# Execute the binary with all arguments const envPath = process.env.OPENCODE_BIN_PATH
exec "$resolved" "$@" if (envPath) {
run(envPath)
}
const scriptPath = fs.realpathSync(__filename)
const scriptDir = path.dirname(scriptPath)
const platformMap = {
darwin: "darwin",
linux: "linux",
win32: "windows",
}
const archMap = {
x64: "x64",
arm64: "arm64",
arm: "arm",
}
let platform = platformMap[os.platform()]
if (!platform) {
platform = os.platform()
}
let arch = archMap[os.arch()]
if (!arch) {
arch = os.arch()
}
const base = "opencode-" + platform + "-" + arch
const binary = platform === "windows" ? "opencode.exe" : "opencode"
function findBinary(startDir) {
let current = startDir
for (;;) {
const modules = path.join(current, "node_modules")
if (fs.existsSync(modules)) {
const entries = fs.readdirSync(modules)
for (const entry of entries) {
if (!entry.startsWith(base)) {
continue
}
const candidate = path.join(modules, entry, "bin", binary)
if (fs.existsSync(candidate)) {
return candidate
}
}
}
const parent = path.dirname(current)
if (parent === current) {
return
}
current = parent
}
}
const resolved = findBinary(scriptDir)
if (!resolved) {
console.error(
'It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "' +
base +
'" package',
)
process.exit(1)
}
run(resolved)

View File

@@ -1,58 +0,0 @@
@echo off
setlocal enabledelayedexpansion
if defined OPENCODE_BIN_PATH (
set "resolved=%OPENCODE_BIN_PATH%"
goto :execute
)
rem Get the directory of this script
set "script_dir=%~dp0"
set "script_dir=%script_dir:~0,-1%"
rem Detect platform and architecture
set "platform=windows"
rem Detect architecture
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
set "arch=x64"
) else if "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
set "arch=arm64"
) else if "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "arch=x86"
) else (
set "arch=x64"
)
set "name=opencode-!platform!-!arch!"
set "binary=opencode.exe"
rem Search for the binary starting from script location
set "resolved="
set "current_dir=%script_dir%"
:search_loop
set "candidate=%current_dir%\node_modules\%name%\bin\%binary%"
if exist "%candidate%" (
set "resolved=%candidate%"
goto :execute
)
rem Move up one directory
for %%i in ("%current_dir%") do set "parent_dir=%%~dpi"
set "parent_dir=%parent_dir:~0,-1%"
rem Check if we've reached the root
if "%current_dir%"=="%parent_dir%" goto :not_found
set "current_dir=%parent_dir%"
goto :search_loop
:not_found
echo It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "%name%" package >&2
exit /b 1
:execute
rem Execute the binary with all arguments in the same console window
rem Use start /b /wait to ensure it runs in the current shell context for all shells
start /b /wait "" "%resolved%" %*
exit /b %ERRORLEVEL%

View File

@@ -1,44 +0,0 @@
#!/usr/bin/env node
import fs from "fs"
import path from "path"
import os from "os"
import { fileURLToPath } from "url"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
function main() {
if (os.platform() !== "win32") {
console.log("Non-Windows platform detected, skipping preinstall")
return
}
console.log("Windows detected: Modifying package.json bin entry")
// Read package.json
const packageJsonPath = path.join(__dirname, "package.json")
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"))
// Modify bin to point to .cmd file on Windows
packageJson.bin = {
opencode: "./bin/opencode.cmd",
}
// Write it back
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
console.log("Updated package.json bin to use opencode.cmd")
// Now you can also remove the Unix script if you want
const unixScript = path.join(__dirname, "bin", "opencode")
if (fs.existsSync(unixScript)) {
console.log("Removing Unix shell script")
fs.unlinkSync(unixScript)
}
}
try {
main()
} catch (error) {
console.error("Preinstall script error:", error.message)
process.exit(0)
}

View File

@@ -3,7 +3,6 @@ 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 { fileURLToPath } from "url"
import fs from "fs"
const dir = fileURLToPath(new URL("..", import.meta.url)) const dir = fileURLToPath(new URL("..", import.meta.url))
process.chdir(dir) process.chdir(dir)
@@ -17,21 +16,6 @@ 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/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(
@@ -39,10 +23,9 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write(
{ {
name: pkg.name + "-ai", name: pkg.name + "-ai",
bin: { bin: {
[pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`, [pkg.name]: `./bin/${pkg.name}`,
}, },
scripts: { scripts: {
preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs",
postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs",
}, },
version: Script.version, version: Script.version,