fix(deploy): --backend-only/--all 不该连带跳过"改动范围"的计算
真机验证时发现:显式指定 --backend-only 会直接 return,没算 git diff, 于是 DIFF_KNOWN 一直是 false —— "无 migrations 改动就自动跳过备份"的判断随之失效, 一次只想重建后端的部署照样会跑 pg_dump + 传 OSS(生产上约 12 分钟)。 修复:拆成两步 - compute_changed_files:只回答"自上次成功部署以来改了什么"(CHANGED_FILES / DIFF_KNOWN / ENV_CHANGED / LAST_DEPLOYED_SHA),在任何分支下都先算; - detect_changed_services:只决定"重建哪一端",显式参数(--all/--backend-only/--web-only/ --reset-db)只覆盖重建范围,不覆盖改动范围。 - print_plan 改用 LAST_DEPLOYED_SHA,不再重复读状态文件。 补一条顺序守卫用例:compute_changed_files 必须在 detect_changed_services 之前调用。
This commit is contained in:
@@ -132,5 +132,12 @@ test(
|
||||
assert.ok(source.includes('DIFF_KNOWN'), '缺少"改动范围是否已知"的判定')
|
||||
assert.ok(source.includes('migrations_changed'), '缺少 migrations 改动判定')
|
||||
assert.ok(source.includes('--backup 可强制'), '缺少强制备份的提示')
|
||||
|
||||
// --backend-only/--all 这类参数只能覆盖"重建哪一端",不能顺手把"改了什么"一起跳过:
|
||||
// 否则 DIFF_KNOWN 永远是 false,无 schema 变更也会去跑 pg_dump + 传 OSS(生产 ~12 分钟)。
|
||||
const computeIndex = source.indexOf('compute_changed_files\n')
|
||||
const detectIndex = source.indexOf('detect_changed_services\n')
|
||||
assert.ok(computeIndex > 0 && detectIndex > 0, '找不到改动计算/重建判定的调用')
|
||||
assert.ok(computeIndex < detectIndex, '必须先算改动范围,再决定重建范围')
|
||||
},
|
||||
)
|
||||
|
||||
+55
-44
@@ -32,6 +32,8 @@ BUILD_WEB=false
|
||||
CHANGED_FILES=""
|
||||
CHANGE_REASON=""
|
||||
DIFF_KNOWN=false
|
||||
ENV_CHANGED=false
|
||||
LAST_DEPLOYED_SHA=""
|
||||
DEPLOY_STARTED_AT=${SECONDS}
|
||||
TIMING_LABELS=()
|
||||
TIMING_SECONDS=()
|
||||
@@ -205,64 +207,37 @@ write_deploy_state() {
|
||||
log "已记录部署状态:${DEPLOY_STATE_FILE}(commit=${head_sha:0:12})"
|
||||
}
|
||||
|
||||
# 决定这次要重建哪一端:--all/--backend-only/--web-only > .deploy-state + git diff > 保守兜底。
|
||||
detect_changed_services() {
|
||||
local head_sha last_sha env_hash last_env_hash services
|
||||
# 只回答"自上次成功部署以来改了什么",不决定重建范围。
|
||||
# 拆成两步的原因:--backend-only/--all 这类显式参数只该覆盖"重建哪一端",
|
||||
# 不该把"改动范围未知"一起带进来——否则会连"无迁移改动就跳过备份"的判断也一起退化成"必须备份"。
|
||||
compute_changed_files() {
|
||||
local head_sha last_sha env_hash last_env_hash
|
||||
|
||||
BUILD_BACKEND=false
|
||||
BUILD_WEB=false
|
||||
CHANGED_FILES=""
|
||||
CHANGE_REASON=""
|
||||
DIFF_KNOWN=false
|
||||
|
||||
if [[ "${FORCE_BACKEND}" == "true" || "${FORCE_WEB}" == "true" ]]; then
|
||||
[[ "${FORCE_BACKEND}" == "true" ]] && BUILD_BACKEND=true
|
||||
[[ "${FORCE_WEB}" == "true" ]] && BUILD_WEB=true
|
||||
CHANGE_REASON="命令行指定了 --backend-only/--web-only"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${FORCE_ALL}" == "true" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="命令行指定了 --all(强制全量重建)"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${RESET_DB}" == "true" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="--reset-db 需要整套服务重建"
|
||||
return
|
||||
fi
|
||||
ENV_CHANGED=false
|
||||
LAST_DEPLOYED_SHA=""
|
||||
|
||||
head_sha="$(git -C "${PROJECT_ROOT}" rev-parse HEAD 2>/dev/null || true)"
|
||||
last_sha="$(read_state_value commit)"
|
||||
|
||||
if [[ -z "${head_sha}" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="项目不是 git 仓库或读不到 HEAD,无法判断改动"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "${last_sha}" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="没有 ${DEPLOY_STATE_FILE##*/} 记录(首次使用按需重建),先全量重建一次"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! git -C "${PROJECT_ROOT}" cat-file -e "${last_sha}^{commit}" 2>/dev/null; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="上次部署的提交 ${last_sha:0:12} 已不在仓库中(force push?),全量重建"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! git -C "${PROJECT_ROOT}" merge-base --is-ancestor "${last_sha}" "${head_sha}" 2>/dev/null; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="上次部署的提交 ${last_sha:0:12} 不是 HEAD 的祖先(回滚/分支切换?),全量重建"
|
||||
return
|
||||
fi
|
||||
@@ -271,13 +246,55 @@ detect_changed_services() {
|
||||
# 那里关掉了 core.quotePath,中文路径(docs/xxx.md)不会被转义成 "\351..." 而匹配不上规则。
|
||||
CHANGED_FILES="$(bash "${PROJECT_ROOT}/deploy/lib/classify-changes.sh" --git-diff "${last_sha}" "${head_sha}" 2>/dev/null || true)"
|
||||
DIFF_KNOWN=true
|
||||
LAST_DEPLOYED_SHA="${last_sha}"
|
||||
|
||||
env_hash="$(file_sha256 "${ENV_FILE}")"
|
||||
last_env_hash="$(read_state_value env_sha256)"
|
||||
if [[ -n "${env_hash}" && -n "${last_env_hash}" && "${env_hash}" != "${last_env_hash}" ]]; then
|
||||
ENV_CHANGED=true
|
||||
CHANGE_REASON=".env 与上次部署时不一致(运行时环境/构建参数可能变化)"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "${CHANGED_FILES}" ]]; then
|
||||
CHANGE_REASON="自 ${last_sha:0:12} 以来没有代码改动"
|
||||
else
|
||||
CHANGE_REASON="自 ${last_sha:0:12} 以来改动 $(printf '%s\n' "${CHANGED_FILES}" | grep -c .) 个文件"
|
||||
fi
|
||||
}
|
||||
|
||||
# 只决定"重建哪一端":显式参数 > 改动范围 > 保守兜底。
|
||||
detect_changed_services() {
|
||||
local services
|
||||
|
||||
BUILD_BACKEND=false
|
||||
BUILD_WEB=false
|
||||
|
||||
if [[ "${FORCE_BACKEND}" == "true" || "${FORCE_WEB}" == "true" ]]; then
|
||||
[[ "${FORCE_BACKEND}" == "true" ]] && BUILD_BACKEND=true
|
||||
[[ "${FORCE_WEB}" == "true" ]] && BUILD_WEB=true
|
||||
CHANGE_REASON="${CHANGE_REASON};命令行指定了 --backend-only/--web-only"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${FORCE_ALL}" == "true" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="${CHANGE_REASON};命令行指定了 --all"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${RESET_DB}" == "true" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON="${CHANGE_REASON};--reset-db 需要整套服务重建"
|
||||
return
|
||||
fi
|
||||
|
||||
# 算不出改动范围、或 .env 变了:两端都重建(保守兜底)
|
||||
if [[ "${DIFF_KNOWN}" != "true" || "${ENV_CHANGED}" == "true" ]]; then
|
||||
BUILD_BACKEND=true
|
||||
BUILD_WEB=true
|
||||
CHANGE_REASON=".env 与上次部署时不一致(运行时环境/构建参数可能变化),两端全量重建"
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -288,12 +305,6 @@ detect_changed_services() {
|
||||
if [[ " ${services} " == *" web "* ]]; then
|
||||
BUILD_WEB=true
|
||||
fi
|
||||
|
||||
if [[ -z "${CHANGED_FILES}" ]]; then
|
||||
CHANGE_REASON="自 ${last_sha:0:12} 以来没有代码改动"
|
||||
else
|
||||
CHANGE_REASON="自 ${last_sha:0:12} 以来改动 $(printf '%s\n' "${CHANGED_FILES}" | grep -c . ) 个文件"
|
||||
fi
|
||||
}
|
||||
|
||||
migrations_changed() {
|
||||
@@ -302,12 +313,11 @@ migrations_changed() {
|
||||
}
|
||||
|
||||
print_plan() {
|
||||
local head_sha last_sha targets="(无)" skipped
|
||||
local head_sha targets="(无)" skipped
|
||||
head_sha="$(git -C "${PROJECT_ROOT}" rev-parse HEAD 2>/dev/null || true)"
|
||||
last_sha="$(read_state_value commit)"
|
||||
|
||||
log "部署计划:"
|
||||
printf ' 上次成功部署:%s\n' "${last_sha:-(无记录)}"
|
||||
printf ' 上次成功部署:%s\n' "${LAST_DEPLOYED_SHA:-(无记录)}"
|
||||
printf ' 本次 HEAD :%s\n' "${head_sha:-(非 git 仓库)}"
|
||||
printf ' 改动依据 :%s\n' "${CHANGE_REASON:-未判断}"
|
||||
|
||||
@@ -828,6 +838,7 @@ main() {
|
||||
ensure_data_dir
|
||||
ensure_disk_space
|
||||
|
||||
compute_changed_files
|
||||
detect_changed_services
|
||||
print_plan
|
||||
|
||||
|
||||
Reference in New Issue
Block a user