diff --git a/.github/scripts/check_team_membership.js b/.github/scripts/check_team_membership.js index ca8e75f1d13..46705d648ef 100644 --- a/.github/scripts/check_team_membership.js +++ b/.github/scripts/check_team_membership.js @@ -1,25 +1,38 @@ // Copyright (c) Microsoft. All rights reserved. /** - * Resolve the issue author and check their team membership. + * Resolve the issue or pull request author and check their team membership. * * @param {object} opts * @param {object} opts.github - Octokit REST client from actions/github-script * @param {object} opts.context - GitHub Actions context * @param {object} opts.core - GitHub Actions core toolkit * @param {string} opts.teamSlug - Team slug to check membership against - * @param {string|number} opts.issueNumber - Issue number to resolve author for + * @param {string|number} opts.issueNumber - Issue or pull request number to resolve author for * @returns {Promise<{author: string|null, isTeamMember: boolean}>} */ async function checkTeamMembership({ github, context, core, teamSlug, issueNumber }) { - let author = context.payload.issue?.user?.login; + let author = + context.payload.issue?.user?.login ?? + context.payload.pull_request?.user?.login; + if (!author) { - const { data: issue } = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: Number(issueNumber), - }); - author = issue.user?.login; + const number = Number(issueNumber); + if (context.payload.pull_request) { + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: number, + }); + author = pr.user?.login; + } else { + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: number, + }); + author = issue.user?.login; + } } if (!author) { diff --git a/.github/tests/test_check_team_membership.js b/.github/tests/test_check_team_membership.js index 6fbec9ff609..2e35135b9e7 100644 --- a/.github/tests/test_check_team_membership.js +++ b/.github/tests/test_check_team_membership.js @@ -16,7 +16,12 @@ const checkTeamMembership = require('../scripts/check_team_membership.js'); // Helpers // --------------------------------------------------------------------------- -function createMocks({ payloadIssue = undefined, apiUser = 'api-user', teamState = 'active' } = {}) { +function createMocks({ + payloadIssue = undefined, + payloadPullRequest = undefined, + apiUser = 'api-user', + teamState = 'active', +} = {}) { const core = { _infoMessages: [], _failedMessages: [], @@ -24,8 +29,16 @@ function createMocks({ payloadIssue = undefined, apiUser = 'api-user', teamState setFailed(msg) { this._failedMessages.push(msg); }, }; + const payload = {}; + if (payloadIssue !== undefined) { + payload.issue = payloadIssue; + } + if (payloadPullRequest !== undefined) { + payload.pull_request = payloadPullRequest; + } + const context = { - payload: { issue: payloadIssue }, + payload, repo: { owner: 'test-org', repo: 'test-repo' }, }; @@ -36,6 +49,11 @@ function createMocks({ payloadIssue = undefined, apiUser = 'api-user', teamState data: { user: apiUser ? { login: apiUser } : null }, }), }, + pulls: { + get: async () => ({ + data: { user: apiUser ? { login: apiUser } : null }, + }), + }, teams: { getByName: async () => ({}), getMembershipForUserInOrg: async () => ({ @@ -64,6 +82,37 @@ describe('author resolution', () => { assert.equal(result.author, 'payload-user'); }); + it('resolves author from pull_request event payload', async () => { + const { github, context, core } = createMocks({ + payloadPullRequest: { user: { login: 'pr-author' } }, + }); + let issuesGetCalled = false; + github.rest.issues.get = async () => { + issuesGetCalled = true; + return { data: { user: { login: 'api-user' } } }; + }; + + const result = await checkTeamMembership({ github, context, core, ...BASE_OPTS }); + assert.equal(result.author, 'pr-author'); + assert.equal(issuesGetCalled, false); + }); + + it('resolves author via pulls API when pull_request payload user is null', async () => { + const { github, context, core } = createMocks({ + payloadPullRequest: { user: null }, + apiUser: 'fetched-pr-author', + }); + let pullsGetCalled = false; + github.rest.pulls.get = async () => { + pullsGetCalled = true; + return { data: { user: { login: 'fetched-pr-author' } } }; + }; + + const result = await checkTeamMembership({ github, context, core, ...BASE_OPTS }); + assert.equal(result.author, 'fetched-pr-author'); + assert.equal(pullsGetCalled, true); + }); + it('resolves author via API when payload issue is absent', async () => { const { github, context, core } = createMocks({ apiUser: 'api-user' }); const result = await checkTeamMembership({ github, context, core, ...BASE_OPTS });