Files
ezbookkeeping/CLAUDE.md
T
zhengchen.tao 47b5641597 docs: CLAUDE.md 解释 ci/custom 不需保持一致 + UI commit 不等于构建 commit
补充三分支拓扑后的"FAQ 段":

- ci 与 custom 内容不重叠是设计,不是 bug
- Gitea Actions UI 顶部显示的 commit 是 workflow dispatch 触发
  位置(即 ci 的 HEAD),不是构建源代码 commit
- 真实构建的代码 commit 在镜像 tag / OCI revision label /
  workflow 末尾 Build summary 三处都能看到,看 summary 区即可

附两条可选替代方案(workflow 挪 custom / 加 push trigger 自动构建),
说明当前选择的中间路径理由。
2026-05-02 18:26:40 +08:00

8.8 KiB
Raw Blame History

CLAUDE.md

本项目是 mayswind/ezbookkeeping 的个人 fork。

本文件:仓库分支模型、上游同步流程、CI 故障排查 —— meta 层 FORK.md:fork 相对上游的具体改动清单(feature 维度 + 进度状态) 个人笔记:通用 fork 工作流决策框架在 fork-工作流决策框架.md(不入库)

本文件只记录这个仓库的具体事实,避免 Claude 会话误判。


仓库拓扑

github.com/mayswind/ezbookkeeping       (上游)
        │  Gitea pull mirror(后台异步)
        ▼
git.zhengchentao.win/mirror/ezbookkeeping   (只读镜像)
        │  CI workflow 拉过来
        ▼
git.zhengchentao.win/dev/ezbookkeeping     origin,本地唯一 remote

本地 git remote -v 只有 origin 一项,没有手工配 upstream。上游同步通过 ci 分支上的 workflow 在服务端完成,不是本地操作。


三个分支的职责(必须先理解,否则会改错地方)

