419 lines
18 KiB
Markdown
419 lines
18 KiB
Markdown
---
|
||
title: "chore: GEO Platform Production Readiness — Final Mile to Deployable"
|
||
type: chore
|
||
status: active
|
||
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 并安装 Playwright,CI 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:** U2(Docker 镜像拆分后 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:** U6(CI 修复后再迁移,避免 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 个与子目录重复
|