发布包
每个版本包含三个程序,各自提供便携包和安装包:gproxy-*:CLI,内置 Web 控制台。gproxy-headless-*:不带控制台的同一个 CLI,用于 CI 和小型服务器,见无前端 CLI。gproxy-tauri-*:桌面与移动端应用,同样内嵌控制台。
发布工作流还会发布 serverless 可执行文件(
gproxy-serverless-linux-<arch>-musl,x86_64 和 aarch64)、Cloudflare Workers 包(gproxy-edge-cloudflare.zip),以及 GNU 和 musl 容器镜像。应用包会生成托管在 GitHub 上的构建证明(attestation)。公开的发布附件只包括各个包、manifest.json 和 SHA256SUMS;单独的校验文件和构建证明属于 CI 内部输入。
各平台说明:
- Linux:CLI DEB 把
gproxy安装到/usr/bin。GNU Linux 应用依赖发行版的 GTK 3 和 WebKitGTK 4.1。musl 构建面向 Alpine,只提供 APK,不提供 DEB。 - Android CLI:Termux DEB 安装到
/data/data/com.termux/files/usr。Android CLI 使用distribution/termux/中的源码配方和固定版本的 Termux 官方构建器构建。DEB 和 ZIP 都依赖 Termux 的libc++、OpenSSL 和 CA 证书;ZIP 包含启动脚本、可执行文件以及记录安装和更新方法的TERMUX.txt。这些构建禁用了自更新:用 APT 安装新版 DEB,或在已启用的软件仓库收录后执行pkg upgrade gproxy。 - Android 应用:APK 使用
ANDROID_SIGNING_*secrets 签名并验证。每个应用的<target-triple>-tauri-apk条目写入 Ed25519 签名的更新清单,与 CLI ZIP 的更新分开。旧的服务包装 APK 不再构建。 - Windows:CLI MSIX 使用 Partner Center 分配的独立包身份
LeenHawk.GPROXYCLI,并提供控制台命令别名。应用依赖系统的 WebView2 Runtime。 - macOS:CLI DMG 包含可执行文件和在终端中安装的说明。应用 ZIP 保留桌面资源,macOS 版包含完整的
.app。构建只做 ad-hoc 签名,尚未接入 Developer ID 签名和公证。 - 鸿蒙:使用缓存的工具链镜像和固定版本的实验性 Tauri 分支构建,其他平台使用稳定版 Tauri。HAP 安装前需要自行签名,已在模拟器上验证。已实现持续后台运行,但能否生效取决于设备、系统版本和授予的权限;应用进程退出后代理随之停止。
构建环境
需要 stable Rust(edition 2024)、Go、Clang、Node.js 22.12+(推荐 24 LTS)和 pnpm。Linux 桌面构建还需要webkit2gtk-4.1、gtk+-3.0、libsoup-3.0 开发包。其他平台的工具链由发布工作流配置。
CLI 与控制台
在仓库根目录执行:pnpm --dir console build 会把构建好的控制台复制到 HTTP 宿主和 Tauri 宿主的嵌入目录,之后的 Rust 构建会把它编译进去。顺序不能颠倒:只执行 Rust 构建的全新检出没有控制台资源,/console 会返回 404。如果要使用单独构建的控制台,传入 --console-path console/dist。
Cargo feature
gproxy crate 的默认 feature 集合是 channels,memory,fs,bundled-vocabulary,embedded-console,postgres,mysql。
只带四个渠道、不带外部数据库驱动的精简构建:
gproxy-serverless 二进制,需要启用 postgres feature。
无前端 CLI
无前端 CLI 就是不启用embedded-console 构建的 gproxy 二进制。它保留代理路由、管理 API、全部渠道、SQLite、PostgreSQL 和 MySQL 驱动、内存缓存、本地文件存储和内置词表,通过 CLI 或管理 API 配置。构建不需要 Node.js、pnpm 或桌面库:
embedded-console 时,即使检出目录中已有构建好的控制台,也不会嵌入二进制。--console=false 还会关闭对外部控制台目录的服务。自定义 feature 集合如果需要内嵌控制台,加上 embedded-console。
发布工作流独立于控制台构建生成以下无前端包:
从 Releases 下载:开发通道选
nightly,beta 选 staging,稳定版选对应版本。无前端安装的自更新会选择对应的无前端包。
在 Android 的 Termux 中安装并启动:
gproxy 包提供同一个命令,安装时会替换后者。如果使用 ZIP,先安装运行库,再把 ZIP 解压到 Termux 主目录下的某个目录(Android 共享存储中的文件不能执行),然后在该目录中运行:
gproxy.exe 代替 gproxy。Windows MSIX 的包身份为 LeenHawk.GPROXYHeadless,命令别名为 gproxy-headless.exe,不会替换 CLI 的 gproxy.exe。GPROXY Headless 也已上架 Microsoft Store(9ND7FQQMV566)。
桌面与移动端应用
构建控制台后执行:--workspace 会把它包含进来。
要在本地生成发布包,先构建控制台,再运行打包脚本。pnpm --dir console build 已经会执行 sync-to-embed.mjs,再执行一次也没有影响。
dist/release/。
Cloudflare Workers
在仓库根目录执行:worker-build 负责编译和优化 WebAssembly 模块;check 用 Wrangler 做一次部署预演,不会发布。配置和运行限制见边缘部署;构建带自有渠道的 Worker 见新增渠道。
CI 执行的检查
提交 PR 前请先在本地运行。CI 对每次改动都会执行,分为后端、桌面和 WebAssembly 三个任务。 后端(workspace 默认成员):net feature,而 mio 无法在该目标上编译。
pnpm --dir console lint 包含翻译一致性检查(pnpm i18n:check)。修改 Rust DTO 后,执行 pnpm --dir console types 重新生成 TypeScript 类型。
发布
分支与更新通道
Release 工作流(.github/workflows/release.yml)在推送时发布:
dev开发新功能,推送后只发布到nightly(dev 更新通道)。main维护已发布的功能并修复 bug,推送后只发布到staging(beta 更新通道)。- 正式版本 tag 从
main创建,同时发布到 release 和 beta 通道,不会覆盖 dev 通道。
dev 前执行 bash scripts/push-dev.sh。脚本会获取最新的 origin/main,把 dev rebase 到它上面,再以针对上一次已发布 dev 的显式 --force-with-lease 推送。用 git config core.hooksPath .githooks 启用本地推送检查。
发布版本
在最新的main 之上执行 bash scripts/release.sh,其间只允许新增 chore(release): 提交。以下条件不满足时脚本会停止:
- tag 与 workspace 版本一致,且存在
release-notes/v<版本>.md; - 已跟踪的工作区是干净的;
HEAD包含最新的origin/main,且其后的提交都是chore(release):提交。
pnpm update --latest 更新控制台的 npm 依赖,用 cargo upgrade 升级 Rust 注册表依赖约束(包括大版本和固定版本),再用 cargo update 刷新 Cargo.lock。RSA/getrandom、JNI/Tauri、Codex reqwest 和 WebSocket 配置的兼容桥接依赖保留上游要求的版本线,但兼容版本仍会通过 cargo update 更新。需要先安装辅助工具:cargo install cargo-edit --locked。如果刷新改动了已跟踪文件,脚本会在打 tag 之前停止:处理兼容性变更,执行上面的检查,提交并推送到 main,然后重新运行脚本。预发布 tag 不执行依赖刷新。
随后脚本创建 tag,并把 main 和 tag 在一次原子推送中推上去。tag 触发的工作流发布 release 和 beta 通道,main 在该 tag 提交上的运行不发布任何内容。完成后用 scripts/push-dev.sh 推送 dev。
工作流负责构建各个包、生成签名的更新清单并上传附件。构建或签名任一步失败,发布就不完整。
版本 tag 还会执行 scripts/publish-crates.sh,把 MIT 许可的库发布到 crates.io。其他 crate 通过 git 或路径依赖使用,见嵌入核心库。
签名与商店提交
缺少签名密钥或 Store 身份变量时,打包会失败。- 更新清单:使用 Ed25519 签名,自更新在安装前校验。
- Android:APK 使用
ANDROID_SIGNING_*secrets 签名。 - macOS:只做 ad-hoc 签名。
- Windows:各包使用 Microsoft Store 的包身份。在
release环境中配置四个变量:MS_STORE_IDENTITY_NAME、MS_STORE_DISPLAY_NAME、MS_STORE_IDENTITY_PUBLISHER、MS_STORE_PUBLISHER_DISPLAY_NAME;CLI 使用对应的MS_STORE_CLI_*变量。Headless 的包身份和显示名固定,Store 提交只需在共用的发布者变量之外再配置MS_STORE_HEADLESS_PRODUCT_ID。正式版保留两种架构的 Store 提交包;设置MS_STORE_PUBLISH_ENABLED后,GitHub 发布成功会触发 Store 提交流程。Store 提交包不签名,由 Store 在分发时签名。 - GitHub 上的 Windows 包:发布包不做代码签名。版本附带的 ZIP 和 MSIX 都没有签名,Windows 运行前可能会弹出警告,MSIX 需要开启旁加载才能安装。签名版本只能从 Microsoft Store 获取,也可以用
winget install --source msstore安装。WinGet 社区源只接收已签名的 MSIX,发布包不签名期间不会有新版本。