githubgithub-api

How to get count of pull requests made by a user on any repo belonging to an organization?


I am trying to develop a rating system which can list the individuals who have contributed most to my organization on GitHub. I am trying to do that by counting the number of "merged" pull requests created by an user in any of the org's repo.

I am somewhat familiar with GitHub APIs, but I am facing difficulty figuring out the proper requests to make. Any help will be appreciated. Thank you all. Also, it will be nicer if contributions counted this way include those in private repos also.

PS: I don't want to use number of commits as a count, because that is not a precise measure, as in developing a feature some users keep committing one file at time, while others commit after creating a bunch of them. So, please don't suggest that.

Also, there are invalid pull requests also, or some which turn stale, I don't wanna count those in number of contributions.


Solution

  • You can use a search query to look for issues :

    The search query :

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

    The call would be :

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

    Then filter the total count, an example using and :

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

    Output:

    715
    

    What you could do is using GraphQL API to :

    So you end up with only 2 requests

    An example in :

    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)
    

    output :

    {'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}