修正(08-08-production-deployment-execution): 先验生产公网身份再冻结目录
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-08-08 19:36:32 +08:00
父节点 eb76de7c98
当前提交 bf2631c0d4
共修改 8 个文件,包含 151 行新增和 48 行删除
@@ -60,14 +60,10 @@ function parseHistoricalDefault(source, key) {
export function parseHistoricalDeploymentIdentity(targetSource, projectSource) {
const deployServer = parseHistoricalDefault(targetSource, "DEPLOY_SERVER");
const remoteDir = parseHistoricalDefault(targetSource, "REMOTE_DIR");
const projectRemoteDir = parseHistoricalDefault(projectSource, "REMOTE_DIR");
const composeProjectName = parseHistoricalDefault(projectSource, "COMPOSE_PROJECT_NAME");
if (projectRemoteDir !== remoteDir) fail("HISTORICAL_REMOTE_DIR_DIVERGED");
if (!SAFE_SSH_TARGET_PATTERN.test(deployServer)) fail("HISTORICAL_DEPLOY_SERVER_INVALID");
if (!SAFE_ABSOLUTE_PATH_PATTERN.test(remoteDir)) fail("HISTORICAL_REMOTE_DIR_INVALID");
if (!SAFE_PROJECT_PATTERN.test(composeProjectName)) fail("HISTORICAL_COMPOSE_PROJECT_INVALID");
return { deployServer, remoteDir, composeProjectName };
return { deployServer, composeProjectName };
}
export function parseExpectedProductionOrigin(runbook) {
@@ -145,9 +141,8 @@ export function parseDeploymentContract(raw) {
return contract;
}
export function assertExactHistoricalContract(identity, contract) {
if (contract.REMOTE_DIR !== identity.remoteDir) fail("SYSTEMD_REMOTE_DIR_MISMATCH");
if (contract.REMOTE_ENV_FILE !== `${identity.remoteDir}/deploy/trialrun/.env`) {
export function assertContractForOriginVerification(identity, contract) {
if (contract.REMOTE_ENV_FILE !== `${contract.REMOTE_DIR}/deploy/trialrun/.env`) {
fail("SYSTEMD_REMOTE_ENV_FILE_MISMATCH");
}
if (contract.COMPOSE_FILE !== "deploy/trialrun/docker-compose.yml") {
@@ -166,8 +161,9 @@ function shellQuote(value) {
return `'${String(value).replaceAll("'", "'\\''")}'`;
}
function bootstrapDatabaseIdentityHash(identity, contract, expectedOrigin) {
function runRemoteIdentityBootstrap(mode, identity, contract, expectedOrigin) {
const remoteCommand = [
`IDENTITY_BOOTSTRAP_MODE=${shellQuote(mode)}`,
`REMOTE_DIR=${shellQuote(contract.REMOTE_DIR)}`,
`REMOTE_ENV_FILE=${shellQuote(contract.REMOTE_ENV_FILE)}`,
`COMPOSE_FILE=${shellQuote(contract.COMPOSE_FILE)}`,
@@ -181,7 +177,18 @@ function bootstrapDatabaseIdentityHash(identity, contract, expectedOrigin) {
const code = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.match(/code=([A-Z0-9_]+)/u)?.[1];
fail(code || "REMOTE_IDENTITY_BOOTSTRAP_FAILED");
}
const output = String(result.stdout ?? "").trim();
return String(result.stdout ?? "").trim();
}
function verifyOriginIdentity(identity, contract, expectedOrigin) {
const output = runRemoteIdentityBootstrap("origin", identity, contract, expectedOrigin);
if (output !== "[production-identity-bootstrap][PASS] origin_identity") {
fail("REMOTE_ORIGIN_IDENTITY_PAYLOAD_INVALID");
}
}
function bootstrapDatabaseIdentityHash(identity, contract, expectedOrigin) {
const output = runRemoteIdentityBootstrap("database", identity, contract, expectedOrigin);
const match = output.match(/^\[production-identity-bootstrap\]\[DB_SHA256\] ([0-9a-f]{64})$/u);
if (!match) fail("REMOTE_DB_IDENTITY_PAYLOAD_INVALID");
return match[1];
@@ -189,6 +196,8 @@ function bootstrapDatabaseIdentityHash(identity, contract, expectedOrigin) {
function main() {
try {
const identityOnly = process.env.PRODUCTION_IDENTITY_ONLY ?? "0";
if (!["0", "1"].includes(identityOnly)) fail("PRODUCTION_IDENTITY_ONLY_INVALID");
const historicalTargetScript = requiredCommandOutput(
"git",
["show", `${HISTORICAL_TARGET_COMMIT}:${DEPLOY_SCRIPT_AT_COMMIT}`],
@@ -208,7 +217,14 @@ function main() {
"SYSTEMD_CONTRACT_UNAVAILABLE",
);
const contract = parseDeploymentContract(contractRaw);
assertExactHistoricalContract(identity, contract);
assertContractForOriginVerification(identity, contract);
verifyOriginIdentity(identity, contract, expectedOrigin);
const expectedRemoteDir = contract.REMOTE_DIR;
if (identityOnly === "1") {
console.log("[production-identity-bootstrap][PASS] origin_verified_remote_dir_baseline=systemd_contract");
return;
}
const databaseIdentityHash = bootstrapDatabaseIdentityHash(identity, contract, expectedOrigin);
console.log("[production-identity-bootstrap][PASS] exact_identity_group");
@@ -220,7 +236,7 @@ function main() {
DEPLOY_SERVER: identity.deployServer,
DEPLOY_REFRESH_SERVER: refreshTarget,
EXPECTED_DEPLOY_SERVER: identity.deployServer,
EXPECTED_REMOTE_DIR: identity.remoteDir,
EXPECTED_REMOTE_DIR: expectedRemoteDir,
EXPECTED_COMPOSE_PROJECT_NAME: identity.composeProjectName,
EXPECTED_PRODUCTION_ORIGIN: expectedOrigin,
EXPECTED_PRODUCTION_DB_NAME_SHA256: databaseIdentityHash,