Compare commits

..

28 Commits

Author SHA1 Message Date
052fc72b41 Merge pull request #724 from peter-evans/fix-assignees
fix: use the correct assignees property
2021-02-10 09:28:28 +09:00
ed00d4629c fix: use the correct assignees property 2021-02-10 09:00:23 +09:00
34371f09e5 Merge pull request #719 from peter-evans/add-to-lists
fix: add to labels and assignees instead of resetting
2021-02-08 10:19:41 +09:00
c27ea51ae0 fix: add to labels and assignees instead of resetting 2021-02-08 09:32:46 +09:00
5e9d0ee9ea Merge pull request #712 from peter-evans/operation-output
feat: add pull-request-operation output
2021-02-01 10:28:29 +09:00
b5f41d9b08 feat: add pull-request-operation output 2021-02-01 09:57:11 +09:00
2455e15969 Merge pull request #704 from jonico/support-ghes
Support GitHub Enterprise Server
2021-01-26 11:17:38 +09:00
05bc46786e Support GitHub Server API URL
* pass GitHub Server API in Octokkit constructor
2021-01-25 19:16:19 +01:00
adc6552966 Support GitHub Enterprise Server
* parse GITHUB_SERVER_URL if present
* accept proper server remotes as well
2021-01-25 18:25:20 +01:00
171fc6cce4 Merge pull request #701 from peter-evans/update-distribution
Update distribution
2021-01-25 14:22:27 +09:00
3fb765f674 build: update distribution 2021-01-25 05:19:37 +00:00
d95c81ee98 Merge pull request #686 from peter-evans/update-dependencies
Update dependencies
2021-01-25 14:16:59 +09:00
8d5ed6557f chore: update dependencies 2021-01-21 02:46:33 +00:00
7b1819c092 Merge pull request #683 from peter-evans/update-distribution
Update distribution
2020-12-28 10:22:06 +09:00
be0a8c9666 build: update distribution 2020-12-28 01:20:44 +00:00
a0a6157bf1 Merge pull request #594 from peter-evans/update-dependencies
Update dependencies
2020-12-28 10:18:18 +09:00
9c5ec2e07d chore: update dependencies 2020-12-24 02:04:52 +00:00
45c510e1f6 Merge pull request #672 from peter-evans/reset-perf
perf: git reset instead of fetch
2020-12-23 14:28:23 +09:00
249b80db6b perf: git reset instead of fetch 2020-12-23 14:10:40 +09:00
6c2b44c6ac Merge pull request #666 from peter-evans/dependabot/npm_and_yarn/node-notifier-8.0.1
build(deps): bump node-notifier from 8.0.0 to 8.0.1
2020-12-23 09:48:12 +09:00
76c58cf6a9 build(deps): bump node-notifier from 8.0.0 to 8.0.1
Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/v8.0.1/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-22 13:17:50 +00:00
8c603dbb04 Merge pull request #653 from peter-evans/fix-error-handling
fix: change or->and to catch all errors
2020-12-09 09:56:23 +09:00
d01e0807ef fix: change or->and to catch all errors 2020-12-09 09:38:10 +09:00
ce699aa2d1 Merge pull request #637 from peter-evans/prune-remote
fix: prune stale remote ref for self-hosted runners
2020-11-25 12:40:23 +09:00
9984f611a7 fix: prune stale remote ref for self-hosted runners 2020-11-24 12:34:57 +09:00
ff0beed1b2 Merge pull request #627 from peter-evans/git-diff-perf
perf: set diff quiet and switch isdirty command order
2020-11-17 13:22:44 +09:00
ddeca94037 perf: set diff quiet and switch isdirty command order 2020-11-17 11:42:31 +09:00
0fd77ba8cc docs: add missing contents link 2020-10-26 09:23:01 +09:00
10 changed files with 9384 additions and 2538 deletions

View File

@ -66,7 +66,13 @@ All inputs are **optional**. If not set, sensible defaults will be used.
### Action outputs ### Action outputs
The pull request number and URL are available as step outputs. The following outputs can be used by subsequent workflow steps.
- `pull-request-number` - The pull request number.
- `pull-request-url` - The URL of the pull request.
- `pull-request-operation` - The pull request operation performed by the action, `created`, `updated` or `closed`.
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.
```yml ```yml

