HarmonyOS 发布质量连载06:发布门禁与问题闭环【共创稿事节】
应用准备进入发布阶段时,常常同时存在几个看似很小的问题:多语言资源少了一个键,权限用途说明仍待补齐,签名文件引用需要人工确认,产物摘要也还没有入库。如果把它们散落在聊天记录和临时表格中,版本负责人很难判断哪些问题已经修复、哪些可以复核、哪些会继续阻止交付。ReleaseGuard的任务就是让这些分散信息汇聚为同一份版本快照和一套可追踪的质量门禁。

一、沿用已有发布快照,不重新开始
工程继续使用com.example.releaseguard、versionName=1.2.3、versionCode=1000203和product=default。从此前章节继承两个待核对构建产物,当前完成摘要的数量为0。配置模型检查已满足要求,状态为CONFIG_PASS;产物清单仍为MANIFEST_PENDING,权限隐私核对为PRIVACY_REVIEW,资源及多语言检查为RESOURCE_REVIEW,签名材料关联为SIGNING_REVIEW。因此总体决策是HOLD,不能用已经通过的配置项掩盖其他未关闭的问题。
从资源章节继承两项差异:英文资源缺少privacy_retention_notice,以及release_version的参数占位符不一致。本章把第一项作为可以完成闭环的样本,补齐资源后保留处理记录;第二项继续待复核,资源门禁仍保持RESOURCE_REVIEW。这项选择很关键:关闭一个问题并不会自动使同一门禁中的所有问题消失。
签名章节已经建立三种材料的引用模型:.p12为敏感密钥库引用,.cer为公开证书资料,.p7b为受控配置描述。本章处理的是引用与关联记录,不在问题列表中保存口令、私钥内容或完整敏感路径。质量门禁只接收最小化结果字段,避免将发布材料带入普通诊断数据。
二、将门禁与问题分开建模
“门禁”表示某个质量维度当前是否允许继续,“问题”表示导致门禁不能通过的具体原因。一个门禁可以关联多个问题,一项问题可以有独立负责人、状态、证据链接和最后复核记录。两者混在同一行会造成状态错乱:即使某一项已关闭,也可能还存在另一项未处理,因此门禁不能直接被标成通过。
ReleaseGuard把门禁固定为配置、产物、隐私、资源和签名五个维度。配置通过,其余四个维度暂未满足条件。问题记录用gate:resource:privacy_retention_notice这类业务主键,稳定地关联到具体检查条件。主键只用于业务追踪,不含用户信息,也不依赖界面排序号;状态变更不会修改主键。
const release = {
bundleName: 'com.example.releaseguard',
versionName: '1.2.3', versionCode: 1000203,
product: 'default', candidateArtifacts: 2, digested: 0
};
const gates = {
config: 'CONFIG_PASS', manifest: 'MANIFEST_PENDING',
privacy: 'PRIVACY_REVIEW', resource: 'RESOURCE_REVIEW',
signing: 'SIGNING_REVIEW'
};
const issues = [
{ id: 'resource:privacy_retention_notice', gate: 'resource', state: 'OPEN' },
{ id: 'resource:release_version', gate: 'resource', state: 'OPEN' },
{ id: 'privacy:purpose', gate: 'privacy', state: 'OPEN' },
{ id: 'signing:relation', gate: 'signing', state: 'OPEN' },
{ id: 'manifest:digest', gate: 'manifest', state: 'OPEN' }
];
这五条问题记录有清楚的来源,并非重复计算的系统告警。resource:privacy_retention_notice对应资源键缺失,resource:release_version对应占位符差异;隐私、签名和摘要各有一项待办。此时开放问题5项、关闭0项、待处理门禁4项。这组初始计数作为本章后续闭环的基准,可以解释每一次状态改变产生的影响。
三、证据链必须早于关闭操作
一个问题被标注为“已修复”,至少要回答三个问题:修改的对象是什么、怎样核对修改结果、谁复核了对应的规则。对于资源键缺失,修改对象是en_US资源中的privacy_retention_notice,复核依据是与基准资源的键名及参数集合比较。只有相同规则重新计算得到一致结论,才允许把问题变为CLOSED。仅填写一段“已经处理”的备注会使门禁失去可信度。
为了保持最小且可检验的结构,证据记录可以保存检查项主键、输入摘要、检查规则版本和结论,不必在文章之外引入失效的资料文件。示例中补入英文资源键后再执行集合比较;该键自身没有格式化参数,因此可以通过。另一个release_version存在占位符差异,仍留在开放清单中,不能因为同属资源门禁而一起关闭。
function placeholders(value) {
return [...String(value).matchAll(/%\d+\$[sd]/g)].map(v => v[0]).sort();
}
function sameTokens(left, right) {
return JSON.stringify(placeholders(left)) === JSON.stringify(placeholders(right));
}
const baseline = {
privacy_retention_notice: '数据保留策略已更新',
release_version: '当前版本:%1$s'
};
const english = {
privacy_retention_notice: 'Data retention policy updated',
release_version: 'Current version: %1$d'
};
function checkKey(key) {
return Object.hasOwn(english, key) &&
sameTokens(baseline[key], english[key]);
}
console.log(checkKey('privacy_retention_notice'), checkKey('release_version'));
// true false
这段逻辑处理的是规则结果,而不是直接修改HarmonyOS资源文件。项目中采用的语言目录、字符串资源与占位符格式仍应依据开发环境中的资源规范配置。对于语言资源,不能把显示文字不同当作错误;真正需要核对的是资源键是否齐全,以及参数数量、顺序和类型能否匹配调用方预期。

