From f04c62d1f5dbc53c4bd013e288199958ca6fe1a9 Mon Sep 17 00:00:00 2001 From: Calum Young <32770960+CalumY@users.noreply.github.com> Date: Mon, 15 Aug 2022 23:39:15 +0100 Subject: [PATCH] Handle workflow run (#65) * Get issue number and author from workflow run * Update remove author for PR PR can be assigned to the author but cannot be assigned as a reviewer * Separate assignee and reviewer assignment * Only assign reviewer if assignees available * Remove author from pr reviewer assignment * Fix typo in tests * Add pr assignment tests with author * Add tests for workflow_run context --- src/__tests__/action.test.js | 75 +++++++++++++++++++++++++++++++++++- src/action.js | 30 +++++++++++---- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/__tests__/action.test.js b/src/__tests__/action.test.js index d0a2859da..08e530233 100644 --- a/src/__tests__/action.test.js +++ b/src/__tests__/action.test.js @@ -22,6 +22,17 @@ const PR_CONTEXT_PAYLOAD = { user: { login: 'author' } } }; +const WORKFLOW_RUN_CONTEXT_PAYLOAD = { + repository: { full_name: 'mockOrg/mockRepo' }, + workflow_run: { + pull_requests: [ + { + number: 667 + } + ], + actor: { login: 'author' } + } +}; const PROJECT_CONTEXT_PAYLOAD = { repository: { full_name: 'mockOrgCard/mockRepoCard' }, @@ -198,7 +209,7 @@ describe('action', () => { }); }); - it('works with asignees only, no random pick', async () => { + it('works with assignees only, no random pick', async () => { await runAction(octokitMock, CONTEXT_PAYLOAD, { assigneesString: 'user1,user2' }); @@ -336,5 +347,67 @@ describe('action', () => { assignees: ['userA', 'userB'] }); }); + + it('assigns author to pull request assignee', async () => { + await runAction(octokitMock, PR_CONTEXT_PAYLOAD, { + assigneesString: 'author,user1,user2', + allowSelfAssign: true + }); + + expect(listTeamMembersMock).not.toHaveBeenCalled(); + expect(addIssueAssigneesMock).toHaveBeenCalledTimes(1); + expect(addIssueAssigneesMock).toHaveBeenCalledWith({ + assignees: ['author', 'user1', 'user2'], + issue_number: 667, + owner: 'mockOrg', + repo: 'mockRepo' + }); + }); + + it('does not assigns author to pull request reviewer', async () => { + await runAction(octokitMockForPRs, PR_CONTEXT_PAYLOAD, { + assigneesString: 'author,user1,user2', + allowSelfAssign: true + }); + + expect(addPRReviewersMock).toHaveBeenCalledTimes(1); + expect(addPRReviewersMock).toHaveBeenCalledWith({ + reviewers: ['user1', 'user2'], + pull_number: 667, + owner: 'mockOrg', + repo: 'mockRepo' + }); + }); + + it('assigns author to pull request assignee from workflow_run', async () => { + await runAction(octokitMock, WORKFLOW_RUN_CONTEXT_PAYLOAD, { + assigneesString: 'author,user1,user2', + allowSelfAssign: true + }); + + expect(listTeamMembersMock).not.toHaveBeenCalled(); + expect(addIssueAssigneesMock).toHaveBeenCalledTimes(1); + expect(addIssueAssigneesMock).toHaveBeenCalledWith({ + assignees: ['author', 'user1', 'user2'], + issue_number: 667, + owner: 'mockOrg', + repo: 'mockRepo' + }); + }); + + it('does not assigns author to pull request reviewer from workflow_run', async () => { + await runAction(octokitMockForPRs, WORKFLOW_RUN_CONTEXT_PAYLOAD, { + assigneesString: 'author,user1,user2', + allowSelfAssign: true + }); + + expect(addPRReviewersMock).toHaveBeenCalledTimes(1); + expect(addPRReviewersMock).toHaveBeenCalledWith({ + reviewers: ['user1', 'user2'], + pull_number: 667, + owner: 'mockOrg', + repo: 'mockRepo' + }); + }); }); }); diff --git a/src/action.js b/src/action.js index 53feb9033..8ed82d756 100644 --- a/src/action.js +++ b/src/action.js @@ -127,10 +127,15 @@ const runAction = async (octokit, context, parameters) => { } = parameters; // Get issue info from context - let issueNumber = context.issue?.number || context.pull_request?.number; + let issueNumber = + context.issue?.number || + context.pull_request?.number || + context.workflow_run?.pull_requests[0].number; let isIssue = context.issue ? true : false; const author = - context.issue?.user.login || context.pull_request?.user.login; + context.issue?.user.login || + context.pull_request?.user.login || + context.workflow_run?.actor.login; // If the issue is not found directly, maybe it came for a card movement with a linked issue if ( @@ -204,8 +209,8 @@ const runAction = async (octokit, context, parameters) => { // Remove duplicates from assignees assignees = [...new Set(assignees)]; - // Remove author if allowSelfAssign is disabled OR if it's a PR (where it's not allowed). - if (!allowSelfAssign || !isIssue) { + // Remove author if allowSelfAssign is disabled + if (!allowSelfAssign) { const foundIndex = assignees.indexOf(author); if (foundIndex !== -1) { assignees.splice(foundIndex, 1); @@ -231,8 +236,19 @@ const runAction = async (octokit, context, parameters) => { issue_number: issueNumber, assignees }); - if (!isIssue) { - // Assign PR reviewers + } else if (!allowNoAssignees) { + throw new Error('No candidates found for assignment'); + } + + // Assign PR reviewers + if (!isIssue) { + // Remove author from reviewers + const foundIndex = assignees.indexOf(author); + if (foundIndex !== -1) { + assignees.splice(foundIndex, 1); + } + + if (assignees.length > 0) { console.log( `Assigning PR ${issueNumber} to users ${JSON.stringify( assignees @@ -246,8 +262,6 @@ const runAction = async (octokit, context, parameters) => { reviewers: assignees }); } - } else if (!allowNoAssignees) { - throw new Error('No candidates found for assignement'); } };