diff --git a/src/github/validation/actor.ts b/src/github/validation/actor.ts index 4fe2bcb..2599254 100644 --- a/src/github/validation/actor.ts +++ b/src/github/validation/actor.ts @@ -25,12 +25,6 @@ export async function checkHumanActor( if (actorType !== "User") { const allowedBots = githubContext.inputs.allowedBots; - // Parse allowed bots list - const allowedBotsList = allowedBots - .split(",") - .map((bot) => bot.trim().toLowerCase()) - .filter((bot) => bot.length > 0); - // Check if all bots are allowed if (allowedBots.trim() === "*") { console.log( @@ -39,17 +33,30 @@ export async function checkHumanActor( return; } + // Parse allowed bots list + const allowedBotsList = allowedBots + .split(",") + .map((bot) => + bot + .trim() + .toLowerCase() + .replace(/\[bot\]$/, ""), + ) + .filter((bot) => bot.length > 0); + + const botName = githubContext.actor.toLowerCase().replace(/\[bot\]$/, ""); + // Check if specific bot is allowed - if (allowedBotsList.includes(githubContext.actor.toLowerCase())) { + if (allowedBotsList.includes(botName)) { console.log( - `Bot ${githubContext.actor} is in allowed list, skipping human actor check`, + `Bot ${botName} is in allowed list, skipping human actor check`, ); return; } // Bot not allowed throw new Error( - `Workflow initiated by non-human actor: ${githubContext.actor} (type: ${actorType}). Add bot to allowed_bots list or use '*' to allow all bots.`, + `Workflow initiated by non-human actor: ${botName} (type: ${actorType}). Add bot to allowed_bots list or use '*' to allow all bots.`, ); } diff --git a/test/actor.test.ts b/test/actor.test.ts index 7d51e29..4c9d206 100644 --- a/test/actor.test.ts +++ b/test/actor.test.ts @@ -35,7 +35,7 @@ describe("checkHumanActor", () => { context.inputs.allowedBots = ""; await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow( - "Workflow initiated by non-human actor: test-bot[bot] (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.", + "Workflow initiated by non-human actor: test-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.", ); }); @@ -61,6 +61,17 @@ describe("checkHumanActor", () => { ).resolves.toBeUndefined(); }); + test("should pass for specific bot when in allowed list (without [bot])", async () => { + const mockOctokit = createMockOctokit("Bot"); + const context = createMockContext(); + context.actor = "dependabot[bot]"; + context.inputs.allowedBots = "dependabot,renovate"; + + await expect( + checkHumanActor(mockOctokit, context), + ).resolves.toBeUndefined(); + }); + test("should throw error for bot not in allowed list", async () => { const mockOctokit = createMockOctokit("Bot"); const context = createMockContext(); @@ -68,7 +79,18 @@ describe("checkHumanActor", () => { context.inputs.allowedBots = "dependabot[bot],renovate[bot]"; await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow( - "Workflow initiated by non-human actor: other-bot[bot] (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.", + "Workflow initiated by non-human actor: other-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.", + ); + }); + + test("should throw error for bot not in allowed list (without [bot])", async () => { + const mockOctokit = createMockOctokit("Bot"); + const context = createMockContext(); + context.actor = "other-bot[bot]"; + context.inputs.allowedBots = "dependabot,renovate"; + + await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow( + "Workflow initiated by non-human actor: other-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.", ); }); });