checkpoint: 架构治理四件套——统一 async / 测试真 PG / Redis 降级可选 / DPB 扶正
- A1 业务层统一 async:gencode 表内省改 run_sync 异步(不再阻塞事件循环)、 check_db 改 async_engine、dict_util 启动预热异步载入;psycopg 降为 APScheduler SQLAlchemyJobStore 专用同步孤岛(注释标注) - A2 测试真 PG 化:conftest 弃 SQLite + mock Redis,改连真实 PG16(dpb_test)+ Redis(number_gen advisory lock 路径真被测);新增 docker/test-compose.yaml 测试依赖栈(postgres:16:5433 + redis:7:6380);run_ci 前置探测 + 容器兜底, pytest -m pg 10 套正式 tc 全过(真实 PG16 + Redis) - B1 Redis 启动不强依赖:redis_connect 失败降级启动,缓存类回源 DB、存储类 (会话/AI 配置/调度)经 require_redis 守卫返回 503;真机 3 阶段降级测试 PASS=11 FAIL=0(独立 Redis 6390 + 后端 8091,不动共享 dev 服务) - C 扶正 DPB:后端横幅/日志(dpb.log)/README/pyproject/ai_factory agent 名、 前端 package.json/署名注释/链接文案/deploy.sh/docker 注释全部去 fastapiadmin; grep backend/app + frontend/web/src 零残留 - 验证:全量回归 pass=72 fail=0
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""本机 CI stage:验收门 = 真实 PostgreSQL16 + Redis 就绪 → `pytest -m pg` 全绿。
|
||||
|
||||
背景:全工程无 git 仓库(root/backend/frontend 均无 .git),GitHub Actions 是云端服务,
|
||||
本机用不上;CI stage 落地为本机驱动脚本。v8 验收标准「CI 跑通 pytest 全绿」= 本脚本 EXIT=0。
|
||||
背景:工程已纳入 git(Gitea gonsun/dpb,2026-08-06 起);CI stage 落地为本机驱动脚本。
|
||||
v8 验收标准「CI 跑通 pytest 全绿」= 本脚本 EXIT=0。
|
||||
|
||||
step 0 探测本机真实 PG16(backend/env/.env.dev 的 DATABASE_*,可用 TC_CI_DB_* 覆盖)+ Redis
|
||||
(REDIS_*)连通;任一失败给出明确指引并 exit 非 0。
|
||||
step 1 backend 目录下 `pytest -m pg`(dpb python + -X utf8)跑 9 套统计引擎正式 tc 套件
|
||||
step 0 探测真实 PG16(backend/env/.env.dev 的 DATABASE_*,可用 TC_CI_DB_* 覆盖)+ Redis
|
||||
(REDIS_*)连通。本机 PG/Redis 未就绪且 docker 可用时,自动
|
||||
`docker compose -f docker/test-compose.yaml up -d` 拉起测试依赖栈
|
||||
(postgres:16:5433 + redis:7:6380,预建 dpb_test)并注入 TC_CI_* 覆盖后重探。
|
||||
仍失败给出明确指引并 exit 非 0。
|
||||
step 1 backend 目录下 `pytest -m pg`(dpb python + -X utf8)跑 10 套统计引擎正式 tc 套件
|
||||
(backend/tests/test_stat_analysis_tc.py 包装层,subprocess 调真实脚本)。
|
||||
step 2 汇总 EXIT=0 → 「CI 全绿」;日志写 Temp/claude/ci_logs/。
|
||||
|
||||
说明:
|
||||
- 全程真实 PG16 + Redis(本工程无 SQLite);PG/Redis 缺失时 step 0 拦截,不会误绿。
|
||||
- 与 run_regression.py 并存:run_regression = 手动全量回归(e2e 探针 + tc 套件);
|
||||
run_ci = 验收门(只跑 pytest -m pg 的 9 套正式 tc)。
|
||||
run_ci = 验收门(只跑 pytest -m pg 的 10 套正式 tc)。
|
||||
- 解释器默认 sys.executable(须用 dpb env python 运行);可用 DPB_PYTHON 覆盖。
|
||||
"""
|
||||
import asyncio
|
||||
@@ -60,6 +63,28 @@ def _env_cfg() -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _maybe_start_compose() -> bool:
|
||||
"""本机 PG/Redis 未就绪时,用 docker compose 拉起测试依赖栈(postgres:16 + redis)。
|
||||
|
||||
测试栈端口与宿主机常驻服务错开(5433/6380),预建测试库 dpb_test。
|
||||
返回是否成功拉起(docker 缺失/失败返回 False,交由 step 0 给出指引)。
|
||||
"""
|
||||
import shutil
|
||||
|
||||
if shutil.which("docker") is None:
|
||||
return False
|
||||
compose = os.path.join(ROOT, "docker", "test-compose.yaml")
|
||||
try:
|
||||
subprocess.run(
|
||||
["docker", "compose", "-f", compose, "up", "-d"],
|
||||
cwd=ROOT, capture_output=True, timeout=120, check=True,
|
||||
)
|
||||
return True
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(f" [warn] docker compose 拉起测试依赖失败: {str(exc)[:120]}")
|
||||
return False
|
||||
|
||||
|
||||
async def _probe(cfg: dict) -> tuple[bool, bool, str, str]:
|
||||
import asyncpg
|
||||
import redis.asyncio as aioredis
|
||||
@@ -101,12 +126,36 @@ def main() -> int:
|
||||
print(f"[step 0] 探测 Redis {cfg['REDIS_HOST']}:{cfg['REDIS_PORT']}/{cfg['REDIS_DB_NAME']} → "
|
||||
f"{'OK' if redis_ok else 'FAIL ' + redis_err}")
|
||||
if not (db_ok and redis_ok):
|
||||
print("\n❌ 基础设施未就绪,CI 无法放行。请检查:")
|
||||
print(" · 本机 PostgreSQL 16 服务是否启动(服务名 postgresql-x64-16,端口 5432)")
|
||||
print(" · Redis 是否启动(redis-server,端口 6379;工程 WSL 内运行则确认 WSL 已起)")
|
||||
print(f" · 连接配置 backend/env/.env.dev 的 DATABASE_*/REDIS_* 是否与本地一致")
|
||||
print(" · 可用 TC_CI_DB_HOST / TC_CI_DB_PORT 等环境变量临时覆盖探测地址")
|
||||
return 1
|
||||
print("\n[step 0] 本机 PG/Redis 未就绪,尝试 docker compose 拉起测试依赖栈…")
|
||||
if _maybe_start_compose():
|
||||
# 测试栈端口与常驻服务错开(5433/6380),预建 dpb_test;注入 TC_CI_* 覆盖
|
||||
os.environ.update({
|
||||
"TC_CI_DB_HOST": "127.0.0.1", "TC_CI_DB_PORT": "5433",
|
||||
"TC_CI_DB_USER": "dpb", "TC_CI_DB_PASSWORD": "dpb",
|
||||
"TC_CI_DB_NAME": "dpb_test",
|
||||
"TC_CI_REDIS_HOST": "127.0.0.1", "TC_CI_REDIS_PORT": "6380",
|
||||
"TC_CI_REDIS_DB": "1",
|
||||
})
|
||||
cfg = _env_cfg()
|
||||
# postgres:16 首次初始化可能需数十秒,轮询等健康
|
||||
for _ in range(15):
|
||||
db_ok, redis_ok, db_err, redis_err = asyncio.run(_probe(cfg))
|
||||
if db_ok and redis_ok:
|
||||
break
|
||||
import time
|
||||
time.sleep(5)
|
||||
print(f"[step 0] 容器 PG {cfg['DATABASE_HOST']}:{cfg['DATABASE_PORT']}/{cfg['DATABASE_NAME']} → "
|
||||
f"{'OK' if db_ok else 'FAIL ' + db_err}")
|
||||
print(f"[step 0] 容器 Redis {cfg['REDIS_HOST']}:{cfg['REDIS_PORT']}/{cfg['REDIS_DB_NAME']} → "
|
||||
f"{'OK' if redis_ok else 'FAIL ' + redis_err}")
|
||||
if not (db_ok and redis_ok):
|
||||
print("\n❌ 基础设施未就绪,CI 无法放行。请检查:")
|
||||
print(" · 本机 PostgreSQL 16 服务是否启动(服务名 postgresql-x64-16,端口 5432)")
|
||||
print(" · Redis 是否启动(redis-server,端口 6379;工程 WSL 内运行则确认 WSL 已起)")
|
||||
print(f" · 连接配置 backend/env/.env.dev 的 DATABASE_*/REDIS_* 是否与本地一致")
|
||||
print(" · 或安装 docker 后由本脚本自动拉起 docker/test-compose.yaml 测试依赖栈")
|
||||
print(" · 可用 TC_CI_DB_HOST / TC_CI_DB_PORT 等环境变量临时覆盖探测地址")
|
||||
return 1
|
||||
|
||||
# ---- step 1: pytest -m pg ----
|
||||
os.makedirs(LOG_DIR, exist_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user