Files
xmwork/playbooks/casdoor-upstream-rebase.md
gongzhiyong b39fbddd84 feat: add 5 more team assets (upstream sync, migration review, pre-commit hook)
Commands:
- /sync-upstream [--dry-run]   — casdoor-internal upstream sync with commit classification
- /check-migrations [repo|all] — Alembic/Prisma/Drizzle consistency checker (focuses on xiaoshou pending migrations)

Specialist agents:
- migration-reviewer — Critical/High/Low severity review for DB schema changes across
  all 6 repos (Alembic, Prisma, Drizzle, xorm Sync2, raw SQL)

Playbooks:
- playbooks/casdoor-upstream-rebase.md — quarterly upstream rebase flow
  with commit classification, batched merging, cross-repo JWT compat check, rollback criteria

Hooks (active by default via settings.json):
- .claude/hooks/pre-commit-check.sh — PreToolUse on Bash:
  * blocks inline secrets in command strings (10+ patterns: sk-ant-, ghp_, AKIA, PEM, etc.)
  * on git commit, scans staged diff for same patterns
  * blocks diffs > 5000 lines (override with [huge-diff-ok] in commit msg)
- settings.json: wire PreToolUse hook
2026-04-23 23:57:41 +08:00

7.2 KiB
Raw Permalink Blame History

Casdoor 上游 Rebase Playbook

频率: 每季度一次,或上游发布新 release 时触发 负责人: 你派给 casdoor-specialist 执行,人类审批 预期耗时: 半天到 1 天 风险等级: 🔴 高(影响全团队认证)


前置条件(全部 ✅ 才能开始)

  • casdoor-internal/ 当前 main 分支干净(git status 无未提交)
  • 最近 3 次 CI(.github/workflows/build.yml + build-and-deploy.yml)都通过
  • 生产环境 Casdoor 最近 48 小时没有告警
  • 已通知团队"即将 rebase,请暂缓改动 casdoor-internal"
  • 生产数据库已做备份(ACA PG 自动快照,确认最近 24h 有快照)

阶段 1:侦察(1-2 小时)

cd /workspace/casdoor-internal
git fetch upstream main
git log --oneline ^HEAD upstream/main | tee /tmp/upstream-commits.txt

对每个 commit 分类(见 /sync-upstream 命令的分类规则)。

产出:reports/casdoor-rebase-plan-<date>.md,包含:

  • 上游 commit 总数
  • 各等级分类统计
  • 🔴/⚫ 清单(需要决策)
  • 建议执行顺序

暂停点:把报告发到团队 review,得到 "继续 / 修改计划 / 放弃" 的明确答复再往下走。

阶段 2:准备工作区(30 分钟)

# 拉 rebase 分支
git checkout -b chore/upstream-rebase-$(date +%Y%m%d)

# 记录当前状态
git rev-parse HEAD > /tmp/rebase-baseline-hash
git diff HEAD upstream/main --stat > /tmp/rebase-diff-stat.txt

阶段 3:分批 merge(核心,2-4 小时)

批次 A:🟢 safe commits

while read hash; do
  git cherry-pick "$hash" || git cherry-pick --abort
done < <(grep -E "^🟢" /tmp/upstream-commits.txt | awk '{print $2}')

# 验证
make fmt && make vet && make ut

失败的 commit → 跳过,追加到 /tmp/rebase-skipped.txt,不要逼自己过。

批次 B:🔵 feature commits

逐个 cherry-pick + 跑测试。feature 之间有依赖就按时间序。

批次 C:🟡 careful commits

这是最危险的批次。 每个 commit 单独处理:

for hash in <🟡 列表>; do
  git cherry-pick "$hash"
  # 冲突?进入下面流程
done

🟡 冲突处理流程

  1. git status 看冲突文件列表
  2. 对每个文件:
    • 读上游改动:git show $hash:<file>
    • 读我们版本:git show HEAD:<file>
    • 理解上游意图(读 commit message + diff)
    • 决策三选一:
      • 全接受上游:git checkout --theirs <file>(仅当我们没碰过这文件)
      • 保留我们:git checkout --ours <file>(仅当上游改动与我们无关)
      • 人工合并:手动编辑,确保既有我们的改动又吸收上游新逻辑
  3. git add <file>
  4. 全部解完 git cherry-pick --continue
  5. 跑 make fmt && make vet 立即验证不挂

绝不粗暴 -X theirs 或 -X ours 一把梭。

批次 D:🔴 / ⚫ —— 不做

这批永远不在自动 rebase 范围内。PR 描述里列清楚,交给人类决策。

阶段 4:前端同步(30 分钟)

cd web
yarn install   # 拉可能的新依赖
yarn build     # 必须通过
yarn test      # 如果有测试
cd ..

