gitlink-cli/skills/gitlink-gatekeeper/TROUBLESHOOTING.md

17 KiB
Raw Permalink Blame History

gitlink-gatekeeper — 故障排查TROUBLESHOOTING

CRITICAL — 开始前请先阅读 gitlink-shared/SKILL.md(认证、全局参数、真实 API 坑)与 ./SKILL.md(工作流)、./REFERENCE.md(策略字段与评分算法)。 CRITICAL — gatekeeper 默认 dry-run绝不自动合并。本文档中任何「修复」都不应放宽该安全默认除非用户明确要求。 CRITICAL — GitLink 资源只能用 gitlink-cli 操作,禁止用 gh/glab

本文档列出运行 gatekeeper 时的常见问题,按「症状 / 原因 / 解决」三段式给出。先看下表速查,再到对应小节读细节。

速查表

# 症状 根因 一句话解决
1 提示「未找到策略文件」 仓库根无 gatekeeper.yaml 且未传 --policy 回退内置默认策略,或 --policy <path> 指定
2 报「weights 之和 ≠ 100」 五维权重总和不是 100 调整权重让 review+test+hygiene+commit+ci = 100
3 401(请登录)/ 403(无权限) Token 过期 / owner-repo 错或无权限 gitlink-cli auth login / 核对 owner、repo、权限
4 pr +diff 输出巨大、超出处理窗口 大型 PR 的 diff 一次性返回太大 改用 pr +files 选关键文件 + version-diff -f 按文件分段
5 评分卡里 CI 显示 unknown ci +builds 取不到与该 PR 对应的构建 按 unknown 计 0.5×权重,不要当失败
6 如何表达 REQUEST_CHANGES 裁决 自动门禁刻意不替人按 approved/rejected 用建议性 common 评论 + 标题标注裁决 + 打 gatekeeper:needs-changes 标签表达
7 打标签报「标签不存在」 该 label 尚未在仓库创建 label +list 查,缺则 label +create 再挂到 issue
8 auto_merge 开了却没合并 三条件未同时满足 verdict==PASS + 命令带 --apply + 策略 auto_merge: true
9 评分卡对 draft PR 给出裁决 草稿 PR 不应被门禁裁决 检测 draft 标志,提示先转 Ready for Review
10 大仓库只看到前 20 条 PR/构建/标签 列表接口默认分页 limit=20 --page / --limit 翻页,按 meta.total_count 判完整
11 --state open 仍返回已合并/关闭的 PR GitLink --state 仅影响计数 用返回里的 pull_request_status 客户端过滤
12 pr +merge--do 不是已知 flag flag 名记错(do 是底层 API 字段) CLI flag 是 --method/-m,不是 --do

1. 找不到 gatekeeper.yaml(回退默认)

症状:运行时提示「未在仓库根目录找到 gatekeeper.yaml」,或评分卡页脚 policy: 显示为内置默认而非你期望的文件。

原因:策略文件默认从仓库根目录gatekeeper.yaml 读取。当根目录没有该文件、且命令未带 --policy <path>gatekeeper 不会报错中止,而是按设计回退到内置默认策略(见 REFERENCE.md 的默认值:pass=85 / request_changes=60,权重 40/20/15/15/10)。

解决

  • 若你确实想用默认策略 —— 这是正常行为,无需处理;评分卡页脚会标 policy: built-in@v1
  • 若你有自定义策略 —— 确认文件确实在仓库根,或显式指定路径:
# 显式指定策略文件(路径相对当前工作目录)
gitlink-gatekeeper --policy ./policies/gatekeeper.strict.yaml --pr 42

# 把示例策略复制到仓库根,让默认查找命中
cp skills/gitlink-gatekeeper/examples/gatekeeper.yaml ./gatekeeper.yaml

注意:策略文件路径区分大小写;Gatekeeper.yamlgatekeeper.yml.yml 后缀)都不会被默认查找命中。


2. weights 之和不等于 100

症状加载策略时报错「weights 之和必须为 100当前为 <n>gatekeeper 拒绝按该策略评分。

原因:评分算法要求五个维度权重之和严格等于 100,这样 total ∈ 0..100 才有可比性与可复现性。常见错误是只改了一两个维度、忘了让其余维度补平。

解决:调整 weights,使五项相加正好 100。

