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

Merge develop into main #70

Merged
merged 79 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
d24b5a7
feat: add permit env variables
rndquu Jun 20, 2024
5b2f8cc
Merge branch 'development' into feat/permit-fees
rndquu Jul 5, 2024
b7154c4
feat: subtract fees
rndquu Jul 5, 2024
0533eba
feat: added ubiquibot logger
gentlementlegen Jul 9, 2024
a5f5a1d
Merge branch 'refs/heads/development' into meniole-main
gentlementlegen Jul 9, 2024
45b5abb
chore: test comment
gentlementlegen Jul 9, 2024
d43d96c
chore: test comment
gentlementlegen Jul 9, 2024
16c78e3
chore: test comment
gentlementlegen Jul 9, 2024
474c55e
chore: test comment
gentlementlegen Jul 9, 2024
d514d4a
chore: test comment
gentlementlegen Jul 9, 2024
32510dc
chore: test comment
gentlementlegen Jul 9, 2024
bb69c65
chore: test comment
gentlementlegen Jul 9, 2024
322b915
chore: test comment
gentlementlegen Jul 9, 2024
0993b96
chore: test comment
gentlementlegen Jul 9, 2024
e1437ae
chore: test comment
gentlementlegen Jul 9, 2024
d8e190c
chore: test comment
gentlementlegen Jul 9, 2024
0851f32
chore: test comment
gentlementlegen Jul 9, 2024
b92e254
chore: test comment
gentlementlegen Jul 9, 2024
8961e3d
chore: test comment
gentlementlegen Jul 9, 2024
995a4f5
chore: test comment
gentlementlegen Jul 9, 2024
1650647
chore: test comment
gentlementlegen Jul 9, 2024
44e98a0
chore: test comment
gentlementlegen Jul 9, 2024
352bd32
chore: test comment
gentlementlegen Jul 9, 2024
65519cb
chore: test comment
gentlementlegen Jul 9, 2024
9c89229
chore: test comment
gentlementlegen Jul 9, 2024
bd38e30
chore: test comment
gentlementlegen Jul 9, 2024
02ae80c
chore: test comment
gentlementlegen Jul 9, 2024
c47ba4d
chore: fixed CI
gentlementlegen Jul 9, 2024
8bb0dd6
chore: fixed CI
gentlementlegen Jul 9, 2024
c8bd3f3
chore: updated README.md to match the schema
gentlementlegen Jul 9, 2024
5800938
Merge branch 'ubiquibot:development' into development
gentlementlegen Jul 10, 2024
bfc85da
chore(development): release 1.2.0
github-actions[bot] Jul 10, 2024
00dbd3a
test: add permit fee tests
rndquu Jul 10, 2024
2aef967
Merge branch 'development' into feat/permit-fees
rndquu Jul 10, 2024
9318652
feat: added ubiquibot logger
gentlementlegen Jul 9, 2024
628db1c
chore: removed unused directive in tsconfig.json
gentlementlegen Jul 10, 2024
7a5ba72
chore: removed ts extensions on imports
gentlementlegen Jul 10, 2024
d2ff558
test: add test for empty PERMIT_FEE_RATE
rndquu Jul 10, 2024
0e84240
ci(test): add fee env variables
rndquu Jul 10, 2024
866f853
chore: added comment on COMMENT_ID
gentlementlegen Jul 11, 2024
ccd3c3c
test: mock supabase
rndquu Jul 11, 2024
cd752b7
Merge pull request #52 from gentlementlegen/development
gentlementlegen Jul 11, 2024
e45b610
chore: manifest.json
gentlementlegen Jul 12, 2024
05e19bf
fix: resolve conflicts
rndquu Jul 12, 2024
9ae0e17
refactor: remove default value from PERMIT_FEE_RATE
rndquu Jul 12, 2024
6e09210
fix: do not apply fee to user.total
rndquu Jul 12, 2024
2a9f0ef
Revert "fix: do not apply fee to user.total"
rndquu Jul 12, 2024
0206639
fix: remove unnecessary toFixed()
rndquu Jul 12, 2024
dad384f
Merge pull request #54 from ubiquibot/release-please--branches--devel…
gentlementlegen Jul 15, 2024
7af3266
chore(development): release 1.2.0
github-actions[bot] Jul 10, 2024
97a1a38
Merge pull request #43 from rndquu/feat/permit-fees
rndquu Jul 15, 2024
fcdd1d9
chore: manifest.json
gentlementlegen Jul 16, 2024
3815eac
chore: use logger for error
gentlementlegen Jul 16, 2024
f833afa
chore: debug context
gentlementlegen Jul 16, 2024
87dd667
chore: metadata in comment
gentlementlegen Jul 16, 2024
ba993e0
chore: fix metadata line breaks
gentlementlegen Jul 16, 2024
7f21c42
chore: test throw error
gentlementlegen Jul 16, 2024
ca5e016
chore: error formatting
gentlementlegen Jul 16, 2024
2e6f0ed
chore: removed fake error
gentlementlegen Jul 16, 2024
bb3de97
chore: added related test to metadata posting
gentlementlegen Jul 16, 2024
653501c
chore: test fixing
gentlementlegen Jul 16, 2024
8a85842
chore: test fixing
gentlementlegen Jul 16, 2024
fcdfbb7
chore: test fixing
gentlementlegen Jul 16, 2024
2a0c98a
chore: added log for test
gentlementlegen Jul 16, 2024
2622106
chore: added log for test
gentlementlegen Jul 16, 2024
ac95cfd
chore: updated output test
gentlementlegen Jul 16, 2024
07115f4
chore: updated output test
gentlementlegen Jul 16, 2024
41b49da
chore: updated output test
gentlementlegen Jul 16, 2024
234850d
chore: updated output test
gentlementlegen Jul 16, 2024
590841a
chore: updated output test
gentlementlegen Jul 16, 2024
bc08034
chore: updated output test
gentlementlegen Jul 16, 2024
e8474b3
Merge pull request #59 from gentlementlegen/feat/error-reporting
gentlementlegen Jul 17, 2024
a89fffd
feat: retry to fetch on error
gentlementlegen Jul 19, 2024
82d75fe
chore: removed post on failed attempts
gentlementlegen Jul 19, 2024
26a0bed
feat: configuration for data collection
gentlementlegen Jul 19, 2024
50f499e
chore: added tests for retry
gentlementlegen Jul 19, 2024
9144368
chore: added tests for retry
gentlementlegen Jul 19, 2024
69cb9b5
chore: rename maxTry and delay
gentlementlegen Jul 19, 2024
6d8bd23
Merge pull request #63 from gentlementlegen/feat/exponential-backoff
gentlementlegen Jul 19, 2024
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
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
Loading