diff --git a/.cspell.json b/.cspell.json index 6bf60054..dc5f3e9a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -1,10 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", "version": "0.2", - "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log"], + "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "**/tests/__mocks__"], "useGitignore": true, "language": "en", - "words": ["dataurl", "devpool", "outdir", "servedir", "ubiquibot", "tiktoken", "typebox", "supabase", "wxdai", "noopener"], + "words": ["dataurl", "devpool", "outdir", "servedir", "ubiquibot", "tiktoken", "typebox", "supabase", "wxdai", "noopener", "knip", "hellip"], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml new file mode 100644 index 00000000..79caa3e6 --- /dev/null +++ b/.github/workflows/compute.yml @@ -0,0 +1,49 @@ +name: Compute Rewards + +on: + workflow_dispatch: + inputs: + stateId: + description: "State Id" + eventName: + description: "Event Name" + eventPayload: + description: "Event Payload" + settings: + description: "Settings" + authToken: + description: "Auth Token" + ref: + description: "Ref" + +jobs: + compute: + name: Rewards + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + X25519_PRIVATE_KEY: ${{ secrets.X25519_PRIVATE_KEY }} + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + NFT_MINTER_PRIVATE_KEY: ${{ secrets.NFT_MINTER_PRIVATE_KEY }} + NFT_CONTRACT_ADDRESS: ${{ secrets.NFT_CONTRACT_ADDRESS }} + EVM_PRIVATE_ENCRYPTED: ${{ secrets.EVM_PRIVATE_ENCRYPTED }} + APP_ID: ${{ secrets.APP_ID }} + UBIQUIBOT_APP_PRIVATE_KEY: ${{ secrets.UBIQUIBOT_APP_PRIVATE_KEY }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: Generate Rewards + uses: ./ + with: + issueUrl: "${{ fromJSON(inputs.eventPayload).issue.html_url }}" + evmPrivateEncrypted: "${{ secrets.EVM_PRIVATE_ENCRYPTED }}" + evmNetworkId: "${{ fromJSON(inputs.settings).evmNetworkId }}" diff --git a/.github/workflows/jest-testing.yml b/.github/workflows/jest-testing.yml index d85a19d6..a406f422 100644 --- a/.github/workflows/jest-testing.yml +++ b/.github/workflows/jest-testing.yml @@ -15,6 +15,9 @@ jobs: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} X25519_PRIVATE_KEY: ${{ secrets.X25519_PRIVATE_KEY }} + NFT_MINTER_PRIVATE_KEY: ${{ secrets.NFT_MINTER_PRIVATE_KEY }} + NFT_CONTRACT_ADDRESS: ${{ secrets.NFT_CONTRACT_ADDRESS }} + EVM_PRIVATE_ENCRYPTED: ${{ secrets.EVM_PRIVATE_ENCRYPTED }} steps: - name: Checkout code diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 082c8642..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Run Local Tests - -on: - workflow_dispatch: - inputs: - issueUrl: - description: "The URL the the issue needing to be parsed" - required: true - evmNetworkId: - description: "The EVM network ID to use" - required: true - evmPrivateEncrypted: - description: "The encrypted EVM private key" - required: true - -jobs: - test: - name: Run Local Tests - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - - steps: - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: "20.10.0" - - - name: Action Test - uses: gentlementlegen/conversation-rewards@feat/permit-generation - with: - issueUrl: ${{ inputs.issueUrl }} diff --git a/rewards-configuration.default.yml b/.rewards-configuration.default.yml similarity index 68% rename from rewards-configuration.default.yml rename to .rewards-configuration.default.yml index 0ab07260..e1565c63 100644 --- a/rewards-configuration.default.yml +++ b/.rewards-configuration.default.yml @@ -27,39 +27,39 @@ formattingEvaluator: td: 1 hr: 0 multipliers: - - type: [ISSUE, ISSUER, TASK]: + - type: [ISSUE, ISSUER, SPECIFICATION] formattingMultiplier: 1 wordValue: 0.1 - - type: [ISSUE, ISSUER, COMMENTED]: + - type: [ISSUE, ISSUER, COMMENTED] formattingMultiplier: 1 wordValue: 0.2 - - type: [ISSUE, ASSIGNEE, COMMENTED]: + - type: [ISSUE, ASSIGNEE, COMMENTED] formattingMultiplier: 0 wordValue: 0 - - type: [ISSUE, COLLABORATOR, COMMENTED]: + - type: [ISSUE, COLLABORATOR, COMMENTED] formattingMultiplier: 1 wordValue: 0.1 - - type: [ISSUE, CONTRIBUTOR, COMMENTED]: + - type: [ISSUE, CONTRIBUTOR, COMMENTED] formattingMultiplier: 0.25 wordValue: 0.1 - - type: [REVIEW, ISSUER, SPECIFICATION]: + - type: [REVIEW, ISSUER, TASK] formattingMultiplier: 0 wordValue: 0 - - type: [REVIEW, ISSUER, COMMENTED]: + - type: [REVIEW, ISSUER, COMMENTED] formattingMultiplier: 2 wordValue: 0.2 - - type: [REVIEW, ASSIGNEE, COMMENTED]: + - type: [REVIEW, ASSIGNEE, COMMENTED] formattingMultiplier: 1 wordValue: 0.1 - - type: [REVIEW, COLLABORATOR, COMMENTED]: + - type: [REVIEW, COLLABORATOR, COMMENTED] formattingMultiplier: 1 wordValue: 0.1 - - type: [REVIEW, CONTRIBUTOR, COMMENTED]: + - type: [REVIEW, CONTRIBUTOR, COMMENTED] formattingMultiplier: 0.25 wordValue: 0.1 permitGeneration: enabled: true githubComment: enabled: true - post: false + post: true debug: true diff --git a/action.yml b/action.yml index 6a7213f0..18a276a1 100644 --- a/action.yml +++ b/action.yml @@ -19,7 +19,7 @@ runs: steps: - run: | yarn --cwd ${{ github.action_path }} --production=true - yarn --cwd ${{ github.action_path }} start --issue "${{ inputs.issueUrl }}" --file "${{ github.action_path }}/results.json" + yarn --cwd ${{ github.action_path }} start --issue "${{ inputs.issueUrl }}" --file "${{ github.action_path }}/results.json" --evmNetworkId "${{ inputs.evmNetworkId }}" --evmPrivateEncrypted "${{ inputs.evmPrivateEncrypted }}" output=$(cat ${{ github.action_path }}/results.json | tr -s ' ' | tr -d '\n') echo "Output of calculations:" echo "$output" diff --git a/knip.ts b/knip.ts index e7f75a5d..c066ee07 100644 --- a/knip.ts +++ b/knip.ts @@ -5,7 +5,7 @@ const config: KnipConfig = { project: ["src/**/*.ts"], ignore: ["src/data-collection/examples/*.ts", "src/configuration/common-config-type.ts"], ignoreExportsUsedInFile: true, - ignoreDependencies: ["ts-node", "msw"], + ignoreDependencies: ["ts-node", "msw", "@mswjs/data"], jest: { config: ["jest.config.ts"], entry: ["src/**/*.test.ts"], diff --git a/package.json b/package.json index aaf667b1..e6d219b4 100644 --- a/package.json +++ b/package.json @@ -27,16 +27,22 @@ "dependencies": { "@actions/github": "6.0.0", "@commander-js/extra-typings": "12.0.1", + "@octokit/auth-app": "6.1.1", "@octokit/rest": "20.1.0", - "@sinclair/typebox": "0.32.20", + "@sinclair/typebox": "0.32.23", "@supabase/supabase-js": "2.42.0", - "@ubiquibot/permit-generation": "1.2.1", + "@ubiquibot/configuration": "2.0.3", + "@ubiquibot/permit-generation": "1.2.2", + "ajv": "8.12.0", + "ajv-formats": "3.0.1", "commander": "12.0.0", "decimal.js": "10.4.3", "dotenv": "16.4.5", "js-tiktoken": "1.0.10", "jsdom": "24.0.0", + "lodash": "4.17.21", "markdown-it": "14.1.0", + "ms": "2.1.3", "openai": "4.29.1", "tsx": "4.7.1", "yaml": "2.4.1" @@ -50,6 +56,7 @@ "@cspell/dict-node": "4.0.3", "@cspell/dict-software-terms": "3.3.18", "@cspell/dict-typescript": "3.1.2", + "@mswjs/data": "0.16.1", "@types/jest": "29.5.12", "@types/jsdom": "21.1.6", "@types/markdown-it": "13.0.7", diff --git a/src/configuration/common-config-type.ts b/src/configuration/common-config-type.ts deleted file mode 100644 index e18710cf..00000000 --- a/src/configuration/common-config-type.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Type, Static } from "@sinclair/typebox"; - -const baseConfiguration = Type.Object({ - enabled: Type.Boolean({ default: true }), -}); - -export type BaseConfiguration = Static; - -export default baseConfiguration; diff --git a/src/configuration/config-reader.ts b/src/configuration/config-reader.ts index 06a913a9..60c0cb7f 100644 --- a/src/configuration/config-reader.ts +++ b/src/configuration/config-reader.ts @@ -1,8 +1,26 @@ +import { Value } from "@sinclair/typebox/value"; +import { baseIncentiveConfiguration, BotConfig, generateConfiguration } from "@ubiquibot/configuration"; import * as fs from "fs"; import YAML from "yaml"; import program from "../parser/command-line"; -const file = fs.readFileSync(program.opts().config, "utf8"); -const configuration = YAML.parse(file); +let configuration: BotConfig; +let incentivesConfiguration: BotConfig["incentives"] | null = null; +try { + const file = fs.readFileSync(program.opts().config, "utf8"); + incentivesConfiguration = YAML.parse(file); +} catch (e) { + console.error(e); +} + +// Get the default configuration +configuration = generateConfiguration(); + +if (!Value.Check(baseIncentiveConfiguration, incentivesConfiguration)) { + console.warn("Invalid bot configuration detected, will use defaults."); +} else { + // Merge the default with our own + configuration = generateConfiguration({ ...configuration, incentives: incentivesConfiguration }); +} export default configuration; diff --git a/src/configuration/constants.ts b/src/configuration/constants.ts index d13e2a6f..35c77966 100644 --- a/src/configuration/constants.ts +++ b/src/configuration/constants.ts @@ -1,5 +1,7 @@ import { config } from "dotenv"; config(); -export const GITHUB_TOKEN = process.env.GITHUB_TOKEN; export const OPENAI_API_KEY = process.env.OPENAI_API_KEY; +export const APP_ID = process.env.APP_ID; +export const UBIQUIBOT_APP_PRIVATE_KEY = process.env.UBIQUIBOT_APP_PRIVATE_KEY; +export const INSTALLATION_ID = process.env.INSTALLATION_ID; diff --git a/src/configuration/content-evaluator-config.ts b/src/configuration/content-evaluator-config.ts deleted file mode 100644 index 7cbea1c8..00000000 --- a/src/configuration/content-evaluator-config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Static, Type } from "@sinclair/typebox"; - -const contentEvaluatorConfigurationType = Type.Object({ - enabled: Type.Boolean(), -}); - -export type ContentEvaluatorConfiguration = Static; - -export default contentEvaluatorConfigurationType; diff --git a/src/configuration/formatting-evaluator-config.ts b/src/configuration/formatting-evaluator-config.ts deleted file mode 100644 index 02495680..00000000 --- a/src/configuration/formatting-evaluator-config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Static, Type } from "@sinclair/typebox"; -import { CommentType } from "../issue-activity"; - -const type = Type.Union([...Object.keys(CommentType).map((key) => Type.Literal(key as keyof typeof CommentType))]); - -const formattingEvaluatorConfigurationType = Type.Object({ - enabled: Type.Boolean({ default: true }), - multipliers: Type.Array( - Type.Object({ - type: Type.Array(type), - formattingMultiplier: Type.Number(), - wordValue: Type.Number(), - }) - ), - scores: Type.Record(Type.String(), Type.Number()), -}); - -export type FormattingEvaluatorConfiguration = Static; - -export default formattingEvaluatorConfigurationType; diff --git a/src/configuration/github-comment-config.ts b/src/configuration/github-comment-config.ts deleted file mode 100644 index 74e3794c..00000000 --- a/src/configuration/github-comment-config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Static, Type } from "@sinclair/typebox"; - -const githubCommentConfigurationType = Type.Object({ - enabled: Type.Boolean({ default: true }), - post: Type.Boolean({ default: true }), - debug: Type.Boolean({ default: false }), -}); - -export type GithubCommentConfiguration = Static; - -export default githubCommentConfigurationType; diff --git a/src/configuration/permit-generation-configuration.ts b/src/configuration/permit-generation-configuration.ts deleted file mode 100644 index 421352a0..00000000 --- a/src/configuration/permit-generation-configuration.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Static, Type } from "@sinclair/typebox"; - -const permitGenerationConfigurationType = Type.Object({ - enabled: Type.Boolean(), -}); - -export type PermitGenerationConfiguration = Static; - -export default permitGenerationConfigurationType; diff --git a/src/configuration/user-extractor-config.ts b/src/configuration/user-extractor-config.ts deleted file mode 100644 index 43517995..00000000 --- a/src/configuration/user-extractor-config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Static, Type } from "@sinclair/typebox"; - -const userExtractorConfigurationType = Type.Object({ - enabled: Type.Boolean({ default: true }), - redeemTask: Type.Boolean({ default: true }), -}); - -export type UserExtractorConfiguration = Static; - -export default userExtractorConfigurationType; diff --git a/src/data-collection/collect-linked-pulls.ts b/src/data-collection/collect-linked-pulls.ts index 5c1ba539..2a842afc 100644 --- a/src/data-collection/collect-linked-pulls.ts +++ b/src/data-collection/collect-linked-pulls.ts @@ -1,10 +1,30 @@ import { GitHubLinkEvent, isGitHubLinkEvent } from "../github-types"; -import { IssueParams, getAllTimelineEvents } from "../start"; +import { IssueParams, getAllTimelineEvents, parseGitHubUrl } from "../start"; export async function collectLinkedMergedPulls(issue: IssueParams) { // normally we should only use this one to calculate incentives, because this specifies that the pull requests are merged (accepted) + // and that are also related to the current issue, no just mentioned by const onlyPullRequests = await collectLinkedPulls(issue); - return onlyPullRequests.filter((event) => isGitHubLinkEvent(event) && event.source.issue.pull_request?.merged_at); + return onlyPullRequests.filter((event) => { + if (!event.source.issue.body) { + return false; + } + const linkedPrUrl = /Resolves[\s:]*(https:\/\/\S+|#\d+)/gim.exec(event.source.issue.body)?.[1]; + if (!linkedPrUrl) { + return false; + } + let isClosingPr: boolean; + if (linkedPrUrl[0] === "#") { + isClosingPr = Number(linkedPrUrl.slice(1)) === issue.issue_number; + } else { + const linkedRepo = parseGitHubUrl(linkedPrUrl); + isClosingPr = + linkedRepo.issue_number === issue.issue_number && + linkedRepo.repo === issue.repo && + linkedRepo.owner === issue.owner; + } + return isGitHubLinkEvent(event) && event.source.issue.pull_request?.merged_at && isClosingPr; + }); } export async function collectLinkedPulls(issue: IssueParams) { // this one was created to help with tests, but probably should not be used in the main code diff --git a/src/get-authentication-token.ts b/src/get-authentication-token.ts index ef533e65..af05cbbb 100644 --- a/src/get-authentication-token.ts +++ b/src/get-authentication-token.ts @@ -1,19 +1,33 @@ +import * as github from "@actions/github"; +import { createAppAuth } from "@octokit/auth-app"; import { Octokit } from "@octokit/rest"; -import { GITHUB_TOKEN } from "./configuration/constants"; +import { APP_ID, INSTALLATION_ID, UBIQUIBOT_APP_PRIVATE_KEY } from "./configuration/constants"; let octokitInstance: Octokit | null = null; -function getAuthenticationToken(): string { - const auth = GITHUB_TOKEN; - if (!auth) { - throw new Error("No authentication token provided"); +async function getAuthenticationToken() { + const appId = APP_ID; + const privateKey = UBIQUIBOT_APP_PRIVATE_KEY; + // Defaults to the ENV value in case we are not in a GitHub Action context + const inputs = { + installationId: INSTALLATION_ID, + }; + + if (github.context.payload.inputs) { + const eventPayload = JSON.parse(github.context.payload.inputs.eventPayload); + if (eventPayload?.installation) { + inputs.installationId = eventPayload.installation.id; + } } - return auth; + + const auth = createAppAuth({ appId, privateKey, installationId: inputs.installationId }); + const authInstance = await auth({ type: "installation" }); + return authInstance.token; } -function getOctokitInstance(): Octokit { +async function getOctokitInstance(): Promise { if (!octokitInstance) { - const auth = getAuthenticationToken(); + const auth = await getAuthenticationToken(); octokitInstance = new Octokit({ auth }); } return octokitInstance; diff --git a/src/issue-activity.ts b/src/issue-activity.ts index 156c0368..f0805d04 100644 --- a/src/issue-activity.ts +++ b/src/issue-activity.ts @@ -99,13 +99,19 @@ export class IssueActivity { } _getTypeFromComment( - comment: GitHubIssueComment | GitHubPullRequestReviewComment | GitHubIssue | GitHubPullRequest, + issueType: CommentType.ISSUE | CommentType.REVIEW, + comment: + | GitHubIssueComment + | GitHubPullRequestReviewComment + | GitHubPullRequestReviewState + | GitHubIssue + | GitHubPullRequest, self: GitHubPullRequest | GitHubIssue | null ) { let ret = 0; - ret |= "pull_request_review_id" in comment || "draft" in comment ? CommentType.REVIEW : CommentType.ISSUE; + ret |= issueType; if (comment.id === self?.id) { - ret |= ret & CommentType.ISSUE ? CommentType.TASK : CommentType.SPECIFICATION; + ret |= ret & CommentType.ISSUE ? CommentType.SPECIFICATION : CommentType.TASK; } else { ret |= CommentType.COMMENTED; } @@ -121,36 +127,43 @@ export class IssueActivity { return ret; } + _getLinkedReviewComments() { + const comments = []; + for (const linkedReview of this.linkedReviews) { + for (const value of Object.values(linkedReview)) { + if (Array.isArray(value)) { + for (const review of value) { + comments.push({ + ...review, + type: this._getTypeFromComment(CommentType.REVIEW, review, linkedReview.self), + }); + } + } else if (value) { + comments.push({ + ...value, + type: this._getTypeFromComment(CommentType.REVIEW, value, value), + }); + } + } + } + return comments; + } + get allComments() { const comments: Array< (GitHubIssueComment | GitHubPullRequestReviewComment | GitHubIssue | GitHubPullRequest) & { type: CommentType } > = this.comments.map((comment) => ({ ...comment, - type: this._getTypeFromComment(comment, this.self), + type: this._getTypeFromComment(CommentType.ISSUE, comment, this.self), })); if (this.self) { comments.push({ ...this.self, - type: this._getTypeFromComment(this.self, this.self), + type: this._getTypeFromComment(CommentType.ISSUE, this.self, this.self), }); } if (this.linkedReviews) { - for (const linkedReview of this.linkedReviews) { - if (linkedReview.self) { - comments.push({ - ...linkedReview.self, - type: this._getTypeFromComment(linkedReview.self, linkedReview.self), - }); - } - if (linkedReview.reviewComments) { - for (const reviewComment of linkedReview.reviewComments) { - comments.push({ - ...reviewComment, - type: this._getTypeFromComment(reviewComment, linkedReview.self), - }); - } - } - } + comments.push(...this._getLinkedReviewComments()); } return comments; } @@ -160,14 +173,21 @@ export class Review { self: GitHubPullRequest | null = null; reviews: GitHubPullRequestReviewState[] | null = null; // this includes every comment on the files view. reviewComments: GitHubPullRequestReviewComment[] | null = null; + comments: GitHubIssueComment[] | null = null; constructor(private _pullParams: PullParams) {} async init() { - [this.self, this.reviews, this.reviewComments] = await Promise.all([ + [this.self, this.reviews, this.reviewComments, this.comments] = await Promise.all([ getPullRequest(this._pullParams), getPullRequestReviews(this._pullParams), getPullRequestReviewComments(this._pullParams), + // This fetches all the comments inside the Pull Request that were not created in a reviewing context + getIssueComments({ + owner: this._pullParams.owner, + repo: this._pullParams.repo, + issue_number: this._pullParams.pull_number, + }), ]); } } diff --git a/src/parser/command-line.ts b/src/parser/command-line.ts index 2f29561b..e5b98124 100644 --- a/src/parser/command-line.ts +++ b/src/parser/command-line.ts @@ -12,14 +12,14 @@ if (process.env.NODE_ENV === "test") { process.argv.push("-n"); process.argv.push("100"); process.argv.push("-e"); - process.argv.push("privateKey"); + process.argv.push(`${process.env.EVM_PRIVATE_ENCRYPTED}`); } const program = new Command() .requiredOption("-i, --issue ", "The url of the issue to parse") .requiredOption("-n, --evmNetworkId ", "The network ID", parseInt) .requiredOption("-e, --evmPrivateEncrypted ", "The EVM private encrypted key") - .option("-c, --config ", "The path to the desired configuration to use", "rewards-configuration.default.yml") + .option("-c, --config ", "The path to the desired configuration to use", ".rewards-configuration.default.yml") .option("-f, --file ", "The target file to store the results in") .version(packageJson.version) .parse(); diff --git a/src/parser/content-evaluator-module.ts b/src/parser/content-evaluator-module.ts index c46c5c63..26b4e1f3 100644 --- a/src/parser/content-evaluator-module.ts +++ b/src/parser/content-evaluator-module.ts @@ -1,9 +1,9 @@ import Decimal from "decimal.js"; import { encodingForModel } from "js-tiktoken"; import OpenAI from "openai"; +import { ContentEvaluatorConfiguration, contentEvaluatorConfigurationType } from "@ubiquibot/configuration"; import configuration from "../configuration/config-reader"; import { OPENAI_API_KEY } from "../configuration/constants"; -import contentEvaluatorConfig, { ContentEvaluatorConfiguration } from "../configuration/content-evaluator-config"; import { IssueActivity } from "../issue-activity"; import { GithubCommentScore, Module, Result } from "./processor"; import { Value } from "@sinclair/typebox/value"; @@ -13,10 +13,10 @@ import { Value } from "@sinclair/typebox/value"; */ export class ContentEvaluatorModule implements Module { readonly _openAi = new OpenAI({ apiKey: OPENAI_API_KEY }); - readonly _configuration: ContentEvaluatorConfiguration = configuration.contentEvaluator; + readonly _configuration: ContentEvaluatorConfiguration = configuration.incentives.contentEvaluator; get enabled(): boolean { - if (!Value.Check(contentEvaluatorConfig, this._configuration)) { + if (!Value.Check(contentEvaluatorConfigurationType, this._configuration)) { console.warn("Invalid configuration detected for ContentEvaluatorModule, disabling."); return false; } diff --git a/src/parser/data-purge-module.ts b/src/parser/data-purge-module.ts index b65e8b4b..4be06303 100644 --- a/src/parser/data-purge-module.ts +++ b/src/parser/data-purge-module.ts @@ -1,3 +1,5 @@ +import { Value } from "@sinclair/typebox/value"; +import { DataPurgeConfiguration, dataPurgeConfigurationType } from "@ubiquibot/configuration"; import configuration from "../configuration/config-reader"; import { IssueActivity } from "../issue-activity"; import { Module, Result } from "./processor"; @@ -6,20 +8,28 @@ import { Module, Result } from "./processor"; * Removes the data in the comments that we do not want to be processed. */ export class DataPurgeModule implements Module { - readonly configuration = configuration.dataPurge; + readonly _configuration: DataPurgeConfiguration = configuration.incentives.dataPurge; get enabled(): boolean { - return this.configuration.enabled; + if (!Value.Check(dataPurgeConfigurationType, this._configuration)) { + console.warn("Invalid configuration detected for DataPurgeModule, disabling."); + return false; + } + return this._configuration.enabled; } async transform(data: Readonly, result: Result) { for (const comment of data.allComments) { if (comment.body && comment.user?.login && result[comment.user.login]) { const newContent = comment.body + // Remove quoted text .replace(/^>.*$/gm, "") + // Remove commands such as /start + .replace(/^\/.+/g, "") + // makes the content single lined .replace(/[\r\n]+/g, " ") + // Removes URLs .replace(/\[.*?\]\(.*?\)/g, "") - .replace(/^\/\S+/g, "") .trim(); if (newContent.length) { result[comment.user.login].comments = [ diff --git a/src/parser/formatting-evaluator-module.ts b/src/parser/formatting-evaluator-module.ts index ba806a73..569249e8 100644 --- a/src/parser/formatting-evaluator-module.ts +++ b/src/parser/formatting-evaluator-module.ts @@ -2,10 +2,8 @@ import { Value } from "@sinclair/typebox/value"; import Decimal from "decimal.js"; import { JSDOM } from "jsdom"; import MarkdownIt from "markdown-it"; +import { FormattingEvaluatorConfiguration, formattingEvaluatorConfigurationType } from "@ubiquibot/configuration"; import configuration from "../configuration/config-reader"; -import formattingEvaluatorConfig, { - FormattingEvaluatorConfiguration, -} from "../configuration/formatting-evaluator-config"; import { CommentType, IssueActivity } from "../issue-activity"; import { GithubCommentScore, Module, Result } from "./processor"; @@ -15,7 +13,7 @@ interface Multiplier { } export class FormattingEvaluatorModule implements Module { - private readonly _configuration: FormattingEvaluatorConfiguration = configuration.formattingEvaluator; + private readonly _configuration: FormattingEvaluatorConfiguration = configuration.incentives.formattingEvaluator; private readonly _md = new MarkdownIt(); private readonly _multipliers: { [k: string]: Multiplier } = {}; @@ -68,7 +66,7 @@ export class FormattingEvaluatorModule implements Module { } get enabled(): boolean { - if (!Value.Check(formattingEvaluatorConfig, this._configuration)) { + if (!Value.Check(formattingEvaluatorConfigurationType, this._configuration)) { console.warn("Invalid configuration detected for FormattingEvaluatorModule, disabling."); return false; } diff --git a/src/parser/github-comment-module.ts b/src/parser/github-comment-module.ts index e7622191..91f423db 100644 --- a/src/parser/github-comment-module.ts +++ b/src/parser/github-comment-module.ts @@ -1,9 +1,9 @@ import { Value } from "@sinclair/typebox/value"; +import { GithubCommentConfiguration, githubCommentConfigurationType } from "@ubiquibot/configuration"; import Decimal from "decimal.js"; import * as fs from "fs"; import { stringify } from "yaml"; import configuration from "../configuration/config-reader"; -import githubCommentConfig, { GithubCommentConfiguration } from "../configuration/github-comment-config"; import { getOctokitInstance } from "../get-authentication-token"; import { CommentType, IssueActivity } from "../issue-activity"; import { parseGitHubUrl } from "../start"; @@ -12,7 +12,7 @@ import program from "./command-line"; import { GithubCommentScore, Module, Result } from "./processor"; interface SortedTasks { - issues: { task: GithubCommentScore | null; comments: GithubCommentScore[] }; + issues: { specification: GithubCommentScore | null; comments: GithubCommentScore[] }; reviews: GithubCommentScore[]; } @@ -20,7 +20,7 @@ interface SortedTasks { * Posts a GitHub comment according to the given results. */ export class GithubCommentModule implements Module { - private readonly _configuration: GithubCommentConfiguration = configuration.githubComment; + private readonly _configuration: GithubCommentConfiguration = configuration.incentives.githubComment; private readonly _debugFilePath = "./output.html"; async transform(data: Readonly, result: Result): Promise { @@ -36,7 +36,7 @@ export class GithubCommentModule implements Module { } if (this._configuration.post) { try { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); const { owner, repo, issue_number } = parseGitHubUrl(program.opts().issue); await octokit.issues.createComment({ @@ -53,78 +53,13 @@ export class GithubCommentModule implements Module { } get enabled(): boolean { - if (!Value.Check(githubCommentConfig, this._configuration)) { + if (!Value.Check(githubCommentConfigurationType, this._configuration)) { console.warn("Invalid configuration detected for GithubContentModule, disabling."); return false; } return true; } - _generateHtml(username: string, result: Result[0]) { - const sortedTasks = result.comments?.reduce( - (acc, curr) => { - if (curr.type & CommentType.ISSUE) { - if (curr.type & CommentType.TASK) { - acc.issues.task = curr; - } else { - acc.issues.comments.push(curr); - } - } else if (curr.type & CommentType.REVIEW) { - acc.reviews.push(curr); - } - return acc; - }, - { issues: { task: null, comments: [] }, reviews: [] } - ); - - return ` -
- - -

- - [ ${result.total} ${getPayoutConfigByNetworkId(program.opts().evmNetworkId).symbol} ] - -

-
- @${username} -
-
-
-
Contributions Overview
- - - - - - - - - - - ${this._createContributionRows(result, sortedTasks)} - -
ViewContributionCountReward
-
Conversation Incentives
- - - - - - - - - - - ${this._createIncentiveRows(sortedTasks)} - -
CommentFormattingRelevanceReward
-
- ` - .replace(/\s+/g, " ") - .trim(); - } - _createContributionRows(result: Result[0], sortedTasks: SortedTasks | undefined) { const content: string[] = []; @@ -150,8 +85,8 @@ export class GithubCommentModule implements Module { if (result.task?.reward) { content.push(buildContributionRow("Issue", "Task", 1, result.task.reward)); } - if (sortedTasks.issues.task) { - content.push(buildContributionRow("Issue", "Specification", 1, sortedTasks.issues.task.score?.reward)); + if (sortedTasks.issues.specification) { + content.push(buildContributionRow("Issue", "Specification", 1, sortedTasks.issues.specification.score?.reward)); } if (sortedTasks.issues.comments.length) { content.push( @@ -186,18 +121,25 @@ export class GithubCommentModule implements Module { function buildIncentiveRow(commentScore: GithubCommentScore) { // Properly escape carriage returns for HTML rendering const formatting = stringify(commentScore.score?.formatting?.content).replace(/[\n\r]/g, " "); + // Makes sure any HTML injected in the templated is not rendered itself + const sanitizedContent = commentScore.content.replaceAll("<", "<").replaceAll(">", ">"); return `
- ${commentScore.content.replace(/(.{64})..+/, "$1…")} + ${sanitizedContent.replace(/(.{64})..+/, "$1…")}
${Object.values(commentScore.score?.formatting?.content || {}).reduce((acc, curr) => { - return acc.add(curr.score * curr.count); + const multiplier = new Decimal( + commentScore.score?.formatting + ? commentScore.score.formatting.formattingMultiplier * commentScore.score.formatting.wordValue + : 0 + ); + return acc.add(multiplier.mul(curr.score * curr.count)); }, new Decimal(0))}
${formatting}
@@ -208,6 +150,9 @@ export class GithubCommentModule implements Module { `; } + if (sortedTasks.issues.specification) { + content.push(buildIncentiveRow(sortedTasks.issues.specification)); + } for (const issueComment of sortedTasks.issues.comments) { content.push(buildIncentiveRow(issueComment)); } @@ -216,4 +161,69 @@ export class GithubCommentModule implements Module { } return content.join(""); } + + _generateHtml(username: string, result: Result[0]) { + const sortedTasks = result.comments?.reduce( + (acc, curr) => { + if (curr.type & CommentType.ISSUE) { + if (curr.type & CommentType.SPECIFICATION) { + acc.issues.specification = curr; + } else { + acc.issues.comments.push(curr); + } + } else if (curr.type & CommentType.REVIEW) { + acc.reviews.push(curr); + } + return acc; + }, + { issues: { specification: null, comments: [] }, reviews: [] } + ); + + return ` +
+ + +

+ + [ ${result.total} ${getPayoutConfigByNetworkId(program.opts().evmNetworkId).symbol} ] + +

+
+ @${username} +
+
+
+
Contributions Overview
+ + + + + + + + + + + ${this._createContributionRows(result, sortedTasks)} + +
ViewContributionCountReward
+
Conversation Incentives
+ + + + + + + + + + + ${this._createIncentiveRows(sortedTasks)} + +
CommentFormattingRelevanceReward
+
+ ` + .replace(/[\n\r]+/g, " ") + .trim(); + } } diff --git a/src/parser/permit-generation-module.ts b/src/parser/permit-generation-module.ts index 74fd20d2..3d6e20ff 100644 --- a/src/parser/permit-generation-module.ts +++ b/src/parser/permit-generation-module.ts @@ -10,10 +10,8 @@ import { SupportedEvents, TokenType, } from "@ubiquibot/permit-generation/core"; +import { PermitGenerationConfiguration, permitGenerationConfigurationType } from "@ubiquibot/configuration"; import configuration from "../configuration/config-reader"; -import permitGenerationConfigurationType, { - PermitGenerationConfiguration, -} from "../configuration/permit-generation-configuration"; import { getOctokitInstance } from "../get-authentication-token"; import { IssueActivity } from "../issue-activity"; import envConfigSchema, { EnvConfigType } from "../types/env-type"; @@ -28,7 +26,7 @@ interface Payload { } export class PermitGenerationModule implements Module { - readonly _configuration: PermitGenerationConfiguration = configuration.permitGeneration; + readonly _configuration: PermitGenerationConfiguration = configuration.incentives.permitGeneration; readonly _supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY); async transform(data: Readonly, result: Result): Promise { @@ -48,20 +46,16 @@ export class PermitGenerationModule implements Module { return Promise.resolve(result); } const eventName = context.eventName as SupportedEvents; - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); const logger = { - debug(message: unknown, optionalParams: unknown) { - console.log(message, optionalParams); - }, + debug() {}, error(message: unknown, optionalParams: unknown) { console.error(message, optionalParams); }, fatal(message: unknown, optionalParams: unknown) { console.error(message, optionalParams); }, - info(message: unknown, optionalParams: unknown) { - console.log(message, optionalParams); - }, + info() {}, warn(message: unknown, optionalParams: unknown) { console.warn(message, optionalParams); }, diff --git a/src/parser/processor.ts b/src/parser/processor.ts index 2ada04d7..2d6357c5 100644 --- a/src/parser/processor.ts +++ b/src/parser/processor.ts @@ -9,12 +9,11 @@ import { FormattingEvaluatorModule } from "./formatting-evaluator-module"; import { GithubCommentModule } from "./github-comment-module"; import { PermitGenerationModule } from "./permit-generation-module"; import { UserExtractorModule } from "./user-extractor-module"; -import { BaseConfiguration } from "../configuration/common-config-type"; export class Processor { private _transformers: Module[] = []; private _result: Result = {}; - private readonly _configuration: BaseConfiguration = configuration; + private readonly _configuration = configuration.incentives; constructor() { this.add(new UserExtractorModule()) diff --git a/src/parser/user-extractor-module.ts b/src/parser/user-extractor-module.ts index 8e45722c..d9da98e0 100644 --- a/src/parser/user-extractor-module.ts +++ b/src/parser/user-extractor-module.ts @@ -1,18 +1,18 @@ import { Value } from "@sinclair/typebox/value"; import configuration from "../configuration/config-reader"; -import userExtractorConfig, { UserExtractorConfiguration } from "../configuration/user-extractor-config"; import { GitHubIssue } from "../github-types"; import { IssueActivity } from "../issue-activity"; import { Module, Result } from "./processor"; +import { UserExtractorConfiguration, userExtractorConfigurationType } from "@ubiquibot/configuration"; /** * Creates entries for each user with its associated comments. */ export class UserExtractorModule implements Module { - private readonly _configuration: UserExtractorConfiguration = configuration.userExtractor; + private readonly _configuration: UserExtractorConfiguration = configuration.incentives.userExtractor; get enabled(): boolean { - if (!Value.Check(userExtractorConfig, this._configuration)) { + if (!Value.Check(userExtractorConfigurationType, this._configuration)) { console.warn("Invalid configuration detected for UserExtractorModule, disabling."); return false; } diff --git a/src/start.ts b/src/start.ts index 185f7b34..0dabeab9 100644 --- a/src/start.ts +++ b/src/start.ts @@ -58,30 +58,30 @@ export type IssueParams = ReturnType; export type PullParams = { owner: string; repo: string; pull_number: number }; export async function getIssue(params: IssueParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return (await octokit.issues.get(params)).data; } export async function getPullRequest(pullParams: PullParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return (await octokit.pulls.get(pullParams)).data; } export async function getIssueEvents(issueParams: IssueParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return await octokit.paginate(octokit.issues.listEvents.endpoint.merge(issueParams)); } export async function getIssueComments(issueParams: IssueParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return await octokit.paginate(octokit.issues.listComments.endpoint.merge(issueParams)); } export async function getPullRequestReviews(pullParams: PullParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return await octokit.paginate(octokit.pulls.listReviews.endpoint.merge(pullParams)); } export async function getPullRequestReviewComments(pullParams: PullParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); return await octokit.paginate(octokit.pulls.listReviewComments.endpoint.merge(pullParams)); } @@ -91,7 +91,7 @@ async function getAllIssueActivity(issueParams: IssueParams) { // which includes the issue specification, any events, and all conversation // that has occurred on the issue in chronological order - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); const [issue, events, comments] = await Promise.all([ octokit.issues.get(issueParams), octokit.paginate(octokit.issues.listEvents.endpoint.merge(issueParams)), @@ -113,14 +113,14 @@ async function getTimelineUsers(issueParams: IssueParams): Promise } export async function getAllTimelineEvents(issueParams: IssueParams): Promise { - const octokit = getOctokitInstance(); + const octokit = await getOctokitInstance(); const options = octokit.issues.listEventsForTimeline.endpoint.merge(issueParams); return await octokit.paginate(options); } export function parseGitHubUrl(url: string): { owner: string; repo: string; issue_number: number } { const path = new URL(url).pathname.split("/"); - if (path.length < 5) { + if (path.length !== 5) { throw new Error(`[parseGitHubUrl] Invalid url: [${url}]`); } return { diff --git a/src/types/env-type.ts b/src/types/env-type.ts index b2f356ac..23e208ea 100644 --- a/src/types/env-type.ts +++ b/src/types/env-type.ts @@ -8,6 +8,8 @@ const envConfigSchema = Type.Object({ OPENAI_API_KEY: Type.String(), NFT_MINTER_PRIVATE_KEY: Type.String(), NFT_CONTRACT_ADDRESS: Type.String(), + APP_ID: Type.String(), + UBIQUIBOT_APP_PRIVATE_KEY: Type.String(), }); export type EnvConfigType = Static; diff --git a/src/types/env.d.ts b/src/types/env.d.ts index cbe80985..7ac5db3e 100644 --- a/src/types/env.d.ts +++ b/src/types/env.d.ts @@ -8,6 +8,8 @@ declare global { SUPABASE_URL: string; NFT_CONTRACT_ADDRESS: string; NFT_MINTER_PRIVATE_KEY: string; + APP_ID: string; + UBIQUIBOT_APP_PRIVATE_KEY: string; } } } diff --git a/tests/__mocks__/db-seed.json b/tests/__mocks__/db-seed.json new file mode 100644 index 00000000..fe184aa7 --- /dev/null +++ b/tests/__mocks__/db-seed.json @@ -0,0 +1,123 @@ +{ + "users": [ + { + "login": "molecula451", + "id": 41552663, + "node_id": "MDQ6VXNlcjQxNTUyNjYz", + "avatar_url": "https://avatars.githubusercontent.com/u/41552663?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/molecula451", + "html_url": "https://github.com/molecula451", + "followers_url": "https://api.github.com/users/molecula451/followers", + "following_url": "https://api.github.com/users/molecula451/following{/other_user}", + "gists_url": "https://api.github.com/users/molecula451/gists{/gist_id}", + "starred_url": "https://api.github.com/users/molecula451/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/molecula451/subscriptions", + "organizations_url": "https://api.github.com/users/molecula451/orgs", + "repos_url": "https://api.github.com/users/molecula451/repos", + "events_url": "https://api.github.com/users/molecula451/events{/privacy}", + "received_events_url": "https://api.github.com/users/molecula451/received_events", + "type": "User", + "site_admin": false, + "name": "Paul", + "company": null, + "blog": "https://molecula451.github.io/molecula451dev/", + "location": "Night City", + "email": null, + "hireable": true, + "bio": "Wizard of the Electronic Age", + "twitter_username": null, + "public_repos": 188, + "public_gists": 1, + "followers": 29, + "following": 18, + "created_at": "2018-07-22T20:57:16Z", + "updated_at": "2024-04-05T03:53:30Z" + }, + { + "login": "0x4007", + "id": 4975670, + "node_id": "MDQ6VXNlcjQ5NzU2NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/4975670?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x4007", + "html_url": "https://github.com/0x4007", + "followers_url": "https://api.github.com/users/0x4007/followers", + "following_url": "https://api.github.com/users/0x4007/following{/other_user}", + "gists_url": "https://api.github.com/users/0x4007/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x4007/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x4007/subscriptions", + "organizations_url": "https://api.github.com/users/0x4007/orgs", + "repos_url": "https://api.github.com/users/0x4007/repos", + "events_url": "https://api.github.com/users/0x4007/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x4007/received_events", + "type": "User", + "site_admin": false, + "name": "アレクサンダー.eth", + "company": "@ubiquity", + "blog": "", + "location": "Mainnet", + "email": null, + "hireable": null, + "bio": "Philomath. \r\nDigital media and technology pioneer.", + "twitter_username": "0x4007", + "public_repos": 53, + "public_gists": 14, + "followers": 60, + "following": 108, + "created_at": "2013-07-09T18:20:01Z", + "updated_at": "2024-04-20T14:30:52Z" + }, + { + "login": "gitcoindev", + "id": 88761781, + "node_id": "MDQ6VXNlcjg4NzYxNzgx", + "avatar_url": "https://avatars.githubusercontent.com/u/88761781?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gitcoindev", + "html_url": "https://github.com/gitcoindev", + "followers_url": "https://api.github.com/users/gitcoindev/followers", + "following_url": "https://api.github.com/users/gitcoindev/following{/other_user}", + "gists_url": "https://api.github.com/users/gitcoindev/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gitcoindev/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gitcoindev/subscriptions", + "organizations_url": "https://api.github.com/users/gitcoindev/orgs", + "repos_url": "https://api.github.com/users/gitcoindev/repos", + "events_url": "https://api.github.com/users/gitcoindev/events{/privacy}", + "received_events_url": "https://api.github.com/users/gitcoindev/received_events", + "type": "User", + "site_admin": false, + "name": "korrrba", + "company": null, + "blog": "", + "location": "Web3 / Europe", + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "public_repos": 44, + "public_gists": 0, + "followers": 3, + "following": 5, + "created_at": "2021-08-11T05:22:33Z", + "updated_at": "2024-02-05T14:11:36Z" + } + ], + "wallets": [ + { + "id": 1, + "userId": 41552663, + "address": "0x4D0704f400D57Ba93eEa88765C3FcDBD826dCFc4" + }, + { + "id": 2, + "userId": 4975670, + "address": "0x4D0704f400D57Ba93eEa88765C3FcDBD826dCFc4" + }, + { + "id": 3, + "userId": 88761781, + "address": "0x4D0704f400D57Ba93eEa88765C3FcDBD826dCFc4" + } + ] +} diff --git a/tests/__mocks__/db.ts b/tests/__mocks__/db.ts new file mode 100644 index 00000000..2517c5d5 --- /dev/null +++ b/tests/__mocks__/db.ts @@ -0,0 +1,17 @@ +// cSpell:disable +import { factory, primaryKey } from "@mswjs/data"; + +/** + * Creates an object that can be used as a db to persist data within tests + */ +export const db = factory({ + users: { + id: primaryKey(Number), + login: String, + }, + wallets: { + id: primaryKey(Number), + userId: Number, + address: String, + }, +}); diff --git a/tests/__mocks__/handlers.ts b/tests/__mocks__/handlers.ts index 891d1678..41a7660c 100644 --- a/tests/__mocks__/handlers.ts +++ b/tests/__mocks__/handlers.ts @@ -1,11 +1,14 @@ import { http, HttpResponse } from "msw"; import issueGet from "./routes/issue-get.json"; import issueEventsGet from "./routes/issue-events-get.json"; +import issueEvents2Get from "./routes/issue-events-2-get.json"; import issueCommentsGet from "./routes/issue-comments-get.json"; +import issue25CommentsGet from "./routes/issue-25-comments-get.json"; import issueTimelineGet from "./routes/issue-timeline-get.json"; import pullsGet from "./routes/pulls-get.json"; import pullsReviewsGet from "./routes/pulls-reviews-get.json"; import pullsCommentsGet from "./routes/pulls-comments-get.json"; +import { db } from "./db"; /** * Intercepts the routes and returns a custom payload @@ -14,12 +17,15 @@ export const handlers = [ http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/22", () => { return HttpResponse.json(issueGet); }), - http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/22/events", () => { - return HttpResponse.json(issueEventsGet); + http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/22/events", ({ params: { page } }) => { + return HttpResponse.json(!page ? issueEventsGet : issueEvents2Get); }), http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/22/comments", () => { return HttpResponse.json(issueCommentsGet); }), + http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/25/comments", () => { + return HttpResponse.json(issue25CommentsGet); + }), http.get("https://api.github.com/repos/ubiquibot/comment-incentives/issues/22/timeline", () => { return HttpResponse.json(issueTimelineGet); }), @@ -32,4 +38,17 @@ export const handlers = [ http.get("https://api.github.com/repos/ubiquibot/comment-incentives/pulls/25/comments", () => { return HttpResponse.json(pullsCommentsGet); }), + http.get("https://api.github.com/users/:login", ({ params: { login } }) => { + const user = db.users.findFirst({ + where: { + login: { + equals: login.toString(), + }, + }, + }); + if (!user) { + return HttpResponse.json("User was not found", { status: 404 }); + } + return HttpResponse.json(user); + }), ]; diff --git a/tests/__mocks__/results/content-evaluator-results.json b/tests/__mocks__/results/content-evaluator-results.json new file mode 100644 index 00000000..fefce8b7 --- /dev/null +++ b/tests/__mocks__/results/content-evaluator-results.json @@ -0,0 +1,434 @@ +{ + "molecula451": { + "total": 1.8, + "userId": 41552663, + "comments": [ + { + "content": "pavlovcik i think we need to update a bit the readme ! dm what to whom?", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948916343", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 16, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.32, + "relevance": 0.8 + } + }, + { + "content": "let us know when done", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948989989", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 5, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.1, + "relevance": 0.8 + } + }, + { + "content": "https://github.com/ubiquibot/comment-incentives/actions/runs/7935268560 invalid input sounds unexpected @gitcoindev ??", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949195772", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.14, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik permitted with hard debug (tho no funds in the private key)", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949564869", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.24, + "relevance": 0.8 + } + }, + { + "content": "pavlovcik i re-generated the X25519 to trigger the permit, what you don't understand? using a private key i own, but also did many commits to reach the root cause", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949635137", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 29, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.58, + "relevance": 0.8 + } + }, + { + "content": "sure thing", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639196", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 2, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.04, + "relevance": 0.8 + } + }, + { + "content": "indeed", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.02, + "relevance": 0.8 + } + }, + { + "content": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 18, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.36, + "relevance": 0.8 + } + } + ] + }, + "0x4007": { + "total": 33.44, + "userId": 4975670, + "comments": [ + { + "content": "Link below for conversation context. It was to me. Anyways you need to create a new private key for this task!", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948930217", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 21, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 3.36, + "relevance": 0.8 + } + }, + { + "content": "In the repository secrets I think I need to change the key to match @gitcoindev's", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949201722", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 2.4, + "relevance": 0.8 + } + }, + { + "content": "I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7GQ` I hope that it doesn't break production for some reason (it should get it from Netlify secrets, but not sure if we implemented this correctly!) I fear that we might need to build a feature for this to support development key pair and production. Unfortunately I'm already winding down for the day so I'll leave you guys to try and investigate.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949203681", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 67, + "score": 1 + }, + "code": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 10.88, + "relevance": 0.8 + } + }, + { + "content": "I don't understand what you mean by this", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949633751", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 8, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.28, + "relevance": 0.8 + } + }, + { + "content": "I'll investigate more on my computer later.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639054", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.12, + "relevance": 0.8 + } + }, + { + "content": "Will it be an issue if I revert to the commit and secret that I had before? It was the production x25519 key in the GitHub repository secrets when it was working like eight hours ago. Posting this message before checking on my computer to get you before you log off.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949642845", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 51, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 8.16, + "relevance": 0.8 + } + }, + { + "content": "Can somebody work on generating a new `X25519_PRIVATE_KEY` for the ubiquibot organization? We need to share it for development purposes. 1. Generate a new key 2. Encrypt a new `evmPrivateKeyEncrypted` (no funds!) and add to the org bot config 3. Add the shared test key to the `comment-incentives` readme. https://github.com/ubiquibot/comment-incentives/pull/21/commits/567419d9688e92edf698f64c697f1a7cafe1d02e _Originally posted by @pavlovcik in https://github.com/ubiquibot/comment-incentives/issues/19#issuecomment-1948876653_", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22", + "type": "ISSUE|ISSUER|TASK", + "score": { + "formatting": { + "content": { + "p": { + "count": 56, + "score": 1 + }, + "code": { + "count": 3, + "score": 1 + }, + "em": { + "count": 6, + "score": 0 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 4.72, + "relevance": 0.8 + } + }, + { + "content": "Need to document a private key too", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.56, + "relevance": 0.8 + } + }, + { + "content": "I was editing this right now but was too slow to push.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.96, + "relevance": 0.8 + } + } + ] + }, + "gitcoindev": { + "total": 45.5, + "task": { + "reward": 37.5 + }, + "userId": 88761781, + "comments": [ + { + "content": "@molecula451 I tried to override X25519_PRIVATE_KEY but it did not help. It seems that https://github.com/ubiquibot/production/blob/1937a6ba75588f51d1bf07fed1f6384f79090465/.github/ubiquibot-config.yml#L2 takes precedence over https://github.com/ubiquibot/comment-incentives/blob/main/.github/ubiquibot-config.yml#L2 (I see the first one in logs).", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949333227", + "type": "ISSUE|ASSIGNEE|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 26, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10AbEf5CB4a6E492c5ba93d30068d2D95 (no funds). Resolves: https://github.com/ubiquibot/comment-incentives/issues/22", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25", + "type": "REVIEW|ISSUER|SPECIFICATION", + "score": { + "formatting": { + "content": { + "p": { + "count": 11, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik @molecula451 please check now again, I added to docs.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 10, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 3.2, + "relevance": 0.8 + } + }, + { + "content": "No way, full details are available in plain sight, only for test in production purposes", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 4.8, + "relevance": 0.8 + } + } + ] + } +} diff --git a/tests/__mocks__/results/data-purge-result.json b/tests/__mocks__/results/data-purge-result.json index 3eb341c9..cc4dbd00 100644 --- a/tests/__mocks__/results/data-purge-result.json +++ b/tests/__mocks__/results/data-purge-result.json @@ -32,6 +32,16 @@ "content": "sure thing", "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639196", "type": "ISSUE|CONTRIBUTOR|COMMENTED" + }, + { + "content": "indeed", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "type": "REVIEW|CONTRIBUTOR|COMMENTED" + }, + { + "content": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "type": "REVIEW|CONTRIBUTOR|COMMENTED" } ] }, @@ -73,6 +83,16 @@ "content": "Can somebody work on generating a new `X25519_PRIVATE_KEY` for the ubiquibot organization? We need to share it for development purposes. 1. Generate a new key 2. Encrypt a new `evmPrivateKeyEncrypted` (no funds!) and add to the org bot config 3. Add the shared test key to the `comment-incentives` readme. https://github.com/ubiquibot/comment-incentives/pull/21/commits/567419d9688e92edf698f64c697f1a7cafe1d02e _Originally posted by @pavlovcik in https://github.com/ubiquibot/comment-incentives/issues/19#issuecomment-1948876653_", "url": "https://github.com/ubiquibot/comment-incentives/issues/22", "type": "ISSUE|ISSUER|TASK" + }, + { + "content": "Need to document a private key too", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "type": "REVIEW|COLLABORATOR|COMMENTED" + }, + { + "content": "I was editing this right now but was too slow to push.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "type": "REVIEW|COLLABORATOR|COMMENTED" } ] }, @@ -92,6 +112,16 @@ "content": "The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10AbEf5CB4a6E492c5ba93d30068d2D95 (no funds). Resolves: https://github.com/ubiquibot/comment-incentives/issues/22", "url": "https://github.com/ubiquibot/comment-incentives/pull/25", "type": "REVIEW|ISSUER|SPECIFICATION" + }, + { + "content": "@pavlovcik @molecula451 please check now again, I added to docs.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "type": "REVIEW|ISSUER|COMMENTED" + }, + { + "content": "No way, full details are available in plain sight, only for test in production purposes", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "type": "REVIEW|ISSUER|COMMENTED" } ] } diff --git a/tests/__mocks__/results/formatting-evaluator-results.json b/tests/__mocks__/results/formatting-evaluator-results.json new file mode 100644 index 00000000..52e9720d --- /dev/null +++ b/tests/__mocks__/results/formatting-evaluator-results.json @@ -0,0 +1,413 @@ +{ + "molecula451": { + "total": 2.25, + "userId": 41552663, + "comments": [ + { + "content": "pavlovcik i think we need to update a bit the readme ! dm what to whom?", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948916343", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 16, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.4 + } + }, + { + "content": "let us know when done", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948989989", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 5, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.125 + } + }, + { + "content": "https://github.com/ubiquibot/comment-incentives/actions/runs/7935268560 invalid input sounds unexpected @gitcoindev ??", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949195772", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.175 + } + }, + { + "content": "@pavlovcik permitted with hard debug (tho no funds in the private key)", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949564869", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.3 + } + }, + { + "content": "pavlovcik i re-generated the X25519 to trigger the permit, what you don't understand? using a private key i own, but also did many commits to reach the root cause", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949635137", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 29, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.725 + } + }, + { + "content": "sure thing", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639196", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 2, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.05 + } + }, + { + "content": "indeed", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.025 + } + }, + { + "content": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 18, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.45 + } + } + ] + }, + "0x4007": { + "total": 41.8, + "userId": 4975670, + "comments": [ + { + "content": "Link below for conversation context. It was to me. Anyways you need to create a new private key for this task!", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948930217", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 21, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 4.2 + } + }, + { + "content": "In the repository secrets I think I need to change the key to match @gitcoindev's", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949201722", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 3 + } + }, + { + "content": "I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7GQ` I hope that it doesn't break production for some reason (it should get it from Netlify secrets, but not sure if we implemented this correctly!) I fear that we might need to build a feature for this to support development key pair and production. Unfortunately I'm already winding down for the day so I'll leave you guys to try and investigate.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949203681", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 67, + "score": 1 + }, + "code": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 13.6 + } + }, + { + "content": "I don't understand what you mean by this", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949633751", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 8, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.6 + } + }, + { + "content": "I'll investigate more on my computer later.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639054", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.4 + } + }, + { + "content": "Will it be an issue if I revert to the commit and secret that I had before? It was the production x25519 key in the GitHub repository secrets when it was working like eight hours ago. Posting this message before checking on my computer to get you before you log off.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949642845", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 51, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 10.2 + } + }, + { + "content": "Can somebody work on generating a new `X25519_PRIVATE_KEY` for the ubiquibot organization? We need to share it for development purposes. 1. Generate a new key 2. Encrypt a new `evmPrivateKeyEncrypted` (no funds!) and add to the org bot config 3. Add the shared test key to the `comment-incentives` readme. https://github.com/ubiquibot/comment-incentives/pull/21/commits/567419d9688e92edf698f64c697f1a7cafe1d02e _Originally posted by @pavlovcik in https://github.com/ubiquibot/comment-incentives/issues/19#issuecomment-1948876653_", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22", + "type": "ISSUE|ISSUER|TASK", + "score": { + "formatting": { + "content": { + "p": { + "count": 56, + "score": 1 + }, + "code": { + "count": 3, + "score": 1 + }, + "em": { + "count": 6, + "score": 0 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 5.9 + } + }, + { + "content": "Need to document a private key too", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.7 + } + }, + { + "content": "I was editing this right now but was too slow to push.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 1.2 + } + } + ] + }, + "gitcoindev": { + "total": 47.5, + "task": { + "reward": 37.5 + }, + "userId": 88761781, + "comments": [ + { + "content": "@molecula451 I tried to override X25519_PRIVATE_KEY but it did not help. It seems that https://github.com/ubiquibot/production/blob/1937a6ba75588f51d1bf07fed1f6384f79090465/.github/ubiquibot-config.yml#L2 takes precedence over https://github.com/ubiquibot/comment-incentives/blob/main/.github/ubiquibot-config.yml#L2 (I see the first one in logs).", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949333227", + "type": "ISSUE|ASSIGNEE|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 26, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0 + } + }, + { + "content": "The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10AbEf5CB4a6E492c5ba93d30068d2D95 (no funds). Resolves: https://github.com/ubiquibot/comment-incentives/issues/22", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25", + "type": "REVIEW|ISSUER|SPECIFICATION", + "score": { + "formatting": { + "content": { + "p": { + "count": 11, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0 + } + }, + { + "content": "@pavlovcik @molecula451 please check now again, I added to docs.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 10, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 4 + } + }, + { + "content": "No way, full details are available in plain sight, only for test in production purposes", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 6 + } + } + ] + } +} diff --git a/tests/__mocks__/results/github-comment-results.json b/tests/__mocks__/results/github-comment-results.json new file mode 100644 index 00000000..c776f208 --- /dev/null +++ b/tests/__mocks__/results/github-comment-results.json @@ -0,0 +1,440 @@ +{ + "molecula451": { + "total": 1.8, + "userId": 41552663, + "comments": [ + { + "content": "pavlovcik i think we need to update a bit the readme ! dm what to whom?", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948916343", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 16, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.32, + "relevance": 0.8 + } + }, + { + "content": "let us know when done", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948989989", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 5, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.1, + "relevance": 0.8 + } + }, + { + "content": "https://github.com/ubiquibot/comment-incentives/actions/runs/7935268560 invalid input sounds unexpected @gitcoindev ??", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949195772", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.14, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik permitted with hard debug (tho no funds in the private key)", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949564869", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.24, + "relevance": 0.8 + } + }, + { + "content": "pavlovcik i re-generated the X25519 to trigger the permit, what you don't understand? using a private key i own, but also did many commits to reach the root cause", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949635137", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 29, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.58, + "relevance": 0.8 + } + }, + { + "content": "sure thing", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639196", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 2, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.04, + "relevance": 0.8 + } + }, + { + "content": "indeed", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.02, + "relevance": 0.8 + } + }, + { + "content": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 18, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.36, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiIxODAwMDAwMDAwMDAwMDAwMDAwIn0sIm5vbmNlIjoiNTU5OTM2MDE0NzcwMzQzMTA4MTU5NDY5ODEzMzcwNTA1MDMxMzkxMzU2MjIzMDMwNTA5MjQyNzA2ODYyOTY3NzAwMDEzODA2OTM3ODEiLCJkZWFkbGluZSI6IjU3ODk2MDQ0NjE4NjU4MDk3NzExNzg1NDkyNTA0MzQzOTUzOTI2NjM0OTkyMzMyODIwMjgyMDE5NzI4NzkyMDAzOTU2NTY0ODE5OTY3In0sInRyYW5zZmVyRGV0YWlscyI6eyJ0byI6IjB4NEQwNzA0ZjQwMEQ1N0JhOTNlRWE4ODc2NUMzRmNEQkQ4MjZkQ0ZjNCIsInJlcXVlc3RlZEFtb3VudCI6IjE4MDAwMDAwMDAwMDAwMDAwMDAifSwib3duZXIiOiIweDBmQzFiOTA5YmE5MjY1QTg0NmI4MkNGNENFMzUyZmMzZTdFZUIyRUQiLCJzaWduYXR1cmUiOiIweDdjYmNiNzIzODU3NDQwMWIwNDA2YjYxNmYwY2RiYjQzNjM5YjUyMDAwOGYwNGRmY2ZhZWVjNmZlMjg5NjZjZWUxOGQ4NDA5M2RmM2MwZjk3ZWJlMGRiZjYyYjE5ZTE5NzU2ZWNiMGY2YWU2YjAyMThjZGRlOTAxZTA2N2JmM2YzMWIiLCJuZXR3b3JrSWQiOjEwMH1d", + "evaluationCommentHtml": "

[ 1.8 WXDAI ]

@molecula451
Contributions Overview
View Contribution Count Reward
Issue Comment 6 1.42
Review Comment 2 0.38
Conversation Incentives
Comment Formatting Relevance Reward
pavlovcik i think we need to update a bit the readme ! dm what…
0.4
content:
  p:
    count: 16
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.32
let us know when done
0.125
content:
  p:
    count: 5
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.1
https://github.com/ubiquibot/comment-incentives/actions/runs/793…
0.175
content:
  p:
    count: 7
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.14
@pavlovcik permitted with hard debug (tho no funds in the privat…
0.3
content:
  p:
    count: 12
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.24
pavlovcik i re-generated the X25519 to trigger the permit, what …
0.725
content:
  p:
    count: 29
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.58
sure thing
0.05
content:
  p:
    count: 2
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.04
indeed
0.025
content:
  p:
    count: 1
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.02
go to go pavlovick, we'll be using this one for test only or tes…
0.45
content:
  p:
    count: 18
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.36
" + }, + "0x4007": { + "total": 33.44, + "userId": 4975670, + "comments": [ + { + "content": "Link below for conversation context. It was to me. Anyways you need to create a new private key for this task!", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948930217", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 21, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 3.36, + "relevance": 0.8 + } + }, + { + "content": "In the repository secrets I think I need to change the key to match @gitcoindev's", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949201722", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 2.4, + "relevance": 0.8 + } + }, + { + "content": "I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7GQ` I hope that it doesn't break production for some reason (it should get it from Netlify secrets, but not sure if we implemented this correctly!) I fear that we might need to build a feature for this to support development key pair and production. Unfortunately I'm already winding down for the day so I'll leave you guys to try and investigate.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949203681", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 67, + "score": 1 + }, + "code": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 10.88, + "relevance": 0.8 + } + }, + { + "content": "I don't understand what you mean by this", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949633751", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 8, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.28, + "relevance": 0.8 + } + }, + { + "content": "I'll investigate more on my computer later.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639054", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.12, + "relevance": 0.8 + } + }, + { + "content": "Will it be an issue if I revert to the commit and secret that I had before? It was the production x25519 key in the GitHub repository secrets when it was working like eight hours ago. Posting this message before checking on my computer to get you before you log off.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949642845", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 51, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 8.16, + "relevance": 0.8 + } + }, + { + "content": "Can somebody work on generating a new `X25519_PRIVATE_KEY` for the ubiquibot organization? We need to share it for development purposes. 1. Generate a new key 2. Encrypt a new `evmPrivateKeyEncrypted` (no funds!) and add to the org bot config 3. Add the shared test key to the `comment-incentives` readme. https://github.com/ubiquibot/comment-incentives/pull/21/commits/567419d9688e92edf698f64c697f1a7cafe1d02e _Originally posted by @pavlovcik in https://github.com/ubiquibot/comment-incentives/issues/19#issuecomment-1948876653_", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22", + "type": "ISSUE|ISSUER|TASK", + "score": { + "formatting": { + "content": { + "p": { + "count": 56, + "score": 1 + }, + "code": { + "count": 3, + "score": 1 + }, + "em": { + "count": 6, + "score": 0 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 4.72, + "relevance": 0.8 + } + }, + { + "content": "Need to document a private key too", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.56, + "relevance": 0.8 + } + }, + { + "content": "I was editing this right now but was too slow to push.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.96, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiIzMzQ0MDAwMDAwMDAwMDAwMDAwMCJ9LCJub25jZSI6IjU0MTU2NjczMjEwMTg2MDc2NjY3MDM0MzA4MDMwMzQxMTU2NjMyMTc1NDA0MTE1ODg4NzA3NjM5NTc1ODU0Mzg0MzM3NTUwNzUyMjU2IiwiZGVhZGxpbmUiOiI1Nzg5NjA0NDYxODY1ODA5NzcxMTc4NTQ5MjUwNDM0Mzk1MzkyNjYzNDk5MjMzMjgyMDI4MjAxOTcyODc5MjAwMzk1NjU2NDgxOTk2NyJ9LCJ0cmFuc2ZlckRldGFpbHMiOnsidG8iOiIweDREMDcwNGY0MDBENTdCYTkzZUVhODg3NjVDM0ZjREJEODI2ZENGYzQiLCJyZXF1ZXN0ZWRBbW91bnQiOiIzMzQ0MDAwMDAwMDAwMDAwMDAwMCJ9LCJvd25lciI6IjB4MGZDMWI5MDliYTkyNjVBODQ2YjgyQ0Y0Q0UzNTJmYzNlN0VlQjJFRCIsInNpZ25hdHVyZSI6IjB4YWUyOWQwNWE1N2EwNDg0NzE5MDc4ZDQ4MWUxMWVmMDBlY2RiYzIwMjczOGJiY2QzZjc5NDFiYjkzNTY2ZDE4ZDUwZTBkY2NjNjkxM2U5OTM2MjJmNTVjZmM4NWNkNmY5YTNhOTYzZWNhNmRhZGY4NzVlYjIxOTg4NmM1MGY4ZTUxYiIsIm5ldHdvcmtJZCI6MTAwfV0=", + "evaluationCommentHtml": "

[ 33.44 WXDAI ]

@0x4007
Contributions Overview
View Contribution Count Reward
Issue Specification 1 4.72
Issue Comment 6 27.2
Review Comment 2 1.52
Conversation Incentives
Comment Formatting Relevance Reward
Link below for conversation context. It was to me. Anyways you n…
4.2
content:
  p:
    count: 21
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 3.36
In the repository secrets I think I need to change the key to ma…
3
content:
  p:
    count: 15
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 2.4
I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7G…
13.6
content:
  p:
    count: 67
    score: 1
  code:
    count: 1
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 10.88
I don't understand what you mean by this
1.6
content:
  p:
    count: 8
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 1.28
I'll investigate more on my computer later.
1.4
content:
  p:
    count: 7
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 1.12
Will it be an issue if I revert to the commit and secret that I …
10.2
content:
  p:
    count: 51
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 8.16
Need to document a private key too
0.7
content:
  p:
    count: 7
    score: 1
wordValue: 0.1
formattingMultiplier: 1
0.8 0.56
I was editing this right now but was too slow to push.
1.2
content:
  p:
    count: 12
    score: 1
wordValue: 0.1
formattingMultiplier: 1
0.8 0.96
" + }, + "gitcoindev": { + "total": 45.5, + "task": { + "reward": 37.5 + }, + "userId": 88761781, + "comments": [ + { + "content": "@molecula451 I tried to override X25519_PRIVATE_KEY but it did not help. It seems that https://github.com/ubiquibot/production/blob/1937a6ba75588f51d1bf07fed1f6384f79090465/.github/ubiquibot-config.yml#L2 takes precedence over https://github.com/ubiquibot/comment-incentives/blob/main/.github/ubiquibot-config.yml#L2 (I see the first one in logs).", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949333227", + "type": "ISSUE|ASSIGNEE|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 26, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10AbEf5CB4a6E492c5ba93d30068d2D95 (no funds). Resolves: https://github.com/ubiquibot/comment-incentives/issues/22", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25", + "type": "REVIEW|ISSUER|SPECIFICATION", + "score": { + "formatting": { + "content": { + "p": { + "count": 11, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik @molecula451 please check now again, I added to docs.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 10, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 3.2, + "relevance": 0.8 + } + }, + { + "content": "No way, full details are available in plain sight, only for test in production purposes", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 4.8, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiI0NTUwMDAwMDAwMDAwMDAwMDAwMCJ9LCJub25jZSI6IjI1NTAxODE5OTY2NjA1NzQ1MzA1NTE0MTk4MDg3NTY5MTYyMTg1ODQzNzc2NTY0MDgxNzUwODI4NjE5MzMxNjYyNDIzMjAwMTU3MDk1IiwiZGVhZGxpbmUiOiI1Nzg5NjA0NDYxODY1ODA5NzcxMTc4NTQ5MjUwNDM0Mzk1MzkyNjYzNDk5MjMzMjgyMDI4MjAxOTcyODc5MjAwMzk1NjU2NDgxOTk2NyJ9LCJ0cmFuc2ZlckRldGFpbHMiOnsidG8iOiIweDREMDcwNGY0MDBENTdCYTkzZUVhODg3NjVDM0ZjREJEODI2ZENGYzQiLCJyZXF1ZXN0ZWRBbW91bnQiOiI0NTUwMDAwMDAwMDAwMDAwMDAwMCJ9LCJvd25lciI6IjB4MGZDMWI5MDliYTkyNjVBODQ2YjgyQ0Y0Q0UzNTJmYzNlN0VlQjJFRCIsInNpZ25hdHVyZSI6IjB4NzQzNWUxMTZlN2FjYTg4OTI0YmI3ODVmZmQ0ZWM4ZjYzNGI4YWNkYmM1NGQ5OTBjOTU5N2VkNzVmYTA0MTE5NDcwZjc2ZGRhMTAzMzVmMGUyMjVmM2Q0YTVkMWEzNDQyYWMxZjkzYTIwMjNlYjY4N2VlZmI3NzIzMGY5MTQzZmYxYiIsIm5ldHdvcmtJZCI6MTAwfV0=", + "evaluationCommentHtml": "

[ 45.5 WXDAI ]

@gitcoindev
Contributions Overview
View Contribution Count Reward
Issue Task 1 37.5
Issue Comment 1 0
Review Comment 3 8
Conversation Incentives
Comment Formatting Relevance Reward
@molecula451 I tried to override X25519_PRIVATE_KEY but it did n…
0
content:
  p:
    count: 26
    score: 1
wordValue: 0
formattingMultiplier: 0
0.8 -
The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10…
0
content:
  p:
    count: 11
    score: 1
wordValue: 0
formattingMultiplier: 0
0.8 -
@pavlovcik @molecula451 please check now again, I added to docs.
4
content:
  p:
    count: 10
    score: 1
wordValue: 0.2
formattingMultiplier: 2
0.8 3.2
No way, full details are available in plain sight, only for test…
6
content:
  p:
    count: 15
    score: 1
wordValue: 0.2
formattingMultiplier: 2
0.8 4.8
" + } +} diff --git a/tests/__mocks__/results/output.html b/tests/__mocks__/results/output.html new file mode 100644 index 00000000..b0046555 --- /dev/null +++ b/tests/__mocks__/results/output.html @@ -0,0 +1 @@ +

[ 1.8 WXDAI ]

@molecula451
Contributions Overview
View Contribution Count Reward
Issue Comment 6 1.42
Review Comment 2 0.38
Conversation Incentives
Comment Formatting Relevance Reward
pavlovcik i think we need to update a bit the readme ! dm what…
0.4
content:
  p:
    count: 16
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.32
let us know when done
0.125
content:
  p:
    count: 5
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.1
https://github.com/ubiquibot/comment-incentives/actions/runs/793…
0.175
content:
  p:
    count: 7
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.14
@pavlovcik permitted with hard debug (tho no funds in the privat…
0.3
content:
  p:
    count: 12
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.24
pavlovcik i re-generated the X25519 to trigger the permit, what …
0.725
content:
  p:
    count: 29
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.58
sure thing
0.05
content:
  p:
    count: 2
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.04
indeed
0.025
content:
  p:
    count: 1
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.02
go to go pavlovick, we'll be using this one for test only or tes…
0.45
content:
  p:
    count: 18
    score: 1
wordValue: 0.1
formattingMultiplier: 0.25
0.8 0.36

[ 33.44 WXDAI ]

@0x4007
Contributions Overview
View Contribution Count Reward
Issue Specification 1 4.72
Issue Comment 6 27.2
Review Comment 2 1.52
Conversation Incentives
Comment Formatting Relevance Reward
Link below for conversation context. It was to me. Anyways you n…
4.2
content:
  p:
    count: 21
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 3.36
In the repository secrets I think I need to change the key to ma…
3
content:
  p:
    count: 15
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 2.4
I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7G…
13.6
content:
  p:
    count: 67
    score: 1
  code:
    count: 1
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 10.88
I don't understand what you mean by this
1.6
content:
  p:
    count: 8
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 1.28
I'll investigate more on my computer later.
1.4
content:
  p:
    count: 7
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 1.12
Will it be an issue if I revert to the commit and secret that I …
10.2
content:
  p:
    count: 51
    score: 1
wordValue: 0.2
formattingMultiplier: 1
0.8 8.16
Need to document a private key too
0.7
content:
  p:
    count: 7
    score: 1
wordValue: 0.1
formattingMultiplier: 1
0.8 0.56
I was editing this right now but was too slow to push.
1.2
content:
  p:
    count: 12
    score: 1
wordValue: 0.1
formattingMultiplier: 1
0.8 0.96

[ 45.5 WXDAI ]

@gitcoindev
Contributions Overview
View Contribution Count Reward
Issue Task 1 37.5
Issue Comment 1 0
Review Comment 3 8
Conversation Incentives
Comment Formatting Relevance Reward
@molecula451 I tried to override X25519_PRIVATE_KEY but it did n…
0
content:
  p:
    count: 26
    score: 1
wordValue: 0
formattingMultiplier: 0
0.8 -
The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10…
0
content:
  p:
    count: 11
    score: 1
wordValue: 0
formattingMultiplier: 0
0.8 -
@pavlovcik @molecula451 please check now again, I added to docs.
4
content:
  p:
    count: 10
    score: 1
wordValue: 0.2
formattingMultiplier: 2
0.8 3.2
No way, full details are available in plain sight, only for test…
6
content:
  p:
    count: 15
    score: 1
wordValue: 0.2
formattingMultiplier: 2
0.8 4.8
\ No newline at end of file diff --git a/tests/__mocks__/results/permit-generation-results.json b/tests/__mocks__/results/permit-generation-results.json new file mode 100644 index 00000000..6fb270c4 --- /dev/null +++ b/tests/__mocks__/results/permit-generation-results.json @@ -0,0 +1,437 @@ +{ + "molecula451": { + "total": 1.8, + "userId": 41552663, + "comments": [ + { + "content": "pavlovcik i think we need to update a bit the readme ! dm what to whom?", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948916343", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 16, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.32, + "relevance": 0.8 + } + }, + { + "content": "let us know when done", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948989989", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 5, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.1, + "relevance": 0.8 + } + }, + { + "content": "https://github.com/ubiquibot/comment-incentives/actions/runs/7935268560 invalid input sounds unexpected @gitcoindev ??", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949195772", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.14, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik permitted with hard debug (tho no funds in the private key)", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949564869", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.24, + "relevance": 0.8 + } + }, + { + "content": "pavlovcik i re-generated the X25519 to trigger the permit, what you don't understand? using a private key i own, but also did many commits to reach the root cause", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949635137", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 29, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.58, + "relevance": 0.8 + } + }, + { + "content": "sure thing", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639196", + "type": "ISSUE|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 2, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.04, + "relevance": 0.8 + } + }, + { + "content": "indeed", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.02, + "relevance": 0.8 + } + }, + { + "content": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "type": "REVIEW|CONTRIBUTOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 18, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 0.25 + }, + "reward": 0.36, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiIxODAwMDAwMDAwMDAwMDAwMDAwIn0sIm5vbmNlIjoiNTU5OTM2MDE0NzcwMzQzMTA4MTU5NDY5ODEzMzcwNTA1MDMxMzkxMzU2MjIzMDMwNTA5MjQyNzA2ODYyOTY3NzAwMDEzODA2OTM3ODEiLCJkZWFkbGluZSI6IjU3ODk2MDQ0NjE4NjU4MDk3NzExNzg1NDkyNTA0MzQzOTUzOTI2NjM0OTkyMzMyODIwMjgyMDE5NzI4NzkyMDAzOTU2NTY0ODE5OTY3In0sInRyYW5zZmVyRGV0YWlscyI6eyJ0byI6IjB4NEQwNzA0ZjQwMEQ1N0JhOTNlRWE4ODc2NUMzRmNEQkQ4MjZkQ0ZjNCIsInJlcXVlc3RlZEFtb3VudCI6IjE4MDAwMDAwMDAwMDAwMDAwMDAifSwib3duZXIiOiIweDBmQzFiOTA5YmE5MjY1QTg0NmI4MkNGNENFMzUyZmMzZTdFZUIyRUQiLCJzaWduYXR1cmUiOiIweDdjYmNiNzIzODU3NDQwMWIwNDA2YjYxNmYwY2RiYjQzNjM5YjUyMDAwOGYwNGRmY2ZhZWVjNmZlMjg5NjZjZWUxOGQ4NDA5M2RmM2MwZjk3ZWJlMGRiZjYyYjE5ZTE5NzU2ZWNiMGY2YWU2YjAyMThjZGRlOTAxZTA2N2JmM2YzMWIiLCJuZXR3b3JrSWQiOjEwMH1d" + }, + "0x4007": { + "total": 33.44, + "userId": 4975670, + "comments": [ + { + "content": "Link below for conversation context. It was to me. Anyways you need to create a new private key for this task!", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1948930217", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 21, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 3.36, + "relevance": 0.8 + } + }, + { + "content": "In the repository secrets I think I need to change the key to match @gitcoindev's", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949201722", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 2.4, + "relevance": 0.8 + } + }, + { + "content": "I just changed it to `627H-BcWbcp_O3YmQGIA6MqgxVsFuplFCA9DK3iC7GQ` I hope that it doesn't break production for some reason (it should get it from Netlify secrets, but not sure if we implemented this correctly!) I fear that we might need to build a feature for this to support development key pair and production. Unfortunately I'm already winding down for the day so I'll leave you guys to try and investigate.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949203681", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 67, + "score": 1 + }, + "code": { + "count": 1, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 10.88, + "relevance": 0.8 + } + }, + { + "content": "I don't understand what you mean by this", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949633751", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 8, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.28, + "relevance": 0.8 + } + }, + { + "content": "I'll investigate more on my computer later.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949639054", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 1.12, + "relevance": 0.8 + } + }, + { + "content": "Will it be an issue if I revert to the commit and secret that I had before? It was the production x25519 key in the GitHub repository secrets when it was working like eight hours ago. Posting this message before checking on my computer to get you before you log off.", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949642845", + "type": "ISSUE|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 51, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 1 + }, + "reward": 8.16, + "relevance": 0.8 + } + }, + { + "content": "Can somebody work on generating a new `X25519_PRIVATE_KEY` for the ubiquibot organization? We need to share it for development purposes. 1. Generate a new key 2. Encrypt a new `evmPrivateKeyEncrypted` (no funds!) and add to the org bot config 3. Add the shared test key to the `comment-incentives` readme. https://github.com/ubiquibot/comment-incentives/pull/21/commits/567419d9688e92edf698f64c697f1a7cafe1d02e _Originally posted by @pavlovcik in https://github.com/ubiquibot/comment-incentives/issues/19#issuecomment-1948876653_", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22", + "type": "ISSUE|ISSUER|TASK", + "score": { + "formatting": { + "content": { + "p": { + "count": 56, + "score": 1 + }, + "code": { + "count": 3, + "score": 1 + }, + "em": { + "count": 6, + "score": 0 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 4.72, + "relevance": 0.8 + } + }, + { + "content": "Need to document a private key too", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 7, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.56, + "relevance": 0.8 + } + }, + { + "content": "I was editing this right now but was too slow to push.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "type": "REVIEW|COLLABORATOR|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 12, + "score": 1 + } + }, + "wordValue": 0.1, + "formattingMultiplier": 1 + }, + "reward": 0.96, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiIzMzQ0MDAwMDAwMDAwMDAwMDAwMCJ9LCJub25jZSI6IjU0MTU2NjczMjEwMTg2MDc2NjY3MDM0MzA4MDMwMzQxMTU2NjMyMTc1NDA0MTE1ODg4NzA3NjM5NTc1ODU0Mzg0MzM3NTUwNzUyMjU2IiwiZGVhZGxpbmUiOiI1Nzg5NjA0NDYxODY1ODA5NzcxMTc4NTQ5MjUwNDM0Mzk1MzkyNjYzNDk5MjMzMjgyMDI4MjAxOTcyODc5MjAwMzk1NjU2NDgxOTk2NyJ9LCJ0cmFuc2ZlckRldGFpbHMiOnsidG8iOiIweDREMDcwNGY0MDBENTdCYTkzZUVhODg3NjVDM0ZjREJEODI2ZENGYzQiLCJyZXF1ZXN0ZWRBbW91bnQiOiIzMzQ0MDAwMDAwMDAwMDAwMDAwMCJ9LCJvd25lciI6IjB4MGZDMWI5MDliYTkyNjVBODQ2YjgyQ0Y0Q0UzNTJmYzNlN0VlQjJFRCIsInNpZ25hdHVyZSI6IjB4YWUyOWQwNWE1N2EwNDg0NzE5MDc4ZDQ4MWUxMWVmMDBlY2RiYzIwMjczOGJiY2QzZjc5NDFiYjkzNTY2ZDE4ZDUwZTBkY2NjNjkxM2U5OTM2MjJmNTVjZmM4NWNkNmY5YTNhOTYzZWNhNmRhZGY4NzVlYjIxOTg4NmM1MGY4ZTUxYiIsIm5ldHdvcmtJZCI6MTAwfV0=" + }, + "gitcoindev": { + "total": 45.5, + "task": { + "reward": 37.5 + }, + "userId": 88761781, + "comments": [ + { + "content": "@molecula451 I tried to override X25519_PRIVATE_KEY but it did not help. It seems that https://github.com/ubiquibot/production/blob/1937a6ba75588f51d1bf07fed1f6384f79090465/.github/ubiquibot-config.yml#L2 takes precedence over https://github.com/ubiquibot/comment-incentives/blob/main/.github/ubiquibot-config.yml#L2 (I see the first one in logs).", + "url": "https://github.com/ubiquibot/comment-incentives/issues/22#issuecomment-1949333227", + "type": "ISSUE|ASSIGNEE|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 26, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "The new evmPrivateKeyEncrypted generated for address 0x3a2E44e10AbEf5CB4a6E492c5ba93d30068d2D95 (no funds). Resolves: https://github.com/ubiquibot/comment-incentives/issues/22", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25", + "type": "REVIEW|ISSUER|SPECIFICATION", + "score": { + "formatting": { + "content": { + "p": { + "count": 11, + "score": 1 + } + }, + "wordValue": 0, + "formattingMultiplier": 0 + }, + "reward": 0, + "relevance": 0.8 + } + }, + { + "content": "@pavlovcik @molecula451 please check now again, I added to docs.", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 10, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 3.2, + "relevance": 0.8 + } + }, + { + "content": "No way, full details are available in plain sight, only for test in production purposes", + "url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "type": "REVIEW|ISSUER|COMMENTED", + "score": { + "formatting": { + "content": { + "p": { + "count": 15, + "score": 1 + } + }, + "wordValue": 0.2, + "formattingMultiplier": 2 + }, + "reward": 4.8, + "relevance": 0.8 + } + } + ], + "permitUrl": "https://pay.ubq.fi?claim=W3sidHlwZSI6ImVyYzIwLXBlcm1pdCIsInBlcm1pdCI6eyJwZXJtaXR0ZWQiOnsidG9rZW4iOiIweGU5MUQxNTNFMGI0MTUxOEEyQ2U4RGQzRDc5NDRGYTg2MzQ2M2E5N2QiLCJhbW91bnQiOiI0NTUwMDAwMDAwMDAwMDAwMDAwMCJ9LCJub25jZSI6IjI1NTAxODE5OTY2NjA1NzQ1MzA1NTE0MTk4MDg3NTY5MTYyMTg1ODQzNzc2NTY0MDgxNzUwODI4NjE5MzMxNjYyNDIzMjAwMTU3MDk1IiwiZGVhZGxpbmUiOiI1Nzg5NjA0NDYxODY1ODA5NzcxMTc4NTQ5MjUwNDM0Mzk1MzkyNjYzNDk5MjMzMjgyMDI4MjAxOTcyODc5MjAwMzk1NjU2NDgxOTk2NyJ9LCJ0cmFuc2ZlckRldGFpbHMiOnsidG8iOiIweDREMDcwNGY0MDBENTdCYTkzZUVhODg3NjVDM0ZjREJEODI2ZENGYzQiLCJyZXF1ZXN0ZWRBbW91bnQiOiI0NTUwMDAwMDAwMDAwMDAwMDAwMCJ9LCJvd25lciI6IjB4MGZDMWI5MDliYTkyNjVBODQ2YjgyQ0Y0Q0UzNTJmYzNlN0VlQjJFRCIsInNpZ25hdHVyZSI6IjB4NzQzNWUxMTZlN2FjYTg4OTI0YmI3ODVmZmQ0ZWM4ZjYzNGI4YWNkYmM1NGQ5OTBjOTU5N2VkNzVmYTA0MTE5NDcwZjc2ZGRhMTAzMzVmMGUyMjVmM2Q0YTVkMWEzNDQyYWMxZjkzYTIwMjNlYjY4N2VlZmI3NzIzMGY5MTQzZmYxYiIsIm5ldHdvcmtJZCI6MTAwfV0=" + } +} diff --git a/tests/__mocks__/routes/issue-25-comments-get.json b/tests/__mocks__/routes/issue-25-comments-get.json new file mode 100644 index 00000000..b76e848d --- /dev/null +++ b/tests/__mocks__/routes/issue-25-comments-get.json @@ -0,0 +1,266 @@ +[ + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949021356", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949021356", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949021356, + "node_id": "IC_kwDOK87YcM50K7Ss", + "user": { + "login": "0x4007", + "id": 4975670, + "node_id": "MDQ6VXNlcjQ5NzU2NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/4975670?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x4007", + "html_url": "https://github.com/0x4007", + "followers_url": "https://api.github.com/users/0x4007/followers", + "following_url": "https://api.github.com/users/0x4007/following{/other_user}", + "gists_url": "https://api.github.com/users/0x4007/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x4007/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x4007/subscriptions", + "organizations_url": "https://api.github.com/users/0x4007/orgs", + "repos_url": "https://api.github.com/users/0x4007/repos", + "events_url": "https://api.github.com/users/0x4007/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x4007/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T18:11:04Z", + "updated_at": "2024-02-16T18:11:04Z", + "author_association": "MEMBER", + "body": "Need to document a private key too ", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949021356/reactions", + "total_count": 2, + "+1": 2, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "performed_via_github_app": null + }, + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949038563", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949038563", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949038563, + "node_id": "IC_kwDOK87YcM50K_fj", + "user": { + "login": "molecula451", + "id": 41552663, + "node_id": "MDQ6VXNlcjQxNTUyNjYz", + "avatar_url": "https://avatars.githubusercontent.com/u/41552663?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/molecula451", + "html_url": "https://github.com/molecula451", + "followers_url": "https://api.github.com/users/molecula451/followers", + "following_url": "https://api.github.com/users/molecula451/following{/other_user}", + "gists_url": "https://api.github.com/users/molecula451/gists{/gist_id}", + "starred_url": "https://api.github.com/users/molecula451/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/molecula451/subscriptions", + "organizations_url": "https://api.github.com/users/molecula451/orgs", + "repos_url": "https://api.github.com/users/molecula451/repos", + "events_url": "https://api.github.com/users/molecula451/events{/privacy}", + "received_events_url": "https://api.github.com/users/molecula451/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T18:17:06Z", + "updated_at": "2024-02-16T18:17:06Z", + "author_association": "CONTRIBUTOR", + "body": "indeed", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949038563/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "performed_via_github_app": null + }, + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949044575", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044575", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949044575, + "node_id": "IC_kwDOK87YcM50LA9f", + "user": { + "login": "gitcoindev", + "id": 88761781, + "node_id": "MDQ6VXNlcjg4NzYxNzgx", + "avatar_url": "https://avatars.githubusercontent.com/u/88761781?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gitcoindev", + "html_url": "https://github.com/gitcoindev", + "followers_url": "https://api.github.com/users/gitcoindev/followers", + "following_url": "https://api.github.com/users/gitcoindev/following{/other_user}", + "gists_url": "https://api.github.com/users/gitcoindev/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gitcoindev/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gitcoindev/subscriptions", + "organizations_url": "https://api.github.com/users/gitcoindev/orgs", + "repos_url": "https://api.github.com/users/gitcoindev/repos", + "events_url": "https://api.github.com/users/gitcoindev/events{/privacy}", + "received_events_url": "https://api.github.com/users/gitcoindev/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T18:19:03Z", + "updated_at": "2024-02-16T18:19:03Z", + "author_association": "CONTRIBUTOR", + "body": "@pavlovcik @molecula451 please check now again, I added to docs.", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949044575/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "performed_via_github_app": null + }, + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949044855", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949044855", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949044855, + "node_id": "IC_kwDOK87YcM50LBB3", + "user": { + "login": "molecula451", + "id": 41552663, + "node_id": "MDQ6VXNlcjQxNTUyNjYz", + "avatar_url": "https://avatars.githubusercontent.com/u/41552663?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/molecula451", + "html_url": "https://github.com/molecula451", + "followers_url": "https://api.github.com/users/molecula451/followers", + "following_url": "https://api.github.com/users/molecula451/following{/other_user}", + "gists_url": "https://api.github.com/users/molecula451/gists{/gist_id}", + "starred_url": "https://api.github.com/users/molecula451/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/molecula451/subscriptions", + "organizations_url": "https://api.github.com/users/molecula451/orgs", + "repos_url": "https://api.github.com/users/molecula451/repos", + "events_url": "https://api.github.com/users/molecula451/events{/privacy}", + "received_events_url": "https://api.github.com/users/molecula451/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T18:19:09Z", + "updated_at": "2024-02-16T18:19:09Z", + "author_association": "CONTRIBUTOR", + "body": "go to go pavlovick, we'll be using this one for test only or test in production (lmao) ?", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949044855/reactions", + "total_count": 1, + "+1": 0, + "-1": 0, + "laugh": 1, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "performed_via_github_app": null + }, + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949046925", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949046925", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949046925, + "node_id": "IC_kwDOK87YcM50LBiN", + "user": { + "login": "gitcoindev", + "id": 88761781, + "node_id": "MDQ6VXNlcjg4NzYxNzgx", + "avatar_url": "https://avatars.githubusercontent.com/u/88761781?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gitcoindev", + "html_url": "https://github.com/gitcoindev", + "followers_url": "https://api.github.com/users/gitcoindev/followers", + "following_url": "https://api.github.com/users/gitcoindev/following{/other_user}", + "gists_url": "https://api.github.com/users/gitcoindev/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gitcoindev/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gitcoindev/subscriptions", + "organizations_url": "https://api.github.com/users/gitcoindev/orgs", + "repos_url": "https://api.github.com/users/gitcoindev/repos", + "events_url": "https://api.github.com/users/gitcoindev/events{/privacy}", + "received_events_url": "https://api.github.com/users/gitcoindev/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T18:19:52Z", + "updated_at": "2024-02-16T18:25:38Z", + "author_association": "CONTRIBUTOR", + "body": "No way, full details are available in plain sight, only for test in production purposes", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949046925/reactions", + "total_count": 1, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 1 + }, + "performed_via_github_app": null + }, + { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949196677", + "html_url": "https://github.com/ubiquibot/comment-incentives/pull/25#issuecomment-1949196677", + "issue_url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/25", + "id": 1949196677, + "node_id": "IC_kwDOK87YcM50LmGF", + "user": { + "login": "0x4007", + "id": 4975670, + "node_id": "MDQ6VXNlcjQ5NzU2NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/4975670?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x4007", + "html_url": "https://github.com/0x4007", + "followers_url": "https://api.github.com/users/0x4007/followers", + "following_url": "https://api.github.com/users/0x4007/following{/other_user}", + "gists_url": "https://api.github.com/users/0x4007/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x4007/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x4007/subscriptions", + "organizations_url": "https://api.github.com/users/0x4007/orgs", + "repos_url": "https://api.github.com/users/0x4007/repos", + "events_url": "https://api.github.com/users/0x4007/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x4007/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2024-02-16T19:27:30Z", + "updated_at": "2024-02-16T19:27:30Z", + "author_association": "MEMBER", + "body": "I was editing this right now but was too slow to push.", + "reactions": { + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/comments/1949196677/reactions", + "total_count": 1, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 1 + }, + "performed_via_github_app": null + } +] diff --git a/tests/__mocks__/routes/issue-events-2-get.json b/tests/__mocks__/routes/issue-events-2-get.json new file mode 100644 index 00000000..576662ec --- /dev/null +++ b/tests/__mocks__/routes/issue-events-2-get.json @@ -0,0 +1,32 @@ +[ + { + "id": 11835426216, + "node_id": "SE_lADOK87YcM5_fo85zwAAAALBckWo", + "url": "https://api.github.com/repos/ubiquibot/comment-incentives/issues/events/11835426216", + "actor": { + "login": "0x4007", + "id": 4975670, + "node_id": "MDQ6VXNlcjQ5NzU2NzA=", + "avatar_url": "https://avatars.githubusercontent.com/u/4975670?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x4007", + "html_url": "https://github.com/0x4007", + "followers_url": "https://api.github.com/users/0x4007/followers", + "following_url": "https://api.github.com/users/0x4007/following{/other_user}", + "gists_url": "https://api.github.com/users/0x4007/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x4007/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x4007/subscriptions", + "organizations_url": "https://api.github.com/users/0x4007/orgs", + "repos_url": "https://api.github.com/users/0x4007/repos", + "events_url": "https://api.github.com/users/0x4007/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x4007/received_events", + "type": "User", + "site_admin": false + }, + "event": "subscribed", + "commit_id": null, + "commit_url": null, + "created_at": "2024-02-17T03:55:29Z", + "performed_via_github_app": null + } +] diff --git a/tests/get-activity.test.ts b/tests/get-activity.test.ts index d0f5fa1d..37db43fd 100644 --- a/tests/get-activity.test.ts +++ b/tests/get-activity.test.ts @@ -1,5 +1,4 @@ import { IssueActivity } from "../src/issue-activity"; -import { Processor } from "../src/parser/processor"; import { parseGitHubUrl } from "../src/start"; // Mock process.argv @@ -17,10 +16,7 @@ describe("GetActivity class", () => { expect(activity.events).toBeTruthy(); expect(activity.comments).toBeTruthy(); expect(Array.isArray(activity.linkedReviews)).toBeTruthy(); - const processor = new Processor(); - await processor.run(activity); - processor.dump(); - }, 30000); + }); it("should create an instance of GetActivity", () => { expect(activity).toBeInstanceOf(IssueActivity); diff --git a/tests/process.issue.test.ts b/tests/process.issue.test.ts index 07109499..18768bc6 100644 --- a/tests/process.issue.test.ts +++ b/tests/process.issue.test.ts @@ -6,9 +6,55 @@ import { server } from "./__mocks__/node"; import { DataPurgeModule } from "../src/parser/data-purge-module"; import userCommentResults from "./__mocks__/results/user-comment-results.json"; import dataPurgeResults from "./__mocks__/results/data-purge-result.json"; +import formattingEvaluatorResults from "./__mocks__/results/formatting-evaluator-results.json"; +import permitGenerationResults from "./__mocks__/results/permit-generation-results.json"; +import contentEvaluatorResults from "./__mocks__/results/content-evaluator-results.json"; +import githubCommentResults from "./__mocks__/results/github-comment-results.json"; +import dbSeed from "./__mocks__/db-seed.json"; +import { FormattingEvaluatorModule } from "../src/parser/formatting-evaluator-module"; +import { ContentEvaluatorModule } from "../src/parser/content-evaluator-module"; +import Decimal from "decimal.js"; +import { PermitGenerationModule } from "../src/parser/permit-generation-module"; +import { db as mockDb } from "./__mocks__/db"; +import { GithubCommentModule } from "../src/parser/github-comment-module"; +import fs from "fs"; const issueUrl = process.env.TEST_ISSUE_URL || "https://github.com/ubiquibot/comment-incentives/issues/22"; +jest.spyOn(ContentEvaluatorModule.prototype, "_evaluateComments").mockImplementation((specification, comments) => { + return Promise.resolve(comments.map(() => new Decimal(0.8))); +}); + +jest.mock("@ubiquibot/permit-generation/core", () => { + const originalModule = jest.requireActual("@ubiquibot/permit-generation/core"); + + return { + __esModule: true, + ...originalModule, + createAdapters: jest.fn(() => { + return { + supabase: { + wallet: { + getWalletByUserId: jest.fn((userId: number) => { + const wallet = mockDb.wallets.findFirst({ + where: { + userId: { + equals: userId, + }, + }, + }); + if (!wallet) { + return Promise.resolve(null); + } + return Promise.resolve(wallet.address); + }), + }, + }, + }; + }), + }; +}); + beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); @@ -19,6 +65,12 @@ describe("Modules tests", () => { beforeAll(async () => { await activity.init(); + for (const item of dbSeed.users) { + mockDb.users.create(item); + } + for (const item of dbSeed.wallets) { + mockDb.wallets.create(item); + } }); it("Should extract users from comments", async () => { @@ -28,6 +80,7 @@ describe("Modules tests", () => { await processor.run(activity); processor.dump(); expect(logSpy).toHaveBeenCalledWith(JSON.stringify(userCommentResults, undefined, 2)); + logSpy.mockReset(); }); it("Should purge data", async () => { @@ -37,5 +90,65 @@ describe("Modules tests", () => { await processor.run(activity); processor.dump(); expect(logSpy).toHaveBeenCalledWith(JSON.stringify(dataPurgeResults, undefined, 2)); + logSpy.mockReset(); + }); + + it("Should evaluate formatting", async () => { + const logSpy = jest.spyOn(console, "log"); + const processor = new Processor(); + processor["_transformers"] = [new UserExtractorModule(), new DataPurgeModule(), new FormattingEvaluatorModule()]; + await processor.run(activity); + processor.dump(); + expect(logSpy).toHaveBeenCalledWith(JSON.stringify(formattingEvaluatorResults, undefined, 2)); + logSpy.mockReset(); + }); + + it("Should evaluate content", async () => { + const logSpy = jest.spyOn(console, "log"); + const processor = new Processor(); + processor["_transformers"] = [ + new UserExtractorModule(), + new DataPurgeModule(), + new FormattingEvaluatorModule(), + new ContentEvaluatorModule(), + ]; + await processor.run(activity); + processor.dump(); + expect(logSpy).toHaveBeenCalledWith(JSON.stringify(contentEvaluatorResults, undefined, 2)); + logSpy.mockReset(); + }); + + it("Should generate permits", async () => { + const logSpy = jest.spyOn(console, "log"); + const processor = new Processor(); + processor["_transformers"] = [ + new UserExtractorModule(), + new DataPurgeModule(), + new FormattingEvaluatorModule(), + new ContentEvaluatorModule(), + new PermitGenerationModule(), + ]; + await processor.run(activity); + processor.dump(); + expect(logSpy).toHaveBeenCalledWith(JSON.stringify(permitGenerationResults, undefined, 2)); + logSpy.mockReset(); + }); + + it("Should generate GitHub comment", async () => { + const logSpy = jest.spyOn(console, "log"); + const processor = new Processor(); + processor["_transformers"] = [ + new UserExtractorModule(), + new DataPurgeModule(), + new FormattingEvaluatorModule(), + new ContentEvaluatorModule(), + new PermitGenerationModule(), + new GithubCommentModule(), + ]; + await processor.run(activity); + processor.dump(); + expect(logSpy).toHaveBeenCalledWith(JSON.stringify(githubCommentResults, undefined, 2)); + expect(fs.readFileSync("./output.html")).toEqual(fs.readFileSync("./tests/__mocks__/results/output.html")); + logSpy.mockReset(); }); }); diff --git a/tsconfig.json b/tsconfig.json index 8fe01bab..54f91018 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,7 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, + "module": "Node16" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ diff --git a/yarn.lock b/yarn.lock index a02f22f6..ba6587a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1011,7 +1011,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.8.4": +"@babel/runtime@^7.21.0", "@babel/runtime@^7.8.4": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== @@ -2433,6 +2433,27 @@ resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== +"@mswjs/data@0.16.1": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@mswjs/data/-/data-0.16.1.tgz#ee41b95b8f2e954a07b0eb54154592a2459064d1" + integrity sha512-VhJvL/VmgAuU9/tDOcKcxHfNd+8nxYntZnrkaQEQPvZZnFwQQR9bzI1FTRROGxCHVoyfv9v84AEkl/7CIw4FAg== + dependencies: + "@types/lodash" "^4.14.172" + "@types/md5" "^2.3.0" + "@types/pluralize" "^0.0.29" + "@types/uuid" "^8.3.0" + date-fns "^2.21.1" + debug "^4.3.1" + graphql "^16.8.1" + lodash "^4.17.21" + md5 "^2.3.0" + outvariant "^1.2.1" + pluralize "^8.0.0" + strict-event-emitter "^0.5.0" + uuid "^8.3.1" + optionalDependencies: + msw "^2.0.8" + "@mswjs/interceptors@^0.26.14": version "0.26.15" resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.26.15.tgz#256ad5c89f325c87d972cc27fc7d0d6d382ce804" @@ -2548,6 +2569,56 @@ dependencies: which "^4.0.0" +"@octokit/auth-app@6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-6.1.1.tgz#758a5d2e0324c750f7463b10398fd99c52b2eb89" + integrity sha512-VrTtzRpyuT5nYGUWeGWQqH//hqEZDV+/yb6+w5wmWpmmUA1Tx950XsAc2mBBfvusfcdF2E7w8jZ1r1WwvfZ9pA== + dependencies: + "@octokit/auth-oauth-app" "^7.1.0" + "@octokit/auth-oauth-user" "^4.1.0" + "@octokit/request" "^8.3.1" + "@octokit/request-error" "^5.1.0" + "@octokit/types" "^13.1.0" + deprecation "^2.3.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^1.1.2" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-app@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz#d0f74e19ebd5a4829cb780c107cedd6c894f20fc" + integrity sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA== + dependencies: + "@octokit/auth-oauth-device" "^6.1.0" + "@octokit/auth-oauth-user" "^4.1.0" + "@octokit/request" "^8.3.1" + "@octokit/types" "^13.0.0" + "@types/btoa-lite" "^1.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-device@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz#f868213a3db05fe27e68d1fc607502a322379dd9" + integrity sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw== + dependencies: + "@octokit/oauth-methods" "^4.1.0" + "@octokit/request" "^8.3.1" + "@octokit/types" "^13.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-user@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz#32e5529f8bd961af9839a1f8c6ab0c8ad2184eee" + integrity sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ== + dependencies: + "@octokit/auth-oauth-device" "^6.1.0" + "@octokit/oauth-methods" "^4.1.0" + "@octokit/request" "^8.3.1" + "@octokit/types" "^13.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + "@octokit/auth-token@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" @@ -2583,6 +2654,22 @@ "@octokit/types" "^13.0.0" universal-user-agent "^6.0.0" +"@octokit/oauth-authorization-url@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz#cc82ca29cc5e339c9921672f39f2b3f5c8eb6ef2" + integrity sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA== + +"@octokit/oauth-methods@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz#1403ac9c4d4e277922fddc4c89fa8a782f8f791b" + integrity sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw== + dependencies: + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/request" "^8.3.1" + "@octokit/request-error" "^5.1.0" + "@octokit/types" "^13.0.0" + btoa-lite "^1.0.0" + "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" @@ -2813,16 +2900,21 @@ "@pnpm/types" "9.4.2" ramda "npm:@pnpm/ramda@0.28.1" -"@sinclair/typebox@0.32.20", "@sinclair/typebox@^0.32.5": - version "0.32.20" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.20.tgz#32bdeb6b185188622f965ebbc88e1a6d5127d88a" - integrity sha512-ziK497ILSIYMxD/thl496idIb03IZPlha04itLQu1xAFQbumWZ+Dj4PMMCkDRpAYhvVSdmRlTjGu2B2MA5RplQ== +"@sinclair/typebox@0.32.23": + version "0.32.23" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.23.tgz#18419f3a276da4e7f26300497c1537848727778b" + integrity sha512-NiMhEgFo5nDlg39HDEvETDdXmURfyd8ougIjynebGebZti/gZ4LxoCcbVS6jgfNF8Sf7ZvPVl/fV0YsJIW4ltg== "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sinclair/typebox@^0.32.5": + version "0.32.20" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.20.tgz#32bdeb6b185188622f965ebbc88e1a6d5127d88a" + integrity sha512-ziK497ILSIYMxD/thl496idIb03IZPlha04itLQu1xAFQbumWZ+Dj4PMMCkDRpAYhvVSdmRlTjGu2B2MA5RplQ== + "@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -2956,6 +3048,11 @@ dependencies: "@babel/types" "^7.20.7" +"@types/btoa-lite@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/btoa-lite/-/btoa-lite-1.0.2.tgz#82bb6aab00abf7cff3ca2825abe010c0cd536ae5" + integrity sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg== + "@types/cookie@^0.6.0": version "0.6.0" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" @@ -3009,11 +3106,23 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/jsonwebtoken@^9.0.0": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== + dependencies: + "@types/node" "*" + "@types/linkify-it@*": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== +"@types/lodash@^4.14.172": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== + "@types/markdown-it@13.0.7": version "13.0.7" resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-13.0.7.tgz#4a495115f470075bd4434a0438ac477a49c2e152" @@ -3022,6 +3131,11 @@ "@types/linkify-it" "*" "@types/mdurl" "*" +"@types/md5@^2.3.0": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@types/md5/-/md5-2.3.5.tgz#481cef0a896e3a5dcbfc5a8a8b02c05958af48a5" + integrity sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw== + "@types/mdurl@*": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" @@ -3088,6 +3202,11 @@ resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.3.tgz#be60498568c19e989e43fb39aa84be1ed3655e92" integrity sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg== +"@types/pluralize@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/pluralize/-/pluralize-0.0.29.tgz#6ffa33ed1fc8813c469b859681d09707eb40d03c" + integrity sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA== + "@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" @@ -3108,6 +3227,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== +"@types/uuid@^8.3.0": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + "@types/wrap-ansi@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" @@ -3218,10 +3342,15 @@ "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" -"@ubiquibot/permit-generation@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@ubiquibot/permit-generation/-/permit-generation-1.2.1.tgz#e4cbeedf5aca9f1b088e4bcf06e97991fe428131" - integrity sha512-OSr4Pfcuy51AeasAKVVGuRcgUE9de7erLiv67dMxewMpCMdM0xZn+ash1FbV5EtbxkNRyO2uu1wCTV/z5cbhUg== +"@ubiquibot/configuration@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@ubiquibot/configuration/-/configuration-2.0.3.tgz#2138ead3f38d14f498afb17be92a590b6d48c365" + integrity sha512-Seizwvt3kg6biF9DtbqSJ+aLkIgr0iOYBPvTL1x6ueIILdJgnTgf3Mzfsy7G0BUXGT6Jlr/2eAPqQy77CHhpkg== + +"@ubiquibot/permit-generation@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@ubiquibot/permit-generation/-/permit-generation-1.2.2.tgz#3493b4701e1d9deccd4e4d5c9aef4e3f7b76e4d8" + integrity sha512-782Pd5Ub7T5bjfsPGGhE1LVFWhhyAl20ZX1EgCltGzouHgXdha5NKWYh4aG1DIfx7EVJ/6lUAE2yb1PyqAlb5Q== dependencies: "@actions/core" "^1.10.1" "@actions/github" "^6.0.0" @@ -3329,17 +3458,14 @@ aggregate-error@^5.0.0: clean-stack "^5.2.0" indent-string "^5.0.0" -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== +ajv-formats@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" + ajv "^8.0.0" -ajv@^8.11.0: +ajv@8.12.0, ajv@^8.0.0, ajv@^8.11.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -3349,6 +3475,16 @@ ajv@^8.11.0: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -3662,6 +3798,16 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +btoa-lite@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" + integrity sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -4205,6 +4351,13 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" +date-fns@^2.21.1: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -4280,7 +4433,7 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -deprecation@^2.0.0: +deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== @@ -4355,6 +4508,13 @@ easy-table@1.2.0: optionalDependencies: wcwidth "^1.0.1" +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + electron-to-chromium@^1.4.668: version "1.4.738" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.738.tgz#9a7fca98abaee61e20c9c25013d5ce60bb533436" @@ -6187,6 +6347,39 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +jsonwebtoken@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + keyv@^4.5.3, keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -6352,16 +6545,41 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + lodash.isfunction@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.kebabcase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" @@ -6377,6 +6595,11 @@ lodash.mergewith@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + lodash.snakecase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" @@ -6397,7 +6620,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.15: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6413,6 +6636,11 @@ log-update@^6.0.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" +lru-cache@^10.0.0: + version "10.2.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.1.tgz#e8d901141f22937968e45a6533d52824070151e4" + integrity sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA== + lru-cache@^10.0.1, lru-cache@^10.0.2, lru-cache@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" @@ -6659,12 +6887,12 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msw@2.2.14: +msw@2.2.14, msw@^2.0.8: version "2.2.14" resolved "https://registry.yarnpkg.com/msw/-/msw-2.2.14.tgz#ed16b89f99ffc105a84b0295a6fcae2ee99f5c62" integrity sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA== @@ -7135,6 +7363,11 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + possible-typed-array-names@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" @@ -7476,7 +7709,7 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -7706,7 +7939,7 @@ statuses@^2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -strict-event-emitter@^0.5.1: +strict-event-emitter@^0.5.0, strict-event-emitter@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== @@ -8221,6 +8454,14 @@ unique-string@^3.0.0: dependencies: crypto-random-string "^4.0.0" +universal-github-app-jwt@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz#8c1867a394d7d9d42cda34f11d1bcb023797d8df" + integrity sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA== + dependencies: + "@types/jsonwebtoken" "^9.0.0" + jsonwebtoken "^9.0.2" + universal-user-agent@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" @@ -8264,7 +8505,7 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@^8.3.2: +uuid@^8.3.1, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==