diff --git a/README.md b/README.md index 4fff394..f6c9ed7 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ All inputs are **optional**. If not set, sensible defaults will be used. | `labels` | A comma or newline-separated list of labels. | | | `assignees` | A comma or newline-separated list of assignees (GitHub usernames). | | | `reviewers` | A comma or newline-separated list of reviewers (GitHub usernames) to request a review from. | | -| `team-reviewers` | A comma or newline-separated list of GitHub teams to request a review from. Note that a `repo` scoped [PAT](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) may be required. See [this issue](https://github.com/peter-evans/create-pull-request/issues/155). If using a GitHub App, refer to [Authenticating with GitHub App generated tokens](docs/concepts-guidelines.md#authenticating-with-github-app-generated-tokens) for the proper permissions. | | +| `team-reviewers` | A comma or newline-separated list of GitHub teams to request a review from. Note that a `repo` scoped [PAT](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token), or equivalent [GitHub App permissions](docs/concepts-guidelines.md#authenticating-with-github-app-generated-tokens), are required. | | | `milestone` | The number of the milestone to associate this pull request with. | | | `draft` | Create a [draft pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). It is not possible to change draft status after creation except through the web interface. | `false` | @@ -252,8 +252,8 @@ jobs: assignees: peter-evans reviewers: peter-evans team-reviewers: | - owners - maintainers + developers + qa-team milestone: 1 draft: false ``` diff --git a/__test__/utils.unit.test.ts b/__test__/utils.unit.test.ts index 19b3660..257575d 100644 --- a/__test__/utils.unit.test.ts +++ b/__test__/utils.unit.test.ts @@ -25,6 +25,18 @@ describe('utils tests', () => { expect(array2.length).toEqual(0) }) + test('stripOrgPrefixFromTeams strips org prefixes correctly', async () => { + const array = utils.stripOrgPrefixFromTeams([ + 'org/team1', + 'org/team2', + 'team3' + ]) + expect(array.length).toEqual(3) + expect(array[0]).toEqual('team1') + expect(array[1]).toEqual('team2') + expect(array[2]).toEqual('team3') + }) + test('getRepoPath successfully returns the path to the repository', async () => { expect(utils.getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE']) expect(utils.getRepoPath('foo')).toEqual( diff --git a/dist/index.js b/dist/index.js index 6caa857..b3fdacb 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1034,7 +1034,7 @@ exports.GitHubHelper = void 0; const core = __importStar(__nccwpck_require__(2186)); const octokit_client_1 = __nccwpck_require__(5040); const utils = __importStar(__nccwpck_require__(918)); -const ERROR_PR_REVIEW_FROM_AUTHOR = 'Review cannot be requested from pull request author'; +const ERROR_PR_REVIEW_TOKEN_SCOPE = 'Validation Failed: "Could not resolve to a node with the global id of'; class GitHubHelper { constructor(token) { const options = {}; @@ -1123,20 +1123,19 @@ class GitHubHelper { core.info(`Requesting reviewers '${inputs.reviewers}'`); } if (inputs.teamReviewers.length > 0) { - requestReviewersParams['team_reviewers'] = inputs.teamReviewers; - core.info(`Requesting team reviewers '${inputs.teamReviewers}'`); + const teams = utils.stripOrgPrefixFromTeams(inputs.teamReviewers); + requestReviewersParams['team_reviewers'] = teams; + core.info(`Requesting team reviewers '${teams}'`); } if (Object.keys(requestReviewersParams).length > 0) { try { yield this.octokit.rest.pulls.requestReviewers(Object.assign(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { pull_number: pull.number }), requestReviewersParams)); } catch (e) { - if (utils.getErrorMessage(e).includes(ERROR_PR_REVIEW_FROM_AUTHOR)) { - core.warning(ERROR_PR_REVIEW_FROM_AUTHOR); - } - else { - throw e; + if (utils.getErrorMessage(e).includes(ERROR_PR_REVIEW_TOKEN_SCOPE)) { + core.error(`Unable to request reviewers. If requesting team reviewers a 'repo' scoped PAT is required.`); } + throw e; } } return pull; @@ -1283,7 +1282,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getErrorMessage = exports.fileExistsSync = exports.parseDisplayNameEmail = exports.randomString = exports.secondsSinceEpoch = exports.getRemoteUrl = exports.getRemoteDetail = exports.getRepoPath = exports.getStringAsArray = exports.getInputAsArray = void 0; +exports.getErrorMessage = exports.fileExistsSync = exports.parseDisplayNameEmail = exports.randomString = exports.secondsSinceEpoch = exports.getRemoteUrl = exports.getRemoteDetail = exports.getRepoPath = exports.stripOrgPrefixFromTeams = exports.getStringAsArray = exports.getInputAsArray = void 0; const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); const path = __importStar(__nccwpck_require__(1017)); @@ -1298,6 +1297,16 @@ function getStringAsArray(str) { .filter(x => x !== ''); } exports.getStringAsArray = getStringAsArray; +function stripOrgPrefixFromTeams(teams) { + return teams.map(team => { + const slashIndex = team.lastIndexOf('/'); + if (slashIndex > 0) { + return team.substring(slashIndex + 1); + } + return team; + }); +} +exports.stripOrgPrefixFromTeams = stripOrgPrefixFromTeams; function getRepoPath(relativePath) { let githubWorkspacePath = process.env['GITHUB_WORKSPACE']; if (!githubWorkspacePath) { diff --git a/src/github-helper.ts b/src/github-helper.ts index 7e0cfee..663d392 100644 --- a/src/github-helper.ts +++ b/src/github-helper.ts @@ -3,8 +3,8 @@ import {Inputs} from './create-pull-request' import {Octokit, OctokitOptions} from './octokit-client' import * as utils from './utils' -const ERROR_PR_REVIEW_FROM_AUTHOR = - 'Review cannot be requested from pull request author' +const ERROR_PR_REVIEW_TOKEN_SCOPE = + 'Validation Failed: "Could not resolve to a node with the global id of' interface Repository { owner: string @@ -159,8 +159,9 @@ export class GitHubHelper { core.info(`Requesting reviewers '${inputs.reviewers}'`) } if (inputs.teamReviewers.length > 0) { - requestReviewersParams['team_reviewers'] = inputs.teamReviewers - core.info(`Requesting team reviewers '${inputs.teamReviewers}'`) + const teams = utils.stripOrgPrefixFromTeams(inputs.teamReviewers) + requestReviewersParams['team_reviewers'] = teams + core.info(`Requesting team reviewers '${teams}'`) } if (Object.keys(requestReviewersParams).length > 0) { try { @@ -170,11 +171,12 @@ export class GitHubHelper { ...requestReviewersParams }) } catch (e) { - if (utils.getErrorMessage(e).includes(ERROR_PR_REVIEW_FROM_AUTHOR)) { - core.warning(ERROR_PR_REVIEW_FROM_AUTHOR) - } else { - throw e + if (utils.getErrorMessage(e).includes(ERROR_PR_REVIEW_TOKEN_SCOPE)) { + core.error( + `Unable to request reviewers. If requesting team reviewers a 'repo' scoped PAT is required.` + ) } + throw e } } diff --git a/src/utils.ts b/src/utils.ts index b98f8fa..f5bed07 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -16,6 +16,16 @@ export function getStringAsArray(str: string): string[] { .filter(x => x !== '') } +export function stripOrgPrefixFromTeams(teams: string[]): string[] { + return teams.map(team => { + const slashIndex = team.lastIndexOf('/') + if (slashIndex > 0) { + return team.substring(slashIndex + 1) + } + return team + }) +} + export function getRepoPath(relativePath?: string): string { let githubWorkspacePath = process.env['GITHUB_WORKSPACE'] if (!githubWorkspacePath) {