feat(release): add optional remote schema preflight
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
## 发布前置条件
|
## 发布前置条件
|
||||||
|
|
||||||
1. 确认发布窗口、DB 备份和回滚负责人;迁移脚本包含 `ALTER TABLE`,不能在无备份状态执行。
|
1. 确认发布窗口、DB 备份和回滚负责人;迁移脚本包含 `ALTER TABLE`,不能在无备份状态执行。
|
||||||
2. 先执行 `scripts/release-preflight.sh` 的只读检查;生产静态资源、后端包和当前提交必须一致。
|
2. 先执行 `scripts/release-preflight.sh` 的只读检查;生产静态资源、后端包和当前提交必须一致。若要同时核对线上结构,追加 `RELEASE_VERIFY_REMOTE_SCHEMA=true`,该开关只读检查必需表,不执行迁移。
|
||||||
3. 确认迁移目标库、租户和字符集为 MySQL 8 / `utf8mb4`;脚本只允许在目标业务库执行。
|
3. 确认迁移目标库、租户和字符集为 MySQL 8 / `utf8mb4`;脚本只允许在目标业务库执行。
|
||||||
4. 生产组织同步凭据、AI 供应商留存/费用口径和正式试点窗口仍未闭合时,不要把迁移完成宣称为 BRD 验收完成。
|
4. 生产组织同步凭据、AI 供应商留存/费用口径和正式试点窗口仍未闭合时,不要把迁移完成宣称为 BRD 验收完成。
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ grep -q '/h5/' "$mobile_index" || fail "mobile H5 index does not contain the /h5
|
|||||||
if [[ "${RELEASE_VERIFY_REMOTE_BACKEND:-false}" == "true" && "${RELEASE_VERIFY_REMOTE_MATCH:-false}" != "true" ]]; then
|
if [[ "${RELEASE_VERIFY_REMOTE_BACKEND:-false}" == "true" && "${RELEASE_VERIFY_REMOTE_MATCH:-false}" != "true" ]]; then
|
||||||
fail "RELEASE_VERIFY_REMOTE_BACKEND=true requires RELEASE_VERIFY_REMOTE_MATCH=true"
|
fail "RELEASE_VERIFY_REMOTE_BACKEND=true requires RELEASE_VERIFY_REMOTE_MATCH=true"
|
||||||
fi
|
fi
|
||||||
|
if [[ "${RELEASE_VERIFY_REMOTE_SCHEMA:-false}" == "true" && "${RELEASE_VERIFY_REMOTE_MATCH:-false}" != "true" ]]; then
|
||||||
|
fail "RELEASE_VERIFY_REMOTE_SCHEMA=true requires RELEASE_VERIFY_REMOTE_MATCH=true"
|
||||||
|
fi
|
||||||
|
|
||||||
head_epoch="$(git show -s --format=%ct HEAD)"
|
head_epoch="$(git show -s --format=%ct HEAD)"
|
||||||
|
|
||||||
@@ -103,6 +106,47 @@ require_remote_business_success() {
|
|||||||
echo "$label=200 $url"
|
echo "$label=200 $url"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_remote_schema() {
|
||||||
|
local remote_ssh="${RELEASE_REMOTE_SSH:-YCWY}"
|
||||||
|
local remote_db="${RELEASE_REMOTE_DB_NAME:-ry-vue}"
|
||||||
|
[[ "$remote_db" =~ ^[A-Za-z0-9_-]+$ ]] || fail "remote database name is invalid: $remote_db"
|
||||||
|
|
||||||
|
local missing
|
||||||
|
missing="$(ssh -o BatchMode=yes -o ConnectTimeout=10 "$remote_ssh" bash -s -- "$remote_db" <<'REMOTE'
|
||||||
|
set -euo pipefail
|
||||||
|
db="$1"
|
||||||
|
mysql --batch --skip-column-names --connect-timeout=5 "$db" <<'SQL'
|
||||||
|
SELECT required.table_name
|
||||||
|
FROM (
|
||||||
|
SELECT 'aihr_prompt_template' AS table_name
|
||||||
|
UNION ALL SELECT 'aihr_practice_scenario'
|
||||||
|
UNION ALL SELECT 'aihr_practice_rubric'
|
||||||
|
UNION ALL SELECT 'aihr_practice_rubric_dimension'
|
||||||
|
UNION ALL SELECT 'aihr_practice_audio'
|
||||||
|
UNION ALL SELECT 'aihr_practice_audio_upload'
|
||||||
|
UNION ALL SELECT 'aihr_practice_calibration'
|
||||||
|
UNION ALL SELECT 'aihr_knowledge_gap'
|
||||||
|
UNION ALL SELECT 'aihr_knowledge_answer_feedback'
|
||||||
|
UNION ALL SELECT 'aihr_candidate_material'
|
||||||
|
UNION ALL SELECT 'aihr_interview_result'
|
||||||
|
UNION ALL SELECT 'aihr_candidate_employee_link'
|
||||||
|
UNION ALL SELECT 'aihr_position_responsibility'
|
||||||
|
UNION ALL SELECT 'aihr_sop_applicability'
|
||||||
|
UNION ALL SELECT 'aihr_onboard_task'
|
||||||
|
UNION ALL SELECT 'aihr_qualification_gate'
|
||||||
|
) required
|
||||||
|
LEFT JOIN information_schema.tables actual
|
||||||
|
ON actual.table_schema = DATABASE() AND actual.table_name = required.table_name
|
||||||
|
WHERE actual.table_name IS NULL
|
||||||
|
ORDER BY required.table_name;
|
||||||
|
SQL
|
||||||
|
REMOTE
|
||||||
|
)" || fail "remote schema check failed: $remote_ssh:$remote_db"
|
||||||
|
|
||||||
|
[[ -z "$missing" ]] || fail "remote schema missing required tables: $(printf '%s' "$missing" | tr '\n' ', ' | sed 's/, $//')"
|
||||||
|
echo "remote_schema=16/16 $remote_ssh:$remote_db"
|
||||||
|
}
|
||||||
|
|
||||||
changed_files="$(git status --porcelain)"
|
changed_files="$(git status --porcelain)"
|
||||||
[[ -z "$changed_files" ]] || fail "worktree has uncommitted changes; commit the release batch before publishing"
|
[[ -z "$changed_files" ]] || fail "worktree has uncommitted changes; commit the release batch before publishing"
|
||||||
|
|
||||||
@@ -124,6 +168,10 @@ if [[ -n "${RELEASE_REMOTE_URL:-}" ]]; then
|
|||||||
require_remote_business_success "remote_tenant_list" "$remote/prod-api/auth/tenant/list"
|
require_remote_business_success "remote_tenant_list" "$remote/prod-api/auth/tenant/list"
|
||||||
require_remote_business_success "remote_mobile_home" "$remote/prod-api/api/aihr/mobile/home/user"
|
require_remote_business_success "remote_mobile_home" "$remote/prod-api/api/aihr/mobile/home/user"
|
||||||
|
|
||||||
|
if [[ "${RELEASE_VERIFY_REMOTE_SCHEMA:-false}" == "true" ]]; then
|
||||||
|
require_remote_schema
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${RELEASE_VERIFY_REMOTE_MATCH:-false}" == "true" ]]; then
|
if [[ "${RELEASE_VERIFY_REMOTE_MATCH:-false}" == "true" ]]; then
|
||||||
remote_frontend_asset="$(curl -fsS --max-time 15 "$remote/" | sed -nE 's/.*src="(\/assets\/[^" ]+\.js)".*/\1/p' | head -n 1)"
|
remote_frontend_asset="$(curl -fsS --max-time 15 "$remote/" | sed -nE 's/.*src="(\/assets\/[^" ]+\.js)".*/\1/p' | head -n 1)"
|
||||||
remote_mobile_asset="$(curl -fsS --max-time 15 "$remote/h5/" | sed -nE 's/.*src="(\/h5\/assets\/[^" ]+\.js)".*/\1/p' | head -n 1)"
|
remote_mobile_asset="$(curl -fsS --max-time 15 "$remote/h5/" | sed -nE 's/.*src="(\/h5\/assets\/[^" ]+\.js)".*/\1/p' | head -n 1)"
|
||||||
|
|||||||
Reference in New Issue
Block a user