fix(healthcheck): 生产健康检查 /docs 接受 404,修复 develop push 生产部署回滚 #1646

Merged
xiaoxia merged 1 commits from fix/healthcheck-docs-404 into develop 2026-09-03 15:38:53 +08:00
Owner

问题

每次 develop push 触发生产部署,健康检查因 /docs 返回 404 而超时失败,导致自动回滚。

根因:

  • main.py 第 25 行:docs_url=None if settings.ENVIRONMENT == "production" else "/docs"
  • scripts/ci_production_healthcheck.sh 第 163-168 行:只接受 /docs 返回 200

生产环境禁用了 FastAPI docs,/docs 永远 404,但健康检查把这当作不健康。

修复

/docs 健康检查改为接受 200 或 404

  • 200:staging/其他环境,docs 正常
  • 404:production 环境,API 在正常响应(只是禁用了文档),视为健康
  • 其他(000/5xx):仍视为不健康

关于 nginx 问题

nginx 配置(/etc/nginx/sites-enabled/00-xiaoxia-saas)中的 /docs/openapi.json proxy_pass 不在代码仓库中,需要在业务服务器上单独清理。

影响范围

仅修改 scripts/ci_production_healthcheck.sh,不改变任何业务逻辑。

## 问题 每次 develop push 触发生产部署,健康检查因 `/docs` 返回 404 而超时失败,导致自动回滚。 **根因:** - `main.py` 第 25 行:`docs_url=None if settings.ENVIRONMENT == "production" else "/docs"` - `scripts/ci_production_healthcheck.sh` 第 163-168 行:只接受 `/docs` 返回 200 生产环境禁用了 FastAPI docs,`/docs` 永远 404,但健康检查把这当作不健康。 ## 修复 将 `/docs` 健康检查改为接受 **200 或 404**: - 200:staging/其他环境,docs 正常 - 404:production 环境,API 在正常响应(只是禁用了文档),视为健康 - 其他(000/5xx):仍视为不健康 ## 关于 nginx 问题 nginx 配置(`/etc/nginx/sites-enabled/00-xiaoxia-saas`)中的 `/docs` 和 `/openapi.json` proxy_pass 不在代码仓库中,需要在业务服务器上单独清理。 ## 影响范围 仅修改 `scripts/ci_production_healthcheck.sh`,不改变任何业务逻辑。
xiaoxia added 1 commit 2026-09-03 15:24:34 +08:00
fix(healthcheck): accept 404 for /docs in production health check
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 19s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 26s
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
AI Code Review / AI Code Review (pull_request) Successful in 58s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m11s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 2m6s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m4s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m24s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m55s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 6m38s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 7m20s
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 Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 11s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 36s
f7307842f1
Production sets docs_url=None in main.py (FastAPI), so /docs returns 404.
The health check now treats 404 as healthy (API is responding,
just docs are disabled). 200 still passes for staging/other envs.
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:否
  • 阻塞级问题数量:0 个

📊 审查概览

  • 整体评价:通过
  • 建议级问题数量:0 个

🔴 阻塞级问题(必须修复)

💡 改进建议(不阻塞合并)

良好实践

  1. 逻辑调整合理:针对生产环境禁用 API 文档(/docs)的场景,正确地将 404 状态码纳入健康检查的通过条件,符合实际部署需求。
  2. 注释清晰:新增的注释清楚地解释了为什么在生产环境中接受 404 状态码,有助于后续维护人员理解逻辑。
  3. 日志完善:在日志中输出具体的 HTTP 状态码,便于排查问题。
  4. 异常处理健壮:保留了 || echo "000" 的兜底逻辑,确保在 curl 命令本身执行失败(如网络超时、DNS解析失败)时,脚本不会因变量为空而误判,且能正确触发检查失败(因为 000 不等于 200 或 404)。

🤖 由 AI 代码审查机器人自动生成 | 2026-09-03 07:25:30 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:0 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 无 ### ✅ 良好实践 1. **逻辑调整合理**:针对生产环境禁用 API 文档(/docs)的场景,正确地将 404 状态码纳入健康检查的通过条件,符合实际部署需求。 2. **注释清晰**:新增的注释清楚地解释了为什么在生产环境中接受 404 状态码,有助于后续维护人员理解逻辑。 3. **日志完善**:在日志中输出具体的 HTTP 状态码,便于排查问题。 4. **异常处理健壮**:保留了 `|| echo "000"` 的兜底逻辑,确保在 curl 命令本身执行失败(如网络超时、DNS解析失败)时,脚本不会因变量为空而误判,且能正确触发检查失败(因为 000 不等于 200 或 404)。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-03 07:25:30 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1646 | | 预览链接 | [https://pr-1646.preview.xiaoxiajianji.com](https://pr-1646.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia merged commit 5cdaa29511 into develop 2026-09-03 15:38:53 +08:00
xiaoxia deleted branch fix/healthcheck-docs-404 2026-09-03 15:38:56 +08:00

🗑️ 预览环境已清理

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

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

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