Skip to content

Commit

Permalink
Merge pull request #70 from ubiquibot/development
Browse files Browse the repository at this point in the history
Merge develop into main
  • Loading branch information
gentlementlegen committed Jul 25, 2024
2 parents d0c3197 + 6d8bd23 commit a68ad6b
Show file tree
Hide file tree
Showing 32 changed files with 1,179 additions and 92 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
GITHUB_TOKEN="<token>"
OPENAI_API_KEY="<api_key>"
# treasury fee applied to the final permits, ex: 100 = 100%, 0.1 = 0.1%
PERMIT_FEE_RATE=""
# github account associated with EVM treasury address allowed to claim permit fees, ex: "ubiquibot-treasury"
PERMIT_TREASURY_GITHUB_USERNAME=""
# comma separated list of token addresses which should not incur any fees, ex: "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d, 0x4ECaBa5870353805a9F068101A40E0f32ed605C6"
PERMIT_ERC20_TOKENS_NO_FEE_WHITELIST=""
30 changes: 27 additions & 3 deletions .github/workflows/compute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,35 @@ jobs:
SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }}
NFT_MINTER_PRIVATE_KEY: ${{ secrets.NFT_MINTER_PRIVATE_KEY }}
NFT_CONTRACT_ADDRESS: ${{ secrets.NFT_CONTRACT_ADDRESS }}
PERMIT_FEE_RATE: ${{ secrets.PERMIT_FEE_RATE }}
PERMIT_TREASURY_GITHUB_USERNAME: ${{ secrets.PERMIT_TREASURY_GITHUB_USERNAME }}
PERMIT_ERC20_TOKENS_NO_FEE_WHITELIST: ${{ secrets.PERMIT_ERC20_TOKENS_NO_FEE_WHITELIST }}

steps:
- name: Post starting comment to issue
uses: actions/github-script@v7
id: post-comment
with:
github-token: ${{ inputs.authToken }}
script: |
const comment_body = '\`\`\`diff\n+ Evaluating results. Please wait...';
const obj = ${{ inputs.eventPayload }}
if (obj.issue && "${{ inputs.eventName }}" === "issues.closed") {
const response = await github.rest.issues.createComment({
owner: obj.repository.owner.login,
repo: obj.repository.name,
issue_number: obj.issue.number,
body: comment_body,
});
core.setOutput('comment_id', response.data.id);
}
- name: Set environment variable
run: echo "COMMENT_ID=${{ steps.post-comment.outputs.comment_id }}" >> $GITHUB_ENV

- run: ${{ toJSON(inputs) }}
shell: cat {0}

- name: Checkout code
uses: actions/checkout@v4

Expand All @@ -38,8 +65,5 @@ jobs:
with:
node-version: "20.10.0"

- run: ${{ toJSON(inputs) }}
shell: cat {0}

