跳转至

DIP1 技术基础设施设计

文档编号:DOC-D01-D3 / 简称:DIP1-P3 版本:V1.1 创建日期:2026-08-09 最近更新:2026-08-09 维护人:TL / DT 关联文档PJMDIP1-ARC 架构设计 V2.0DIP1-P1DIP1-P2 V2.0

V1.1 变更(对齐 DIP1 原生 App 方案 ADR-002/006/007/008):① §1.1 工具链新增 Expo CLI / EAS CLI / watchman / Xcode / Android Studio;② §1.2 Windows 初始化脚本增加 Expo/EAS 安装与登录步骤;③ §1.3 .env.example 新增 EXPO/EAS/推送/移动端认证变量组,飞书变量标注⏸ 暂不实施;④ §三 CI/CD 新增 EAS Build/Submit/Update Job + 移动端流水线子图;⑤ §四 测试策略新增 Detox RN E2E + Jest RN 单测;⑥ §五 部署架构新增 App Store Connect / Google Play Console 发布通道 + Expo Updates OTA 热更新 + 推送服务(APNs+FCM);⑦ §六 可观测新增 Sentry RN SDK + 移动端 APM(启动时间/崩溃率/屏幕 FPS)+ 推送送达率指标;⑧ ADR 表新增 ADR-011 Expo managed workflow、ADR-012 NativeWind、ADR-013 EAS Build 云端构建。


一、开发环境配置

1.1 工具链版本

工具 版本 安装方式 说明
Python 3.12.x pyenv / 官网 最低 3.11,推荐 3.12(性能 + 类型提示优化)
Node.js 20 LTS fnm 与 Next.js 14 + Expo SDK 51 兼容
pnpm 9.x corepack enable 前端 monorepo 包管理器(比 npm/yarn 快)
PostgreSQL 16.x Docker 官方镜像,JSONB 性能最佳
Redis 7.2 Docker 缓存 + 队列 + 会话
Docker Desktop 4.x 官网 Windows/macOS 本地开发容器
Direnv 2.x winget / brew 自动加载 .envrc 环境变量
【V1.1 新增】Expo CLI 0.18.x npm i -g expo-cli React Native + Expo managed workflow 开发工具
【V1.1 新增】EAS CLI 13.x npm i -g eas-cli Expo Application Services 云端构建/提审/OTA
【V1.1 新增】watchman 4.9.x brew / 官网 RN 文件监听(macOS/Linux 必需,Windows 可选)
【V1.1 新增】Xcode 15.4+ Mac App Store iOS 构建(仅 macOS;CI 走 EAS Build 云端,本地非必需)
【V1.1 新增】Android Studio Hedgehog+ 官网 Android 构建(仅模拟器/真机调试用;CI 走 EAS Build 云端)
【V1.1 新增】Apple Developer 账号 TL 提供 App Store 上架(年费 $99;TL 持有,Code Agent 用 EAS Submit 调用凭据)
【V1.1 新增】Google Play Console TL 提供 Google Play 上架(一次费 $25;TL 持有 Service Account JSON)

1.2 Windows 本机开发一键初始化

文件dip1/scripts/dev/setup-dev.ps1(PowerShell)

<#
.SYNOPSIS DIP1 开发环境初始化(Windows,管理员权限运行一次)
#>
# 1. 安装工具链(winget 前提)
winget install -e --id Python.Python.3.12
winget install -e --id CoreyButler.NVMforWindows
winget install -e --id Docker.DockerDesktop
winget install -e --id direnv.direnv
# 2. 启用 pnpm corepack
corepack enable
corepack prepare pnpm@9.15.0 --activate
# 3. Python venv 创建
cd dip1/backend
py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt -r requirements-dev.txt
# 4. 前端依赖安装(V1.1:含 wkr-app + cst-app RN 包)
cd ../frontend
pnpm install
# 5. 【V1.1 新增】Expo/EAS CLI 全局安装 + 账户登录
npm install -g expo-cli eas-cli
expo login  # TL 提供 DIP1 Expo 账户凭据
# 6. 【V1.1 新增】配置 EAS 项目(双端各一份 eas.json)
cd apps/wkr-app && eas build:configure && cd ../..
cd apps/cst-app && eas build:configure && cd ../..
# 7. 预提交钩子
cd ../..
pre-commit install
Write-Host "✅ DIP1 开发环境初始化完成,请重启终端后运行:docker compose up -d"
Write-Host "✅ RN 开发:cd frontend/apps/wkr-app && pnpm start(Expo DevTools)"

1.3 环境变量模板(.env.example)

# ====== 基础 ======
ENV=dev                        # dev / staging / prod
TZ=Asia/Hong_Kong
APP_SECRET_KEY=change-me-to-32bytes-random

