优化:Validate 检查内部并行化(8→2组并行) #707

Merged
xiaoxia merged 1 commits from feat/ci-validate-parallel into develop 2026-07-22 14:20:34 +08:00
Owner

变更概述

scripts/ci/run_validate.sh 从串行执行 8 项检查重构为 5 个子任务并行执行,预期耗时从 ~1.8min 降至 ~1min

并行分组

Group A(独立并行,无需外部依赖)

子任务 内容 阻断
A1 Secret detection (detect-secrets)
A2 Code quality (black/isort/ruff/compileall)
A3 Mypy type check
A4 Advisory (bandit + pip-audit + vulture + 脚本语法) 否(仅告警)

Group B(PG 依赖,独立并行)

子任务 内容 阻断
B1 Alembic migrations validation

5 个子任务同时启动,全部完成后汇总结果。

实现方式

  • bash background jobs + wait(无需安装 parallel,更可靠)
  • 每个子任务独立函数,输出写入 /tmp/validate_logs/ 独立日志文件
  • wait 收集所有后台任务的退出码
  • 阻断类检查失败 → 整体失败
  • 告警类检查不阻断,行为与原来一致
  • 增量模式逻辑完整保留
  • PG 迁移验证独立运行(启动/建库/迁移/清理一整套),不与其他检查争资源
  • 完成后按顺序打印结果摘要,失败任务打印完整日志方便排查

影响范围

仅修改 scripts/ci/run_validate.sh,不涉及业务代码。

## 变更概述 将 `scripts/ci/run_validate.sh` 从串行执行 8 项检查重构为 5 个子任务并行执行,预期耗时从 **~1.8min 降至 ~1min**。 ## 并行分组 ### Group A(独立并行,无需外部依赖) | 子任务 | 内容 | 阻断 | |--------|------|------| | A1 | Secret detection (detect-secrets) | ✅ 是 | | A2 | Code quality (black/isort/ruff/compileall) | ✅ 是 | | A3 | Mypy type check | ✅ 是 | | A4 | Advisory (bandit + pip-audit + vulture + 脚本语法) | ❌ 否(仅告警) | ### Group B(PG 依赖,独立并行) | 子任务 | 内容 | 阻断 | |--------|------|------| | B1 | Alembic migrations validation | ✅ 是 | 5 个子任务同时启动,全部完成后汇总结果。 ## 实现方式 - **bash background jobs + wait**(无需安装 parallel,更可靠) - 每个子任务独立函数,输出写入 `/tmp/validate_logs/` 独立日志文件 - `wait` 收集所有后台任务的退出码 - 阻断类检查失败 → 整体失败 - 告警类检查不阻断,行为与原来一致 - 增量模式逻辑完整保留 - PG 迁移验证独立运行(启动/建库/迁移/清理一整套),不与其他检查争资源 - 完成后按顺序打印结果摘要,失败任务打印完整日志方便排查 ## 影响范围 仅修改 `scripts/ci/run_validate.sh`,不涉及业务代码。
xiaoxia added 1 commit 2026-07-22 12:26:08 +08:00
优化:Validate 检查内部并行化(8→2组并行)
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 26s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 30s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m15s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 43s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m45s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 2m14s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m56s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m26s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m31s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m35s
AI Code Review / AI Code Review (pull_request) Successful in 4m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 8m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 33m16s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 9s
2d327323f8
将 run_validate.sh 从串行执行 8 项检查重构为 5 个子任务并行执行:

并行分组:
  Group A(独立并行):
    A1: Secret detection (detect-secrets)
    A2: Code quality checks (black/isort/ruff/compileall)
    A3: Mypy type check
    A4: Advisory checks (bandit + pip-audit + vulture + 脚本语法)
  Group B(PG 依赖,独立并行):
    B1: Alembic migrations validation

