Skip to content
This repository was archived by the owner on Nov 18, 2024. It is now read-only.

Commit d3ecefb

Browse files
committed
wip
1 parent 44654bc commit d3ecefb

File tree

4 files changed

+141
-11
lines changed

4 files changed

+141
-11
lines changed

metrics-collector/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"dotenv": "^16.4.5",
2222
"express": "^4.19.2",
2323
"faker": "^6.6.6",
24+
"json2csv": "6.0.0-alpha.2",
2425
"moment": "^2.30.1",
2526
"pg": "^8.11.5",
2627
"ts-node": "^10.9.2",

metrics-collector/pnpm-lock.yaml

+30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
const fs = require('fs');
2+
const { Parser } = require('json2csv');
3+
4+
const filePath = "./gh_contributions_metrics.json";
5+
6+
// Read JSON data from the file
7+
function readJsonFile(filePath) {
8+
if (fs.existsSync(filePath)) {
9+
const data = fs.readFileSync(filePath, "utf8");
10+
return JSON.parse(data);
11+
}
12+
return {};
13+
}
14+
15+
const data = readJsonFile(filePath);
16+
17+
function extractData(data) {
18+
const projects = Object.keys(data);
19+
const allMonths = new Set();
20+
21+
// Collect all months from all projects
22+
projects.forEach(project => {
23+
data[project].forEach(entry => {
24+
const { data } = entry;
25+
Object.values(data).forEach(item => {
26+
Object.keys(item).forEach(month => {
27+
allMonths.add(month);
28+
});
29+
});
30+
});
31+
});
32+
33+
const monthsArray = Array.from(allMonths).sort();
34+
35+
const csvData = [];
36+
37+
projects.forEach(project => {
38+
const projectRows = {
39+
issues: { project: project, type: 'issues' },
40+
internalMemberIssues: { project: project, type: 'internalMemberIssues' },
41+
prs: { project: project, type: 'prs' },
42+
internalMemberPrs: { project: project, type: 'internalMemberPrs' },
43+
comments: { project: project, type: 'comments' },
44+
internalMemberComments: { project: project, type: 'internalMemberComments' }
45+
};
46+
47+
monthsArray.forEach(month => {
48+
projectRows.issues[month] = 0;
49+
projectRows.internalMemberIssues[month] = 0;
50+
projectRows.prs[month] = 0;
51+
projectRows.internalMemberPrs[month] = 0;
52+
projectRows.comments[month] = 0;
53+
projectRows.internalMemberComments[month] = 0;
54+
});
55+
56+
data[project].forEach(entry => {
57+
const { data } = entry;
58+
Object.entries(data).forEach(([key, values]) => {
59+
Object.entries(values).forEach(([month, count]) => {
60+
projectRows[key][month] = (projectRows[key][month] || 0) + count;
61+
});
62+
});
63+
});
64+
65+
csvData.push(projectRows.issues);
66+
csvData.push(projectRows.internalMemberIssues);
67+
csvData.push(projectRows.prs);
68+
csvData.push(projectRows.internalMemberPrs);
69+
csvData.push(projectRows.comments);
70+
csvData.push(projectRows.internalMemberComments);
71+
});
72+
73+
return { csvData, monthsArray };
74+
}
75+
76+
function buildCSV(data) {
77+
const { csvData, monthsArray } = extractData(data);
78+
const fields = ['project', 'type', ...monthsArray];
79+
const opts = { fields };
80+
const parser = new Parser(opts);
81+
const csv = parser.parse(csvData);
82+
83+
fs.writeFileSync('gh_contributions_metrics.csv', csv);
84+
console.log('CSV file created successfully.');
85+
}
86+
87+
buildCSV(data);

metrics-collector/src/gh-contributions.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ let octokit;
99

1010
const orgName = "TBD54566975";
1111
const repos = [
12+
"tbdex",
1213
"tbdex-js",
1314
"tbdex-kt",
1415
"tbdex-swift",
1516
"tbdex-rs",
17+
"web5-spec",
1618
"web5-js",
1719
"web5-kt",
1820
"web5-swift",
1921
"web5-rs",
20-
// "dwn-sdk-js",
22+
"dwn-sdk-js",
23+
"dwn-server",
2124
];
2225

