feat(build): 生成 get dspy 后注入会话当前项目过滤(迭代/Bug/测试用例 无项目报错)

This commit is contained in:
yumoqing 2026-08-22 18:55:10 +08:00
parent b2d07ce247
commit cde7293d5e
2 changed files with 97 additions and 0 deletions

View File

@ -175,6 +175,11 @@ for d in sd_projects sd_iterations; do
done done
done done
# 6b. Inject session-current-project filter into generated get dspys (迭代/Bug/测试用例 用会话当前项目,无项目报错)
if [ -f "$cdir/scripts/inject_project_filter.py" ]; then
"$cdir/py3/bin/python" "$cdir/scripts/inject_project_filter.py" "$cdir/wwwroot/pipeline-sdlc" || echo " WARN: inject_project_filter.py failed"
fi
# 10.6 Create module tables (models -> DDL -> execute) # 10.6 Create module tables (models -> DDL -> execute)
echo "=== Module table creation ===" echo "=== Module table creation ==="

View File

@ -0,0 +1,92 @@
#!/usr/bin/env python3
"""给生成的 get_*.dspy 注入「会话当前项目强制过滤」(xls2ui 生成后 post-processing)。
背景:迭代/Bug/测试用例 三个功能页面要「用会话当前项目,不选项目,没项目报错」。
这些页面是 xls2ui 从 json/ + models/ 生成的(不入 git),无法在 json 源里表达
「后端强制按 current_project_id 过滤」这类自定义逻辑,故在生成后注入:
1. 在 ns = params_kw.copy() 之后注入「读 current_project_id + 无项目报错」代码;
2. SQL 里 where 1=1 [[filterstr]] 之前插入项目过滤条件(直接字段或子查询)。
幂等:已含 _cur_pid 的文件跳过;找不到锚点(ns 初始化 / where 1=1)跳过并告警。
用法:py3/bin/python scripts/inject_project_filter.py <pipeline-sdlc-wwwroot-dir>
"""
import sys
import os
# 表 -> 项目过滤 SQL 片段(插在 where 1=1 [[filterstr]] 的 1=1 之后)
PROJECT_FILTERS = {
"sd_iterations": "project_id = ${_cur_pid}$",
"sd_bugs": "iteration_id IN (SELECT id FROM sd_iterations WHERE project_id = ${_cur_pid}$)",
"sd_test_cases": (
"plan_id IN (SELECT id FROM sd_test_plans WHERE iteration_id IN "
"(SELECT id FROM sd_iterations WHERE project_id = ${_cur_pid}$))"
),
}
INJECT_CODE = '''
# 会话当前项目强制过滤(auto-injected):读 current_project_id,无项目报错
_uid = await get_user()
if not _uid:
_uid = 'user-01'
_dbname = get_module_dbname('pipeline_sdlc')
async with DBPools().sqlorContext(_dbname) as _sor:
_prec = await _sor.sqlExe("SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": _uid})
await _sor.sqlExe("COMMIT", {})
_cur_pid = getattr(_prec[0], 'current_project_id', '') if _prec else ''
if not _cur_pid:
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":20,"cheight":9,"message":"请先在会话中切换项目"}}
ns['_cur_pid'] = _cur_pid
'''
def process_file(path, filter_sql):
with open(path, "r", encoding="utf-8") as f:
content = f.read()
changed = False
# 1. 注入读 current_project_id(幂等:已注入则跳过)
if "_cur_pid" in content:
print(f" skip {os.path.basename(path)}: 已注入")
return False
if "ns = params_kw.copy()" not in content:
print(f" WARN {path}: 未找到 ns = params_kw.copy(),跳过")
return False
content = content.replace("ns = params_kw.copy()",
"ns = params_kw.copy()" + INJECT_CODE, 1)
changed = True
# 2. SQL 加项目过滤
if "where 1=1 [[filterstr]]" not in content:
print(f" WARN {path}: 未找到 where 1=1 [[filterstr]],跳过 SQL 过滤")
else:
content = content.replace("where 1=1 [[filterstr]]",
"where " + filter_sql + " [[filterstr]]", 1)
changed = True
with open(path, "w", encoding="utf-8") as f:
f.write(content)
print(f" injected {os.path.basename(path)}")
return True
def main():
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
wwwroot = sys.argv[1]
ok = 0
for tbl, fs in PROJECT_FILTERS.items():
path = os.path.join(wwwroot, tbl, "get_" + tbl + ".dspy")
if not os.path.isfile(path):
print(f" missing {path}")
continue
if process_file(path, fs):
ok += 1
print(f"inject_project_filter: {ok} 个文件已处理")
if __name__ == "__main__":
main()