各端发布步骤(闭源 · 私密免费分享)
配合 发布与在线更新.md 阅读。客户端覆盖 6 端:Docker(服务端+Web UI)/ Android / iOS / macOS / 鸿蒙 / Windows;监控 Agent 是配套组件(见附录)。
核心原则:源码留 Private 仓库,只分发产物(镜像 / APK / ipa / app / zip / hap),走私密网盘 + TG 群。
0. 所有端共用的发版动作(每次发版先做)
- 改版本号(4 处同步):
- backend/internal/version/version.go(权威,CI 会用 tag 覆盖)
- frontend/package.json(vite 注入
__APP_VERSION__) - mobile/lib/core/version.dart(离线兜底)
- mobile/pubspec.yaml(
version: X.Y.Z+<递增 buildCode>,影响 Android versionCode)
- 更新官方 manifest JSON(见 发布与在线更新.md §3.2):把各端新版本的下载直链 + sha256 填进
targets - 打 tag 触发 CI:bash
git tag vX.Y.Z git push origin vX.Y.Z # 必须带 v 前缀,触发全部 workflow - 等 CI 跑完(约 15 分钟),产物就绪
- 把产物搬到私密网盘:你作为仓库 owner 能从 GitHub Release 下载(Private repo 的 Release 外部下不了),下载后传网盘,把网盘直链回填进 manifest
1. Docker(服务端 + 内嵌 Web UI)
主形态。一个镜像同时提供 API(:8088)和 Web UI(前端 go:embed 内嵌)。
构建
- CI 自动(docker.yml):tag → 多架构镜像(amd64/arm64)→
ghcr.io/gntv456/pt-patronus:vX.Y.Z+:latest - 本地手动:
make image或docker compose build
产物:ghcr 镜像
分发(一次性配置):ghcr 包设为 public(GitHub → Packages → ptpatronus → Package settings → Public),用户 docker pull 免登录。
用户安装:给用户一份 docker-compose.yml(基于 docker-compose.yml):
services:
ptpatronus:
image: ghcr.io/gntv456/pt-patronus:latest
restart: unless-stopped
ports: ["8088:8088"]
environment:
APP_ENV: release
SECRET_KEY: <openssl rand -base64 32> # 必填,release 模式留空拒绝启动
ACTIVATION_SECRET: <openssl rand -base64 32> # 必填
UPDATE_MANIFEST_URL: https://<你的gist>/update-manifest.json # 在线更新
volumes:
- ./data:/app/datadocker compose up -d,访问 http://服务器:8088。
用户升级:docker compose pull && docker compose up -d;或 Web UI「设置 → 关于 → 检查更新」提示新版本后一键复制命令。
manifest:"docker": { "image": "ghcr.io/gntv456/pt-patronus:0.70.01", "instructions": "docker compose pull && docker compose up -d" }
2. Android(Flutter APK)
构建
- CI 自动(flutter-release.yml):tag → APK → GitHub Release
- 本地手动:
cd mobile && flutter build apk --release
产物:app-release.apk
⚠️ 发布前必须配 release 签名(否则用 debug 签名 → 不安全 + 新版无法覆盖安装旧版):
- 生成 keystore(一次性,妥善保管,丢了只能换包名重装):bash
keytool -genkey -v -keystore ptpatronus.jks -keyalg RSA -keysize 2048 -validity 36500 -alias ptpatronus mobile/android/key.properties(别提交 git,加进 .gitignore):propertiesstorePassword=*** keyPassword=*** keyAlias=ptpatronus storeFile=../ptpatronus.jksbuild.gradle.kts已配好 signingConfigs(见 build.gradle.kts:读android/key.properties,存在用 release 否则回退 debug)+ key.properties.example 模板- 每次发版用同一 keystore → 升级可覆盖安装
CI 自动签名(flutter-release.yml 的 android job 已配):在 GitHub Settings → Secrets and variables → Actions 配 4 个 secret,打 tag 时自动注入:
ANDROID_KEYSTORE_BASE64:base64 -w0 ptpatronus.jks(Linux/mac)/[Convert]::ToBase64String([IO.File]::ReadAllBytes("ptpatronus.jks"))(PowerShell)ANDROID_STORE_PASSWORD/ANDROID_KEY_PASSWORD/ANDROID_KEY_ALIAS未配 secret 时 CI 回退 debug 签名(能出包但无法覆盖安装升级)。
分发:APK 传网盘(直链)+ TG 群。
用户安装:首次下载 → 允许「未知来源」→ 安装;升级(应用内 OTA):旧版启动自动检查 / 账户页「检查更新」→ 弹窗 → 自动下载 APK(进度条)→ sha256 校验 → 调系统安装器(apk_downloader.dart)。
manifest:"android": { "url": "https://网盘直链/ptpatronus-0.70.01.apk", "sha256": "<sha256sum>" } ⚠️ url 必须是 .apk 直链(不是网盘页面/提取码页),否则 APP 自动回退外链浏览器下载。
算 sha256:sha256sum app-release.apk(Linux/mac)/ certutil -hashfile app-release.apk SHA256(Windows)。
3. iOS(Flutter IPA)
构建(需 macOS + Xcode + Apple 开发者账号):
cd mobile
flutter build ipa --release # 产物 build/ios/ipa/ptpatronus.ipa需在 Apple Developer 后台配好证书(Distribution)+ Provisioning Profile。
签名:Apple Developer 证书签名;分发方式决定 Profile 类型。
分发(私密,不进 App Store)—— 三选一:
| 方式 | 适合 | 上限 | 更新机制 |
|---|---|---|---|
| AltStore / AltSource(推荐私密) | 圈内邀请分享 | 需用户 7 天重签(自签) | 用户 AltStore 订阅 AltSource.json 源 → 自动检测更新 |
| TestFlight | 半公开测试 | 10000 测试员 | App Store Connect 推送,自动更新 |
| Ad-Hoc | 固定设备 | ≤100 台(设备 UDID 绑定) | 手动重装 |
AltStore 方案:用 mobile/altsource/gen_altsource.py 生成 AltSource.json(私密分发版,手动传参,不走 GitHub API——因 ipa 在网盘)。每次发 iOS 版:
cd mobile/altsource
cp config.json.example config.json # 首次:填 app_id / icon_url / website 等
cd .. && flutter build ipa --release # 出 build/ios/ipa/*.ipa,传网盘拿直链
cd altsource && python3 gen_altsource.py \
--version 0.70.01 \
--url https://网盘直链/ptpatronus-0.70.01.ipa \
--size $(wc -c < ../build/ios/ipa/*.ipa | tr -d ' ') \
--notes "本次更新内容..."把生成的 AltSource.json 推到公开 URL(gist / 轻量仓库 raw / 静态站),用户在 AltStore「添加源」订阅该 URL → 自动检测并安装/更新 ipa。
用户安装:AltStore 侧载 / TestFlight 邀请链接。
升级:iOS 端主要靠 AltStore/TestFlight 自身的更新机制;manifest 的 targets.ios 条目已常驻(url 指向下载页或 AltSource.json URL),Flutter iOS 端「检查更新」有新版时外链打开该页并提示走 TestFlight/分发渠道安装(实际安装仍走 AltStore)。
manifest:"ios": { "url": "<下载页或 AltSource.json URL>", "sha256": "<ipa 的 sha256,可选>" };ipa 拷进 dist 目录后 node scripts/update-manifest.mjs 会自动回填 sha256。
⚠️ CI:iOS 构建需 Apple 签名 secrets(证书 + Profile + 设备列表),CI 配置复杂,建议本地手动构建后传网盘,不放 GitHub Actions。
4. macOS(Flutter .app)
构建(需 macOS 机器):
cd mobile
flutter build macos --release # 产物 build/macos/Build/Products/Release/ptpatronus.app打包:整个 .app 打成 zip 或 dmg:
cd build/macos/Build/Products/Release
zip -r ptpatronus-macos-0.70.01.zip ptpatronus.app签名 / 公证(二选一):
- 私密分发不公证(最简):用户首次「右键 → 打开」绕过 Gatekeeper(会提示「未识别开发者」)。适合圈内小范围。
- Developer ID 签名 + 公证(体验最好):需 Apple 开发者账号 +
xcrun notarytool提交公证。用户双击即可运行。
分发:网盘 zip/dmg + TG 群。
用户安装:解压 zip → 拖到「访达 → 应用程序」→(首次右键打开,或在「系统设置 → 隐私与安全性」点「仍要打开」)。
升级:macOS 客户端「检查更新」→ 外链打开下载页 → 手动替换 .app(Flutter 桌面无应用内自更新,走外链兜底对话框)。
manifest:"macos": { "url": "https://网盘/ptpatronus-macos-0.70.01.zip", "sha256": "..." };zip 拷进 dist 目录后 node scripts/update-manifest.mjs 会自动回填 sha256。
CI 已自动:flutter-release.yml 的 macos job(runs-on: macos-latest)已配好,打 tag 自动出未签名 zip 挂 Release。无需任何 secret。
5. 鸿蒙 HarmonyOS
CI 没有鸿蒙 runner(需华为 flutter 分支 + DevEco Studio),纯手动。
构建(在配好鸿蒙 SDK + 华为 flutter 分支的机器上):
cd mobile
flutter build hap --release # 仅鸿蒙分支的 flutter 有 build hap产物:.hap 包。
分发:网盘。
用户安装:DevEco Studio 或 hdc install <hap>。
升级:手动重装(鸿蒙端暂未接在线更新;如需可加 harmony target 到 manifest,外链提示)。
6. Windows(Flutter Windows)
构建
- CI 自动(flutter-release.yml):tag → Windows → GitHub Release(zip)
- 本地手动:
cd mobile && flutter build windows --release,产物在mobile/build/windows/x64/runner/Release/
产物:ptpatronus-windows-x64.zip(整个 Release 目录打包)
分发:网盘 + TG 群。
用户安装:解压 → 运行 ptpatronus.exe(可能需在「Windows 安全中心」允许「更多信息 → 仍要运行」,因无代码签名证书)。
升级:Windows 客户端「检查更新」→ 外链打开下载页 → 手动替换文件(Flutter 桌面无应用内自更新,走外链兜底)。
manifest:"windows": { "url": "https://网盘/ptpatronus-windows-x64-0.70.01.zip", "sha256": "..." }
💡 代码签名(可选增强):购买 Windows 代码签名证书(EV/普通),用 signtool 签 exe,消除 SmartScreen 警告。私密分发可不签。
附录 A. 监控 Agent(配套组件,非客户端)
装在被监控服务器上,WS 主动上报指标到主面板。
构建
- CI 自动(release.yml):tag → linux amd64/arm64 二进制 → GitHub Release
- 本地手动:
cd backend && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ptpatronus-agent-linux-amd64 ./cmd/ptpatronus-agent
⚠️ 闭源关键坑:agent_install.sh 默认从 GitHub Release 下载,Private 仓库外部下不了。脚本已支持 AGENT_DOWNLOAD_BASE 环境变量——把两个架构二进制传网盘,安装命令带上 AGENT_DOWNLOAD_BASE=https://网盘/path,脚本即从 ${BASE}/ptpatronus-agent-linux-<arch> 下载,绕过 GitHub。或单独建 Public 仓库只放 agent Release(AGENT_REPO 指向它)。
用户安装:主面板「设备监控 → Agent 管理 → 新建」生成一键命令,被监控机执行 curl -fsSL <面板>/api/v1/monitor/agents/install.sh | AGENT_ID=.. AGENT_SECRET=.. DASHBOARD_URL=.. bash(自动 systemd 注册)。
升级:Agent 无自动更新,靠重装。manifest:"agent-linux-amd64": {"url":"...","sha256":"..."}、"agent-linux-arm64": {...}。
7. 一次完整发版 checklist
发版前(main 分支):
- [ ] 4 处版本号改成 X.Y.Z
- [ ] Flutter release keystore 已配(首次)/ 仍有效
- [ ]
make test全绿(后端 go test + 前端 npm build + Flutter analyze)
发版:
- [ ]
git tag vX.Y.Z && git push origin vX.Y.Z - [ ] 等 CI 全绿
- [ ] 从 GitHub Release / 本地构建产物:Android APK、Windows zip(+ macOS zip 若加 CI)
- [ ] 本地手动出:iOS ipa(Apple 签名)、macOS app(若未加 CI)、鸿蒙 hap
- [ ] 算各产物 sha256
- [ ] 全部传私密网盘,拿直链;iOS 的 AltSource.json 上传到公开 URL
- [ ] 更新官方 manifest:latestVersion +
targets各端 url + sha256 - [ ] 网盘 + TG 群发新版公告
验证:
- [ ] Docker:
docker compose pull && up -d,Web 关于页版本号变 X.Y.Z - [ ] 旧 Android:启动弹更新 → 下载 → 安装 → 新版启动
- [ ] iOS:AltStore 检测到新版本
- [ ] macOS / Windows:检查更新 → 外链下载替换
8. 闭源分发的特殊处理(汇总)
| 问题 | 解法 |
|---|---|
| Private repo 的 GitHub Release 外部匿名下不了 | 所有产物走私密网盘;manifest url 指向网盘直链 |
| docker 镜像默认跟随 repo 私有 | ghcr 包单独设 public(用户 pull 免登录) |
agent_install.sh 写死 GitHub Release | 改 URLS 指向网盘,或建公开 release 仓库 |
| APK 升级签名不一致无法覆盖安装 | 配 release keystore,每次同一签名 |
| iOS 不进 App Store 怎么分发 | AltStore/AltSource(私密推荐)或 TestFlight |
| macOS 未签名被 Gatekeeper 拦 | 用户右键打开绕过;或 Developer ID 签名+公证 |
| Windows 未签名被 SmartScreen 拦 | 用户点「仍要运行」;或买代码签名证书 |
| 网盘页面/提取码拿不到直链 | 用支持直链的网盘/对象存储,或自建静态站 |
| 防中间人替换产物 | manifest 每个产物填 sha256,下载后校验 |
9. 各端在线更新方式速查
| 端 | manifest target key | 更新落地方式 |
|---|---|---|
| Docker | docker | Web UI 提示 docker compose pull && up -d(一键复制) |
| Android | android | 应用内 OTA:dio 下载 APK → sha256 → 系统安装 |
| iOS | ios(可选) | AltStore/TestFlight 自更新为主 |
| macOS | macos | 外链下载 zip → 手动替换 .app |
| 鸿蒙 | harmony(可选) | 手动重装 |
| Windows | windows | 外链下载 zip → 手动替换 |
| Agent | agent-linux-* | 重装(暂无自动) |