加固既有生产部署流程(07-27-yang-jun-reimbursement-readiness)

这个提交包含在:
2026-08-01 18:25:20 +08:00
父节点 5dac336fbf
当前提交 07de198b51
共修改 15 个文件,包含 375 行新增和 34 行删除
+46
查看文件
@@ -16,6 +16,9 @@ const checklistPath = path.join(rootDir, 'deploy/trialrun/checklist.md');
const deployScriptPath = path.resolve(
process.env.ENV_CONTRACT_DEPLOY_SCRIPT_PATH || path.join(rootDir, 'deploy/trialrun/deploy.sh'),
);
const deployExistingScriptPath = path.join(rootDir, 'deploy/trialrun/deploy-existing.sh');
const remotePreflightScriptPath = path.join(rootDir, 'deploy/trialrun/preflight-remote.sh');
const dockerfilePath = path.join(rootDir, 'deploy/trialrun/Dockerfile');
const timerScriptPath = path.resolve(
process.env.ENV_CONTRACT_TIMER_SCRIPT_PATH
|| path.join(rootDir, 'deploy/trialrun/install-warch3-ops-timer.sh'),
@@ -155,6 +158,9 @@ const composeContent = readFile(composePath);
const runbookContent = readFile(runbookPath);
const checklistContent = readFile(checklistPath);
const deployScriptContent = readFile(deployScriptPath);
const deployExistingScriptContent = readFile(deployExistingScriptPath);
const remotePreflightScriptContent = readFile(remotePreflightScriptPath);
const dockerfileContent = readFile(dockerfilePath);
const timerScriptContent = readFile(timerScriptPath);
const automaticBackupTimerScriptContent = readFile(automaticBackupTimerScriptPath);
const offhostReceiverInstallerContent = readFile(offhostReceiverInstallerPath);
@@ -439,12 +445,52 @@ for (const requiredFragment of [
'DEPLOY_DATA_MODE" != "existing"',
'DEPLOY_DATA_MODE" != "initialize"',
'"$POSTGRES_DATA_DIR/PG_VERSION"',
'>>> 3. 同步前只读校验远端部署合同',
'REMOTE_PREFLIGHT_SCRIPT="deploy/trialrun/preflight-remote.sh"',
]) {
if (!deployScriptContent.includes(requiredFragment)) {
errors.push(`deploy.sh 缺少正式部署数据目录护栏: ${requiredFragment}`);
}
}
if (deployScriptContent.indexOf('>>> 3. 同步前只读校验远端部署合同')
> deployScriptContent.indexOf('rsync -az --delete')) {
errors.push('deploy.sh 必须在 rsync 前执行远端只读 preflight');
}
for (const requiredFragment of [
'systemctl show',
'DEPLOY_DATA_MODE=existing',
'SYNC_ENV=0',
'路径与标识不回显',
]) {
if (!deployExistingScriptContent.includes(requiredFragment)) {
errors.push(`deploy-existing.sh 缺少既有部署合同: ${requiredFragment}`);
}
}
for (const requiredFragment of [
'REMOTE_DIR 是现存仓库根目录',
'SYNC_ENV=0 要求同步前已有普通远端 .env 文件',
'"$POSTGRES_DATA_DIR/PG_VERSION"',
]) {
if (!remotePreflightScriptContent.includes(requiredFragment)) {
errors.push(`preflight-remote.sh 缺少同步前护栏: ${requiredFragment}`);
}
}
for (const [earlier, later] of [
['RUN apk add --no-cache bash curl', 'ARG VITE_BUILD_SHA'],
['RUN cd client && npm ci', 'ARG VITE_BUILD_SHA'],
['RUN cd server && npm ci', 'ARG BUILD_SHA'],
]) {
if (dockerfileContent.indexOf(earlier) === -1
|| dockerfileContent.indexOf(later) === -1
|| dockerfileContent.indexOf(earlier) > dockerfileContent.indexOf(later)) {
errors.push(`Dockerfile 缓存顺序无效: ${earlier} 必须早于 ${later}`);
}
}
for (const { filePath, content } of nginxContents) {
const relativePath = path.relative(rootDir, filePath);
if (content.includes('$proxy_add_x_forwarded_for')) {