补齐跨渠道产物隔离核对并把 dev-mac 缺陷钉到字节级
Project CI / AI game creator shell Rust crates (push) Failing after 1m11s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m59s
Project CI / AI game creator shell Rust lane 2/2 (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled

- check:agc-update-channel-manifests:新增「不同渠道更新包不得字节相同」断言(需 AGC_UPDATE_VERIFY_DOWNLOAD=1),并核对 Windows 安装包文件名带本渠道产品名
- 只读核对 dev-win/dev-mac/release-win/release-mac:dev-win 0.1.154、release-win 0.1.150、release-mac 0.1.139 身份与版本一致;dev-mac 0.1.142 与 release-mac 0.1.139 的更新包 sha256 相同,字节级证明 dev 分区放了 release 渠道的产物
- 渠道安装身份隔离里程碑补本轮核对(发布产物身份 + 跨渠道唯一性),真机并存仍待验收
- macOS 里程碑与 pitfalls、decision-log 记录字节级取证与新断言
This commit is contained in:
kdletters
2026-09-28 22:18:37 +08:00
parent c6ea0f0e34
commit 7da6de0b4e
5 changed files with 80 additions and 1 deletions
@@ -56,6 +56,8 @@ const WINDOWS_PLATFORM_KEY = 'windows-x86_64';
let failures = 0;
let skipped = 0;
/** 下载过的更新包摘要:用于「不同渠道不能共用同一份产物字节」这条隔离断言。 */
const downloadedArtifacts = [];
function check(name, ok, detail = '') {
if (!ok) failures += 1;
console.log(
@@ -261,6 +263,20 @@ async function verifyChannel(channel, tempDir) {
Boolean(platforms[WINDOWS_PLATFORM_KEY]),
`platforms=${platformKeys.join(',')}`,
);
// 渠道身份会写进产物文件名的产品名,这里先用清单里的地址核对(下载后再验签与摘要)。
const expectedIdentity = resolveChannelInstallIdentity(
channel.replace(/-win$/u, ''),
);
const artifactNames = platformKeys.map((key) =>
decodeURIComponent(new URL(String(platforms[key].url ?? '')).pathname),
);
check(
`${channel} 安装包文件名带本渠道产品名`,
artifactNames.every((name) =>
name.includes(expectedIdentity.productName),
),
`names=${artifactNames.map((name) => path.basename(name)).join(',')} expected=${expectedIdentity.productName}`,
);
}
if (channel === 'dev-win') {
@@ -315,6 +331,13 @@ async function verifyChannel(channel, tempDir) {
`downloaded=${size} head=${artifactHead.length}`,
);
const sha256 = await sha256Of(artifactPath);
downloadedArtifacts.push({
channel,
platformKey: key,
sha256,
size,
url,
});
if (channel === 'dev-win' && key === WINDOWS_PLATFORM_KEY) {
const bridgeJson = await (
await fetch(`${OSS_BASE_URL}/latest.json`)
@@ -359,6 +382,48 @@ try {
await rm(tempDir, { recursive: true, force: true });
}
// 渠道隔离:同一次核对里如果下载到多个渠道的更新包,它们不能是同一份字节——
// 不同渠道的 productName / identifier 不同,产物就不会相同(2026-09-28 的 dev-mac
// 事故正是「dev 分区里放的其实是 release 渠道那份包」,字节级完全相同)。
const channelNames = [
...new Set(
downloadedArtifacts.map((item) => item.channel.replace(/-(win|mac)$/u, '')),
),
];
if (!VERIFY_DOWNLOAD) {
skip(
'不同渠道的更新包互不相同(渠道隔离)',
'需要 AGC_UPDATE_VERIFY_DOWNLOAD=1 才能比对产物字节',
);
} else if (channelNames.length < 2) {
skip(
'不同渠道的更新包互不相同(渠道隔离)',
`本次只核对到 ${channelNames.length} 个渠道(${channelNames.join(',')});用 AGC_UPDATE_CHANNELS=dev-win,dev-mac,release-win,release-mac 可覆盖全量`,
);
} else {
const byHash = new Map();
for (const item of downloadedArtifacts) {
const bucket = byHash.get(item.sha256) ?? [];
bucket.push(item);
byHash.set(item.sha256, bucket);
}
const collisions = [...byHash.entries()].filter(
([, items]) =>
new Set(items.map((item) => item.channel.replace(/-(win|mac)$/u, '')))
.size > 1,
);
check(
'不同渠道的更新包互不相同(渠道隔离)',
collisions.length === 0,
collisions
.map(
([hash, items]) =>
`${hash.slice(0, 12)}: ${items.map((item) => `${item.channel}/${item.platformKey}`).join(' = ')}`,
)
.join(';'),
);
}
console.log(
failures === 0
? `\n全部通过${skipped > 0 ? `(${skipped} 项跳过)` : ''}`