Skip to content

Instantly share code, notes, and snippets.

@HazAT
Last active May 8, 2024 08:32
Show Gist options
  • Save HazAT/c880a58f129bd0fb1762bf00cb3bd016 to your computer and use it in GitHub Desktop.
Save HazAT/c880a58f129bd0fb1762bf00cb3bd016 to your computer and use it in GitHub Desktop.
Fetch top 100 external contributors from a github org
const axios = require('axios');
const ORGANIZATION = 'ORG';
const GITHUB_TOKEN = 'GH_TOKEN';
// Get the date one year ago
const oneYearAgo = new Date();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
async function fetchAllMembers() {
let members = [];
let page = 1;
let hasMorePages = true;
while (hasMorePages) {
try {
const response = await axios.get(
`https://api.github.com/orgs/${ORGANIZATION}/members`,
{
headers: {
Authorization: `Bearer ${GITHUB_TOKEN}`,
},
params: {
per_page: 100,
page: page,
},
}
);
members = members.concat(response.data.map((member) => member.login));
hasMorePages =
response.headers.link && response.headers.link.includes('rel="next"');
page++;
} catch (error) {
console.error(`Error fetching members (page ${page}):`, error.message);
hasMorePages = false;
}
}
return members;
}
async function fetchRecentRepos() {
try {
const response = await axios.get(
`https://api.github.com/orgs/${ORGANIZATION}/repos`,
{
headers: {
Authorization: `Bearer ${GITHUB_TOKEN}`,
},
params: {
sort: "updated",
per_page: 100,
},
}
);
return response.data;
} catch (error) {
console.error("Error fetching repositories:", error.message);
return [];
}
}
async function fetchUserEmail(username) {
try {
const response = await axios.get(
`https://api.github.com/users/${username}`,
{
headers: {
Authorization: `Bearer ${GITHUB_TOKEN}`,
},
}
);
return response.data.email;
} catch (error) {
console.error(`Error fetching email for user ${username}:`, error.message);
return null;
}
}
async function fetchTopContributors() {
try {
console.log("Fetching recent repositories...");
const repos = await fetchRecentRepos();
console.log("Fetching organization members...");
const members = await fetchAllMembers();
const contributors = new Map();
console.log("Fetching contributors for each repository...");
for (const repo of repos) {
try {
const contributorsResponse = await axios.get(
`https://api.github.com/repos/${ORGANIZATION}/${repo.name}/commits`,
{
headers: {
Authorization: `Bearer ${GITHUB_TOKEN}`,
"If-Modified-Since": oneYearAgo.toISOString(),
},
}
);
const commits = contributorsResponse.data;
// Include only external contributors (users not part of the organization)
for (const commit of commits) {
const { author } = commit;
if (author && !members.includes(author.login)) {
const login = author.login;
if (contributors.has(login)) {
contributors.set(login, contributors.get(login) + 1);
} else {
contributors.set(login, 1);
}
}
}
console.log(`Processed repository: ${repo.name}`);
} catch (error) {
console.error(
`Error fetching contributors for repository ${repo.name}:`,
error.message
);
}
}
// Sort the contributors by their total contributions in descending order
const sortedContributors = Array.from(contributors.entries()).sort(
(a, b) => b[1] - a[1]
);
// Get the top 100 external contributors
const topContributors = sortedContributors.slice(0, 100);
console.log("Top 100 External Contributors (Last Year):");
for (const [login, contributions] of topContributors) {
const email = await fetchUserEmail(login);
console.log(
`${login};https://github.com/${login};${email};${contributions}`
);
}
} catch (error) {
console.error("Error:", error.message);
}
}
fetchTopContributors();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment