Skip to content

Issue 98

clean edited this page Oct 8, 2026 · 3 revisions

Issue #98:仓库关联的 GitHub PR / GitLab MR

背景与目标

在 Alune 的远程 Git 工作区内查看仓库收到的合并请求,避免先离开工作区查找对应的托管平台。Issue 原先只记录方向;本次明确首版范围并实现可验证的完整查询路径。

用户入口与获取范围

仓库工具条新增 PR/MR 视图,沿用现有自适应标签布局。默认选择可解析的 origin;缺少时依次选择已识别的平台、其他可解析远端或第一个远端。用户可明确切换任意配置的远端。使用 fetch 地址,push 地址不参与目标选择,多个平台的结果不混合。

查询所选仓库收到的全部目标分支的 PR/MR;Fork 的外发请求需要切换到对应的上游远端查看。默认“开放中”(包括草稿),可切换“全部状态”,后者区分开放、关闭与已合并。每页 30 条,按最近更新时间倒序。列表显示标题、编号、作者、来源与目标分支、状态、草稿标记及更新时间。

点击标题在系统浏览器打开平台详情。支持上一页、下一页、手动刷新和工具条刷新;刷新先重读 Git 配置。不自动轮询,不提供创建、评审、关闭、合并、检出等写操作。分页期间远端数据可能变化,必要时回到第一页刷新。

平台与认证

平台 支持范围 认证
GitHub github.com,HTTPS / SSH / SCP 地址;暂不支持 Enterprise 公开仓库匿名读取;细粒度令牌需要目标仓库 Pull requests 读取权限,经典令牌需要 repo;组织可能要求 SSO
GitLab gitlab.com 自动识别;自建主机由用户显式选择 GitLab;支持多级群组 公开项目匿名读取;私有项目使用具有项目访问权且包含 read_api 或 api 的个人、项目或群组访问令牌

自建实例要求本机可达且证书受信任的 HTTPS,并部署在域名根路径。HTTPS URL 的显式端口保留,SSH 端口不推断为 HTTPS 端口。暂不支持 HTTP、路径前缀部署和 SSH 主机别名。

令牌通过密码输入框显式应用,仅保留在当前视图内存中;可主动清除,切换远端、仓库、视图或重载页面后清除。发送主机在界面中显示。服务端只对本次请求使用令牌,不保存到磁盘、数据库、浏览器存储或全局状态,不读取远端 Git 凭据或 AI 密钥。

实现与失败处理

  1. 浏览器调用 GET /api/repositories/:id/pull-requests/remotes,通过已登记仓库及 SSH 执行只读 git remote -v,返回去除凭据后的远端描述。
  2. 浏览器调用只读 POST /api/repositories/:id/pull-requests/list,在请求体中携带远端名、预期地址、平台、状态、页码和可选临时令牌。使用 POST 避免将令牌放入 URL;响应设置 Cache-Control: no-store。
  3. 服务端重读 Git 配置,校验目标仍与用户选择一致。远端已删除返回 404,地址已变化返回 409,平台不匹配返回 400,校验失败不发送令牌。
  4. 托管平台 API 由运行 Alune 的本机访问:GitHub REST /repos/{owner}/{repo}/pulls 或 GitLab REST /api/v4/projects/{encodedPath}/merge_requests。不依赖远端安装 gh/glab,不跟随 API 重定向或分页中的任意 URL。
  5. 每次查询包含 SSH 和 HTTP 的总时限为 20 秒,超时取消该 Git 命令或 HTTP 请求;平台响应上限为 2 MiB。Git 输出也有大小上限,Windows 使用既有编码 PowerShell 参数构建器。
  6. 将返回数据统一为只读列表,外链由已校验的仓库地址与请求编号构造,不信任 API 提供的任意链接。前端取消旧请求,避免切换筛选、远端或仓库后的迟到结果覆盖当前视图。

空列表、无远端、不支持的地址分别展示。401 提示认证失效,403 提示权限或组织授权,404 提示不存在或私有权限,429/限流提示稍后重试,502/504 提示网络、平台或超时。错误不回显原始远端输出、上游正文或令牌。刷新失败保留上一次同一查询的列表,并明确标为上次结果;初次失败不显示为空列表。

