dwgx@blog:~$dwgx
> cd ../posts

windsurf-ls-release:给 WindsurfAPI 做的 language server 二进制镜像

// created

windsurf-ls-release 是给我另一个项目 WindsurfAPI 做的 language server 二进制镜像仓库。WindsurfAPI 跑起来得有一份 language server 二进制,这堆 language_server_* 塞在 Devin Desktop 官方桌面包里,位置、版本、结构说变就变。我不想让用户在 install-ls.sh 里直连一个随时挪窝的上游,所以单独开了这个镜像。

它每天定时把上游最新二进制抠出来,重发成 GitHub Release 当 fallback,安装器指到这就行:

https://github.com/dwgx/windsurf-ls-release/releases/latest/download

说清楚,发的是从上游包直接提取的二进制,不是我编译的,我就是个搬运加校验的中间层。

核心是一个 GitHub Actions,cron: "17 3 * * *" 每天凌晨跑,三步对应三个纯 Python 脚本。discover_release.pydocs.devin.ai,解出页面里的 JSON/MDX 块,拿 stable 和 next 两条频道的最新版拼成 manifest。build_assets.py 按 manifest 下官方归档,Linux 是 .tar.gz,mac/Win 是 .zip,从里面抠 language_server_*;解包这块加了路径穿越防护,归档里的东西不能信,谁知道有没有个 ../../ 想往外写。render_release_notes.py 渲染 release notes,顺带带上 release-manifest.jsonSHA256SUMS

几个在意的点。stable 发 Latest,next 发 prerelease,这样 /releases/latest/download/ 永远只指稳定版,不会被 next 顶上去把用户搞崩。fail closed:上游结构一变脚本直接退,绝不静默发错东西,镜像最怕悄无声息发错版本。非默认分支只验证不发布,真发布只在默认分支,stable 打 v<version>,next 打 next-v<version>。平台只有 Linux x64 标成必须成功,别的尽力而为。

顺手写了 tools/update_ls_linux_x64.sh,一个独立 POSIX shell 更新器,优先走 ghfast.top 代理,代理挂了回退直连,下完先 SHA256 校验再替换,国内拉 GitHub 代理回退是刚需。

LS_CHANNEL=stable ./tools/update_ls_linux_x64.sh

整个项目只用 Python 3.12 标准库,零第三方依赖,测试用 unittest。一个下载、解包、校验的活儿,不想还先 pip install 一堆东西,越薄越好。现在它每天安静跑一次,当 WindsurfAPI 的公共二进制来源活着。