Skip to content

Latest commit

 

History

History
312 lines (230 loc) · 16.1 KB

RELEASING.md

File metadata and controls

312 lines (230 loc) · 16.1 KB

Releasing / Packaging

本地打包

  • 生成安装包:pnpm build:mac
  • 生成 macOS Apple Silicon 安装包:pnpm build:mac:arm64
  • 生成 macOS Intel 安装包:pnpm build:mac:x64
  • 生成 Windows 安装包:pnpm build:win
  • 生成 Linux 安装包:pnpm build:linux
  • 生成“明确不签名”的安装包:pnpm build:mac:unsigned

产物默认在 dist/:

  • OpenCove-<version>-mac-arm64.dmg / OpenCove-<version>-mac-arm64.zip
  • OpenCove-<version>-mac-x64.dmg / OpenCove-<version>-mac-x64.zip
  • *.exe
  • *.AppImage / *.deb
  • opencove-server-<platform>-<arch>.tar.gz(macOS / Linux standalone CLI / Worker runtime)
  • opencove-server-windows-<arch>.zip(Windows standalone CLI / Worker runtime)

额外的 Release asset:

  • 所有包含 standalone installer 的 release 都会发布 tag-pinned 脚本: opencove-install-v<tag>.sh、opencove-install-v<tag>.ps1、 opencove-uninstall-v<tag>.sh、opencove-uninstall-v<tag>.ps1
  • 只有 stable release 额外发布 latest stable 别名: opencove-install.sh、opencove-install.ps1、 opencove-uninstall.sh、opencove-uninstall.ps1

发布渠道

本项目当前只区分两个发行渠道:

  • stable:给普通用户安装的正式版,使用纯版本 tag,如 v0.2.0
  • nightly:给你自己和早期测试者抢先试用的预发布版,使用带 nightly 后缀的 tag,如 v0.2.0-nightly.20260312.1

建议的判断标准:

  • 发布 nightly
    • main 上有值得提前验证的新功能、重构或高风险修复
    • 你想先给少量测试者试,不想立刻推荐给所有人
  • 发布 stable
    • 这批改动已经过你自己的实际使用验证
    • pnpm pre-commit 全绿
    • 你能清楚说明这次更新为什么值得普通用户安装

GitHub:打 Tag 自动打包(unsigned)

本仓库已配置 GitHub Actions:当你 push 形如 v* 的 tag 时,会自动构建 macOS / Windows / Linux 三端产物,并自动创建对应的 GitHub Release。无需手动打包或手动上传产物。上传内容包括:

  • macOS Apple Silicon 产物(OpenCove-<version>-mac-arm64.dmg / .zip)
  • macOS Intel 产物(OpenCove-<version>-mac-x64.dmg / .zip)
  • Windows 产物(如 *.exe)
  • Linux 产物(*.AppImage / *.deb)
  • macOS / Linux standalone server bundle(opencove-server-<platform>-<arch>.tar.gz)
  • Windows standalone server bundle(opencove-server-windows-<arch>.zip)
  • tag-pinned 一键安装 / 卸载脚本(opencove-install-v<tag>.*、opencove-uninstall-v<tag>.*)
  • stable release 额外包含 latest stable 别名(opencove-install.*、opencove-uninstall.*)
  • 汇总校验文件 SHA256SUMS.txt

注意:macOS 的应用内自动更新依赖稳定的代码签名(Developer ID)。当前 unsigned/ad-hoc 构建在 macOS 上会禁用更新检查;请通过 GitHub Releases 手动下载新版本。macOS release 现在使用拆分的 arm64 / x64 单架构安装包,release workflow 不上传单一 latest-mac.yml,避免更新 metadata 指向错误架构;恢复 macOS 自动更新前必须先补齐 universal 或按架构分流的更新策略。

其中:

  • v0.2.0 会创建正式 stable release
  • v0.2.0-nightly.20260312.1 会创建 nightly prerelease

Standalone CLI / Worker 资产

只有当 release 实际包含以下资产时,才能对外宣称“可直接通过 GitHub Release 安装 OpenCove CLI / Worker”:

  • opencove-server-<platform>-<arch>.tar.gz
  • opencove-server-windows-<arch>.zip
  • opencove-install-v<tag>.sh
  • opencove-install-v<tag>.ps1
  • opencove-uninstall-v<tag>.sh
  • opencove-uninstall-v<tag>.ps1