验收标准

  • 工具条提供直接入口,窄窗口保留入口与可访问名称。
  • GitHub、GitLab 和自建 GitLab 的支持边界、获取方向和认证方式明确。
  • 正确选择 fetch 远端;支持多远端、SSH/HTTPS/SCP、多级群组和端口区分。
  • 可读取公开 PR/MR,并展示开放、关闭、合并、草稿、分支、作者及更新信息。
  • 状态筛选、分页、刷新、空结果和可重试错误有明确行为。
  • 私有令牌只用于当前目标;服务端拒绝目标变更,前端切换后清除。
  • 查询有超时和响应上限;不执行 Git 或平台写操作。
  • 自动化测试覆盖认证、权限、限流、分页、非法输入、超时和真实 SSH 查询。

验证记录

环境:macOS arm64,Node.js 25.5.0,2026-09-26。所有 Git / SQLite / SSH 集成数据均来自临时隔离目录。

检查 结果
npm test -w server -- --runInBand 14 套、150 项通过,其中新增 PR/MR 47 项
npm test -w web 140 项通过,包含列表内容、XSS 转义、远端选择及工具条回归
npm test -w @alune/ssh-client 76 项通过;2 项 Windows 原生环境测试在 macOS 跳过
npm run desktop:test:unit 42 项通过
node --test apps/web/tests/pull-requests.integration.cjs 真实 Nest HTTP、SQLite、SSH 和 Git 通过;仅托管平台响应模拟;验证无缓存、分页、认证、远端变更拦截、无远端及工作区未被修改
GitHub CI Ubuntu 22.04 / Node 22.22.0:PR 与分支 push 的 server、web、ssh-client、desktop 及 commitlint 检查全部通过(运行记录)
npm run build 5 个工作区构建成功,包含桌面应用暂存与原生模块;保留原有前端大包提示
GitHub 公开 API 使用生产服务读取 ShaoClean/Alune,返回 30 条,分页和状态映射正常
GitLab 公开 API 使用生产服务读取 gitlab-org/cli,返回 30 条,开放/关闭/合并状态与分页正常
Ego Lite 浏览器验收 分页、全部状态、自建 GitLab 手动识别、认证应用与清除、跨远端令牌隔离、浏览器存储无令牌、刷新失败保留结果、重试、迟到响应隔离、不支持远端、无远端均通过;560px 窄屏没有页面横向溢出,浅色/深色可读

复验页面:构建后运行 node apps/web/tests/pull-requests-fixture.cjs,打开输出的 URL。Fixture 使用真实本地 SSH 与服务端路径,GitLab 认证场景接受测试用非空令牌,绝不接触真实私有凭据。

风险与回退

真实私有 GitHub/GitLab 账号、自建实例、组织 SSO 和 Windows/Linux 桌面真机未验收;相关协议、错误及认证隔离已由模拟平台与真实 SSH 的集成用例覆盖。需要本机访问托管平台的网络能力。新功能没有数据库迁移或凭据持久化;回退代码提交即可移除入口,Wiki 历史独立保留。

界面证据

前后截图使用同一组隔离演示仓库。修改前前端由 f6ce4ac 源码独立构建;修改后来自实现分支。1440×900 浅色/深色以及 560×800 窄屏,截图不包含真实账号、私有地址或令牌。

修改前,“远程”仅展示 fetch/push 地址,工具条没有 PR/MR 入口:

Alune 修改前的远程视图

修改后,可直接查看 PR/MR 状态与元数据:

Alune PR/MR 浅色列表

Alune PR/MR 深色列表

自建 GitLab 的平台选择与临时认证;输入框在应用后清空,截图只显示“已应用”:

Alune 自建 GitLab 的临时认证

窄屏保留入口、筛选与可滚动列表:

Alune PR/MR 窄屏

后续扩展:全局 PR/MR 中心(2026-10-08)

新增跨仓库中心的方案、验证范围和截图见 PR/MR 中心,关联 PR #212。本节补充后续能力,不替换上文历史验收记录。

Clone this wiki locally