weights:
  review_findings: 40
  test_coverage:   20
  pr_hygiene:      15
  commit_quality:  15
  ci_status:       10   # 40+20+15+15+10 = 100 ✅
错误示例 问题
40/20/15/15/5 95 少 5需补到某一维度
50/20/15/15/10 110 多 10把 review 降回 40

注意:维度名必须是这五个固定键(review_findings/test_coverage/pr_hygiene/commit_quality/ci_status),多写或漏写键也会校验失败。某维度想「不计分」应把权重设 0 并把差额加到别处,而不是删除该键。


3. 401 / 403 认证与权限错误

症状:任意数据采集命令返回

{"ok": false, "error": {"code": 401, "message": "请登录后再操作", "suggestion": "请先运行 gitlink-cli auth login 登录"}}

403(拒绝访问)。

原因(详见 gitlink-shared/SKILL.md「认证错误处理」):

  • 401:未登录或 Token 已过期。GitLink Token 有效期 7 天,过期需重新登录。
  • 403:已登录但对该 owner/repo 无权限,或 owner/repo 解析错误。

解决

# 401重新登录
gitlink-cli auth login
gitlink-cli auth status        # 确认登录态

# 403核对上下文在仓库目录下可从 git remote 自动解析)
gitlink-cli repo +info --owner <owner> --repo <repo> --format json

注意gatekeeper 全程不回显 Token。若 auth status 正常但仍 403,多半是 owner/repo 写错或你只有读权限——读权限足够采集与生成评分卡dry-run但写评论、打标签、合并需要写权限。


4. PR diff 过大需分段

症状gitlink-cli pr +diff -i <id> --format json 返回内容极大,超出单次处理窗口,或采集很慢/报频率限制。

原因:大型 PR 的全量 diff 一次返回会非常大(gitlink-sharedgitlink-code-review 均提示 pr +diff 输出可能很大需分段处理files/diff 接口有频率限制)。

解决:先用 pr +files 拿到文件清单,只对与评分相关的源码/测试文件按文件取 diff

# 1. 先取文件清单(轻量),用于 test_coverage 维度与体量判断
gitlink-cli pr +files -i <id> --format json

# 2. 对单个文件取差异(避免一次拉全量)
gitlink-cli pr +version-diff -i <id> -v <version-id> -f path/to/file.go --format json
#   version-id 从 pr +versions -i <id> 获取patchset 版本)

注意:test_coveragepr_hygiene 的体量判定只依赖文件清单changed_src/changed_tests/changed_files),不需要全量 diff只有 review_findingsAI 审查)才需要看 diff 内容。所以分段时优先保证文件清单完整diff 可按文件懒加载。避免短时间内重复请求 files/diff 接口。


5. CI 状态取不到(按 unknown 处理)

症状:评分卡 CI status 行显示 unknown,得分为权重的一半(默认 10 → 5)。

原因gitlink-cli ci +builds 返回的是仓库的构建列表,并不保证能定位到正好对应当前 PR 头部 commit 的那次构建——仓库可能没配 CI、构建尚未触发、或无法把构建与该 PR 的 commit 关联。此时 CI 既非「通过」也非「失败」,而是未知

