claude-gitea-agent/docs/03-porting-plan.md
pangtiankai c29af91113 docs: project scaffolding — README + architecture + roadmap + porting plan + ADRs
Initial documentation for route A (port claude-code-action to Gitea Actions).
Research complete, no implementation code yet. See docs/02-roadmap.md for milestones.
2026-05-25 20:36:54 +08:00

140 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`(已包含 nodebun 安装 1 行命令) |
| Gitea webhook 评论事件名是 `issue_comment` 还是 `issues_comment` | 写 entrypoint 时先 dump payload 验证 |
| Anthropic API rate limit 在循环交互场景下会不会爆 | 暂不优化,到了再说 |