# ====== PostgreSQL ======
DATABASE_URL=postgresql+asyncpg://dip1:dip1pass@localhost:5432/dip1_dev

# ====== Redis ======
REDIS_URL=redis://localhost:6379/0

# ====== Cloudflare R2(对象存储,S3 兼容)======
R2_ACCOUNT_ID=xxxxxxxxxxxxxxxx
R2_ACCESS_KEY_ID=xxxxxxxxxxxxxxxx
R2_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxx
R2_BUCKET=dip1-assets-dev
R2_PUBLIC_URL=https://assets-dev.weavely.hk

# ====== ⏸ 飞书开放平台(V1.1:阶段 1 暂不实施,保留占位)======
# FEISHU_APP_ID=cli_xxxxxxxxxxxx
# FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# FEISHU_BITABLE_APP_TOKEN=bascnXXXXXXXXXXXX
# FEISHU_WEBHOOK_VERIFY_TOKEN=xxxxxxxxxxxx
# FEISHU_WEBHOOK_ENCRYPT_KEY=xxxxxxxxxxxxxxxx

# ====== 【V1.1 新增】Expo / EAS(TL 提供 DIP1 Expo 账户)======
EXPO_USERNAME=weavely-dip1
EXPO_PROJECT_ID_WKR=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
EXPO_PROJECT_ID_CST=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
EAS_PROJECT_ACCOUNT=weavely-dip1

# ====== 【V1.1 新增】推送服务(APNs + FCM via Expo Notifications)======
EXPO_PUSH_AUTH_TOKEN=ExponentPushToken_dev_only_xxxxxxxxxxxxx
# 生产环境由 EAS 自动注入 Expo push 凭据;开发环境用 ExpoPushToken[xxx] 格式即可测试

# ====== 【V1.1 新增】移动端认证 ======
JWT_ACCESS_TTL_SECONDS=900        # access token 15 分钟
JWT_REFRESH_TTL_SECONDS=2592000    # refresh token 30 天
OTP_TTL_SECONDS=300                # WhatsApp OTP 5 分钟
OTP_RATE_LIMIT_PER_HOUR=5          # OTP 限流 5 次/小时
BIOMETRIC_REQUIRED=false           # 是否强制生物识别(生产可设 true)

# ====== AI 听写助手(OPS-D 用)======
DT_API_BASE=https://api.trae.ai
DT_API_KEY=sk-xxxxxxxxxxxx
DT_MODEL=trae-gpt

# ====== 可观测 ======
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317  # OpenTelemetry
SENTRY_DSN=https://xxx@sentry.io/xxx              # 后端 + RN 双端共用
SENTRY_DSN_WKR=https://xxx@sentry.io/xxx          # 【V1.1】wkr-app RN 专用(可同 SENTRY_DSN)
SENTRY_DSN_CST=https://xxx@sentry.io/xxx          # 【V1.1】cst-app RN 专用(可同 SENTRY_DSN)
LARK_WEBHOOK_ALERT=https://open.feishu.cn/open-apis/bot/v2/hook/xxx  # 飞书告警群机器人

1.4 本地一键启动(docker-compose.yml)

文件dip1/docker-compose.yml

services:
  postgres:
    image: postgres:16-alpine
    ports: ["5432:5432"]
    environment:
      POSTGRES_USER: dip1
      POSTGRES_PASSWORD: dip1pass
      POSTGRES_DB: dip1_dev
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./scripts/db/init-dev.sql:/docker-entrypoint-initdb.d/10-init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dip1"]
      interval: 5s

  redis:
    image: redis:7.2-alpine
    ports: ["6379:6379"]
    command: redis-server --save 60 1 --loglevel warning

  # 邮件/短信本地捕获(dev 用,避免发真消息)
  mailpit:
    image: axllent/mailpit:latest
    ports: ["1025:1025", "8025:8025"]  # SMTP / Web UI

  # 本地 OpenTelemetry + Jaeger(trace 调试)
  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "4317:4317"   # OTLP gRPC
      - "16686:16686" # Jaeger UI

volumes:
  pgdata:

二、Git 分支策略(对齐 PJM §4.3 Git Flow Lite)

2.1 分支模型

与主项目(hk2026)策略一致,但 dip1/ 子目录采用更细的粒度:

