Compare commits
151 Commits
Author | SHA1 | Date | |
---|---|---|---|
4d3b0a48ef | |||
e9a825aacd | |||
3509fd45ae | |||
14ee9d1df2 | |||
5d969a55c1 | |||
44130f6fc9 | |||
86ccd8cdef | |||
7e7fa32a5f | |||
5f7beeb2ff | |||
926d56fcba | |||
8d744a2cd3 | |||
c2d829c681 | |||
d77392faf0 | |||
ccd2b64012 | |||
58fb221778 | |||
7a856e8b5d | |||
65d7a66451 | |||
44a7f59b6f | |||
8acaf6bb4c | |||
498d78cb23 | |||
172ec762f8 | |||
5cb0d674f3 | |||
eb892d7803 | |||
f8274253bd | |||
0f423da02c | |||
9573f479a0 | |||
eb4cde120d | |||
25902ccdd1 | |||
39b337e8bb | |||
7e70d8e63c | |||
1a640f5b01 | |||
9faa8dc1d9 | |||
afcf57957d | |||
8cc3564bf3 | |||
6910c5cd03 | |||
14836c6ff3 | |||
8fbfcfbcbb | |||
326f260418 | |||
75104b7d7e | |||
fbb7e0e650 | |||
0f1e60a1f8 | |||
caa116d991 | |||
d2f72f0799 | |||
ded05960f3 | |||
eb605db8a3 | |||
b11e4c665b | |||
65327d17a5 | |||
0837238e66 | |||
17bd947e89 | |||
24b42ba7f4 | |||
c0aaf5bab9 | |||
968cb0f4d9 | |||
9d6f73d546 | |||
70d240d0c4 | |||
7bb7d96c96 | |||
66fcd19e8d | |||
d93f2b46fd | |||
246328e3d8 | |||
61cff7c673 | |||
46ba7bdfe8 | |||
d650be7389 | |||
2f7173349f | |||
4ca95026d7 | |||
64c4efd526 | |||
16e35685ce | |||
3b12cf0165 | |||
2a283f5fc3 | |||
8ed207bcca | |||
bd1f6727cd | |||
9a3acf8f32 | |||
b38fd9eb87 | |||
4a9e76e377 | |||
8cb4c8b741 | |||
b9eb5dd95e | |||
5502904068 | |||
56ad1fed7b | |||
2132f428f6 | |||
c558d39395 | |||
db640fa8db | |||
95d6677567 | |||
1f4e24248b | |||
08595270b5 | |||
237244614a | |||
6295d61f0c | |||
d4024e2876 | |||
ee96ad03d9 | |||
755b39d2ff | |||
9f95ac6c53 | |||
cedbe4ad47 | |||
0e48ed8743 | |||
e7291b422e | |||
eb824681a8 | |||
4cc13107a9 | |||
c71b8e4206 | |||
e2bf7f9b75 | |||
e1f4cfdcd4 | |||
b3f0552507 | |||
f4be118b21 | |||
c9f22f86fb | |||
35d5f3c8ae | |||
000a0fc06a | |||
2a59f517a7 | |||
48ce89bc7d | |||
6570353abb | |||
8f6cecd6c4 | |||
e14ef3b543 | |||
c5778e5181 | |||
374fc61fef | |||
6fa547cc6f | |||
4db3619128 | |||
989a8308ec | |||
6249109e58 | |||
c9b850c450 | |||
340e629d2f | |||
abc19caa82 | |||
3474dda921 | |||
ad11b10aa4 | |||
86aa5be8bf | |||
6867319cf3 | |||
cc84a2389e | |||
7e7150d0e8 | |||
eb99d45ce6 | |||
115b7391e1 | |||
8305970523 | |||
32f5c5dd5f | |||
628c2d7d35 | |||
37582e8764 | |||
1e6b4d1790 | |||
a70c6ebe2a | |||
5bd05538d0 | |||
26bc40eea1 | |||
6bb0e7771c | |||
4c347a4514 | |||
cff2c3381d | |||
e48dab0c1c | |||
ac9f92d6e7 | |||
3ff256ce08 | |||
0bcb10560b | |||
3c4b2793c1 | |||
22870d7816 | |||
e324a22ee1 | |||
8b60386018 | |||
6852d55922 | |||
32e5bb80a5 | |||
619cf2115d | |||
69008aa567 | |||
ae4278bf24 | |||
88da40fea7 | |||
694e068136 | |||
64c34f6885 | |||
52ada17960 |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
@ -1,17 +1,19 @@
|
||||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
}
|
||||
}
|
||||
"env": { "node": true, "jest": true },
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/typescript",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier/@typescript-eslint"
|
||||
],
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"@typescript-eslint/camelcase": "off"
|
||||
}
|
||||
}
|
||||
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -1 +0,0 @@
|
||||
* @peter-evans
|
136
.github/workflows/ci.yml
vendored
Normal file
136
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- run: npm ci
|
||||
- run: npm run clean
|
||||
- run: npm run build
|
||||
- run: npm run format-check
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
- run: npm run package
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: action.yml
|
||||
path: action.yml
|
||||
|
||||
test:
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
target: [built, committed]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: master
|
||||
- if: matrix.target == 'built' || github.event_name == 'pull_request'
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
- if: matrix.target == 'built' || github.event_name == 'pull_request'
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: action.yml
|
||||
path: .
|
||||
|
||||
- name: Create change
|
||||
run: date +%s > report.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: ./
|
||||
with:
|
||||
commit-message: '[CI] test ${{ matrix.target }}'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
title: '[CI] test ${{ matrix.target }}'
|
||||
body: |
|
||||
- CI test case for target '${{ matrix.target }}'
|
||||
|
||||
Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
branch: ci-test-${{ matrix.target }}
|
||||
|
||||
- name: Close Pull
|
||||
uses: peter-evans/close-pull@v1
|
||||
with:
|
||||
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
|
||||
comment: '[CI] test ${{ matrix.target }}'
|
||||
delete-branch: true
|
||||
|
||||
commentTestSuiteHelp:
|
||||
if: github.event_name == 'pull_request'
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v1
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Full test suite slash command
|
||||
|
||||
- if: steps.fc.outputs.comment-id == ''
|
||||
name: Create comment
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: |
|
||||
Full test suite slash command (repository admin only)
|
||||
```
|
||||
/test repository=${{ github.event.pull_request.head.repo.full_name }} branch=${{ github.event.pull_request.head.ref }} build=true
|
||||
```
|
||||
|
||||
package:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: rm -rf dist
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
commit-message: Update distribution
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
title: Update distribution
|
||||
body: |
|
||||
- Updates the distribution for changes on `master`
|
||||
|
||||
Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
branch: update-distribution
|
15
.github/workflows/cpr-example-command.yml
vendored
15
.github/workflows/cpr-example-command.yml
vendored
@ -7,15 +7,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Create report file
|
||||
run: date +%s > report.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: ./
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Add report file
|
||||
committer: Peter Evans <peter-evans@users.noreply.github.com>
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
title: '[Example] Add report file'
|
||||
body: |
|
||||
New report
|
||||
@ -27,17 +29,18 @@ jobs:
|
||||
assignees: peter-evans
|
||||
reviewers: peter-evans
|
||||
milestone: 1
|
||||
project: Example Project
|
||||
project-column: To do
|
||||
draft: false
|
||||
branch: example-patches
|
||||
request-to-parent: false
|
||||
|
||||
- name: Check outputs
|
||||
run: |
|
||||
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
||||
|
||||
- name: Add reaction
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repository: ${{ github.event.client_payload.github.payload.repository.full_name }}
|
||||
comment-id: ${{ github.event.client_payload.github.payload.comment.id }}
|
||||
reaction-type: hooray
|
||||
|
19
.github/workflows/dockerhub-description.yml
vendored
19
.github/workflows/dockerhub-description.yml
vendored
@ -1,19 +0,0 @@
|
||||
name: Update Docker Hub Description
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- README.md
|
||||
- .github/workflows/dockerhub-description.yml
|
||||
jobs:
|
||||
dockerHubDescription:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Docker Hub Description
|
||||
uses: peter-evans/dockerhub-description@v2.1.0
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
DOCKERHUB_REPOSITORY: peterevans/create-pull-request
|
9
.github/workflows/slash-command-dispatch.yml
vendored
9
.github/workflows/slash-command-dispatch.yml
vendored
@ -9,8 +9,7 @@ jobs:
|
||||
- name: Slash Command Dispatch
|
||||
uses: peter-evans/slash-command-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
reaction-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
|
||||
config: >
|
||||
[
|
||||
{
|
||||
@ -34,5 +33,11 @@ jobs:
|
||||
"command": "cpr-example",
|
||||
"permission": "admin",
|
||||
"issue_type": "issue"
|
||||
},
|
||||
{
|
||||
"command": "rebase",
|
||||
"permission": "admin",
|
||||
"repository": "peter-evans/slash-command-dispatch-processor",
|
||||
"issue_type": "pull-request"
|
||||
}
|
||||
]
|
||||
|
31
.github/workflows/update-dep.yml
vendored
Normal file
31
.github/workflows/update-dep.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: Update Dependencies
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 1 * * 4'
|
||||
jobs:
|
||||
update-dep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.x'
|
||||
- name: Update dependencies
|
||||
run: |
|
||||
npx -p npm-check-updates ncu -u
|
||||
npm install
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
|
||||
commit-message: Update dependencies
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: actions-bot <actions-bot@users.noreply.github.com>
|
||||
title: Update dependencies
|
||||
body: |
|
||||
- Dependency updates
|
||||
|
||||
Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
branch: update-dependencies
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
__pycache__
|
||||
.python-version
|
||||
|
||||
node_modules
|
||||
lib/
|
||||
node_modules/
|
||||
|
||||
.DS_Store
|
||||
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
90
README.md
90
README.md
@ -1,4 +1,5 @@
|
||||
# <img width="24" height="24" src="docs/assets/logo.svg"> Create Pull Request
|
||||
[](https://github.com/peter-evans/create-pull-request/actions?query=workflow%3ACI)
|
||||
[](https://github.com/marketplace/actions/create-pull-request)
|
||||
|
||||
A GitHub action to create a pull request for changes to your repository in the actions workspace.
|
||||
@ -27,22 +28,20 @@ Create Pull Request action will:
|
||||
```yml
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v2.x.x`
|
||||
|
||||
### Action inputs
|
||||
|
||||
With the exception of `token`, all inputs are **optional**. If not set, sensible default values will be used.
|
||||
All inputs are **optional**. If not set, sensible default values will be used.
|
||||
|
||||
**Note**: If you want pull requests created by this action to trigger an `on: push` or `on: pull_request` workflow then you must use a [Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) instead of the default `GITHUB_TOKEN`. Alternatively, allow the action to [push using SSH](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-using-ssh-deploy-keys) by configuring a deploy key.
|
||||
**Note**: If you want pull requests created by this action to trigger an `on: push` or `on: pull_request` workflow then you cannot use the default `GITHUB_TOKEN`. See the [documentation here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) for workarounds.
|
||||
|
||||
| Name | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| `token` | `GITHUB_TOKEN` or a `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | |
|
||||
| `path` | Relative path under `$GITHUB_WORKSPACE` to the repository. | `$GITHUB_WORKSPACE` |
|
||||
| `token` | `GITHUB_TOKEN` or a `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | `GITHUB_TOKEN` |
|
||||
| `path` | Relative path under `GITHUB_WORKSPACE` to the repository. | `GITHUB_WORKSPACE` |
|
||||
| `commit-message` | The message to use when committing changes. | `[create-pull-request] automated change` |
|
||||
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user. See [Committer and author](#committer-and-author) for details. |
|
||||
| `author` | The author name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user. See [Committer and author](#committer-and-author) for details. |
|
||||
@ -51,15 +50,17 @@ With the exception of `token`, all inputs are **optional**. If not set, sensible
|
||||
| `labels` | A comma separated list of labels. | |
|
||||
| `assignees` | A comma separated list of assignees (GitHub usernames). | |
|
||||
| `reviewers` | A comma separated list of reviewers (GitHub usernames) to request a review from. | |
|
||||
| `team-reviewers` | A comma separated list of GitHub teams to request a review from. | |
|
||||
| `team-reviewers` | A comma separated list of GitHub teams to request a review from. A `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) may be required. See [this issue](https://github.com/peter-evans/create-pull-request/issues/155). | |
|
||||
| `milestone` | The number of the milestone to associate this pull request with. | |
|
||||
| `project` | The name of the project for which a card should be created. Requires `project-column`. | |
|
||||
| `project-column` | The name of the project column under which a card should be created. Requires `project`. | |
|
||||
| `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` |
|
||||
| `project` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
||||
| `project-column` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
||||
| `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` |
|
||||
| `branch` | The branch name. See [Action behaviour](#action-behaviour) for details. | `create-pull-request/patch` |
|
||||
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` |
|
||||
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
|
||||
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Branch naming](#branch-naming) for details. | |
|
||||
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Action behaviour](#action-behaviour) for details. | |
|
||||
|
||||
**Outputs**
|
||||
### Action outputs
|
||||
|
||||
The pull request number is output as both an environment variable and a step output.
|
||||
Note that in order to read the step output the action step must have an id.
|
||||
@ -68,12 +69,10 @@ Note that in order to read the step output the action step must have an id.
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check outputs
|
||||
run: |
|
||||
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
||||
```
|
||||
|
||||
### Checkout
|
||||
@ -87,20 +86,29 @@ If there is some reason you need to use `actions/checkout@v1` the following step
|
||||
- run: git checkout "${GITHUB_REF:11}"
|
||||
```
|
||||
|
||||
### Branch naming
|
||||
### Action behaviour
|
||||
|
||||
For branch naming there are two strategies. Create a fixed-name pull request branch that will be updated with new changes until it is merged or closed, OR, always create a new unique branch each time there are changes to be committed.
|
||||
The default behaviour of the action is to create a pull request that will be continually updated with new changes until it is merged or closed.
|
||||
Changes are committed and pushed to a fixed-name branch, the name of which can be configured with the `branch` input.
|
||||
Any subsequent changes will be committed to the *same* branch and reflected in the open pull request.
|
||||
|
||||
#### Strategy A - Create and update a pull request branch (default)
|
||||
How the action behaves:
|
||||
|
||||
This strategy is the default behaviour of the action. The input `branch` defaults to `create-pull-request/patch`. Changes will be committed to this branch and a pull request created. Any subsequent changes will be committed to the *same* branch and reflected in the open pull request. If the pull request is merged or closed a new one will be created. If subsequent changes cause the branch to no longer differ from the base the pull request will be automatically closed and the branch deleted.
|
||||
- If there are changes (i.e. a diff exists with the checked out base branch), the changes will be pushed to a new `branch` and a pull request created.
|
||||
- If there are no changes (i.e. no diff exists with the checked out base branch), no pull request will be created and the action exits silently.
|
||||
- If a pull request already exists and there are no further changes (i.e. no diff with the current pull request branch) then the action exits silently.
|
||||
- If a pull request exists and new changes on the base branch make the pull request unnecessary (i.e. there is no longer a diff between the base and pull request branch), the pull request is automatically closed and the branch deleted.
|
||||
|
||||
#### Strategy B - Always create a new pull request branch
|
||||
For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
|
||||
|
||||
For this strategy there are three options to suffix the branch name.
|
||||
The branch name is defined by the input `branch` and defaults to `create-pull-request/patch`. The following options are values for `branch-suffix`.
|
||||
#### Alternative strategy - Always create a new pull request branch
|
||||
|
||||
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. This option should be used if multiple pull requests will be created during the execution of a workflow. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd`
|
||||
For some use cases it *may* be desirable to always create a new unique branch each time there are changes to be committed.
|
||||
This strategy is not recommended and mainly kept for backwards compatibility.
|
||||
|
||||
To use this strategy, set input `branch-suffix` with one of the following options.
|
||||
|
||||
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd`
|
||||
|
||||
- `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552`
|
||||
|
||||
@ -114,13 +122,13 @@ If there are files or directories you want to ignore you can simply add them to
|
||||
|
||||
If neither `committer` or `author` inputs are supplied the action will default to making commits that appear to be made by the GitHub Actions bot user.
|
||||
|
||||
In most cases, where the committer and author are the same, just the committer can be set.
|
||||
The following configuration can be used to have commits authored by the user who triggered the workflow event.
|
||||
```yml
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
committer: Peter Evans <peter-evans@users.noreply.github.com>
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
```
|
||||
|
||||
### Controlling commits
|
||||
@ -143,8 +151,23 @@ As well as relying on the action to handle uncommitted changes, you can addition
|
||||
run: date +%s > report.txt
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
```
|
||||
|
||||
### Create a project card
|
||||
|
||||
To create a project card for the pull request, pass the `pull-request-number` step output to [create-or-update-project-card](https://github.com/peter-evans/create-or-update-project-card) action.
|
||||
|
||||
```yml
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
|
||||
- name: Create or Update Project Card
|
||||
uses: peter-evans/create-or-update-project-card@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
project-name: My project
|
||||
column-name: My column
|
||||
issue-number: ${{ steps.cpr.outputs.pull-request-number }}
|
||||
```
|
||||
|
||||
## Reference Example
|
||||
@ -169,8 +192,8 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Add report file
|
||||
committer: Peter Evans <peter-evans@users.noreply.github.com>
|
||||
author: Peter Evans <peter-evans@users.noreply.github.com>
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
title: '[Example] Add report file'
|
||||
body: |
|
||||
New report
|
||||
@ -181,17 +204,18 @@ jobs:
|
||||
labels: report, automated pr
|
||||
assignees: peter-evans
|
||||
reviewers: peter-evans
|
||||
team-reviewers: owners, maintainers
|
||||
milestone: 1
|
||||
project: Example Project
|
||||
project-column: To do
|
||||
draft: false
|
||||
branch: example-patches
|
||||
request-to-parent: false
|
||||
- name: Check outputs
|
||||
run: |
|
||||
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
|
||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
||||
```
|
||||
|
||||
This reference configuration will create pull requests that look like this:
|
||||
An example based on the above reference configuration creates pull requests that look like this:
|
||||
|
||||

|
||||
|
||||
|
29
__test__/entrypoint.sh
Executable file
29
__test__/entrypoint.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh -l
|
||||
set -euo pipefail
|
||||
|
||||
# Save the working directory
|
||||
WORKINGDIR=$PWD
|
||||
|
||||
# Serve remote repo
|
||||
mkdir /git
|
||||
git init --bare /git/test-repo.git
|
||||
git daemon --verbose --enable=receive-pack --base-path=/git --export-all /git/test-repo.git &>/dev/null &
|
||||
|
||||
# Give the daemon time to start
|
||||
sleep 2
|
||||
|
||||
# Clone and make an initial commit
|
||||
git clone git://127.0.0.1/test-repo.git /git/test-repo
|
||||
cd /git/test-repo
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Your Name"
|
||||
echo "#test-repo" > README.md
|
||||
git add .
|
||||
git commit -m "initial commit"
|
||||
git push -u
|
||||
|
||||
# Restore the working directory
|
||||
cd $WORKINGDIR
|
||||
|
||||
# Execute integration tests
|
||||
jest int
|
153
__test__/git.int.test.ts
Normal file
153
__test__/git.int.test.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import {
|
||||
getRepoPath,
|
||||
execGit,
|
||||
addConfigOption,
|
||||
unsetConfigOption,
|
||||
configOptionExists,
|
||||
getConfigOption,
|
||||
getAndUnsetConfigOption
|
||||
} from '../lib/git'
|
||||
|
||||
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
|
||||
|
||||
describe('git tests', () => {
|
||||
beforeAll(() => {
|
||||
// GitHub workspace
|
||||
process.env['GITHUB_WORKSPACE'] = '/git/test-repo'
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
// Restore GitHub workspace
|
||||
delete process.env['GITHUB_WORKSPACE']
|
||||
if (originalGitHubWorkspace) {
|
||||
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
|
||||
}
|
||||
})
|
||||
|
||||
it('successfully executes a git command', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
['config', '--local', '--name-only', '--get-regexp', 'remote.origin.url'],
|
||||
true
|
||||
)
|
||||
expect(result.exitCode).toEqual(0)
|
||||
expect(result.stdout.trim()).toEqual('remote.origin.url')
|
||||
})
|
||||
|
||||
it('adds and unsets a config option', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(
|
||||
repoPath,
|
||||
'test.add.and.unset.config.option',
|
||||
'foo'
|
||||
)
|
||||
expect(add).toBeTruthy()
|
||||
const unset = await unsetConfigOption(
|
||||
repoPath,
|
||||
'test.add.and.unset.config.option'
|
||||
)
|
||||
expect(unset).toBeTruthy()
|
||||
})
|
||||
|
||||
it('adds and unsets a config option with value regex', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(
|
||||
repoPath,
|
||||
'test.add.and.unset.config.option',
|
||||
'foo bar'
|
||||
)
|
||||
expect(add).toBeTruthy()
|
||||
const unset = await unsetConfigOption(
|
||||
repoPath,
|
||||
'test.add.and.unset.config.option',
|
||||
'^foo'
|
||||
)
|
||||
expect(unset).toBeTruthy()
|
||||
})
|
||||
|
||||
it('determines that a config option exists', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const result = await configOptionExists(repoPath, 'remote.origin.url')
|
||||
expect(result).toBeTruthy()
|
||||
})
|
||||
|
||||
it('determines that a config option does not exist', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const result = await configOptionExists(repoPath, 'this.key.does.not.exist')
|
||||
expect(result).toBeFalsy()
|
||||
})
|
||||
|
||||
it('successfully retrieves a config option', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(repoPath, 'test.get.config.option', 'foo')
|
||||
expect(add).toBeTruthy()
|
||||
const option = await getConfigOption(repoPath, 'test.get.config.option')
|
||||
expect(option.value).toEqual('foo')
|
||||
const unset = await unsetConfigOption(repoPath, 'test.get.config.option')
|
||||
expect(unset).toBeTruthy()
|
||||
})
|
||||
|
||||
it('gets a config option with value regex', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(
|
||||
repoPath,
|
||||
'test.get.config.option',
|
||||
'foo bar'
|
||||
)
|
||||
expect(add).toBeTruthy()
|
||||
const option = await getConfigOption(
|
||||
repoPath,
|
||||
'test.get.config.option',
|
||||
'^foo'
|
||||
)
|
||||
expect(option.value).toEqual('foo bar')
|
||||
const unset = await unsetConfigOption(
|
||||
repoPath,
|
||||
'test.get.config.option',
|
||||
'^foo'
|
||||
)
|
||||
expect(unset).toBeTruthy()
|
||||
})
|
||||
|
||||
it('gets and unsets a config option', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(
|
||||
repoPath,
|
||||
'test.get.and.unset.config.option',
|
||||
'foo'
|
||||
)
|
||||
expect(add).toBeTruthy()
|
||||
const getAndUnset = await getAndUnsetConfigOption(
|
||||
repoPath,
|
||||
'test.get.and.unset.config.option'
|
||||
)
|
||||
expect(getAndUnset.value).toEqual('foo')
|
||||
})
|
||||
|
||||
it('gets and unsets a config option with value regex', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const add = await addConfigOption(
|
||||
repoPath,
|
||||
'test.get.and.unset.config.option',
|
||||
'foo bar'
|
||||
)
|
||||
expect(add).toBeTruthy()
|
||||
const getAndUnset = await getAndUnsetConfigOption(
|
||||
repoPath,
|
||||
'test.get.and.unset.config.option',
|
||||
'^foo'
|
||||
)
|
||||
expect(getAndUnset.value).toEqual('foo bar')
|
||||
})
|
||||
|
||||
it('fails to get and unset a config option', async () => {
|
||||
const repoPath = getRepoPath()
|
||||
const getAndUnset = await getAndUnsetConfigOption(
|
||||
repoPath,
|
||||
'this.key.does.not.exist'
|
||||
)
|
||||
expect(getAndUnset.name).toEqual('')
|
||||
expect(getAndUnset.value).toEqual('')
|
||||
})
|
||||
})
|
26
__test__/git.unit.test.ts
Normal file
26
__test__/git.unit.test.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import * as path from 'path'
|
||||
import {getRepoPath} from '../lib/git'
|
||||
|
||||
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
|
||||
|
||||
describe('git tests', () => {
|
||||
beforeAll(() => {
|
||||
// GitHub workspace
|
||||
process.env['GITHUB_WORKSPACE'] = __dirname
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
// Restore GitHub workspace
|
||||
delete process.env['GITHUB_WORKSPACE']
|
||||
if (originalGitHubWorkspace) {
|
||||
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
|
||||
}
|
||||
})
|
||||
|
||||
test('getRepoPath', async () => {
|
||||
expect(getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE'])
|
||||
expect(getRepoPath('foo')).toEqual(
|
||||
path.resolve(process.env['GITHUB_WORKSPACE'] || '', 'foo')
|
||||
)
|
||||
})
|
||||
})
|
23
__test__/integration-tests.sh
Executable file
23
__test__/integration-tests.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
IMAGE="cpr-integration-tests:latest"
|
||||
ARG1=${1:-}
|
||||
|
||||
if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" || $ARG1 == "build" ]]; then
|
||||
echo "Building Docker image $IMAGE ..."
|
||||
|
||||
cat > Dockerfile << EOF
|
||||
FROM node:12-alpine
|
||||
RUN apk --no-cache add git git-daemon
|
||||
RUN npm install jest --global
|
||||
WORKDIR /cpr
|
||||
COPY __test__/entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
EOF
|
||||
|
||||
docker build -t $IMAGE .
|
||||
rm Dockerfile
|
||||
fi
|
||||
|
||||
docker run -v $PWD:/cpr $IMAGE
|
15
action.yml
15
action.yml
@ -3,7 +3,7 @@ description: 'Creates a pull request for changes to your repository in the actio
|
||||
inputs:
|
||||
token:
|
||||
description: 'GITHUB_TOKEN or a repo scoped PAT'
|
||||
required: true
|
||||
default: ${{ github.token }}
|
||||
path:
|
||||
description: 'Relative path under $GITHUB_WORKSPACE to the repository.'
|
||||
commit-message:
|
||||
@ -27,21 +27,26 @@ inputs:
|
||||
milestone:
|
||||
description: 'The number of the milestone to associate this pull request with.'
|
||||
project:
|
||||
description: 'The name of the project for which a card should be created.'
|
||||
description: 'Deprecated. See README for details.'
|
||||
project-column:
|
||||
description: 'The name of the project column under which a card should be created.'
|
||||
description: 'Deprecated. See README for details.'
|
||||
draft:
|
||||
description: 'Create a draft pull request'
|
||||
branch:
|
||||
description: 'The pull request branch name.'
|
||||
request-to-parent:
|
||||
description: 'Create the pull request in the parent repository of the checked out fork.'
|
||||
default: false
|
||||
base:
|
||||
description: 'The pull request base branch.'
|
||||
branch-suffix:
|
||||
description: 'The branch suffix type.'
|
||||
outputs:
|
||||
pr_number:
|
||||
pull-request-number:
|
||||
description: 'The pull request number'
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'dist/index.js'
|
||||
branding:
|
||||
icon: 'git-pull-request'
|
||||
icon: 'git-pull-request'
|
||||
color: 'gray-dark'
|
||||
|
2
dist/cpr/common.py
vendored
2
dist/cpr/common.py
vendored
@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
|
||||
def parse_github_repository(url):
|
||||
# Parse the protocol and github repository from a URL
|
||||
# e.g. HTTPS, peter-evans/create-pull-request
|
||||
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
|
||||
https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
|
||||
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
||||
|
||||
match = https_pattern.match(url)
|
||||
|
44
dist/cpr/create_or_update_pull_request.py
vendored
44
dist/cpr/create_or_update_pull_request.py
vendored
@ -4,6 +4,20 @@ from github import Github, GithubException
|
||||
import os
|
||||
|
||||
|
||||
def string_to_bool(str):
|
||||
if str is None:
|
||||
return False
|
||||
else:
|
||||
return str.lower() in [
|
||||
"true",
|
||||
"1",
|
||||
"t",
|
||||
"y",
|
||||
"yes",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def cs_string_to_list(str):
|
||||
# Split the comma separated string into a list
|
||||
l = [i.strip() for i in str.split(",")]
|
||||
@ -56,31 +70,51 @@ def create_or_update_pull_request(
|
||||
team_reviewers,
|
||||
project_name,
|
||||
project_column_name,
|
||||
draft,
|
||||
request_to_parent,
|
||||
):
|
||||
github_repo = head_repo = Github(github_token).get_repo(github_repository)
|
||||
if string_to_bool(request_to_parent):
|
||||
github_repo = github_repo.parent
|
||||
if github_repo is None:
|
||||
raise ValueError(
|
||||
"The checked out repository is not a fork. Input 'request-to-parent' should be set to false."
|
||||
)
|
||||
|
||||
head_branch = f"{head_repo.owner.login}:{branch}"
|
||||
|
||||
# Create the pull request
|
||||
github_repo = Github(github_token).get_repo(github_repository)
|
||||
try:
|
||||
pull_request = github_repo.create_pull(
|
||||
title=title, body=body, base=base, head=branch
|
||||
title=title,
|
||||
body=body,
|
||||
base=base,
|
||||
head=head_branch,
|
||||
draft=string_to_bool(draft),
|
||||
)
|
||||
print(
|
||||
f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
|
||||
)
|
||||
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
|
||||
except GithubException as e:
|
||||
if e.status == 422:
|
||||
# A pull request exists for this branch and base
|
||||
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
|
||||
# Get the pull request
|
||||
pull_request = github_repo.get_pulls(
|
||||
state="open", base=base, head=head_branch
|
||||
)[0]
|
||||
# Update title and body
|
||||
pull_request.as_issue().edit(title=title, body=body)
|
||||
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
|
||||
print(
|
||||
f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
|
||||
)
|
||||
else:
|
||||
print(str(e))
|
||||
raise
|
||||
|
||||
# Set the output variables
|
||||
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
|
||||
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
|
||||
# 'pr_number' is deprecated
|
||||
os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
|
||||
|
||||
# Set labels, assignees and milestone
|
||||
|
2
dist/cpr/create_pull_request.py
vendored
Executable file → Normal file
2
dist/cpr/create_pull_request.py
vendored
Executable file → Normal file
@ -224,4 +224,6 @@ if result["action"] in ["created", "updated"]:
|
||||
os.environ.get("CPR_TEAM_REVIEWERS"),
|
||||
os.environ.get("CPR_PROJECT_NAME"),
|
||||
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
|
||||
os.environ.get("CPR_DRAFT"),
|
||||
os.environ.get("CPR_REQUEST_TO_PARENT"),
|
||||
)
|
||||
|
6
dist/cpr/requirements.txt
vendored
6
dist/cpr/requirements.txt
vendored
@ -1,2 +1,4 @@
|
||||
GitPython==3.0.8
|
||||
PyGithub==1.46
|
||||
setuptools==46.4.0
|
||||
wheel==0.34.2
|
||||
GitPython==3.1.2
|
||||
PyGithub==1.51
|
||||
|
6
dist/cpr/test_common.py
vendored
6
dist/cpr/test_common.py
vendored
@ -16,6 +16,12 @@ def test_parse_github_repository_success():
|
||||
assert protocol == "HTTPS"
|
||||
assert repository == "peter-evans/create-pull-request"
|
||||
|
||||
protocol, repository = cmn.parse_github_repository(
|
||||
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
|
||||
)
|
||||
assert protocol == "HTTPS"
|
||||
assert repository == "peter-evans/create-pull-request"
|
||||
|
||||
protocol, repository = cmn.parse_github_repository(
|
||||
"git@github.com:peter-evans/create-pull-request.git"
|
||||
)
|
||||
|
3236
dist/index.js
vendored
3236
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
BIN
dist/vendor/Deprecated-1.2.10.tar.gz
vendored
Normal file
BIN
dist/vendor/Deprecated-1.2.10.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/Deprecated-1.2.7.tar.gz
vendored
BIN
dist/vendor/Deprecated-1.2.7.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/GitPython-3.0.8.tar.gz
vendored
BIN
dist/vendor/GitPython-3.0.8.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/GitPython-3.1.2.tar.gz
vendored
Normal file
BIN
dist/vendor/GitPython-3.1.2.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/PyGithub-1.46.tar.gz
vendored
BIN
dist/vendor/PyGithub-1.46.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/PyGithub-1.51.tar.gz
vendored
Normal file
BIN
dist/vendor/PyGithub-1.51.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/certifi-2019.11.28.tar.gz
vendored
BIN
dist/vendor/certifi-2019.11.28.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/certifi-2020.6.20.tar.gz
vendored
Normal file
BIN
dist/vendor/certifi-2020.6.20.tar.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
dist/vendor/requests-2.23.0.tar.gz
vendored
BIN
dist/vendor/requests-2.23.0.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/requests-2.24.0.tar.gz
vendored
Normal file
BIN
dist/vendor/requests-2.24.0.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/setuptools-46.4.0.zip
vendored
Normal file
BIN
dist/vendor/setuptools-46.4.0.zip
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/smmap-3.0.4.tar.gz
vendored
Normal file
BIN
dist/vendor/smmap-3.0.4.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/smmap2-2.0.5.tar.gz
vendored
BIN
dist/vendor/smmap2-2.0.5.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/urllib3-1.25.8.tar.gz
vendored
BIN
dist/vendor/urllib3-1.25.8.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/urllib3-1.25.9.tar.gz
vendored
Normal file
BIN
dist/vendor/urllib3-1.25.9.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/wheel-0.34.2.tar.gz
vendored
Normal file
BIN
dist/vendor/wheel-0.34.2.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/wrapt-1.12.0.tar.gz
vendored
BIN
dist/vendor/wrapt-1.12.0.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/wrapt-1.12.1.tar.gz
vendored
Normal file
BIN
dist/vendor/wrapt-1.12.1.tar.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 414 KiB After Width: | Height: | Size: 126 KiB |
@ -9,10 +9,12 @@ This document covers terminology, how the action works, general usage guidelines
|
||||
- [Providing a consistent base](#providing-a-consistent-base)
|
||||
- [Pull request events](#pull-request-events)
|
||||
- [Restrictions on forked repositories](#restrictions-on-forked-repositories)
|
||||
- [Triggering further workflow runs](#triggering-further-workflow-runs)
|
||||
- [Security](#security)
|
||||
- [Advanced usage](#advanced-usage)
|
||||
- [Creating pull requests in a remote repository](#creating-pull-requests-in-a-remote-repository)
|
||||
- [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys)
|
||||
- [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork)
|
||||
- [Running in a container](#running-in-a-container)
|
||||
- [Creating pull requests on tag push](#creating-pull-requests-on-tag-push)
|
||||
|
||||
@ -88,7 +90,7 @@ Workflows triggered by `pull_request` events will by default check out a [merge
|
||||
|
||||
### Restrictions on forked repositories
|
||||
|
||||
GitHub Actions have imposed restrictions on events triggered by a forked repository. For example, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
|
||||
GitHub Actions have imposed restrictions on events triggered by a forked repository. Specifically, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
|
||||
|
||||
- Events from forks cannot access secrets, except for for the default `GITHUB_TOKEN`.
|
||||
> With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository.
|
||||
@ -99,7 +101,7 @@ GitHub Actions have imposed restrictions on events triggered by a forked reposit
|
||||
|
||||
[GitHub Actions: Permissions for the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token)
|
||||
|
||||
These restrictions mean that during a `pull_request` event triggered by a forked repository the action will be unable to commit changes to a branch.
|
||||
These restrictions mean that during a `pull_request` event triggered by a forked repository, actions have no write access to GitHub resources and will fail on attempt.
|
||||
|
||||
A job condition can be added to prevent workflows from executing when triggered by a repository fork.
|
||||
|
||||
@ -112,6 +114,23 @@ jobs:
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
> When you use the repository's GITHUB_TOKEN to perform tasks on behalf of the GitHub Actions app, events triggered by the GITHUB_TOKEN will not create a new workflow run.
|
||||
|
||||
[GitHub Actions: Events that trigger workflows](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token)
|
||||
|
||||
#### Workarounds to trigger further workflow runs
|
||||
|
||||
There are a number of workarounds with different pros and cons.
|
||||
|
||||
- Use the default `GITHUB_TOKEN` and allow the action to create pull requests that have no checks enabled. Manually close pull requests and immediately reopen them. This will enable `on: pull_request` workflows to run and be added as checks.
|
||||
- Use a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) created on an account that has write access to the repository that pull requests are being created in. This is the standard workaround and [recommended by GitHub](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token). However, the PAT cannot be scoped to a specific repository so the token becomes a very sensitive secret. If this is a concern, the PAT can instead be created for a dedicated [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements) that has collaborator access to the repository. Also note that because the account that owns the PAT will be the creator of pull requests, that user account will be unable to perform actions such as request changes or approve the pull request.
|
||||
- Use [SSH (deploy keys)](#push-using-ssh-deploy-keys) to push the pull request branch. This is arguably more secure than using a PAT because deploy keys can be set per repository. However, this method will only trigger `on: push` workflows.
|
||||
- Use a [machine account that creates pull requests from its own fork](#push-pull-request-branches-to-a-fork). This is the most secure because the PAT created only grants access to the machine account's fork, not the main repository. This method will trigger `on: pull_request` workflows to run. Workflows triggered `on: push` will not run because the push event is in the fork.
|
||||
|
||||
### Security
|
||||
|
||||
From a security perspective it's good practice to fork third-party actions, review the code, and use your fork of the action in workflows.
|
||||
@ -161,23 +180,48 @@ How to use SSH (deploy keys) with create-pull-request action:
|
||||
1. [Create a new SSH key pair](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key) for your repository. Do not set a passphrase.
|
||||
2. Copy the contents of the public key (.pub file) to a new repository [deploy key](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) and check the box to "Allow write access."
|
||||
3. Add a secret to the repository containing the entire contents of the private key.
|
||||
4. As shown in the example steps below, use the [`webfactory/ssh-agent`](https://github.com/webfactory/ssh-agent) action to install the private key and clone your repository. Remember to checkout the `base` of your pull request if it's not the default branch, e.g. `git checkout my-branch`.
|
||||
4. As shown in the example below, configure `actions/checkout` to use the deploy key you have created.
|
||||
|
||||
```yml
|
||||
steps:
|
||||
- uses: webfactory/ssh-agent@v0.2.0
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout via SSH
|
||||
run: git clone git@github.com:peter-evans/create-pull-request.git .
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
||||
# Make changes to pull request here
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
```
|
||||
|
||||
### Push pull request branches to a fork
|
||||
|
||||
Instead of pushing pull request branches to the repository you want to update, you can push them to a fork of that repository.
|
||||
This allows you to employ the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) by using a dedicated user acting as a [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements).
|
||||
This user has no access to the main repository.
|
||||
It will use their own fork to push code and create the pull request.
|
||||
|
||||
1. Create a new GitHub user and login.
|
||||
2. Fork the repository that you will be creating pull requests in.
|
||||
3. Create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
|
||||
4. Logout and log back in to your main user account.
|
||||
5. Add a secret to your repository containing the above PAT.
|
||||
6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and set the action input `request-to-parent` to `true`.
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: |
|
||||
git config user.password ${{ secrets.MACHINE_USER_PAT }}
|
||||
git remote set-url origin https://github.com/machine-user/fork-of-repository
|
||||
git fetch --unshallow -p origin
|
||||
|
||||
# Make changes to pull request here
|
||||
|
||||
- uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ${{ secrets.MACHINE_USER_PAT }}
|
||||
request-to-parent: true
|
||||
```
|
||||
|
||||
### Running in a container
|
||||
@ -197,7 +241,9 @@ jobs:
|
||||
image: alpine
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: apk --no-cache add git python3
|
||||
run: |
|
||||
apk --no-cache add git python3
|
||||
python3 -m ensurepip
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@ -205,8 +251,6 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
**Ubuntu container example:**
|
||||
@ -230,8 +274,6 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
### Creating pull requests on tag push
|
||||
@ -265,7 +307,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
base: master
|
||||
|
||||
- name: Delete tag branch
|
||||
@ -293,6 +334,4 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
@ -5,6 +5,7 @@
|
||||
- [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another)
|
||||
- [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically)
|
||||
- [Update NPM dependencies](#update-npm-dependencies)
|
||||
- [Update Gradle dependencies](#update-gradle-dependencies)
|
||||
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
|
||||
- [Spider and download a website](#spider-and-download-a-website)
|
||||
- [Use case: Create a pull request to update X by calling the GitHub API](#use-case-create-a-pull-request-to-update-x-by-calling-the-github-api)
|
||||
@ -45,7 +46,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: update authors
|
||||
title: Update AUTHORS
|
||||
body: Credit new contributors by updating AUTHORS
|
||||
@ -78,7 +78,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: production-promotion
|
||||
```
|
||||
|
||||
@ -88,33 +87,100 @@ This pattern will work well for updating any kind of static content from an exte
|
||||
|
||||
### Update NPM dependencies
|
||||
|
||||
This workflow will create a pull request for npm dependencies.
|
||||
It works best in combination with a build workflow triggered on `push` and `pull_request`.
|
||||
A [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) can be used in order for the creation of the pull request to trigger further workflows. See the [documentation here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) for further details.
|
||||
|
||||
```yml
|
||||
name: Update Dependencies
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 10 * * 1'
|
||||
jobs:
|
||||
update-deps:
|
||||
update-dep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
node-version: '12.x'
|
||||
- name: Update dependencies
|
||||
id: vars
|
||||
run: |
|
||||
npm install -g npm-check-updates
|
||||
ncu -u
|
||||
npx -p npm-check-updates ncu -u
|
||||
npm install
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: update dependencies
|
||||
title: Automated Dependency Updates
|
||||
body: This is an auto-generated PR with dependency updates.
|
||||
branch: dep-updates
|
||||
token: ${{ secrets.PAT }}
|
||||
commit-message: Update dependencies
|
||||
title: Update dependencies
|
||||
body: |
|
||||
- Dependency updates
|
||||
|
||||
Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
branch: update-dependencies
|
||||
```
|
||||
|
||||
The above workflow works best in combination with a build workflow triggered on `push` and `pull_request`.
|
||||
|
||||
```yml
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
- run: npm ci
|
||||
- run: npm run test
|
||||
- run: npm run build
|
||||
```
|
||||
|
||||
### Update Gradle dependencies
|
||||
|
||||
The following workflow will create a pull request for Gradle dependencies.
|
||||
It requires first configuring your project to use Gradle lockfiles.
|
||||
See [here](https://github.com/peter-evans/gradle-auto-dependency-updates) for how to configure your project and use the following workflow.
|
||||
|
||||
```yml
|
||||
name: Update Dependencies
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 1 * * 1'
|
||||
jobs:
|
||||
update-dep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Perform dependency resolution and write new lockfiles
|
||||
run: ./gradlew dependencies --write-locks
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
commit-message: Update dependencies
|
||||
title: Update dependencies
|
||||
body: |
|
||||
- Dependency updates
|
||||
|
||||
Auto-generated by [create-pull-request][1]
|
||||
|
||||
[1]: https://github.com/peter-evans/create-pull-request
|
||||
branch: update-dependencies
|
||||
```
|
||||
|
||||
### Update SwaggerUI for GitHub Pages
|
||||
@ -161,7 +227,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update swagger-ui to ${{ steps.swagger-ui.outputs.release_tag }}
|
||||
title: Update SwaggerUI to ${{ steps.swagger-ui.outputs.release_tag }}
|
||||
body: |
|
||||
@ -204,7 +269,6 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: update local website copy
|
||||
title: Automated Updates to Local Website Copy
|
||||
body: This is an auto-generated PR with website updates.
|
||||
@ -248,7 +312,7 @@ An `on: repository_dispatch` workflow can be triggered from another workflow wit
|
||||
|
||||
```yml
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v1.0.0
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
repository: username/my-repo
|
||||
@ -299,7 +363,6 @@ jobs:
|
||||
if: steps.autopep8.outputs.exit-code == 2
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: autopep8 action fixes
|
||||
title: Fixes by autopep8 action
|
||||
body: This is an auto-generated PR with fixes by autopep8.
|
||||
@ -358,7 +421,6 @@ The recommended method is to use [`set-output`](https://help.github.com/en/githu
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: ${{ steps.vars.outputs.pr_title }}
|
||||
body: ${{ steps.vars.outputs.pr_body }}
|
||||
```
|
||||
@ -374,7 +436,6 @@ Alternatively, [`set-env`](https://help.github.com/en/github/automating-your-wor
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: ${{ env.PULL_REQUEST_TITLE }}
|
||||
body: ${{ env.PULL_REQUEST_BODY }}
|
||||
```
|
||||
|
@ -1,3 +1,11 @@
|
||||
process.env = Object.assign(process.env, {
|
||||
GITHUB_WORKSPACE: __dirname
|
||||
});
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
}
|
||||
|
5773
package-lock.json
generated
5773
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -1,21 +1,31 @@
|
||||
{
|
||||
"name": "create-pull-request",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"description": "Creates a pull request for changes to your repository in the actions workspace",
|
||||
"main": "index.js",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist",
|
||||
"lint": "eslint src/index.js",
|
||||
"test": "eslint src/index.js && jest",
|
||||
"build": "ncc build src/index.js -o dist",
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write '**/*.ts'",
|
||||
"format-check": "prettier --check '**/*.ts'",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"test:unit": "jest unit",
|
||||
"test:int": "__test__/integration-tests.sh",
|
||||
"test": "npm run test:unit && npm run test:int",
|
||||
"pack-assets": "mkdir -p dist/cpr && cp -rv src/cpr/* dist/cpr",
|
||||
"vendor-deps": "pip download -r src/cpr/requirements.txt --no-binary=:all: -d dist/vendor",
|
||||
"package": "npm run build && npm run vendor-deps"
|
||||
"package": "npm run build && npm run pack-assets && npm run vendor-deps"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/peter-evans/create-pull-request.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"keywords": [
|
||||
"actions",
|
||||
"pull",
|
||||
"request"
|
||||
],
|
||||
"author": "Peter Evans",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
@ -23,14 +33,24 @@
|
||||
},
|
||||
"homepage": "https://github.com/peter-evans/create-pull-request",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.1.1",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/tool-cache": "^1.1.2",
|
||||
"is-docker": "^2.0.0"
|
||||
"@actions/core": "1.2.4",
|
||||
"@actions/exec": "1.0.4",
|
||||
"@actions/tool-cache": "1.3.4",
|
||||
"is-docker": "2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zeit/ncc": "0.21.1",
|
||||
"eslint": "6.8.0",
|
||||
"jest": "25.1.0"
|
||||
"@types/jest": "25.2.2",
|
||||
"@types/node": "14.0.1",
|
||||
"@typescript-eslint/parser": "2.33.0",
|
||||
"@zeit/ncc": "0.22.1",
|
||||
"eslint": "7.0.0",
|
||||
"eslint-plugin-github": "3.4.1",
|
||||
"eslint-plugin-jest": "23.11.0",
|
||||
"jest": "26.0.1",
|
||||
"jest-circus": "26.0.1",
|
||||
"js-yaml": "3.13.1",
|
||||
"prettier": "2.0.5",
|
||||
"ts-jest": "25.5.1",
|
||||
"typescript": "3.9.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"enabledManagers": ["pip_requirements"],
|
||||
"ignorePaths": [
|
||||
"**/dist/**"
|
||||
]
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
|
||||
def parse_github_repository(url):
|
||||
# Parse the protocol and github repository from a URL
|
||||
# e.g. HTTPS, peter-evans/create-pull-request
|
||||
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
|
||||
https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
|
||||
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
||||
|
||||
match = https_pattern.match(url)
|
||||
|
@ -4,6 +4,20 @@ from github import Github, GithubException
|
||||
import os
|
||||
|
||||
|
||||
def string_to_bool(str):
|
||||
if str is None:
|
||||
return False
|
||||
else:
|
||||
return str.lower() in [
|
||||
"true",
|
||||
"1",
|
||||
"t",
|
||||
"y",
|
||||
"yes",
|
||||
"on",
|
||||
]
|
||||
|
||||
|
||||
def cs_string_to_list(str):
|
||||
# Split the comma separated string into a list
|
||||
l = [i.strip() for i in str.split(",")]
|
||||
@ -56,31 +70,51 @@ def create_or_update_pull_request(
|
||||
team_reviewers,
|
||||
project_name,
|
||||
project_column_name,
|
||||
draft,
|
||||
request_to_parent,
|
||||
):
|
||||
github_repo = head_repo = Github(github_token).get_repo(github_repository)
|
||||
if string_to_bool(request_to_parent):
|
||||
github_repo = github_repo.parent
|
||||
if github_repo is None:
|
||||
raise ValueError(
|
||||
"The checked out repository is not a fork. Input 'request-to-parent' should be set to false."
|
||||
)
|
||||
|
||||
head_branch = f"{head_repo.owner.login}:{branch}"
|
||||
|
||||
# Create the pull request
|
||||
github_repo = Github(github_token).get_repo(github_repository)
|
||||
try:
|
||||
pull_request = github_repo.create_pull(
|
||||
title=title, body=body, base=base, head=branch
|
||||
title=title,
|
||||
body=body,
|
||||
base=base,
|
||||
head=head_branch,
|
||||
draft=string_to_bool(draft),
|
||||
)
|
||||
print(
|
||||
f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
|
||||
)
|
||||
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
|
||||
except GithubException as e:
|
||||
if e.status == 422:
|
||||
# A pull request exists for this branch and base
|
||||
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
|
||||
# Get the pull request
|
||||
pull_request = github_repo.get_pulls(
|
||||
state="open", base=base, head=head_branch
|
||||
)[0]
|
||||
# Update title and body
|
||||
pull_request.as_issue().edit(title=title, body=body)
|
||||
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
|
||||
print(
|
||||
f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
|
||||
)
|
||||
else:
|
||||
print(str(e))
|
||||
raise
|
||||
|
||||
# Set the output variables
|
||||
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
|
||||
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
|
||||
# 'pr_number' is deprecated
|
||||
os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
|
||||
|
||||
# Set labels, assignees and milestone
|
||||
|
@ -224,4 +224,6 @@ if result["action"] in ["created", "updated"]:
|
||||
os.environ.get("CPR_TEAM_REVIEWERS"),
|
||||
os.environ.get("CPR_PROJECT_NAME"),
|
||||
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
|
||||
os.environ.get("CPR_DRAFT"),
|
||||
os.environ.get("CPR_REQUEST_TO_PARENT"),
|
||||
)
|
||||
|
@ -1,2 +1,4 @@
|
||||
GitPython==3.0.8
|
||||
PyGithub==1.46
|
||||
setuptools==46.4.0
|
||||
wheel==0.34.2
|
||||
GitPython==3.1.2
|
||||
PyGithub==1.51
|
||||
|
@ -16,6 +16,12 @@ def test_parse_github_repository_success():
|
||||
assert protocol == "HTTPS"
|
||||
assert repository == "peter-evans/create-pull-request"
|
||||
|
||||
protocol, repository = cmn.parse_github_repository(
|
||||
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
|
||||
)
|
||||
assert protocol == "HTTPS"
|
||||
assert repository == "peter-evans/create-pull-request"
|
||||
|
||||
protocol, repository = cmn.parse_github_repository(
|
||||
"git@github.com:peter-evans/create-pull-request.git"
|
||||
)
|
||||
|
97
src/git.js
97
src/git.js
@ -1,97 +0,0 @@
|
||||
const core = require("@actions/core");
|
||||
const exec = require("@actions/exec");
|
||||
const path = require("path");
|
||||
|
||||
function getRepoPath(relativePath) {
|
||||
let githubWorkspacePath = process.env["GITHUB_WORKSPACE"];
|
||||
if (!githubWorkspacePath) {
|
||||
throw new Error("GITHUB_WORKSPACE not defined");
|
||||
}
|
||||
githubWorkspacePath = path.resolve(githubWorkspacePath);
|
||||
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`);
|
||||
|
||||
repoPath = githubWorkspacePath;
|
||||
if (relativePath) repoPath = path.resolve(repoPath, relativePath);
|
||||
|
||||
core.debug(`repoPath: ${repoPath}`);
|
||||
return repoPath;
|
||||
}
|
||||
|
||||
async function execGit(repoPath, args, ignoreReturnCode = false) {
|
||||
const stdout = [];
|
||||
const options = {
|
||||
cwd: repoPath,
|
||||
ignoreReturnCode: ignoreReturnCode,
|
||||
listeners: {
|
||||
stdout: data => {
|
||||
stdout.push(data.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = {};
|
||||
result.exitCode = await exec.exec("git", args, options);
|
||||
result.stdout = stdout.join("");
|
||||
return result;
|
||||
}
|
||||
|
||||
async function addConfigOption(repoPath, name, value) {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
["config", "--local", "--add", name, value],
|
||||
true
|
||||
);
|
||||
return result.exitCode === 0;
|
||||
}
|
||||
|
||||
async function unsetConfigOption(repoPath, name, valueRegex=".") {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
["config", "--local", "--unset", name, valueRegex],
|
||||
true
|
||||
);
|
||||
return result.exitCode === 0;
|
||||
}
|
||||
|
||||
async function configOptionExists(repoPath, name, valueRegex=".") {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
["config", "--local", "--name-only", "--get-regexp", name, valueRegex],
|
||||
true
|
||||
);
|
||||
return result.exitCode === 0;
|
||||
}
|
||||
|
||||
async function getConfigOption(repoPath, name, valueRegex=".") {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
["config", "--local", "--get-regexp", name, valueRegex],
|
||||
true
|
||||
);
|
||||
const option = result.stdout.trim().split(`${name} `);
|
||||
return {
|
||||
name: name,
|
||||
value: option[1]
|
||||
}
|
||||
}
|
||||
|
||||
async function getAndUnsetConfigOption(repoPath, name, valueRegex=".") {
|
||||
if (await configOptionExists(repoPath, name, valueRegex)) {
|
||||
const option = await getConfigOption(repoPath, name, valueRegex);
|
||||
if (await unsetConfigOption(repoPath, name, valueRegex)) {
|
||||
core.debug(`Unset config option '${name}'`);
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getRepoPath,
|
||||
execGit,
|
||||
addConfigOption,
|
||||
unsetConfigOption,
|
||||
configOptionExists,
|
||||
getConfigOption,
|
||||
getAndUnsetConfigOption
|
||||
};
|
@ -1,98 +0,0 @@
|
||||
const path = require("path");
|
||||
const {
|
||||
getRepoPath,
|
||||
execGit,
|
||||
addConfigOption,
|
||||
unsetConfigOption,
|
||||
configOptionExists,
|
||||
getConfigOption,
|
||||
getAndUnsetConfigOption
|
||||
} = require("./git");
|
||||
|
||||
test("getRepoPath", async () => {
|
||||
expect(getRepoPath()).toEqual(process.env["GITHUB_WORKSPACE"]);
|
||||
expect(getRepoPath("foo")).toEqual(
|
||||
path.resolve(process.env["GITHUB_WORKSPACE"], "foo")
|
||||
);
|
||||
});
|
||||
|
||||
test("execGit", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
["config", "--local", "--name-only", "--get-regexp", "remote.origin.url"],
|
||||
true
|
||||
);
|
||||
expect(result.exitCode).toEqual(0);
|
||||
expect(result.stdout.trim()).toEqual("remote.origin.url");
|
||||
});
|
||||
|
||||
test("add and unset config option", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo");
|
||||
expect(add).toBeTruthy();
|
||||
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option");
|
||||
expect(unset).toBeTruthy();
|
||||
});
|
||||
|
||||
test("add and unset config option with value regex", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo bar");
|
||||
expect(add).toBeTruthy();
|
||||
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option", "^foo");
|
||||
expect(unset).toBeTruthy();
|
||||
});
|
||||
|
||||
test("configOptionExists returns true", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const result = await configOptionExists(repoPath, "remote.origin.url");
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
test("configOptionExists returns false", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const result = await configOptionExists(repoPath, "this.key.does.not.exist");
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
test("get config option", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.get.config.option", "foo");
|
||||
expect(add).toBeTruthy();
|
||||
const option = await getConfigOption(repoPath, "test.get.config.option");
|
||||
expect(option.value).toEqual("foo");
|
||||
const unset = await unsetConfigOption(repoPath, "test.get.config.option");
|
||||
expect(unset).toBeTruthy();
|
||||
});
|
||||
|
||||
test("get config option with value regex", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.get.config.option", "foo bar");
|
||||
expect(add).toBeTruthy();
|
||||
const option = await getConfigOption(repoPath, "test.get.config.option", "^foo");
|
||||
expect(option.value).toEqual("foo bar");
|
||||
const unset = await unsetConfigOption(repoPath, "test.get.config.option", "^foo");
|
||||
expect(unset).toBeTruthy();
|
||||
});
|
||||
|
||||
test("get and unset config option is successful", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo");
|
||||
expect(add).toBeTruthy();
|
||||
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option");
|
||||
expect(getAndUnset.value).toEqual("foo");
|
||||
});
|
||||
|
||||
test("get and unset config option is successful with value regex", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo bar");
|
||||
expect(add).toBeTruthy();
|
||||
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option", "^foo");
|
||||
expect(getAndUnset.value).toEqual("foo bar");
|
||||
});
|
||||
|
||||
test("get and unset config option is unsuccessful", async () => {
|
||||
const repoPath = getRepoPath();
|
||||
const getAndUnset = await getAndUnsetConfigOption(repoPath, "this.key.does.not.exist");
|
||||
expect(getAndUnset).toBeNull();
|
||||
});
|
121
src/git.ts
Normal file
121
src/git.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as path from 'path'
|
||||
|
||||
class GitOutput {
|
||||
stdout = ''
|
||||
exitCode = 0
|
||||
}
|
||||
|
||||
export class ConfigOption {
|
||||
name = ''
|
||||
value = ''
|
||||
}
|
||||
|
||||
export function getRepoPath(relativePath?: string): string {
|
||||
let githubWorkspacePath = process.env['GITHUB_WORKSPACE']
|
||||
if (!githubWorkspacePath) {
|
||||
throw new Error('GITHUB_WORKSPACE not defined')
|
||||
}
|
||||
githubWorkspacePath = path.resolve(githubWorkspacePath)
|
||||
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`)
|
||||
|
||||
let repoPath = githubWorkspacePath
|
||||
if (relativePath) repoPath = path.resolve(repoPath, relativePath)
|
||||
|
||||
core.debug(`repoPath: ${repoPath}`)
|
||||
return repoPath
|
||||
}
|
||||
|
||||
export async function execGit(
|
||||
repoPath: string,
|
||||
args: string[],
|
||||
ignoreReturnCode = false
|
||||
): Promise<GitOutput> {
|
||||
const result = new GitOutput()
|
||||
|
||||
const stdout: string[] = []
|
||||
const options = {
|
||||
cwd: repoPath,
|
||||
ignoreReturnCode: ignoreReturnCode,
|
||||
listeners: {
|
||||
stdout: (data: Buffer): void => {
|
||||
stdout.push(data.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.exitCode = await exec.exec('git', args, options)
|
||||
result.stdout = stdout.join('')
|
||||
return result
|
||||
}
|
||||
|
||||
export async function addConfigOption(
|
||||
repoPath: string,
|
||||
name: string,
|
||||
value: string
|
||||
): Promise<boolean> {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
['config', '--local', '--add', name, value],
|
||||
true
|
||||
)
|
||||
return result.exitCode === 0
|
||||
}
|
||||
|
||||
export async function unsetConfigOption(
|
||||
repoPath: string,
|
||||
name: string,
|
||||
valueRegex = '.'
|
||||
): Promise<boolean> {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
['config', '--local', '--unset', name, valueRegex],
|
||||
true
|
||||
)
|
||||
return result.exitCode === 0
|
||||
}
|
||||
|
||||
export async function configOptionExists(
|
||||
repoPath: string,
|
||||
name: string,
|
||||
valueRegex = '.'
|
||||
): Promise<boolean> {
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
['config', '--local', '--name-only', '--get-regexp', name, valueRegex],
|
||||
true
|
||||
)
|
||||
return result.exitCode === 0
|
||||
}
|
||||
|
||||
export async function getConfigOption(
|
||||
repoPath: string,
|
||||
name: string,
|
||||
valueRegex = '.'
|
||||
): Promise<ConfigOption> {
|
||||
const option = new ConfigOption()
|
||||
const result = await execGit(
|
||||
repoPath,
|
||||
['config', '--local', '--get-regexp', name, valueRegex],
|
||||
true
|
||||
)
|
||||
option.name = name
|
||||
option.value = result.stdout.trim().split(`${name} `)[1]
|
||||
return option
|
||||
}
|
||||
|
||||
export async function getAndUnsetConfigOption(
|
||||
repoPath: string,
|
||||
name: string,
|
||||
valueRegex = '.'
|
||||
): Promise<ConfigOption> {
|
||||
if (await configOptionExists(repoPath, name, valueRegex)) {
|
||||
const option = await getConfigOption(repoPath, name, valueRegex)
|
||||
if (await unsetConfigOption(repoPath, name, valueRegex)) {
|
||||
core.debug(`Unset config option '${name}'`)
|
||||
return option
|
||||
}
|
||||
}
|
||||
return new ConfigOption()
|
||||
}
|
118
src/index.js
118
src/index.js
@ -1,118 +0,0 @@
|
||||
const { inspect } = require("util");
|
||||
const isDocker = require("is-docker");
|
||||
const core = require("@actions/core");
|
||||
const exec = require("@actions/exec");
|
||||
const setupPython = require("./setup-python");
|
||||
const {
|
||||
getRepoPath,
|
||||
getAndUnsetConfigOption,
|
||||
addConfigOption
|
||||
} = require("./git");
|
||||
|
||||
const EXTRAHEADER_OPTION = "http.https://github.com/.extraheader";
|
||||
const EXTRAHEADER_VALUE_REGEX = "^AUTHORIZATION:";
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
// Allows ncc to find assets to be included in the distribution
|
||||
const cpr = __dirname + "/cpr";
|
||||
core.debug(`cpr: ${cpr}`);
|
||||
|
||||
// Determine how to access python and pip
|
||||
const { pip, python } = (function() {
|
||||
if (isDocker()) {
|
||||
core.info("Running inside a Docker container");
|
||||
// Python 3 assumed to be installed and on the PATH
|
||||
return {
|
||||
pip: "pip3",
|
||||
python: "python3"
|
||||
};
|
||||
} else {
|
||||
// Setup Python from the tool cache
|
||||
setupPython("3.x", "x64");
|
||||
return {
|
||||
pip: "pip",
|
||||
python: "python"
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
// Install requirements
|
||||
await exec.exec(pip, [
|
||||
"install",
|
||||
"--requirement",
|
||||
`${cpr}/requirements.txt`,
|
||||
"--no-index",
|
||||
`--find-links=${__dirname}/vendor`
|
||||
]);
|
||||
|
||||
// Fetch action inputs
|
||||
const inputs = {
|
||||
token: core.getInput("token"),
|
||||
path: core.getInput("path"),
|
||||
commitMessage: core.getInput("commit-message"),
|
||||
committer: core.getInput("committer"),
|
||||
author: core.getInput("author"),
|
||||
title: core.getInput("title"),
|
||||
body: core.getInput("body"),
|
||||
labels: core.getInput("labels"),
|
||||
assignees: core.getInput("assignees"),
|
||||
reviewers: core.getInput("reviewers"),
|
||||
teamReviewers: core.getInput("team-reviewers"),
|
||||
milestone: core.getInput("milestone"),
|
||||
project: core.getInput("project"),
|
||||
projectColumn: core.getInput("project-column"),
|
||||
branch: core.getInput("branch"),
|
||||
base: core.getInput("base"),
|
||||
branchSuffix: core.getInput("branch-suffix")
|
||||
};
|
||||
core.debug(`Inputs: ${inspect(inputs)}`);
|
||||
|
||||
// Set environment variables from inputs.
|
||||
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
|
||||
if (inputs.path) process.env.CPR_PATH = inputs.path;
|
||||
if (inputs.commitMessage) process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
|
||||
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer;
|
||||
if (inputs.author) process.env.CPR_AUTHOR = inputs.author;
|
||||
if (inputs.title) process.env.CPR_TITLE = inputs.title;
|
||||
if (inputs.body) process.env.CPR_BODY = inputs.body;
|
||||
if (inputs.labels) process.env.CPR_LABELS = inputs.labels;
|
||||
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees;
|
||||
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers;
|
||||
if (inputs.teamReviewers) process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
|
||||
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone;
|
||||
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
|
||||
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
|
||||
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
|
||||
if (inputs.base) process.env.CPR_BASE = inputs.base;
|
||||
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
|
||||
|
||||
// Get the repository path
|
||||
var repoPath = getRepoPath(inputs.path);
|
||||
// Get the extraheader config option if it exists
|
||||
var extraHeaderOption = await getAndUnsetConfigOption(
|
||||
repoPath,
|
||||
EXTRAHEADER_OPTION,
|
||||
EXTRAHEADER_VALUE_REGEX
|
||||
);
|
||||
|
||||
// Execute create pull request
|
||||
await exec.exec(python, [`${cpr}/create_pull_request.py`]);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
} finally {
|
||||
// Restore the extraheader config option
|
||||
if (extraHeaderOption) {
|
||||
if (
|
||||
await addConfigOption(
|
||||
repoPath,
|
||||
EXTRAHEADER_OPTION,
|
||||
extraHeaderOption.value
|
||||
)
|
||||
)
|
||||
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
22
src/isDocker.ts
Normal file
22
src/isDocker.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import * as fs from 'fs'
|
||||
|
||||
function hasDockerEnv(): boolean {
|
||||
try {
|
||||
fs.statSync('/.dockerenv')
|
||||
return true
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function hasDockerCGroup(): boolean {
|
||||
try {
|
||||
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker')
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function isDocker(): boolean {
|
||||
return hasDockerEnv() || hasDockerCGroup()
|
||||
}
|
129
src/main.ts
Normal file
129
src/main.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import {isDocker} from './isDocker'
|
||||
import {setupPython} from './setupPython'
|
||||
import {
|
||||
ConfigOption,
|
||||
getRepoPath,
|
||||
getAndUnsetConfigOption,
|
||||
addConfigOption
|
||||
} from './git'
|
||||
import {inspect} from 'util'
|
||||
|
||||
const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader'
|
||||
const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
let repoPath
|
||||
let extraHeaderOption = new ConfigOption()
|
||||
try {
|
||||
// Python assets
|
||||
const cpr = `${__dirname}/cpr`
|
||||
core.debug(`cpr: ${cpr}`)
|
||||
|
||||
// Determine how to access python and pip
|
||||
const {pip, python} = (function (): {pip: string; python: string} {
|
||||
if (isDocker()) {
|
||||
core.info('Running inside a Docker container')
|
||||
// Python 3 assumed to be installed and on the PATH
|
||||
return {
|
||||
pip: 'pip3',
|
||||
python: 'python3'
|
||||
}
|
||||
} else {
|
||||
// Setup Python from the tool cache
|
||||
setupPython('3.x', 'x64')
|
||||
return {
|
||||
pip: 'pip',
|
||||
python: 'python'
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
||||
// Install requirements
|
||||
await exec.exec(pip, [
|
||||
'install',
|
||||
'--requirement',
|
||||
`${cpr}/requirements.txt`,
|
||||
'--no-index',
|
||||
`--find-links=${__dirname}/vendor`
|
||||
])
|
||||
|
||||
// Fetch action inputs
|
||||
const inputs = {
|
||||
token: core.getInput('token'),
|
||||
path: core.getInput('path'),
|
||||
commitMessage: core.getInput('commit-message'),
|
||||
committer: core.getInput('committer'),
|
||||
author: core.getInput('author'),
|
||||
title: core.getInput('title'),
|
||||
body: core.getInput('body'),
|
||||
labels: core.getInput('labels'),
|
||||
assignees: core.getInput('assignees'),
|
||||
reviewers: core.getInput('reviewers'),
|
||||
teamReviewers: core.getInput('team-reviewers'),
|
||||
milestone: core.getInput('milestone'),
|
||||
project: core.getInput('project'),
|
||||
projectColumn: core.getInput('project-column'),
|
||||
draft: core.getInput('draft'),
|
||||
branch: core.getInput('branch'),
|
||||
requestToParent: core.getInput('request-to-parent'),
|
||||
base: core.getInput('base'),
|
||||
branchSuffix: core.getInput('branch-suffix')
|
||||
}
|
||||
core.debug(`Inputs: ${inspect(inputs)}`)
|
||||
|
||||
// Set environment variables from inputs.
|
||||
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token
|
||||
if (inputs.path) process.env.CPR_PATH = inputs.path
|
||||
if (inputs.commitMessage)
|
||||
process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage
|
||||
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer
|
||||
if (inputs.author) process.env.CPR_AUTHOR = inputs.author
|
||||
if (inputs.title) process.env.CPR_TITLE = inputs.title
|
||||
if (inputs.body) process.env.CPR_BODY = inputs.body
|
||||
if (inputs.labels) process.env.CPR_LABELS = inputs.labels
|
||||
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees
|
||||
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers
|
||||
if (inputs.teamReviewers)
|
||||
process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers
|
||||
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone
|
||||
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project
|
||||
if (inputs.projectColumn)
|
||||
process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn
|
||||
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft
|
||||
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch
|
||||
if (inputs.requestToParent)
|
||||
process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent
|
||||
if (inputs.base) process.env.CPR_BASE = inputs.base
|
||||
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix
|
||||
|
||||
// Get the repository path
|
||||
repoPath = getRepoPath(inputs.path)
|
||||
// Get the extraheader config option if it exists
|
||||
extraHeaderOption = await getAndUnsetConfigOption(
|
||||
repoPath,
|
||||
EXTRAHEADER_OPTION,
|
||||
EXTRAHEADER_VALUE_REGEX
|
||||
)
|
||||
|
||||
// Execute create pull request
|
||||
await exec.exec(python, [`${cpr}/create_pull_request.py`])
|
||||
} catch (error) {
|
||||
core.setFailed(error.message)
|
||||
} finally {
|
||||
// Restore the extraheader config option
|
||||
if (extraHeaderOption.value != '') {
|
||||
if (
|
||||
await addConfigOption(
|
||||
repoPath,
|
||||
EXTRAHEADER_OPTION,
|
||||
extraHeaderOption.value
|
||||
)
|
||||
)
|
||||
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
@ -1,52 +0,0 @@
|
||||
const core = require("@actions/core");
|
||||
const tc = require("@actions/tool-cache");
|
||||
const path = require("path");
|
||||
const semver = require("semver");
|
||||
|
||||
/**
|
||||
* Setup for Python from the GitHub Actions tool cache
|
||||
* Converted from https://github.com/actions/setup-python
|
||||
*
|
||||
* @param {string} versionSpec version of Python
|
||||
* @param {string} arch architecture (x64|x32)
|
||||
*/
|
||||
let setupPython = function(versionSpec, arch) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const IS_WINDOWS = process.platform === "win32";
|
||||
|
||||
// Find the version of Python we want in the tool cache
|
||||
const installDir = tc.find("Python", versionSpec, arch);
|
||||
core.debug(`installDir: ${installDir}`);
|
||||
|
||||
// Set paths
|
||||
core.exportVariable("pythonLocation", installDir);
|
||||
core.addPath(installDir);
|
||||
if (IS_WINDOWS) {
|
||||
core.addPath(path.join(installDir, "Scripts"));
|
||||
} else {
|
||||
core.addPath(path.join(installDir, "bin"));
|
||||
}
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
// Add --user directory
|
||||
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
|
||||
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
|
||||
const version = path.basename(path.dirname(installDir));
|
||||
const major = semver.major(version);
|
||||
const minor = semver.minor(version);
|
||||
|
||||
const userScriptsDir = path.join(
|
||||
process.env["APPDATA"] || "",
|
||||
"Python",
|
||||
`Python${major}${minor}`,
|
||||
"Scripts"
|
||||
);
|
||||
core.addPath(userScriptsDir);
|
||||
}
|
||||
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
|
||||
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = setupPython;
|
50
src/setupPython.ts
Normal file
50
src/setupPython.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as tc from '@actions/tool-cache'
|
||||
import * as path from 'path'
|
||||
import * as semver from 'semver'
|
||||
|
||||
/**
|
||||
* Setup for Python from the GitHub Actions tool cache
|
||||
* Converted from https://github.com/actions/setup-python
|
||||
*
|
||||
* @param {string} versionSpec version of Python
|
||||
* @param {string} arch architecture (x64|x32)
|
||||
*/
|
||||
export function setupPython(versionSpec: string, arch: string): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
|
||||
// Find the version of Python we want in the tool cache
|
||||
const installDir = tc.find('Python', versionSpec, arch)
|
||||
core.debug(`installDir: ${installDir}`)
|
||||
|
||||
// Set paths
|
||||
core.exportVariable('pythonLocation', installDir)
|
||||
core.addPath(installDir)
|
||||
if (IS_WINDOWS) {
|
||||
core.addPath(path.join(installDir, 'Scripts'))
|
||||
} else {
|
||||
core.addPath(path.join(installDir, 'bin'))
|
||||
}
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
// Add --user directory
|
||||
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
|
||||
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
|
||||
const version = path.basename(path.dirname(installDir))
|
||||
const major = semver.major(version)
|
||||
const minor = semver.minor(version)
|
||||
|
||||
const userScriptsDir = path.join(
|
||||
process.env['APPDATA'] || '',
|
||||
'Python',
|
||||
`Python${major}${minor}`,
|
||||
'Scripts'
|
||||
)
|
||||
core.addPath(userScriptsDir)
|
||||
}
|
||||
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
|
||||
|
||||
resolve()
|
||||
})
|
||||
}
|
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["__test__", "lib", "node_modules"]
|
||||
}
|
Reference in New Issue
Block a user