# 03 - 移植计划 > 把 `anthropics/claude-code-action` 源代码逐文件迁移到本仓库的清单。 > 上游版本:master @ 2026-05-23(克隆在 `/home/pangtiankai/projects/claude-code-action-upstream/`) ## 目录映射 | 上游 | 本仓库 | 移植量 | |---|---|---| | `action.yml` | `action.yml` | 🟡 改 inputs:去掉 GitHub 特有字段(如 `github_token` → `gitea_token`) | | `package.json` | `package.json` | 🟡 替换 `@octokit/*` 依赖 | | `bunfig.toml` | `bunfig.toml` | ✅ 原样 | | `tsconfig.json` | `tsconfig.json` | ✅ 原样 | | `src/entrypoints/` | `src/entrypoints/` | 🟡 适配 Gitea 事件载荷字段 | | `src/modes/tag/` | `src/modes/tag/` | 🟢 90% 原样,少量字段重命名 | | `src/modes/agent/` | — | ⛔ **暂不移植**(后期再说) | | `src/create-prompt/` | `src/create-prompt/` | 🟢 90% 原样 | | `src/github/api/` | `src/gitea/api/` | 🔴 **完全重写**(Gitea API client) | | `src/github/data/` | `src/gitea/data/` | 🔴 重写 schema | | `src/github/operations/` | `src/gitea/operations/` | 🔴 重写(评论、branch、PR) | | `src/github/validation/` | `src/gitea/validation/` | 🔴 重写 | | `src/github/utils/` | `src/gitea/utils/` | 🟡 部分通用,部分重写 | | `src/auth/` | `src/auth/` | 🟢 90% 原样(Anthropic API key 认证不变) | | `src/mcp/` | `src/mcp/` | ✅ 原样 | | `src/utils/` | `src/utils/` | ✅ 原样 | | `base-action/` | `base-action/` | 🟢 90% 原样 | **统计**:约 30% 文件要重写,60% 只改字段或导入路径,10% 完全不动。 ## 重写优先级(P0 = 第一周必交付) ### P0 — Gitea API client(`src/gitea/api/`) 最低要凑齐的 endpoint: | 操作 | Gitea API | 备注 | |---|---|---| | 获取 issue | `GET /repos/{owner}/{repo}/issues/{number}` | | | 获取 issue 评论列表 | `GET /repos/{owner}/{repo}/issues/{number}/comments` | | | 创建评论 | `POST /repos/{owner}/{repo}/issues/{number}/comments` | | | 更新评论 | `PATCH /repos/{owner}/{repo}/issues/comments/{id}` | 用于流式更新("思考中..."→ 最终回复) | | 获取 PR | `GET /repos/{owner}/{repo}/pulls/{number}` | | | 获取 PR diff | `GET /repos/{owner}/{repo}/pulls/{number}.diff` | | | 创建分支 | `POST /repos/{owner}/{repo}/branches` | | | 创建 PR | `POST /repos/{owner}/{repo}/pulls` | | | 获取仓库内容 | `GET /repos/{owner}/{repo}/contents/{filepath}` | | **选择**:直接用 `fetch` + zod schema,不引入完整 Gitea SDK(依赖最小化)。 ### P0 — Trigger 解析(`src/modes/tag/`) 需要适配的事件类型: | Gitea 事件 | trigger 条件 | |---|---| | `issues.opened` | issue 正文含 `@claude` | | `issues.edited` | 同上 | | `issue_comment.created` | 评论正文含 `@claude` | | `pull_request.opened` | PR 正文含 `@claude` | | `pull_request_comment.created` | PR 评论含 `@claude` | ### P0 — Entrypoint(`src/entrypoints/`) 读取 `GITHUB_EVENT_PATH` → 改成 `GITEA_EVENT_PATH`(Gitea Actions 自动注入)。 事件载荷字段: ``` github.event.issue.user.login → gitea.event.issue.user.login ✅ 一致 github.event.comment.user.login → gitea.event.comment.user.login ✅ 一致 github.repository → gitea.repository ✅ 一致 github.event.pull_request.head.sha → 一致 ``` ### P1 — Status comment("我在干活" 进度评论) 上游用 GitHub Checks API 做进度展示,Gitea 没有等价 API([Gitea Issue #28381](https://github.com/go-gitea/gitea/issues/28381) 是 commit status,不一样)。 替代方案:**用一条评论的连续 edit 模拟**。 - 第一条评论:"🤔 Claude 正在分析需求..." - 边干边 PATCH 更新这条评论的正文 - 完成后定格成最终内容 ### P2 — `agent` mode、`review` mode 后期再说。 ## 依赖替换 ### package.json 去掉: ```json "@actions/github": "^...", "@octokit/rest": "^...", "@octokit/graphql": "^...", "@octokit/webhooks-types": "^..." ``` 新增(如果需要): ```json // 如果用生成的 SDK "gitea-js": "latest" // 否则只用 fetch + zod,零新增 ``` 保留原样: ```json "@actions/core": "...", // 跟 Gitea Actions 兼容 "@anthropic-ai/claude-agent-sdk": "...", "@modelcontextprotocol/sdk": "...", "shell-quote": "...", "zod": "..." ``` ## webhook payload 差异速查 Gitea 的 webhook payload 大部分字段和 GitHub 一致(这是有意为之的),主要差异: | GitHub | Gitea | 说明 | |---|---|---| | `pull_request.head.repo` | `pull_request.head.repo` | Gitea 始终有此字段(GH 偶尔 null) | | `installation` | — | Gitea 没有 GitHub App 概念 | | `sender.type === "Bot"` | `sender.type === "user"` | Gitea 暂无 Bot 用户类型 | 完整差异参考:[Gitea webhook 文档](https://docs.gitea.com/usage/webhooks)。 ## 测试策略 1. **本仓库自身做 dogfooding**:在 `claude-gitea-agent` 自己的 issue 里 @claude,让它给自己写功能 2. **mock 测试**:`test/fixtures/` 放几个 Gitea webhook payload 样本 3. **CI**:暂不上 CI,跑通 happy path 后再加 ## 当前阻塞 / 风险 | 风险 | 缓解 | |---|---| | Gitea Actions 跑 bun 容器可能要装 bun | runner image 用 `catthehacker/ubuntu:act-latest`(已包含 node,bun 安装 1 行命令) | | Gitea webhook 评论事件名是 `issue_comment` 还是 `issues_comment`? | 写 entrypoint 时先 dump payload 验证 | | Anthropic API rate limit 在循环交互场景下会不会爆 | 暂不优化,到了再说 |