Compare commits

..

39 Commits

Author SHA1 Message Date
1ff93da091 Merge pull request #795 from peter-evans/gpg-sign
feat: add input to enable gpg commit signing
2021-05-09 14:15:03 +09:00
0524c01297 feat: add input to enable gpg commit signing 2021-05-09 10:14:59 +09:00
548adff9dc docs: update examples 2021-04-09 15:03:53 +09:00
28674474a4 docs: add link to github blog post 2021-04-06 10:46:44 +09:00
4fb90330a4 Merge pull request #773 from peter-evans/update-distribution
Update distribution
2021-04-01 12:08:39 +09:00
e4c811acf5 build: update distribution 2021-04-01 03:07:25 +00:00
99ccb3479b Merge pull request #759 from peter-evans/update-dependencies
Update dependencies
2021-04-01 12:05:05 +09:00
13616a4432 fix: update octokit rest methods 2021-04-01 11:56:16 +09:00
b5b91bc2b0 chore: update dependencies 2021-04-01 01:28:21 +00:00
5666cd8fe9 Merge pull request #755 from peter-evans/update-distribution
Update distribution
2021-03-16 11:35:49 +09:00
ad897490d5 build: update distribution 2021-03-16 02:35:04 +00:00
0735106af9 Merge pull request #744 from peter-evans/update-dependencies
Update dependencies
2021-03-16 11:31:26 +09:00
9aeedaa8c2 fix: remove unnecessary prettier config 2021-03-16 11:16:45 +09:00
52d31873b6 chore: update dependencies 2021-03-11 01:43:57 +00:00
09b9ac155b Merge pull request #740 from peter-evans/update-distribution
Update distribution
2021-02-25 11:22:27 +09:00
6ec5e3e26b build: update distribution 2021-02-25 02:20:17 +00:00
8b46437b6d Merge pull request #709 from peter-evans/update-dependencies
Update dependencies
2021-02-25 11:17:55 +09:00
e361fd1788 chore: update dependencies 2021-02-25 01:38:41 +00:00
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
14 changed files with 9869 additions and 2824 deletions

View File

