From e51b6410ad51872e98b4c799ffb6b229f801c4ab Mon Sep 17 00:00:00 2001 From: Amit0617Dev <71893015+Amit0617@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:16:25 +0530 Subject: [PATCH 1/5] feat(plugins): initial draft for rewards plugin --- .github/workflows/compute.yml | 6 ++--- manifest.json | 41 +++++++++++++++++++++++++++++++++-- src/plugin.ts | 16 +++++++++++++- src/types/context.ts | 37 ++++++++++++++++++++++++++++++- src/types/plugin-inputs.ts | 2 +- 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 3d204b1..4dbbb68 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -1,4 +1,4 @@ -name: "the name of the plugin" +name: "github contributor rewards" on: workflow_dispatch: @@ -18,7 +18,7 @@ on: jobs: compute: - name: "plugin name" + name: "github contributor rewards" runs-on: ubuntu-latest permissions: write-all env: @@ -38,7 +38,7 @@ jobs: - name: execute directive run: npx tsx ./src/main.ts - id: plugin-name + id: github-contrib-reward env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} diff --git a/manifest.json b/manifest.json index a6f2a10..5fa3896 100644 --- a/manifest.json +++ b/manifest.json @@ -2,17 +2,54 @@ "name": "ts-template", "description": "ts-template for UbiquityOS plugins.", "ubiquity:listeners": [ - "issue_comment.created" + "issue_comment.created", + "issue_comment.deleted", + "issue_comment.edited", + "pull_request.assigned", + "pull_request.auto_merge_disabled", + "pull_request.auto_merge_enabled", + "pull_request.closed", + "pull_request.converted_to_draft", + "pull_request.demilestoned", + "pull_request.dequeued", + "pull_request.edited", + "pull_request.enqueued", + "pull_request.labeled", + "pull_request.locked", + "pull_request.milestoned", + "pull_request.opened", + "pull_request.ready_for_review", + "pull_request.reopened", + "pull_request.review_request_removed", + "pull_request.review_requested", + "pull_request.synchronize", + "pull_request.unassigned", + "pull_request.unlabeled", + "pull_request.unlocked", + "pull_request_review", + "pull_request_review.dismissed", + "pull_request_review.edited", + "pull_request_review.submitted", + "pull_request_review_comment", + "pull_request_review_comment.created", + "pull_request_review_comment.deleted", + "pull_request_review_comment.edited", + "pull_request_review_thread", + "pull_request_review_thread.resolved", + "pull_request_review_thread.unresolved" ], "commands": { "command1": { "ubiquity:example": "/command1 argument", "description": "Command 1 with an argument." + }, + "rewards": { + "description": "Rewards to get calculate for contributors." } }, "configuration": { "default": { - "configurableResponse": "Hello, world!" + "configurableResponse": "Hello, world! Amit passed from here" }, "type": "object", "properties": { diff --git a/src/plugin.ts b/src/plugin.ts index 01fc311..98f2669 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -10,12 +10,26 @@ import { LogLevel, Logs } from "@ubiquity-dao/ubiquibot-logger"; * The main plugin function. Split for easier testing. */ export async function runPlugin(context: Context) { - const { logger, eventName } = context; + const { logger, eventName, payload } = context; + // let's keep it for testing purposes if (isIssueCommentEvent(context)) { return await helloWorld(context); } + const contributors: Record = {}; + + // increment the counter for each new event for every contributor in that issue or PR + const login = payload.sender?.login; // the user who triggered the event + + if (login) { + if (contributors[login]) { + contributors[login]++; + } else { + contributors[login] = 1; + } + } + logger.error(`Unsupported event: ${eventName}`); } diff --git a/src/types/context.ts b/src/types/context.ts index 0a59f93..0493831 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -9,7 +9,42 @@ import { Logs } from "@ubiquity-dao/ubiquibot-logger"; * * ubiquity:listeners: ["issue_comment.created", ...] */ -export type SupportedEventsU = "issue_comment.created"; +export type SupportedEventsU = + | "issue_comment.created" + | "issue_comment.deleted" + | "issue_comment.edited" + | "pull_request.assigned" + | "pull_request.auto_merge_disabled" + | "pull_request.auto_merge_enabled" + | "pull_request.closed" + | "pull_request.converted_to_draft" + | "pull_request.demilestoned" + | "pull_request.dequeued" + | "pull_request.edited" + | "pull_request.enqueued" + | "pull_request.labeled" + | "pull_request.locked" + | "pull_request.milestoned" + | "pull_request.opened" + | "pull_request.ready_for_review" + | "pull_request.reopened" + | "pull_request.review_request_removed" + | "pull_request.review_requested" + | "pull_request.synchronize" + | "pull_request.unassigned" + | "pull_request.unlabeled" + | "pull_request.unlocked" + | "pull_request_review" + | "pull_request_review.dismissed" + | "pull_request_review.edited" + | "pull_request_review.submitted" + | "pull_request_review_comment" + | "pull_request_review_comment.created" + | "pull_request_review_comment.deleted" + | "pull_request_review_comment.edited" + | "pull_request_review_thread" + | "pull_request_review_thread.resolved" + | "pull_request_review_thread.unresolved"; export type SupportedEvents = { [K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent : never; diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 0a530f9..bb3c35b 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -23,7 +23,7 @@ export const pluginSettingsSchema = T.Object( configurableResponse: T.String(), customStringsUrl: T.Optional(T.String()), }, - { default: { configurableResponse: "Hello, world!" } } + { default: { configurableResponse: "Hello, world! Amit passed from here" } } ); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); From 006464902955c201c257df98d6cd11f3b1d8122d Mon Sep 17 00:00:00 2001 From: Amit0617Dev <71893015+Amit0617@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:38:45 +0530 Subject: [PATCH 2/5] feat(plugins): contributor rewards --- manifest.json | 2 +- src/handlers/contrib-reward.ts | 61 ++++++++++++++++++++++++++++++++++ src/types/plugin-inputs.ts | 2 +- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/handlers/contrib-reward.ts diff --git a/manifest.json b/manifest.json index 5fa3896..f5d70fe 100644 --- a/manifest.json +++ b/manifest.json @@ -49,7 +49,7 @@ }, "configuration": { "default": { - "configurableResponse": "Hello, world! Amit passed from here" + "configurableResponse": "Hello, world! Amit passed from here, testing." }, "type": "object", "properties": { diff --git a/src/handlers/contrib-reward.ts b/src/handlers/contrib-reward.ts new file mode 100644 index 0000000..c539f51 --- /dev/null +++ b/src/handlers/contrib-reward.ts @@ -0,0 +1,61 @@ +import { Context } from "../types"; + +export async function contribReward(context: Context) { + const { + logger, + payload, + octokit, + // config: { configurableResponse, }, + } = context; + const contributors: Record = {}; + + const sender = payload.comment.user?.login; + const repo = payload.repository.name; + const issueNumber = payload.issue.number; + const owner = payload.repository.owner.login; + const body = payload.comment.body; + + if (!body.match(/rewards/i)) { + logger.error(`Invalid use of slash command, use "/rewards".`, { body }); + return; + } + + logger.info("Calculating rewards for contributor."); + logger.debug(`Executing contribReward:`, { sender, repo, issueNumber, owner }); + + try { + const events = await octokit.issues.listEventsForTimeline({ + owner, + repo, + issue_number: issueNumber, + }); + + events.data.forEach((event) => { + const contributor = event.actor?.login; + if (!contributors[contributor]) { + contributors[contributor] = 0; + } + contributors[contributor]++; + }); + + await octokit.issues.createComment({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + issue_number: payload.issue.number, + body: JSON.stringify(contributors), + }); + + logger.info(`Contributors: ${JSON.stringify(contributors)}`); + } catch (error) { + if (error instanceof Error) { + logger.error(`Error calculating rewards:`, { error }); + throw error; + } else { + logger.error(`Error calculating rewards:`, { error: new Error(String(error)) }); + throw error; + } + } + + logger.ok(`Successfully created comment!`); + logger.verbose(`Exiting contribReward`); +} diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index bb3c35b..e2a5184 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -23,7 +23,7 @@ export const pluginSettingsSchema = T.Object( configurableResponse: T.String(), customStringsUrl: T.Optional(T.String()), }, - { default: { configurableResponse: "Hello, world! Amit passed from here" } } + { default: { configurableResponse: "Hello, world! Amit passed from here, testing" } } ); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); From d9d2cb315b92ee88f983b8595df167678753db8e Mon Sep 17 00:00:00 2001 From: Amit0617Dev <71893015+Amit0617@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:51:36 +0530 Subject: [PATCH 3/5] fix: not called the plugin ever --- src/plugin.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 98f2669..00e0a42 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -4,6 +4,7 @@ import { Env, PluginInputs } from "./types"; import { Context } from "./types"; import { isIssueCommentEvent } from "./types/typeguards"; import { helloWorld } from "./handlers/hello-world"; +import { contribReward } from "./handlers/contrib-reward"; import { LogLevel, Logs } from "@ubiquity-dao/ubiquibot-logger"; /** @@ -17,17 +18,8 @@ export async function runPlugin(context: Context) { return await helloWorld(context); } - const contributors: Record = {}; - - // increment the counter for each new event for every contributor in that issue or PR - const login = payload.sender?.login; // the user who triggered the event - - if (login) { - if (contributors[login]) { - contributors[login]++; - } else { - contributors[login] = 1; - } + if (eventName === "issue_comment.created" && payload.comment.body.match(/rewards/i)) { + return await contribReward(context); } logger.error(`Unsupported event: ${eventName}`); From 4f5c1a13058914d270daee4468f5c5c68764c950 Mon Sep 17 00:00:00 2001 From: Amit0617Dev <71893015+Amit0617@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:46:32 +0530 Subject: [PATCH 4/5] feat: add config for kernel to work --- .github/.ubiquibot-config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/.ubiquibot-config.yml diff --git a/.github/.ubiquibot-config.yml b/.github/.ubiquibot-config.yml new file mode 100644 index 0000000..766bd45 --- /dev/null +++ b/.github/.ubiquibot-config.yml @@ -0,0 +1,8 @@ +plugins: + "issue_comment.created": + - name: "reward plugin name" + command: "/rewards" + skipBotEvents: true + uses: + - plugin: amit0617/contributor-rewards:compute.yml@development + type: github \ No newline at end of file From 6caabcaedb897db11d0df1825d416f082e368a34 Mon Sep 17 00:00:00 2001 From: "ubiquity-os[bot]" Date: Wed, 16 Oct 2024 14:17:28 +0000 Subject: [PATCH 5/5] chore: updated generated configuration --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index f5d70fe..72562b6 100644 --- a/manifest.json +++ b/manifest.json @@ -49,7 +49,7 @@ }, "configuration": { "default": { - "configurableResponse": "Hello, world! Amit passed from here, testing." + "configurableResponse": "Hello, world! Amit passed from here, testing" }, "type": "object", "properties": {