实现方式:bash background jobs + wait
- 每个子任务独立函数,输出写入 /tmp/validate_logs/ 独立日志
- wait 收集所有后台任务退出码
- 阻断类(secret/code quality/mypy/alembic)失败则整体失败
- 告警类(bandit/pip-audit/vulture)不阻断,行为不变
- 增量模式逻辑完整保留
- PG 迁移验证独立运行,不与其他检查争资源
- 完成后按顺序打印摘要,失败任务打印完整日志

预期耗时从 ~1.8min 降至 ~1min

🚀 预览环境已部署

项目 详情
PR号 #707
预览链接 https://pr-707.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #707 | | 预览链接 | [https://pr-707.preview.xiaoxiajianji.com](https://pr-707.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot approved these changes 2026-07-22 12:28:35 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-07-22 12:28:35 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
Collaborator

代码审查结果 - PR #707

⚠️ 问题(3个需要修改)

  1. scripts/ci/run_validate.sh 第130行:敏感信息泄露风险(Token 暴露在进程列表)

    • 问题描述curl 命令通过 -H "Authorization: token ${GITHUB_TOKEN}" 直接传递 Token。在 Linux 系统中,当前用户的所有进程(及其参数)通常对同主机上的其他用户可见(如通过 ps aux)。在 CI 共享 Runner 环境中,这可能导致 Token 泄露给同一节点的其他并发任务。
    • 后果:GitHub Token 泄露可能导致仓库被恶意写入或读取。
    • 修改建议:虽然 curl 不支持直接从环境变量读取 Header,但应尽量避免将敏感明文放在命令行参数中。建议使用 netrc 文件或 CI 环境提供的更安全的封装方式;若必须使用此方式,需评估 CI 环境隔离性。
  2. scripts/ci/run_validate.sh 第152行:逻辑错误(空文件列表导致工具挂起)

    • 问题描述:在 task_code_quality 函数中,如果 PR 中删除了所有 Python 文件(或过滤后 EXISTING_PY_FILES 为空),变量 CHANGED_PY_FILES 将为空字符串。随后执行 python3 -m black --check --fast $CHANGED_PY_FILES 时,black 因未接收到文件参数,会尝试从标准输入(stdin)读取数据。
    • 后果:由于该任务在后台运行且 stdin 可能未关闭或指向终端,black(及后续的 isort/ruff)可能会挂起等待输入,导致 CI 流程卡死超时。
    • 修改建议:在执行检查工具前,增加判断 if [ -n "$CHANGED_PY_FILES" ]; then,确保仅在存在待检查文件时才调用工具。
  3. scripts/ci/run_validate.sh 第140行:逻辑缺陷(文件名包含空格导致检查失败)

    • 问题描述:脚本通过空格拼接文件路径(print(' '.join(...))),并在 Shell 中使用 for f in $CHANGED_PY_FILES 进行遍历。如果仓库中存在包含空格的文件名(如 my file.py),Shell 会将其拆分为两个参数(myfile.py),导致后续的 [ -f "$f" ] 检查失败,以及 black 等工具报错。
    • 后果:包含空格的文件名将无法被正确检查,且可能报错误导开发者。
    • 修改建议:修改 Python 脚本输出为以 Null 字符分隔的列表,或在 Shell 中使用数组(Array)来存储和传递文件列表,避免基于空格的字符串分割。

💡 建议(2个可选)

  1. 死代码清理record_result 函数被定义并在子任务中被调用,用于将结果写入文件,但在主流程的“结果汇总”阶段,脚本直接使用了 wait 命令捕获的退出码(TASK_EXIT),并未读取 record_result 写入的文件。建议删除 record_result 函数及相关调用,以减少混淆。

  2. 命令行参数长度风险task_code_quality 中将所有变更文件名拼接到变量 CHANGED_PY_FILES 并直接作为参数传递给 black/isort/ruff。如果 PR 变更文件极多(例如数千个),可能会超过系统的 ARG_MAX 限制,导致命令执行失败。建议使用 xargs 分批处理或通过参数文件(@args.txt)方式传递文件列表。