@ -9,8 +9,7 @@
"plugin:import/errors", "plugin:import/errors",
"plugin:import/warnings", "plugin:import/warnings",
"plugin:import/typescript", "plugin:import/typescript",
"plugin:prettier/recommended", "plugin:prettier/recommended"
"prettier/@typescript-eslint"
], ],
"plugins": ["@typescript-eslint"], "plugins": ["@typescript-eslint"],
"rules": { "rules": {

View File

@ -50,6 +50,7 @@ All inputs are **optional**. If not set, sensible defaults will be used.
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. Defaults to the GitHub Actions bot user. | `GitHub <noreply@github.com>` | | `committer` | The committer name and email address in the format `Display Name <email@address.com>`. Defaults to the GitHub Actions bot user. | `GitHub <noreply@github.com>` |
| `author` | The author name and email address in the format `Display Name <email@address.com>`. Defaults to the user who triggered the workflow run. | `${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>` | | `author` | The author name and email address in the format `Display Name <email@address.com>`. Defaults to the user who triggered the workflow run. | `${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>` |
| `signoff` | Add [`Signed-off-by`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---signoff) line by the committer at the end of the commit log message. | `false` | | `signoff` | Add [`Signed-off-by`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---signoff) line by the committer at the end of the commit log message. | `false` |
| `gpg-sign` | GPG-sign commits. See [GPG commit signature verification](docs/concepts-guidelines.md#gpg-commit-signature-verification) for details. | `false` |
| `branch` | The pull request branch name. | `create-pull-request/patch` | | `branch` | The pull request branch name. | `create-pull-request/patch` |
| `delete-branch` | Delete the `branch` when closing pull requests, and when undeleted after merging. Recommend `true`. | `false` | | `delete-branch` | Delete the `branch` when closing pull requests, and when undeleted after merging. Recommend `true`. | `false` |
| `branch-suffix` | The branch suffix type when using the alternative branching strategy. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Alternative strategy](#alternative-strategy---always-create-a-new-pull-request-branch) for details. | | | `branch-suffix` | The branch suffix type when using the alternative branching strategy. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Alternative strategy](#alternative-strategy---always-create-a-new-pull-request-branch) for details. | |
@ -66,7 +67,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

View File

@ -220,6 +220,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('none') expect(result.action).toEqual('none')
@ -236,6 +237,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -263,6 +265,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -283,6 +286,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -310,6 +314,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -332,6 +337,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -360,6 +366,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('not-updated') expect(_result.action).toEqual('not-updated')
@ -380,6 +387,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -416,6 +424,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -446,6 +455,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -473,6 +483,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -493,6 +504,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -532,6 +544,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -558,6 +571,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -600,6 +614,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -621,6 +636,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -651,6 +667,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -676,6 +693,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -710,6 +728,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -737,6 +756,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -779,6 +799,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -805,6 +826,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
FORK_REMOTE_NAME, FORK_REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -833,6 +855,7 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
FORK_REMOTE_NAME, FORK_REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -854,7 +877,8 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
true true,
false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
@ -889,7 +913,8 @@ describe('create-or-update-branch tests', () => {
'', '',
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
true true,
false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
expect(_result.hasDiffWithBase).toBeTruthy() expect(_result.hasDiffWithBase).toBeTruthy()
@ -920,6 +945,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('none') expect(result.action).toEqual('none')
@ -939,6 +965,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -969,6 +996,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -992,6 +1020,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1022,6 +1051,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1047,6 +1077,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1078,6 +1109,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('not-updated') expect(_result.action).toEqual('not-updated')
@ -1101,6 +1133,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1140,6 +1173,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1173,6 +1207,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1203,6 +1238,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1228,6 +1264,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1270,6 +1307,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1299,6 +1337,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1344,6 +1383,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1368,6 +1408,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1401,6 +1442,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1429,6 +1471,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1466,6 +1509,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1496,6 +1540,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1541,6 +1586,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1570,6 +1616,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
FORK_REMOTE_NAME, FORK_REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1601,6 +1648,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
FORK_REMOTE_NAME, FORK_REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1629,6 +1677,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1661,6 +1710,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')
@ -1686,6 +1736,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(result.action).toEqual('created') expect(result.action).toEqual('created')
@ -1726,6 +1777,7 @@ describe('create-or-update-branch tests', () => {
BASE, BASE,
BRANCH, BRANCH,
REMOTE_NAME, REMOTE_NAME,
false,
false false
) )
expect(_result.action).toEqual('updated') expect(_result.action).toEqual('updated')

View File

@ -24,6 +24,9 @@ inputs:
signoff: signoff:
description: 'Add `Signed-off-by` line by the committer at the end of the commit log message.' description: 'Add `Signed-off-by` line by the committer at the end of the commit log message.'
default: false default: false
gpg-sign:
description: 'GPG-sign commits.'
default: false
branch: branch:
description: 'The pull request branch name.' description: 'The pull request branch name.'
default: 'create-pull-request/patch' default: 'create-pull-request/patch'

980
dist/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ This document covers terminology, how the action works, general usage guidelines
- [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys) - [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys)
- [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork) - [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork)
- [Authenticating with GitHub App generated tokens](#authenticating-with-github-app-generated-tokens) - [Authenticating with GitHub App generated tokens](#authenticating-with-github-app-generated-tokens)
- [GPG commit signature verification](#gpg-commit-signature-verification)
- [Running in a container or on self-hosted runners](#running-in-a-container-or-on-self-hosted-runners) - [Running in a container or on self-hosted runners](#running-in-a-container-or-on-self-hosted-runners)
## Terminology ## Terminology
@ -129,6 +130,8 @@ jobs:
if: github.event.pull_request.head.repo.full_name == github.repository if: github.event.pull_request.head.repo.full_name == github.repository
``` ```
For further reading regarding the security of pull requests, see this GitHub blog post titled [Keeping your GitHub Actions and workflows secure: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)
### Triggering further workflow runs ### Triggering further workflow runs
Pull requests created by the action using the default `GITHUB_TOKEN` cannot trigger other workflows. If you have `on: pull_request` or `on: push` workflows acting as checks on pull requests, they will not run. Pull requests created by the action using the default `GITHUB_TOKEN` cannot trigger other workflows. If you have `on: pull_request` or `on: push` workflows acting as checks on pull requests, they will not run.
@ -272,6 +275,49 @@ GitHub App generated tokens are more secure than using a PAT because GitHub App
token: ${{ steps.generate-token.outputs.token }} token: ${{ steps.generate-token.outputs.token }}
``` ```
### GPG commit signature verification
The action can use GPG to sign commits with a GPG key that you generate yourself.
1. Follow GitHub's guide to [generate a new GPG key](https://docs.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key).
2. [Add the public key](https://docs.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account) to the user account associated with the [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) that you will use with the action.
3. Copy the private key to your clipboard, replacing `email@example.com` with the email address of your GPG key.
```
# macOS
gpg --armor --export-secret-key email@example.com | pbcopy
```
4. Paste the private key into a repository secret where the workflow will run. e.g. `GPG_PRIVATE_KEY`
5. Create another repository secret for the key's passphrase, if applicable. e.g. `GPG_PASSPHRASE`
6. The following example workflow shows how to use [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) to import your GPG key and instruct the action to sign commits by setting the `gpg-sign` input to `true`.
Note that the `committer` email address *MUST* match the email address used to create your GPG key.
```yaml
steps:
- uses: actions/checkout@v2
- uses: crazy-max/ghaction-import-gpg@v3
with:
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git-user-signingkey: true
git-commit-gpgsign: true
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.PAT }}
committer: example <email@example.com>
gpg-sign: true
```
### Running in a container or on self-hosted runners ### Running in a container or on self-hosted runners
This action can be run inside a container, or on [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners), by installing the necessary dependencies. This action can be run inside a container, or on [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners), by installing the necessary dependencies.

View File

@ -21,6 +21,7 @@
- [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) - [Setting the pull request body from a file](#setting-the-pull-request-body-from-a-file)
- [Using a markdown template](#using-a-markdown-template)
- [Debugging GitHub Actions](#debugging-github-actions) - [Debugging GitHub Actions](#debugging-github-actions)
@ -560,6 +561,31 @@ The content must be [escaped to preserve newlines](https://github.community/t/se
body: ${{ steps.get-pr-body.outputs.body }} body: ${{ steps.get-pr-body.outputs.body }}
``` ```
### Using a markdown template
In this example, a markdown template file is added to the repository at `.github/pull-request-template.md` with the following content.
```
This is a test pull request template
Render template variables such as {{ .foo }} and {{ .bar }}.
```
The template is rendered using the [render-template](https://github.com/chuhlomin/render-template) action and the result is used to create the pull request.
```yml
- name: Render template
id: template
uses: chuhlomin/render-template@v1.2
with:
template: .github/pull-request-template.md
vars: |
foo: this
bar: that
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
body: ${{ steps.template.outputs.result }}
```
### Debugging GitHub Actions ### Debugging GitHub Actions
#### Runner Diagnostic Logging #### Runner Diagnostic Logging

11407
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.3.2",
"@octokit/plugin-paginate-rest": "2.4.0", "@octokit/plugin-paginate-rest": "2.13.3",
"@octokit/plugin-rest-endpoint-methods": "4.2.0", "@octokit/plugin-rest-endpoint-methods": "5.0.0",
"uuid": "8.3.0" "uuid": "8.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "26.0.14", "@types/jest": "26.0.22",
"@types/node": "14.10.3", "@types/node": "14.14.37",
"@typescript-eslint/parser": "4.1.1", "@typescript-eslint/parser": "4.20.0",
"@vercel/ncc": "0.24.1", "@vercel/ncc": "0.27.0",
"eslint": "7.9.0", "eslint": "7.23.0",
"eslint-plugin-github": "4.1.1", "eslint-plugin-github": "4.1.2",
"eslint-plugin-jest": "24.0.1", "eslint-plugin-jest": "24.3.2",
"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.5.4",
"typescript": "4.0.2" "typescript": "4.2.3"
} }
} }

View File

@ -91,7 +91,8 @@ export async function createOrUpdateBranch(
base: string, base: string,
branch: string, branch: string,
branchRemoteName: string, branchRemoteName: string,
signoff: boolean signoff: boolean,
gpgSign: boolean
): Promise<CreateOrUpdateBranchResult> { ): Promise<CreateOrUpdateBranchResult> {
// Get the working base. // Get the working base.
// When a ref, it may or may not be the actual base. // When a ref, it may or may not be the actual base.
@ -124,14 +125,27 @@ export async function createOrUpdateBranch(
if (signoff) { if (signoff) {
params.push('--signoff') params.push('--signoff')
} }
if (gpgSign) {
params.push('--gpg-sign')
}
await git.commit(params) await git.commit(params)
} }
// 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
@ -168,7 +182,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) {

View File

@ -16,6 +16,7 @@ export interface Inputs {
committer: string committer: string
author: string author: string
signoff: boolean signoff: boolean
gpgSign: boolean
branch: string branch: string
deleteBranch: boolean deleteBranch: boolean
branchSuffix: string branchSuffix: string
@ -173,7 +174,8 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
inputs.base, inputs.base,
inputs.branch, inputs.branch,
branchRemoteName, branchRemoteName,
inputs.signoff inputs.signoff,
inputs.gpgSign
) )
core.endGroup() core.endGroup()
@ -195,11 +197,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
@ -215,6 +230,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

@ -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)
} }
@ -41,7 +43,7 @@ export class GitHubHelper {
): Promise<Pull> { ): Promise<Pull> {
// Try to create the pull request // Try to create the pull request
try { try {
const {data: pull} = await this.octokit.pulls.create({ const {data: pull} = await this.octokit.rest.pulls.create({
...this.parseRepository(baseRepository), ...this.parseRepository(baseRepository),
title: inputs.title, title: inputs.title,
head: headBranch, head: headBranch,
@ -54,7 +56,8 @@ 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 (
@ -68,13 +71,13 @@ export class GitHubHelper {
} }
// Update the pull request that exists for this branch and base // Update the pull request that exists for this branch and base
const {data: pulls} = await this.octokit.pulls.list({ const {data: pulls} = await this.octokit.rest.pulls.list({
...this.parseRepository(baseRepository), ...this.parseRepository(baseRepository),
state: 'open', state: 'open',
head: headBranch, head: headBranch,
base: inputs.base base: inputs.base
}) })
const {data: pull} = await this.octokit.pulls.update({ const {data: pull} = await this.octokit.rest.pulls.update({
...this.parseRepository(baseRepository), ...this.parseRepository(baseRepository),
pull_number: pulls[0].number, pull_number: pulls[0].number,
title: inputs.title, title: inputs.title,
@ -86,12 +89,13 @@ export class GitHubHelper {
) )
return { return {
number: pull.number, number: pull.number,
html_url: pull.html_url html_url: pull.html_url,
created: false
} }
} }
async getRepositoryParent(headRepository: string): Promise<string> { async getRepositoryParent(headRepository: string): Promise<string> {
const {data: headRepo} = await this.octokit.repos.get({ const {data: headRepo} = await this.octokit.rest.repos.get({
...this.parseRepository(headRepository) ...this.parseRepository(headRepository)
}) })
if (!headRepo.parent) { if (!headRepo.parent) {
@ -106,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}'`)
} await this.octokit.rest.issues.update({
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({
...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.rest.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.rest.issues.addAssignees({
...this.parseRepository(baseRepository),
issue_number: pull.number,
assignees: inputs.assignees
}) })
} }
@ -155,7 +157,7 @@ export class GitHubHelper {
} }
if (Object.keys(requestReviewersParams).length > 0) { if (Object.keys(requestReviewersParams).length > 0) {
try { try {
await this.octokit.pulls.requestReviewers({ await this.octokit.rest.pulls.requestReviewers({
...this.parseRepository(baseRepository), ...this.parseRepository(baseRepository),
pull_number: pull.number, pull_number: pull.number,
...requestReviewersParams ...requestReviewersParams
@ -168,5 +170,7 @@ export class GitHubHelper {
} }
} }
} }
return pull
} }
} }

View File

@ -12,6 +12,7 @@ async function run(): Promise<void> {
committer: core.getInput('committer'), committer: core.getInput('committer'),
author: core.getInput('author'), author: core.getInput('author'),
signoff: core.getInput('signoff') === 'true', signoff: core.getInput('signoff') === 'true',
gpgSign: core.getInput('gpg-sign') === 'true',
branch: core.getInput('branch'), branch: core.getInput('branch'),
deleteBranch: core.getInput('delete-branch') === 'true', deleteBranch: core.getInput('delete-branch') === 'true',
branchSuffix: core.getInput('branch-suffix'), branchSuffix: core.getInput('branch-suffix'),

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) {