783
dist/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
- [Misc workflow tips](#misc-workflow-tips) - [Misc workflow tips](#misc-workflow-tips)
- [Filtering push events](#filtering-push-events) - [Filtering push events](#filtering-push-events)
- [Dynamic configuration using variables](#dynamic-configuration-using-variables) - [Dynamic configuration using variables](#dynamic-configuration-using-variables)
- [Setting the pull request body from a file](#setting-the-pull-request-body-from-a-file)
- [Debugging GitHub Actions](#debugging-github-actions) - [Debugging GitHub Actions](#debugging-github-actions)

10940
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -31,24 +31,24 @@
"dependencies": { "dependencies": {
"@actions/core": "1.2.6", "@actions/core": "1.2.6",
"@actions/exec": "1.0.4", "@actions/exec": "1.0.4",
"@octokit/core": "3.1.2", "@octokit/core": "3.2.4",
"@octokit/plugin-paginate-rest": "2.4.0", "@octokit/plugin-paginate-rest": "2.8.0",
"@octokit/plugin-rest-endpoint-methods": "4.2.0", "@octokit/plugin-rest-endpoint-methods": "4.5.2",
"uuid": "8.3.0" "uuid": "8.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "26.0.14", "@types/jest": "26.0.20",
"@types/node": "14.10.3", "@types/node": "14.14.22",
"@typescript-eslint/parser": "4.1.1", "@typescript-eslint/parser": "4.14.0",
"@vercel/ncc": "0.24.1", "@vercel/ncc": "0.27.0",
"eslint": "7.9.0", "eslint": "7.18.0",
"eslint-plugin-github": "4.1.1", "eslint-plugin-github": "4.1.1",
"eslint-plugin-jest": "24.0.1", "eslint-plugin-jest": "24.1.3",
"jest": "26.4.2", "jest": "26.6.3",
"jest-circus": "26.4.2", "jest-circus": "26.6.3",
"js-yaml": "3.14.0", "js-yaml": "4.0.0",
"prettier": "2.1.2", "prettier": "2.2.1",
"ts-jest": "26.3.0", "ts-jest": "26.4.4",
"typescript": "4.0.2" "typescript": "4.1.3"
} }
} }

View File

@ -78,15 +78,6 @@ async function isEven(
) )
} }
async function hasDiff(
git: GitCommandManager,
branch1: string,
branch2: string
): Promise<boolean> {
const result = await git.diff([`${branch1}..${branch2}`])
return result.length > 0
}
function splitLines(multilineString: string): string[] { function splitLines(multilineString: string): string[] {
return multilineString return multilineString
.split('\n') .split('\n')
@ -139,8 +130,18 @@ export async function createOrUpdateBranch(
// Perform fetch and reset the working base // Perform fetch and reset the working base
// Commits made during the workflow will be removed // Commits made during the workflow will be removed
if (workingBaseType == WorkingBaseType.Branch) { if (workingBaseType == WorkingBaseType.Branch) {
core.info(`Resetting working base branch '${workingBase}' to its remote`) core.info(`Resetting working base branch '${workingBase}'`)
await git.fetch([`${workingBase}:${workingBase}`], baseRemote, ['--force']) if (branchRemoteName == 'fork') {
// If pushing to a fork we must fetch with 'unshallow' to avoid the following error on git push
// ! [remote rejected] HEAD -> tests/push-branch-to-fork (shallow update not allowed)
await git.fetch([`${workingBase}:${workingBase}`], baseRemote, [
'--force'
])
} else {
// If the remote is 'origin' we can git reset
await git.checkout(workingBase)
await git.exec(['reset', '--hard', `${baseRemote}/${workingBase}`])
}
} }
// If the working base is not the base, rebase the temp branch commits // If the working base is not the base, rebase the temp branch commits
@ -177,7 +178,7 @@ export async function createOrUpdateBranch(
// The pull request branch does not exist // The pull request branch does not exist
core.info(`Pull request branch '${branch}' does not exist yet.`) core.info(`Pull request branch '${branch}' does not exist yet.`)
// Create the pull request branch // Create the pull request branch
await git.checkout(branch, 'HEAD') await git.checkout(branch, tempBranch)
// Check if the pull request branch is ahead of the base // Check if the pull request branch is ahead of the base
result.hasDiffWithBase = await isAhead(git, base, branch) result.hasDiffWithBase = await isAhead(git, base, branch)
if (result.hasDiffWithBase) { if (result.hasDiffWithBase) {
@ -205,7 +206,7 @@ export async function createOrUpdateBranch(
// to have a diff with the base due to different commits for the same changes. // to have a diff with the base due to different commits for the same changes.
// For changes on base this reset is equivalent to a rebase of the pull request branch. // For changes on base this reset is equivalent to a rebase of the pull request branch.
if ( if (
(await hasDiff(git, branch, tempBranch)) || (await git.hasDiff([`${branch}..${tempBranch}`])) ||
!(await isAhead(git, base, tempBranch)) !(await isAhead(git, base, tempBranch))
) { ) {
core.info(`Resetting '${branch}'`) core.info(`Resetting '${branch}'`)

View File

@ -106,6 +106,12 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
`The 'base' and 'branch' for a pull request must be different branches. Unable to continue.` `The 'base' and 'branch' for a pull request must be different branches. Unable to continue.`
) )
} }
// For self-hosted runners the repository state persists between runs.
// This command prunes the stale remote ref when the pull request branch was
// deleted after being merged or closed. Without this the push using
// '--force-with-lease' fails due to "stale info."
// https://github.com/peter-evans/create-pull-request/issues/633
await git.exec(['remote', 'prune', branchRemoteName])
core.endGroup() core.endGroup()
// Apply the branch suffix if set // Apply the branch suffix if set
@ -189,11 +195,24 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
if (result.hasDiffWithBase) { if (result.hasDiffWithBase) {
// Create or update the pull request // Create or update the pull request
await githubHelper.createOrUpdatePullRequest( const pull = await githubHelper.createOrUpdatePullRequest(
inputs, inputs,
baseRemote.repository, baseRemote.repository,
branchRepository branchRepository
) )
// Set outputs
core.startGroup('Setting outputs')
core.setOutput('pull-request-number', pull.number)
core.setOutput('pull-request-url', pull.html_url)
if (pull.created) {
core.setOutput('pull-request-operation', 'created')
} else if (result.action == 'updated') {
core.setOutput('pull-request-operation', 'updated')
}
// Deprecated
core.exportVariable('PULL_REQUEST_NUMBER', pull.number)
core.endGroup()
} else { } else {
// There is no longer a diff with the base // There is no longer a diff with the base
// Check we are in a state where a branch exists // Check we are in a state where a branch exists
@ -209,6 +228,10 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
branchRemoteName, branchRemoteName,
`refs/heads/${inputs.branch}` `refs/heads/${inputs.branch}`
]) ])
// Set outputs
core.startGroup('Setting outputs')
core.setOutput('pull-request-operation', 'closed')
core.endGroup()
} }
} }
} }

