forked from typescript-eslint/typescript-eslint
-
Notifications
You must be signed in to change notification settings - Fork 1
/
generate-contributors.ts
120 lines (105 loc) · 3.21 KB
/
generate-contributors.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// this script uses the github api to fetch a list of contributors
// https://developer.github.com/v3/repos/#list-contributors
// this endpoint returns a list of contributors sorted by number of contributions
import * as fs from 'fs';
import fetch from 'node-fetch';
import * as path from 'path';
const IGNORED_USERS = new Set([
'dependabot[bot]',
'eslint[bot]',
'greenkeeper[bot]',
'semantic-release-bot',
]);
const COMPLETELY_ARBITRARY_CONTRIBUTION_COUNT = 3;
const PAGE_LIMIT = 100;
const contributorsApiUrl = `https://api.github.com/repos/typescript-eslint/typescript-eslint/contributors?per_page=${PAGE_LIMIT}`;
interface Contributor {
contributions: number;
login: string;
url: string;
}
interface User {
login: string;
name: string;
avatar_url: string;
html_url: string;
}
interface AllContributorsUser {
login: string;
name: string;
avatar_url: string;
profile: string;
contributions: string[];
}
async function* fetchUsers(page = 1): AsyncIterableIterator<Contributor[]> {
let lastLength = 0;
do {
const response = await fetch(`${contributorsApiUrl}&page=${page}`, {
method: 'GET',
});
const contributors = (await response.json()) as
| Contributor[]
| { message: string };
if (!Array.isArray(contributors)) {
throw new Error(contributors.message);
}
const thresholdedContributors = contributors.filter(
user => user.contributions >= COMPLETELY_ARBITRARY_CONTRIBUTION_COUNT,
);
yield thresholdedContributors;
lastLength = thresholdedContributors.length;
} while (
/*
If the filtered list wasn't 100 long, that means that either:
- there wasn't 100 users in the page, or
- there wasn't 100 users with > threshold commits in the page.
In either case, it means that there's no need to fetch any more pages
*/
lastLength === PAGE_LIMIT
);
}
async function main(): Promise<void> {
const githubContributors: Contributor[] = [];
// fetch all of the contributor info
for await (const lastUsers of fetchUsers()) {
githubContributors.push(...lastUsers);
}
// fetch the user info
const users = await Promise.all(
githubContributors.map(async c => {
const response = await fetch(c.url, { method: 'GET' });
return (await response.json()) as User;
}),
);
const contributors = users
// remove ignored users
.filter(u => !IGNORED_USERS.has(u.login))
// fetch the in-depth information for each user
.map<AllContributorsUser>(usr => {
return {
login: usr.login,
name: usr.name || usr.login,
avatar_url: usr.avatar_url,
profile: usr.html_url,
contributions: [],
};
});
// build + write the .all-contributorsrc
const allContributorsConfig = {
projectName: 'typescript-eslint',
projectOwner: 'typescript-eslint',
repoType: 'github',
repoHost: 'https://github.com',
files: ['CONTRIBUTORS.md'],
imageSize: 100,
commit: false,
contributors,
contributorsPerLine: 5,
};
const rcPath = path.resolve(__dirname, '../.all-contributorsrc');
fs.writeFileSync(rcPath, JSON.stringify(allContributorsConfig, null, 2));
}
main().catch(error => {
console.error(error);
process.exitCode = 1;
});