四、用状态机防止错误关闭
问题状态采用OPEN、IN_REVIEW、CLOSED三类。开发者补齐资源后,问题先从OPEN转为IN_REVIEW;当规则检查产生可核对结果后,才能进入CLOSED。关闭操作要有前置条件:对应规则确实通过、问题主键仍然存在、证据摘要非空、快照版本没有发生改变。若发布版本从1000203切换到另一版,旧证据不能自动用于新快照。
在业务层,状态流转比简单的布尔值更稳妥。它能够避免“刚修复、尚未复核”的中间状态被误认成完成,也能防止重复点击生成多条关闭记录。对于已经关闭的问题,重复提交相同证据保持幂等;若发现新差异,则建立新的复核记录,而不是删除旧历史。
function closeIssue(list, id, checkPassed, evidence) {
const item = list.find(row => row.id === id);
if (!item) throw new Error('缺少问题记录');
if (item.state === 'CLOSED') return item;
if (!checkPassed || !evidence || evidence.versionCode !== release.versionCode) {
throw new Error('复核条件尚未满足');
}
item.state = 'CLOSED';
item.evidence = { rule: evidence.rule, digest: evidence.digest };
return item;
}
closeIssue(issues, 'resource:privacy_retention_notice', true, {
versionCode: 1000203, rule: 'resource-key-and-token', digest: 'sha256:resource-key-ok'
});
const openCount = issues.filter(v => v.state !== 'CLOSED').length;
const closedCount = issues.length - openCount;
const holding = Object.values(gates).filter(v => !v.endsWith('PASS')).length;
console.log({ openCount, closedCount, holding, decision: 'HOLD' });
// { openCount: 4, closedCount: 1, holding: 4, decision: 'HOLD' }
代码中的摘要值是用于展示字段形态的业务输入;在交付流程里应以对应资源文本的实际内容计算摘要后保存。这里不修改产物清单,也不启动签名流程。门禁重算仍将RESOURCE_REVIEW保留,因为release_version还有差异;隐私、签名和产物门禁同样维持原状态。最终结果为开放问题4项、关闭问题1项、待处理门禁4项,总体决策继续HOLD。
五、让问题列表可以直接用于工程协作
界面按门禁分类展示问题,比按创建时间混排更容易定位责任。版本快照始终固定在顶部,资源问题下显示“缺失键已关闭、占位符待复核”,签名问题下显示“材料关联待复核”,产物问题下显示“摘要待补齐”。每项问题提供当前状态、规则名称和查看复核记录入口;不应将敏感路径及签名口令透传到列表页。

如果资源编辑与门禁重算几乎同时发生,检查结果必须绑定相同的版本标识。老快照返回的结果不能直接覆盖新快照中的问题状态;同一个问题连续提交时,也要保证关闭记录不会重复。页面选择“已关闭”过滤条件后,仍应保留该项的规则描述和处理依据,以便下一次版本迭代查阅。
六、把质量检查工具的输出接入同一机制
华为开发者测试服务覆盖静态检查、单元测试、应用与元服务体检,以及上架预检等不同环节。DevEco Testing的稳定性测试报告也提供问题列表和定位信息。这些资料可作为ReleaseGuard外部检查记录的来源,但需要与具体版本快照、检测对象和检查时间关联。工具结果发生变化时,应建立新的结果记录,由本地门禁规则决定是否触发复核,而不是只根据报告中出现“完成”二字更新状态。
官方参考资料:
七、发布门禁的价值在于能解释等待原因
本章关闭了privacy_retention_notice这一项资源缺失记录,但保留了另外四项开放问题;五个门禁仍是一项通过、四项待处理,总体决策为HOLD。这正是质量平台需要呈现的事实:完成了一个修复动作,流程确实向前推进,却没有因此提前宣布整个版本已经满足发布要求。下一篇进行版本回滚和兼容迁移时,可以直接沿用这些稳定问题主键与版本快照,避免历史问题丢失或跨版本串联。
更多推荐



所有评论(0)