mcpField
R
respond-pr-feedback

respond-pr-feedback

github.com/existential-birds开发8560 次安装11 周前更新
代码仓库

关于 respond-pr-feedback

respond-pr-feedback 是用于回复 PR 审查评论的技能,要求先评估反馈并完成修复或确定回应方式。默认在回复后解决可匹配的审查讨论串,也可用 `--no-resolve` 保留未解决状态。

主要功能

  1. 01指定 PR 或使用当前分支 PR
  2. 02筛选尚未回复的审查评论
  3. 03先回复,再解决讨论串
  4. 04将评论映射到审查讨论串 ID
  5. 05可选择跳过解决讨论串

适用场景

  1. 01修复代码后回复审查意见
  2. 02向审查者说明设计选择
  3. 03保留讨论串以便后续跟进

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/existential-birds/beagle --skill respond-pr-feedback

安装后在 Claude Code 中输入/respond-pr-feedback确认已加载。

详细介绍

回复 PR 反馈

评估反馈并完成修复后,回复评审评论。默认情况下会解决对话线程。

用法

调用 respond-pr-feedback 技能,可选择传入以下标志:

respond-pr-feedback [--pr <number>] [--no-resolve]

标志:

  • --pr <number> - 指定目标 PR 编号(默认为当前分支对应的 PR)
  • --no-resolve - 发布回复后跳过解决线程(默认:全部解决)

前提条件

先运行 fetch-pr-feedback 技能,以评估反馈并进行任何必要的修复。

硬性门槛(按顺序执行)

只有在满足每项通过条件后才能继续(基于客观检查,不可假定已完成)。

  1. 已满足前提条件: 你已运行 fetch-pr-feedback 技能,评估了每个线程,并针对每个线程应用了修复或选择了明确的回复策略(不得盲目发布回复)。
  2. 已加载上下文: 第 2 步的命令以 0 退出;从 gh pr view、gh repo view 和 gh api user 解析出的值均非空,并已赋给 $PR_NUMBER、$PR_AUTHOR、$OWNER、$REPO、$CURRENT_USER——绝不可臆造所有者、仓库或 PR 编号。
  3. 已确定队列: 第 3a 步的 jq 以 0 退出。如果筛选后的列表为空,则准确输出 All review comments have been addressed. 并停止(不要调用回复或 GraphQL 解决 API)。
  4. 先回复,再解决: 对每条目标评论,第 4 步的 gh api .../replies 必须先以 0 退出,然后第 5 步才能尝试解决该评论对应的线程(除非传入了 --no-resolve)。
  5. 根据映射解决: 只有当第 3b 步为相应评论的 ID 提供了 threadId 时,第 5 步才调用 resolveReviewThread;如果没有映射,则跳过该项的解决操作,不视为失败。

指令

1. 解析参数

从 $ARGUMENTS 中提取标志:

  • --pr <number>,或从当前分支检测
  • --no-resolve 标志(布尔值,默认为 false)
2. 获取 PR 上下文
# Get PR info (if --pr not specified, uses current branch)
gh pr view --json number,author --jq '{number, author: .author.login}'

# Get repo owner/name
gh repo view --json owner,name --jq '{owner: .owner.login, name: .name}'

# Get current authenticated user
gh api user --jq '.login'

保存为 $PR_NUMBER、$PR_AUTHOR、$OWNER、$REPO、$CURRENT_USER。

注意: $OWNER、$REPO 等是占位符。请替换为前序步骤获取的实际值。

3. 获取尚未回复的评论和线程数据
3a. 尚未回复的评审评论

获取评审评论,排除 PR 作者和当前用户的评论,并筛选出尚未收到回复的根评论。

使用带单引号分隔符的 heredoc 将 jq 筛选条件写入临时文件(避免 !=、正则表达式模式和尖括号的 shell 转义问题):

