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"