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.
140 lines
5.4 KiB
Markdown
140 lines
5.4 KiB
Markdown
# 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 在循环交互场景下会不会爆 | 暂不优化,到了再说 |
|