完善 readiness、发布追溯与敏感治理(07-15-production-trust-closeout-cleanup)
这个提交包含在:
@@ -8,10 +8,21 @@ const envExamplePath = path.join(rootDir, 'deploy/trialrun/.env.example');
|
||||
const composePath = path.join(rootDir, 'deploy/trialrun/docker-compose.yml');
|
||||
|
||||
const requiredServices = ['server', 'worker', 'init'];
|
||||
const deploymentInjectedEnvKeys = new Set(['BUILD_SHA']);
|
||||
const allowedOverrides = {
|
||||
server: ['NODE_ENV'],
|
||||
worker: ['NODE_ENV', 'SERVE_CLIENT_DIST', 'JOBS_ENABLED'],
|
||||
init: ['NODE_ENV'],
|
||||
server: ['NODE_ENV', 'BUILD_SHA'],
|
||||
worker: ['NODE_ENV', 'BUILD_SHA', 'SERVE_CLIENT_DIST', 'JOBS_ENABLED'],
|
||||
init: ['NODE_ENV', 'BUILD_SHA'],
|
||||
};
|
||||
const requiredRuntimeOverrides = {
|
||||
server: ['BUILD_SHA'],
|
||||
worker: ['BUILD_SHA'],
|
||||
init: ['BUILD_SHA'],
|
||||
};
|
||||
const requiredBuildArgs = {
|
||||
server: ['BUILD_SHA', 'VITE_BUILD_SHA'],
|
||||
worker: ['BUILD_SHA', 'VITE_BUILD_SHA'],
|
||||
init: ['BUILD_SHA', 'VITE_BUILD_SHA'],
|
||||
};
|
||||
|
||||
function readFile(filePath) {
|
||||
@@ -117,10 +128,15 @@ const envExampleKeys = extractEnvExampleKeys(envExampleContent);
|
||||
const errors = [];
|
||||
|
||||
for (const key of configKeys) {
|
||||
if (!envExampleKeys.has(key)) {
|
||||
if (!deploymentInjectedEnvKeys.has(key) && !envExampleKeys.has(key)) {
|
||||
errors.push(`.env.example 缺少 ${key}`);
|
||||
}
|
||||
}
|
||||
for (const key of deploymentInjectedEnvKeys) {
|
||||
if (envExampleKeys.has(key)) {
|
||||
errors.push(`.env.example 不应持久化部署注入键 ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const serviceName of requiredServices) {
|
||||
const block = extractServiceBlock(composeContent, serviceName);
|
||||
@@ -138,10 +154,22 @@ for (const serviceName of requiredServices) {
|
||||
const illegalOverrides = environmentKeys.filter(
|
||||
(key) => !(allowedOverrides[serviceName] ?? []).includes(key),
|
||||
);
|
||||
const missingRuntimeOverrides = (requiredRuntimeOverrides[serviceName] ?? []).filter(
|
||||
(key) => !environmentKeys.includes(key),
|
||||
);
|
||||
const missingBuildArgs = (requiredBuildArgs[serviceName] ?? []).filter(
|
||||
(key) => !new RegExp(`^\\s{8}${key}:`, 'm').test(block),
|
||||
);
|
||||
|
||||
if (illegalOverrides.length) {
|
||||
errors.push(`服务 ${serviceName} 存在未授权 override: ${illegalOverrides.join(', ')}`);
|
||||
}
|
||||
if (missingRuntimeOverrides.length) {
|
||||
errors.push(`服务 ${serviceName} 缺少运行时 override: ${missingRuntimeOverrides.join(', ')}`);
|
||||
}
|
||||
if (missingBuildArgs.length) {
|
||||
errors.push(`服务 ${serviceName} 缺少构建参数: ${missingBuildArgs.join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
|
||||
在新工单中引用
屏蔽一个用户