From 84207b4d5d09d8f60d4b804a2cab1488e21af1d5 Mon Sep 17 00:00:00 2001 From: "agent.develop" Date: Wed, 30 Sep 2026 19:49:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(build):=20=E6=8E=A5=E5=85=A5=E5=9F=BA?= =?UTF-8?q?=E5=BA=A7=20DDL=20=E5=BB=BA=E8=A1=A8=E9=93=BE=EF=BC=88Bug=204Sx?= =?UTF-8?q?qQAulkH9eAzEys=5Fh-e=20=E6=A0=B9=E5=9B=A0=E9=97=AD=E7=8E=AF=20/?= =?UTF-8?q?=20QC=20=E6=9C=AA=E8=BF=87=E9=A1=B9=20#1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:build.sh 建表段只覆盖 scripts/ddl/pbls_tables.sql(32 张 pbl_* 手写表) 与 modules/pbl_*/models(6 张治理/模板域表,第 10a 步),已交付的 scripts/gen_base_ddl.py 与 scripts/ddl/base_tables.sql(12 张基座表含 users) 在 build.sh 中零引用 → 重新部署 users 表仍缺失 → POST /main/rbac/user/up_login.dspy ERROR 1146 Table 'pbl.users' doesn't exist → ahserver 兜底 500,会话 cookie 不下发。 改动(仅 build.sh,83 行纯新增,0 删除): 1) 变量声明段新增 BASE_GEN / BASE_DDL_FILE / BASE_ALIAS_MAP / BASE_PKGS_ROOT (= /pkgs,WS_DIR 由既有三段式探测解析, 不硬编码路径;不存在时回退 gen_base_ddl.py 自带三段式探测并逐条回显候选)。 2) 新增第 10a-base 步(位于 10a 模块链之后、10b 运行目录之前): - python3 scripts/gen_base_ddl.py --out/--alias-map 从 models 单一真源 重新生成 base_tables.sql + base_table_alias_map.json(脚本自带 「表数<8 或 users 缺失即 die」门禁,不改其生成逻辑); - 产物存在性 + grep 复核表数>=8 与 users 在场; - mysql --protocol=TCP < base_tables.sql,连接参数全部取既有 ////(env 事实源派生, 零硬编码); - information_schema 逐张点名核验 12 张(appbase 4 + rbac 8),不达标 die 并枚举缺失表名;users 单独点名 + 登录链 4 列 (username/login_fail_count/last_login_fail/last_login)终态核验; - 打印 SELF_CHECK base_tables: PASS tables=N/12 users=present login_cols=4/4。 3) 幂等:base_tables.sql 全部 CREATE TABLE IF NOT EXISTS,重复执行零副作用。 4) 口径边界:未改动第 10 步 32 张手写表门禁、第 10a 步 6 张模块链门禁、 第 733 行 38 关键表终态门禁;未改 gen_base_ddl.py 与 pkgs/ 下基座包。 本地实测(真实回显,非模拟): [gen_base_ddl] resolved BASE_PKGS_ROOT=/d/pipeline/pipeline-app/pkgs [gen_base_ddl] SELF_CHECK base_ddl: PASS tables=12 users=present [10a-base] 生成校验通过: base_tables.sql 含 12 张表,users=present [10a-base] 基座表点名核验: 12/12(appbase 4 + rbac 8) [10a-base] SELF_CHECK base_tables: PASS tables=12/12 users=present login_cols=4/4 幂等复跑第二次同结果,退出码 0;bash -n build.sh 通过。 --- build.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/build.sh b/build.sh index a4442bf..2161794 100755 --- a/build.sh +++ b/build.sh @@ -46,6 +46,15 @@ RESOLVED_WS_DIR="$(_ws_probe || true)" WS_DIR="${RESOLVED_WS_DIR}" ENV_FILE="${WS_DIR}/projects/pbls/env/test.json" DDL_FILE="${APP_DIR}/scripts/ddl/pbls_tables.sql" +# [Bug 4SxqQAulkH9eAzEys_h-e 根因闭环] 基座模块(appbase/rbac)models 链 DDL —— +# 单一真源 = ${BASE_PKGS_ROOT}/{appbase,rbac}/models/*.json,由 gen_base_ddl.py 生成, +# 禁止手工编辑 base_tables.sql。第 10a-base 步执行。 +BASE_GEN="${APP_DIR}/scripts/gen_base_ddl.py" +BASE_DDL_FILE="${APP_DIR}/scripts/ddl/base_tables.sql" +BASE_ALIAS_MAP="${APP_DIR}/scripts/ddl/base_table_alias_map.json" +# 基座包根:显式取 WS_DIR/pkgs(build.sh 已三段式解析 WS_DIR),gen_base_ddl.py +# 内部再做存在性校验并打印解析出的绝对路径(web-application-spec 铁律 5)。 +BASE_PKGS_ROOT="${PBL_BASE_PKGS_ROOT:-${WS_DIR}/pkgs}" VENV_DIR="${APP_DIR}/venv" PY="${VENV_DIR}/bin/python" @@ -371,6 +380,80 @@ MOD_TABLES="$(mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" [ "${MOD_TABLES}" = "6" ] || die "模块 models 链建表应为 6 张,实际 ${MOD_TABLES}" log "[10a] 模块 models 链建表完成: 6/6(governance 4 含 privacy_consent + template 2)" +# ---- 10a-base. 基座模块(appbase / rbac)models 链建表 ---- +# [Bug 4SxqQAulkH9eAzEys_h-e 根因闭环 / QC 未过项 #1] +# 症状链:POST /main/rbac/user/up_login.dspy → 500 "Server got itself in trouble" +# ← ERROR 1146 (42S02) Table 'pbl.users' doesn't exist +# ← build.sh 建表段只覆盖 scripts/ddl/pbls_tables.sql(32 张 pbl_* 手写表) +# 与 modules/pbl_*/models(6 张治理/模板域表,第 10a 步), +# 基座 appbase(appcodes/appcodes_kv/params/svgicon)与 +# rbac(users/role/permission/rolepermission/userrole/organization/orgtypes/audit_log) +# 的 models 链从未被建表。 +# 本段职责:① 从 models 单一真源重新生成 base_tables.sql + alias map(脚本自带 +# 「表数<8 或 users 缺失即 die」门禁);② 用 env 派生的连接参数执行建表; +# ③ information_schema 逐张点名自校验(防计数虚高);④ 全部 IF NOT EXISTS,幂等。 +# 口径边界:本段只新增 12 张基座表,不触碰第 10 步 32 张手写表门禁、 +# 第 10a 步 6 张模块链表门禁,也不改动后续 38 关键表终态门禁的口径。 +[ -f "${BASE_GEN}" ] || die "缺少基座 DDL 生成器 ${BASE_GEN}" + +# gen_base_ddl.py 只用标准库;优先用 venv 解释器(与 10a 一致),venv 不在位时回退 python3 +BASE_GEN_PY="${PY}" +[ -x "${BASE_GEN_PY}" ] || BASE_GEN_PY="python3" + +# 把 WS_DIR 交给生成器(其候选链第 2 项 = ${WS_DIR}/pkgs);BASE_PKGS_ROOT 仅在 +# 真实存在时导出,否则留给生成器自带的三段式探测(会逐条打印候选与存在性,不静默)。 +export WS_DIR +if [ -d "${BASE_PKGS_ROOT}" ]; then + export BASE_PKGS_ROOT + log "[10a-base] BASE_PKGS_ROOT=${BASE_PKGS_ROOT} exists=yes(显式导出)" +else + log "[10a-base][WARN] BASE_PKGS_ROOT=${BASE_PKGS_ROOT} exists=no —— 交由 gen_base_ddl.py 三段式探测基座包根(其候选含 /d/pipeline/pipeline-app/pkgs),探测过程逐条回显" +fi +log "[10a-base] 生成基座 DDL: ${BASE_GEN_PY} ${BASE_GEN}" +log "[10a-base] 输出: ${BASE_DDL_FILE} / ${BASE_ALIAS_MAP}" +"${BASE_GEN_PY}" "${BASE_GEN}" \ + --out "${BASE_DDL_FILE}" \ + --alias-map "${BASE_ALIAS_MAP}" \ + || die "[10a-base] gen_base_ddl.py 失败(基座 models 读取不完整 / users 缺失 / BASE_PKGS_ROOT 不可达,详见上方 [gen_base_ddl] 真实错误链)" + +# 生成产物存在性 + 生成器 SELF_CHECK 口径复核(不依赖 stderr 抓取,直接数 SQL 文件) +[ -f "${BASE_DDL_FILE}" ] || die "[10a-base] 生成器未产出 ${BASE_DDL_FILE}" +[ -f "${BASE_ALIAS_MAP}" ] || die "[10a-base] 生成器未产出 ${BASE_ALIAS_MAP}(声明表名→真源表名对照,test/deploy 探针据此改用真名消除 1146 误报)" +BASE_SQL_TABLES="$(grep -c 'CREATE TABLE IF NOT EXISTS' "${BASE_DDL_FILE}" || true)" +[ "${BASE_SQL_TABLES}" -ge 8 ] || die "[10a-base] base_tables.sql 仅含 ${BASE_SQL_TABLES} 张表(<8),基座 models 读取不完整" +grep -q 'CREATE TABLE IF NOT EXISTS `users`' "${BASE_DDL_FILE}" \ + || die "[10a-base] base_tables.sql 不含 users 表 —— up_login.dspy 500 根因未消除" +log "[10a-base] 生成校验通过: base_tables.sql 含 ${BASE_SQL_TABLES} 张表,users=present" + +log "[10a-base] 执行基座 DDL: ${BASE_DDL_FILE} → ${DB_NAME}@${DB_HOST}:${DB_PORT}" +mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \ + --default-character-set=utf8mb4 "${DB_NAME}" < "${BASE_DDL_FILE}" \ + || die "[10a-base] 基座 DDL 执行失败(连接参数取自 ${ENV_FILE},请核对 db.host/port/user/password 可达性)" + +# 自校验:逐张点名(IN 列表),不用 LIKE —— LIKE 会被同前缀表/迁移备份表干扰而虚高判死。 +# 期望 12 张:appbase 4(appcodes/appcodes_kv/params/svgicon) +# + rbac 8(audit_log/organization/orgtypes/permission/role/rolepermission/userrole/users) +BASE_TABLES="'appcodes','appcodes_kv','params','svgicon','audit_log','organization','orgtypes','permission','role','rolepermission','userrole','users'" +BASE_ACTUAL="$(mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \ + -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB_NAME}' AND table_name IN (${BASE_TABLES})" "${DB_NAME}")" +log "[10a-base] 基座表点名核验: ${BASE_ACTUAL}/12(appbase 4 + rbac 8)" +[ "${BASE_ACTUAL}" = "12" ] || { + MISSING="$(mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \ + -N -B -e "SELECT t.n FROM (SELECT 'appcodes' n UNION ALL SELECT 'appcodes_kv' UNION ALL SELECT 'params' UNION ALL SELECT 'svgicon' UNION ALL SELECT 'audit_log' UNION ALL SELECT 'organization' UNION ALL SELECT 'orgtypes' UNION ALL SELECT 'permission' UNION ALL SELECT 'role' UNION ALL SELECT 'rolepermission' UNION ALL SELECT 'userrole' UNION ALL SELECT 'users') t LEFT JOIN information_schema.tables i ON i.table_schema='${DB_NAME}' AND i.table_name=t.n WHERE i.table_name IS NULL" "${DB_NAME}" | tr '\n' ' ')" + die "[10a-base] 基座表在场数应为 12,实际 ${BASE_ACTUAL};缺失: ${MISSING:-(无法枚举)}" +} + +# users 表单独点名(登录链路命门,QC 验收项要求显式回显 users=present) +USERS_PRESENT="$(mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \ + -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB_NAME}' AND table_name='users'" "${DB_NAME}")" +[ "${USERS_PRESENT}" = "1" ] || die "[10a-base] users 表不存在 —— up_login.dspy 仍会 ERROR 1146 → 500" +# up_login.dspy 锁定检查/成功登录写的三列必须在位(来源 pkgs/rbac/migration/*.sql, +# models/users.json 未含,由 gen_base_ddl.py 补齐;此处对已存在的旧表做终态核验) +USERS_LOGIN_COLS="$(mysql --protocol=TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \ + -N -B -e "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='${DB_NAME}' AND table_name='users' AND column_name IN ('username','login_fail_count','last_login_fail','last_login')" "${DB_NAME}")" +[ "${USERS_LOGIN_COLS}" = "4" ] || die "[10a-base] users 表登录链列不全(username/login_fail_count/last_login_fail/last_login 应在场 4,实际 ${USERS_LOGIN_COLS})" +log "[10a-base] SELF_CHECK base_tables: PASS tables=${BASE_ACTUAL}/12 users=present login_cols=${USERS_LOGIN_COLS}/4" + # ---- 10b. 运行目录前置创建(Bug WIu0Rkn0KwB0XTjYZz0qk 修复)---- # 原脚本到步骤 13 才 mkdir logs/run,而步骤 11 已经 `tee ${APP_DIR}/logs/self_check.log`。 # 全新克隆(仓库不含 logs/,.gitignore 也排除 *.log)时 tee 打不开文件 →