feat(ci): 全面审计修复CI配置 - 18个问题(P0×3 + P1×7 + P2×8) #196

Closed
xiaoxia wants to merge 19 commits from feature/ci-full-audit-fix into develop
Owner

CI 全面审计修复

对 xiaoxia-saas 仓库 CI 配置进行全面审计,共发现 18 个问题,按 P0/P1/P2 分级修复。

修复统计

  • P0(安全/正确性,3 项): 全部修复
  • P1(重要功能/可靠性,7 项): 全部修复
  • P2(优化类,8 项): 7 项修复,1 项记录为建议

P0 - 必须立即修复

P0-1: 明文凭据泄露

问题: daily-check.yml 中有 5 处明文测试账号密码
修复: 创建 STAGING_TEST_USER / STAGING_TEST_PASSWORD 两个仓库级 secrets,替换所有明文引用

P0-2: 调试文件残留

问题: test-ssh-secret.yml 调试用 workflow 遗留在仓库中
修复: 已删除该文件

P0-3: job outputs 配置错误

问题: daily-check.yml 中 staging-api-tests 和 staging-e2e 的 outputs 指向错误的 step id
修复:

  • staging-api-tests: steps.smoke.outputs.resultsteps.report.outputs.result
  • staging-e2e: steps.smoke.outputs.resultsteps.e2e.outputs.result

P1 - 重要功能/可靠性

P1-1: 重复的 tests.yml 流水线

问题: tests.yml 与 ci-cd.yml 的 validate job 功能完全重复
修复: 删除 tests.yml

P1-2: performance-check 死代码

问题: performance-check 的第一个 step 是 118 行的死代码(与第二个 step 功能重叠且无 id 引用)
修复: 删除第一个死代码 step

P1-3: staging 部署失败无自动回滚

问题: smoke test 失败后直接退出,staging 环境停留在损坏状态
修复:

  • 部署前保存当前 :staging 镜像的 digest 作为回滚点
  • smoke test 失败时自动将 :staging tag 回滚至旧版本
  • Watchtower 自动检测并恢复旧版本

P1-4: 生产部署是停机重启模式

问题: 先 docker rm -f 再 docker run,服务中断时间长;失败时无回滚
修复:

  • 部署前记录当前运行版本(用于回滚)
  • 健康检查失败时自动用旧镜像回滚
  • 容器优雅停止(docker stop -t 10 替代 docker rm -f)

P1-5: :dev tag 不一致且不推送

问题: API/Worker 有本地 :dev tag 但不 push,Web 完全没有 :dev tag
修复:

  • 三个镜像统一打 :dev tag
  • push 阶段同时推送 :dev tag 到 Registry

P1-6: auto_merge_prs.sh 缺少安全检查

问题: 只检查 mergeable 标志,不检查 CI 状态、不需要 review、没有标签白名单
修复:

  • 增加 auto-merge 标签白名单(必须打标签才会自动合并)
  • 增加 CI 状态检查(所有 check 必须 success)
  • 增加 Review 审批检查(至少 1 个 approve,无 changes requested)
  • 合并方式改为 squash

P1-7: cleanup_old_images.sh 目标过时+明文密码

问题: 指向旧 Registry(localhost:5000),硬编码明文密码 admin:Xiaoxia2026
修复:

  • 移除过时的 Registry API 清理逻辑(已由 Gitea Package 清理规则替代)
  • 移除明文密码
  • 保留本地镜像清理功能
  • 增加 builder 缓存清理
  • 默认保留版本从 2 个增加到 5 个

P2 - 优化类

P2-2: Python 依赖无缓存

修复: validate job 增加 actions/cache,缓存 pip 下载目录

P2-3: validate job timeout 偏紧

修复: 10 分钟 → 20 分钟

P2-4: 缺少 concurrency 控制

修复: 增加 concurrency 配置,同一分支重复 push 自动取消旧构建

P2-5: 测试失败无日志产物上传

修复:

  • pytest 输出改为详细模式(-v),增加 --tb=short
  • 输出 junitxml 报告
  • 失败时用 actions/upload-artifact 上传测试结果

P2-6: E2E 测试缺少重试机制

修复: 所有 Playwright E2E 测试增加 --retries=2,降低偶发失败率

P2-7: 缺少镜像安全扫描

修复: 生产构建增加 Trivy 镜像扫描(仅检测 CRITICAL/HIGH 级别,仅告警不阻断)

P2-8: Dockerfile 可进一步瘦身

修复: api.Dockerfile 和 worker.Dockerfile 增加 Python 字节码清理、文档清理、apt 缓存清理

P2-1: 重复 checkout 代码未提取

状态: 建议,暂不实施
原因: checkout 是 workflow 第一步,无法调用仓库内的脚本。Gitea Actions 支持 actions/checkout,但当前自定义 checkout 有重试逻辑(应对 API 不稳定性),替换有一定风险。建议后续评估后再决定是否替换为官方 action。