原因细节与评分映射(见 REFERENCE.md 3.5

CI 情况 ci_status 得分(权重 10 时)
找到对应构建且通过 10
找到对应构建且失败 0
取不到 / 无 CI / 无法关联 5round(10 * 0.5)

解决

  • 这是预期的降级行为,不是 bug取不到就当 unknown,给一半分,不要当成失败而误触发 require_ci_pass 硬门禁。
  • 若希望 unknown 也拦截,可在策略里收紧(但要清楚这会拦下没配 CI 的仓库)。默认 require_ci_pass: true 的语义是「CI 明确失败才拦」,unknown 不触发硬门禁。
# 排查:先看仓库到底有没有构建记录
gitlink-cli ci +builds --limit 20 --format json

注意:硬门禁 require_ci_pass 只在 CI 明确失败时命中;unknown 不算失败、不触发硬门禁,仅按 0.5×权重计分。


6. 如何表达 REQUEST_CHANGES 裁决(为何用评论而非 rejected

症状:纠结要不要用 GitLink review 的 rejected 状态把 gatekeeper 的 REQUEST_CHANGES 裁决"硬"标到 PR 上。

原因 / 设计选择GitLink 原生 PR review 的 statuscommon/approved/rejectedrejected 即"请求修改"的等价)。但 approved/rejected强语义的人工授意动作。gatekeeper 是自动门禁,刻意不替人按下 approved/rejected —— 所有自动裁决(含 REQUEST_CHANGES一律以建议性的 common 评论回写,把强语义留给维护者。

解决:用「评论 + 标签」组合表达裁决(这正是本作品复用 label 命令的原因):

  1. 评分卡以 pr +comment(或 pr +review --status common)回写,标题里明确标注裁决Verdict: ❌ REQUEST_CHANGES),一眼可读;
  2. 同时打上状态标签 gatekeeper:needs-changes,让状态可被列表/过滤识别。
# 评分卡回写(标题已含裁决,正文是评分卡)—— 与 workflow 脚本一致,走 pr +comment
gitlink-cli pr +comment -i <id> -b "$(cat scorecard.md)"
#   也可作为评审记录gitlink-cli pr +review -i <id> --status common --content "$(cat scorecard.md)"

注意gatekeeper 绝不自动发 approved/rejected —— 那是维护者的权限。裁决的「拦截」语义靠标题文字 + gatekeeper:needs-changes 标签承载。


7. label 不存在,需先 create

症状:打标签时提示标签不存在,或 issue_tag_ids 里传了一个查不到的 ID。

原因gatekeeper.yaml 里配置的 labelsgatekeeper:pass / gatekeeper:needs-changes / gatekeeper:review)只是名字,仓库里未必已经创建对应的 label 实体。给 PR/Issue 挂标签时用的是 label 的数字 ID,名字对不上数据库里就没有,自然挂不上。

解决:先查后建——先用 label +list 看标签是否存在并拿到 ID缺的用 label +create 创建(注意 label只有 +list/+create/+update/+delete没有 +view

# 1. 查标签是否已存在,拿 id--only-name true 只返回 id+name便于解析
gitlink-cli label +list --keyword gatekeeper --only-name true --format json

# 2. 缺失则创建color 为十六进制,缺省有内置默认色)
gitlink-cli label +create -n "gatekeeper:needs-changes" -d "Gatekeeper requested changes" -c "#D73A4A" --format json
gitlink-cli label +create -n "gatekeeper:pass"          -d "Gatekeeper passed"            -c "#0E8A16" --format json
gitlink-cli label +create -n "gatekeeper:review"        -d "Gatekeeper left comments"     -c "#FBCA04" --format json

# 3. 把标签 id 挂到 PR 背后的 issue用 PR 关联的 issue.id非 PR 号;先取:)
ISSUE_ID=$(gitlink-cli pr +view -i <pr> --format json | jq -r '.data.issue.id')
#    更新时需带 done_ratio/subject/description见 gitlink-shared
gitlink-cli api POST /:owner/:repo/issues/$ISSUE_ID --body '{
  "issue_tag_ids": [<tag_id>],
  "done_ratio": 0,
  "subject": "<原始标题>",
  "description": "<原始描述>"
}'
#    也可用 gitlink-cli issue +update它会自动保留 subject/description免手动回传。

注意:标签是幂等创建——重复 +create 同名标签前应先 +list 检查,避免产生重名标签。更新 issue 挂标签时务必带上当前 subject/description,否则可能清空描述(gitlink-shared 已警示)。


8. auto_merge 想生效但没合并(需三者同时满足)

症状:策略里写了 auto_merge: true,跑完却没有合并 PR。

原因:这是故意的安全设计,不是 bug。gatekeeper 绝不轻易合并,合并必须三个条件同时成立

条件 来源 缺了会怎样
verdict == PASS 评分结果 非 PASSCOMMENT/REQUEST_CHANGES一律不合并
命令带 --apply 运行参数 不带则全程 dry-run只打印不写不合并
策略 auto_merge: true gatekeeper.yaml 默认 false,不会合并

