Skip to content
bitzorcas
中EN

Concept

发布管理

负责租户发布说明与全局客户端版本目录,并提供确定性灰度、强制升级下限和升级检查。

Last updated

负责租户发布说明与全局客户端版本目录,并提供确定性灰度、强制升级下限和升级检查。

一张图读懂主路径

客户端提交平台与版本

解析受支持的语义版本

选择已发布候选版本

应用稳定灰度哈希

返回可选或强制升级结论

珊瑚色节点表示本模块的核心决策或状态边界。

能力边界

  • 发布说明的草稿、已发布与归档生命周期
  • 客户端版本的草稿、已发布与弃用生命周期
  • 语义版本比较、稳定灰度与强制升级决策

模块明确不包含:ReleaseManagement 只发布元数据并给出升级决策;它不构建产物、不上传二进制、不运营应用商店,也不替代包分发与部署流水线。

代码地图

项目主要职责
BitzOrcas.Platform.ReleaseManagement.Contracts公开契约、端口、DTO 与事件
BitzOrcas.Platform.ReleaseManagement.Application命令、查询、处理器与应用策略
BitzOrcas.Platform.ReleaseManagement.Infrastructure持久化、连接器与框架适配器

源码位置: src/Platform/ReleaseManagement

核心用例

  • CreateReleaseNoteCommand
  • PublishReleaseNoteCommand
  • ListPublicReleaseNotesQuery
  • CreateAppVersionCommand
  • PublishAppVersionCommand
  • CheckUpgradeQuery

阅读用例时,先看请求契约和权限声明,再跟进处理器调用的聚合或端口,最后检查提交后的事件、缓存和审计。

关键模型与契约

关键类型阅读重点
ReleaseNoteDto租户发布说明投影
AppVersionDto全局客户端版本投影
IRolloutEvaluator确定性灰度决策扩展缝
UpgradeCheckResult客户端升级决策

用例边界示例

字段说明
代表性契约CheckUpgradeQuery
返回结果Result<UpgradeCheckResult>
审查重点解析当前版本后只选择已发布候选项,以稳定客户端标识绑定灰度,并把强制升级下限与可选灰度分别判断。

示例伪代码

CheckUpgradeQuery 伪代码
// ① 版本解析失败立即以稳定校验错误拒绝(Release.AppVersion.VersionInvalid)。
if (!SemanticVersion.TryParse(query.CurrentVersion, out var current))
return Result.Failure<UpgradeCheckResult>(ReleaseManagementErrors.AppVersionVersionInvalid);
// ② 候选按平台与渠道过滤且只取已发布版本,列表已按版本从高到低排序。
var published = await store.ListPublishedByPlatformAsync(
query.Platform, query.Channel, cancellationToken);
if (published.Count == 0) return NoUpdate;
var latest = published[0];
// ③ 强制升级下限与可选灰度是两个独立判断:MinForceUpdateVersion 命中则无视灰度。
var forceUpdate = !string.IsNullOrWhiteSpace(latest.MinForceUpdateVersion)
&& SemanticVersion.TryParse(latest.MinForceUpdateVersion, out var minRequired)
&& current.IsLowerThan(minRequired);
var rolloutHit = evaluator.IsHit(request.ActorKey, latest.RolloutPercentage);
// ④ 稳定 ActorKey 哈希让同一设备或用户始终落入同一灰度批次。
return forceUpdate || rolloutHit
? Result.Success(new UpgradeCheckResult(forceUpdate, latest.Version,
latest.BuildNumber, rolloutHit, latest.DownloadUrl, latest.ReleaseNoteKey))
: NoUpdate;

NoUpdate 不是类型上的静态工厂,而是 CheckUpgradeQueryHandler 内部保存的私有“无更新”成功结果(六个字段取中性值的 UpgradeCheckResult)。

集成关系

发布说明按租户隔离,AppVersionCatalogRecord 则是全局目录。升级检查使用稳定客户端标识做百分比灰度,返回版本元数据与 HTTPS 下载地址;产物完整性与托管仍由外部系统负责。

跨模块协作遵循以下方向:

  • 调用方依赖本模块公开 Contracts 或窄端口。
  • 状态变化通过版本化集成事件传播。
  • 具体数据库、消息、缓存、文件或厂商 SDK 留在 Infrastructure。
  • 组合根先注册失败关闭默认实现,再接入生产适配器。

安全、租户与隐私

管理端路由受 release 权限与默认关闭的 release.manage Feature 约束。公开发布说明与升级检查不会返回草稿。生产下载地址要求 HTTPS,本地或私网例外只用于受限开发环境。

模块保存租户数据时必须写入 TenantId,列表和详情使用同一授权规则。日志、事件和审计只保留诊断所需字段。

失败语义、幂等与可观测性

同一版本与客户端标识的灰度结果保持确定,不会在批次间来回跳变。版本解析接受带 v 前缀的三段版本与日期式版本,但拒绝 prerelease/build 后缀。

情况处理原则
校验、未找到、冲突或禁止返回类型化 Result/Error,并由统一映射生成 Problem Details
适配器或关键状态不可用安全或高价值操作失败关闭;只读降级必须显式标记
重复请求或重复事件使用稳定幂等键,数据库唯一约束作为最后防线
外部超时传播取消,记录脱敏诊断,仅对安全操作执行有界重试

测试矩阵

#必须覆盖建议层级
1语义版本允许与拒绝的格式单元 + 集成
2零、全量与稳定部分灰度集成/契约
3强制升级下限与弃用版本集成/契约
4租户发布说明与全局客户端版本边界集成/契约

测试还要固定一条通用红线:租户 A 的标识、缓存键、事件或查询条件不能让租户 B 读取或修改数据。

源码导航与变更检查

在 BitzOrcasVNext 仓库根目录运行:

Terminal window
# 列出公开类型,确认新增契约是否真的属于模块边界。
rg -n "^public (sealed |abstract |static |partial )*(record|class|interface|enum)" src/Platform/ReleaseManagement -g '*.cs'
# 检查跨层引用;调用方不应依赖另一个模块的 Infrastructure。
rg -n "ProjectReference|PackageReference" src/Platform/ReleaseManagement -g '*.csproj'
# 查找待补实现和省略式代码;预期没有命中。
rg -n "TODO|FIXME|// \.\.\.|省略" src/Platform/ReleaseManagement -g '*.cs'

扩展与发布检查

  1. 新能力是否由明确的 Contracts、权限和 Feature Key 表达?
  2. 持久化、连接器和 Provider 是否可以通过窄适配器替换?
  3. 生产组合是否仍命中 Null/Unavailable 默认实现?健康检查会不会误报绿色?
  4. 事务、事件、缓存失效、审计和后台任务是否有失败与重试证据?
  5. 中英文文档、图表、契约测试和运维手册是否随代码一起更新?

返回平台模块目录 · 查看模块依赖图 · 新增模块指南

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%