备注 & 待确认事项

  1. P2-1 未实施: 重复 checkout 提取需要评估是否替换为 actions/checkout 官方 action
  2. Trivy 扫描: 使用 aquasec/trivy:latest 镜像,首次运行需要拉取,可能增加构建时间。建议观察效果后决定是否保留
  3. concurrency: 对 tag 触发的生产部署同样生效,如果重新运行同一个 tag 的部署会取消之前的(通常是期望行为)
  4. staging 回滚: 使用 docker buildx imagetools create 回滚 tag,需要 buildx 支持。已在 saas runner 上验证可用
  5. 生产回滚: 保存旧镜像名,失败时用旧镜像重新启动。旧镜像需仍在本地(正常情况下不会被立即清理)

变更文件数: 12 个
新增 commit: 19 个
目标分支: develop

## CI 全面审计修复 对 xiaoxia-saas 仓库 CI 配置进行全面审计,共发现 18 个问题,按 P0/P1/P2 分级修复。 ### 修复统计 - **P0(安全/正确性,3 项)**: ✅ 全部修复 - **P1(重要功能/可靠性,7 项)**: ✅ 全部修复 - **P2(优化类,8 项)**: ✅ 7 项修复,1 项记录为建议 --- ## P0 - 必须立即修复 ### P0-1: 明文凭据泄露 **问题**: daily-check.yml 中有 5 处明文测试账号密码 **修复**: 创建 `STAGING_TEST_USER` / `STAGING_TEST_PASSWORD` 两个仓库级 secrets,替换所有明文引用 ### P0-2: 调试文件残留 **问题**: test-ssh-secret.yml 调试用 workflow 遗留在仓库中 **修复**: 已删除该文件 ### P0-3: job outputs 配置错误 **问题**: daily-check.yml 中 staging-api-tests 和 staging-e2e 的 outputs 指向错误的 step id **修复**: - staging-api-tests: `steps.smoke.outputs.result` → `steps.report.outputs.result` - staging-e2e: `steps.smoke.outputs.result` → `steps.e2e.outputs.result` --- ## P1 - 重要功能/可靠性 ### P1-1: 重复的 tests.yml 流水线 **问题**: tests.yml 与 ci-cd.yml 的 validate job 功能完全重复 **修复**: 删除 tests.yml ### P1-2: performance-check 死代码 **问题**: performance-check 的第一个 step 是 118 行的死代码(与第二个 step 功能重叠且无 id 引用) **修复**: 删除第一个死代码 step ### P1-3: staging 部署失败无自动回滚 **问题**: smoke test 失败后直接退出,staging 环境停留在损坏状态 **修复**: - 部署前保存当前 :staging 镜像的 digest 作为回滚点 - smoke test 失败时自动将 :staging tag 回滚至旧版本 - Watchtower 自动检测并恢复旧版本 ### P1-4: 生产部署是停机重启模式 **问题**: 先 docker rm -f 再 docker run,服务中断时间长;失败时无回滚 **修复**: - 部署前记录当前运行版本(用于回滚) - 健康检查失败时自动用旧镜像回滚 - 容器优雅停止(docker stop -t 10 替代 docker rm -f) ### P1-5: :dev tag 不一致且不推送 **问题**: API/Worker 有本地 :dev tag 但不 push,Web 完全没有 :dev tag **修复**: - 三个镜像统一打 :dev tag - push 阶段同时推送 :dev tag 到 Registry ### P1-6: auto_merge_prs.sh 缺少安全检查 **问题**: 只检查 mergeable 标志,不检查 CI 状态、不需要 review、没有标签白名单 **修复**: - 增加 `auto-merge` 标签白名单(必须打标签才会自动合并) - 增加 CI 状态检查(所有 check 必须 success) - 增加 Review 审批检查(至少 1 个 approve,无 changes requested) - 合并方式改为 squash ### P1-7: cleanup_old_images.sh 目标过时+明文密码 **问题**: 指向旧 Registry(localhost:5000),硬编码明文密码 admin:Xiaoxia2026 **修复**: - 移除过时的 Registry API 清理逻辑(已由 Gitea Package 清理规则替代) - 移除明文密码 - 保留本地镜像清理功能 - 增加 builder 缓存清理 - 默认保留版本从 2 个增加到 5 个 --- ## P2 - 优化类 ### P2-2: Python 依赖无缓存 ⭐ **修复**: validate job 增加 actions/cache,缓存 pip 下载目录 ### P2-3: validate job timeout 偏紧 ⭐ **修复**: 10 分钟 → 20 分钟 ### P2-4: 缺少 concurrency 控制 ⭐ **修复**: 增加 concurrency 配置,同一分支重复 push 自动取消旧构建 ### P2-5: 测试失败无日志产物上传 **修复**: - pytest 输出改为详细模式(-v),增加 --tb=short - 输出 junitxml 报告 - 失败时用 actions/upload-artifact 上传测试结果 ### P2-6: E2E 测试缺少重试机制 ⭐ **修复**: 所有 Playwright E2E 测试增加 `--retries=2`,降低偶发失败率 ### P2-7: 缺少镜像安全扫描 **修复**: 生产构建增加 Trivy 镜像扫描(仅检测 CRITICAL/HIGH 级别,仅告警不阻断) ### P2-8: Dockerfile 可进一步瘦身 **修复**: api.Dockerfile 和 worker.Dockerfile 增加 Python 字节码清理、文档清理、apt 缓存清理 ### P2-1: 重复 checkout 代码未提取 **状态**: 建议,暂不实施 **原因**: checkout 是 workflow 第一步,无法调用仓库内的脚本。Gitea Actions 支持 actions/checkout,但当前自定义 checkout 有重试逻辑(应对 API 不稳定性),替换有一定风险。建议后续评估后再决定是否替换为官方 action。 --- ## 备注 & 待确认事项 1. **P2-1 未实施**: 重复 checkout 提取需要评估是否替换为 actions/checkout 官方 action 2. **Trivy 扫描**: 使用 aquasec/trivy:latest 镜像,首次运行需要拉取,可能增加构建时间。建议观察效果后决定是否保留 3. **concurrency**: 对 tag 触发的生产部署同样生效,如果重新运行同一个 tag 的部署会取消之前的(通常是期望行为) 4. **staging 回滚**: 使用 docker buildx imagetools create 回滚 tag,需要 buildx 支持。已在 saas runner 上验证可用 5. **生产回滚**: 保存旧镜像名,失败时用旧镜像重新启动。旧镜像需仍在本地(正常情况下不会被立即清理) --- **变更文件数**: 12 个 **新增 commit**: 19 个 **目标分支**: develop
xiaoxia added 19 commits 2026-07-09 14:01:16 +08:00
ci(P0-1): 移除明文测试账号密码,改用 Gitea Secrets
CI/CD Pipeline / Frontend Lint (push) Successful in 2m16s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m1s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
f678504b97
- 创建 STAGING_TEST_USER / STAGING_TEST_PASSWORD 两个 secret
- 修改 daily-check.yml 中 5 处明文凭据引用
- 涉及 staging-api-tests 和 performance-check 两个 job
ci(P0-2): 删除调试残留的 test-ssh-secret.yml
CI/CD Pipeline / Frontend Lint (push) Successful in 1m56s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
b012a7da00
该文件是用于调试 SSH secret 配置的临时 workflow,
仅在修改自身时触发,无实际业务用途,应从生产 workflow 目录移除。
ci(P0-3): 修复 daily-check.yml 中 job outputs 配置错误
CI/CD Pipeline / Frontend Lint (push) Successful in 1m49s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
bc83a361b1
- staging-api-tests.outputs.report: steps.smoke → steps.report
  (smoke step 输出的是 api_report,report step 才输出 report)
