-
Notifications
You must be signed in to change notification settings - Fork 31
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
Changes from all commits
5c9fa6f
14e6964
7d5193e
63ff526
fba1b27
c34ee34
fc5a63b
e4d52d9
81b1595
b131a80
383d67d
74953a7
e0cd2f4
3d285f5
95a187f
8f17b06
cb06d40
f2e522b
a2093ed
4f2eb73
6d437b7
31848ae
7093922
1a6b2f2
8067d73
1f0171d
3d38c0f
880c720
7644062
7625773
9be1324
43a9d26
03823ab
9194551
bb6074d
367064b
4987882
3ac6bcc
be1cdca
487b9d8
87456c1
e76d914
a3c7f97
fbf72c8
12c327f
cd48565
20d0c5e
e370a3b
3523e59
809b325
d2ee5d5
f50b037
6aaf5fd
e2bb265
21fe3c6
3afb0a1
070af86
ba8db72
db70c57
7061e76
9ae7f9d
941223e
6e85e1d
404b939
6b3241a
fdcf1bf
bf1e87e
827e9f1
ac6705f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
"language": "en", | ||
"words": [ | ||
"dataurl", | ||
"Incentivizer", | ||
"devpool", | ||
"outdir", | ||
"servedir", | ||
|
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Static, Type } from "@sinclair/typebox"; | ||
|
||
export const reviewIncentivizerConfigurationType = Type.Object( | ||
{ | ||
/** | ||
* Number of lines of code that equals $1 in review credit | ||
*/ | ||
baseRate: Type.Number({ | ||
default: 100, | ||
description: "Number of lines of code that equals $1 in review credit", | ||
}), | ||
/** | ||
* Flat rate bonus in dollars for completing a conclusive review i.e (Approved or Changes Requested) | ||
*/ | ||
conclusiveReviewCredit: Type.Number({ | ||
default: 25, | ||
description: "Flat rate bonus in dollars for completing a conclusive review i.e (Approved or Changes Requested)", | ||
}), | ||
}, | ||
{ default: {} } | ||
); | ||
|
||
export type ReviewIncentivizerConfiguration = Static<typeof reviewIncentivizerConfigurationType>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { ContextPlugin } from "../types/plugin-input"; | ||
|
||
interface GitAttributes { | ||
pattern: string; | ||
attributes: { [key: string]: string | boolean }; | ||
} | ||
|
||
async function parseGitAttributes(content: string): Promise<GitAttributes[]> { | ||
const lines = content.split("\n"); | ||
return lines | ||
.map((line) => { | ||
line = line.trim(); | ||
if (!line || line.startsWith("#")) return null; | ||
|
||
const parts = line.split(/\s+/); | ||
if (parts.length < 2) return null; | ||
|
||
const pattern = parts[0]; | ||
const attributes: { [key: string]: string | boolean } = {}; | ||
|
||
for (let i = 1; i < parts.length; i++) { | ||
const attr = parts[i]; | ||
if (attr.includes("=")) { | ||
const [key, value] = attr.split("="); | ||
attributes[key.trim()] = value.trim(); | ||
} else { | ||
attributes[attr.trim()] = true; | ||
} | ||
} | ||
|
||
return { pattern, attributes }; | ||
}) | ||
.filter((item): item is GitAttributes => item !== null); | ||
} | ||
|
||
export async function getExcludedFiles(context: ContextPlugin, owner: string, repo: string) { | ||
const gitAttributesContent = await getFileContent(context, ".gitattributes", owner, repo); | ||
if (!gitAttributesContent) { | ||
return null; | ||
} | ||
const gitAttributesLinguistGenerated = (await parseGitAttributes(gitAttributesContent)) | ||
.filter((v) => v.attributes["linguist-generated"]) | ||
.map((v) => v.pattern); | ||
|
||
return gitAttributesLinguistGenerated; | ||
} | ||
|
||
async function getFileContent( | ||
context: ContextPlugin, | ||
path: string, | ||
owner: string, | ||
repo: string | ||
): Promise<string | null> { | ||
try { | ||
const response = await context.octokit.rest.repos.getContent({ | ||
owner, | ||
repo, | ||
path, | ||
}); | ||
|
||
// GitHub API returns content as base64 | ||
if ("content" in response.data && !Array.isArray(response.data)) { | ||
return Buffer.from(response.data.content, "base64").toString("utf-8"); | ||
} | ||
return null; | ||
} catch (err) { | ||
if (err instanceof Error && "status" in err && err.status === 404) { | ||
context.logger.error( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe better as a warning. |
||
`.gitattributes was not found for ${context.payload.repository.owner.login}/${context.payload.repository.name}` | ||
); | ||
return null; | ||
} | ||
throw context.logger.error(`Error fetching files to be excluded ${err}`); | ||
} | ||
} |
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. export function parsePriorityLabel(labels?: GitHubIssue["labels"]) { I think would have been more concise |
||
if (!labels) return 1; | ||
|
||
for (const label of labels) { | ||
const priorityLabel = typeof label === "string" ? label : (label.name ?? ""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is empty string CI not working? I suppose its not set up in this repo @gentlementlegen rfc |
||
const matched = priorityLabel.match(/^Priority:\s*(\d+)/i); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const matched = priorityLabel.match(/^Priority:\s*(\d+)/); Should be case sensitive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? The priority label could be defined like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our special labels aren't defined like that and it should be targeting specifically our brand of labels. I think the only customization should be the name of the priority level in parenthesis. |
||
|
||
if (matched) { | ||
const urgency = Number(matched[1]); | ||
if (urgency) return urgency; | ||
} | ||
} | ||
|
||
return 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ishowvel can you prove that this always stays at $25 no matter the priority level?