Compare commits

..

9 Commits

Author SHA1 Message Date
Peter Evans
740d9850a7 add maintainer-can-modify input 2024-08-16 15:44:43 +01:00
Peter Evans
e7f5ea9fd9 use separate client for branch and pull operations 2024-08-16 12:26:38 +00:00
Peter Evans
66ddf90dac output retryafter for secondary rate limit 2024-08-15 15:24:58 +00:00
Peter Evans
fd3e742ffd default the operation output to none 2024-08-15 13:37:41 +00:00
Peter Evans
eea4f44785 fix head sha output 2024-08-15 10:16:22 +00:00
Peter Evans
5a9be5875b log outputs 2024-08-14 21:55:31 +00:00
Peter Evans
3d665e5aea output head sha and verified status 2024-08-14 21:50:59 +00:00
Peter Evans
bb1f2b1327 set default back to false 2024-08-14 21:06:45 +00:00
Peter Evans
1da4bbe67c add throttling 2024-08-14 21:10:21 +01:00
7 changed files with 129 additions and 64 deletions

View File

@@ -75,6 +75,7 @@ All inputs are **optional**. If not set, sensible defaults will be used.
| `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. | | | `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. | | | `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` | | `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` |
| `maintainer-can-modify` | Indicates whether [maintainers can modify](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) the pull request. | `true` |
#### commit-message #### commit-message
@@ -116,9 +117,10 @@ The following outputs can be used by subsequent workflow steps.
- `pull-request-number` - The pull request number. - `pull-request-number` - The pull request number.
- `pull-request-url` - The URL of the pull request. - `pull-request-url` - The URL of the pull request.
- `pull-request-operation` - The pull request operation performed by the action, `created`, `updated` or `closed`. - `pull-request-operation` - The pull request operation performed by the action, `created`, `updated`, `closed` or `none`.
- `pull-request-head-sha` - The commit SHA of the pull request branch. - `pull-request-head-sha` - The commit SHA of the pull request branch.
- `pull-request-branch` - The branch name of the pull request. - `pull-request-branch` - The branch name of the pull request.
- `pull-request-commits-verified` - Whether GitHub considers the signature of the branch's commits to be verified; `true` or `false`.
Step outputs can be accessed as in the following example. Step outputs can be accessed as in the following example.
Note that in order to read the step outputs the action step must have an id. Note that in order to read the step outputs the action step must have an id.

View File

@@ -53,7 +53,7 @@ inputs:
The pull request will be created to merge the fork's branch into the parent's base. The pull request will be created to merge the fork's branch into the parent's base.
sign-commits: sign-commits:
description: 'Sign commits as `github-actions[bot]` when using `GITHUB_TOKEN`, or your own bot when using GitHub App tokens.' description: 'Sign commits as `github-actions[bot]` when using `GITHUB_TOKEN`, or your own bot when using GitHub App tokens.'
default: true default: false
title: title:
description: 'The title of the pull request.' description: 'The title of the pull request.'
default: 'Changes by create-pull-request action' default: 'Changes by create-pull-request action'
@@ -77,6 +77,9 @@ inputs:
draft: draft:
description: 'Create a draft pull request. It is not possible to change draft status after creation except through the web interface' description: 'Create a draft pull request. It is not possible to change draft status after creation except through the web interface'
default: false default: false
maintainer-can-modify:
description: 'Indicates whether maintainers can modify the pull request.'
default: true
outputs: outputs:
pull-request-number: pull-request-number:
description: 'The pull request number' description: 'The pull request number'

80
dist/index.js vendored
View File