gitGraph
    commit id: "init" tag: "v0.0.0"
    branch dev
    commit id: "dev-start"
    branch feat/qsv-engine
    commit id: "qsv-1"
    commit id: "qsv-2"
    checkout dev
    merge feat/qsv-engine id: "merge-qsv"
    branch feat/cpt-lifecycle
    commit id: "cpt-1"
    commit id: "cpt-2"
    checkout dev
    merge feat/cpt-lifecycle id: "merge-cpt"
    branch release/v0.1.0
    commit id: "rc1" tag: "v0.1.0-rc1"
    commit id: "fix-rc1-bug"
    checkout main
    merge release/v0.1.0 id: "release-0.1" tag: "v0.1.0"
    branch hotfix/auth-security
    commit id: "security-patch"
    checkout main
    merge hotfix/auth-security id: "merge-hotfix" tag: "v0.1.1"
    checkout dev
    merge hotfix/auth-security id: "backport-hotfix"
分支 命名 生命周期 保护规则
main 固定 永久 ✅ 保护:仅 PR squash merge,CI 全绿
dev 固定 永久 ✅ 保护:仅 PR merge,CI 全绿
feat/* feat/jira-id-简述feat/领域-功能 开发期 < 2 周,合并即删 ❌ 无保护,可强制推送
fix/* fix/缺陷编号-简述 同上 ❌ 同上
release/vX.Y.Z 语义化版本 RC → 发布期间 ✅ 发布期保护,仅修 bug
hotfix/* hotfix/vX.Y.Z+1-简述 紧急修复,合并双端(main+dev) ❌ 无保护

2.2 提交规范(Conventional Commits)

<type>(<scope>): <subject>

<body>

<footer>

typefeat 新功能 / fix 修复 / docs 文档 / refactor 重构 / perf 性能 / test 测试 / chore 构建工具 / migrate 数据库迁移
scope(可选):qsv / cpt / mds / ops / auth / ops-admin / wkr-app / infra

示例:

feat(qsv): 新增 QMD 8 大类参数自动计算

- 实现 base_fee × 8 因子 = subtotal 的公式(对齐 QMD V2.1 §3)
- 新增封顶价保护:final_amount = MIN(subtotal - discount, cap_price)
- 新增 QuoteParamProvider 端口对接 MDS SCL/BPL

Closes: DIP1-42

2.3 PR 准入 Checklist(合并 gate)

## ✅ PR Checklist

- [ ] 已通过 `pre-commit run --all-files`(ruff/mypy/black)
- [ ] 单测覆盖率 ≥ 新增代码的 80%(`pytest --cov-report=term-missing`)
- [ ] API 变更已同步更新 OpenAPI spec 并上传 Swagger UI 预览
- [ ] DB 迁移已生成 Alembic 脚本,且 upgrade/downgrade 双向验证通过
- [ ] 文档 README / ADR 已更新(涉及架构决策时)
- [ ] 权限矩阵已更新(涉及 auth/role 变更时)

三、CI/CD 流水线

3.1 流水线架构(V1.1:后端 Web + 移动端 RN 三轨)

采用 GitHub Actions(主)+ 自建 Runner(香港低延迟)+ EAS Build(云端 RN 构建) 三模式:

flowchart LR
    subgraph Local["开发者本地"]
        PRE["pre-commit<br/>ruff/mypy/black/eslint"]
    end
    subgraph GHA["GitHub Actions CI(后端 + Web)"]
        LINT["Lint Check<br/>ruff + eslint"]
        TEST_BE["后端测试<br/>pytest (Testcontainers)"]
        TEST_FE["Web 测试<br/>vitest + playwright"]
        MIG["迁移校验<br/>alembic up+down"]
        BUILD_BE["后端镜像<br/>docker build"]
        BUILD_FE["Web 产物<br/>next build"]
        SCAN["安全扫描<br/>trivy + npm audit"]
    end
    subgraph EAS["【V1.1 新增】EAS Build(移动端 RN 云端构建)"]
        RN_TEST["RN 单测<br/>Jest wkr-app + cst-app"]
        RN_DETOX["RN E2E<br/>Detox 双端主流程"]
        EAS_BUILD["EAS Build<br/>iOS + Android × 双端 = 4 artifact"]
        EAS_SUBMIT["EAS Submit<br/>App Store + Google Play 提审"]
        EAS_UPDATE["EAS Update<br/>OTA JS Bundle 热更新"]
    end
    subgraph Staging["Staging 香港 VPS"]
        DEPLOY_S["Fly.io / 自建<br/>docker compose up"]
        SMOKE["冒烟测试<br/>50+ E2E API"]
    end
    subgraph Prod["生产环境"]
        DEPLOY_P["蓝绿部署<br/>10%/50%/100% 灰度"]
        APP_STORE["App Store + Google Play<br/>上架发布"]
    end

    Local -->|"push feat/*"| LINT
    LINT --> TEST_BE & TEST_FE & MIG & RN_TEST
    TEST_BE --> BUILD_BE
    TEST_FE --> BUILD_FE
    RN_TEST --> RN_DETOX
    BUILD_BE --> SCAN
    BUILD_FE --> SCAN
    SCAN -->|"merge dev"| DEPLOY_S
    DEPLOY_S --> SMOKE
    SMOKE -->|"tag release"| DEPLOY_P
    SMOKE -->|"tag release"| EAS_BUILD
    RN_DETOX --> EAS_BUILD
    EAS_BUILD --> EAS_SUBMIT
    EAS_SUBMIT --> APP_STORE
    EAS_BUILD -.->|"JS 变更 only"| EAS_UPDATE
    EAS_UPDATE -.->|"OTA 推送"| APP_STORE

3.2 CI 工作流文件(dip1/.github/workflows/ci.yml + dip1/.github/workflows/eas.yml

核心步骤清单(完整 YAML 见实际文件):

Job 触发 耗时 关键动作
lint 每次 push PR 1min ruff check backend/;eslint frontend/;hadolint Dockerfile
test-backend 每次 push PR 8min Testcontainers 起 PG+Redis → pytest → 上传 coverage 到 Codecov
test-frontend-web 每次 push PR 10min pnpm install → vitest(opr-admin)→ Playwright 10 条 E2E 冒烟
【V1.1】test-rn 每次 push PR 6min pnpm install → Jest wkr-app + cst-app 单测 → 覆盖率 ≥ 70%
【V1.1】e2e-detox 修改 frontend/apps/* RN 代码时 12min Detox iOS 模拟器跑 wkr-app + cst-app 各 1 条 L1→L8 主流程
db-migrate-check 修改 alembic/versions 时 3min 创建临时空库 → upgrade head(含 0001+0002)→ downgrade base → 二次 upgrade 无错
security-scan main/dev push + 每日 5min Trivy 镜像漏洞 + pip-audit + pnpm audit → 飞书告警高危
build-and-push tag v* + main push 12min docker buildx 多架构 → 推送到阿里云香港 ACR
【V1.1】eas-build tag v* + main push 25min eas build --platform ios --profile production × 2(wkr+cst)+ --platform android × 2 = 4 artifact(云端并行约 25 分钟)
【V1.1】eas-submit eas-build 成功后 10min eas submit -p ios(App Store Connect API Key)+ eas submit -p android(Google Play Service Account JSON)→ 自动提审
【V1.1】eas-update dev push + 仅 JS 变更时 3min eas update --branch production 推送 JS Bundle → App 自动检测 OTA 更新
deploy-staging dev merge + schedule(每日 09:00) 5min SSH 到 staging 机 → docker compose pull && up -d
smoke-staging staging deploy 后 3min newman 跑 Postman 50 条 API 冒烟集 + Lighthouse 分数

OTA 热更新策略(V1.1):仅 JS Bundle 变更走 OTA(无需重新提审);原生模块变更(如新增/升级 expo-camera 版本、修改 app.json 中 ios/android 配置)必须 EAS Build 重新构建并提审。GitHub Actions 中通过 git diff 检测是否触及 ios/android/app.json、原生模块依赖,自动选择 OTA 或 Build 通道。

3.3 版本号与发布节奏

  • 语义化版本vMAJOR.MINOR.PATCH(v2.0.0 / v2.0.1 ... v2.1.0 含原生模块升级)
  • 发布节奏
  • dev:每次 PR 合并 → 自动部署 staging;JS 变更 → EAS Update OTA 推送 staging 通道
  • release/*:每 2 周一个 release candidate,UAT 3 天;EAS Build 生产 profile 构建双端
  • main:每月一个生产版本,第二周周二生产发布;App Store + Google Play 同步上架
  • Changeloggit-cliff 基于 Conventional Commits 自动生成 CHANGELOG.md
  • 【V1.1】App 审核节奏:App Store 审核 24-48h;Google Play 几小时~1 天;提审被拒记录到 DWLG(CROSS 类型 Issue 给 TL)

四、测试策略

4.1 测试金字塔(V1.1:三端分离)

              ▲
             / \
            /E2E\   顶层:
           /     \     · Web:10~20 条 Playwright(opr-admin 11 屏基线,5 分钟)
          /-------\    · 【V1.1】RN:Detox wkr-app + cst-app 各 1 条 L1→L8 主流程(10 分钟/端)
         /         \
        /Integration\  中层:
       /-------------\    · 50~100 条 API 集成测试(Testcontainers,8 分钟)
      /               \   · 【V1.1】6 域 × ≥15 条 + 144 RBAC 越权 = ≥240 条
     /  Unit           \ 底层:
    /-------------------\   · 后端:300+ 条领域/应用层单元测试(< 2 分钟)
   /                     \  · 【V1.1】RN:Jest wkr-app + cst-app hooks/组件单测(< 1 分钟)
  /-----------------------\

4.2 各层测试要求

测试层 框架 覆盖率目标 示例
单元测试(Domain + Application) pytest + hypothesis 80% test_quote_recalculate_cap_price()test_order_transition_l4_ok()
单元测试(纯函数) parametrize 100% Money.__add__Factor 数学运算
仓储集成测试 pytest + Testcontainers PG 90% test_quote_repo_add_and_get()、filter/分页场景
API 集成测试 FastAPI TestClient + Testcontainers 90% POST /api/v1/qsv/quotes 全参数组合;RBAC 越权 403;CST RLS 18 条
【V1.1】RN 单元测试 Jest + @testing-library/react-native 70% useOfflineQueue hook、QuotePreview 组件渲染、OTPInput 交互
【V1.1】RN 组件快照 Jest snapshot N/A wkr-app 8+ 页 + cst-app 8 页关键组件快照(防 UI 回归)
【V1.1】飞书对接契约测试 pytest + respx mock ⏸ 暂不实施 阶段 1 启动时启用;DIP1-P1 所有 API 响应体 mock
E2E 冒烟(Web) Playwright + 10 条核心路径 N/A L1 新建 → L3 报价 → L4 派单 → L6 安装 → L8 回访 NPS(opr-admin)
【V1.1】E2E 冒烟(RN) Detox + iOS/Android 模拟器 N/A wkr-app:L4→L6(6S 勾选+原生相机拍照)→L7→L8;cst-app:询价→报价→下单→L8 评价→推荐分享
性能基准 locust 50 VU + Detox 性能模式 吞吐量 ≥ 200 RPS;启动 ≤ 2s GET /api/v1/cpt/orders 分页;POST /qsv/quotes 计算;RN 冷启动时间
安全回归 OWASP ZAP 被动扫描 高危 0 个 SQLi / XSS / JWT 伪造越权;【V1.1】refresh token 轮换漏洞、OTP 暴力破解

4.3 数据库迁移回滚测试

强制规则:每个 Alembic 迁移脚本必须通过:

# 脚本自动验证 3 轮循环:base → head → base → head → base → head
python scripts/migration/verify_up_down_loop.py --revision <REV_ID> --loops 3
# 任何一轮失败 → 不允许合并 PR

4.4 测试命令速查

# 仅单测(<2min,开发时高频跑)
cd backend && pytest tests/domain tests/application -x --tb=short

# 集成测试(<8min,PR 前跑)
pytest tests/infrastructure tests/interfaces --testcontainers

# 覆盖率报告
pytest --cov=app --cov-report=html:htmlcov --cov-report=term-missing

# 前端 Web 测试
cd frontend && pnpm vitest run          # opr-admin 单测
pnpm playwright test --project=chromium  # Web E2E

# 【V1.1】RN 测试
cd frontend/apps/wkr-app && pnpm test           # Jest 单测
cd frontend/apps/cst-app && pnpm test           # Jest 单测
cd frontend/apps/wkr-app && pnpm detox:test:ios   # Detox E2E(iOS 模拟器)
cd frontend/apps/cst-app && pnpm detox:test:ios   # Detox E2E(iOS 模拟器)

# 全量 CI 模拟(本地提交前最后一道门)
make ci-local   # ≈ ruff + mypy + 单测 + 迁移校验 + RN Jest

五、部署架构

5.1 生产部署拓扑(V1.1:香港后端 + App Store/Google Play + Expo Updates)

flowchart TB
    subgraph CF["Cloudflare CDN"]
        WAF["WAF / Bot Management"]
        CDN["静态资源缓存<br/>JS/CSS/图片(R2)"]
    end

    subgraph HK["香港阿里云 VPC(可用区 B+C 双 AZ)"]
        LB["ALB 负载均衡(HTTPS 卸载)"]

        subgraph App["应用集群(2-4 台 ECS,按需弹性)"]
            API1["FastAPI worker x2<br/>(gunicorn + uvicorn)"]
            API2["FastAPI worker x2"]
            WORKER["Celery Beat + Worker x1<br/>(异步任务/推送发送)"]
        end

        subgraph Data["数据层高可用"]
            PG["PostgreSQL 16<br/>主从半同步<br/>(跨 AZ)"]
            REDIS["Redis 7 哨兵<br/>3 节点<br/>(跨 AZ)"]
        end
    end

    subgraph R2["Cloudflare R2 Storage"]
        ASSETS["附件/照片<br/>L6 现场/签字照"]
    end

    subgraph PUSH["【V1.1】推送服务"]
        EXPO_PUSH["Expo Notifications<br/>统一 APNs + FCM"]
    end

    subgraph APPS["【V1.1】App 发布与热更新"]
        APPSTORE["App Store Connect<br/>wkr-app + cst-app iOS"]
        GOOGLEPLAY["Google Play Console<br/>wkr-app + cst-app Android"]
        EXPO_UPDATE["Expo Updates<br/>OTA JS Bundle 热更新"]
    end

    USER_WEB["运营后台用户<br/>(PC Web)"] --> CF
    USER_WKR["【V1.1】师傅<br/>wkr-app RN"] --> APPSTORE
    USER_WKR --> GOOGLEPLAY
    USER_WKR -.->|"OTA 检查"| EXPO_UPDATE
    USER_CST["【V1.1】客户<br/>cst-app RN"] --> APPSTORE
    USER_CST --> GOOGLEPLAY
    USER_CST -.->|"OTA 检查"| EXPO_UPDATE

    CF --> LB
    LB --> API1 & API2
    API1 --> PG & REDIS & R2
    API2 --> PG & REDIS & R2
    WORKER --> PG & REDIS
    WORKER --> EXPO_PUSH
    EXPO_PUSH --> USER_WKR
    EXPO_PUSH --> USER_CST

    APPSTORE --> USER_WKR
    APPSTORE --> USER_CST
    GOOGLEPLAY --> USER_WKR
    GOOGLEPLAY --> USER_CST
    EXPO_UPDATE --> USER_WKR
    EXPO_UPDATE --> USER_CST

5.2 环境规格

环境 计算 数据库 缓存 域名 / App 通道
本地 dev 1 Docker(单容器) PG 16 单节点 Redis 单节点 localhost:3000(Web)/ 8000(API)/ Expo Go(RN)
staging 2C4G × 1 ECS PG 16 单节点 40G SSD Redis 单节点 1G stg-api.weavely.hk / stg-admin.weavely.hk;【V1.1】Expo staging channel + TestFlight 内测 + Google Play 内部测试轨道
prod 4C8G × 2~4 ECS(弹性) PG 16 主从 200G SSD + PITR Redis 哨兵 3 节点 4G api.weavely.hk / admin.weavely.hk;【V1.1】App Store 正式版 + Google Play 正式版 + Expo production channel OTA

5.3 【V1.1】移动端发布流程(EAS Build → Submit → Update)

flowchart LR
    DEV["开发者提交 PR"] --> MERGE["合并 dev 分支"]
    MERGE -->|"JS 变更 only"| OTA["EAS Update<br/>推送 staging channel"]
    MERGE -->|"含原生模块变更"| BUILD_S["EAS Build<br/>development profile"]
    BUILD_S --> TESTFLIGHT["TestFlight + Google Play 内部测试<br/>(FL 5 师傅 + CUS 10 客户内测 7 天)"]
    OTA --> TESTFLIGHT
    TESTFLIGHT -->|"UAT 通过"| TAG["TL 打 tag v2.x.0"]
    TAG --> BUILD_P["EAS Build<br/>production profile<br/>iOS + Android × 双端 = 4 artifact"]
    BUILD_P --> SUBMIT["EAS Submit<br/>App Store Connect + Google Play"]
    SUBMIT --> REVIEW["审核 24-48h"]
    REVIEW -->|"通过"| LIVE["App Store + Google Play 正式上架"]
    REVIEW -->|"被拒"| REJECT["记录 DWLG + 修正 + 重新提交"]
    LIVE --> OTA_P["EAS Update<br/>production channel 后续 OTA"]

关键凭据(TL 持有,Code Agent 通过 EAS CLI 调用,禁止直接接触明文): - Apple Developer 账号 + App Store Connect API Key.eas/credentials/ios.json 加密存储) - Google Play Service Account JSON.eas/credentials/android-service-account.json) - Expo Access Token(CI 环境变量 EXPO_TOKEN,TL 在 GitHub Actions Secrets 配置)

5.4 容器化方案(Dockerfile 多阶段)

后端 dip1/backend/Dockerfile

# --- Builder:编译依赖 ---
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends build-essential
COPY requirements.txt requirements-dev.txt ./
RUN pip install --user --no-cache-dir -r requirements.txt

# --- Runtime:最小化镜像 ---
FROM python:3.12-slim AS runtime
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/*
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH="/root/.local/bin:$PATH"
EXPOSE 8000
HEALTHCHECK --interval=10s CMD curl -f http://localhost:8000/health || exit 1
CMD ["gunicorn", "app.main:create_app()", "-b", "0.0.0.0:8000", \
     "-k", "uvicorn.workers.UvicornWorker", "-w", "2", "--threads", "4"]

【V1.1】RN App 不走 Docker 容器化(Expo managed workflow 由 EAS 云端构建);opr-admin Next.js 走 Cloudflare Pages 静态部署(next build 产物)。

5.5 蓝绿部署与回滚

# Step 1: 发布绿色环境(v2.0.0),不切流量
docker compose up -d --scale api-green=2 api-green
# Step 2: 冒烟绿色环境
curl -H "Host: api.weavely.hk" http://green-internal/health
newman run smoke-tests.postman_collection.json --env-var baseUrl=http://green-internal
# Step 3: 逐步切流量 10% → 50% → 100%(ALB 权重调整)
# Step 4: 观察 30 分钟,指标异常 → 一键回滚
make rollback-blue  # ALB 权重切回蓝色 100%,绿色停服
# Step 5: 成功 → 旧环境保留 24 小时后清理

# 【V1.1】App 回滚(不同于后端):
# App Store:通过 phased release(7 天 1%/2%/5%/10%/20%/50%/100%)中途暂停或完全停止
# Google Play:staged rollout(0.1%/1%/10%/50%/100%)中途可 halt
# OTA 回滚:eas update --branch production --rev <previous-update-id>(即时回滚 JS Bundle)

5.6 备份与容灾

组件 策略 RPO RTO
PostgreSQL pg_basebackup 每日全量 + WAL 归档每 5 分钟到 R2 5 分钟 30 分钟
Redis AOF 每 1 秒 fsync + 每日 RDB 快照到 R2 1 秒 10 分钟
R2 附件 自带 11 9 耐用性 + 跨区域复制 N/A N/A
【V1.1】Expo Updates JS Bundle 版本历史自动保留(最近 30 个) N/A 即时(eas update --rev 回滚)
【V1.1】App Store / Google Play 历史版本保留(App Store 最近 30 个;Google Play 无限) N/A 24h(重新上架旧版本)
配置/密钥 Vault + GitOps 加密存储 N/A 5 分钟

六、可观测与告警

6.1 三支柱(V1.1:后端 + 移动端双视角)

支柱 工具 关键指标/查询
Logs 日志(后端) Python structlog → Loki → Grafana trace_id 串联;ERROR 级自动入告警
【V1.1】Logs 日志(RN) Sentry RN SDK → Sentry Dashboard 崩溃 stack trace + 设备信息(iOS/Android/version); breadcrumbs 自动记录用户操作
Metrics 指标(后端) Prometheus(/metrics)→ Grafana HTTP 4xx/5xx 率、P95 延迟、DB 连接池、QSV 计算耗时、推送送达率
【V1.1】Metrics 指标(RN) Sentry Performance + Expo APM App 启动时间(冷启 ≤ 2s 热启 ≤ 0.5s)、屏幕 FPS、操作响应时间
Traces 链路(后端) OpenTelemetry → Jaeger 单请求跨域耗时分布:API → App → Domain → Repo → DB/Redis
【V1.1】推送监控 push_delivery_logs 表 + Grafana 8 类推送 24h 送达率、点击率、失败重试队列长度

6.2 告警阈值(飞书机器人推送到 TL/OL 群,V1.1 扩展至 12 项)

告警项 阈值 级别 通知对象
API P95 延迟 > 1s,连续 5 分钟 阈值 + 持续 P1 TL
HTTP 5xx 率 > 3% 阈值 P1 TL + OL
DB 连接池使用率 > 85% 阈值 P2 TL
Redis 可用内存 < 20% 阈值 P2 TL
⏸ 飞书 DLQ 队列长度 > 10 条(阶段 1 启动时启用) 阈值 P1 TL + DT
PG 复制延迟 > 30s 阈值 P1 TL
定时巡检同步脚本 2 次未执行 Cron 失败 P2 TL
每日 23:59 当日无异常报告 心跳 信息 BO
【V1.1】RN 崩溃率 > 0.5%(wkr-app + cst-app 合并) 阈值 + 1h 持续 P1 TL
【V1.1】App 启动时间 P95 > 3s 阈值 + 24h 持续 P2 TL
【V1.1】推送送达率 < 95%(24h 窗口) 阈值 P2 TL + OL
【V1.1】App Store / Google Play 审核被拒 事件触发 P2 TL + DT

七、ADR(架构决策记录)摘要(V1.1:新增 ADR-011/012/013)

ADR 决策 替代方案 原因
ADR-001 模块化单体优先,阶段 2 不拆微服务 直接微服务 DDD 模块边界清晰后才拆;团队规模 < 10 人,单体效率高
ADR-002 Python FastAPI 后端 Go Gin / Node.js NestJS 现有团队 Python 熟练;AI 听写助手 Python 生态无缝
ADR-003 Next.js App Router 前端(opr-admin Web) Vue Nuxt React 生态成熟 + TL 熟悉;Web 运营后台 PC 场景体验佳
ADR-004 PostgreSQL + JSONB 存储灵活字段 MongoDB 事务一致性(报价/支付)+ JSONB 性能够,单库上手快
ADR-005 ULID 主键(非自增 ID) UUID v4 / Snowflake 可排序 + 时间前缀 + 无中心节点,比 UUID4 索引紧凑
ADR-006 Testcontainers 集成测试 SQLite / H2 贴近 PG 真实行为(JSONB/Rls/索引),避免"本地过 CI 挂"
ADR-007 Redis Stream 轻量消息总线 RabbitMQ / Kafka 阶段 2 日吞吐 < 1 万条,Redis 已部署,零额外依赖
ADR-008 Cloudflare R2 存附件(零流出费) 阿里云 OSS / 自建 MinIO 香港 CDN 天然近 + R2 零 egress 费,月省 30% 成本
ADR-009 GitHub Actions + 自建 Runner + EAS Build GitLab CI 主项目已在 Gitee/GitHub;Runner 香港部署低延迟;EAS 云端构建免本地 Xcode/Android Studio
ADR-010 PostgreSQL RLS 行级权限 应用层 WHERE 过滤 物理隔离不可绕过;审计合规(师傅只能看自己订单;客户只能看自己订单)
【V1.1】ADR-011 Expo managed workflow(RN 双端) 纯 RN CLI / Flutter EAS Build 云端构建免本地原生工具链;Expo Updates OTA 一站式;Expo Notifications 统一 APNs+FCM;SDK 统一依赖版本减少冲突
【V1.1】ADR-012 NativeWind v4(Tailwind for RN) Tamagui / RN Paper 与 opr-admin 的 Tailwind 语法一致,降低切换成本;V2.0 重写 ADR-002 后前端团队维护负担最小
【V1.1】ADR-013 EAS Build 云端构建 + EAS Submit 自动提审 本地 Xcode + Fastlane + 手动提审 香港团队 Windows 为主无 macOS;云端构建 25min/4 artifact 远优于本地;EAS Submit 自动化提审减少人工失误

修订记录

版本 日期 修订人 修订内容
V1.0 2026-08-09 DT 初始版本:工具链 · Windows 一键初始化 · .env.example · docker-compose · Git Flow Lite · Conventional Commits · CI/CD 8 Job · 测试金字塔 · 香港双 AZ 部署 · 三支柱可观测 · 10 条 ADR
V1.1 2026-08-09 DT 原生 App 方案升级(对齐 ADR-002/006/007/008):① §1.1 工具链新增 6 项(Expo CLI / EAS CLI / watchman / Xcode / Android Studio / Apple Developer + Google Play Console 账号);② §1.2 Windows 初始化脚本新增步骤 5-6(Expo/EAS 安装登录 + 双端 eas.json 配置);③ §1.3 .env.example 新增 4 组变量(Expo/EAS / 推送 / 移动端认证 / Sentry RN DSN 双端);飞书变量注释为⏸ 暂不实施;④ §三 CI/CD 流水线架构图重写为三轨(后端 + Web + RN),新增 4 Job(test-rn / e2e-detox / eas-build / eas-submit / eas-update),OTA 热更新策略说明;⑤ §四 测试金字塔重写为三端分离(Web Playwright + RN Detox + 后端 Testcontainers),各层测试要求新增 RN Jest/快照/Detox E2E;测试命令速查新增 RN 4 条命令;⑥ §五 部署架构拓扑图新增推送服务 + App Store/Google Play + Expo Updates 三个子图;环境规格表新增 App 通道列;§5.3 新增移动端发布流程 Mermaid(EAS Build → Submit → Update)+ 关键凭据说明;§5.5 蓝绿部署新增 App 回滚策略(phased release / staged rollout / OTA rev);§5.6 备份容灾表新增 Expo Updates + App Store/Google Play 历史版本;⑦ §六 可观测三支柱表新增 RN Sentry + Expo APM + 推送监控;告警阈值从 8 项扩展为 12 项(新增 RN 崩溃率/启动时间/推送送达率/审核被拒);⑧ §七 ADR 表新增 ADR-011 Expo managed workflow / ADR-012 NativeWind / ADR-013 EAS Build 云端构建;ADR-009 扩展为含 EAS Build;⑨ 新增修订记录

本文件为 DIP1 技术基础设施设计(DOC-D01-D3 V1.1,对齐原生 App 方案 V2.0),与 DIP1-P1 V1.1(⏸ 暂不实施)、DIP1-P2 V2.0DIP1-ARC V2.0 共同构成完整技术方案。