首页 > 解决方案 > 如何获取用户在属于组织的任何 repo 上提出的拉取请求的计数?

问题描述

我正在尝试开发一个评级系统,该系统可以列出在 GitHub 上为我的组织做出最大贡献的个人。我试图通过计算用户在任何组织的存储库中创建的“合并”拉取请求的数量来做到这一点。

我对 GitHub API 有点熟悉,但我很难确定要发出的正确请求。任何帮助将不胜感激。谢谢你们。此外,如果以这种方式计算的贡献也包括私人回购中的贡献,那就更好了。

PS:我不想使用提交次数作为计数,因为这不是一个精确的衡量标准,因为在开发一项功能时,一些用户会一直提交一个文件,而其他用户在创建一堆文件后提交。所以,请不要这样建议。

此外,还有一些无效的拉取请求,或者一些变得陈旧的请求,我不想计算贡献的数量。

标签: githubgithub-api

解决方案


您可以使用搜索查询来查找问题:

  • 类型prtype:pr
  • 作者:author:{some user}
  • 合并:is:merged
  • 在特定的组织中:org:{some org}

搜索查询

org:mui-org author:eps1lon type:pr is:merged

电话是:

https://api.github.com/search/issues?q=org:mui-org%20author:eps1lon%20type:pr%20is:merged

然后过滤总计数,使用的示例:

curl -s "https://api.github.com/search/issues?q=org:mui-org%20author:eps1lon%20type:pr%20is:merged" | \
     jq '.total_count'

输出:

715

你可以做的是使用GraphQL API来:

  • 获取组织中的用户列表
  • 使用别名为每个用户动态构建请求以执行搜索查询

所以你最终只有 2 个请求

中的一个例子:

import requests

token = "YOUR_TOKEN"
org = "mui-org"

userQuery = """
{ 
  organization(login: "%s"){
    membersWithRole(first: 100){
      nodes {
        login
      }
    }
  }
}
"""
pullRequestQuery = """
  %s: search(query: "org:%s author:%s type:pr is:merged", type: ISSUE){
    issueCount
  } 
"""

def makeCall(query):
    r = requests.post("https://api.github.com/graphql",
        headers = {
            "Authorization": f"Bearer {token}"
        },
        json = {
            "query": query
        }
    )
    return r.json()["data"]

userList = makeCall(userQuery % org)

#build a list of keys matching user (user0: johndoe ....)
keyList = {}
for idx, user in enumerate(userList["organization"]["membersWithRole"]["nodes"]):
    keyList[f"user{idx}"] = user["login"]

#build the query
builtQuery = "".join([
    pullRequestQuery % (t, org, keyList[t]) 
    for t in keyList.keys()
])
result = makeCall("{%s}" % builtQuery)

#match the original user login
stats = {}
for it in result.keys():
    stats[keyList[it]] = result[it]["issueCount"]

print(stats)

输出 :

{'kof': 1, 'pelotom': 57, 'mbrookes': 487, 'dtassone': 78, 'sebald': 29, 'hai-cea': 14, 'kgregory': 21, 'oliviertassinari': 2077, 'merceyz': 70, 'nathanmarks': 80, 'mnajdova': 56, 'leMaik': 45, 'DanailH': 4, 'alitaheri': 98, 'm2mathew': 6, 'eps1lon': 715, 'DDDDDanica': 13, 'joshwooding': 110, 'dimitropoulos': 2, 'dmtrKovalenko': 352}

推荐阅读