修复(08-08-production-deployment-execution): 校验候选 Compose 构建标识
这个提交包含在:
@@ -15,7 +15,8 @@ pass() {
|
||||
|
||||
for key in REMOTE_DIR REMOTE_ENV_FILE COMPOSE_FILE COMPOSE_PROJECT_NAME \
|
||||
POSTGRES_DATA_DIR STORAGE_HOST_DIR EXPECTED_PRODUCTION_ORIGIN_SHA256 \
|
||||
EXPECTED_PRODUCTION_DB_NAME_SHA256 CANDIDATE_MIGRATIONS_CSV \
|
||||
EXPECTED_PRODUCTION_DB_NAME_SHA256 BUILD_SHA VITE_BUILD_SHA \
|
||||
CANDIDATE_MIGRATIONS_CSV \
|
||||
EXPECTED_PENDING_MIGRATIONS_CSV; do
|
||||
[[ -n "${!key:-}" || "$key" == "EXPECTED_PENDING_MIGRATIONS_CSV" ]] \
|
||||
|| fail "${key}_MISSING"
|
||||
@@ -25,6 +26,12 @@ done
|
||||
|| fail "PROD_TARGET_ORIGIN_HASH_INVALID"
|
||||
[[ "$EXPECTED_PRODUCTION_DB_NAME_SHA256" =~ ^[0-9a-f]{64}$ ]] \
|
||||
|| fail "PROD_TARGET_DB_HASH_INVALID"
|
||||
[[ "$BUILD_SHA" =~ ^[0-9a-f]{40,64}$ ]] \
|
||||
|| fail "PROD_TARGET_BUILD_SHA_INVALID"
|
||||
[[ "$VITE_BUILD_SHA" =~ ^[0-9a-f]{12}$ ]] \
|
||||
|| fail "PROD_TARGET_VITE_BUILD_SHA_INVALID"
|
||||
[[ "${BUILD_SHA:0:12}" == "$VITE_BUILD_SHA" ]] \
|
||||
|| fail "PROD_TARGET_BUILD_SHA_MISMATCH"
|
||||
|
||||
cd "$REMOTE_DIR"
|
||||
[[ -f "$REMOTE_ENV_FILE" && ! -L "$REMOTE_ENV_FILE" && -r "$REMOTE_ENV_FILE" ]] \
|
||||
|
||||
@@ -163,16 +163,6 @@ export function validateExactProductionIdentity({
|
||||
assertExactIdentity("COMPOSE_PROJECT_NAME", composeProjectName, expectedComposeProjectName);
|
||||
}
|
||||
|
||||
function gitText(args) {
|
||||
const result = spawnSync("git", args, {
|
||||
cwd: ROOT_DIR,
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
if (result.status !== 0) fail("CANDIDATE_COMMIT_UNAVAILABLE");
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
function reportRef(reportDir) {
|
||||
const relative = path.relative(ROOT_DIR, reportDir).replaceAll(path.sep, "/");
|
||||
return relative && !relative.startsWith("..") ? relative : "controlled-production-preflight-report";
|
||||
@@ -283,10 +273,10 @@ function main() {
|
||||
expectedComposeProjectName,
|
||||
});
|
||||
|
||||
const candidateCommit = String(
|
||||
process.env.CANDIDATE_COMMIT ?? gitText(["rev-parse", "--verify", "HEAD"]),
|
||||
).trim();
|
||||
if (process.env.CANDIDATE_COMMIT == null) fail("CANDIDATE_COMMIT_MISSING");
|
||||
const candidateCommit = String(process.env.CANDIDATE_COMMIT).trim();
|
||||
if (!/^[0-9a-f]{40,64}$/iu.test(candidateCommit)) fail("CANDIDATE_COMMIT_INVALID");
|
||||
const candidateShortCommit = candidateCommit.slice(0, 12);
|
||||
const candidateManifest = collectMigrationManifest(ROOT_DIR, candidateCommit);
|
||||
const candidateSet = new Set(candidateManifest);
|
||||
if (expectedPending.some((migration) => !candidateSet.has(migration))) {
|
||||
@@ -315,6 +305,8 @@ function main() {
|
||||
`STORAGE_HOST_DIR=${shellQuote(storageHostDir)}`,
|
||||
`EXPECTED_PRODUCTION_ORIGIN_SHA256=${shellQuote(sha256Text(expectedOrigin))}`,
|
||||
`EXPECTED_PRODUCTION_DB_NAME_SHA256=${shellQuote(expectedDbNameHash)}`,
|
||||
`BUILD_SHA=${shellQuote(candidateCommit)}`,
|
||||
`VITE_BUILD_SHA=${shellQuote(candidateShortCommit)}`,
|
||||
`CANDIDATE_MIGRATIONS_CSV=${shellQuote(candidateManifest.join(","))}`,
|
||||
`EXPECTED_PENDING_MIGRATIONS_CSV=${shellQuote(expectedPending.join(","))}`,
|
||||
"bash -s",
|
||||
|
||||
@@ -751,6 +751,9 @@ for (const requiredFragment of [
|
||||
'validateProductionDbName',
|
||||
'collectMigrationManifest',
|
||||
'EXPECTED_PENDING_MIGRATIONS',
|
||||
'CANDIDATE_COMMIT_MISSING',
|
||||
'BUILD_SHA=',
|
||||
'VITE_BUILD_SHA=',
|
||||
'PRISMA_STATUS_OUTPUT_MISSING',
|
||||
'PRISMA_STATUS_OUTPUT_UNREADABLE',
|
||||
'sanitizePrismaStatus',
|
||||
@@ -767,6 +770,9 @@ for (const requiredFragment of [
|
||||
for (const requiredFragment of [
|
||||
'EXPECTED_PRODUCTION_ORIGIN_SHA256',
|
||||
'EXPECTED_PRODUCTION_DB_NAME_SHA256',
|
||||
'PROD_TARGET_BUILD_SHA_INVALID',
|
||||
'PROD_TARGET_VITE_BUILD_SHA_INVALID',
|
||||
'PROD_TARGET_BUILD_SHA_MISMATCH',
|
||||
'PRISMA_STATUS_BEGIN',
|
||||
'FROM "_prisma_migrations"',
|
||||
'logged_failure',
|
||||
|
||||
在新工单中引用
屏蔽一个用户