三者缺一不可。最常见的是忘了 --apply(默认 dry-run或裁决其实不是 PASS。

解决

# 先 dry-run 看裁决是不是 PASS默认就是 dry-run不写任何东西
gitlink-gatekeeper --pr <id>

# 确认 PASS 且策略 auto_merge: true 后,显式带 --apply 才会合并
gitlink-gatekeeper --pr <id> --apply

# 底层合并命令CLI flag 是 --method不是 --do详见 #12
gitlink-cli pr +merge -i <id> --method squash --format json

注意:merge_methodmerge/rebase/squash)由策略 behavior.merge_method 决定,映射到 pr +merge --method。即便三条件都满足,合并前也应向用户复述「将以 <method> 合并 PR #」。


9. 草稿draftPR

症状:对一个还是草稿状态的 PR 跑出了正式裁决;作者反馈「我还没写完」。

原因:草稿 PR 通常尚未完成描述未补、测试未加、commit 未整理),此时打门禁裁决意义不大,且容易误伤——gitlink-code-review 也建议对 draft PR 先提示作者转 Ready for Review。

解决:采集 PR 元信息后检查草稿标志(pr +view 返回里的 draft / WIP 标记,或标题含 WIP/[Draft]),命中则不出裁决,只提示:

gitlink-cli pr +view -i <id> --format json   # 检查是否 draft / 标题含 WIP

注意:可在 dry-run 下对 draft PR 生成「预览评分卡」帮作者自查,但不回写评论、不打标签、不合并,直到 PR 转为 Ready for Review。


10. 分页 / 大仓库(列表只看到一页)

症状:大仓库里 pr +list / ci +builds / label +list 只返回 20 条,漏掉了你要找的 PR、构建或标签。

原因:列表类接口默认分页,limit 默认 20、page 默认 1。返回 Envelope 的 meta 里有 page/limit/total_count,但不会自动翻页

解决:按 meta.total_count 判断是否还有下一页,循环翻页直到取全:

# 第一页,先看 meta.total_count
gitlink-cli pr +list --state open --page 1 --limit 50 --format json
# 还有更多则继续翻页
gitlink-cli pr +list --state open --page 2 --limit 50 --format json

# 构建、标签同理
gitlink-cli ci +builds --page 1 --limit 50 --format json
gitlink-cli label +list --page 1 --limit 50 --format json

注意:把 limit 适当调大(如 50可减少请求轮次但 files/diff 接口有频率限制,翻页时不要过于密集。评分只针对单个 PR,分页主要用于「先在列表里定位到目标 PR 号」这一步。


11. 用 --state 过滤 PR 不准

症状gitlink-cli pr +list --state open 返回的列表里混进了已合并 / 已关闭的 PR。

原因GitLink 的真实行为(gitlink-shared 已记录)——--state 参数仅影响统计计数,返回的列表可能包含所有状态。不能只信 --state

解决:在客户端用每条 PR 的 pull_request_status 字段二次过滤:

pull_request_status 含义
0 open
1 merged
2 closed

gatekeeper 只对 pull_request_status == 0open的 PR 做裁决;对已 merged/closed 的应跳过并提示。

注意:这是平台行为,不是 CLI bug。任何依赖「PR 是否仍 open」的逻辑如批量门禁扫描都必须以 pull_request_status 为准,而非 --state


12. pr +merge 的 flag 是 --method,不是 --do

症状:执行 gitlink-cli pr +merge -i <id> --do squash 报错「未知 flag --do」。

原因do 是 GitLink 合并 APIPOST .../pulls/:id/pr_merge)的底层请求字段名;而 gitlink-cli 暴露给用户的 flag 名是 --method(短选项 -m,默认值 merge。两者不要混淆——文档/笔记里若看到 --do 是记错了。

解决

# 正确:用 --method / -m
gitlink-cli pr +merge -i <id> --method squash --format json
gitlink-cli pr +merge -i <id> -m rebase       --format json

# 合并方式取值merge | rebase | squash缺省 merge

注意gatekeeper 的 behavior.merge_method 直接对应 --method。合并仍受 #8 的三条件约束PASS + --apply + auto_merge: true)。


还没解决?

  1. --debug 重跑,看原始请求/响应(gitlink-cli ... --debug)。
  2. --format json 拿结构化输出,核对 error.code / error.suggestion 与本文对照。
  3. 回到 SKILL.md 重走工作流,确认每步命令与参数;字段/算法/阈值一律以 REFERENCE.mdSSOTREFERENCE.md 为准。
  4. 始终遵守安全默认:默认 dry-run、绝不自动合并、写操作前复述意图、不回显 Token。