stable release 额外再提供以下 latest stable 别名:

  • opencove-install.sh
  • opencove-install.ps1
  • opencove-uninstall.sh
  • opencove-uninstall.ps1

对外文档必须与已发布资产保持一致。如果 releases/latest/download/opencove-install.sh 返回 404,说明 latest stable 尚未 发布 standalone installer,README / docs 不应写成“latest stable 可直接安装”。

当 latest stable 已包含这些资产时,没有 Desktop 的机器可使用以下安装脚本:

macOS / Linux:

curl -fsSL https://github.com/DeadWaveWave/opencove/releases/latest/download/opencove-install.sh | sh

Windows PowerShell:

powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod https://github.com/DeadWaveWave/opencove/releases/latest/download/opencove-install.ps1 | Invoke-Expression"

对于 nightly 或任意指定 tag 的 release,请改用对应 release 页面里的 tag-pinned installer:

curl -fsSL https://github.com/DeadWaveWave/opencove/releases/download/v<version>/opencove-install-v<version>.sh | sh
powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod https://github.com/DeadWaveWave/opencove/releases/download/v<version>/opencove-install-v<version>.ps1 | Invoke-Expression"

安装脚本会:

  • 按平台/架构下载 opencove-server-<platform>-<arch>.tar.gz 或 opencove-server-windows-<arch>.zip
  • 同时下载同一路径的 SHA256SUMS.txt 并验证 bundle;找不到 checksum、本机没有 SHA256 工具或 hash 不一致时 fail closed,不解压也不安装
  • macOS / Linux 默认安装到 ~/.local/share/opencove(可由 OPENCOVE_INSTALL_ROOT 覆盖)
  • Windows 默认安装到 %LOCALAPPDATA%\OpenCove\standalone(可由 OPENCOVE_INSTALL_ROOT 覆盖)
  • macOS / Linux 在 ~/.local/bin/opencove 写入 launcher(可由 OPENCOVE_BIN_DIR 覆盖)
  • Windows 在 %LOCALAPPDATA%\OpenCove\bin\opencove.cmd 写入 launcher,并把该目录加入用户级 PATH(可由 OPENCOVE_BIN_DIR 覆盖)

服务器上的典型启动方式:

opencove worker start --hostname 0.0.0.0 --web-ui-password 'change-me'

卸载 standalone runtime:

curl -fsSL https://github.com/DeadWaveWave/opencove/releases/latest/download/opencove-uninstall.sh | sh
powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod https://github.com/DeadWaveWave/opencove/releases/latest/download/opencove-uninstall.ps1 | Invoke-Expression"

对于 nightly 或任意指定 tag 的 release,请使用对应的 tag-pinned uninstall 脚本:

curl -fsSL https://github.com/DeadWaveWave/opencove/releases/download/v<version>/opencove-uninstall-v<version>.sh | sh
powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod https://github.com/DeadWaveWave/opencove/releases/download/v<version>/opencove-uninstall-v<version>.ps1 | Invoke-Expression"

发布约束:

  • stable 同时发布 latest 通用别名与 tag-pinned 脚本;nightly 只发布 tag-pinned 脚本。
  • releases/latest/download/... 只能表示 latest stable,不得在 nightly 文档中当作“当前 nightly”使用。
  • Managed SSH 的 bootstrap / reinstall 使用 Desktop 当前版本拼出 tag-pinned installer URL;该 installer 下载的 standalone Worker 必须报告相同版本,不能成为身份不明的 runtime,也不能在这条安装路径中回退到 latest 猜测。
  • release workflow 会在上传前使用本地生成的 standalone asset 运行安装 smoke。
  • stable 资产先以 prerelease 且非 latest 的状态暂存。Verify Published Standalone 必须在 macOS arm64、macOS x64、Windows x64 和 Linux x64 上从公开的 tag-pinned URL 下载 installer、uninstaller 与 bundle,验证实际 SHA256、隔离安装、launcher、Worker 启动、system.ping、版本身份和卸载后置条件。四个平台全部通过后,workflow 才能把该 release 提升为 stable/latest。
  • 提升 stable 后,Verify Latest Stable Download 还必须通过 releases/latest/download 再完成一次 Linux 下载、SHA256、安装、Worker 健康和卸载验证。任一验证失败时不得宣称 Remote Worker 可用;修复后必须重新跑真实公开 URL,不能用本地产物代替。

