我如何构建了一个检查 GitHub issue 是否已有 PR 的工具——以及它为何是没人实现的功能

发布: (2026年5月5日 GMT+8 11:30)
5 分钟阅读
原文: Dev.to

Source: Dev.to

问题

寻找一个适合初学者的 issue,fork 仓库,搭建开发环境,阅读代码库会让人感觉很棒——直到你再次查看该 issue,看到最近的评论类似于:

“嘿,我正在处理这个,应该很快就会有 PR。”

浪费了两个小时。这种情况反复出现,因为大多数 issue 发现工具(例如 goodfirstissue.dev、up‑for‑grabs.net、codetriage)依赖静态列表或定期抓取。它们会展示 issue,但并不会告诉你是否已经有人在悄悄处理这些 issue。

介绍 GitTrek

GitTrek 填补了这一空白。它会寻找开发者在开始处理问题时留下的“数字痕迹”:

痕迹类型出现方式
PR 提及在 PR 描述或提交信息中提及了问题编号(例如 Fixes #847)。
关联分支通过 GitHub 的 UI 从该问题创建分支,然后从该分支打开 PR。

这两种痕迹都可以通过 GitHub 的 GraphQL API 访问,具体是通过 issue 上的 timelineItems 字段。

相关 GraphQL 事件

  • CROSS_REFERENCED_EVENT – 当 PR 或提交提及 issue 编号时触发。该 PR 是事件的 source(来源)。
  • CONNECTED_EVENT – 当与 issue 关联的分支变为 pull request 时触发。该 PR 是事件的 subject(主体)。

专业提示: 混淆 sourcesubject 会导致返回 null,但不会报错。

示例查询

issue(number: $issueNumber) {
  timelineItems(
    first: 25,
    itemTypes: [CROSS_REFERENCED_EVENT, CONNECTED_EVENT]
  ) {
    nodes {
      ... on CrossReferencedEvent {
        source {
          ... on PullRequest {
            number
            state      # OPEN | CLOSED | MERGED
            isDraft
          }
        }
      }
      ... on ConnectedEvent {
        subject {
          ... on PullRequest {
            number
            state
            isDraft
          }
        }
      }
    }
  }
  linkedBranches(first: 3) {
    totalCount
  }
}

GitTrek 如何可视化竞争

GitTrek 根据上述数据对每个 issue 进行颜色编码:

徽章含义
Active PR存在未草稿的打开 PR —— 竞争激烈
Someone started已关联草稿 PR —— 请谨慎操作
Branch existslinkedBranches > 0 但尚未有 PR —— 早期信号
Safe to claim未发现关联的 PR 或分支

检查 20 条 issue 需要 21 次 API 调用(1 次搜索 + 20 次状态检查)。为了保持 UI 的流畅性,GitTrek 会立即显示 issue 列表,并在后台并行“填充”徽章。

在后台填充徽章

// Fetch fresh data from APIs in the background
// This ensures one badge failure doesn't block the entire dashboard
const settlements = await Promise.allSettled([
  fetch(`/api/github/badges/pull-shark?username=${user}`).then(r => r.json()),
  fetch(`/api/github/badges/starstruck?username=${user}`).then(r => r.json()),
  // ... more badge checks
]);

// Safely extract results even if some failed
const [pullShark, starstruck, ...] = settlements.map(s =>
  s.status === "fulfilled" ? s.value : null
);

// Apply fallback values for failed items
const psData = pullShark || { count: 0 };

使用 Promise.allSettled 而不是 Promise.all,可以防止单个检查失败(例如权限问题或速率限制)导致整个仪表盘中断。

超越“ghost PR”检测

  • Repository Quality Gates – 按星标、分叉数以及是否存在 CONTRIBUTING.md 进行过滤。
  • Live Achievement Tracking – 使用实时 GraphQL 计算,监控获取 Pull Shark、Galaxy Brain、YOLO 等徽章的进度。
  • Focus Mission – 当你离某个徽章只差几次 PR 时,GitTrek 会构建自定义搜索查询,精准呈现你需要的 Issue。

入门

  • Live app:
  • Source code:

GitTrek 是免费、开源的,浏览时无需任何设置。仅在您想要个性化徽章跟踪时,才连接您的 GitHub 账户。

您的体验

您是否曾在已经有人在处理的问题上浪费时间? 在评论中分享您的故事——想了解这实际上有多常见。

0 浏览
Back to Blog

相关文章

阅读更多 »

自己制作框架,有什么建议吗?

《Making my own framework》的封面图片。有什么建议吗?https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fde...

开源并不意味着开放社区

开源软件早在 DVCS 发明之前就已经存在。作者可能托管了一个简陋的 HTML 页面或一个纯文本文件来描述该项目……

开源并不意味着开放社区

开源软件早在 DVCS 发明之前就已经存在。作者可能只托管了一个简陋的 HTML 网页或一个 txt 文件来描述该项目......