- staging-e2e.outputs.report: steps.smoke → steps.e2e
  (该 job 的 step id 是 e2e,不是 smoke)
- 修复后 daily-report job 才能正确获取各巡检项状态
ci(P1-1): 删除重复的 tests.yml 流水线
CI/CD Pipeline / Frontend Lint (push) Successful in 1m41s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
ed398b8c78
ci-cd.yml 的 validate job 已经覆盖了 tests.yml 的全部功能:
- 单元测试 + 集成测试
- Black 代码格式化检查
- Flake8 静态分析
- 还有安全扫描、迁移检查等 tests.yml 没有的检查

且 ci-cd.yml 已配置 pull_request 触发,PR 时会自动运行。
删除重复流水线,减少维护成本。
ci(P1-2): 删除 performance-check 中第一个死代码 step
CI/CD Pipeline / Frontend Lint (push) Successful in 1m41s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
5772de2ade
performance-check job 中有两个 step 都在做性能测试:
- 第一个 step(118行)使用 while read 子 shell 方式,变量全部丢失,结果完全没用
- 第二个 step 使用函数方式,正确统计结果

删除无用的第一个 step,减少约一半的请求次数和执行时间。
ci(P1-5): 统一 build_release_images.sh 的 :dev tag 并推送至 Registry
CI/CD Pipeline / Frontend Lint (push) Successful in 1m53s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2a6d3f0d8b
ci(P1-6): 增强 auto_merge_prs.sh 安全检查:CI状态+标签白名单+Review审批
CI/CD Pipeline / Frontend Lint (push) Successful in 1m34s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
90e5f47975
ci(P1-7): 重写 cleanup_old_images.sh:移除过时Registry清理和明文密码,仅保留本地清理
CI/CD Pipeline / Frontend Lint (push) Successful in 1m41s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 10m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
c6d1136ae3
xiaoxia closed this pull request 2026-07-15 07:39:13 +08:00

Pull request closed

Sign in to join this conversation.