格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-22 12:30:46 | 模型:

## 代码审查结果 - PR #707 ### ⚠️ 问题(3个需要修改) 1. **scripts/ci/run_validate.sh 第130行**:敏感信息泄露风险(Token 暴露在进程列表) - **问题描述**:`curl` 命令通过 `-H "Authorization: token ${GITHUB_TOKEN}"` 直接传递 Token。在 Linux 系统中,当前用户的所有进程(及其参数)通常对同主机上的其他用户可见(如通过 `ps aux`)。在 CI 共享 Runner 环境中,这可能导致 Token 泄露给同一节点的其他并发任务。 - **后果**:GitHub Token 泄露可能导致仓库被恶意写入或读取。 - **修改建议**:虽然 `curl` 不支持直接从环境变量读取 Header,但应尽量避免将敏感明文放在命令行参数中。建议使用 `netrc` 文件或 CI 环境提供的更安全的封装方式;若必须使用此方式,需评估 CI 环境隔离性。 2. **scripts/ci/run_validate.sh 第152行**:逻辑错误(空文件列表导致工具挂起) - **问题描述**:在 `task_code_quality` 函数中,如果 PR 中删除了所有 Python 文件(或过滤后 `EXISTING_PY_FILES` 为空),变量 `CHANGED_PY_FILES` 将为空字符串。随后执行 `python3 -m black --check --fast $CHANGED_PY_FILES` 时,`black` 因未接收到文件参数,会尝试从标准输入(stdin)读取数据。 - **后果**:由于该任务在后台运行且 stdin 可能未关闭或指向终端,`black`(及后续的 `isort`/`ruff`)可能会挂起等待输入,导致 CI 流程卡死超时。 - **修改建议**:在执行检查工具前,增加判断 `if [ -n "$CHANGED_PY_FILES" ]; then`,确保仅在存在待检查文件时才调用工具。 3. **scripts/ci/run_validate.sh 第140行**:逻辑缺陷(文件名包含空格导致检查失败) - **问题描述**:脚本通过空格拼接文件路径(`print(' '.join(...))`),并在 Shell 中使用 `for f in $CHANGED_PY_FILES` 进行遍历。如果仓库中存在包含空格的文件名(如 `my file.py`),Shell 会将其拆分为两个参数(`my` 和 `file.py`),导致后续的 `[ -f "$f" ]` 检查失败,以及 `black` 等工具报错。 - **后果**:包含空格的文件名将无法被正确检查,且可能报错误导开发者。 - **修改建议**:修改 Python 脚本输出为以 Null 字符分隔的列表,或在 Shell 中使用数组(Array)来存储和传递文件列表,避免基于空格的字符串分割。 ### 💡 建议(2个可选) 1. **死代码清理**:`record_result` 函数被定义并在子任务中被调用,用于将结果写入文件,但在主流程的“结果汇总”阶段,脚本直接使用了 `wait` 命令捕获的退出码(`TASK_EXIT`),并未读取 `record_result` 写入的文件。建议删除 `record_result` 函数及相关调用,以减少混淆。 2. **命令行参数长度风险**:`task_code_quality` 中将所有变更文件名拼接到变量 `CHANGED_PY_FILES` 并直接作为参数传递给 `black/isort/ruff`。如果 PR 变更文件极多(例如数千个),可能会超过系统的 `ARG_MAX` 限制,导致命令执行失败。建议使用 `xargs` 分批处理或通过参数文件(`@args.txt`)方式传递文件列表。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-22 12:30:46 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 7cec7b4a31 into develop 2026-07-22 14:20:34 +08:00
xiaoxia deleted branch feat/ci-validate-parallel 2026-07-22 14:20:34 +08:00

🗑️ 预览环境已清理

PR #707 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #707 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.