lib/git → KenShell gRPC 迁移说明与待办
0. 当前状态(已完成)
- 新增 crate
lib/kenshell:proto/kenshell/**与proto/gitken/v1/{lint,shared,cleanup,conflicts}.proto从KenShell/proto原样复制;build.rs只生成 client;KenShellClient暴露全部kenshell.v1与kenshell.internal.v1服务客户端,并统一 64 MiB 消息上限与x-request-id。 - 配置写在
[git]段:kenshell_endpoint、kenshell_rpc_key、kenshell_timeout_secs。 lib/git不再包含任何gix、不再 spawngit:- 删除
lib/gitbaby(整个 crate)与 workspace 依赖gix、russh、ssh-key、sha1。 - 删除
src/smart/**、src/ssh/**、src/graphql/**、src/share/git_env.rs、src/service/gitcmd.rs、src/lfs/{object,handle}.rs。 src/sync/只保留 Redis 队列与事件类型(queue/event/error),worker 删除。
- 删除
GitService持有KenShellClient;GitContext由「本地路径 + gix 仓库」改为 「RepositoryRef+ KenShell 客户端」。src/rpcgit/是 KenShell 的薄封装:保留原gitbaby的公开数据类型与GitBaby方法签名,内部全部映射到 gRPC;业务层(service/handler)改用crate::rpcgit::...。- 已切到 RPC 的能力:tree/file 列表与解析、blob 元数据/内容/LFS 指针、commit 列表/详情/ 统计/blame/rev-parse/is-ancestor、diff(raw/range/shortstat/numstat/changed-paths/ compare/diff-tree)、refs/branches/tags 读写、conflict 检查与明细、analysis 读、 archive 创建与查询、remote 增删查与 import/fetch/push(异步 Job 轮询)、 repository 存在性/体积、commit status 回写、code comment 的 revision 解析。
app/githost退役(smart HTTP/SSH 由 KenShell 提供);charts与scripts/dev.*移除 githost、改由kenshell.*配置注入/git环境变量。
1. 架构边界
| 关注点 | 归属 |
|---|---|
| Git 对象库、引用、pack、LFS 对象、smart HTTP、SSH | KenShell |
| 仓库/分支/标签/提交/PR/评论/星标等元数据 | KenApi 数据库 |
| LFS 锁 | KenApi 数据库(KenShell 无锁协议) |
| 页面渲染(maud HTML 片段、PDF 分页) | KenApi |
| 定时任务、搜索索引、导入任务编排 | KenApi(synchost,见 §5) |
GitContext 只描述「哪个仓库」:
GitContext { model, cache, database, space_name, repo_root, ks }
space_name 是组织 slug,model.name 是仓库名,二者组成 KenShell 的 RepositoryRef。
前提:KenShell 必须能按 (org slug, repo name) 解析到自己的仓库行。
2. KenShell 已覆盖、且已完成对接
| API / 能力 | KenShell RPC |
|---|---|
GET /tree/{rev}、/html/* 目录读取 | TreeService/GetTree、ListFiles、ResolveTreePath |
GET /blobs/{oid}/metadata、/content | BlobService/GetBlobMetadata、GetBlobContent |
GET /lfs-pointers | BlobService/ListLfsPointers |
GET /commits、/commits/{rev}、/commits/stats、/commits/ancestor、/rev/{rev} | CommitService/ListCommits、GetCommit、GetCommitStats、IsAncestor、RevParse |
GET /blame | CommitService/ListBlame |
GET /diff、/diff/raw、/diff/for-commit、/diff/range | DiffService/CompareCommits、GetRawDiff、ListChangedPaths、ListDiffTree、GetRangeDiff、GetDiffShortStat、ListDiffNumStats |
GET /conflicts、/conflicts/detail | ConflictService/CheckConflicts、GetConflictDetail |
GET /analysis/{languages,contributors,code-activity} | AnalysisService/GetLanguages、ListContributors、GetCodeActivity |
POST /archives、GET /archives/{rev}、/archives/bundle | ArchiveService/StartArchive、GetArchiveArtifact、StartArchiveBundle(Job 轮询) |
GET /remotes、PUT/DELETE /remotes/{name} | RemoteService/ListRemotes、UpsertRemote、RemoveRemote |
POST /remotes/{import,fetch,push} | `RemoteService/StartRemoteImport |
GET/POST /branches、GET/DELETE/PATCH /branches/{name}、{name}/default | RefService/*、CommandService/* |
GET/POST /tags、GET/DELETE /tags/{name} | `RefService/ListTags |
GET /path-log | CommitService/ListCommits(path=...)(近似,见 §4) |
| 仓库创建 | CommandService/CreateRepository |
语义变化(调用方已适配)
- 远端导入/拉取/推送:由同步返回结果改为启动 Job 并轮询
JobService/GetJob。 HTTP 响应字段保持兼容(default_branch/commit_count/updated/new/pushed/rejected)。 - 归档:KenShell 生成产物后返回
storage_key+download_url,KenApi 不再自己打包、 不再写入自己的 S3。 - 仓库创建:只创建裸库和默认分支,不再写入初始提交/README(见 §4)。
- Tag 详情:
TagView没有 tag 对象的 oid,GitBaby用target_sha填充TagInfo.sha,前端展示不受影响;若需要区分 tag 对象 oid,需 KenShell 补字段。 - Blame:以
BlameLineView逐行返回,KenApi 按连续相同 commit 聚合成 hunk;previous_sha/previous_path/orig_start_line固定为空(原实现有值)。
3. 保留在 KenApi 的本地能力(不依赖 git 对象库)
| 能力 | 说明 |
|---|---|
LFS 锁(/lfs/locks*) | git_lfs_lock 表;KenShell 只有对象与 LFS HTTP 协议 |
| 分支/标签保护、白名单 | KenApi 数据库;写操作时前置校验 |
| releases / stars / watch / topics | KenApi 数据库 |
| code comments(含 resolve/parent/outdated) | KenApi 数据库;KenShell 的 CodeCommentService 字段不足 |
| HTML 片段(readme/tree/blob-pages/languages 等) | maud 渲染,数据来自 RPC |
| PDF 分页 | hayro,输入来自 BlobService |
POST /utils/patch/parse | 纯文本解析 |
POST /utils/commit-signature | 读取用户身份,无 git |
4. 未覆盖能力(当前返回 501 Not Implemented)
统一错误:GitError::Unimplemented → HTTP 501。路由与 OpenAPI 声明保留,便于后续补齐。
| 接口 / 能力 | 现状 | 需要的 KenShell 能力 |
|---|---|---|
POST /pulls/{id}/merge、POST /pulls/{id}/update-branch、/gate 的合并判定 | 不可用(merge_plan/merge_execute 直接返回 501) | MergeService:merge-base、merge-tree(含冲突树)、fast-forward、squash/rebase、任意 ref 更新 |
GET /patch/generate | 可用(DiffService/GetRawDiff) | — |
POST /patch/apply | 501 | PatchService/ApplyPatch(3-way) |
GET /packs/stats、POST /packs/ingest、POST /packs/repack | 501 | PackService(或明确由 KenShell 内部管理并删除接口) |
POST /maintenance/prune、/fsck | 501 | MaintenanceService |
GET /signatures/commit/{sha}、/signatures/tag/{name} | 501 | SignatureService/VerifyCommit、VerifyTag |
GET /submodules、/submodules/resolve | 501 | SubmoduleService(或解析 .gitmodules 的 RPC) |
POST /hooks/{script} | 501 | HookService/Execute(或确认废弃) |
POST /contents/blobs、/trees、/commits | 501 | ContentWriteService(写对象 + 建提交) |
POST /lfs/cleanup | 501 | LfsAdminService/UnreferenceObject 的批量版本 |
| 仓库创建时的初始提交 / README | 不再执行 | ContentWriteService 或 CommandService.CreateRepository(initial_commit) |
| 分支/标签删除的 hook 事件回写 | 不再触发(原 sync worker 负责) | KenShell 事件推送(§6) |
任意 ref 写入/删除(PATCH/DELETE /refs/{name}、refs/notes/*、refs/pull/*) | 仅支持 refs/heads/* | `CommandService/UpdateRef |
GET /graphql | 已移除(前端未使用;字段逐步被 REST 覆盖) | 若要恢复:用 service 层重写,并补 pack_stats/submodules/patch_generate |
search 索引(synchost 的 search worker) | 仍按本地路径扫描,仓库已不在本地 | SearchService 或 ListFiles/GetFile 驱动索引 |
5. 进程与部署变化
- 删除
app/githost:smart HTTP / SSH 由 KenShell 提供。charts/core移除githostDeployment、Service、IngressRoute 与相关 values;scripts/dev.*与justfile同步移除。 - 保留
app/synchost:只承载 import worker、search worker 与健康检查;git::sync::SyncWorker已删除。 - 克隆地址改为指向 KenShell:
git.http_clone_base_url、git.ssh_clone_*; Helm 通过kenshell.*values 注入APP_GIT__KENSHELL_ENDPOINT/RPC_KEY/TIMEOUT_SECS/HTTP_CLONE_BASE_URL/SSH_CLONE_*。
6. 建议 KenShell 补充的协议
MergeServiceGetMergeBase(repository, a, b) -> oidMergeTrees(base, ours, theirs, opts) -> {tree_oid, conflicts[]}Merge(base_ref, head, strategy, message, actor) -> {method, new_sha, rewritten[]}UpdateRef(ref_name, new_oid, expected_old_oid, force)
PatchService:GeneratePatch、ApplyPatch(3-way)SignatureService:VerifyCommit、VerifyTagSubmoduleService:ListSubmodules、ResolveSubmodulePackService:GetPackStats、IngestPack(stream)、RepackMaintenanceService:Prune、FsckContentWriteService:WriteBlob、WriteTree、CreateCommit(含初始提交)HookService:ExecuteHook(script, args, stdin)LfsLockService(可选):ListLocks/Lock/Unlock/VerifyLocksCommandService:UpdateRef/DeleteRef泛化到任意 refBlobService/GetBlobContent:支持stream,避免 64 MiB 单消息上限RefService/TagView:补 tag 对象sha与peeled- 事件通道:写入完成(push/command)后向 KenApi 推送事件,替代已删除的 sync worker
RepositoryService:补齐展示字段,或明确 KenApi 为仓库元数据唯一来源
7. 前端受影响清单
来自 web/src/shared/api/apiDefinitions.ts(已按新 openapi 重新生成):
| 前端接口 | 迁移后 |
|---|---|
GET /repos/{space}/{repo}/tree/{rev}、/blobs/*、/commits*、/blame、/diff* | 正常(RPC) |
GET/POST /branches*、/tags*、/remotes* | 正常(RPC;远端操作改异步 Job,轮询在服务端完成) |
GET/POST /analysis/*、/archives* | 正常(创建为 Job + 轮询) |
GET /html/{tree,readme,blob-content,blob-pages,languages} | 正常 |
GET /lfs/locks*、/lfs/locks/verify | 正常(KenApi DB) |
GET /patch/generate | 正常(raw diff) |
GET /pulls/{id}/files、/commits、/patch | 列表与 patch 正常;合并动作不可用 |
GET /lfs-pointers | 正常(只返回 oid/size,file_oid 字段置零) |
GET /submodules*、/signatures/*、/path-log | submodules/signatures 501;path-log 近似可用 |
/graphql | 已从 OpenAPI 与前端生成代码移除 |
| 其余 DB 接口(star/watch/topics/releases/protection/whitelists/code-comments) | 正常 |
8. 后续执行顺序
- 与 KenShell 对齐
MergeService+ContentWriteService,恢复 PR 合并与建库初始提交。 - 补
SignatureService、SubmoduleService、PatchService,替换对应 501。 - 补反射/事件通道,替换已删除的 sync worker(分支/标签/提交镜像与 webhook 触发)。
- search worker 改为 RPC 驱动。
- 清理
GitContext.repo_root、git.repo_root/objects_root与相关 chart 挂载。