完善(08-09-deployment-contract-single-source-harness): 收敛部署合同并补失败路径

这个提交包含在:
2026-08-09 14:40:28 +08:00
父节点 099f58cf3b
当前提交 621934a35e
共修改 13 个文件,包含 648 行新增和 27 行删除
+44 -2
查看文件
@@ -287,6 +287,9 @@ const deploymentRefreshHelperContent = readFile(deploymentRefreshHelperPath);
const remotePreflightScriptContent = readFile(remotePreflightScriptPath);
const productionPreflightScriptContent = readFile(productionPreflightScriptPath);
const productionPreflightRemoteScriptContent = readFile(productionPreflightRemoteScriptPath);
const sourceProvenanceScriptContent = readFile(
path.join(rootDir, 'deploy/trialrun/check-source-provenance.mjs'),
);
const productionIdentityBootstrapScriptContent = readFile(productionIdentityBootstrapScriptPath);
const productionIdentityBootstrapRemoteScriptContent = readFile(productionIdentityBootstrapRemoteScriptPath);
const dockerfileContent = readFile(dockerfilePath);
@@ -453,6 +456,34 @@ for (const requiredFragment of [
errors.push(`install-warch3-ops-timer.sh 缺少活动部署环境绑定: ${requiredFragment}`);
}
}
for (const requiredFragment of [
'deriveCandidateBuildEnv',
'BUILD_SHA: normalized',
'VITE_BUILD_SHA: normalized.slice(0, 12)',
'buildEnv,',
]) {
if (!sourceProvenanceScriptContent.includes(requiredFragment)) {
errors.push(`check-source-provenance.mjs 缺少候选构建身份单一合同: ${requiredFragment}`);
}
}
for (const requiredFragment of [
'Object.entries(p.buildEnv ?? {})',
'declare -A SOURCE_BUILD_ENV=()',
'"${#SOURCE_BUILD_ENV[@]}" -eq 2',
'SOURCE_COMMIT="${SOURCE_BUILD_ENV[BUILD_SHA]}"',
'SOURCE_SHORT_COMMIT="${SOURCE_BUILD_ENV[VITE_BUILD_SHA]}"',
]) {
if (!deployScriptContent.includes(requiredFragment)) {
errors.push(`deploy.sh 未完整消费 provenance buildEnv: ${requiredFragment}`);
}
}
if (deployScriptContent.includes('p.shortCommit')
|| deployScriptContent.includes('p.buildEnv.BUILD_SHA')
|| deployScriptContent.includes('p.buildEnv.VITE_BUILD_SHA')
|| deployScriptContent.includes('${BUILD_SHA:0:12}')) {
errors.push('deploy.sh 不得绕过完整对象遍历单独读取候选构建字段');
}
if (productionIdentityBootstrapScriptContent.indexOf('if (identityOnly === "1")')
> productionIdentityBootstrapScriptContent.indexOf('const databaseIdentityHash = bootstrapDatabaseIdentityHash')) {
errors.push('production-identity-bootstrap.mjs 的 identity-only 停止点必须位于数据库身份读取前');
@@ -765,8 +796,9 @@ for (const requiredFragment of [
'collectMigrationManifest',
'EXPECTED_PENDING_MIGRATIONS',
'CANDIDATE_COMMIT_MISSING',
'BUILD_SHA=',
'VITE_BUILD_SHA=',
'deriveCandidateBuildEnv',
'Object.entries(candidateBuildEnv)',
'([key, value]) => `${key}=${shellQuote(value)}`',
'PRISMA_STATUS_OUTPUT_MISSING',
'PRISMA_STATUS_OUTPUT_UNREADABLE',
'sanitizePrismaStatus',
@@ -779,6 +811,16 @@ for (const requiredFragment of [
errors.push(`production-preflight.mjs 缺少生产目标/候选迁移合同: ${requiredFragment}`);
}
}
if (productionPreflightScriptContent.includes('candidateCommit.slice(0, 12)')) {
errors.push('production-preflight.mjs 不得自行派生候选短 SHA');
}
if (productionPreflightScriptContent.includes('CANDIDATE_BUILD_ENV_KEYS')) {
errors.push('production-preflight.mjs 不得以独立键数组重新定义候选构建环境对象');
}
if (productionPreflightScriptContent.lastIndexOf('assertRemotePreflightResult({')
> productionPreflightScriptContent.lastIndexOf('validatePrismaStatusText(rawStatus);')) {
errors.push('production-preflight.mjs 必须先传播远端失败,再校验 Prisma marker 内容');
}
for (const requiredFragment of [
'EXPECTED_PRODUCTION_ORIGIN_SHA256',