- name: Generate Rewards
uses: ./
3 changes: 3 additions & 0 deletions .github/workflows/jest-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
EVM_PRIVATE_ENCRYPTED: "kmpTKq5Wh9r9x5j3U9GqZr3NYnjK2g0HtbzeUBOuLC2y3x8ja_SKBNlB2AZ6LigXHP_HeMitftVUtzmoj8CFfVP9SqjWoL6IPku1hVTWkdTn97g1IxzmjydFxjdcf0wuDW1hvVtoq3Uw5yALABqxcQ"
NFT_MINTER_PRIVATE_KEY: ${{ secrets.NFT_MINTER_PRIVATE_KEY }}
NFT_CONTRACT_ADDRESS: ${{ secrets.NFT_CONTRACT_ADDRESS }}
PERMIT_FEE_RATE: ""
PERMIT_TREASURY_GITHUB_USERNAME: ""
PERMIT_ERC20_TOKENS_NO_FEE_WHITELIST: ""
steps:
- uses: actions/setup-node@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ jobs:
- uses: googleapis/release-please-action@v4
with:
release-type: simple
target-branch: main
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [1.2.0](https://github.com/ubiquibot/conversation-rewards/compare/v1.1.0...v1.2.0) (2024-07-10)


### Features

* reward is now split if there are multiple assignees ([b556238](https://github.com/ubiquibot/conversation-rewards/commit/b55623812633bc48760e07bbbd7a1c8f7509121d))


### Bug Fixes

* assignees are added to the reward even without commenting ([170cdcc](https://github.com/ubiquibot/conversation-rewards/commit/170cdcc694cf4499eb8210beff1a58885c99c5a4))
* users with no comment now can see their issue task on multiple assignees ([615d221](https://github.com/ubiquibot/conversation-rewards/commit/615d221bc1d0a8129f58e2c0ff5c06339d177792))

## [1.1.0](https://github.com/ubiquibot/conversation-rewards/compare/v1.0.0...v1.1.0) (2024-07-07)


Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ with:
evmNetworkId: 100
evmPrivateEncrypted: "encrypted-key"
erc20RewardToken: "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"
dataCollection:
maxAttempts: 10
delayMs: 10000
incentives:
enabled: true
requirePriceLabel: true
Expand Down
5 changes: 5 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Conversation rewards",
"description": "Generate rewards for on topic conversation for closing issues as complete.",
"ubiquity:listeners": [ "issues.closed" ]
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
"@supabase/supabase-js": "2.42.0",
"@ubiquibot/permit-generation": "1.3.1",
"@ubiquity-dao/rpc-handler": "1.1.0",
"@ubiquity-dao/ubiquibot-logger": "1.2.0",
"decimal.js": "10.4.3",
"dotenv": "16.4.5",
"ethers": "^6.13.0",
"jsdom": "24.0.0",
"lodash": "4.17.21",
"markdown-it": "14.1.0",
"openai": "4.29.1",
"ts-retry": "4.2.5",
"tsx": "4.7.1",
"typebox-validators": "0.3.5",
"yaml": "2.4.1"
Expand Down
14 changes: 14 additions & 0 deletions src/configuration/data-collection-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Static, Type } from "@sinclair/typebox";

export const dataCollectionConfigurationType = Type.Object({
/**
* The maximum amount of retries on failure.
*/
maxAttempts: Type.Number({ default: 10, minimum: 1 }),
/**
* The delay between each retry, in milliseconds.
*/
delayMs: Type.Number({ default: 10000, minimum: 100 }),
});

export type DataCollectionConfiguration = Static<typeof dataCollectionConfigurationType>;
3 changes: 3 additions & 0 deletions src/configuration/incentives.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StaticDecode, Type as T } from "@sinclair/typebox";
import { StandardValidator } from "typebox-validators";
import { contentEvaluatorConfigurationType } from "./content-evaluator-config";
import { dataCollectionConfigurationType } from "./data-collection-config";
import { dataPurgeConfigurationType } from "./data-purge-config";
import { formattingEvaluatorConfigurationType } from "./formatting-evaluator-config";
import { githubCommentConfigurationType } from "./github-comment-config";
Expand Down Expand Up @@ -40,7 +41,9 @@ export const incentivesConfigurationSchema = T.Object({
permitGeneration: permitGenerationConfigurationType,
githubComment: githubCommentConfigurationType,
}),
dataCollection: dataCollectionConfigurationType,
});

export const validateIncentivesConfiguration = new StandardValidator(incentivesConfigurationSchema);

export type IncentivesConfiguration = StaticDecode<typeof incentivesConfigurationSchema>;
10 changes: 10 additions & 0 deletions src/helpers/github-comment-module-instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as github from "@actions/github";
import { GithubCommentModule } from "../parser/github-comment-module";

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

const githubCommentModule = new GithubCommentModule();

export default githubCommentModule;
2 changes: 1 addition & 1 deletion src/helpers/label-price-extractor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GitHubIssue } from "../github-types.ts";
import { GitHubIssue } from "../github-types";

export function getSortedPrices(labels: GitHubIssue["labels"] | undefined) {
if (!labels) return [];
Expand Down
5 changes: 5 additions & 0 deletions src/helpers/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Logs } from "@ubiquity-dao/ubiquibot-logger";

const logger = new Logs("debug");

export default logger;
15 changes: 12 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import * as core from "@actions/core";
import githubCommentModuleInstance, { getGithubWorkflowRunUrl } from "./helpers/github-comment-module-instance";
import logger from "./helpers/logger";
import { run } from "./run";

export default run()
.then((result) => {
core?.setOutput("result", result);
return result;
})
.catch((e) => {
console.error("Failed to run comment evaluation:", e);
core?.setFailed(e.toString());
.catch(async (e) => {
const errorMessage = logger.error(`Failed to run comment evaluation. ${e}`, e);
try {
await githubCommentModuleInstance.postComment(
`${errorMessage?.logMessage.diff}\n<!--\n${getGithubWorkflowRunUrl()}\n${JSON.stringify(errorMessage?.metadata, null, 2)}\n-->`
);
} catch (err) {
logger.error(`Failed to update Github comment: ${err}`);
}
core?.setFailed(e);
return e;
});
40 changes: 34 additions & 6 deletions src/issue-activity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { retryAsyncUntilDefinedDecorator } from "ts-retry";
import { CommentType } from "./configuration/comment-types";
import configuration from "./configuration/config-reader";
import { DataCollectionConfiguration } from "./configuration/data-collection-config";
import { collectLinkedMergedPulls } from "./data-collection/collect-linked-pulls";
import {
GitHubIssue,
Expand All @@ -8,18 +11,22 @@ import {
GitHubPullRequestReviewComment,
GitHubPullRequestReviewState,
} from "./github-types";
import githubCommentModuleInstance from "./helpers/github-comment-module-instance";
import logger from "./helpers/logger";
import {
IssueParams,
PullParams,
getIssue,
getIssueComments,
getIssueEvents,
getPullRequest,
getPullRequestReviewComments,
getPullRequestReviews,
IssueParams,
PullParams,
} from "./start";

export class IssueActivity {
readonly _configuration: DataCollectionConfiguration = configuration.dataCollection;

constructor(private _issueParams: IssueParams) {}

self: GitHubIssue | null = null;
Expand All @@ -28,11 +35,32 @@ export class IssueActivity {
linkedReviews: Review[] = [];

async init() {
function fn<T>(func: () => Promise<T>) {
return func();
}
const decoratedFn = retryAsyncUntilDefinedDecorator(fn, {
delay: this._configuration.delayMs,
maxTry: this._configuration.maxAttempts,
async onError(error) {
try {
const content = "Failed to retrieve activity. Retrying...";
const message = logger.error(content, { error });
await githubCommentModuleInstance.postComment(message?.logMessage.diff || content);
} catch (e) {
logger.error(`${e}`);
}
},
async onMaxRetryFunc(error) {
logger.error("Failed to retrieve activity after 10 attempts. See logs for more details.", {
error,
});
},
});
[this.self, this.events, this.comments, this.linkedReviews] = await Promise.all([
getIssue(this._issueParams),
getIssueEvents(this._issueParams),
getIssueComments(this._issueParams),
this._getLinkedReviews(),
decoratedFn(() => getIssue(this._issueParams)),
decoratedFn(() => getIssueEvents(this._issueParams)),
decoratedFn(() => getIssueComments(this._issueParams)),
decoratedFn(() => this._getLinkedReviews()),
]);
}

Expand Down
50 changes: 37 additions & 13 deletions src/parser/github-comment-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { CommentType } from "../configuration/comment-types";
import configuration from "../configuration/config-reader";
import { GithubCommentConfiguration, githubCommentConfigurationType } from "../configuration/github-comment-config";
import { getOctokitInstance } from "../get-authentication-token";
import { getGithubWorkflowRunUrl } from "../helpers/github-comment-module-instance";
import logger from "../helpers/logger";
import { getERC20TokenSymbol } from "../helpers/web3";
import { IssueActivity } from "../issue-activity";
import { parseGitHubUrl } from "../start";
import program from "./command-line";
import { GithubCommentScore, Module, Result } from "./processor";
import { getERC20TokenSymbol } from "../helpers/web3";

interface SortedTasks {
issues: { specification: GithubCommentScore | null; comments: GithubCommentScore[] };
Expand All @@ -23,6 +24,11 @@ interface SortedTasks {
export class GithubCommentModule implements Module {
private readonly _configuration: GithubCommentConfiguration = configuration.incentives.githubComment;
private readonly _debugFilePath = "./output.html";
/**
* COMMENT_ID can be set in the environment to reference the id of the last comment created during this workflow.
* See also compute.yml to understand how it is set.
*/
private _lastCommentId: number | null = process.env.COMMENT_ID ? Number(process.env.COMMENT_ID) : null;

async transform(data: Readonly<IssueActivity>, result: Result): Promise<Result> {
const bodyArray: (string | undefined)[] = [];
Expand All @@ -31,36 +37,54 @@ export class GithubCommentModule implements Module {
result[key].evaluationCommentHtml = await this._generateHtml(key, value);
bodyArray.push(result[key].evaluationCommentHtml);
}
// Add the workflow run url and the metadata in the GitHub's comment
bodyArray.push("\n<!--");
bodyArray.push(`\n${getGithubWorkflowRunUrl()}\n`);
bodyArray.push(JSON.stringify(result, null, 2));
bodyArray.push("\n-->");
const body = bodyArray.join("");
if (this._configuration.debug) {
fs.writeFileSync(this._debugFilePath, body);
}
if (this._configuration.post) {
try {
const octokit = getOctokitInstance();
const { owner, repo, issue_number } = parseGitHubUrl(program.eventPayload.issue.html_url);

await octokit.issues.createComment({
body,
repo,
owner,
issue_number,
});
await this.postComment(body);
} catch (e) {
console.error(`Could not post GitHub comment: ${e}`);
logger.error(`Could not post GitHub comment: ${e}`);
}
}
return result;
}

get enabled(): boolean {
if (!Value.Check(githubCommentConfigurationType, this._configuration)) {
console.warn("Invalid configuration detected for GithubContentModule, disabling.");
logger.error("Invalid configuration detected for GithubContentModule, disabling.");
return false;
}
return true;
}

async postComment(body: string, updateLastComment = true) {
const { eventPayload } = program;
if (updateLastComment && this._lastCommentId !== null) {
await getOctokitInstance().issues.updateComment({
body,
repo: eventPayload.repository.name,
owner: eventPayload.repository.owner.login,
issue_number: eventPayload.issue.number,
comment_id: this._lastCommentId,
});
} else {
const comment = await getOctokitInstance().issues.createComment({
body,
repo: eventPayload.repository.name,
owner: eventPayload.repository.owner.login,
issue_number: eventPayload.issue.number,
});
this._lastCommentId = comment.data.id;
}
}

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

Expand Down
Loading

0 comments on commit a68ad6b

Please sign in to comment.