好学云谱(yunpu)打包发布操作手册
配套 云端数据中心.md 阅读。本手册 = 版本同步 + 规范命名打包 + OTA 在线更新清单,step-by-step 可直接抄。
设计参考 PTPatronus 发版体系,适配好学云谱技术栈(原生 JS + Node 认证代理 + Capacitor Android + Electron 桌面 + Docker)。
命名规范速查(软件命名规则)
| 项 | 规则 | 示例 |
|---|---|---|
| 版本号 | semver MAJOR.MINOR.PATCH | 1.0.1 |
| 产物文件 | <产品名>-<版本>+<构建日期>-<平台>.<ext> | yunpu-1.0.1+20260714-windows-x64-portable.zip |
| 发版目录 | release/yunpu-<版本>+<日期>/ | release/yunpu-1.0.1+20260714/ |
| Docker 镜像 | ghcr.io/gntv456/yunpu:<版本> + :latest | ghcr.io/gntv456/yunpu:1.0.1 |
| Git tag | v<版本>(带 v 前缀) | v1.0.1 |
| OTA 清单 | update-manifest.json(latestVersion = 版本) | "latestVersion": "1.0.1" |
- 产品短名统一用
yunpu(与package.json的name一致)。 +YYYYMMDD是 semver 构建元数据,不影响版本优先级比较,仅作可追溯标识。- 平台后缀:
-mobile-pwa/-windows-x64-portable/-android。
每次发版(以 1.0.0 → 1.0.1 为例)
0. 改版本号(4 处自动同步)
npm run version:bump -- 1.0.1脚本 scripts/bump-version.mjs 一次性改:
package.json(权威,/api/system/version与打包脚本都从这里读)js/main.js(window.Yunpu.version运行时版本 + 控制台日志)android/app/build.gradle(versionName+versionCode自增)
「设置→关于」的版本号动态读
window.Yunpu.version,无需手改。
提交版本号:
git add package.json js/main.js android/app/build.gradle
git commit -m "chore: bump 版本号 → 1.0.1"1. 本地打包(Web PWA + Windows 便携)
npm run package:release脚本 scripts/package-release.mjs 产出:
release/yunpu-1.0.1+<日期>/yunpu-1.0.1+<日期>-mobile-pwa.zip—— 手机 PWA 静态包release/yunpu-1.0.1+<日期>/yunpu-1.0.1+<日期>-windows-x64-portable.zip—— Windows 便携版(自带 node 运行时)
可用
YUNPU_MOBILE_API_BASE=https://yunpu.example.com预填手机端默认后端地址。
2. (可选)Android APK / Electron 便携 exe
# Android APK(需 Android SDK,本机 .android-sdk 已在)
npm run package:apk
# 产物: android/app/build/outputs/apk/debug/app-debug.apk
# 重命名为规范名后拷进 release/yunpu-1.0.1+<日期>/yunpu-1.0.1+<日期>-android.apk
# Electron Windows 便携 exe(需 electron-builder,首次会下载 electron)
npm run package:desktop-exe
# 产物: release-desktop/yunpu 1.0.1.exe(portable)3. Docker 构建
本机 Docker 被 WSL2 未启用卡住(需重启装),镜像在 ptang 服务器构建(详见下文「Docker 构建(ptang)」),或推 v* tag 让 .github/workflows/docker.yml 在 CI 出多架构镜像。镜像名:ghcr.io/gntv456/yunpu:<版本> + :latest。
首次发布后到 GitHub → Packages → yunpu → Package settings → 设 Public,用户
docker pull免登录。
4. 回填 OTA manifest(sha256)
npm run release:manifest脚本 scripts/update-manifest.mjs 扫描 release/yunpu-1.0.1+<日期>/,按文件名后缀识别平台,计算 sha256 回填 update-manifest.json 的 targets.*.sha256,并同步 latestVersion 与 targets.docker.image。
然后手填两样:
targets.*.url:各产物上传网盘后,填网盘分享地址。当前手机/电脑安装包统一在蓝奏云https://wwazg.lanzoub.com/b03annjefe(提取码hxpt),三个客户端 target 都填它。releaseNotes:本次更新说明(带网盘提取码)。
5. 发布 OTA manifest 到 gist(在线更新源)
OTA manifest 托管在一个公开 GitHub gist(只含版本号 + changelog + 下载地址,无密钥):
| 项 | 值 |
|---|---|
| Gist 页面 | https://gist.github.com/gntv456/450138b061159bc6783b1c7b786e0b02 |
| raw 地址(最新版,带 ~5min CDN 缓存) | https://gist.githubusercontent.com/gntv456/450138b061159bc6783b1c7b786e0b02/raw/update-manifest.json |
docker-compose.example.yml 的 YUNPU_UPDATE_MANIFEST_URL 已默认指向它,用户开箱即用,无需配置。
每次发版要更新这个 gist 的内容(把新版 update-manifest.json 推上去)。两种方式:
- Web UI(最简单):打开上面 gist 页面 → 编辑
update-manifest.json→ 粘贴本地新版内容 → 保存。 - 命令行(在 ptang 上跑,本机连不上 GitHub):用带
gist权限的 PAT,bashtoken 用完即弃,不落盘。ssh ptang 'curl -sS -X PATCH https://api.github.com/gists/450138b061159bc6783b1c7b786e0b02 \ -H "Authorization: token <PAT>" -H "Accept: application/vnd.github+json" \ -d @<(python3 -c "import json;print(json.dumps({\"files\":{\"update-manifest.json\":{\"content\":open(\"/root/yunpu-build/update-manifest.json\").read()}}}))")"
6. 提交 + 打 tag
git add update-manifest.json
git commit -m "build: 发版 1.0.1(manifest + sha256)"
git tag v1.0.1
git push origin main --tags7. 验证
- 版本号:
curl http://<部署地址>/api/system/version→{"ok":true,"version":"1.0.1"} - OTA:
curl http://<部署地址>/api/system/update-check→manifest.latestVersion= 1.0.1 - 客户端:设置→关于,版本显示 v1.0.1;点「检查更新」,配了
YUNPU_UPDATE_MANIFEST_URL时提示最新/新版,未配时提示「未配置更新源」。 - Docker:
docker pull ghcr.io/gntv456/yunpu:1.0.1(或:latest)启动后关于页版本号变 1.0.1。
在线更新机制(两条,别混淆)
| 机制 | 触发 | 你要做的 |
|---|---|---|
| 客户端「检查更新」 | 客户端调本服务 /api/system/update-check,本服务代理官方 manifest,客户端与 window.Yunpu.version 比对 | 部署 compose 设 YUNPU_UPDATE_MANIFEST_URL,维护好 update-manifest.json |
| Docker 镜像更新 | 用户 docker compose pull && up -d 拉 :latest | push 完 :latest 即可 |
客户端不直连官方源(由本服务中转),避墙 + 不泄露官方地址。没设 YUNPU_UPDATE_MANIFEST_URL 只是客户端「检查更新」提示未配置,不影响拉镜像更新。
常见坑
- 网盘拿不到直链:用支持直链的网盘/对象存储,或自建静态站;manifest 的
url必须是直链,否则客户端「前往下载」打不开。 - APK 升级签名不一致无法覆盖安装:每次发版用同一签名(debug 包同 debug 签名可覆盖;正式发布建议配 release keystore)。
- manifest CDN 缓存:上传后 raw 约 5 分钟才更新,验证时等一下。
- ARM 部署:x86 build 出单 amd64,ARM 用户需 buildx 多架构。
/api/system/version返回 0.0.0:说明 server.js 读不到package.json,检查 Dockerfile 是否 COPY 了package.json(已 COPY)。
附录:Docker 构建(ptang 服务器)
本机 Docker 被 WSL2 未启用卡住(WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED,需管理员 wsl --install --no-distribution + 重启),所以镜像在 ptang 服务器构建(能直连 GitHub/Docker Hub,且就是 PTPatronus 那台)。流程:
# 1. 传代码(只传 Dockerfile 需要的文件,经 ssh 管道)
tar czf - index.html manifest.webmanifest runtime-config.js service-worker.js \
server.js package.json package-lock.json README.md Dockerfile .dockerignore \
css icons js \
| ssh ptang 'rm -rf /root/yunpu-build && mkdir -p /root/yunpu-build && tar xzf - -C /root/yunpu-build'
# 2. ptang 上构建(ghcr 全名 tag,方便后续推送)
ssh ptang 'cd /root/yunpu-build && docker build -t ghcr.io/gntv456/yunpu:1.0.1 -t ghcr.io/gntv456/yunpu:latest .'
# 3. 验证
ssh ptang 'docker run --rm -d --name yunpu-t -p 5199:5173 -e JIAPU_AUTH_SECRET=dev ghcr.io/gntv456/yunpu:1.0.1
&& sleep 2 && curl -s http://127.0.0.1:5199/api/system/version && docker rm -f yunpu-t'推到 GHCR(让用户 docker pull,需 device flow 授权一次,token 用完即 logout):见 PTPatronus 手册的 ghcr device flow(client_id 178c6fc778ccc68e1d6a,scope write:packages),或在 GitHub 仓库建一个 PAT 给 CI 用,打 v* tag 让 docker.yml 自动推。
ARM 部署需多架构:CI workflow 已配
linux/amd64,linux/arm64;ptang 本地只出 amd64。