@@ -356,8 +356,9 @@ function createPullRequest(inputs) {
core.endGroup(); core.endGroup();
core.startGroup('Determining the base and head repositories'); core.startGroup('Determining the base and head repositories');
const baseRemote = gitConfigHelper.getGitRemote(); const baseRemote = gitConfigHelper.getGitRemote();
// Init the GitHub client // Init the GitHub clients
const githubHelper = new github_helper_1.GitHubHelper(baseRemote.hostname, inputs.token); const ghBranch = new github_helper_1.GitHubHelper(baseRemote.hostname, inputs.gitToken);
const ghPull = new github_helper_1.GitHubHelper(baseRemote.hostname, inputs.token);
// Determine the head repository; the target for the pull request branch // Determine the head repository; the target for the pull request branch
const branchRemoteName = inputs.pushToFork ? 'fork' : 'origin'; const branchRemoteName = inputs.pushToFork ? 'fork' : 'origin';
const branchRepository = inputs.pushToFork const branchRepository = inputs.pushToFork
@@ -366,8 +367,8 @@ function createPullRequest(inputs) {
if (inputs.pushToFork) { if (inputs.pushToFork) {
// Check if the supplied fork is really a fork of the base // Check if the supplied fork is really a fork of the base
core.info(`Checking if '${branchRepository}' is a fork of '${baseRemote.repository}'`); core.info(`Checking if '${branchRepository}' is a fork of '${baseRemote.repository}'`);
const baseParentRepository = yield githubHelper.getRepositoryParent(baseRemote.repository); const baseParentRepository = yield ghBranch.getRepositoryParent(baseRemote.repository);
const branchParentRepository = yield githubHelper.getRepositoryParent(branchRepository); const branchParentRepository = yield ghBranch.getRepositoryParent(branchRepository);
if (branchParentRepository == null) { if (branchParentRepository == null) {
throw new Error(`Repository '${branchRepository}' is not a fork. Unable to continue.`); throw new Error(`Repository '${branchRepository}' is not a fork. Unable to continue.`);
} }
@@ -450,9 +451,15 @@ function createPullRequest(inputs) {
core.info(`Configured git committer as '${parsedCommitter.name} <${parsedCommitter.email}>'`); core.info(`Configured git committer as '${parsedCommitter.name} <${parsedCommitter.email}>'`);
core.info(`Configured git author as '${parsedAuthor.name} <${parsedAuthor.email}>'`); core.info(`Configured git author as '${parsedAuthor.name} <${parsedAuthor.email}>'`);
core.endGroup(); core.endGroup();
// Action outputs
const outputs = new Map();
outputs.set('pull-request-branch', inputs.branch);
outputs.set('pull-request-operation', 'none');
outputs.set('pull-request-commits-verified', 'false');
// Create or update the pull request branch // Create or update the pull request branch
core.startGroup('Create or update the pull request branch'); core.startGroup('Create or update the pull request branch');
const result = yield (0, create_or_update_branch_1.createOrUpdateBranch)(git, inputs.commitMessage, inputs.base, inputs.branch, branchRemoteName, inputs.signoff, inputs.addPaths, inputs.signCommits); const result = yield (0, create_or_update_branch_1.createOrUpdateBranch)(git, inputs.commitMessage, inputs.base, inputs.branch, branchRemoteName, inputs.signoff, inputs.addPaths, inputs.signCommits);
outputs.set('pull-request-head-sha', result.headSha);
// Set the base. It would have been '' if not specified as an input // Set the base. It would have been '' if not specified as an input
inputs.base = result.base; inputs.base = result.base;
core.endGroup(); core.endGroup();
@@ -463,7 +470,9 @@ function createPullRequest(inputs) {
// Create signed commits via the GitHub API // Create signed commits via the GitHub API
const stashed = yield git.stashPush(['--include-untracked']); const stashed = yield git.stashPush(['--include-untracked']);
yield git.checkout(inputs.branch); yield git.checkout(inputs.branch);
yield githubHelper.pushSignedCommits(result.branchCommits, result.baseSha, repoPath, branchRepository, inputs.branch); const pushSignedCommitsResult = yield ghBranch.pushSignedCommits(result.branchCommits, result.baseSha, repoPath, branchRepository, inputs.branch);
outputs.set('pull-request-head-sha', pushSignedCommitsResult.sha);
outputs.set('pull-request-commits-verified', pushSignedCommitsResult.verified.toString());
yield git.checkout('-'); yield git.checkout('-');
if (stashed) { if (stashed) {
yield git.stashPop(); yield git.stashPop();
@@ -479,22 +488,16 @@ function createPullRequest(inputs) {
core.endGroup(); core.endGroup();
} }
if (result.hasDiffWithBase) { if (result.hasDiffWithBase) {
// Create or update the pull request
core.startGroup('Create or update the pull request'); core.startGroup('Create or update the pull request');
const pull = yield githubHelper.createOrUpdatePullRequest(inputs, baseRemote.repository, branchRepository); const pull = yield ghPull.createOrUpdatePullRequest(inputs, baseRemote.repository, branchRepository);
core.endGroup(); outputs.set('pull-request-number', pull.number.toString());
// Set outputs outputs.set('pull-request-url', pull.html_url);
core.startGroup('Setting outputs');
core.setOutput('pull-request-number', pull.number);
core.setOutput('pull-request-url', pull.html_url);
if (pull.created) { if (pull.created) {
core.setOutput('pull-request-operation', 'created'); outputs.set('pull-request-operation', 'created');
} }
else if (result.action == 'updated') { else if (result.action == 'updated') {
core.setOutput('pull-request-operation', 'updated'); outputs.set('pull-request-operation', 'updated');
} }
core.setOutput('pull-request-head-sha', result.headSha);
core.setOutput('pull-request-branch', inputs.branch);
// Deprecated // Deprecated
core.exportVariable('PULL_REQUEST_NUMBER', pull.number); core.exportVariable('PULL_REQUEST_NUMBER', pull.number);
core.endGroup(); core.endGroup();
@@ -512,13 +515,17 @@ function createPullRequest(inputs) {
branchRemoteName, branchRemoteName,
`refs/heads/${inputs.branch}` `refs/heads/${inputs.branch}`
]); ]);
// Set outputs outputs.set('pull-request-operation', 'closed');
core.startGroup('Setting outputs');
core.setOutput('pull-request-operation', 'closed');
core.endGroup();
} }
} }
} }
// Set outputs
core.startGroup('Setting outputs');
for (const [key, value] of outputs) {
core.info(`${key} = ${value}`);
core.setOutput(key, value);
}
core.endGroup();
} }
catch (error) { catch (error) {
core.setFailed(utils.getErrorMessage(error)); core.setFailed(utils.getErrorMessage(error));
@@ -1162,7 +1169,9 @@ const core = __importStar(__nccwpck_require__(2186));
const octokit_client_1 = __nccwpck_require__(5040); const octokit_client_1 = __nccwpck_require__(5040);
const p_limit_1 = __importDefault(__nccwpck_require__(3783)); const p_limit_1 = __importDefault(__nccwpck_require__(3783));
const utils = __importStar(__nccwpck_require__(918)); const utils = __importStar(__nccwpck_require__(918));
const ERROR_PR_ALREADY_EXISTS = 'A pull request already exists for';
const ERROR_PR_REVIEW_TOKEN_SCOPE = 'Validation Failed: "Could not resolve to a node with the global id of'; const ERROR_PR_REVIEW_TOKEN_SCOPE = 'Validation Failed: "Could not resolve to a node with the global id of';
const ERROR_PR_FORK_COLLAB = `Fork collab can't be granted by someone without permission`;
const blobCreationLimit = (0, p_limit_1.default)(8); const blobCreationLimit = (0, p_limit_1.default)(8);
class GitHubHelper { class GitHubHelper {
constructor(githubServerHostname, token) { constructor(githubServerHostname, token) {
@@ -1193,7 +1202,7 @@ class GitHubHelper {
// Try to create the pull request // Try to create the pull request
try { try {
core.info(`Attempting creation of pull request`); core.info(`Attempting creation of pull request`);
const { data: pull } = yield this.octokit.rest.pulls.create(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { title: inputs.title, head: headBranch, head_repo: headRepository, base: inputs.base, body: inputs.body, draft: inputs.draft })); const { data: pull } = yield this.octokit.rest.pulls.create(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { title: inputs.title, head: headBranch, head_repo: headRepository, base: inputs.base, body: inputs.body, draft: inputs.draft, maintainer_can_modify: inputs.maintainerCanModify }));
core.info(`Created pull request #${pull.number} (${headBranch} => ${inputs.base})`); core.info(`Created pull request #${pull.number} (${headBranch} => ${inputs.base})`);
return { return {
number: pull.number, number: pull.number,
@@ -1202,9 +1211,15 @@ class GitHubHelper {
}; };
} }
catch (e) { catch (e) {
if (utils.getErrorMessage(e).includes(`A pull request already exists for`)) { const errorMessage = utils.getErrorMessage(e);
if (errorMessage.includes(ERROR_PR_ALREADY_EXISTS)) {
core.info(`A pull request already exists for ${headBranch}`); core.info(`A pull request already exists for ${headBranch}`);
} }
else if (errorMessage.includes(ERROR_PR_FORK_COLLAB)) {
core.warning('An attempt was made to create a pull request using a token that does not have write access to the head branch.');
core.warning(`For this case, set input 'maintainer-can-modify' to 'false' to allow pull request creation.`);
throw e;
}
else { else {
throw e; throw e;
} }
@@ -1277,11 +1292,15 @@ class GitHubHelper {
} }
pushSignedCommits(branchCommits, baseSha, repoPath, branchRepository, branch) { pushSignedCommits(branchCommits, baseSha, repoPath, branchRepository, branch) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let headSha = baseSha; let headCommit = {
sha: baseSha,
verified: false
};
for (const commit of branchCommits) { for (const commit of branchCommits) {
headSha = yield this.createCommit(commit, [headSha], repoPath, branchRepository); headCommit = yield this.createCommit(commit, [headCommit.sha], repoPath, branchRepository);
} }
yield this.createOrUpdateRef(branchRepository, branch, headSha); yield this.createOrUpdateRef(branchRepository, branch, headCommit.sha);
return headCommit;
}); });
} }
createCommit(commit, parents, repoPath, branchRepository) { createCommit(commit, parents, repoPath, branchRepository) {
@@ -1312,7 +1331,10 @@ class GitHubHelper {
const { data: remoteCommit } = yield this.octokit.rest.git.createCommit(Object.assign(Object.assign({}, repository), { parents: parents, tree: treeSha, message: `${commit.subject}\n\n${commit.body}` })); const { data: remoteCommit } = yield this.octokit.rest.git.createCommit(Object.assign(Object.assign({}, repository), { parents: parents, tree: treeSha, message: `${commit.subject}\n\n${commit.body}` }));
core.info(`Created commit ${remoteCommit.sha} for local commit ${commit.sha}`); core.info(`Created commit ${remoteCommit.sha} for local commit ${commit.sha}`);
core.info(`Commit verified: ${remoteCommit.verification.verified}; reason: ${remoteCommit.verification.reason}`); core.info(`Commit verified: ${remoteCommit.verification.verified}; reason: ${remoteCommit.verification.reason}`);
return remoteCommit.sha; return {
sha: remoteCommit.sha,
verified: remoteCommit.verification.verified
};
}); });
} }
createOrUpdateRef(branchRepository, branch, newHead) { createOrUpdateRef(branchRepository, branch, newHead) {
@@ -1405,7 +1427,8 @@ function run() {
reviewers: utils.getInputAsArray('reviewers'), reviewers: utils.getInputAsArray('reviewers'),
teamReviewers: utils.getInputAsArray('team-reviewers'), teamReviewers: utils.getInputAsArray('team-reviewers'),
milestone: Number(core.getInput('milestone')), milestone: Number(core.getInput('milestone')),
draft: core.getBooleanInput('draft') draft: core.getBooleanInput('draft'),
maintainerCanModify: core.getBooleanInput('maintainer-can-modify')
}; };
core.debug(`Inputs: ${(0, util_1.inspect)(inputs)}`); core.debug(`Inputs: ${(0, util_1.inspect)(inputs)}`);
if (!inputs.token) { if (!inputs.token) {
@@ -1485,8 +1508,9 @@ exports.throttleOptions = {
return true; return true;
} }
}, },
onSecondaryRateLimit: (_, options) => { onSecondaryRateLimit: (retryAfter, options) => {
core.warning(`Hit secondary rate limit for request ${options.method} ${options.url}`); core.warning(`Hit secondary rate limit for request ${options.method} ${options.url}`);
core.warning(`Requests may be retried after ${retryAfter} seconds.`);
} }
}; };
const proxyFetch = (proxyUrl) => (url, opts) => { const proxyFetch = (proxyUrl) => (url, opts) => {

View File

@@ -33,6 +33,7 @@ export interface Inputs {
teamReviewers: string[] teamReviewers: string[]
milestone: number milestone: number
draft: boolean draft: boolean
maintainerCanModify: boolean
} }
export async function createPullRequest(inputs: Inputs): Promise<void> { export async function createPullRequest(inputs: Inputs): Promise<void> {
@@ -46,8 +47,9 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
core.startGroup('Determining the base and head repositories') core.startGroup('Determining the base and head repositories')
const baseRemote = gitConfigHelper.getGitRemote() const baseRemote = gitConfigHelper.getGitRemote()
// Init the GitHub client // Init the GitHub clients
const githubHelper = new GitHubHelper(baseRemote.hostname, inputs.token) const ghBranch = new GitHubHelper(baseRemote.hostname, inputs.gitToken)
const ghPull = new GitHubHelper(baseRemote.hostname, inputs.token)
// Determine the head repository; the target for the pull request branch // Determine the head repository; the target for the pull request branch
const branchRemoteName = inputs.pushToFork ? 'fork' : 'origin' const branchRemoteName = inputs.pushToFork ? 'fork' : 'origin'
const branchRepository = inputs.pushToFork const branchRepository = inputs.pushToFork
@@ -58,11 +60,11 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
core.info( core.info(
`Checking if '${branchRepository}' is a fork of '${baseRemote.repository}'` `Checking if '${branchRepository}' is a fork of '${baseRemote.repository}'`
) )
const baseParentRepository = await githubHelper.getRepositoryParent( const baseParentRepository = await ghBranch.getRepositoryParent(
baseRemote.repository baseRemote.repository
) )
const branchParentRepository = const branchParentRepository =
await githubHelper.getRepositoryParent(branchRepository) await ghBranch.getRepositoryParent(branchRepository)
if (branchParentRepository == null) { if (branchParentRepository == null) {
throw new Error( throw new Error(
`Repository '${branchRepository}' is not a fork. Unable to continue.` `Repository '${branchRepository}' is not a fork. Unable to continue.`
@@ -175,6 +177,12 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
) )
core.endGroup() core.endGroup()
// Action outputs
const outputs = new Map<string, string>()
outputs.set('pull-request-branch', inputs.branch)
outputs.set('pull-request-operation', 'none')
outputs.set('pull-request-commits-verified', 'false')
// Create or update the pull request branch // Create or update the pull request branch
core.startGroup('Create or update the pull request branch') core.startGroup('Create or update the pull request branch')
const result = await createOrUpdateBranch( const result = await createOrUpdateBranch(
@@ -187,6 +195,7 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
inputs.addPaths, inputs.addPaths,
inputs.signCommits inputs.signCommits
) )
outputs.set('pull-request-head-sha', result.headSha)
// Set the base. It would have been '' if not specified as an input // Set the base. It would have been '' if not specified as an input
inputs.base = result.base inputs.base = result.base
core.endGroup() core.endGroup()
@@ -200,13 +209,18 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
// Create signed commits via the GitHub API // Create signed commits via the GitHub API
const stashed = await git.stashPush(['--include-untracked']) const stashed = await git.stashPush(['--include-untracked'])
await git.checkout(inputs.branch) await git.checkout(inputs.branch)
await githubHelper.pushSignedCommits( const pushSignedCommitsResult = await ghBranch.pushSignedCommits(
result.branchCommits, result.branchCommits,
result.baseSha, result.baseSha,
repoPath, repoPath,
branchRepository, branchRepository,
inputs.branch inputs.branch
) )
outputs.set('pull-request-head-sha', pushSignedCommitsResult.sha)
outputs.set(
'pull-request-commits-verified',
pushSignedCommitsResult.verified.toString()
)
await git.checkout('-') await git.checkout('-')
if (stashed) { if (stashed) {
await git.stashPop() await git.stashPop()
@@ -222,26 +236,19 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
} }
if (result.hasDiffWithBase) { if (result.hasDiffWithBase) {
// Create or update the pull request
core.startGroup('Create or update the pull request') core.startGroup('Create or update the pull request')
const pull = await githubHelper.createOrUpdatePullRequest( const pull = await ghPull.createOrUpdatePullRequest(
inputs, inputs,
baseRemote.repository, baseRemote.repository,
branchRepository branchRepository
) )
core.endGroup() outputs.set('pull-request-number', pull.number.toString())
outputs.set('pull-request-url', pull.html_url)
// Set outputs
core.startGroup('Setting outputs')
core.setOutput('pull-request-number', pull.number)
core.setOutput('pull-request-url', pull.html_url)
if (pull.created) { if (pull.created) {
core.setOutput('pull-request-operation', 'created') outputs.set('pull-request-operation', 'created')
} else if (result.action == 'updated') { } else if (result.action == 'updated') {
core.setOutput('pull-request-operation', 'updated') outputs.set('pull-request-operation', 'updated')
} }
core.setOutput('pull-request-head-sha', result.headSha)
core.setOutput('pull-request-branch', inputs.branch)
// Deprecated // Deprecated
core.exportVariable('PULL_REQUEST_NUMBER', pull.number) core.exportVariable('PULL_REQUEST_NUMBER', pull.number)
core.endGroup() core.endGroup()
@@ -260,13 +267,18 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
branchRemoteName, branchRemoteName,
`refs/heads/${inputs.branch}` `refs/heads/${inputs.branch}`
]) ])
// Set outputs outputs.set('pull-request-operation', 'closed')
core.startGroup('Setting outputs')
core.setOutput('pull-request-operation', 'closed')
core.endGroup()
} }
} }
} }
// Set outputs
core.startGroup('Setting outputs')
for (const [key, value] of outputs) {
core.info(`${key} = ${value}`)
core.setOutput(key, value)
}
core.endGroup()
} catch (error) { } catch (error) {
core.setFailed(utils.getErrorMessage(error)) core.setFailed(utils.getErrorMessage(error))
} finally { } finally {

View File

@@ -5,8 +5,10 @@ import {Octokit, OctokitOptions, throttleOptions} from './octokit-client'
import pLimit from 'p-limit' import pLimit from 'p-limit'
import * as utils from './utils' import * as utils from './utils'
const ERROR_PR_ALREADY_EXISTS = 'A pull request already exists for'
const ERROR_PR_REVIEW_TOKEN_SCOPE = const ERROR_PR_REVIEW_TOKEN_SCOPE =
'Validation Failed: "Could not resolve to a node with the global id of' 'Validation Failed: "Could not resolve to a node with the global id of'
const ERROR_PR_FORK_COLLAB = `Fork collab can't be granted by someone without permission`
const blobCreationLimit = pLimit(8) const blobCreationLimit = pLimit(8)
@@ -21,6 +23,11 @@ interface Pull {
created: boolean created: boolean
} }
interface CommitResponse {
sha: string
verified: boolean
}
type TreeObject = { type TreeObject = {
path: string path: string
mode: '100644' | '100755' | '040000' | '160000' | '120000' mode: '100644' | '100755' | '040000' | '160000' | '120000'
@@ -71,7 +78,8 @@ export class GitHubHelper {
head_repo: headRepository, head_repo: headRepository,
base: inputs.base, base: inputs.base,
body: inputs.body, body: inputs.body,
draft: inputs.draft draft: inputs.draft,
maintainer_can_modify: inputs.maintainerCanModify
}) })
core.info( core.info(
`Created pull request #${pull.number} (${headBranch} => ${inputs.base})` `Created pull request #${pull.number} (${headBranch} => ${inputs.base})`
@@ -82,10 +90,17 @@ export class GitHubHelper {
created: true created: true
} }
} catch (e) { } catch (e) {
if ( const errorMessage = utils.getErrorMessage(e)
utils.getErrorMessage(e).includes(`A pull request already exists for`) if (errorMessage.includes(ERROR_PR_ALREADY_EXISTS)) {
) {
core.info(`A pull request already exists for ${headBranch}`) core.info(`A pull request already exists for ${headBranch}`)
} else if (errorMessage.includes(ERROR_PR_FORK_COLLAB)) {
core.warning(
'An attempt was made to create a pull request using a token that does not have write access to the head branch.'
)
core.warning(
`For this case, set input 'maintainer-can-modify' to 'false' to allow pull request creation.`
)
throw e
} else { } else {
throw e throw e
} }
@@ -203,17 +218,21 @@ export class GitHubHelper {
repoPath: string, repoPath: string,
branchRepository: string, branchRepository: string,
branch: string branch: string
): Promise<void> { ): Promise<CommitResponse> {
let headSha = baseSha let headCommit: CommitResponse = {
sha: baseSha,
verified: false
}
for (const commit of branchCommits) { for (const commit of branchCommits) {
headSha = await this.createCommit( headCommit = await this.createCommit(
commit, commit,
[headSha], [headCommit.sha],
repoPath, repoPath,
branchRepository branchRepository
) )
} }
await this.createOrUpdateRef(branchRepository, branch, headSha) await this.createOrUpdateRef(branchRepository, branch, headCommit.sha)
return headCommit
} }
private async createCommit( private async createCommit(
@@ -221,7 +240,7 @@ export class GitHubHelper {
parents: string[], parents: string[],
repoPath: string, repoPath: string,
branchRepository: string branchRepository: string
): Promise<string> { ): Promise<CommitResponse> {
const repository = this.parseRepository(branchRepository) const repository = this.parseRepository(branchRepository)
let treeSha = commit.tree let treeSha = commit.tree
if (commit.changes.length > 0) { if (commit.changes.length > 0) {
@@ -270,7 +289,10 @@ export class GitHubHelper {
core.info( core.info(
`Commit verified: ${remoteCommit.verification.verified}; reason: ${remoteCommit.verification.reason}` `Commit verified: ${remoteCommit.verification.verified}; reason: ${remoteCommit.verification.reason}`
) )
return remoteCommit.sha return {
sha: remoteCommit.sha,
verified: remoteCommit.verification.verified
}
} }
private async createOrUpdateRef( private async createOrUpdateRef(

View File

@@ -28,7 +28,8 @@ async function run(): Promise<void> {
reviewers: utils.getInputAsArray('reviewers'), reviewers: utils.getInputAsArray('reviewers'),
teamReviewers: utils.getInputAsArray('team-reviewers'), teamReviewers: utils.getInputAsArray('team-reviewers'),
milestone: Number(core.getInput('milestone')), milestone: Number(core.getInput('milestone')),
draft: core.getBooleanInput('draft') draft: core.getBooleanInput('draft'),
maintainerCanModify: core.getBooleanInput('maintainer-can-modify')
} }
core.debug(`Inputs: ${inspect(inputs)}`) core.debug(`Inputs: ${inspect(inputs)}`)

View File

@@ -25,10 +25,11 @@ export const throttleOptions = {
return true return true
} }
}, },
onSecondaryRateLimit: (_, options) => { onSecondaryRateLimit: (retryAfter, options) => {
core.warning( core.warning(
`Hit secondary rate limit for request ${options.method} ${options.url}` `Hit secondary rate limit for request ${options.method} ${options.url}`
) )
core.warning(`Requests may be retried after ${retryAfter} seconds.`)
} }
} }