Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase weight of funded PRs #27

Merged
merged 3 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 39 additions & 21 deletions analyse-contributions/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { calculateScore } from "./src/contribution-calculator";
import { calculateScore, CalculatorInput } from "./src/contribution-calculator";
import { formatScore } from "./src/formatter";
import GitHubClient from "./src/github-client";
import { Comment, Issue, PullRequest } from "./src/types";
import { Comment, Issue, PullRequest, User } from "./src/types";

(async () => {
const { AUTH_TOKEN, FROM } = process.env;
Expand All @@ -12,16 +12,45 @@ import { Comment, Issue, PullRequest } from "./src/types";
}

const github = new GitHubClient(AUTH_TOKEN, new Date(FROM));

// Make sure we can connect to the GitHub API
await github.authenticate();

const members = await github.readMembers();
const calculatorInput = await getData(github);
const usersWithScore = await calculateScore(calculatorInput);

// sort users by total score
const sortedUsers = usersWithScore
.sort((a, b) => b.score.total - a.score.total)
.filter(({ score }) => score.total > 0);

// get sum of total scores
const totalScore = sortedUsers
.map(({ score: { total } }) => total)
.reduce((a, b) => a + b, 0);

formatScore(totalScore, sortedUsers);
})();

const uniq = (users: User[]): User[] => {
return users.reduce((acc, user) => {
const userIds = acc.map((_user) => _user.id);
if (!userIds.includes(user.id)) {
acc.push(user);
}

return acc;
}, [] as User[]);
};

