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
244 lines
7.2 KiB
Markdown
244 lines
7.2 KiB
Markdown
# 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 小时)
|
||
|
||
```bash
|
||
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 分钟)
|
||
|
||
```bash
|
||
# 拉 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
|
||
|
||
```bash
|
||
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 单独处理:
|
||
|
||
```bash
|
||
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 分钟)
|
||
|
||
```bash
|
||
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 小时)
|
||
|
||
```bash
|
||
# 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 解析:
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
git push -u origin chore/upstream-rebase-$(date +%Y%m%d)
|
||
```
|
||
|
||
PR 描述模板:
|
||
|
||
```markdown
|
||
## 目标
|
||
同步 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 主版本升级(当前不支持)
|
||
|
||
回滚:
|
||
```bash
|
||
git checkout main
|
||
git branch -D chore/upstream-rebase-$(date +%Y%m%d)
|
||
# 写一个复盘记录到 reports/casdoor-rebase-abandoned-<date>.md
|
||
```
|