DEV Community

Cover image for 5 Different Ways to Get Contributors through the GitHub API
Abdurrahman Rajab for Hadith Tech

Posted on

5 Different Ways to Get Contributors through the GitHub API

Have you ever considered getting information about some Git projects and creating your dashboard to analyze them? This blog will help you by giving you the initial part of such a project which is getting the contributors of a project. So let's start:

This blog uses the GitHub API to explore various methods to retrieve contributors' information from a GitHub project. Remember that the API only shows the first 500 contributors associated with a GitHub username, with the rest appearing as anonymous contributors.

To begin, let's check the GitHub API documentation to understand the available information and endpoints:

List Contributors Endpoint

/repos/{owner}/{repo}/contributors
Enter fullscreen mode Exit fullscreen mode

The endpoint provides information about the contributors to a project. We'll use the optional headers to minimize API requests.

1. Fetch API Iterative

The following code provides a straightforward approach to fetching contributors. We split the process into two steps for code simplicity. First, we request the endpoint and then check if we have reached the end of the list.

async function getContributors(repoName, page = 1) {  
    let request = await fetch(`https://api.github.com/repos/${repoName}/contributors?per_page=100&page=${page}`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
        }
    });

    // print data from the fetch on screen
    let contributorsList = await request.json();
    return contributorsList;
};
Enter fullscreen mode Exit fullscreen mode

In this function, we have passed the repo name as a param and the page as well, and we kept the per_page as a maximum of 100 based on documentation.

per_page is The number of results per page (max 100).
Enter fullscreen mode Exit fullscreen mode

We will now write a function to iterate over the request and collect all the contributors.

To do this, we will do the next:

  • have a contributors list to add the date to it.
  • iterate over the whole pages and get contributors
  • stop if we got an empty list.
  • return the contributors list
async function getAlllContributors(repoName) {
    let contributors = [];
    let page = 1;
    do {
        list = await getContributors(repoName, page);
        contributors = contributors.concat(list);
        page++;
    } while (list.length > 0);
    // while (list.length%100 !== 0)
    return contributors;
}
Enter fullscreen mode Exit fullscreen mode

In this approach, we used a do-while loop to get the contributors at the first request and move with that. This approach will return us all the contributors we need.

As for the condition we have in the do-while loop, we can use another one, which is

list.length%100 !== 0
Enter fullscreen mode Exit fullscreen mode

If we do this, it will return the same result, but we will control if the request returns the maximum results per page.

2. Fetch API recursive

Alternatively, we can write the code recursively. This version continues fetching contributors until we reach the end of the list.

Here are the steps:

  • getting all contributors
  • if it's the end of the list, return the whole list
  • otherwise, call the function again.
async function getAllContributorsRecursive_version1(repoName, page = 1, contributors = []) {

    const list = await getContributors(repoName, page);
    if (list.length === 0) {
        return contributors;
    }
    contributors = contributors.concat(list);
    return getAllContributors(repoName, page + 1, contributors);

}
Enter fullscreen mode Exit fullscreen mode

The getContributors method here is similar to the one in the first example.

We can do this in similar logic but with a different approach by doing the next:

  • get contributes
  • if there is a list, call the function again
  • if the list is done, return all contributors.
async function getAllContributorsRecursive(repoName, page = 1, allContributors = []) {
    const list = await getContributors(repoName, page);
    allContributors = allContributors.concat(list);
    if (list.length === 100) {
        return getAllContributorsRecursive(repoName, page + 1, allContributors);
    }
    // The base case: when the list is empty, return allContributors
    return allContributors;
}
Enter fullscreen mode Exit fullscreen mode

3. Octokit Request

Octokit will be handy if you want to use the official GitHub package for the request. You can reach the GitHub repo from this link OctoKit. The Octokit package provides official support for GitHub API requests. It offers features and authentication options for larger requests. Here's how you can use it to fetch contributors:

await octokit.request("GET /repos/{owner}/{repo}/contributors", {
  owner: "octocat",
  repo: "hello-world",
  per_page: 100, 
  page: 1,
});
Enter fullscreen mode Exit fullscreen mode

4. Octokit Rest

An alternative way to write the previous code is to use the rest endpoints, which is a shorthand for that code, and you can get the documentation in the next link docs

async function getContributorsOctoKit(repo, owner, page = 1) {
    return request = await octokit.rest.repos.listContributors({
        owner,
        repo,
        per_page: 100,
        page
    });
}
Enter fullscreen mode Exit fullscreen mode

Right now, we can iterate over the whole code in a similar way to the fetch that we have done before,

async function rest(){
    let contributors = [];
    let page = 1;
    let request;    
    do {
        request = await getContributorsOctoKit("tensorflow", "tensorflow", page);
        page++;
        contributors = contributors.concat(request.data);
    } while (request.data.length > 0);
    return contributors;
}
Enter fullscreen mode Exit fullscreen mode

5. Octokit paginate

Lastly, Octokit provides a convenient pagination function for easy iteration over API responses. Here's how you can use it to fetch contributors:

async function paginate(){
    let contributors = [];
    const iterator = octokit.paginate.iterator(octokit.rest.repos.listContributors, {
        owner: "tensorflow",
        repo: "tensorflow",
        per_page: 100,
    });
    // iterate through each response
    for await (const { data: users } of iterator) {
        for (const user of users) {
            contributors.push(user);
        }
    }
    return contributors;
}
Enter fullscreen mode Exit fullscreen mode

These five methods provide various ways to retrieve all repository contributors using the GitHub API. You can use these methods to gain insights into your projects and customize them for other GitHub REST API endpoints. If you'd like to test the code examples, you can find them in this repository. The repo is ready to be debugged with VsCode.

Finally, feel free to follow Hadith Tech Newsletter to get insights from tech leaders.

Useful resources:

Acknowledgment:

Header image

Top comments (1)

Collapse
 
a0m0rajab profile image
Abdurrahman Rajab • Edited

A feedback from Bassem Dghaidi:

Nice write-up! I think these calls can be made better by:

  1. Implementing a timeout on the calls
  2. Checking for API rate limitations if you're not authenticated you can only make 60 calls per hour and then you're blocked (both REST and GraphQL)
  3. Putting some boundaries on the pagination so that it doesn't spiral out of control