2326
const KNOWN_PAST_MEMBERS = ["amika-sq"];
@@ -26,7 +29,7 @@ const KNOWN_BOTS = ['codecov-commenter', 'dependabot[bot]', 'renovate[bot]'];
2629

2730
// Cache members to avoid rate limiting
2831
const membersCache = new Map(
29-
KNOWN_PAST_MEMBERS.map((kpm) => [kpm, true])
32+
KNOWN_PAST_MEMBERS.map((kpm) => [kpm, 'org'])
3033
);
3134

3235
async function fetchIssues(owner, repo) {
@@ -93,8 +96,8 @@ async function isMember(org, user) {
9396

9497
if (user.type === 'Bot' || KNOWN_BOTS.includes(user.login)) {
9598
console.info("Skipping bot", user.login);
96-
membersCache.set(username, true);
97-
return true;
99+
membersCache.set(username, 'bot');
100+
return 'bot';
98101
}
99102

100103
try {
@@ -105,9 +108,9 @@ async function isMember(org, user) {
105108
if (res.status === 302) {
106109
throw new Error("Forbidden to check membership!");
107110
} else if (res.status === 204) {
108-
membersCache.set(username, true);
111+
membersCache.set(username, 'org');
109112
console.info("member found in org", username);
110-
return true;
113+
return 'org';
111114
} else {
112115
console.info("member not found in org", username);
113116
membersCache.set(username, false);
@@ -134,12 +137,15 @@ async function aggregateData(owner, repo) {
134137
console.info(`Fetched ${issues.length} issues, ${prs.length} PRs, and ${comments.length} comments for ${owner}/${repo}`);
135138

136139
const now = moment();
137-
const beginningTime = now.clone().subtract(3, 'months');
140+
const beginningTime = now.clone().subtract(4, 'months');
138141

139142
const monthlyData = {
140143
issues: {},
144+
internalMemberIssues: {},
141145
prs: {},
142-
comments: {}
146+
internalMemberPrs: {},
147+
comments: {},
148+
internalMemberComments: {},
143149
};
144150

145151
function addToMonthlyData(type, date) {
@@ -151,7 +157,9 @@ async function aggregateData(owner, repo) {
151157
console.info("Computing issues numbers...");
152158
for (const issue of issues) {
153159
const member = await isMember(owner, issue.user);
154-
if (!member && moment(issue.created_at).isAfter(beginningTime)) {
160+
if (member === 'org') {
161+
addToMonthlyData('internalMemberIssues', issue.created_at);
162+
} else if (member !== 'bot') {
155163
addToMonthlyData('issues', issue.created_at);
156164
// print issue details with link
157165
console.info(`[${issue.user.login}]: ${issue.title} (${issue.html_url})`);
@@ -161,7 +169,9 @@ async function aggregateData(owner, repo) {
161169
console.info("Computing PRs numbers...");
162170
for (const pr of prs) {
163171
const member = await isMember(owner, pr.user);
164-
if (!member && moment(pr.created_at).isAfter(beginningTime)) {
172+
if (member === 'org') {
173+
addToMonthlyData('internalMemberPrs', pr.created_at);
174+
} else if (member !== 'bot') {
165175
addToMonthlyData('prs', pr.created_at);
166176
// print PR details with link
167177
console.info(`[${pr.user.login}]: ${pr.title} (${pr.html_url})`);
@@ -171,7 +181,9 @@ async function aggregateData(owner, repo) {
171181
console.info("Computing comments numbers...");
172182
for (const comment of comments) {
173183
const member = await isMember(owner, comment.user);
174-
if (!member && moment(comment.created_at).isAfter(beginningTime)) {
184+
if (member === 'org') {
185+
addToMonthlyData('internalMemberComments', comment.created_at);
186+
} else if (member !== 'bot') {
175187
addToMonthlyData('comments', comment.created_at);
176188
// print comment details with link
177189
console.info(`[${comment.user.login}]: ${comment.body.substring(0, 48)}... (${comment.html_url})`);

0 commit comments

Comments
 (0)