From 4c296573b0d7091eb3bcb1c02b5ebf909d73d59d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 7 Sep 2024 03:31:53 +0100 Subject: [PATCH 1/6] fix: add rolesWithReviewAuth to config --- README.md | 1 + src/types/plugin-input.ts | 5 +++++ src/utils/issue.ts | 3 ++- tests/main.test.ts | 21 +++++++++++---------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a39b428..a068cb0 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ To configure your Ubiquibot to run this plugin, add the following to the `.ubiqu maxConcurrentTasks: 3 startRequiresWallet: true # default is true emptyWalletText: "Please set your wallet address with the /wallet command first and try again." + rolesWithReviewAuthority: ["MEMBER", "OWNER"] ``` # Testing diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 01a1c95..0b2d91d 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -11,6 +11,8 @@ export interface PluginInputs value.map((role) => role.toUpperCase())) + .Encode((value) => value.map((role) => role.toUpperCase())), }, { default: {}, diff --git a/src/utils/issue.ts b/src/utils/issue.ts index 4133c5d..9ceadc2 100644 --- a/src/utils/issue.ts +++ b/src/utils/issue.ts @@ -174,13 +174,14 @@ export async function getAllPullRequests(context: Context, state: "open" | "clos } export async function getAllPullRequestReviews(context: Context, pullNumber: number, owner: string, repo: string) { + const { config: { rolesWithReviewAuthority } } = context; try { return (await context.octokit.paginate(context.octokit.pulls.listReviews, { owner, repo, pull_number: pullNumber, per_page: 100, - })) as Review[]; + })).filter((review) => rolesWithReviewAuthority.includes(review.author_association)) as Review[]; } catch (err: unknown) { throw new Error(context.logger.error("Fetching all pull request reviews failed!", { error: err as Error }).logMessage.raw); } diff --git a/tests/main.test.ts b/tests/main.test.ts index 8bd67ee..73935e9 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -78,7 +78,7 @@ describe("User start/stop", () => { }); test("Stopping an issue should close the author's linked PR", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "/stop"); @@ -567,6 +567,7 @@ function createContext( maxConcurrentTasks: 3, startRequiresWallet, emptyWalletText: "Please set your wallet address with the /wallet command first and try again.", + rolesWithReviewAuthority: ["COLLABORATOR", "OWNER", "MEMBER"], }, octokit: new octokit.Octokit(), eventName: "issue_comment.created" as SupportedEventsU, @@ -585,17 +586,17 @@ function getSupabase(withData = true) { single: jest.fn().mockResolvedValue({ data: withData ? { - id: 1, - wallets: { - address: "0x123", - }, - } + id: 1, + wallets: { + address: "0x123", + }, + } : { - id: 1, - wallets: { - address: undefined, - }, + id: 1, + wallets: { + address: undefined, }, + }, }), }), }), From d9054ea2db261d9b9438a6c334f663cc5d408ffe Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:12:43 +0100 Subject: [PATCH 2/6] chore: fix setting default and tests --- src/types/plugin-input.ts | 2 +- tests/__mocks__/valid-configuration.json | 15 ++++++++++++--- tests/configuration.test.ts | 9 ++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 43be362..6e1fcf4 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -11,7 +11,7 @@ export interface PluginInputs { it("Should decode the configuration", () => { - const settings = Value.Default(startStopSchema, { maxConcurrentTasks: { admin: 20, member: 10, contributor: 2 } }) as StartStopSettings; + const settings = Value.Default(startStopSchema, { + reviewDelayTolerance: "1 Day", + taskStaleTimeoutDuration: "30 Days", + startRequiresWallet: true, + emptyWalletText: "Please set your wallet address with the /wallet command first and try again.", + maxConcurrentTasks: { admin: 20, member: 10, contributor: 2 }, + rolesWithReviewAuthority: ["OWNER", "ADMIN", "MEMBER"], + }) as StartStopSettings; expect(settings).toEqual(cfg); }); it("Should default the admin to infinity if missing from config when decoded", () => { From 4543ca61a9f93378d23eb27cb8d477a08a3d6292 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:22:39 +0100 Subject: [PATCH 3/6] chore: normalize maxTask roles, add test --- manifest.json | 2 +- src/types/plugin-input.ts | 18 ++++++++++++++---- src/utils/issue.ts | 18 +++++++++++------- tests/__mocks__/valid-configuration.json | 8 ++------ tests/configuration.test.ts | 8 ++++++++ tests/main.test.ts | 20 ++++++++++---------- 6 files changed, 46 insertions(+), 28 deletions(-) diff --git a/manifest.json b/manifest.json index 41056c6..09b7cc3 100644 --- a/manifest.json +++ b/manifest.json @@ -12,4 +12,4 @@ "description": "Unassign yourself from the issue." } } -} \ No newline at end of file +} diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 6e1fcf4..22b120d 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -15,12 +15,22 @@ const rolesWithReviewAuthority = T.Array(T.String(), { default: ["COLLABORATOR", function maxConcurrentTasks() { return T.Transform(T.Record(T.String(), T.Integer(), { default: { member: 10, contributor: 2 } })) - .Decode((value) => { + .Decode((obj) => { + // normalize the role keys to lowercase + obj = Object.keys(obj).reduce( + (acc, key) => { + acc[key.toLowerCase()] = obj[key]; + return acc; + }, + {} as Record + ); + // If admin is omitted, defaults to infinity - if (!Object.keys(value).includes("admin")) { - value["admin"] = Infinity; + if (!obj["admin"]) { + obj["admin"] = Infinity; } - return value; + + return obj; }) .Encode((value) => value); } diff --git a/src/utils/issue.ts b/src/utils/issue.ts index 1bb5a0f..058e90e 100644 --- a/src/utils/issue.ts +++ b/src/utils/issue.ts @@ -187,14 +187,18 @@ export async function getAllPullRequests(context: Context, state: "open" | "clos } export async function getAllPullRequestReviews(context: Context, pullNumber: number, owner: string, repo: string) { - const { config: { rolesWithReviewAuthority } } = context; + const { + config: { rolesWithReviewAuthority }, + } = context; try { - return (await context.octokit.paginate(context.octokit.pulls.listReviews, { - owner, - repo, - pull_number: pullNumber, - per_page: 100, - })).filter((review) => rolesWithReviewAuthority.includes(review.author_association)) as Review[]; + return ( + await context.octokit.paginate(context.octokit.pulls.listReviews, { + owner, + repo, + pull_number: pullNumber, + per_page: 100, + }) + ).filter((review) => rolesWithReviewAuthority.includes(review.author_association)) as Review[]; } catch (err: unknown) { throw new Error(context.logger.error("Fetching all pull request reviews failed!", { error: err as Error }).logMessage.raw); } diff --git a/tests/__mocks__/valid-configuration.json b/tests/__mocks__/valid-configuration.json index c9c0203..367ba0b 100644 --- a/tests/__mocks__/valid-configuration.json +++ b/tests/__mocks__/valid-configuration.json @@ -8,9 +8,5 @@ "contributor": 2 }, "emptyWalletText": "Please set your wallet address with the /wallet command first and try again.", - "rolesWithReviewAuthority": [ - "OWNER", - "ADMIN", - "MEMBER" - ] -} \ No newline at end of file + "rolesWithReviewAuthority": ["OWNER", "ADMIN", "MEMBER"] +} diff --git a/tests/configuration.test.ts b/tests/configuration.test.ts index f362b24..3bfd853 100644 --- a/tests/configuration.test.ts +++ b/tests/configuration.test.ts @@ -19,4 +19,12 @@ describe("Configuration tests", () => { const decodedSettings = Value.Decode(startStopSchema, settings); expect(decodedSettings.maxConcurrentTasks["admin"]).toEqual(Infinity); }); + + it("Should normalize maxConcurrentTasks role keys to lowercase when decoded", () => { + const settings = Value.Default(startStopSchema, { + maxConcurrentTasks: { ADMIN: 20, memBER: 10, CONTRIBUTOR: 2 }, + }) as StartStopSettings; + const decodedSettings = Value.Decode(startStopSchema, settings); + expect(decodedSettings.maxConcurrentTasks).toEqual({ admin: 20, member: 10, contributor: 2 }); + }); }); diff --git a/tests/main.test.ts b/tests/main.test.ts index a7e56d8..5021468 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -93,7 +93,7 @@ describe("User start/stop", () => { }); test("Stopping an issue should close the author's linked PR", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "/stop") as Context<"issue_comment.created">; @@ -641,17 +641,17 @@ function getSupabase(withData = true) { single: jest.fn().mockResolvedValue({ data: withData ? { - id: 1, - wallets: { - address: "0x123", - }, - } + id: 1, + wallets: { + address: "0x123", + }, + } : { - id: 1, - wallets: { - address: undefined, + id: 1, + wallets: { + address: undefined, + }, }, - }, }), }), }), From 5a4c243288ecd03eb67e08940b8ce8fa730aa498 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:24:50 +0100 Subject: [PATCH 4/6] chore: change test role --- tests/main.test.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/main.test.ts b/tests/main.test.ts index 5021468..2a09d76 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -93,7 +93,7 @@ describe("User start/stop", () => { }); test("Stopping an issue should close the author's linked PR", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "/stop") as Context<"issue_comment.created">; @@ -113,7 +113,7 @@ describe("User start/stop", () => { }); test("Author's manual unassign should close linked issue", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "") as Context<"issues.unassigned">; @@ -622,7 +622,7 @@ function createContext( maxConcurrentTasks: maxConcurrentDefaults, startRequiresWallet, emptyWalletText: "Please set your wallet address with the /wallet command first and try again.", - rolesWithReviewAuthority: ["COLLABORATOR", "OWNER", "MEMBER"], + rolesWithReviewAuthority: ["ADMIN", "OWNER", "MEMBER"], }, octokit: new octokit.Octokit(), eventName: "issue_comment.created" as SupportedEventsU, @@ -641,17 +641,17 @@ function getSupabase(withData = true) { single: jest.fn().mockResolvedValue({ data: withData ? { - id: 1, - wallets: { - address: "0x123", - }, - } + id: 1, + wallets: { + address: "0x123", + }, + } : { - id: 1, - wallets: { - address: undefined, - }, + id: 1, + wallets: { + address: undefined, }, + }, }), }), }), From a4f9ecb40d40378c968753ab748db9ffa6c59ad1 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:01:04 +0100 Subject: [PATCH 5/6] Update tests/main.test.ts Co-authored-by: Mentlegen <9807008+gentlementlegen@users.noreply.github.com> --- tests/main.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/main.test.ts b/tests/main.test.ts index 2a09d76..f558bd5 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -93,7 +93,7 @@ describe("User start/stop", () => { }); test("Stopping an issue should close the author's linked PR", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "/stop") as Context<"issue_comment.created">; From 44454b7b630c727f3d17a9641b68fba88f80975b Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:50:57 +0100 Subject: [PATCH 6/6] chore: format --- src/types/plugin-input.ts | 2 +- tests/main.test.ts | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 22b120d..128bde6 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -11,7 +11,7 @@ export interface PluginInputs { }); test("Author's manual unassign should close linked issue", async () => { - const infoSpy = jest.spyOn(console, "info").mockImplementation(() => { }); + const infoSpy = jest.spyOn(console, "info").mockImplementation(() => {}); const issue = db.issue.findFirst({ where: { id: { equals: 2 } } }) as unknown as Issue; const sender = db.users.findFirst({ where: { id: { equals: 2 } } }) as unknown as PayloadSender; const context = createContext(issue, sender, "") as Context<"issues.unassigned">; @@ -641,17 +641,17 @@ function getSupabase(withData = true) { single: jest.fn().mockResolvedValue({ data: withData ? { - id: 1, - wallets: { - address: "0x123", - }, - } + id: 1, + wallets: { + address: "0x123", + }, + } : { - id: 1, - wallets: { - address: undefined, + id: 1, + wallets: { + address: undefined, + }, }, - }, }), }), }),