cat > /tmp/unreplied_comments.jq << 'JQEOF'
add // [] |
# Root comments from reviewers (not replies, not PR author, not current user)
[.[] | select(
  .in_reply_to_id == null and
  .user.login != $pr_author and
  .user.login != $current_user
)] as $roots |
# IDs that current user has already replied to
[.[] | select(.user.login == $current_user) | .in_reply_to_id] as $replied |
# Filter to unreplied only
$roots | map(select(. as $c | $replied | index($c.id) == null)) |
# Dedup: group by path + line + reviewer, pick newest per group
group_by({
  p: .path,
  l: (.line // .original_line),
  u: .user.login
}) |
map(sort_by(.created_at) | last) |
# Output needed fields
map({
  id,
  user: .user.login,
  path,
  line_display: (
    .line as $end | .start_line as $start |
    if $start and $start != $end then "\($start)-\($end)"
    else "\($end // .original_line)" end
  ),
  body
})
JQEOF
gh api --paginate "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" | \
  jq -s --arg pr_author "$PR_AUTHOR" --arg current_user "$CURRENT_USER" \
  -f /tmp/unreplied_comments.jq

如果没有找到尚未回复的评论,则输出:"All review comments have been addressed." 并停止。

3b. 预先获取线程数据

获取评审线程 ID,以便在发布回复后解决线程:

gh api graphql -f query="
  query {
    repository(owner: \"$OWNER\", name: \"$REPO\") {
      pullRequest(number: $PR_NUMBER) {
        reviewThreads(first: 100) {
          nodes {
            id
            isResolved
            comments(first: 1) {
              nodes { databaseId }
            }
          }
        }
      }
    }
  }
"

构建查找映射:评论 databaseId → 线程 id(仅限未解决的线程)。这样便可在发布每条回复后立即解决对应线程。

4. 生成并发布回复

对于每条尚未回复的评论,根据你的评估确定合适的回复:

评估结果回复
反馈不正确或无事实依据解释当前代码为何正确
反馈缺少上下文解释设计决策
反馈有效且已修复"已在 $COMMIT_SHA 中修复",或简要描述所做的更改
反馈有效但不会修复解释权衡或决策

标记指南: 对机器人评审者使用 @ 标记(例如 @coderabbitai),以触发其处理。不要使用 @ 标记人工评审者。

对每条评论发布回复:

gh api "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies" \
  -X POST --raw-field body="$RESPONSE"
5. 解决线程

默认执行此步骤。 只有传入 --no-resolve 时才跳过。

发布每条回复后,使用该评论的 $COMMENT_ID,从第 3b 步的映射中查找 $THREAD_ID:

gh api graphql -f query="
  mutation {
    resolveReviewThread(input: {threadId: \"$THREAD_ID\"}) {
      thread { isResolved }
    }
  }
"
  • 如果评论的 $COMMENT_ID 有对应的线程 ID,则解决该线程
  • 如果找不到线程 ID(例如,该评论是问题评论,而非评审线程),则跳过对该评论的线程解决操作
6. 输出摘要

按评审者分组:

### Reviewer: coderabbitai[bot]

| File:Line | Response Type | Thread |
|-----------|---------------|--------|
| `src/foo.ts:42` | Fixed in `abc1234` | Resolved |
| `src/bar.ts:15` | Explained design | Resolved |

### Reviewer: octocat

| File:Line | Response Type | Thread |
|-----------|---------------|--------|
| `src/baz.ts:7` | Won't fix | Resolved |

页脚:

**Threads resolved: 3/3**

回复指南

  • 使用 @ 标记机器人审查者以触发重新处理;不要标记人工审查者
  • 回复应简洁且专业
  • 不要敷衍附和(“说得太好了!”,“你说得对!”)
  • 解释决策时,引用具体代码或设计
  • 如果问题已修复:说明改动内容,不要致谢

示例

# Respond to all reviewers on current PR (resolves threads)
respond-pr-feedback

# Respond on a specific PR
respond-pr-feedback --pr 123

# Respond without resolving threads
respond-pr-feedback --no-resolve

评论

支持 Markdown