async function getData(github: GitHubClient): Promise<CalculatorInput> {
const pullRequests = await github.readPullRequests();
const members = uniq([
...(await github.readMembers()),
...pullRequests.funded.map((pr) => pr.user),
]);
const issues = await github.readIssues();
const prComments: { pullRequest: PullRequest; comments: Comment[] }[] =
await Promise.all(
pullRequests.map((pullRequest: PullRequest) =>
pullRequests.all.map((pullRequest: PullRequest) =>
github.readPullRequestComments(pullRequest).then((comments) => ({
pullRequest,
comments,
Expand All @@ -36,23 +65,12 @@ import { Comment, Issue, PullRequest } from "./src/types";
.then((comments) => ({ issue, comments }))
)
);
const usersWithScore = await calculateScore({

return {
members,
pullRequests,
issues,
prComments,
issuesComments,
});

// sort users by total score
const sortedUsers = usersWithScore
.sort((a, b) => b.score.total - a.score.total)
.filter(({ score }) => score.total > 0);

// get sum of total scores
const totalScore = sortedUsers
.map(({ score: { total } }) => total)
.reduce((a, b) => a + b, 0);

formatScore(totalScore, sortedUsers);
})();
};
}
2 changes: 1 addition & 1 deletion analyse-contributions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"devDependencies": {
"@octokit/types": "^6.34.0",
"@types/node": "^16.11.9",
"@types/node": "^18.8.0",
"ts-node": "^10.4.0",
"tslib": "^2.3.1",
"typescript": "^4.5.2"
Expand Down
3 changes: 3 additions & 0 deletions analyse-contributions/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const FUNDED_LABEL = "funded";
export const FUNDED_MULTIPLIER = 10;
export const PR_MULTIPLIER = 2;
57 changes: 33 additions & 24 deletions analyse-contributions/src/contribution-calculator.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { FUNDED_LABEL, FUNDED_MULTIPLIER, PR_MULTIPLIER } from "./config";
import { GroupedPullRequests } from "./github-client";
import { Comment, Issue, PullRequest, User } from "./types";

type CalculatorParams = {
export type CalculatorInput = {
members: User[];
pullRequests: PullRequest[];
pullRequests: GroupedPullRequests;
issues: Issue[];
prComments: { pullRequest: PullRequest; comments: Comment[] }[];
issuesComments: { issue: Issue; comments: Comment[] }[];
Expand All @@ -14,21 +16,25 @@ function byMember(member: User) {
};
}

export type Score = {
total: number;
pullRequests: number;
issueComments: number;
prComments: number;
issues: number;
};

export type Contributions = {
pullRequests: PullRequest[];
issueComments: { issue: Issue; comments: Comment[] }[];
prComments: { pullRequest: PullRequest; comments: Comment[] }[];
issues: Issue[];
};

export type UserContributions = {
user: User;
score: {
total: number;
pullRequests: number;
issueComments: number;
prComments: number;
issues: number;
};
contributions: {
pullRequests: PullRequest[];
issueComments: { issue: Issue; comments: Comment[] }[];
prComments: { pullRequest: PullRequest; comments: Comment[] }[];
issues: Issue[];
};
score: Score;
contributions: Contributions;
};

export async function calculateScore({
Expand All @@ -37,38 +43,41 @@ export async function calculateScore({
issues,
prComments,
issuesComments,
}: CalculatorParams): Promise<UserContributions[]> {
}: CalculatorInput): Promise<UserContributions[]> {
return Promise.all(
members.map(async (user: User) => {
const memberPullRequests = pullRequests.filter(byMember(user));
const memberPullRequests = pullRequests.all.filter(byMember(user));
const memberIssueComments = issuesComments.filter(({ comments }) => {
return comments.some(byMember(user));
});
const memberPrComments = prComments.filter(({ comments }) => {
return comments.some(byMember(user));
});
const memberIssues = issues.filter(byMember(user));
const contributions = {
const contributions: Contributions = {
pullRequests: memberPullRequests,
issueComments: memberIssueComments,
prComments: memberPrComments,
issues: memberIssues,
};

const score = {
pullRequests: contributions.pullRequests.length * 2,
const _score: Omit<Score, "total"> = {
pullRequests:
pullRequests.normal.filter(byMember(user)).length * PR_MULTIPLIER +
pullRequests.funded.filter(byMember(user)).length * FUNDED_MULTIPLIER,
issueComments: contributions.issueComments.length,
prComments: contributions.prComments.length,
issues: contributions.issues.length,
};
const score: Score = {
..._score,
total: Object.values(_score).reduce((a, b) => a + b, 0),
};

return {
user,
contributions,
score: {
...score,
total: Object.values(score).reduce((a, b) => a + b, 0),
},
score,
};
})
);
Expand Down
20 changes: 18 additions & 2 deletions analyse-contributions/src/github-client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { Octokit } from "octokit";
import { FUNDED_LABEL } from "./config";
import { readCollection } from "./github-helper";
import { Comment, Issue, PullRequest, Repository } from "./types";

export type GroupedPullRequests = {
normal: PullRequest[];
funded: PullRequest[];
all: PullRequest[];
};
export default class GitHubClient {
private octokit: Octokit;
private from: Date;
Expand Down Expand Up @@ -40,7 +46,10 @@ export default class GitHubClient {
return data;
}

readPullRequests(): Promise<PullRequest[]> {
readPullRequests(): Promise<GroupedPullRequests> {
const isFunded = (pr: PullRequest) =>
pr.labels.some((label) => label.name === FUNDED_LABEL);

return Promise.all(
this.repositories.map((repo: Repository) =>
readCollection<PullRequest>(this.from, this.octokit.rest.pulls.list, {
Expand All @@ -49,7 +58,14 @@ export default class GitHubClient {
state: "closed",
})
)
).then((results) => results.flat(1));
)
.then((results) => results.flat(1))
.then((pullRequests) => {
const funded = pullRequests.filter(isFunded);
const normal = pullRequests.filter((pr) => !funded.includes(pr));

return { funded, normal, all: pullRequests };
});
}

async readIssues(): Promise<Issue[]> {
Expand Down
10 changes: 10 additions & 0 deletions analyse-contributions/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ export type PullRequest = Links &
head: {
repo: Repository;
};
labels: Label[];
};

export type Label = {
id: number;
url: string;
name: string;
color: string;
default: boolean;
description: string;
};

export type Issue = Timestamps & {
id: number;
user: User;
Expand Down
7 changes: 6 additions & 1 deletion analyse-contributions/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,16 @@
resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef"
integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==

"@types/node@*", "@types/node@^16.11.9":
"@types/node@*":
version "16.11.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.9.tgz#879be3ad7af29f4c1a5c433421bf99fab7047185"
integrity sha512-MKmdASMf3LtPzwLyRrFjtFFZ48cMf8jmX5VRYrDQiJa8Ybu5VAmkqBWqKU8fdCwD8ysw4mQ9nrEHvzg6gunR7A==

"@types/node@^18.8.0":
version "18.8.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.0.tgz#b8ee8d83a99470c0661bd899417fcd77060682fe"
integrity sha512-u+h43R6U8xXDt2vzUaVP3VwjjLyOJk6uEciZS8OSyziUQGOwmk+l+4drxcsDboHXwyTaqS1INebghmWMRxq3LA==

acorn-walk@^8.1.1:
version "8.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
Expand Down