基于源码同步(2026-08-27,dev 分支 6568a824)整理的发布流水线。入口为 .github/workflows/publish.yml,push 到 dev/beta 分支或手动触发,job 依赖链:

version → build-cli ──→ sign-cli-windows ──┐
        └→ build-electron ─────────────────┴→ publish

版本与 Channel

  • packages/script/src/index.ts(@opencode-ai/script)统一决定 channel 与 version:
    • channel:OPENCODE_CHANNEL > 有 bump 即 latest > 当前 git 分支;非 latest 即 preview
    • preview 版本:0.0.0-<channel>-<时间戳>;正式版:取 npm opencode-ai/latest 按 bump 递增
  • script/version.ts 生成 changelog 并创建 draft GitHub Release(beta 发到 anomalyco/opencode-beta 仓库)

CLI 二进制构建

packages/opencode/script/build.ts,用 Bun.build({ compile }) 编译独立二进制:

  • 12 个 target:linux/darwin/windows × (arm64, x64, x64-baseline) + linux musl 三变体;baseline = 无 AVX2
  • 内嵌 Web UI(先构建 packages/app 再以 type: "file" import)、tree-sitter worker
  • define 注入版本号、channel、models.dev 数据;产物名 dist/opencode-<os>-<arch>[-baseline][-musl]/bin/opencode
  • 当前平台产物跑 --version smoke test
  • release 时 linux 打 tar.gz、其余打 zip 上传 GH Release;每个 target 目录写含 os/cpu/libc 的 package.json,供 npm optionalDependencies 分发
  • 所有 CLI 二进制在 ubuntu runner 上交叉编译(含 Windows .exe),构建时不签名

签名

Windows:Azure Trusted Signing(两处)

  1. CLI(sign-cli-windows job):下载未签名 artifact → azure/login OIDC 联合登录 → azure/artifact-signing-action 签 3 个 opencode.exe → Get-AuthenticodeSignature 校验必须 Valid → Compress-Archive 重打包 → gh release upload --clobber 覆盖未签名 zip
  2. Desktop:electron-builder win.signtoolOptions.sign 回调 script/sign-windows.ps1,用 TrustedSigning PowerShell module(SHA256 摘要 + RFC3161 时间戳 timestamp.acs.microsoft.com),非 GitHub Actions 环境自动跳过

macOS:仅 Desktop 层签名+公证

  • apple-actions/import-codesign-certs 导入 p12 证书 + Apple API Key (.p8)
  • electron-builder.config.ts:hardenedRuntime: true、entitlements、notarize: true、dmg 签名
  • CLI 的 darwin 二进制不签名不公证(与桌面版不同)

更新包签名:Tauri signer

packages/desktop/scripts/finalize-latest-json.ts:汇总各平台 latest*.yml,对每个更新产物(exe/app.tar.gz/deb/rpm/AppImage)执行 bunx @tauri-apps/cli signer sign(密钥 TAURI_SIGNING_PRIVATE_KEY),生成 latest.json(含 url + signature)上传 Release。Desktop 内置 electron-updater 走 latest.yml 的 sha512 校验(见 升级机制)。

Desktop 构建(Electron)

build-electron job,matrix 6 平台(mac x64/arm64、win x64/arm64、linux x64/arm64):

  • scripts/prepare.ts 写版本号、拷贝图标,并调 build-node.ts 把 CLI 编成 Node 版 bundle 塞进 resources(dev channel 直接下载 CLI 二进制)
  • npx electron-builder --publish never,产物:dmg/zip(mac)、nsis exe(win)、AppImage/deb/rpm(linux)
  • appId 按 channel 隔离:ai.opencode.desktop[.dev|.beta];macOS 产物额外打 .app.tar.gz 供自动更新
  • Windows 产物逐个校验 Authenticode 签名后上传

分发(publish job)

script/publish.ts 编排,统一版本号写回所有 package.json 后:

渠道说明
npm各平台包(opencode-linux-x64 等)+ 主包 opencode-ai;postinstall.mjs 按平台 + AVX2 探测选二进制
GH Releasedesktop 全套资产 + 签名后的 windows zip + latest.json/latest*.yml
Dockerbuildx 多架构推 ghcr.io/anomalyco/opencode
AUR生成 opencode-bin PKGBUILD(内嵌 sha256)push 到 AUR
Homebrew生成 formula push 到 anomalyco/homebrew-tap

最后 gh release edit --draft=false 发布。与 GitHub仓库信息 中的安装脚本(curl 下载 Release 资产)对应。

要点

  • Windows 签名与构建分离:ubuntu 交叉编译 → windows runner 签名,两条流水线(CLI 用官方 action,Desktop 用 ps1 脚本)最终都走 Azure Trusted Signing
  • 校验环节:CLI/桌面 exe 均强制 Get-AuthenticodeSignature Valid 才放行
  • macOS 信任链只在桌面端建立;CLI 依赖用户手动放行 Gatekeeper
  • 版本一致性由 finalize-latest-json.ts 校验(latest.yml 版本 ≠ 发布版本即失败)