View File

@ -96,15 +96,6 @@ export class GitCommandManager {
return output.exitCode === 0 return output.exitCode === 0
} }
async diff(options?: string[]): Promise<string> {
const args = ['-c', 'core.pager=cat', 'diff']
if (options) {
args.push(...options)
}
const output = await this.exec(args)
return output.stdout.trim()
}
async fetch( async fetch(
refSpec: string[], refSpec: string[],
remoteName?: string, remoteName?: string,
@ -153,18 +144,26 @@ export class GitCommandManager {
return this.workingDirectory return this.workingDirectory
} }
async hasDiff(options?: string[]): Promise<boolean> {
const args = ['diff', '--quiet']
if (options) {
args.push(...options)
}
const output = await this.exec(args, true)
return output.exitCode === 1
}
async isDirty(untracked: boolean): Promise<boolean> { async isDirty(untracked: boolean): Promise<boolean> {
const diffArgs = ['--abbrev=40', '--full-index', '--raw'] // Check untracked changes
// Check staged changes if (untracked && (await this.status(['--porcelain', '-unormal']))) {
if (await this.diff([...diffArgs, '--staged'])) {
return true return true
} }
// Check working index changes // Check working index changes
if (await this.diff(diffArgs)) { if (await this.hasDiff()) {
return true return true
} }
// Check untracked changes // Check staged changes
if (untracked && (await this.status(['--porcelain', '-unormal']))) { if (await this.hasDiff(['--staged'])) {
return true return true
} }
return false return false

View File

@ -13,6 +13,7 @@ interface Repository {
interface Pull { interface Pull {
number: number number: number
html_url: string html_url: string
created: boolean
} }
export class GitHubHelper { export class GitHubHelper {
@ -23,6 +24,7 @@ export class GitHubHelper {
if (token) { if (token) {
options.auth = `${token}` options.auth = `${token}`
} }
options.baseUrl = process.env['GITHUB_API_URL'] || 'https://api.github.com'
this.octokit = new Octokit(options) this.octokit = new Octokit(options)
} }
@ -54,13 +56,16 @@ export class GitHubHelper {
) )
return { return {
number: pull.number, number: pull.number,
html_url: pull.html_url html_url: pull.html_url,
created: true
} }
} catch (e) { } catch (e) {
if ( if (
!e.message || e.message &&
!e.message.includes(`A pull request already exists for ${headBranch}`) e.message.includes(`A pull request already exists for ${headBranch}`)
) { ) {
core.info(`A pull request already exists for ${headBranch}`)
} else {
throw e throw e
} }
} }
@ -84,7 +89,8 @@ export class GitHubHelper {
) )
return { return {
number: pull.number, number: pull.number,
html_url: pull.html_url html_url: pull.html_url,
created: false
} }
} }
@ -104,40 +110,38 @@ export class GitHubHelper {
inputs: Inputs, inputs: Inputs,
baseRepository: string, baseRepository: string,
headRepository: string headRepository: string
): Promise<void> { ): Promise<Pull> {
const [headOwner] = headRepository.split('/') const [headOwner] = headRepository.split('/')
const headBranch = `${headOwner}:${inputs.branch}` const headBranch = `${headOwner}:${inputs.branch}`
// Create or update the pull request // Create or update the pull request
const pull = await this.createOrUpdate(inputs, baseRepository, headBranch) const pull = await this.createOrUpdate(inputs, baseRepository, headBranch)
// Set outputs // Apply milestone
core.startGroup('Setting outputs')
core.setOutput('pull-request-number', pull.number)
core.setOutput('pull-request-url', pull.html_url)
// Deprecated
core.exportVariable('PULL_REQUEST_NUMBER', pull.number)
core.endGroup()
// Set milestone, labels and assignees
const updateIssueParams = {}
if (inputs.milestone) { if (inputs.milestone) {
updateIssueParams['milestone'] = inputs.milestone
core.info(`Applying milestone '${inputs.milestone}'`) core.info(`Applying milestone '${inputs.milestone}'`)
}
if (inputs.labels.length > 0) {
updateIssueParams['labels'] = inputs.labels
core.info(`Applying labels '${inputs.labels}'`)
}
if (inputs.assignees.length > 0) {
updateIssueParams['assignees'] = inputs.assignees
core.info(`Applying assignees '${inputs.assignees}'`)
}
if (Object.keys(updateIssueParams).length > 0) {
await this.octokit.issues.update({ await this.octokit.issues.update({
...this.parseRepository(baseRepository), ...this.parseRepository(baseRepository),
issue_number: pull.number, issue_number: pull.number,
...updateIssueParams milestone: inputs.milestone
})
}
// Apply labels
if (inputs.labels.length > 0) {
core.info(`Applying labels '${inputs.labels}'`)
await this.octokit.issues.addLabels({
...this.parseRepository(baseRepository),
issue_number: pull.number,
labels: inputs.labels
})
}
// Apply assignees
if (inputs.assignees.length > 0) {
core.info(`Applying assignees '${inputs.assignees}'`)
await this.octokit.issues.addAssignees({
...this.parseRepository(baseRepository),
issue_number: pull.number,
assignees: inputs.assignees
}) })
} }
@ -166,5 +170,7 @@ export class GitHubHelper {
} }
} }
} }
return pull
} }
} }

