geo/docs/plans/2026-06-04-008-chore-geo-pr...

419 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "chore: GEO Platform Production Readiness — Final Mile to Deployable"
type: chore
status: completed
date: 2026-06-04
---
# GEO Platform Production Readiness — Final Mile to Deployable
## Summary
补齐 GEO 平台从"代码完成"到"生产可用"的最后一公里:修复 Agent 注册缺口、Docker 生产镜像瘦身与健康检查、CI/CD 流水线修复、Sentry 监控接入、测试体系收尾(散落文件迁移+重复文件清理)、配置一致性修复。完成后平台达到可部署、可监控、可持续交付的状态。
## Problem Frame
7 个迭代计划已完成GEO 平台功能代码基本就绪8 个 Agent、35 个前端页面、1521 个后端测试、19 个 E2E 测试)。但深度审查发现多个生产阻塞问题:生产 Docker 镜像包含 Playwright+Chromium+500MB 攻击面)、生产 docker-compose 缺少健康检查、3 个 Agent 未注册导出、CI 流水线 PR 评论功能失效、前后端 Sentry 监控预留但未接入、11 个后端测试文件散落在根目录且 4 个与子目录重复。这些问题不解决,平台无法安全部署到生产环境。
---
## Requirements
**Agent 注册完整性**
R1. 8 个 Agent 全部在 `__init__.py` 中导出Agent 框架可正确发现和调度所有 Agent
**Docker 生产就绪**
R2. 生产 Docker 镜像不包含 Playwright/Chromium 等测试工具,镜像体积合理
R3. 生产 docker-compose 中 backend 和 frontend 均配置 healthcheck
R4. `docker-compose.prod.yml` 移除已弃用的 `version` 字段
**CI/CD 流水线修复**
R5. PR Check 工作流中的步骤引用修复PR 评论正确显示检查结果
R6. CI 和 PR Check 工作流避免对同一 PR 双重触发
R7. CI 中 "Type check" 步骤名称与实际行为一致
**Sentry 监控接入**
R8. 后端集成 Sentry SDK未捕获异常和性能追踪自动上报
R9. 前端集成 Sentry SDK运行时错误和 React 错误边界自动上报
**测试体系收尾**
R10. 11 个根目录散落测试文件迁移到对应子目录
R11. 4 个与子目录重复的根目录测试文件删除
R12. 后端 pytest 配置添加覆盖率报告
**配置一致性**
R13. `config.py``REDIS_URL` 默认值不含密码问题修复
R14. `.env.production.example` 补充缺失变量POSTGRES_USER、POSTGRES_DB 等)
R15. `next.config.mjs` 生产构建启用类型检查和 lint
---
## Key Technical Decisions
KTD1. **生产 Dockerfile 拆分为 runtime 和 e2e 两个阶段。** 当前 runtime 阶段包含 Playwright+Chromium是 E2E 测试工具不应出现在生产镜像。新增 `e2e` 阶段继承 runtime 并安装 PlaywrightCI E2E 测试使用 `e2e` 阶段,生产部署使用 `runtime` 阶段。预估镜像体积减少 500MB+。
KTD2. **Sentry DSN 通过环境变量注入,未配置时静默跳过。** 使用 `sentry_sdk.init(dsn=settings.SENTRY_DSN)` 模式,`SENTRY_DSN` 默认为空字符串Sentry SDK 在 DSN 为空时自动禁用,不影响开发和测试环境。
KTD3. **散落测试文件迁移而非重写。** 11 个文件仅移动位置并更新 import 路径4 个重复文件直接删除根目录版本(保留子目录中更完整的版本)。
KTD4. **CI 修复采用最小改动策略。** 修复 pr-check.yml 的步骤 ID 引用、添加 concurrency 分组、修正步骤名称,不重构整个 CI 流程。
---
## High-Level Technical Design
```mermaid
flowchart TB
subgraph Phase1["Phase 1 — 部署阻塞修复"]
U1[U1. Agent 注册补全] --> U2[U2. Docker 生产镜像瘦身]
U2 --> U3[U3. Docker 生产健康检查+配置修复]
end
subgraph Phase2["Phase 2 — 可观测性"]
U4[U4. Sentry 后端接入]
U5[U5. Sentry 前端接入]
end
subgraph Phase3["Phase 3 — CI/CD 修复"]
U6[U6. CI 流水线修复]
end
subgraph Phase4["Phase 4 — 测试收尾"]
U7[U7. 测试文件迁移+清理]
U8[U8. 覆盖率配置+配置一致性]
end
U3 --> U4
U3 --> U6
U6 --> U7
```
---
## Implementation Units
### U1. Agent Registration Completion
**Goal:** 补全 Agent 框架注册,确保 8 个 Agent 全部可被发现和调度
**Requirements:** R1
**Dependencies:** none
**Files:**
- `backend/app/agent_framework/agents/__init__.py` — 添加 3 个 Agent 导出
- `backend/app/agent_framework/agents/competitor_analyzer.py` — 验证导出接口
- `backend/app/agent_framework/agents/monitor_agent.py` — 验证导出接口
- `backend/app/agent_framework/agents/schema_advisor.py` — 验证导出接口
- `backend/app/agent_framework/registry.py` — 验证自动发现逻辑
- `backend/tests/test_agent_framework/` — 验证测试通过
**Approach:**`__init__.py` 中添加 CompetitorAnalyzerAgent、MonitorAgent、SchemaAdvisorAgent 的 import 和 `__all__` 导出。验证 `registry.py` 的自动发现逻辑能正确注册这 3 个 Agent。运行现有 Agent 框架测试确认无回归。
**Patterns to follow:** 现有 5 个 Agent 的导出模式
**Test scenarios:**
- `from app.agent_framework.agents import CompetitorAnalyzerAgent` 不报错
- `from app.agent_framework.agents import MonitorAgent` 不报错
- `from app.agent_framework.agents import SchemaAdvisorAgent` 不报错
- Agent registry 自动注册后 `list_agents()` 返回 8 个 Agent
- 现有 Agent 框架测试全部通过
**Verification:** `pytest tests/test_agent_framework/` 通过,`__all__` 包含 8 个 Agent 名称
---
### U2. Docker Production Image Slimming
**Goal:** 生产 Docker 镜像移除 Playwright/Chromium减少镜像体积和攻击面
**Requirements:** R2
**Dependencies:** U1
**Files:**
- `backend/Dockerfile` — 拆分 runtime 和 e2e 阶段
**Approach:** 将当前 `runtime` 阶段中的 Playwright 安装(`playwright install --with-deps chromium`)和 Chromium 系统依赖libglib2.0、libnss3 等)移到新增的 `e2e` 阶段。`runtime` 阶段仅保留 Python 依赖 + gunicorn。CI E2E 测试的 docker-compose 使用 `target: e2e`,生产部署使用 `target: runtime`
**Patterns to follow:** 现有 Dockerfile 多阶段构建模式
**Test scenarios:**
- `docker build --target runtime .` 构建成功,镜像不含 Playwright
- `docker build --target e2e .` 构建成功,镜像包含 Playwright
- runtime 镜像体积比 e2e 镜像小 500MB+
- runtime 镜像中 `python -c "import playwright"` 报 ImportError
- e2e 镜像中 `python -c "import playwright"` 成功
**Verification:** `docker build --target runtime .` 成功,`docker run <runtime-image> python -c "from app.main import app"` 成功
---
### U3. Docker Production Health Check and Configuration Fixes
**Goal:** 生产 docker-compose 添加健康检查,修复配置一致性问题
**Requirements:** R3, R4, R13, R14, R15
**Dependencies:** U2
**Files:**
- `docker-compose.prod.yml` — 添加 healthcheck、移除 version 字段
- `backend/app/config.py` — 修复 REDIS_URL 默认值、添加 SENTRY_DSN 字段
- `.env.production.example` — 补充缺失变量
- `frontend/next.config.mjs` — 生产构建启用类型检查
**Approach:**
1. `docker-compose.prod.yml`:为 backend 和 frontend 添加与 Dockerfile 一致的 healthcheck 配置;移除 `version: "3.9"`
2. `config.py`:将 `REDIS_URL` 默认值改为空字符串,添加启动时验证(如果 REDIS_URL 为空则警告);添加 `SENTRY_DSN: str = ""` 字段
3. `.env.production.example`:补充 `POSTGRES_USER`、`POSTGRES_DB`、`SENTRY_DSN`、AI 平台密钥等变量
4. `next.config.mjs`:通过环境变量控制 `ignoreBuildErrors``ignoreDuringBuilds`,生产构建(`NEXT_BUILD_ENV=production`)时设为 false
**Patterns to follow:** 开发环境 docker-compose.yml 的 healthcheck 配置模式
**Test scenarios:**
- 生产 docker-compose backend healthcheck 通过
- 生产 docker-compose frontend healthcheck 通过
- `config.py` REDIS_URL 为空时启动后端发出警告但不崩溃
- `.env.production.example` 包含 docker-compose.prod.yml 所需的全部变量
- `next.config.mjs` 在 NEXT_BUILD_ENV=production 时启用类型检查
**Verification:** `docker compose -f docker-compose.prod.yml up` 启动成功,所有服务健康检查通过
---
### U4. Sentry Backend Integration
**Goal:** 后端集成 Sentry SDK未捕获异常和性能追踪自动上报
**Requirements:** R8
**Dependencies:** U3需要 SENTRY_DSN 配置字段)
**Files:**
- `backend/requirements.txt` — 添加 `sentry-sdk[fastapi]`
- `backend/app/config.py` — 已在 U3 添加 SENTRY_DSN
- `backend/app/main.py` — Sentry 初始化
- `backend/app/middleware/metrics.py` — 替换 TODO 注释为实际 Sentry 集成
**Approach:**
1. 添加 `sentry-sdk[fastapi]` 依赖
2.`main.py` 的 FastAPI app 创建前调用 `sentry_sdk.init(dsn=settings.SENTRY_DSN, traces_sample_rate=0.1, environment=settings.ENVIRONMENT)`
3. 替换 `metrics.py` 中的两处 Sentry TODO 注释为实际集成代码
4. DSN 为空时 Sentry SDK 自动禁用,不影响开发环境
**Patterns to follow:** Sentry FastAPI 集成官方文档模式
**Test scenarios:**
- SENTRY_DSN 为空时后端正常启动,无 Sentry 上报
- SENTRY_DSN 配置后未捕获异常自动上报 Sentry
- FastAPI 请求性能追踪数据上报 Sentry
- 现有测试不受 Sentry 集成影响
**Verification:** 配置有效 SENTRY_DSN 后,触发异常可在 Sentry dashboard 看到
---
### U5. Sentry Frontend Integration
**Goal:** 前端集成 Sentry SDK运行时错误和 React 错误边界自动上报
**Requirements:** R9
**Dependencies:** U3需要 SENTRY_DSN 配置字段)
**Files:**
- `frontend/package.json` — 添加 `@sentry/nextjs` 依赖
- `frontend/next.config.mjs` — Sentry webpack 配置
- `frontend/sentry.client.config.ts` — 新建,客户端 Sentry 初始化
- `frontend/sentry.server.config.ts` — 新建,服务端 Sentry 初始化
- `frontend/components/ErrorBoundary.tsx` — 替换 TODO 注释为 Sentry 上报
**Approach:**
1. 安装 `@sentry/nextjs`
2. 创建 `sentry.client.config.ts``sentry.server.config.ts`,使用 `NEXT_PUBLIC_SENTRY_DSN` 环境变量初始化
3.`next.config.mjs` 中添加 Sentry webpack 插件配置withSentryConfig wrapper
4. 替换 `ErrorBoundary.tsx` 中的 `// TODO:SENTRY``Sentry.captureException(error)`
5. DSN 为空时 Sentry 自动禁用
**Patterns to follow:** Sentry Next.js SDK 官方集成模式
**Test scenarios:**
- NEXT_PUBLIC_SENTRY_DSN 为空时前端正常加载,无 Sentry 上报
- NEXT_PUBLIC_SENTRY_DSN 配置后未捕获错误自动上报
- ErrorBoundary 捕获的 React 错误上报 Sentry
- 前端构建不受 Sentry 集成影响
**Verification:** 配置有效 DSN 后,触发前端错误可在 Sentry dashboard 看到
---
### U6. CI Pipeline Fixes
**Goal:** 修复 CI/CD 流水线中的已知问题
**Requirements:** R5, R6, R7
**Dependencies:** U2Docker 镜像拆分后 CI 需要更新)
**Files:**
- `.github/workflows/ci.yml` — 修正步骤名称、更新 Docker build target
- `.github/workflows/pr-check.yml` — 修复步骤 ID 引用
**Approach:**
1. `ci.yml`:将 "Type check" 步骤名称改为 "Lint (ruff)" 或添加真正的 mypy 步骤E2E 测试的 docker-compose 使用 `target: e2e`;添加 `concurrency: group: ci-${{ github.ref }}` 避免重复运行
2. `pr-check.yml`:为每个步骤添加 `id`(如 `id: backend-lint`),修复 PR 评论中的步骤引用 `${{ steps.backend-lint.outcome }}`;添加 `concurrency: group: pr-check-${{ github.ref }}`
**Patterns to follow:** GitHub Actions 工作流最佳实践
**Test scenarios:**
- PR 提交时 pr-check.yml 正确运行并在 PR 中评论检查结果
- PR 评论表格中各项显示 pass/fail 而非 N/A
- 同一 PR 不会同时触发 ci.yml 和 pr-check.yml 的重复运行
- E2E 测试使用 e2e Docker 镜像(含 Playwright
**Verification:** 提交 PR 后检查 Actions tab 和 PR 评论
---
### U7. Test File Migration and Cleanup
**Goal:** 迁移散落测试文件到标准目录,删除重复文件
**Requirements:** R10, R11
**Dependencies:** U6CI 修复后再迁移,避免 CI 配置冲突)
**Files:**
- `backend/tests/test_config.py``backend/tests/test_infrastructure/test_config.py`
- `backend/tests/test_database_exception_handling.py``backend/tests/test_infrastructure/test_database_exception_handling.py`
- `backend/tests/test_database_migration.py``backend/tests/test_infrastructure/test_database_migration.py`
- `backend/tests/test_performance.py``backend/tests/test_infrastructure/test_performance.py`
- `backend/tests/test_security.py``backend/tests/test_infrastructure/test_security.py`
- `backend/tests/test_platform_adapters.py``backend/tests/test_services/test_platform_adapters.py`
- `backend/tests/test_scheduler.py``backend/tests/test_infrastructure/test_scheduler.py`
- `backend/tests/test_html_generator.py` — 删除(与 `test_content_pipeline/test_html_generator.py` 重复)
- `backend/tests/test_rule_validator.py` — 删除(与 `test_content_pipeline/test_rule_validator.py` 重复)
- `backend/tests/test_sensitive_filter.py` — 删除(与 `test_content_pipeline/test_sensitive_filter.py` 重复)
- `backend/tests/test_seo_optimizer.py` — 删除(与 `test_content_pipeline/test_seo_optimizer.py` 重复)
**Approach:**
1. 迁移前运行 `pytest` 记录基线通过率
2. 逐个迁移文件,更新内部 import 路径(如有)
3. 删除 4 个重复的根目录文件
4. 迁移后运行 `pytest` 确认通过率一致
5. 更新 `pyproject.toml``testpaths` 配置(如有必要)
**Execution note:** 迁移前先运行全部测试记录基线,迁移后验证所有测试仍通过
**Patterns to follow:** 现有 `test_infrastructure/`、`test_services/` 目录的测试组织模式
**Test scenarios:**
- 迁移后 `pytest` 全部通过,通过率与迁移前一致
- 根目录无散落测试文件
- 4 个重复文件已删除
- CI 中 `pytest tests/` 发现并运行全部测试
**Verification:** `pytest tests/` 通过,`find tests/ -maxdepth 1 -name "test_*.py"` 返回空
---
### U8. Coverage Configuration and Config Consistency
**Goal:** 配置后端测试覆盖率报告,确保配置文件一致性
**Requirements:** R12, R13, R14, R15
**Dependencies:** U7
**Files:**
- `backend/pyproject.toml` — 添加 pytest-cov 配置
- `backend/requirements.txt` — 确认 pytest-cov 已存在
- `backend/app/config.py` — U3 中已修复 REDIS_URL
- `.env.production.example` — U3 中已补充变量
- `frontend/next.config.mjs` — U3 中已修复构建检查
**Approach:**
1.`pyproject.toml``[tool.pytest.ini_options]` 中添加 `addopts = "--cov=app --cov-report=term-missing --cov-report=html"`
2. 添加 `[tool.coverage.run]` 配置 omit 列表排除测试文件、migrations 等)
3. 验证 `pytest-cov` 已在 requirements.txt 中
4. 确认 U3 中的配置修复REDIS_URL、.env.production.example、next.config.mjs已生效
**Patterns to follow:** pytest-cov 标准配置模式
**Test scenarios:**
- `pytest --cov=app` 生成覆盖率报告
- 覆盖率报告排除 migrations 和测试文件
- HTML 覆盖率报告可正常打开查看
- CI 中覆盖率步骤正常工作
**Verification:** `pytest --cov=app` 成功生成覆盖率报告,显示各模块覆盖率百分比
---
## Scope Boundaries
**In scope:**
- Agent 注册补全
- Docker 生产镜像优化和健康检查
- CI/CD 流水线修复
- Sentry 监控接入
- 测试文件迁移和清理
- 配置一致性修复
**Deferred for later:**
- 真实微信/支付宝 SDK 商户密钥配置(需外部资质审批)
- Redis 连接池统一管理(当前多模块各自创建连接,功能正常但不够优雅)
- 前端组件测试和页面级单元测试(当前仅 13 个单元测试,覆盖面窄)
- Playwright 移动端设备测试项目
- 性能/负载测试框架Locust/k6搭建
- 视觉回归测试
- 生产环境域名和 HTTPS 配置
- 前端 `images.unoptimized` 评估
**Outside this plan:**
- 新功能开发
- 代码重构(除测试文件迁移外)
- UI 打磨
---
## Risks & Dependencies
- **Sentry DSN 需要 Sentry 项目创建。** 如果团队尚未创建 Sentry 项目,需要先注册并获取 DSN。缓解DSN 为空时 SDK 自动禁用,不阻塞开发。
- **Docker 镜像拆分可能影响 CI E2E 测试。** CI 的 docker-compose 需要使用 `target: e2e` 而非 `target: runtime`。缓解U6 中同步更新 CI 配置。
- **测试文件迁移可能引入 import 路径问题。** 迁移后 pytest 可能找不到某些 fixture 或 conftest。缓解U7 中先记录基线再迁移,逐个验证。
- **next.config.mjs 启用类型检查可能导致构建失败。** 前端代码可能存在未修复的类型错误。缓解:先运行 `npx tsc --noEmit` 检查类型错误数量,如果过多则分批修复。
---
## Open Questions
**Deferred to implementation:**
- Sentry 项目是否已创建?团队使用 SaaS 还是自托管?
- CI runner 环境GitHub Actions 还是自建 Runner
- 前端 TypeScript 类型错误数量——决定是否需要分批修复
---
## Sources & Research
- `docs/plans/2026-06-02-007-chore-geo-launch-sprint-plan.md` — 上线冲刺计划status: completed
- `docs/plans/2026-06-01-005-chore-geo-tech-debt-cleanup-plan.md` — 技术债清理计划status: completed
- `docs/plans/2026-05-31-002-test-quality-assurance-system-plan.md` — 测试质量保障体系status: active
- `backend/app/agent_framework/agents/__init__.py` — 仅导出 5/8 个 Agent
- `backend/Dockerfile` — runtime 阶段包含 Playwright+Chromium
- `docker-compose.prod.yml` — 缺少 backend/frontend healthcheck
- `.github/workflows/ci.yml` — CI 流水线配置
- `.github/workflows/pr-check.yml` — PR 检查工作流(步骤 ID 引用失效)
- `backend/app/config.py` — REDIS_URL 默认值不含密码
- `backend/app/middleware/metrics.py` — 2 处 Sentry TODO
- `frontend/components/ErrorBoundary.tsx` — 1 处 Sentry TODO
- `backend/tests/` — 11 个根目录散落测试文件4 个与子目录重复