فهرست منبع

chore(cli): build binaries with Bun 1.4

Dax Raad 23 ساعت پیش
والد
کامیت
d8e1753330
3فایلهای تغییر یافته به همراه38 افزوده شده و 4 حذف شده
  1. 10 3
      .github/actions/setup-bun/action.yml
  2. 3 0
      .github/workflows/publish.yml
  3. 25 1
      packages/cli/script/build.ts

+ 10 - 3
.github/actions/setup-bun/action.yml

@@ -1,6 +1,10 @@
 name: "Setup Bun"
 description: "Setup Bun with caching and install dependencies"
 inputs:
+  bun-version:
+    description: "Bun version to install instead of the root packageManager version"
+    required: false
+    default: ""
   install-flags:
     description: "Additional flags to pass to 'bun install'"
     required: false
@@ -20,19 +24,22 @@ runs:
       shell: bash
       run: |
         if [ "$RUNNER_ARCH" = "X64" ]; then
-          V=$(node -p "require('./package.json').packageManager.split('@')[1]")
+          V="${{ inputs.bun-version }}"
+          if [ -z "$V" ]; then V=$(node -p "require('./package.json').packageManager.split('@')[1]"); fi
+          TAG=$([ "$V" = "canary" ] && echo "canary" || echo "bun-v${V}")
           case "$RUNNER_OS" in
             macOS)   OS=darwin ;;
             Linux)   OS=linux ;;
             Windows) OS=windows ;;
           esac
-          echo "url=https://github.com/oven-sh/bun/releases/download/bun-v${V}/bun-${OS}-x64-baseline.zip" >> "$GITHUB_OUTPUT"
+          echo "url=https://github.com/oven-sh/bun/releases/download/${TAG}/bun-${OS}-x64-baseline.zip" >> "$GITHUB_OUTPUT"
         fi
 
     - name: Setup Bun
       uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
       with:
-        bun-version-file: ${{ !steps.bun-url.outputs.url && 'package.json' || '' }}
+        bun-version: ${{ !steps.bun-url.outputs.url && inputs.bun-version || '' }}
+        bun-version-file: ${{ !steps.bun-url.outputs.url && !inputs.bun-version && 'package.json' || '' }}
         bun-download-url: ${{ steps.bun-url.outputs.url }}
 
     - name: Get cache directory

+ 3 - 0
.github/workflows/publish.yml

@@ -81,6 +81,8 @@ jobs:
           fetch-tags: true
 
       - uses: ./.github/actions/setup-bun
+        with:
+          bun-version: canary # Bun 1.4 until its stable release is published
 
       - name: Setup git committer
         id: committer
@@ -102,6 +104,7 @@ jobs:
         id: build
         run: ./packages/cli/script/build.ts ${{ (github.ref_name == 'beta' && '--sourcemaps') || '' }}
         env:
+          BUN_COMPILE_RELEASE: canary
           OPENCODE_VERSION: ${{ needs.version.outputs.version }}
           OPENCODE_RELEASE: ${{ needs.version.outputs.release }}
           GH_REPO: ${{ needs.version.outputs.repo }}

+ 25 - 1
packages/cli/script/build.ts

@@ -1,7 +1,7 @@
 #!/usr/bin/env bun
 
 import { $ } from "bun"
-import { rm } from "fs/promises"
+import { mkdir, rm } from "fs/promises"
 import path from "path"
 import { Script } from "@opencode-ai/script"
 import { createSolidTransformPlugin } from "@opentui/solid/bun-plugin"
@@ -99,6 +99,7 @@ for (const item of targets) {
   }
   const target = targetName(item)
   const name = target.replace(binary, "cli")
+  const executablePath = await compileExecutable(item)
   console.log(`building ${name}`)
   const result = await Bun.build({
     entrypoints: ["./src/index.ts"],
@@ -115,6 +116,7 @@ for (const item of targets) {
       autoloadTsconfig: true,
       autoloadPackageJson: true,
       target: target.replace(binary, "bun") as Bun.Build.CompileTarget,
+      executablePath,
       outfile: path.join(outdir, name, "bin", binary),
       execArgv: [`--user-agent=${binary}/${Script.version}`, "--use-system-ca", "--"],
       windows: {},
@@ -154,6 +156,28 @@ for (const item of targets) {
   await verifyArtifact(path.join(outdir, name))
 }
 
+async function compileExecutable(item: (typeof allTargets)[number]) {
+  const release = process.env.BUN_COMPILE_RELEASE
+  if (!release) return
+
+  const platform = item.os === "win32" ? "windows" : item.os
+  const name = ["bun", platform, item.arch, item.abi, item.avx2 === false ? "baseline" : undefined]
+    .filter(Boolean)
+    .join("-")
+  const cache = path.join(outdir, ".bun", release)
+  const executable = path.join(cache, name, item.os === "win32" ? "bun.exe" : "bun")
+  if (await Bun.file(executable).exists()) return executable
+
+  await mkdir(cache, { recursive: true })
+  const archive = path.join(cache, `${name}.zip`)
+  const response = await fetch(`https://github.com/oven-sh/bun/releases/download/${release}/${name}.zip`)
+  if (!response.ok) throw new Error(`Failed to download ${name} from Bun release ${release}: ${response.status}`)
+  await Bun.write(archive, response)
+  await $`unzip -oq ${archive} -d ${cache}`
+  await rm(archive)
+  return executable
+}
+
 function targetName(item: (typeof allTargets)[number]) {
   return [
     binary,