- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
本文以 RELEASING.md 为骨架,完整讲解 WuKongIM 一次“请求发布”从版本段整理、固定 QPS/P99 回归门禁、Docker 镜像与二进制发布,到签名原生包(APT/RPM)发布与公网可用性验证的全流程。读完后,你应当能够独立执行一次合规的 WuKongIM 发布任务:知道哪些证据缺失即代表发布未完成、如何核对不可变身份(source SHA、digest、Release ID),以及四套 Linux 发行版上的干净客户端验收到底检查了什么。
一、发布完成的定义:四件交付物与“失败即未完成”
WuKongIM 的一次发布请求同时包含四类交付物,任何一类未验证完成都不能报告发布完成:
- Docker 镜像——多平台不可变镜像及其在三个镜像仓库中的同步副本;
- 不可变 GitHub 二进制资产——各平台归档与对应 tag 的 GitHub Release;
- 文档部署——发布版本的文档站点部署结果;
- 适用的签名原生包频道——预发布版本对应
preview频道的 APT/RPM 发布。
执行发布时必须保留既有的签名、评审、不可变身份与受保护 Environment 要求。原文给出了两条硬性纪律,它们贯穿全文:
- 失败的阶段保持未完成状态,不能把部分完成的发布包装成已完成;
- 永远不通过替换不可变 tag 或 Release 来修复下游发布问题。下游(如包仓库、Pages、客户端)出问题,只能走对应仓库既有的恢复契约,而不是回改上游身份。
发布前应阅读 Workflow 目录(仓库.github/workflows/下的工作流目录文档),了解每个发布器(publisher)的触发条件与权限边界。
二、阶段一:源码发布(Source Release)
2.1 整理 CHANGELOG 版本段并通过发布说明校验
源码发布的第一步是把适用的Unreleased条目移动到 CHANGELOG.md 中该 tag 对应的精确版本段。根CHANGELOG.md约定:Unreleased段必须位于文件最前且只出现一次,版本段标题必须严格匹配## [vMAJOR.MINOR.PATCH[-PRERELEASE]] - YYYY-MM-DD格式,条目必须归入文件内声明的固定双语分类(如### 🚀 New Features / 新功能、### 🐛 Bug Fixes / 问题修复等)。
在打 tag 之前,仓库提供 awk 校验/提取脚本来验证整份 changelog 并提取精确版本正文:
awk -v version=v3.0.0-beta.5 \ -f scripts/extract-release-notes.awk CHANGELOG.md >/dev/null从 extract-release-notes.awk 的实现可以看到它把“格式不合法”直接当作失败处理:拒绝 CRLF 行尾、拒绝重复的版本号、拒绝空分类(每个分类至少要有一条-列表项)、拒绝目标版本出现 0 次或多次,并要求首行恰为# Changelog。也就是说,Docker 发布器所要求的“tag 对应的 CHANGELOG 中恰好存在一个非空且格式正确的版本段”并非口头约定,而是由这份脚本与发布工作流共同强制的。
2.2 固定 QPS/P99 与分配回归门禁
发布要求针对该精确 tag在 Docker 与二进制两个发布器中通过固定的会话 QPS/P99 和内存分配回归门禁。验证项包括:
- 全部12 个单节点/三节点 endpoint/page 用例,外加7 个三节点 mixed/hidden 窗口,合计20 个 endpoint 结果;
- 干净的 source SHA、profile 与二进制哈希;
- 测量前后所有角色零 active runtime;
- 零错误、零新增 runtime load、零 membership write;
- 达到 QPS/P99 下限值。
证据缺失或任一用例失败都会阻断发布。
门禁本身由可复用工作流 conversation-qps-gate.yml 承担:它以只读权限运行在ubuntu-24.04上,24 分钟作业时限,先校验 tag 形如v*、tag 指向的 commit 与 HEAD 一致、该 commit 是origin/main的祖先、工作树干净,然后执行单节点与三节点集群(256 hash slots,每节点GOMAXPROCS=2)的固定负载矩阵,并输出source_sha供发布器比对——换了一个 commit 就不能复用另一份证据。
固定负载与验收阈值定义在 profile.json(wukongim/conversation-qps-profile/v2)中,关键参数如下:
| 参数 | 值 | 含义 |
|---|---|---|
duration_seconds | 15 | 每个测量相位 15 秒的定时到达 |
workers | 8 | 每相位有界 worker 数 |
cohorts | 3,每 cohort 200 channels、8 users | 600 个已持久化会话组,24 个读取者,每频道 3 条消息 |
payload_bytes | 256 | 固定消息载荷 |
min_completion_ratio | 0.95 | 至少完成 95% 的 offer 请求 |
max_p99_ms | 500 | P99 不得超过 500 ms |
基础用例覆盖/conversation/list与/conversation/sync两个 endpoint,分别以page_size25/100/200 三档运行,offer QPS 依次为 400/200/100(list)与 80/60/40(sync)。每个用例还带max_allocated_bytes_per_request按拓扑("1"单节点、"3"三节点)划定的单请求分配字节上限,用于捕捉尚未触顶的分配回归,例如/conversation/listpage 25 单节点上限 550,000 字节、三节点 800,000 字节。
stress_gate段定义了三节点压力门禁:list 200 QPS 与 sync 60 QPS 同时运行 60 秒(每 endpoint 8 workers),另有 6 个 15 秒的 hidden 窗口以 20 QPS、8 workers 分别验证 50% hidden、90% hidden 以及 99-visible/100-hidden/1-visible 布局,各跑 page 1(size 100)与 page 2(size 50),并按窗口类型固定分配上限(mixed 5 MB、hidden_90_percent 7.5 MB 等)。
结果由 validate-conversation-qps-report.jq 过滤:它要求 7 个窗口齐全、两个同时运行 endpoint 的精确设置匹配、同样的零错误与 500 ms P99 规则成立,并把报告与 HEAD SHA、profile 文件哈希绑定。此外,响应必须包含完整且正确的消息身份,测量请求不做重试;缺失指标直接判失败。即使失败,门禁也会保留完整的 source/profile/二进制哈希、12 项基础结果与 7 个压力窗口共 90 天。该门禁没有任何阈值覆盖或旁路输入——失败时应基于证据诊断 runner,而不是调低下限或反复重跑。
2.3 完成 Docker 与二进制发布器并核对身份
门禁通过后,需为同一 tag 完成 Docker 镜像发布器 docker-image-publish.yml 与二进制发布器 binary-release-publish.yml,并验证:
- 三个镜像仓库(
ghcr.io/wukongim/wukongim、docker.io/wukongim/wukongim、registry.cn-shanghai.aliyuncs.com/wukongim/wukongim)暴露相同的 source SHA 与多平台 digest; - 不可变的数字 GitHub Release ID、完整资产集、校验和与 provenance 齐全;
- 若进入原生包发布,保留 source DEB/RPM 的摘要(digest)。
从工作流目录文档可知,二进制发布器会构建linux/amd64、linux/arm64、darwin/amd64、darwin/arm64四个确定性归档,每个归档包含wukongim、wkcli两个二进制、中英 README 与wukongim.toml.example;当 tag 源码中存在 .goreleaser.packages.yaml 时,同一次运行还会用 GoReleaserv2.18.0构建未签名的 Linux amd64 DEB/RPM,规范化命名为wukongim_<version>_linux_amd64.deb与wukongim_<version>_linux_amd64.rpm。所有归档与原生包共享一份 SHA-256 校验和文件与一份签名的 GitHub build-provenance 声明;这些原生包是“未签名 source 资产”,必须等包仓库施加并验证生产签名后才能发布。
身份注入的底层机制可以从源码印证:.goreleaser.packages.yaml 通过 ldflags 把main.buildVersion、main.buildCommit与main.buildSource=release编译进二进制;而 cmd/wkcli/version.go 与 cmd/wukongim/version.go 的默认值分别为dev/unknown/source。这解释了后文“build source 必须为release”的验收依据——未注入发布身份的二进制在版本自检中会直接暴露出来。
2.4 验证文档部署
发布还需验证文档部署(由 docs-pages.yml 承担)。需要强调的是它的独立性:文档部署成功与否与 APT/RPM 发布相互独立,文档部署成功也不证明包可用。它只是四件套中独立的一件。
三、阶段二:签名原生包发布
3.1 频道策略与触发方式
- 预发布版本走
preview频道; - 稳定版发布保持禁用,直到包仓库要求的存储与签名前置条件满足。不得把稳定版发布到 preview,也不得在其适用频道不可用时报告交付完成;
- 原生包工作流只接受显式 dispatch:推送 source tag 不会触发它们。发布操作者必须在同一发布任务内完成以下序列。
3.2 六步发布序列
原生发布全部发生在独立的WuKongIM/packages仓库中,本仓库只产出未签名的 source 资产。序列如下:
- Source 预检:从
WuKongIM/packages的main运行source-release-preflight.yml,并传入精确的数字 source Release ID。要求校验和、不可变身份、provenance 与包元数据校验全部成功。 - 读取线上状态:读取
packages.githubim.com上实时的status.json,验证其不可变 audit Release 后再将其选为基线;检查保留(retention)与容量,在新增版本前完成任何必需的退役(retirement)。 - 创建审计草稿:从精确的当前包仓库
mainSHA 运行native-package-audit-draft.yml,operation=add_release,目标版本不带v前缀。保留返回的数字 audit Release ID 与上一个 control SHA。 - 评审
manifests/channels.json变更:加入精确版本、source SHA、数字 source/audit Release ID、以及未签名 source DEB/RPM 的 SHA-256 值;把 publication 指向新的 audit ID 与已验证的 base ID;保留既有版本与 bootstrap 字节。运行包契约测试与必需 PR 检查后合入该 control 变更。 - 绑定与发布:待其他包生产运行结束后,用保留的 audit ID、上一个 control SHA 与精确合入后的
mainSHA运行native-package-audit-bind.yml;绑定成功后,用同一合入 SHA 与 audit ID 派发native-package-publish.yml。绑定或发布进行期间不得推进包仓库main。若绑定后main已推进,按包契约的 new-draft 恢复流程处理,永远不要移动保留的 tag。 - 等待完整 publisher 成功:包括公网干净客户端验证。它分别签名 APT 与 RPM、封存一份不可变 audit 快照、部署完整仓库,并在 Ubuntu、Debian、Rocky Linux 与 AlmaLinux 上验证目标版本下载。新版本的发布还额外要求四套发行版上的已安装 CLI 验收通过。
边界纪律:绝不把签名凭据复制进 source 仓库,绝不绕过签名元数据校验;只通过包仓库既有的恢复契约恢复精确匹配的草稿或不可变快照。本仓库侧的 native-package-preview.yml 是一个无凭据的验证工作流而非发布器——它在仓库外用一次性TEST ONLY密钥签名临时仓库做闭环验证,验证完即丢弃,从不上传或发布这些临时签名产物。
四、阶段三:公开可用性与交付证据
4.1 公网状态与版本映射核对
发布器成功不等于公网可见。操作者需确认:
- 公网状态报告指向预期的目标版本与 audit ID;
- APT
Packages索引包含精确映射后的 DEB 版本——SemVer 到 DEB 版本的映射规则是替换连字符为波浪号,例如v3.0.0-beta.9变为3.0.0~beta.9; - publisher 的干净 APT/RPM 客户端检查必须选中并下载目标版本,仅仅刷新了旧元数据不算数。
单个 GitHub 资产 URL、一次成功的/repo调用,或一次 Pages 部署状态,都不足以证明发布可用。若传播延迟导致旧快照仍可见,就保持“未完成”状态,直到公网检查通过。
对已配置好源头的 Debian/Ubuntu 客户端,操作者可运行:
sudo apt update apt-cache madison wukongim sudo apt install -y wukongim4.2 双二进制版本身份交叉验收
对包含统一操作 CLI 的发布版本,每个干净原生客户端还要检查:
wkcli version --output json wukongim version --output json两条输出的version、完整 commit 与build_source必须相互一致,并且都必须匹配已评审快照的精确 source SHA 与版本,build_source为release。从源码看,两个命令的 JSON 字段完全同构(version/commit/build_source,见 cmd/wkcli/version.go 与 cmd/wukongim/version.go),这个设计保证“两个同样错误的二进制无法通过”——交叉比对加上与快照身份比对,堵住了整体回退的错误构建。
公开包验证器的--verify-installed-cli门禁在隔离的无凭据容器中只安装经快照验证的下载件。除 help 命令外,它还执行:
bench validate;- 查询一个已知的合成离线用户;
- 在固定的 stopped-v2 fixture 上完成
migrate diagnose。
要求:非法输入必须失败、源字节必须保持不变、诊断不得创建目标;每条命令与每个容器都有界定时限。四套发行版必须都返回installed_cli_verified=true并带有逐客户端的功能回执。任何一项失败都使发布交付保持未完成,哪怕 Pages 已部署。签名环节与发布前的纯下载沙箱从不执行产品载荷——只有独立验收容器才会真正运行二进制。官方 Linux/macOS 归档则始终同时包含两个二进制。
若要不签名、不发布地重放该门禁,可从WuKongIM/packages的main派发native-package-cli-acceptance.yml,并把expected_control_sha设为其当前受保护 SHA。工作流会从已评审 control 推导 audit 与版本、校验不可变归档与公网身份,并保留 90 天回执。执行期间不得推进包main或运行竞争性发布。
4.3 包升级与重启的边界
两个容易混淆的事实需要在运维时明确:
- 仓库 bootstrap 密钥环有独立版本号,它不是服务器版本,两者不可互相推断;
- 包升级不会重启正在运行的服务器。从打包定义可以印证:.goreleaser.packages.yaml 声明 DEB/RPM 只携带 systemd 单元、sysusers 与 tmpfiles 配置及安装脚本,且单元以
ConditionPathExists=/etc/wukongim/wukongim.toml为启动前置条件——包本身不创建/etc/wukongim/wukongim.toml,也不 enable/start 单元。服务重启是 Linux 部署手册下的显式部署操作,不属于包升级副作用。
五、发布报告的最终记录与收尾
最终发布报告必须逐项记录:
- source tag 与 SHA;
- GitHub Release 链接;
- 已验证的镜像 digest;
- 文档部署结果;
- 原生包 publisher 运行;
- 不可变 audit Release;
- 公网精确版本验证结果。
任一阶段被阻断或失败,都要点名该阶段并让整个发布保持未完成状态。收尾动作:在任务分支的 tip 已在目标分支验证后,清理已合并的任务分支与干净的工作树。
六、关键工件与证据清单速查
| 交付物 | 发布器 / 位置 | 必须核对的身份证据 |
|---|---|---|
| 会话 QPS 门禁 | conversation-qps-gate.yml | tag→commit 一致、source SHA 输出、20 个 endpoint 结果、profile 哈希,保留 90 天 |
| Docker 镜像 | docker-image-publish.yml | 三仓库同一多平台 digest、release构建身份、SBOM/provenance |
| 二进制资产 | binary-release-publish.yml | 不可变数字 Release ID、完整资产集、SHA-256、provenance、未签名 DEB/RPM 摘要 |
| 文档 | docs-pages.yml | 精确版本头与 tag 相等的文档构建 |
| 原生包 | WuKongIM/packages的 audit/publish 工作流 | 数字 audit Release ID、control SHA、installed_cli_verified=true四发行版回执 |
| 版本段 | CHANGELOG.md + extract-release-notes.awk | 目标版本恰好一次、非空、格式合法 |
这套流程的共同设计语言是“身份绑定 + 失败关闭”:tag、source SHA、digest、数字 Release ID 与 audit 快照层层咬合,任何一环证据缺失或身份不一致都会使对应阶段保持未完成,而不是用重跑、替换或旁路来“修复”下游。对读者而言,掌握这一闭环后,判断一次 WuKongIM 发布是否真正完成,只需要逐项核对上表中的身份证据是否齐全。
- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
相关推荐
Pure Live 构建与发布实战指南:从质量门禁到签名交付的完整流水线
Pure Live 构建与发布实战指南:从质量门禁到签名交付的完整流水线 导读 Pure Live 是一个跨 Android / Windows / Linux
音视频直播移动开发openAUTOSAR 经典平台完整上手指南:一个仓库搞定 ECU 通信、诊断与存储
openAUTOSAR 经典平台完整上手指南:一个仓库搞定 ECU 通信、诊断与存储 openAUTOSAR 经典平台是一个从 Arctic Core 分叉出来
嵌入式OS驱动开发Peekaboo 发布全流程指南:CLI 归档、npm 包、签名 DMG 与 Sparkle 更新的发布清单
Peekaboo 发布全流程指南:CLI 归档、npm 包、签名 DMG 与 Sparkle 更新的发布清单 Peekaboo 的发布流程覆盖一条完整的 mac
GUI 自动化MCP 服务AI 应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考