View File

@ -39,8 +39,21 @@ interface RemoteDetail {
export function getRemoteDetail(remoteUrl: string): RemoteDetail { export function getRemoteDetail(remoteUrl: string): RemoteDetail {
// Parse the protocol and github repository from a URL // Parse the protocol and github repository from a URL
// e.g. HTTPS, peter-evans/create-pull-request // e.g. HTTPS, peter-evans/create-pull-request
const httpsUrlPattern = /^https:\/\/.*@?github.com\/(.+\/.+)$/i const githubUrl = process.env['GITHUB_SERVER_URL'] || 'https://github.com'
const sshUrlPattern = /^git@github.com:(.+\/.+).git$/i
const githubServerMatch = githubUrl.match(/^https?:\/\/(.+)$/i)
if (!githubServerMatch) {
throw new Error('Could not parse GitHub Server name')
}
const httpsUrlPattern = new RegExp(
'^https?://.*@?' + githubServerMatch[1] + '/(.+/.+)$',
'i'
)
const sshUrlPattern = new RegExp(
'^git@' + githubServerMatch[1] + ':(.+/.+).git$',
'i'
)
const httpsMatch = remoteUrl.match(httpsUrlPattern) const httpsMatch = remoteUrl.match(httpsUrlPattern)
if (httpsMatch) { if (httpsMatch) {