Standalone server 资产与 Desktop 资产是独立 runtime:bundle 提取应用代码、内置 release job 使用的 Node,并针对该 Node ABI 重新构建 better-sqlite3 / node-pty。Linux release 还必须在 debian:bookworm-slim 容器内真实启动 Worker,确认 CLI 与 Worker 的 executable 都指向 bundle 内 Node,且 runtime 目录中不存在 Electron executable;宿主 runner 上的 --help 不能替代这条 smoke。

Linux 符号基线(glibc / libstdc++)

Standalone server 的 Linux 支持基线覆盖 RHEL/Alma/Rocky 8+、Debian 10+、Ubuntu 18.04+、 Amazon Linux 2023。四个符号族的上限如下,均实测自 AlmaLinux 8(即 glibc 2.28 基线本身) 所提供的版本,而非手工挑选:

符号族 上限
GLIBC 2.28
GLIBCXX 3.4.25
CXXABI 1.3.11
GCC 7.0.0

GLIBC_2.28 同时是我们内置的官方 Node linux-x64 二进制自身的最高要求,所以它是整个 bundle 的 天然下限 —— 原生模块建得更低没有收益,建得更高则会成为唯一短板。GLIBCXX_3.4.25 则独立复现了 VS Code 公开的 Linux server 要求,说明这条基线是业界通行值而非自创。

注意必须四族都检查:Node 二进制除 GLIBC/GLIBCXX 外还要求 CXXABI_1.3.9 与 GCC_3.4。 只匹配前两族会让后两族被静默忽略。检查器对未知符号族一律报错(fail-closed),因此新增依赖 不会悄悄溜过去。

因此 Linux 的原生模块必须在老 glibc 容器内编译,由 release workflow 的 OPENCOVE_NATIVE_BUILD_IMAGE 指定(quay.io/pypa/manylinux_2_28_x86_64:glibc 2.28 基底 + 满足 better-sqlite3 -std=c++20 所需的新 gcc)。在 runner 上直接编译会得到 GLIBC_2.38 之类的依赖,只能在与 runner 同代或更新的发行版上加载。

scripts/check-standalone-glibc-floor.mjs 会读取产出的 ELF 来核验这条基线,因此它不依赖 「容器配置正确」这一假设;读不到符号即失败,不会静默放过。若要调整基线,改 scripts/lib/standalone-glibc-floor.mjs 中的 STANDALONE_GLIBC_FLOOR,并同步更新本节。

一次性原生验证进程的生命周期