分支 职责 force push?
main 锚定上游 release tag(当前 v1.4.0)。被 .gitea/workflows/sync-upstream.yml git reset --hard <tag> 覆写 是(由 CI 做)
custom 所有个人改动都在这:信用额度功能、UI 调整、个人需求清单等。具体改动清单见 FORK.md。日常开发分支 是(rebase 后人工做)
ci origin 的 default branch。只放 .gitea/workflows/*.yml。独立于 main 和 custom

⚠️ origin 的 default branch 是 ci 不是 main 也不是 custom。git clone 默认会落在 ci。要做开发先 git checkout custom

ci 与 custom 不需要保持一致(这是设计,不是 bug)

三分支各管各的,ci 与 custom 内容不重叠

  • ci:只有 .gitea/workflows/*.yml
  • customfork 代码 + FORK.md / CLAUDE.md / .gitignore 等
  • 理论上没有共享文件(除了 inherit 自上游的部分,例如 ci 分支也有 README、Dockerfile 等基底文件,但很少改它们)

Gitea Actions UI 顶部显示的 commit 是 ci 的 HEAD,不是被构建的源代码 commit。这是因为 workflow 文件在 ci 分支,dispatch 触发时 UI 引用的是 workflow 文件所在 commit。但实际:

  1. actions/checkoutref: ${{ inputs.branch }} 拉的是 custom
  2. 镜像 tag 用 custom 的 short SHA
  3. OCI label org.opencontainers.image.revision 是 custom 的 full SHA
  4. workflow 末尾 Build summary 步骤把上述源 commit 显式写入 $GITHUB_STEP_SUMMARY,运行页面有突出显示

所以真实构建的代码 commit 在镜像本身、运行页面 summary 区都能看到,UI 顶部那个只是 dispatch 触发位置的 commit不是 bug,无需修复,看 summary 区即可

如果哪天觉得这种割裂太烦,可选两个替代方案:

  • 把 workflow 挪到 custom,删 ciUI commit 直接对得上,但失去 meta/code 分离)
  • push: branches: [custom] 自动触发(每次 push 自动 build,更直观但费 CI 时间)

当前选 workflow_dispatch only + summary step 是中间路径,节省 CI 又能看到真实信息。


ci 分支 workflow 清单

ci 分支的 .gitea/workflows/ 当前有 5 个 workflow

文件 触发 干什么 状态
sync-upstream.yml 手动(workflow_dispatch,可填 tag 服务端把 dev/main 强制 reset 到 mirror 上的指定 release tag(默认最新),然后 push --force-with-lease + 推 tags 在用
build-image.yml 手动(可填要打包的分支 + 镜像 tag) checkout 指定分支(默认 custom)→ 装 buildkit v0.13.2(钉版本)→ 登录 Gitea registry → 构建镜像(带 OCI 标签 source/revisionGitea 自动关联包到 repo)→ push 到 git.zhengchentao.win/dev/ezbookkeeping:<hash>:latestbuild-args: BUILD_PIPELINE=1 跳过活 API 测试 在用,是日常发布通道
deploy.yml 手动 跑 repo Variables 里 CUSTOM_DEPLOY_SCRIPTS 这条自定义脚本(通用钩子,可拼"build 完触发 NAS 端 docker compose pull/up"等) 🟡 通用钩子,按需配
docker-snapshot.yml push: branches: main 自动 上游模板风格的 snapshot build(用 secrets.DOCKER_REPO,会改 Dockerfile 里 FROM 走私有 mirror ⚠️ 上游残留,main 被 sync-upstream force-push 时会触发;当前未配 secret 估计直接失败。要么补全 secret,要么删除
docker-release.yml push: tags: v* 自动 同上但 release 风格,tag 推送时触发 ⚠️ 同 docker-snapshot.yml,未配 secret 会失败

结论:日常只用 sync-upstream + build-image 两个,其他三个要么按需启用要么后续清理。


同步发布流程(rebase 模型)

  1. 上游出新 release(如 v1.4.0)→ Gitea pull mirror 自动把 tag 同步到 mirror
  2. 人工触发 Sync from upstream workflow → 服务端把 dev/main reset 到该 tag
  3. 本地 git fetch && git checkout custom && git rebase origin/main
  4. 解冲突(如有)→ 验证 → git push --force-with-lease origin custom
  5. ci 分支上的 build-image workflow 触发,构建新镜像

为什么 rebase 不 merge:个人项目,无团队协作语义要保留,线性历史更清爽。


给后续 Claude 会话的明确提示

  • 用户说"我的分支" / "切换到我的分支" → 指 custom
  • 用户说"rebase main" → 指 git rebase origin/main,目标是把 custom 的改动叠到最新上游 tag 之上
  • 不要在 main 分支上提交任何东西(会被 CI 覆写)
  • 不要把工作流文件提交到 custommain(应该走 ci 分支)
  • force-push custom 是常规操作,但每次用 --force-with-lease,不直接 --force
  • 如果发现本地配了 upstream remote,那是历史遗留,不要依赖;以 origin/main 为准
  • .claude/.gitignore 里(个人本地配置不入库),但 CLAUDE.md 本身入库

同步历史

  • 2026-05-01rebase custom → origin/main (v1.4.0)。22 个 custom-only 提交(含一个旧的 Merge branch 'main' into myrequirement commit)压平为 21 个线性提交。已 force-push origin/custom08c69042fe265259)。
  • 2026-05-02:修 Gitea Actions Build Docker Image 工作流。三层故障,全部不在本仓库代码里:
    • TLS 雷docker login 走 host 进程不命中 PREROUTING REDIRECT,且 v6 撞 DSM nginx 的 CF Origin Cert。NAS 侧修:iptables 补 OUTPUT 对称规则 + /etc/hosts 显式 v4 兜底。详见 obsidian vault NAS/notes/内网证书路径 §三.5/§三.6
    • buildkit 内核兼容runc 1.2+ 撞 DSM 4.4 内核。ci 分支 .gitea/workflows/build-image.ymlmoby/buildkit:v0.13.2commit acdbb5bf
    • backend 单元测试撞活 APIpkg/exchangerates/TestExchangeRatesApiLatestExchangeRateHandler_* 跑活 API(加拿大银行 / 乌兹别克央行),国内访问超时。upstream Dockerfile 已设 ARG BUILD_PIPELINE,测试代码看到 BUILD_PIPELINE=1 && CHECK_3RD_API!=1 时早退。修:workflow 加 build-args: BUILD_PIPELINE=1commit 2dd8f099),对齐上游 GH Actions.github/actions/build-linux-docker-and-package/action.yml line 91

给后续 Claude 会话:CI 故障排查路径

如果 Gitea Actions build 又炸,按 NAS 域问题 vs 仓库代码问题分别排查:

现象 大概率位置 文档
Login to Gitea Container Registry 步骤报 x509: certificate signed by unknown authority NAS 网络层(iptables / dnsmasq / DSM nginx 占 443 obsidian vault NAS/notes/内网证书路径.md + NAS/notes/IPv6 设计.md
Build and push 步骤里 RUN ... 在第二条之内就炸 unsafe procfs detected 之类 buildkit/runc 与 DSM 内核版本 .gitea/workflows/build-image.ymldriver-opts
Failed to pass unit testing / Failed to pass lint checkingbuild.sh 报) 先看 Dockerfile 顶部 ARG,多半是 CI 跳过开关没传(如 BUILD_PIPELINE / CHECK_3RD_API / SKIP_TESTS)。不要先去改测试代码 Dockerfile 顶部 ARG + .gitea/workflows/build-image.ymlbuild-args
actions/checkout 报 fetch 失败 Gitea SSH/HTTPS 路径或 token 权限 gitea-runner 的 GITEA_RUNNER_REGISTRATION_TOKEN + NPM git.zhengchentao.win 的 Advanced 配置
Dockerfile 里某条指令业务逻辑报错 真正的代码问题 本仓库 Dockerfile

通用排查原则build.sh 报的"测试失败 / lint 失败"先看是不是上游已经设计了 CI 跳过路径。Dockerfile 的 ARG + build.sh 内的 os.Getenv() 检查通常成对出现(如 BUILD_PIPELINE=1 → 跳过 3rd API 测试,SKIP_TESTS=... → 跳过指定测试名)。对齐上游 .github/actions/ 下的传参,绝大多数情况能直接对齐。