03 · Deployment

部署与 CI/CD

推 main → 自动上线。但「自动」不等于「不用看」—— 这一页讲清楚部署链路、必须遵守的验证规范、以及出问题时怎么回滚。

部署流水线

① Push to main

本地直接推 main 即可(2 人团队约定);或 PR 合并触发

② CI Checks

type-check + lint + unit/integration test,失败则停

~3 min

③ Docker Build

buildx + GHA cache;NEXT_PUBLIC_* 通过 build-args 注入

~4 min

④ DB Migrate

显式pnpm db:migrate,否则线上 schema 落后

~30s

⑤ Fly Deploy

滚动更新 app + worker;新机器健康后旧机下线

~2 min

CI 与 Docker 构建并行执行,整体约 7-9 分钟。

硬规矩 · CLAUDE.md 全局规则: git push 后必须确认 CI 通过才能告诉用户"已部署"。
1. gh run list --limit 1 看最新状态;
2. 若 in_progress 等完成;若 failure 用 gh run view <id> --log-failed 查原因;
3. 最后 curl https://www.softie.ai/<path> 验证生产文件包含改动(CDN 可能没刷新)。

所有 GHA Workflows

fly-deploy.yml push: main
主部署 workflow。CI(type-check / lint / test)与 Docker 构建并行;Docker 用 GHA cache 加速;构建完成后滚动部署到 Fly.io。dev app(softieweb-dev)当前未启用,2 人团队 localhost 开发即可。
pr-checks.yml pull_request
PR 必须通过的检查:type-check + ESLint + 单元测试。是合并前的最后一道。
claude.yml @claude mention
PR 评论里 @claude 可触发 Claude Code Action 做代码审查。CLAUDE.md 全局规则:所有 PR 必须有 Claude 自动审查;high-risk 评论必须人工 ack。
claude-code-review.yml PR opened
PR 一开就自动跑 Claude review,标注 risk 并 inline 评论。
payment-health-cron.yml cron: */15 * * * *
每 15 分钟从 PostHog 拉支付事件,计算转化率;阈值跌破推 Pay-Bot 卡片告警。设计目标:「24h 0 转化」级别故障在 15 分钟内抓到。脚本:scripts/check-payment-health.ts
payment-reconcile-cron.yml cron / 周期
把 webhook 漏掉的订单从 Airwallex/Stripe API 补回 DB。崩了会推 Pay-Bot。原本是 Vercel cron,2026-04-23 迁到 GHA(清理 Vercel 影子部署)。
daily-data-monitor.yml cron: 30 2 * * * (10:30 BJT)
每日数据监控管道 v2:Clarity 5 路并行 + PostHog 16 事件漏斗 + Meta Ads + 结构化需求引擎;输出到 Bitable + Lark 卡片 + AI 建议。失败会推 Lark 告警。同时跑队列深度检查(waiting>200/1000、failed>50/200 时告警)。
daily-cost-report.yml cron: 每天 10:00
8 大服务费用汇总(OpenRouter / fal / R2 / Fly / Sentry / Langfuse / OneSignal / Clarity)→ Cost-Bot 卡片。脚本在 ~/scripts/ 全局,crontab 触发,与项目独立。
clarity-daily-report.yml cron 每日
单独的 Clarity 录屏数据日报,作为日报备援。
db-backup.yml cron 每日
PostgreSQL 全量备份;落到对象存储。
email-retention-cron.yml cron 每日
用户留存邮件触达(沉默 N 天召回)。
status-monitor.yml cron 短间隔
关键 endpoint 200 + payload 字段在位检查;CDN 缓存验证;上线后 5 分钟内自动跑(CLAUDE.md 全局要求)。
security-audit.yml push / cron
依赖漏洞扫描;secrets 泄漏检查。
lark-notify.yml workflow_call
复用型 workflow:被其他 workflow 调用统一推 Lark 卡片。Bot 路由见 Observability

fly.toml 关键点

回滚操作

代码回滚(推荐)

# 找上一个 good commit
git log --oneline --all -20

# 回滚 commit 并推
git revert <bad-sha>
git push origin main
# CI 走完即生效

Fly.io release rollback

fly releases list -a softieweb
fly releases rollback <version> -a softieweb

这只回滚 Docker 镜像,不回滚 DB。如果 migration 已经跑了 destructive 改动(drop column 等),必须先 restore 备份再回滚镜像。

Cloudflare 缓存清理

# Dashboard: Caching → Configuration → Purge Everything
# 或用 API(token 在记忆库 reference_cloudflare_token.md)

部署后必查清单

  1. gh run list --limit 1 → CI success
  2. fly status -a softieweb → 所有机器 passing
  3. curl https://www.softie.ai/api/health(如有)或关键页面 → 200 + 改动内容在 HTML 里
  4. 看 Sentry 5 分钟内有没有新 issue 涌入
  5. 看 Pay-Bot / Cost-Bot 群有没有异常告警
  6. 动了支付:在 demo 账号跑一次 end-to-end

常见坑(部署相关)

症状真相修法
新代码部署后线上行为没变 Cloudflare 橙云 CDN 缓存(24h+) Purge Everything;或在 Cloudflare 侧加 Cache Rule override
线上 42703 column does not exist Fly 部署不会自动跑 migration fly ssh console 进容器跑 pnpm db:migrate;后续 GHA 显式加这一步
NEXT_PUBLIC_FOO 在生产是 undefined fly.toml 的 build-args 没同步到 GHA workflow .github/workflows/fly-deploy.yml 的 build-push-action 里也加一份
Docker 构建慢(10+ 分钟) BuildKit mount cache 在 GHA 无效 actions/cachecache-from/cache-to: type=gha
新 secret 写了 GHA workflow 但运行时空值 ${{ secrets.FOO }} 引用不代表 secret 已配置 gh secret list 确认存在再触发;不要相信 workflow 文件
fly scale 后内存没变 命令可能不持久 事后 fly status 验证;混合机型必须逐台求和
Vercel 莫名其妙又部署了一份 旧账号 GitHub App 没卸载,影子部署 Vercel 控制台 disconnect + GitHub Settings → Apps 卸载 fly-io app

禁止操作

← 上一篇
02 · 本地开发环境