diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 1277601e..2eee5b41 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -15,6 +15,8 @@ on: description: "Auth Token" ref: description: "Ref" + signature: + description: "The kernel signature" jobs: compute: diff --git a/.github/workflows/update-configuration.yml b/.github/workflows/update-configuration.yml new file mode 100644 index 00000000..2490c49a --- /dev/null +++ b/.github/workflows/update-configuration.yml @@ -0,0 +1,58 @@ +name: "Update Configuration" + +on: + workflow_dispatch: + push: + +jobs: + update: + name: "Update Configuration in manifest.json" + runs-on: ubuntu-latest + permissions: write-all + + steps: + - uses: actions/checkout@v4 + + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: Install deps and run configuration update + run: | + yarn install --immutable --immutable-cache --check-cache + yarn tsc --noCheck --project tsconfig.json + + - name: Update manifest configuration using GitHub Script + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const path = require('path'); + + const { pluginSettingsSchema } = require('./src/types'); + + const manifestPath = path.resolve("${{ github.workspace }}", './manifest.json'); + const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); + + const configuration = JSON.stringify(pluginSettingsSchema); + + manifest["configuration"] = JSON.parse(configuration); + + const updatedManifest = JSON.stringify(manifest, null, 2) + console.log('Updated manifest:', updatedManifest); + fs.writeFileSync(manifestPath, updatedManifest); + + - name: Commit and Push generated types + run: | + git config --global user.name 'ubiquity-os[bot]' + git config --global user.email 'ubiquity-os[bot]@users.noreply.github.com' + git add ./manifest.json + if [ -n "$(git diff-index --cached --name-only HEAD)" ]; then + git commit -m "chore: updated generated configuration" || echo "Lint-staged check failed" + git push origin HEAD:${{ github.ref_name }} + else + echo "No changes to commit" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c12d37..d8426d6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,12 @@ ## 1.0.0 (2024-07-29) - ### Features -* database update step ([5bad80a](https://github.com/ubiquibot/automated-merging/commit/5bad80a8049890dcf16a5661caadfdacc89fdf2b)) -* set db to be sqlite ([2dbe73b](https://github.com/ubiquibot/automated-merging/commit/2dbe73be10f9ae436050f6b3626890db847c166c)) - +- database update step ([5bad80a](https://github.com/ubiquibot/automated-merging/commit/5bad80a8049890dcf16a5661caadfdacc89fdf2b)) +- set db to be sqlite ([2dbe73b](https://github.com/ubiquibot/automated-merging/commit/2dbe73be10f9ae436050f6b3626890db847c166c)) ### Bug Fixes -* changed approval requirement check to use the configuration ([e1f50e9](https://github.com/ubiquibot/automated-merging/commit/e1f50e95576f81ce01196bbdc0890b0617bf23df)) -* fixed imports within main ([bb001cf](https://github.com/ubiquibot/automated-merging/commit/bb001cf3204593a79b2d214941940a9a44675c00)) +- changed approval requirement check to use the configuration ([e1f50e9](https://github.com/ubiquibot/automated-merging/commit/e1f50e95576f81ce01196bbdc0890b0617bf23df)) +- fixed imports within main ([bb001cf](https://github.com/ubiquibot/automated-merging/commit/bb001cf3204593a79b2d214941940a9a44675c00)) diff --git a/README.md b/README.md index 65ce6480..ce6090ba 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # `@ubiquibot/automated-merging` -Automatically merge pull-requests based on the reviewer count, the time elapsed since the last activity, depending +Automatically merge pull-requests based on the reviewer count, the time elapsed since the last activity, depending on the association of the pull-request author. ## Configuration example @@ -17,6 +17,10 @@ on the association of the pull-request author. mergeTimeout: collaborator: "3.5 days" # defaults to 3.5 days contributor: "7 days" # defaults to 7 days + repos: + monitor: ["ubiquibot/automated-merging"] + ignore: ["ubiquibot/automated-merging"] + allowedReviewerRoles: ["COLLABORATOR", "MEMBER", "OWNER"] ``` ## Testing diff --git a/manifest.json b/manifest.json index 084c9285..1e2e6897 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,87 @@ { "name": "Automated merging", "description": "Automatically merge pull-requests.", - "ubiquity:listeners": [ "push", "issue_comment.created" ] -} + "ubiquity:listeners": [ + "push", + "issue_comment.created" + ], + "configuration": { + "type": "object", + "properties": { + "approvalsRequired": { + "default": {}, + "type": "object", + "properties": { + "collaborator": { + "default": 1, + "minimum": 1, + "type": "number" + }, + "contributor": { + "default": 2, + "minimum": 1, + "type": "number" + } + }, + "required": [ + "collaborator", + "contributor" + ] + }, + "mergeTimeout": { + "default": {}, + "type": "object", + "properties": { + "collaborator": { + "default": "3.5 days", + "type": "string" + }, + "contributor": { + "default": "7 days", + "type": "string" + } + }, + "required": [ + "collaborator", + "contributor" + ] + }, + "repos": { + "default": {}, + "type": "object", + "properties": { + "monitor": { + "default": [], + "type": "array", + "items": { + "minLength": 1, + "type": "string" + } + }, + "ignore": { + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "monitor", + "ignore" + ] + }, + "allowedReviewerRoles": { + "default": [ + "COLLABORATOR", + "MEMBER", + "OWNER" + ], + "type": "array", + "items": { + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 0b981ee1..ac6b7d84 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,8 @@ "npm-run-all": "4.1.5", "prettier": "3.3.2", "ts-jest": "29.1.5", - "typescript": "5.4.5", - "typescript-eslint": "7.13.1" + "typescript": "5.6.2", + "typescript-eslint": "8.8.0" }, "lint-staged": { "*.ts": [ @@ -84,5 +84,6 @@ "extends": [ "@commitlint/config-conventional" ] - } -} + }, + "packageManager": "yarn@1.22.22" +} \ No newline at end of file diff --git a/src/action.ts b/src/action.ts index e5ed458f..13878716 100644 --- a/src/action.ts +++ b/src/action.ts @@ -1,8 +1,8 @@ import * as github from "@actions/github"; import { Octokit } from "@octokit/rest"; -import { Value } from "@sinclair/typebox/value"; +import { validateAndDecodeSchemas } from "./helpers/validator"; import { plugin } from "./plugin"; -import { envSchema, envValidator, PluginInputs, pluginSettingsSchema, pluginSettingsValidator } from "./types"; +import { PluginInputs } from "./types"; /** * How a GitHub action executes the plugin. @@ -11,47 +11,27 @@ export async function run() { const payload = github.context.payload.inputs; payload.env = { ...(payload.env || {}), workflowName: github.context.workflow }; - if (!envValidator.test(payload.env)) { - const errors: string[] = []; - for (const error of envValidator.errors(payload.env)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - throw new Error(`Invalid environment provided:\n${errors.join(";\n")}`); - } - const env = Value.Decode(envSchema, payload.env || {}); - - payload.settings = Value.Default(pluginSettingsSchema, JSON.parse(payload.settings)); - if (!pluginSettingsValidator.test(payload.settings)) { - const errors: string[] = []; - for (const error of pluginSettingsValidator.errors(payload.settings)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - throw new Error(`Invalid settings provided:\n${errors.join(";\n")}`); - } - - const settings = Value.Decode(pluginSettingsSchema, payload.settings); + const { decodedSettings, decodedEnv } = validateAndDecodeSchemas(payload.env, JSON.parse(payload.settings)); const inputs: PluginInputs = { stateId: payload.stateId, eventName: payload.eventName, eventPayload: JSON.parse(payload.eventPayload), - settings, + settings: decodedSettings, authToken: payload.authToken, ref: payload.ref, }; - await plugin(inputs, env); + await plugin(inputs, decodedEnv); return returnDataToKernel(process.env.GITHUB_TOKEN, inputs.stateId, {}); } -async function returnDataToKernel(repoToken: string, stateId: string, output: object) { +export async function returnDataToKernel(repoToken: string, stateId: string, output: object, eventType = "return-data-to-ubiquity-os-kernel") { const octokit = new Octokit({ auth: repoToken }); return octokit.repos.createDispatchEvent({ owner: github.context.repo.owner, repo: github.context.repo.repo, - event_type: "return_data_to_ubiquibot_kernel", + event_type: eventType, client_payload: { state_id: stateId, output: JSON.stringify(output), diff --git a/src/handlers/summary.ts b/src/handlers/summary.ts index 3f91a628..77ccdeac 100644 --- a/src/handlers/summary.ts +++ b/src/handlers/summary.ts @@ -9,7 +9,7 @@ export interface ResultInfo { function generateGitHubSummary(context: Context, urls: ResultInfo[]): string { const target = `https://github.com/${context.payload.repository.owner?.login}`; - const output: string[] = ["## Merge report\n\n"]; + const output: (string | undefined)[] = ["## Merge report\n\n"]; output.push("\n"); output.push("| Merged | ID |"); output.push("|---|---|"); @@ -29,9 +29,9 @@ function generateGitHubSummary(context: Context, urls: ResultInfo[]): string { output.push("\n\n"); output.push("## Configuration\n\n"); output.push("### Watching Repositories\n\n"); - output.push(context.config.repos.monitor.map((o) => `- [${o}](${target}/${o})`).join("\n")); + output.push(context.config.repos?.monitor.map((o) => `- [${o}](${target}/${o})`).join("\n")); output.push("### Ignored Repositories\n\n"); - output.push(context.config.repos.ignore.map((o) => `- [${o}](${target}/${o})`).join("\n")); + output.push(context.config.repos?.ignore.map((o) => `- [${o}](${target}/${o})`).join("\n")); return output.join("\n"); } diff --git a/src/helpers/github.ts b/src/helpers/github.ts index 1b8e5091..cd99bb92 100644 --- a/src/helpers/github.ts +++ b/src/helpers/github.ts @@ -23,26 +23,35 @@ export interface Requirements { * Gets the merge timeout depending on the status of the assignee. If there are multiple assignees with different * statuses, the longest timeout is chosen. */ -export async function getMergeTimeoutAndApprovalRequiredCount(context: Context, authorAssociation: string): Promise { +export async function getMergeTimeoutAndApprovalRequiredCount(context: Context, authorAssociation: string) { + const { + config: { mergeTimeout, approvalsRequired }, + } = context; const timeoutCollaborator = { - mergeTimeout: context.config.mergeTimeout.collaborator, - requiredApprovalCount: context.config.approvalsRequired.collaborator, + mergeTimeout: mergeTimeout?.collaborator, + requiredApprovalCount: approvalsRequired?.collaborator, }; const timeoutContributor = { - mergeTimeout: context.config.mergeTimeout.contributor, - requiredApprovalCount: context.config.approvalsRequired.contributor, + mergeTimeout: mergeTimeout?.contributor, + requiredApprovalCount: approvalsRequired?.contributor, }; + + /** + * Hardcoded roles here because we need to determine the timeouts + * separate from `allowedReviewerRoles` which introduces + * potential unintended user errors and logic issues. + */ return ["COLLABORATOR", "MEMBER", "OWNER"].includes(authorAssociation) ? timeoutCollaborator : timeoutContributor; } -export async function getApprovalCount({ octokit, logger }: Context, { owner, repo, issue_number: pullNumber }: IssueParams) { +export async function getApprovalCount({ octokit, logger, config: { allowedReviewerRoles } }: Context, { owner, repo, issue_number: pullNumber }: IssueParams) { try { const { data: reviews } = await octokit.rest.pulls.listReviews({ owner, repo, pull_number: pullNumber, }); - return reviews.filter((review) => review.state === "APPROVED").length; + return reviews.filter((review) => allowedReviewerRoles?.includes(review.author_association)).filter((review) => review.state === "APPROVED").length; } catch (e) { logger.error(`Error fetching reviews' approvals: ${e}`); return 0; diff --git a/src/helpers/update-pull-requests.ts b/src/helpers/update-pull-requests.ts index 3e6aa7e4..6a35d7fe 100644 --- a/src/helpers/update-pull-requests.ts +++ b/src/helpers/update-pull-requests.ts @@ -2,7 +2,7 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; import ms from "ms"; import { getAllTimelineEvents } from "../handlers/github-events"; import { generateSummary, ResultInfo } from "../handlers/summary"; -import { Context } from "../types"; +import { Context, ReposWatchSettings } from "../types"; import { getApprovalCount, getMergeTimeoutAndApprovalRequiredCount, @@ -30,7 +30,7 @@ export async function updatePullRequests(context: Context) { const { logger } = context; const results: ResultInfo[] = []; - if (!context.config.repos.monitor.length) { + if (!context.config.repos?.monitor.length) { const owner = context.payload.repository.owner; if (owner) { logger.info(`No organizations or repo have been specified, will default to the organization owner: ${owner.login}.`); @@ -39,7 +39,7 @@ export async function updatePullRequests(context: Context) { } } - const pullRequests = await getOpenPullRequests(context, context.config.repos); + const pullRequests = await getOpenPullRequests(context, context.config.repos as ReposWatchSettings); if (!pullRequests?.length) { return logger.info("Nothing to do."); @@ -74,8 +74,14 @@ export async function updatePullRequests(context: Context) { ); if (isNaN(lastActivityDate.getTime())) { logger.info(`PR ${html_url} does not seem to have any activity, nothing to do.`); - } else if (isPastOffset(lastActivityDate, requirements.mergeTimeout)) { - isMerged = await attemptMerging(context, { gitHubUrl, htmlUrl: html_url, requirements, lastActivityDate, pullRequestDetails }); + } else if (requirements?.mergeTimeout && isPastOffset(lastActivityDate, requirements?.mergeTimeout)) { + isMerged = await attemptMerging(context, { + gitHubUrl, + htmlUrl: html_url, + requirements: requirements as Requirements, + lastActivityDate, + pullRequestDetails, + }); } else { logger.info(`PR ${html_url} has activity up until (${lastActivityDate}), nothing to do.`); } diff --git a/src/helpers/validator.ts b/src/helpers/validator.ts new file mode 100644 index 00000000..1ca759d2 --- /dev/null +++ b/src/helpers/validator.ts @@ -0,0 +1,35 @@ +import { TransformDecodeCheckError, TransformDecodeError, Value, ValueError } from "@sinclair/typebox/value"; +import { Env, envSchema, envValidator, PluginSettings, pluginSettingsSchema, pluginSettingsValidator } from "../types"; + +export function validateAndDecodeSchemas(rawEnv: object, rawSettings: object) { + const errors: ValueError[] = []; + + const env = Value.Default(envSchema, rawEnv) as Env; + if (!envValidator.test(env)) { + for (const error of envValidator.errors(env)) { + errors.push(error); + } + } + + const settings = Value.Default(pluginSettingsSchema, rawSettings) as PluginSettings; + if (!pluginSettingsValidator.test(settings)) { + for (const error of pluginSettingsValidator.errors(settings)) { + errors.push(error); + } + } + + if (errors.length) { + throw { errors }; + } + + try { + const decodedSettings = Value.Decode(pluginSettingsSchema, settings); + const decodedEnv = Value.Decode(envSchema, rawEnv || {}); + return { decodedEnv, decodedSettings }; + } catch (e) { + if (e instanceof TransformDecodeCheckError || e instanceof TransformDecodeError) { + throw { errors: [e.error] }; + } + throw e; + } +} diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index ed79b997..cae4f52a 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -55,13 +55,20 @@ export const reposSchema = T.Object( { default: {} } ); +const allowedReviewerRoles = T.Array(T.String(), { default: ["COLLABORATOR", "MEMBER", "OWNER"] }); + export const pluginSettingsSchema = T.Object({ - approvalsRequired: approvalsRequiredSchema, - mergeTimeout: mergeTimeoutSchema, + approvalsRequired: T.Optional(approvalsRequiredSchema), + mergeTimeout: T.Optional(mergeTimeoutSchema), /** * The list of organizations or repositories to watch for updates. */ - repos: reposSchema, + repos: T.Optional(reposSchema), + allowedReviewerRoles: T.Optional( + T.Transform(allowedReviewerRoles) + .Decode((roles) => roles.map((role) => role.toUpperCase())) + .Encode((roles) => roles.map((role) => role.toUpperCase())) + ), }); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); diff --git a/tests/__mocks__/db.ts b/tests/__mocks__/db.ts index d1a12f75..9e2f9392 100644 --- a/tests/__mocks__/db.ts +++ b/tests/__mocks__/db.ts @@ -24,5 +24,6 @@ export const db = factory({ reviews: { id: primaryKey(Number), state: String, + author_association: String, }, }); diff --git a/tests/__mocks__/routes/search-pull-requests.json b/tests/__mocks__/routes/search-pull-requests.json index 7a67c673..59fdef62 100644 --- a/tests/__mocks__/routes/search-pull-requests.json +++ b/tests/__mocks__/routes/search-pull-requests.json @@ -33,15 +33,11 @@ "type": "User", "site_admin": false }, - "labels": [ - - ], + "labels": [], "state": "open", "locked": false, "assignee": null, - "assignees": [ - - ], + "assignees": [], "milestone": null, "comments": 24, "created_at": "2024-07-02T15:25:13Z", diff --git a/tests/__mocks__/seed.json b/tests/__mocks__/seed.json index 708b5266..a7ed423e 100644 --- a/tests/__mocks__/seed.json +++ b/tests/__mocks__/seed.json @@ -18,11 +18,23 @@ "reviews": [ { "id": 1, - "state": "APPROVED" + "state": "APPROVED", + "author_association": "MEMBER" }, { "id": 2, - "state": "APPROVED" + "state": "APPROVED", + "author_association": "COLLABORATOR" + }, + { + "id": 3, + "state": "APPROVED", + "author_association": "CONTRIBUTOR" + }, + { + "id": 4, + "state": "APPROVED", + "author_association": "NONE" } ] -} +} \ No newline at end of file diff --git a/tests/configuration.test.ts b/tests/configuration.test.ts index e625dc87..189d790b 100644 --- a/tests/configuration.test.ts +++ b/tests/configuration.test.ts @@ -32,6 +32,9 @@ describe("Configuration tests", () => { pull_request: { html_url: "https://github.com/ubiquibot/automated-merging/pull/1", }, + env: { + workflowName: "workflow", + }, }), env: { workflowName: "workflow", @@ -41,8 +44,31 @@ describe("Configuration tests", () => { }, })); const run = (await import("../src/action")).run; - await expect(run()).rejects.toThrow( - "Invalid settings provided:\n/approvalsRequired/collaborator: Expected number to be greater or equal to 1;\n/approvalsRequired/contributor: Expected number to be greater or equal to 1" - ); + await expect(run()).rejects.toMatchObject({ + errors: [ + { + message: "Expected number to be greater or equal to 1", + path: "/approvalsRequired/collaborator", + schema: { + default: 1, + minimum: 1, + type: "number", + }, + type: 39, + value: 0, + }, + { + message: "Expected number to be greater or equal to 1", + path: "/approvalsRequired/contributor", + schema: { + default: 2, + minimum: 1, + type: "number", + }, + type: 39, + value: 0, + }, + ], + }); }); }); diff --git a/tests/main.test.ts b/tests/main.test.ts index 4ea86634..af730979 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -62,6 +62,7 @@ describe("Action tests", () => { eventName: "push", settings: JSON.stringify({ repos: { monitor: [monitor] }, + allowedReviewerRoles: ["COLLABORATOR", "MEMBER", "OWNER"], }), eventPayload: JSON.stringify({ pull_request: { @@ -154,6 +155,59 @@ describe("Action tests", () => { expect(mergePullRequest).toHaveBeenCalled(); }); + it("Should not close a PR if non-approved reviews are present", async () => { + server.use( + http.get( + "https://api.github.com/repos/:org/:repo/pulls/:id/reviews", + () => { + return HttpResponse.json([{ id: 1, state: "COMMENTED", author_association: "CONTRIBUTOR" }, { id: 2, state: "APPROVED", author_association: "NONE" }]); + }, + { once: true } + ) + ); + jest.mock(actionsGithubPackage, () => ({ + context: { + repo: { + owner: { + login: "ubiquibot", + }, + }, + workflow, + payload: { + inputs: { + eventName: "push", + settings: JSON.stringify({ + repos: { monitor: [monitor] }, + }), + eventPayload: JSON.stringify({ + pull_request: { + html_url: htmlUrl, + }, + repository: { + owner: "ubiquibot", + }, + }), + env: { + workflowName: workflow, + }, + }, + }, + }, + })); + const mergePullRequest = jest.fn(); + jest.mock(githubHelpersPath, () => { + const actualModule = jest.requireActual(githubHelpersPath) as object; + return { + __esModule: true, + ...actualModule, + mergePullRequest, + }; + }); + const run = (await import("../src/action")).run; + await expect(run()).resolves.toMatchObject({ status: 200 }); + expect(mergePullRequest).not.toHaveBeenCalled(); + }); + it("Should pick the timeout according to the assignees status", async () => { const contributorMergeTimeout = "7 days"; const collaboratorMergeTimeout = "3.5 days"; @@ -177,6 +231,7 @@ describe("Action tests", () => { collaborator: collaboratorMinimumApprovalsRequired, contributor: contributorMinimumApprovalsRequired, }, + allowedReviewerRoles: ["COLLABORATOR", "MEMBER", "OWNER"], }, octokit: new Octokit(), } as unknown as Context; @@ -228,7 +283,9 @@ describe("Action tests", () => { }, }, workflow: "other workflow", - config: {}, + config: { + allowedReviewerRoles: ["COLLABORATOR", "MEMBER", "OWNER"], + }, octokit: new Octokit(), env: { workflowName: workflow, diff --git a/tsconfig.json b/tsconfig.json index 2481e795..b88b59b3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,8 +12,8 @@ "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ - "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + "experimentalDecorators": true /* Enable experimental support for legacy experimental decorators. */, + "emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */, // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ @@ -80,7 +80,7 @@ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - "strictPropertyInitialization": false, /* Check for class properties that are declared but not set in the constructor. */ + "strictPropertyInitialization": false /* Check for class properties that are declared but not set in the constructor. */, // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ diff --git a/yarn.lock b/yarn.lock index 2b8c8f1d..c60b0379 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1786,85 +1786,85 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz#cdc521c8bca38b55585cf30db787fb2abad3f9fd" - integrity sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg== +"@typescript-eslint/eslint-plugin@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz#b2b02a5447cdc885950eb256b3b8a97b92031bd3" + integrity sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/type-utils" "7.13.1" - "@typescript-eslint/utils" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "8.8.0" + "@typescript-eslint/type-utils" "8.8.0" + "@typescript-eslint/utils" "8.8.0" + "@typescript-eslint/visitor-keys" "8.8.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^1.3.0" -"@typescript-eslint/parser@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.13.1.tgz#fac57811b3e519185f7259bac312291f7b9c4e72" - integrity sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A== +"@typescript-eslint/parser@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.8.0.tgz#ee4397c70230c4eee030456924c0fba480072f5e" + integrity sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg== dependencies: - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "8.8.0" + "@typescript-eslint/types" "8.8.0" + "@typescript-eslint/typescript-estree" "8.8.0" + "@typescript-eslint/visitor-keys" "8.8.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz#c08041206904bf36f0e6997efdb0ca775e0c452e" - integrity sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg== +"@typescript-eslint/scope-manager@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz#30b23a6ae5708bd7882e40675ef2f1b2beac741f" + integrity sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/types" "8.8.0" + "@typescript-eslint/visitor-keys" "8.8.0" -"@typescript-eslint/type-utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz#63bec3f1fb43cf0bc409cbdb88ef96d118ca8632" - integrity sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg== +"@typescript-eslint/type-utils@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz#a0ca1c8a90d94b101176a169d7a0958187408d33" + integrity sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q== dependencies: - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/utils" "7.13.1" + "@typescript-eslint/typescript-estree" "8.8.0" + "@typescript-eslint/utils" "8.8.0" debug "^4.3.4" ts-api-utils "^1.3.0" -"@typescript-eslint/types@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.1.tgz#787db283bd0b58751094c90d5b58bbf5e9fc9bd8" - integrity sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw== +"@typescript-eslint/types@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.8.0.tgz#08ea5df6c01984d456056434641491fbf7a1bf43" + integrity sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw== -"@typescript-eslint/typescript-estree@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz#3412841b130e070db2f675e3d9b8cb1ae49e1c3f" - integrity sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw== +"@typescript-eslint/typescript-estree@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz#072eaab97fdb63513fabfe1cf271812affe779e3" + integrity sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/types" "8.8.0" + "@typescript-eslint/visitor-keys" "8.8.0" debug "^4.3.4" - globby "^11.1.0" + fast-glob "^3.3.2" is-glob "^4.0.3" minimatch "^9.0.4" semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.13.1.tgz#611083379caa0d3a2c09d126c65065a3e4337ba2" - integrity sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ== +"@typescript-eslint/utils@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.8.0.tgz#bd8607e3a68c461b69169c7a5824637dc9e8b3f1" + integrity sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" + "@typescript-eslint/scope-manager" "8.8.0" + "@typescript-eslint/types" "8.8.0" + "@typescript-eslint/typescript-estree" "8.8.0" -"@typescript-eslint/visitor-keys@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz#9c229a795a919db61f2d7f2337ef584ac05fbe96" - integrity sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA== +"@typescript-eslint/visitor-keys@8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz#f93965abd38c82a1a1f5574290a50d02daf1cd2e" + integrity sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g== dependencies: - "@typescript-eslint/types" "7.13.1" + "@typescript-eslint/types" "8.8.0" eslint-visitor-keys "^3.4.3" "@ubiquity-dao/ubiquibot-logger@1.3.1": @@ -2022,11 +2022,6 @@ array-timsort@^1.0.3: resolved "https://registry.yarnpkg.com/array-timsort/-/array-timsort-1.0.3.tgz#3c9e4199e54fb2b9c3fe5976396a21614ef0d926" integrity sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ== -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - arraybuffer.prototype.slice@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" @@ -2728,13 +2723,6 @@ diff3@0.0.3: resolved "https://registry.yarnpkg.com/diff3/-/diff3-0.0.3.tgz#d4e5c3a4cdf4e5fe1211ab42e693fcb4321580fc" integrity sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g== -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -3124,7 +3112,7 @@ fast-equals@^5.0.1: resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== -fast-glob@^3.2.9, fast-glob@^3.3.2: +fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -3390,18 +3378,6 @@ globalthis@^1.0.3: define-properties "^1.2.1" gopd "^1.0.1" -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -4560,7 +4536,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -4932,11 +4908,6 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -5756,19 +5727,19 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript-eslint@7.13.1: - version "7.13.1" - resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-7.13.1.tgz#8bbcc4b59b6bb0c457505ee17a356b1868c3fcd5" - integrity sha512-pvLEuRs8iS9s3Cnp/Wt//hpK8nKc8hVa3cLljHqzaJJQYP8oys8GUyIFqtlev+2lT/fqMPcyQko+HJ6iYK3nFA== +typescript-eslint@8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.8.0.tgz#93762a4cbd9d586dec0d9ab18e07dea13f497a27" + integrity sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw== dependencies: - "@typescript-eslint/eslint-plugin" "7.13.1" - "@typescript-eslint/parser" "7.13.1" - "@typescript-eslint/utils" "7.13.1" + "@typescript-eslint/eslint-plugin" "8.8.0" + "@typescript-eslint/parser" "8.8.0" + "@typescript-eslint/utils" "8.8.0" -typescript@5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== +typescript@5.6.2: + version "5.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" + integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== unbox-primitive@^1.0.2: version "1.0.2"