前端有冲突时参考上面"冲突处理流程"。重点关注:

  • web/src/App.js 路由
  • web/src/Setting.js 全局配置
  • i18n 文件 web/src/locales/*/data.json

阶段 5:全量验证(1 小时)

# Backend
make fmt
make vet
make lint-install && golangci-lint run
make ut

# Docker 构建
sh ./build.sh    # 本地 patch 脚本
make docker-build

# 集成烟测(如果本地能起完整栈)
docker compose up -d
sleep 30
curl -f http://localhost:8000/api/get-global-providers || echo "FAIL"
curl -f http://localhost:8000/api/health || echo "FAIL"
docker compose down

阶段 6:跨仓库兼容性验证

上游改动可能影响下游 JWT 解析:

# 1. 找到 JWT claim 结构变化
git diff HEAD~<N>..HEAD -- object/token.go object/application.go | grep -E "(struct|field)"

# 2. 如果 claim 字段变了,必须同步改:
rg -l "casdoor.*jwt|jwt.*casdoor" /workspace/chat-gw/
rg -l "casdoor.*jwt|jwt.*casdoor" /workspace/xiaoshou/
rg -l "casdoor.*jwt|jwt.*casdoor" /workspace/gongdan/
rg -l "casdoor.*jwt|jwt.*casdoor" /workspace/lobechat-enterprise/

如果发现 JWT 字段变化且下游使用: rebase PR 必须引用配套的下游 PR。

阶段 7:出 PR

git push -u origin chore/upstream-rebase-$(date +%Y%m%d)

PR 描述模板:

## 目标
同步 upstream casdoor/casdoor 到 <hash-short> (<date>)

## 执行范围
- 上游 commit 区间:`<old>..<new>` 共 N 个 commit
- 吸收:X safe + Y feature + Z careful
- 挂起:K dangerous + M breaking(见"需人工决策")

## 本地验证
- [x] make fmt / vet / ut / golangci-lint
- [x] yarn build(web)
- [x] sh ./build.sh + make docker-build
- [x] 本地 docker compose 起栈烟测
- [x] 跨仓库 JWT claim 兼容性扫描:<结果>

## 对下游的影响
- chat-gw:<影响/无影响>
- xiaoshou:<...>
- gongdan:<...>
- lobechat-enterprise:<...>
- 配套下游 PR:<链接或"N/A">

## 需人工决策(🔴/⚫)
- [ ] Commit abc: 上游升级 Beego 到 v3 → 我们拒绝(Makefile 锁 v2.3.8)
- [ ] Commit def: 上游改 conf/app.conf 结构 → 需确认 ACA 部署配置

## 跳过的 commit(冲突放弃)
- abc123:package renaming 太复杂
- def456:删了我们重度依赖的 helper

## 回滚方案
基线 hash:`<rebase-baseline-hash>`
回滚命令:`git reset --hard <baseline-hash>` + 重部署 ACA

阶段 8:合并后监控(24 小时)

合并后的生产部署要监控:

  • ACA 部署成功(az containerapp revision list)
  • Casdoor 首次启动日志无报错
  • /api/get-global-providers 响应正常
  • 下游 4 个仓库的 JWT 校验正常(用 chat-gw /healthz 做代理指标)
  • 24 小时内登录成功率无异常跌落

如果 24 小时内出现异常 → 立刻回滚到基线 hash。


常见翻车场景(前人踩过的坑)

场景 1:上游改了 object/user.go 的字段 tag

症状:Sync2 不会改已有列,新 tag 不生效 应对:rebase PR 附带一个人工执行的 DDL SQL 给 DBA

场景 2:上游新增 OAuth provider

症状:需要 secrets 配置,本地开发没配会启动失败 应对:在 conf/app.conf.example 加空配置(skip-worktree 实际文件由 ops 维护)

场景 3:前端路由新增 /discover 或类似

症状:我们之前可能 de-brand 删过 应对:检查 web/src/App.js,决定吸收还是保留删除

场景 4:controllers/account.go 上游改了登录流程

症状:可能破坏我们与下游系统的 SSO 集成 应对:读上游 commit 原文 + 手动测试 Casdoor → chat-gw → xiaoshou 整条链路


放弃阈值

遇到以下情况,立即停止本次 rebase,回 baseline:

  • 🛑 make ut 失败数 > 10 且 30 分钟修不好
  • 🛑 JWT claim 字段变化但下游 PR 需要 > 2 天才能出
  • 🛑 上游删除了我们系统依赖的 helper / 接口
  • 🛑 需要 Beego / xorm 主版本升级(当前不支持)

回滚:

git checkout main
git branch -D chore/upstream-rebase-$(date +%Y%m%d)
# 写一个复盘记录到 reports/casdoor-rebase-abandoned-<date>.md