managedRuntime verify 和 prepare 是一次性 CLI,由入口拥有进程终止权。 只有命令完成(包含 finally 清理)并刷新 stdout/stderr 后才能退出;失败必须以非零退出码结束。 Windows node-pty 的 Conout 后台线程可能在 PTY 已退出后仍保持 Node 活跃(上游 microsoft/node-pty#887),因此不能仅依赖事件循环自然清空。 不得通过忽略超时、仅解析 stdout 或跳过原生探测来接受安装。子进程回归测试覆盖残留线程、输出完整性和失败退出码, Windows E2E 与 release standalone smoke 覆盖实际原生运行时。

Stable 流程

流程建议:

  1. 用脚本准备版本与 changelog 模板
pnpm release:patch
# 或
pnpm release:minor
# 或显式版本
pnpm release:version 0.2.0
  1. 填好 CHANGELOG.md 新增版本段落
    • 若本次为 major 或 minor 版本(例如 0.1.0 -> 0.2.0、0.x -> 1.0.0),必须补一段 ### ✨ Highlights
    • 若本次为 patch 版本(例如 0.2.0 -> 0.2.1),不强制要求 Highlights
  2. 为该 stable 版本补一份结构化 What's New manifest:
    • 路径:build/release-notes/stable/v<version>.json
    • 要求:至少提供 en;若有对外中文体验,则同步补 zh-CN
    • 该文件是应用内 What's New 的版本真相源;CHANGELOG.md 负责历史文档,二者不再互相解析
    • 只写用户可感知内容:用户能直接看到或使用的新能力、工作流变化、问题修复和必须知道的限制。内部架构、owner/协议细节、重构、测试、CI、依赖升级和发布 bookkeeping 只留在 changelog;只有它们直接改变了安装方式、支持平台、安全行为或用户体验时,才描述最终用户结果,不描述内部实现。
    • 使用结果导向的表达,例如“重启后终端仍可继续输入”,不要写“新增 revision fence / CAS owner”。优先保留 6-12 条最重要内容,不把完整 changelog 搬进弹窗。
  3. 更新 README 顶部的 Important Announcement / 重要公告,用 1-3 句短文概括这次对外想传达的重点
  4. 运行 pnpm pre-commit
  5. 提交 release 准备改动到 main
  6. 先以 exact candidate SHA 手动运行 Release workflow 的 dry_run=true,确认四平台构建与本地 standalone 安装 smoke 全绿
  7. 创建并 push annotated tag
git tag -a v0.2.0 -m "OpenCove v0.2.0"
git push origin v0.2.0
  1. 等待 release workflow 依次完成 Stage Release Assets、四平台 Verify Published Standalone、Promote Verified Stable Release 与 Verify Latest Stable Download,再核对公开资产、SHA256SUMS.txt、tag commit 和 latest 指向。发布完成后也可从本机复核 tag-pinned 与 latest 两条路径:
node scripts/smoke-published-standalone-runtime.mjs v0.2.0
node scripts/smoke-published-standalone-runtime.mjs v0.2.0 --installer-source=latest

如需先预览下一版而不落盘:

node scripts/prepare-release.mjs 0.2.0 --dry-run

Nightly 流程

nightly 默认不改 package.json 版本号,也不要求更新 CHANGELOG.md。它的作用是把当前 main 的某个快照发给测试者。 只有 stable release 才需要在仓库里 bump package.json.version;nightly 只是开发快照,不是新的正式版本承诺。 但为了让应用内更新检测能正确比较版本,CI 在构建 nightly tag 时会临时把 package.json.version 改成对应的 nightly tag 版本;这个改动只发生在 CI 构建目录,不会回写仓库。 应用内 What's New 不再在运行时抓 GitHub compare;nightly 会在构建前自动生成一份版本级 manifest,并嵌入安装包。

推荐流程:

  1. 确认当前 main 已经推到远端
  2. 用当天日期 + 递增序号创建 nightly tag
git tag v0.2.0-nightly.20260312.1
git push origin v0.2.0-nightly.20260312.1

约定建议:

  • 同一天第一次 nightly 用 .1
  • 同一天第二次 nightly 用 .2
  • 如果下一次 stable 准备发 v0.2.1,nightly 也可以提前切到 v0.2.1-nightly.20260313.1

补充说明:

  • stable 路径可以先运行 pnpm release:version 0.2.0,自动更新 package.json 和 CHANGELOG.md 模板。
  • prepare-release 会在 major / minor 版本自动插入 ✨ Highlights 模板;patch 版本不会插入。
  • nightly 路径不需要运行 release 准备脚本;只要 push 合规 tag,CI 就会自动打包并发布 GitHub prerelease。
  • 如需手动覆写某个 nightly 的应用内 What's New,可新增 build/release-notes/nightly/v<version>.json;存在时会优先于自动生成结果。
  • Auto Update 依赖 release assets 中的 channel metadata。当前 GitHub Actions 只上传 Windows / Linux 的 latest*.yml;macOS 因 unsigned/ad-hoc 构建禁用自动更新,暂不上传 latest-mac.yml。
  • 构建命令会自动生成 release/release-manifest.json,并将其嵌入安装包,同时作为 GitHub Release asset 上传。

Nightly 定时发布(每天 04:00 北京时间)

仓库提供一个定时任务:每天北京时间 04:00 自动从 main 打包并发布最新 nightly(GitHub prerelease)。

  • Workflow: .github/workflows/nightly.yml
  • Tag 形如:v<package.json.version>-nightly.<YYYYMMDD>.<N>

未签名/未公证的安装说明(给用户)

当前 Release 构建未做 Apple Developer ID 签名/公证,macOS 可能会拦截首次打开。

可选处理方式:

  • Finder:右键 App → 打开 → 再次确认
  • 或终端(拷贝到 Applications 后):xattr -dr com.apple.quarantine /Applications/OpenCove.app

本地构建 Standalone 资产

如需本地验证无需 Desktop 的 CLI/server 安装链,请使用:

pnpm build:standalone

这会:

  • 先构建 app 与 release manifest
  • 生成 unpacked Electron runtime
  • 再封装出 dist/opencove-server-<platform>-<arch>.tar.gz

签名 + 公证(可选)

当你开通 Apple Developer Program 后,可以在 CI 中注入签名证书与 notarize 凭据,让 Release 自动完成签名与公证。