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

feat: add pull review parsing and reward parsing #218

Open
wants to merge 68 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5c9fa6f
feat: add pull review parsing and reward parsing
ishowvel Dec 14, 2024
14e6964
chore: remove testing leftovers
ishowvel Dec 14, 2024
7d5193e
chore: remove testing leftovers
ishowvel Dec 14, 2024
63ff526
feat: add mod to processor, fix the mod, add metadata to comment
ishowvel Dec 15, 2024
fba1b27
fix: cspell and one spelling mistake
ishowvel Dec 15, 2024
c34ee34
chore: remove review id
ishowvel Dec 15, 2024
fc5a63b
feat: add support for priority label
ishowvel Dec 18, 2024
e4d52d9
chore: updated manifest.json and dist build
github-actions[bot] Dec 18, 2024
81b1595
feat: mul the reward by priority
ishowvel Dec 18, 2024
b131a80
chore: retain parsing comments
ishowvel Dec 18, 2024
383d67d
chore: updated manifest.json and dist build
github-actions[bot] Dec 18, 2024
74953a7
chore: updated manifest.json and dist build
github-actions[bot] Dec 18, 2024
e0cd2f4
feat: refactor existing test results and add tests
ishowvel Dec 20, 2024
3d285f5
chore: updated manifest.json and dist build
github-actions[bot] Dec 20, 2024
95a187f
Merge remote-tracking branch 'upstream/development' into review-incen…
ishowvel Dec 20, 2024
8f17b06
chore: refactor and fix tests
ishowvel Dec 20, 2024
cb06d40
chore: updated manifest.json and dist build
github-actions[bot] Dec 20, 2024
f2e522b
fix: refactor failing tests
ishowvel Dec 20, 2024
a2093ed
fix: add a description to the new config
ishowvel Dec 28, 2024
4f2eb73
chore: updated manifest.json and dist build
github-actions[bot] Dec 28, 2024
6d437b7
fix: add example configs
ishowvel Dec 31, 2024
31848ae
chore: add {} block
ishowvel Dec 31, 2024
7093922
chore: updated manifest.json and dist build
github-actions[bot] Dec 31, 2024
1a6b2f2
chore: fix commit parser and refactor code
ishowvel Jan 2, 2025
8067d73
Merge branch 'review-incentive' of https://github.com/ishowvel/text-c…
ishowvel Jan 2, 2025
1f0171d
chore: add 1 more review reward to each test
ishowvel Jan 2, 2025
3d38c0f
chore: updated manifest.json and dist build
github-actions[bot] Jan 2, 2025
880c720
chore: only add changes when ALL patterns dont match
ishowvel Jan 2, 2025
7644062
fix: review parsing and make code more efficient
ishowvel Jan 5, 2025
7625773
Merge branch 'review-incentive' of https://github.com/ishowvel/text-c…
ishowvel Jan 5, 2025
9be1324
chore: updated manifest.json and dist build
github-actions[bot] Jan 5, 2025
43a9d26
update comment
ishowvel Jan 5, 2025
03823ab
fix: file exclusion, refcator pull fetching and add a test
ishowvel Jan 7, 2025
9194551
Merge branch 'review-incentive' of https://github.com/ishowvel/text-c…
ishowvel Jan 7, 2025
bb6074d
chore: updated manifest.json and dist build
github-actions[bot] Jan 7, 2025
367064b
feat: add support for multiple pull and assignees
ishowvel Jan 8, 2025
4987882
chore: updated manifest.json and dist build
github-actions[bot] Jan 8, 2025
3ac6bcc
chore: refactor test checkpoints
ishowvel Jan 8, 2025
be1cdca
fix: only fetch merged pulls and use cached reviews
ishowvel Jan 9, 2025
487b9d8
chore: updated manifest.json and dist build
github-actions[bot] Jan 9, 2025
87456c1
fix: stop review rewards from reinitializing
ishowvel Jan 11, 2025
e76d914
chore: updated manifest.json and dist build
github-actions[bot] Jan 11, 2025
a3c7f97
Merge remote-tracking branch 'upstream/development' into review-incen…
ishowvel Jan 11, 2025
fbf72c8
Merge branch 'review-incentive' of https://github.com/ishowvel/text-c…
ishowvel Jan 11, 2025
12c327f
chore: updated manifest.json and dist build
github-actions[bot] Jan 11, 2025
cd48565
chore: remove testing leftover and reduce api usage
ishowvel Jan 12, 2025
20d0c5e
chore: updated manifest.json and dist build
github-actions[bot] Jan 12, 2025
e370a3b
fix: testing leftover
ishowvel Jan 14, 2025
3523e59
Merge remote-tracking branch 'upstream/development' into review-incen…
ishowvel Jan 14, 2025
809b325
chore: updated manifest.json and dist build
github-actions[bot] Jan 14, 2025
d2ee5d5
chore: use html url instead of api url
ishowvel Jan 14, 2025
f50b037
chore: updated manifest.json and dist build
github-actions[bot] Jan 14, 2025
6aaf5fd
feat: seperate diff pull reviews to diff tables
ishowvel Jan 15, 2025
e2bb265
chore: updated manifest.json and dist build
github-actions[bot] Jan 15, 2025
21fe3c6
chore: update tests
ishowvel Jan 15, 2025
3afb0a1
chore: updaten contribution overview table
ishowvel Jan 16, 2025
070af86
chore: updated manifest.json and dist build
github-actions[bot] Jan 16, 2025
ba8db72
chore: update table and tests
ishowvel Jan 16, 2025
db70c57
chore: updated manifest.json and dist build
github-actions[bot] Jan 16, 2025
7061e76
Update src/web/.ubiquity-os.config.yml
ishowvel Jan 20, 2025
9ae7f9d
chore: cap each type of reward instead of capping sum of reward, cap …
ishowvel Jan 20, 2025
941223e
chore: fix config and sync with upstream branch
ishowvel Jan 21, 2025
6e85e1d
chore: updated manifest.json and dist build
github-actions[bot] Jan 21, 2025
404b939
fix: enable cross fork diffs, update tests and bump plugin sdk version
ishowvel Jan 23, 2025
6b3241a
Merge remote-tracking branch 'upstream/development' into review-incen…
ishowvel Jan 23, 2025
fdcf1bf
chore: sync to upstream
ishowvel Jan 23, 2025
bf1e87e
fix: base branch can be from outside repo and skip review reward for …
ishowvel Jan 23, 2025
827e9f1
chore: update tests
ishowvel Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"language": "en",
"words": [
"dataurl",
"Incentivizer",
"devpool",
"outdir",
"servedir",
Expand Down
24 changes: 12 additions & 12 deletions dist/index.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,27 @@
}
]
},
"reviewIncentivizer": {
"default": null,
"anyOf": [
{
"default": {},
"type": "object",
"properties": {
"baseRate": {
"type": "number"
},
"conclusiveReviewCredit": {
"type": "number"
}
},
"required": ["baseRate", "conclusiveReviewCredit"]
},
{
"type": "null"
}
]
},
"formattingEvaluator": {
"default": null,
"anyOf": [
Expand Down
11 changes: 11 additions & 0 deletions src/configuration/review-incentivizer-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Static, Type } from "@sinclair/typebox";

export const reviewIncentivizerConfigurationType = Type.Object(
{
baseRate: Type.Number(),
ishowvel marked this conversation as resolved.
Show resolved Hide resolved
conclusiveReviewCredit: Type.Number(),
},
{ default: {} }
);

export type ReviewIncentivizerConfiguration = Static<typeof reviewIncentivizerConfigurationType>;
17 changes: 17 additions & 0 deletions src/helpers/github.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import * as github from "@actions/github";
import { GitHubIssue } from "../github-types";

export function getGithubWorkflowRunUrl() {
return `${github.context.payload.repository?.html_url}/actions/runs/${github.context.runId}`;
}

export function parsePriorityLabel(labels: GitHubIssue["labels"] | undefined) {
if (!labels) return 1;

for (const label of labels) {
const priorityLabel = typeof label === "string" ? label : (label.name ?? "");
const matched = priorityLabel.match(/^Priority:\s*(\d+)/i);

if (matched) {
const urgency = Number(matched[1]);
if (urgency) return urgency;
}
}

return 1;
}
20 changes: 2 additions & 18 deletions src/parser/formatting-evaluator-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { BaseModule } from "../types/module";
import { GithubCommentScore, Result, WordResult } from "../types/results";
import { typeReplacer } from "../helpers/result-replacer";
import { ContextPlugin } from "../types/plugin-input";
import { GitHubIssue } from "../github-types";
import { parsePriorityLabel } from "../helpers/github";

interface Multiplier {
multiplier: number;
Expand Down Expand Up @@ -69,7 +69,7 @@ export class FormattingEvaluatorModule extends BaseModule {
const { formatting, words } = this._getFormattingScore(comment);
const multiplierFactor = this._multipliers?.[comment.type] ?? { multiplier: 0 };
const formattingTotal = this._calculateFormattingTotal(formatting, words, multiplierFactor).toDecimalPlaces(2);
const priority = this._parsePriorityLabel(data.self?.labels);
const priority = parsePriorityLabel(data.self?.labels);
const reward = (comment.score?.reward ? formattingTotal.add(comment.score.reward) : formattingTotal).toNumber();
comment.score = {
...comment.score,
Expand Down Expand Up @@ -192,20 +192,4 @@ export class FormattingEvaluatorModule extends BaseModule {

return { formatting, words };
}

_parsePriorityLabel(labels: GitHubIssue["labels"] | undefined) {
if (!labels) return 1;

for (const label of labels) {
const priorityLabel = typeof label === "string" ? label : (label.name ?? "");
const matched = priorityLabel.match(/^Priority:\s*(\d+)/i);

if (matched) {
const urgency = Number(matched[1]);
if (urgency) return urgency;
}
}

return 1;
}
}
66 changes: 55 additions & 11 deletions src/parser/github-comment-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { removeKeyFromObject, typeReplacer } from "../helpers/result-replacer";
import { getErc20TokenSymbol } from "../helpers/web3";
import { IssueActivity } from "../issue-activity";
import { BaseModule } from "../types/module";
import { GithubCommentScore, Result } from "../types/results";
import { GithubCommentScore, Result, ReviewScore } from "../types/results";

interface SortedTasks {
issues: { specification: GithubCommentScore | null; comments: GithubCommentScore[] };
Expand Down Expand Up @@ -164,15 +164,6 @@ export class GithubCommentModule extends BaseModule {

_createContributionRows(result: Result[0], sortedTasks: SortedTasks | undefined) {
const content: string[] = [];

if (result.task?.reward) {
content.push(buildContributionRow("Issue", "Task", result.task.multiplier, result.task.reward));
}

if (!sortedTasks) {
return content.join("");
}

function buildContributionRow(
view: string,
contribution: string,
Expand All @@ -188,6 +179,29 @@ export class GithubCommentModule extends BaseModule {
</tr>`;
}

if (result.task?.reward) {
content.push(buildContributionRow("Issue", "Task", result.task.multiplier, result.task.reward));
}

if (result.reviewReward) {
if (result.reviewReward.reviewBaseReward?.reward) {
content.push(buildContributionRow("Review", "Base Review", 1, result.reviewReward.reviewBaseReward.reward));
}

const reviewCount = result.reviewReward.reviews?.length ?? 0;

const totalReviewReward =
result.reviewReward.reviews?.reduce((sum, review) => sum.add(review.reward), new Decimal(0)) ?? new Decimal(0);

if (reviewCount > 0) {
content.push(buildContributionRow("Review", "Code Review", reviewCount, totalReviewReward.toNumber()));
}
}

if (!sortedTasks) {
return content.join("");
}

if (sortedTasks.issues.specification) {
content.push(buildContributionRow("Issue", "Specification", 1, sortedTasks.issues.specification.score?.reward));
}
Expand Down Expand Up @@ -266,6 +280,36 @@ export class GithubCommentModule extends BaseModule {
return content.join("");
}

_createReviewRows(result: Result[0]) {
if (!result.reviewReward?.reviews?.length) {
return "";
}
function buildReviewRow(review: ReviewScore) {
return `
<tr>
<td>+${review.effect.addition} -${review.effect.deletion}</td>
<td>${review.priority ?? "-"}</td>
<td>${review.reward}</td>
</tr>`;
}

const rows = result.reviewReward.reviews.map(buildReviewRow).join("");

return `
<h6>Review Details</h6>
<table>
<thead>
<tr>
<th>Changes</th>
<th>Priority</th>
<th>Reward</th>
</tr>
</thead>
<tbody>
${rows}
</tbody>
</table>`;
}
async _generateHtml(username: string, result: Result[0], taskReward: number, stripComments = false) {
const sortedTasks = result.comments?.reduce<SortedTasks>(
(acc, curr) => {
Expand All @@ -291,7 +335,6 @@ export class GithubCommentModule extends BaseModule {
const rewardsSum =
result.comments?.reduce<Decimal>((acc, curr) => acc.add(curr.score?.reward ?? 0), new Decimal(0)) ??
new Decimal(0);
// The task reward can be 0 if either there is no pricing tag or if there is no assignee
const isCapped = taskReward > 0 && rewardsSum.gt(taskReward);

return `
Expand Down Expand Up @@ -326,6 +369,7 @@ export class GithubCommentModule extends BaseModule {
${this._createContributionRows(result, sortedTasks)}
</tbody>
</table>
${!stripComments ? this._createReviewRows(result) : ""}
${
!stripComments
? `<h6>Conversation Incentives</h6>
Expand Down
11 changes: 7 additions & 4 deletions src/parser/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PermitGenerationModule } from "./permit-generation-module";
import { UserExtractorModule } from "./user-extractor-module";
import { getTaskReward } from "../helpers/label-price-extractor";
import { GitHubIssue } from "../github-types";
import { ReviewIncentivizerModule } from "./review-incentivizer-module";

export class Processor {
private _transformers: Module[] = [];
Expand All @@ -25,6 +26,7 @@ export class Processor {
.add(new DataPurgeModule(context))
.add(new FormattingEvaluatorModule(context))
.add(new ContentEvaluatorModule(context))
.add(new ReviewIncentivizerModule(context))
.add(new PermitGenerationModule(context))
.add(new GithubCommentModule(context));
this._context = context;
Expand All @@ -51,7 +53,9 @@ export class Processor {
}
// Aggregate total result
for (const item of Object.keys(this._result)) {
ishowvel marked this conversation as resolved.
Show resolved Hide resolved
this._result[item].total = this._sumRewards(this._result[item], this._getRewardsLimit(data.self));
if (item === data.self?.assignee?.login) {
ishowvel marked this conversation as resolved.
Show resolved Hide resolved
this._result[item].total = this._sumRewards(this._result[item], this._getRewardsLimit(data.self) * 3);
} else this._result[item].total = this._sumRewards(this._result[item], this._getRewardsLimit(data.self));
ishowvel marked this conversation as resolved.
Show resolved Hide resolved
}
}
return this._result;
Expand All @@ -70,17 +74,16 @@ export class Processor {

_sumRewards(obj: Record<string, unknown>, taskRewardLimit = Infinity) {
let totalReward = new Decimal(0);

for (const [key, value] of Object.entries(obj)) {
if (key === "reward" && typeof value === "number") {
totalReward = totalReward.add(Math.min(value, taskRewardLimit));
totalReward = totalReward.add(value);
} else if (typeof value === "object") {
totalReward = totalReward.add(
Math.min(this._sumRewards(value as Record<string, unknown>, taskRewardLimit), taskRewardLimit)
);
}
}

return totalReward.toNumber();
return Math.min(totalReward.toNumber(), taskRewardLimit);
}
}
Loading
Loading