Compare commits

..

127 Commits

Author SHA1 Message Date
305373e8f3 Follow the python minor version 2020-01-17 17:56:13 +09:00
04bf3d439a Update Python to version 3.8.1 2020-01-17 16:03:01 +09:00
ec6352b0a0 Merge pull request #85 from peter-evans/dev
Minor refactor to set url via git params
2019-12-08 16:30:10 +09:00
ce4df54075 Bump version 2019-12-08 16:28:43 +09:00
c855a500d1 Add clean slash command 2019-12-08 15:36:00 +09:00
baf52378ae Minor refactor to set url via git params 2019-12-08 15:02:54 +09:00
e6ebd7ca5c Merge pull request #83 from peter-evans/dev
Add inputs for committer-name and committer-email
2019-12-06 19:17:09 +09:00
83fef4e8a1 Update README 2019-12-06 18:36:27 +09:00
d3dc225920 Add inputs for committer-name and committer-email 2019-12-06 17:06:49 +09:00
6342438c4e Updated README 2019-12-05 18:28:50 +09:00
324fe6cdde Add slash command dispatch workflow 2019-12-03 19:50:15 +09:00
4faa5d5a97 Update README 2019-11-24 09:28:14 +09:00
381bc30cef Update example screenshot 2019-11-24 09:14:05 +09:00
7531167f24 Merge pull request #76 from peter-evans/dev
Add feature to create project card for pull request
2019-11-24 09:04:44 +09:00
66a1436815 Update input descriptions 2019-11-24 09:00:31 +09:00
1d1fedd99c Add feature to create project card for pull request 2019-11-24 08:48:32 +09:00
823751817d Update examples 2019-11-16 10:19:03 +09:00
1edcf07a19 Update examples 2019-11-16 10:17:29 +09:00
4c95214a9b Update README 2019-11-16 09:27:21 +09:00
b37c0a038c Update input description 2019-11-16 09:26:07 +09:00
d9841567d1 Update README 2019-11-16 09:25:06 +09:00
2cce94bfb0 Bump version 2019-11-16 09:25:00 +09:00
d968e8b11b Add warning and fail gracefully when ref is invalid for base 2019-11-16 09:24:46 +09:00
6c73093f9b Merge pull request #74 from peter-evans/renovate/gitpython-3.x
Update dependency GitPython to v3.0.5
2019-11-15 19:46:46 +09:00
d17c882ef3 Update examples 2019-11-15 08:27:12 +09:00
d5f4e48a66 Update dependency GitPython to v3.0.5 2019-11-14 01:46:43 +00:00
484d8bd85d Merge pull request #72 from peter-evans/dev
Logging and handling of PR events from forks
2019-11-13 23:59:38 +09:00
74b6a9337d Update documentation 2019-11-13 23:52:33 +09:00
2dd62d446e Bump version 2019-11-13 19:10:53 +09:00
b6a98c049d Add logging and handling for pr events from forks 2019-11-13 19:10:38 +09:00
67e8822279 Update examples 2019-11-13 11:05:55 +09:00
956a240181 Update examples 2019-11-11 22:49:11 +09:00
179aca65d7 Update examples 2019-11-11 22:45:23 +09:00
e4c8b68e33 Update dockerhub-description workflow 2019-11-10 22:08:30 +09:00
731211fd81 Fix bug with filtering pull requests 2019-11-10 18:14:10 +09:00
006313b45a Fix bug when updating a pull request 2019-11-10 16:56:55 +09:00
3c86e9a421 Add outputs description 2019-11-10 13:07:11 +09:00
e49ebca896 Merge pull request #69 from peter-evans/renovate/pin-dependencies
Pin dependency @zeit/ncc to 0.20.5
2019-11-09 23:36:02 +09:00
d9652cf06a Pin dependency @zeit/ncc to 0.20.5 2019-11-09 14:06:18 +00:00
4517bf7ce3 Merge pull request #68 from peter-evans/dev
Convert to hybrid multi-platfrom
2019-11-09 23:06:00 +09:00
04aa84a2af Update examples 2019-11-09 22:48:30 +09:00
11baa5dc07 Update examples 2019-11-09 22:46:01 +09:00
1281ebd51a Update README 2019-11-09 18:22:57 +09:00
46dc4f23d5 Update workflows 2019-11-09 18:22:03 +09:00
d469aaf0ef Update workflows 2019-11-09 17:59:23 +09:00
5692e041c6 Set a step output 2019-11-09 17:42:11 +09:00
55e7b1ec28 Update action to hybrid multi platform 2019-11-09 17:24:47 +09:00
d99b58f9d5 Merge pull request #67 from peter-evans/renovate/pygithub-1.x
Update dependency PyGithub to v1.44.1
2019-11-08 20:31:06 +09:00
b8ce455e56 Update dependency PyGithub to v1.44.1 2019-11-07 03:57:40 +00:00
c9e477ec05 Update examples 2019-11-05 14:10:23 +09:00
979d417e9d Update examples 2019-11-05 13:23:16 +09:00
b74a77cefc Update examples 2019-11-04 12:19:19 +09:00
2af7d9797a Update documentation 2019-11-04 11:13:18 +09:00
b72489d629 Update image version 2019-11-04 11:08:47 +09:00
1461de7c9d Update README 2019-11-04 11:01:08 +09:00
3061b7bc6e Update workflows 2019-11-04 11:01:00 +09:00
98ee7d63d3 Improvements to updating pull requests 2019-11-04 11:00:38 +09:00
066b4398c0 Merge pull request #66 from staabm/patch-2
Link ::set-output
2019-11-03 18:42:49 +09:00
028e1bbdd5 Link ::set-output 2019-11-03 10:38:30 +01:00
8b8594e5e4 Update examples 2019-11-03 18:29:46 +09:00
cefb562076 Merge pull request #63 from peter-evans/documentation
Update documentation
2019-11-03 17:46:08 +09:00
9eccdd1603 Update README 2019-11-03 17:44:22 +09:00
f429dfef59 Update examples 2019-11-03 17:41:42 +09:00
963e38fd7d Add examples documentation 2019-11-03 17:37:39 +09:00
f411b5902d Merge pull request #62 from peter-evans/asset-location
Update location of assets
2019-11-03 15:47:02 +09:00
97dd1f3ef4 Update location of assets 2019-11-03 15:46:11 +09:00
3413a77ac7 Update README 2019-10-30 16:10:02 +09:00
206756cd93 Update image version 2019-10-30 16:04:28 +09:00
263b5927d1 Remove ignore event logic 2019-10-30 15:27:54 +09:00
a0ad81c6c7 Merge pull request #58 from peter-evans/renovate/gitpython-3.x
Update dependency GitPython to v3.0.4
2019-10-29 13:31:52 +09:00
23846c7f83 Update dependency GitPython to v3.0.4 2019-10-22 11:43:55 +00:00
96ac64ddca Update README 2019-10-22 11:05:42 +09:00
a2ed0052e5 Update image version 2019-10-22 11:01:54 +09:00
6e7e889e01 Minor fixes and refactor 2019-10-22 10:55:33 +09:00
7e18a60b72 Merge pull request #57 from peter-evans/renovate/docker-alpine-3.x
Update alpine Docker tag to v3.10.3
2019-10-22 10:53:31 +09:00
0be4e396cf Update alpine Docker tag to v3.10.3 2019-10-21 17:57:06 +00:00
b86bbce924 Update README 2019-10-21 20:36:01 +09:00
e1e9dd3f1c Update image version 2019-10-21 20:32:02 +09:00
8c2a43987b Add an override for the base branch 2019-10-21 20:17:31 +09:00
c5ff844b40 Update README 2019-10-21 18:42:39 +09:00
1f47cf3861 Update workflows 2019-10-21 18:31:14 +09:00
bcdc7ae6f9 Merge pull request #55 from peter-evans/renovate/pygithub-1.x
Update dependency PyGithub to v1.44
2019-10-19 22:58:42 +09:00
91ca84eab5 Update dependency PyGithub to v1.44 2019-10-19 08:44:24 +00:00
875d189c30 Update README 2019-10-14 18:09:59 +09:00
7c3f5f4833 Update README 2019-10-14 16:12:27 +09:00
7a7e797068 Update README 2019-10-14 16:11:09 +09:00
a41f37fc96 Update README 2019-10-14 16:09:58 +09:00
10554ac6c3 Update README 2019-10-14 15:59:21 +09:00
2439726cfe Update README 2019-10-14 15:51:08 +09:00
4f04f4efd9 Update workflows 2019-10-14 15:50:52 +09:00
32d0abbc7c Update README 2019-10-14 15:07:11 +09:00
ed5b8b1eea Update README 2019-10-14 12:38:52 +09:00
ea241dfc79 Update README 2019-10-14 12:37:36 +09:00
0e70fec054 Update README 2019-10-14 12:36:55 +09:00
5077e8d6bd Rename dockerhub description workflow 2019-10-14 10:26:25 +09:00
901e854f30 Update README 2019-10-14 02:02:55 +09:00
f3b1bd6331 Update image version 2019-10-14 01:58:42 +09:00
51ade9f54b Fix for pull refs 2019-10-14 01:39:53 +09:00
3c86dbf9e6 Update README 2019-10-06 15:13:32 +09:00
b2d426ea4e Update README 2019-10-06 15:06:49 +09:00
fbe0cd3d1a Update README 2019-10-06 14:59:45 +09:00
5f9821866a Update workflows 2019-10-06 14:52:15 +09:00
ee153ec8cf Update image version 2019-10-06 14:52:01 +09:00
e138d84114 Add variables to override the commit author name and email 2019-10-06 14:38:15 +09:00
90843d3c39 Update README 2019-10-05 09:22:43 +09:00
90ad96bd01 Update workflows 2019-10-05 09:22:35 +09:00
f8cc05d28d Update README 2019-10-04 14:53:58 +09:00
fe78afb6d7 Update README 2019-10-04 14:46:26 +09:00
af7dbce93d Merge remote-tracking branch 'origin/master' 2019-10-04 14:36:11 +09:00
2e283eddc6 Add workflow to automatically update dockerhub description 2019-10-04 14:35:58 +09:00
3e0a17d097 Update action to use pre-built container 2019-10-04 14:35:22 +09:00
7ebddff547 Merge pull request #52 from peter-evans/renovate/gitpython-3.x
Update dependency GitPython to v3.0.3
2019-10-04 14:30:27 +09:00
1397aded03 Update dependency GitPython to v3.0.3 2019-10-02 19:31:01 +00:00
40fd4990fc Update README 2019-10-02 22:38:58 +09:00
5784478398 Update README 2019-10-02 19:28:30 +09:00
6e9abd8a8d Add action.yml 2019-10-02 19:20:07 +09:00
ef76e27efb Replace fixed-name branch rebase with stash merge 2019-10-02 19:05:46 +09:00
6be23859c3 Update README 2019-09-30 23:24:16 +09:00
aa09d77c75 Update README
Update README


Update README


Update README
2019-09-30 19:16:55 +09:00
b86b066e8c Update README 2019-09-30 18:58:24 +09:00
7556cef424 Update workflows 2019-09-30 18:57:49 +09:00
ff7ec1c208 Fixed branch, random suffix and output pr number 2019-09-30 18:57:37 +09:00
6f333b4ebc Update README 2019-09-30 10:08:06 +09:00
65682597a6 Update workflows 2019-09-30 10:07:58 +09:00
fc9f1a6380 Update image 2019-09-26 19:06:44 +09:00
4bb662aed6 Update README 2019-09-26 19:03:42 +09:00
a5c1d5b56d Update README 2019-09-26 18:19:51 +09:00
44 changed files with 6139 additions and 1703 deletions

View File

@ -1,7 +1,7 @@
name: Create Pull Request All Platforms
on:
repository_dispatch:
types: [create-pull-request-multi]
name: create-pull-request workflow
jobs:
createPullRequest:
name: Testing on ${{ matrix.platform }}
@ -10,23 +10,37 @@ jobs:
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v1
- name: Create report file
if: matrix.platform == 'ubuntu-latest' || matrix.platform == 'macos-latest'
run: touch report.txt
- name: Create report file (windows)
if: matrix.platform == 'windows-latest'
run: type NUL > report.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@multi-platform-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_MESSAGE: Add report file
PULL_REQUEST_BODY: This PR is auto-generated by [create-pull-request](https://github.com/peter-evans/create-pull-request).
PULL_REQUEST_TITLE: '[Example] Add report file'
PULL_REQUEST_LABELS: report, automated pr
PULL_REQUEST_ASSIGNEES: peter-evans
PULL_REQUEST_REVIEWERS: peter-evans
PULL_REQUEST_MILESTONE: 1
PULL_REQUEST_BRANCH: example-patches
BRANCH_SUFFIX: 'timestamp'
- uses: actions/checkout@v1
- name: Create report file
if: matrix.platform == 'ubuntu-latest' || matrix.platform == 'macos-latest'
run: date +%s > report.txt
- name: Create report file (windows)
if: matrix.platform == 'windows-latest'
run: echo %DATE% %TIME% > report.txt
- name: Create Pull Request
id: cpr
uses: ./
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Add report file
author-email: peter-evans@users.noreply.github.com
author-name: Peter Evans
title: '[Example] Add report file'
body: |
New report
- Contains *today's* date
- Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
labels: report, automated pr
assignees: peter-evans
reviewers: peter-evans
milestone: 1
project: Example Project
project-column: To do
branch: example-patches
branch-suffix: random
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"

View File

@ -1,24 +1,38 @@
name: Create Pull Request
on:
repository_dispatch:
types: [create-pull-request]
name: create-pull-request workflow
jobs:
createPullRequest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Create report file
run: touch report.txt
- name: Create Pull Request
uses: ./
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_MESSAGE: Add report file
PULL_REQUEST_BODY: This PR is auto-generated by [create-pull-request](https://github.com/peter-evans/create-pull-request).
PULL_REQUEST_TITLE: '[Example] Add report file'
PULL_REQUEST_LABELS: report, automated pr
PULL_REQUEST_ASSIGNEES: peter-evans
PULL_REQUEST_REVIEWERS: peter-evans
PULL_REQUEST_MILESTONE: 1
PULL_REQUEST_BRANCH: example-patches
BRANCH_SUFFIX: short-commit-hash
- uses: actions/checkout@v1
- 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
author-email: peter-evans@users.noreply.github.com
author-name: Peter Evans
title: '[Example] Add report file'
body: |
New report
- Contains *today's* date
- Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
labels: report, automated pr
assignees: peter-evans
reviewers: peter-evans
milestone: 1
project: Example Project
project-column: To do
branch: example-patches
branch-suffix: short-commit-hash
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"

View File

@ -0,0 +1,19 @@
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

View File

@ -0,0 +1,16 @@
name: Slash Command Dispatch
on:
issue_comment:
types: [created]
jobs:
slashCommandDispatch:
runs-on: ubuntu-latest
steps:
- name: Slash Command Dispatch
uses: peter-evans/slash-command-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
commands: test, clean
permission: admin
repository: peter-evans/create-pull-request-tests

1
.gitignore vendored
View File

@ -1 +1,2 @@
node_modules
.DS_Store

View File

@ -1,20 +0,0 @@
FROM alpine:3.10.2
LABEL maintainer="Peter Evans <mail@peterevans.dev>"
LABEL repository="https://github.com/peter-evans/create-pull-request"
LABEL homepage="https://github.com/peter-evans/create-pull-request"
LABEL com.github.actions.name="Create Pull Request"
LABEL com.github.actions.description="Creates a pull request for changes to your repository in the actions workspace"
LABEL com.github.actions.icon="git-pull-request"
LABEL com.github.actions.color="gray-dark"
COPY LICENSE README.md /
RUN apk add python3-dev git git-lfs
COPY requirements.txt /tmp/
RUN pip3 install --requirement /tmp/requirements.txt
COPY create-pull-request.py /create-pull-request.py
ENTRYPOINT [ "/create-pull-request.py" ]

188
README.md
View File

@ -1,4 +1,4 @@
# Create Pull Request
# <img width="24" height="24" src="assets/logo.svg"> Create Pull Request
[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-Create%20Pull%20Request-blue.svg?colorA=24292e&colorB=0366d6&style=flat&longCache=true&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAM6wAADOsB5dZE0gAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAERSURBVCiRhZG/SsMxFEZPfsVJ61jbxaF0cRQRcRJ9hlYn30IHN/+9iquDCOIsblIrOjqKgy5aKoJQj4O3EEtbPwhJbr6Te28CmdSKeqzeqr0YbfVIrTBKakvtOl5dtTkK+v4HfA9PEyBFCY9AGVgCBLaBp1jPAyfAJ/AAdIEG0dNAiyP7+K1qIfMdonZic6+WJoBJvQlvuwDqcXadUuqPA1NKAlexbRTAIMvMOCjTbMwl1LtI/6KWJ5Q6rT6Ht1MA58AX8Apcqqt5r2qhrgAXQC3CZ6i1+KMd9TRu3MvA3aH/fFPnBodb6oe6HM8+lYHrGdRXW8M9bMZtPXUji69lmf5Cmamq7quNLFZXD9Rq7v0Bpc1o/tp0fisAAAAASUVORK5CYII=)](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.
@ -10,109 +10,153 @@ The changes will be automatically committed to a new branch and a pull request c
Create Pull Request action will:
1. Check for repository changes in the Actions workspace. This includes untracked (new) files as well as modified files.
2. Commit all changes to a new branch. The commit will be made using the name and email of the `HEAD` commit author.
2. Commit all changes to a new branch, or update an existing pull request branch.
3. Create a pull request to merge the new branch into the currently active branch executing the workflow.
Note: Modifying a repository during workflows is not good practice in general.
However, this action opens up some interesting possibilities when used carefully.
This action is experimental and may not work well for some use cases.
## Usage
Linux
See [examples](examples.md) for detailed use cases.
```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1.3.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
Multi platform - Linux, MacOS, Windows (beta)
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v1.x.x`
**Note**: If you want pull requests created by this action to trigger an `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`.
See [this issue](https://github.com/peter-evans/create-pull-request/issues/48) for further details.
### Action inputs
These inputs are *all optional*. If not set, sensible default values will be used.
| Name | Description | Default |
| --- | --- | --- |
| `commit-message` | The message to use when committing changes. | `Auto-committed changes by create-pull-request action` |
| `author-name` | The name of the commit author. | For `push` events, the HEAD commit author. Otherwise, <GITHUB_ACTOR>, the GitHub user that initiated the event. |
| `author-email` | The email address of the commit author. | For `push` events, the HEAD commit author. Otherwise, <GITHUB_ACTOR>@users.noreply.github.com, where `GITHUB_ACTOR` is the GitHub user that initiated the event. |
| `committer-name` | The name of the committer. | Defaults to match `author-name` |
| `committer-email` | The email address of the committer. | Defaults to match `author-email` |
| `title` | The title of the pull request. | `Auto-generated by create-pull-request action` |
| `body` | The body of the pull request. | `Auto-generated pull request by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action` |
| `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. | |
| `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** below for details. | `create-pull-request/patch` |
| `base` | Sets the pull request base branch. | Defaults to the currently checked out branch, `GITHUB_REF`. For `pull_request` events, `GITHUB_HEAD_REF` |
| `branch-suffix` | The branch suffix type. Valid values are `short-commit-hash`, `timestamp`, `random` and `none`. See **Branch naming** below for details. | `short-commit-hash` |
**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.
```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1.2.1-multi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v1
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 }}"
```
#### Environment variables
### Branch naming
These variables are all optional. If not set, a default value will be used.
For branch naming there are two strategies. Always create a new branch each time there are changes to be committed, OR, create a fixed-name pull request branch that will be updated with any new commits until it is merged or closed.
- `COMMIT_MESSAGE` - The message to use when committing changes.
- `PULL_REQUEST_TITLE` - The title of the pull request.
- `PULL_REQUEST_BODY` - The body of the pull request.
- `PULL_REQUEST_LABELS` - A comma separated list of labels.
- `PULL_REQUEST_ASSIGNEES` - A comma separated list of assignees (GitHub usernames).
- `PULL_REQUEST_REVIEWERS` - A comma separated list of reviewers (GitHub usernames) to request a review from.
- `PULL_REQUEST_TEAM_REVIEWERS` - A comma separated list of GitHub teams to request a review from.
- `PULL_REQUEST_MILESTONE` - The number of the milestone to associate this pull request with.
- `PULL_REQUEST_BRANCH` - The branch name. See **Branch naming** below for details.
- `BRANCH_SUFFIX` - The branch suffix type. Valid values are `short-commit-hash` (default) and `timestamp`. See **Branch naming** below for details.
#### Strategy A - Always create a new pull request branch (default)
The following parameters are available for debugging and troubleshooting.
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`.
- `DEBUG_EVENT` - If present, outputs the event data that triggered the workflow.
- `SKIP_IGNORE` - If present, the `ignore_event` function will be skipped.
- `short-commit-hash` (default) - Commits will be made to a branch suffixed with the short SHA1 commit hash. e.g. `create-pull-request/patch-fcdfb59`, `create-pull-request/patch-394710b`
#### Branch naming
- `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552`
The variable `PULL_REQUEST_BRANCH` defaults to `create-pull-request/patch`.
Commits will be made to a branch with this name and suffixed with the short SHA1 commit hash.
- `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`
e.g.
```
create-pull-request/patch-fcdfb59
create-pull-request/patch-394710b
```
#### Strategy B - Create and update a pull request branch
Alternatively, branches can be suffixed with a timestamp by setting the environment variable `BRANCH_SUFFIX` to the value `timestamp`. This option must be used if multiple pull requests will be created during the execution of a workflow.
To use this strategy, set `branch-suffix` to the value `none`. The input `branch` defaults to `create-pull-request/patch`. Commits will be made 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.
e.g.
```
create-pull-request/patch-1569322532
create-pull-request/patch-1569322552
```
#### Ignoring files
### Ignoring files
If there are files or directories you want to ignore you can simply add them to a `.gitignore` file at the root of your repository. The action will respect this file.
## Example
### Commit as github-actions[bot]
Here is an example that sets all the main environment variables.
You can make commits that appear to be made by the GitHub Actions bot as follows.
```yml
on:
repository_dispatch:
types: [create-pull-request]
name: create-pull-request workflow
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
author-name: github-actions[bot]
author-email: 41898282+github-actions[bot]@users.noreply.github.com
committer-name: GitHub
committer-email: noreply@github.com
```
## Reference Example
The following workflow is a reference example that sets all the main inputs.
See [examples](examples.md) for more realistic use cases.
```yml
name: Create Pull Request
on: push
jobs:
createPullRequest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Create report file
run: touch report.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1.3.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_MESSAGE: Add report file
PULL_REQUEST_BODY: This PR is auto-generated by [create-pull-request](https://github.com/peter-evans/create-pull-request).
PULL_REQUEST_TITLE: '[Example] New report'
PULL_REQUEST_LABELS: report, automated pr
PULL_REQUEST_ASSIGNEES: peter-evans
PULL_REQUEST_REVIEWERS: peter-evans
PULL_REQUEST_MILESTONE: 1
PULL_REQUEST_BRANCH: example-patches
BRANCH_SUFFIX: short-commit-hash
- uses: actions/checkout@v1
- name: Create report file
run: date +%s > report.txt
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Add report file
author-email: peter-evans@users.noreply.github.com
author-name: Peter Evans
title: '[Example] Add report file'
body: |
New report
- Contains *today's* date
- Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
labels: report, automated pr
assignees: peter-evans
reviewers: peter-evans
milestone: 1
project: Example Project
project-column: To do
branch: example-patches
branch-suffix: short-commit-hash
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
```
This configuration will create pull requests that look like this:
This reference configuration will create pull requests that look like this:
![Pull Request Example](pull-request-example.png?raw=true)
![Pull Request Example](assets/pull-request-example.png)
## License
MIT License - see the [LICENSE](LICENSE) file for details
[MIT](LICENSE)

View File

@ -1,5 +1,49 @@
name: 'Create Pull Request'
description: 'Creates a pull request for changes to your repository in the actions workspace'
inputs:
token:
description: 'The GitHub authentication token'
required: true
commit-message:
description: 'The message to use when committing changes.'
author-name:
description: 'The name of the commit author.'
author-email:
description: 'The email address of the commit author.'
committer-name:
description: 'The name of the committer.'
committer-email:
description: 'The email address of the committer.'
title:
description: 'The title of the pull request.'
body:
description: 'The body of the pull request.'
labels:
description: 'A comma separated list of labels.'
assignees:
description: 'A comma separated list of assignees (GitHub usernames).'
reviewers:
description: 'A comma separated list of reviewers (GitHub usernames) to request a review from.'
team-reviewers:
description: 'A comma separated list of GitHub teams to request a review from.'
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.'
project-column:
description: 'The name of the project column under which a card should be created.'
branch:
description: 'The pull request branch name.'
base:
description: 'Sets the pull request base branch.'
branch-suffix:
description: 'The branch suffix type.'
outputs:
pr_number:
description: 'The pull request number'
runs:
using: 'node12'
main: 'index.js'
main: 'dist/index.js'
branding:
icon: 'git-pull-request'
color: 'gray-dark'

6
assets/logo.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="43%" height="43%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color: #000000;"><title>git-pull-request</title>
<circle cx="18" cy="18" r="3"></circle>
<circle cx="6" cy="6" r="3"></circle>
<path d="M13 6h3a2 2 0 0 1 2 2v7"></path>
<line x1="6" y1="9" x2="6" y2="21"></line>
</svg>

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

View File

@ -1,184 +0,0 @@
#!/usr/bin/env python3
''' Create Pull Request '''
import json
import os
import time
from git import Repo
from github import Github
def get_github_event(github_event_path):
with open(github_event_path) as f:
github_event = json.load(f)
if bool(os.environ.get('DEBUG_EVENT')):
print(os.environ['GITHUB_EVENT_NAME'])
print(json.dumps(github_event, sort_keys=True, indent=2))
return github_event
def ignore_event(event_name, event_data):
if event_name == "push":
# Ignore push events on deleted branches
# The event we want to ignore occurs when a PR is created but the repository owner decides
# not to commit the changes. They close the PR and delete the branch. This creates a
# "push" event that we want to ignore, otherwise it will create another branch and PR on
# the same commit.
deleted = "{deleted}".format(**event_data)
if deleted == "True":
print("Ignoring delete branch event.")
return True
ref = "{ref}".format(**event_data)
if not ref.startswith('refs/heads/'):
print("Ignoring events for tags and remotes.")
return True
return False
def pr_branch_exists(repo, branch):
for ref in repo.remotes.origin.refs:
if ref.name == ("origin/%s" % branch):
return True
return False
def get_head_author(event_name, event_data):
if event_name == "push":
email = "{head_commit[author][email]}".format(**event_data)
name = "{head_commit[author][name]}".format(**event_data)
else:
email = os.environ['GITHUB_ACTOR'] + '@users.noreply.github.com'
name = os.environ['GITHUB_ACTOR']
return email, name
def get_head_short_sha1(repo):
return repo.git.rev_parse('--short', 'HEAD')
def set_git_config(git, email, name):
git.config('--global', 'user.email', '"%s"' % email)
git.config('--global', 'user.name', '"%s"' % name)
def set_git_remote_url(git, token, github_repository):
git.remote('set-url', 'origin', "https://x-access-token:%s@github.com/%s" % (token, github_repository))
def commit_changes(git, branch, commit_message):
git.checkout('HEAD', b=branch)
git.add('-A')
git.commit(m=commit_message)
return git.push('--set-upstream', 'origin', branch)
def cs_string_to_list(str):
# Split the comma separated string into a list
l = [i.strip() for i in str.split(',')]
# Remove empty strings
return list(filter(None, l))
def process_event(event_name, event_data, repo, branch, base):
# Fetch required environment variables
github_token = os.environ['GITHUB_TOKEN']
github_repository = os.environ['GITHUB_REPOSITORY']
# Fetch optional environment variables with default values
commit_message = os.getenv(
'COMMIT_MESSAGE',
"Auto-committed changes by create-pull-request action")
title = os.getenv(
'PULL_REQUEST_TITLE',
"Auto-generated by create-pull-request action")
body = os.getenv(
'PULL_REQUEST_BODY', "Auto-generated pull request by "
"[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action")
# Fetch optional environment variables with no default values
pull_request_labels = os.environ.get('PULL_REQUEST_LABELS')
pull_request_assignees = os.environ.get('PULL_REQUEST_ASSIGNEES')
pull_request_milestone = os.environ.get('PULL_REQUEST_MILESTONE')
pull_request_reviewers = os.environ.get('PULL_REQUEST_REVIEWERS')
pull_request_team_reviewers = os.environ.get('PULL_REQUEST_TEAM_REVIEWERS')
# Get the HEAD committer's email and name
author_email, author_name = get_head_author(event_name, event_data)
# Set git configuration
set_git_config(repo.git, author_email, author_name)
# Update URL for the 'origin' remote
set_git_remote_url(repo.git, github_token, github_repository)
# Commit the repository changes
print("Committing changes.")
commit_result = commit_changes(repo.git, branch, commit_message)
print(commit_result)
# Create the pull request
print("Creating a request to pull %s into %s." % (branch, base))
github_repo = Github(github_token).get_repo(github_repository)
pull_request = github_repo.create_pull(
title=title,
body=body,
base=base,
head=branch)
print("Created pull request %d." % pull_request.number)
# Set labels, assignees and milestone
if pull_request_labels is not None:
print("Applying labels")
pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels))
if pull_request_assignees is not None:
print("Applying assignees")
pull_request.as_issue().edit(assignees=cs_string_to_list(pull_request_assignees))
if pull_request_milestone is not None:
print("Applying milestone")
milestone = github_repo.get_milestone(int(pull_request_milestone))
pull_request.as_issue().edit(milestone=milestone)
# Set pull request reviewers and team reviewers
if pull_request_reviewers is not None:
print("Requesting reviewers")
pull_request.create_review_request(reviewers=cs_string_to_list(pull_request_reviewers))
if pull_request_team_reviewers is not None:
print("Requesting team reviewers")
pull_request.create_review_request(team_reviewers=cs_string_to_list(pull_request_team_reviewers))
# Get the JSON event data
event_name = os.environ['GITHUB_EVENT_NAME']
event_data = get_github_event(os.environ['GITHUB_EVENT_PATH'])
# Check if this event should be ignored
skip_ignore_event = bool(os.environ.get('SKIP_IGNORE'))
if skip_ignore_event or not ignore_event(event_name, event_data):
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Fetch/Set the branch name
branch = os.getenv('PULL_REQUEST_BRANCH', 'create-pull-request/patch')
# Set the current branch as the target base branch
base = os.environ['GITHUB_REF'][11:]
# Skip if the current branch is a PR branch created by this action
if not base.startswith(branch):
# Fetch an optional environment variable to determine the branch suffix
branch_suffix = os.getenv('BRANCH_SUFFIX', 'short-commit-hash')
if branch_suffix == "timestamp":
# Suffix with the current timestamp
branch = "%s-%s" % (branch, int(time.time()))
else:
# Suffix with the short SHA1 hash
branch = "%s-%s" % (branch, get_head_short_sha1(repo))
# Check if a PR branch already exists for this HEAD commit
if not pr_branch_exists(repo, branch):
# Check if there are changes to pull request
if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Repository has modified or untracked files.")
process_event(event_name, event_data, repo, branch, base)
else:
print("Repository has no modified or untracked files. Skipping.")
else:
print(
"Pull request branch '%s' already exists for this commit. Skipping." %
branch)
else:
print(
"Branch '%s' was created by this action. Skipping." % base)

4532
dist/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

352
dist/src/create-pull-request.py vendored Executable file
View File

@ -0,0 +1,352 @@
#!/usr/bin/env python3
""" Create Pull Request """
import json
import os
import random
import string
import sys
import time
from git import Repo
from github import Github, GithubException
def get_github_event(github_event_path):
with open(github_event_path) as f:
github_event = json.load(f)
if bool(os.environ.get("DEBUG_EVENT")):
print(os.environ["GITHUB_EVENT_NAME"])
print(json.dumps(github_event, sort_keys=True, indent=2))
return github_event
def get_head_short_sha1(repo):
return repo.git.rev_parse("--short", "HEAD")
def get_random_suffix(size=7, chars=string.ascii_lowercase + string.digits):
return "".join(random.choice(chars) for _ in range(size))
def remote_branch_exists(repo, branch):
for ref in repo.remotes.origin.refs:
if ref.name == ("origin/%s" % branch):
return True
return False
def get_author_default(event_name, event_data):
if event_name == "push":
email = "{head_commit[author][email]}".format(**event_data)
name = "{head_commit[author][name]}".format(**event_data)
else:
email = os.environ["GITHUB_ACTOR"] + "@users.noreply.github.com"
name = os.environ["GITHUB_ACTOR"]
return email, name
def get_repo_url(token, github_repository):
return "https://x-access-token:%s@github.com/%s" % (token, github_repository)
def checkout_branch(git, remote_exists, branch):
if remote_exists:
print("Checking out branch '%s'" % branch)
git.stash("--include-untracked")
git.checkout(branch)
try:
git.stash("pop")
except BaseException:
git.checkout("--theirs", ".")
git.reset()
else:
print("Creating new branch '%s'" % branch)
git.checkout("HEAD", b=branch)
def push_changes(git, token, github_repository, branch, commit_message):
git.add("-A")
git.commit(m=commit_message)
repo_url = get_repo_url(token, github_repository)
return git.push("-f", repo_url, f"HEAD:refs/heads/{branch}")
def cs_string_to_list(str):
# Split the comma separated string into a list
l = [i.strip() for i in str.split(",")]
# Remove empty strings
return list(filter(None, l))
def create_project_card(github_repo, project_name, project_column_name, pull_request):
# Locate the project by name
project = None
for project_item in github_repo.get_projects("all"):
if project_item.name == project_name:
project = project_item
break
if not project:
print("::warning::Project not found. Unable to create project card.")
return
# Locate the column by name
column = None
for column_item in project.get_columns():
if column_item.name == project_column_name:
column = column_item
break
if not column:
print("::warning::Project column not found. Unable to create project card.")
return
# Create a project card for the pull request
column.create_card(content_id=pull_request.id, content_type="PullRequest")
print(
"Added pull request #%d to project '%s' under column '%s'"
% (pull_request.number, project.name, column.name)
)
def process_event(github_token, github_repository, repo, branch, base):
# Fetch optional environment variables with default values
commit_message = os.getenv(
"COMMIT_MESSAGE", "Auto-committed changes by create-pull-request action"
)
title = os.getenv(
"PULL_REQUEST_TITLE", "Auto-generated by create-pull-request action"
)
body = os.getenv(
"PULL_REQUEST_BODY",
"Auto-generated pull request by "
"[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action",
)
# Fetch optional environment variables with no default values
pull_request_labels = os.environ.get("PULL_REQUEST_LABELS")
pull_request_assignees = os.environ.get("PULL_REQUEST_ASSIGNEES")
pull_request_milestone = os.environ.get("PULL_REQUEST_MILESTONE")
pull_request_reviewers = os.environ.get("PULL_REQUEST_REVIEWERS")
pull_request_team_reviewers = os.environ.get("PULL_REQUEST_TEAM_REVIEWERS")
project_name = os.environ.get("PROJECT_NAME")
project_column_name = os.environ.get("PROJECT_COLUMN_NAME")
# Push the local changes to the remote branch
print("Pushing changes to 'origin/%s'" % branch)
push_result = push_changes(
repo.git, github_token, github_repository, branch, commit_message
)
print(push_result)
# 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
)
print(
"Created pull request #%d (%s => %s)" % (pull_request.number, branch, base)
)
except GithubException as e:
if e.status == 422:
# Format the branch name
head_branch = "%s:%s" % (github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
print(
"Updated pull request #%d (%s => %s)"
% (pull_request.number, branch, base)
)
else:
print(str(e))
sys.exit(1)
# Set the output variables
os.system("echo ::set-env name=PULL_REQUEST_NUMBER::%d" % pull_request.number)
os.system("echo ::set-output name=pr_number::%d" % pull_request.number)
# Set labels, assignees and milestone
if pull_request_labels is not None:
print("Applying labels '%s'" % pull_request_labels)
pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels))
if pull_request_assignees is not None:
print("Applying assignees '%s'" % pull_request_assignees)
pull_request.as_issue().edit(
assignees=cs_string_to_list(pull_request_assignees)
)
if pull_request_milestone is not None:
print("Applying milestone '%s'" % pull_request_milestone)
milestone = github_repo.get_milestone(int(pull_request_milestone))
pull_request.as_issue().edit(milestone=milestone)
# Set pull request reviewers
if pull_request_reviewers is not None:
print("Requesting reviewers '%s'" % pull_request_reviewers)
try:
pull_request.create_review_request(
reviewers=cs_string_to_list(pull_request_reviewers)
)
except GithubException as e:
# Likely caused by "Review cannot be requested from pull request
# author."
if e.status == 422:
print("Requesting reviewers failed - %s" % e.data["message"])
# Set pull request team reviewers
if pull_request_team_reviewers is not None:
print("Requesting team reviewers '%s'" % pull_request_team_reviewers)
pull_request.create_review_request(
team_reviewers=cs_string_to_list(pull_request_team_reviewers)
)
# Create a project card for the pull request
if project_name is not None and project_column_name is not None:
try:
create_project_card(
github_repo, project_name, project_column_name, pull_request
)
except GithubException as e:
# Likely caused by "Project already has the associated issue."
if e.status == 422:
print(
"Create project card failed - %s" % e.data["errors"][0]["message"]
)
# Fetch environment variables
github_token = os.environ["GITHUB_TOKEN"]
github_repository = os.environ["GITHUB_REPOSITORY"]
github_ref = os.environ["GITHUB_REF"]
event_name = os.environ["GITHUB_EVENT_NAME"]
# Get the JSON event data
event_data = get_github_event(os.environ["GITHUB_EVENT_PATH"])
# Get the default for author email and name
author_email, author_name = get_author_default(event_name, event_data)
# Set author name and email overrides
author_name = os.getenv("COMMIT_AUTHOR_NAME", author_name)
author_email = os.getenv("COMMIT_AUTHOR_EMAIL", author_email)
# Set committer name and email overrides
committer_name = os.getenv("COMMITTER_NAME", author_name)
committer_email = os.getenv("COMMITTER_EMAIL", author_email)
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Set git environment. This will not persist after the action completes.
print("Configuring git author as '%s <%s>'" % (author_name, author_email))
print("Configuring git committer as '%s <%s>'" % (committer_name, committer_email))
repo.git.update_environment(
GIT_AUTHOR_NAME=author_name,
GIT_AUTHOR_EMAIL=author_email,
GIT_COMMITTER_NAME=committer_name,
GIT_COMMITTER_EMAIL=committer_email,
)
# Fetch/Set the branch name
branch_prefix = os.getenv("PULL_REQUEST_BRANCH", "create-pull-request/patch")
# Fetch an optional base branch override
base_override = os.environ.get("PULL_REQUEST_BASE")
# Set the base branch
if base_override is not None:
base = base_override
print("Overriding the base with branch '%s'" % base)
checkout_branch(repo.git, True, base)
elif github_ref.startswith("refs/pull/"):
# Check the PR is not raised from a fork of the repository
head_repo = "{pull_request[head][repo][full_name]}".format(**event_data)
if head_repo != github_repository:
print(
"::warning::Pull request was raised from a fork of the repository. "
+ "Limitations on forked repositories have been imposed by GitHub Actions. "
+ "Unable to continue. Exiting."
)
sys.exit()
# Switch to the merging branch instead of the merge commit
base = os.environ["GITHUB_HEAD_REF"]
print(
"Removing the merge commit by switching to the pull request head branch '%s'"
% base
)
checkout_branch(repo.git, True, base)
elif github_ref.startswith("refs/heads/"):
base = github_ref[11:]
print("Currently checked out base assumed to be branch '%s'" % base)
else:
print(
f"::warning::Currently checked out ref '{github_ref}' is not a valid base for a pull request. "
+ "Unable to continue. Exiting."
)
sys.exit()
# Skip if the current branch is a PR branch created by this action.
# This may occur when using a PAT instead of GITHUB_TOKEN because
# a PAT allows workflow actions to trigger further events.
if base.startswith(branch_prefix):
print("Branch '%s' was created by this action. Skipping." % base)
sys.exit()
# Fetch an optional environment variable to determine the branch suffix
branch_suffix = os.getenv("BRANCH_SUFFIX", "short-commit-hash")
if branch_suffix == "short-commit-hash":
# Suffix with the short SHA1 hash
branch = "%s-%s" % (branch_prefix, get_head_short_sha1(repo))
elif branch_suffix == "timestamp":
# Suffix with the current timestamp
branch = "%s-%s" % (branch_prefix, int(time.time()))
elif branch_suffix == "random":
# Suffix with the current timestamp
branch = "%s-%s" % (branch_prefix, get_random_suffix())
elif branch_suffix == "none":
# Fixed branch name
branch = branch_prefix
else:
print("Branch suffix '%s' is not a valid value." % branch_suffix)
sys.exit(1)
# Output head branch
print("Pull request branch to create/update set to '%s'" % branch)
# Check if the determined head branch exists as a remote
remote_exists = remote_branch_exists(repo, branch)
if remote_exists:
print(
"Pull request branch '%s' already exists as remote branch 'origin/%s'"
% (branch, branch)
)
if branch_suffix == "short-commit-hash":
# A remote branch already exists for the HEAD commit
print(
"Pull request branch '%s' already exists for this commit. Skipping."
% branch
)
sys.exit()
elif branch_suffix in ["timestamp", "random"]:
# Generated branch name collision with an existing branch
print(
"Pull request branch '%s' collided with a branch of the same name. Please re-run."
% branch
)
sys.exit(1)
# Checkout branch
checkout_branch(repo.git, remote_exists, branch)
# Check if there are changes to pull request
if remote_exists:
print(
"Checking for local working copy changes indicating a "
+ "diff with existing pull request branch 'origin/%s'" % branch
)
else:
print(
"Checking for local working copy changes indicating a "
+ "diff with base 'origin/%s'" % base
)
if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Modified or untracked files detected.")
process_event(github_token, github_repository, repo, branch, base)
else:
print("No modified or untracked files detected. Skipping.")

2
dist/src/requirements.txt vendored Normal file
View File

@ -0,0 +1,2 @@
GitPython==3.0.5
PyGithub==1.44.1

52
dist/src/setup-python.js vendored Normal file
View File

@ -0,0 +1,52 @@
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;

390
examples.md Normal file
View File

@ -0,0 +1,390 @@
# Examples
- [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)
- [Keep Go up to date](#keep-go-up-to-date)
- [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)
- [Call the GitHub API from an external service](#call-the-github-api-from-an-external-service)
- [Call the GitHub API from another GitHub Actions workflow](#call-the-github-api-from-another-github-actions-workflow)
- [Use case: Create a pull request to modify/fix pull requests](#use-case-create-a-pull-request-to-modifyfix-pull-requests)
- [autopep8](#autopep8)
- [Misc workflow tips](#misc-workflow-tips)
- [Filtering push events](#filtering-push-events)
- [Dynamic configuration using variables](#dynamic-configuration-using-variables)
- [Debugging GitHub Actions](#debugging-github-actions)
## Use case: Create a pull request to update X periodically
This pattern will work well for updating any kind of static content from an external source. The workflow executes on a schedule and raises a pull request when there are changes.
### Update NPM dependencies
```yml
name: Update Dependencies
on:
schedule:
- cron: '0 10 * * 1'
jobs:
update-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '10.x'
- name: Update dependencies
id: vars
run: |
npm install -g npm-check-updates
ncu -u
npm install
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
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
branch-suffix: none
```
### Keep Go up to date
Keep Go up to date with [ensure-latest-go](https://github.com/jmhodges/ensure-latest-go) action.
```yml
name: Keeping Go up to date
on:
schedule:
- cron: 47 4 * * *
push:
branches:
- master
jobs:
fresh_go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
ref: master
- uses: jmhodges/ensure-latest-go@v1.0.2
id: ensure_go
- run: echo "##[set-output name=pr_title;]update to latest Go release ${{ steps.ensure_go.outputs.go_version}}"
id: pr_title_maker
- name: Create pull request
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ steps.pr_title_maker.outputs.pr_title }}
body: Auto-generated pull request created by the GitHub Actions [create-pull-request](https://github.com/peter-evans/create-pull-request) and [ensure-latest-go](https://github.com/jmhodges/ensure-latest-go).
commit-message: ${{ steps.pr_title_maker.outputs.pr_title }}
branch-suffix: none
branch: ensure-latest-go/patch-${{ steps.ensure_go.outputs.go_version }}
```
### Update SwaggerUI for GitHub Pages
When using [GitHub Pages to host Swagger documentation](https://github.com/peter-evans/swagger-github-pages), this workflow updates the repository with the latest distribution of [SwaggerUI](https://github.com/swagger-api/swagger-ui).
You must create a file called `swagger-ui.version` at the root of your repository before running.
```yml
name: Update Swagger UI
on:
schedule:
- cron: '0 10 * * *'
jobs:
updateSwagger:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Get Latest Swagger UI Release
id: swagger-ui
run: |
echo ::set-output name=release_tag::$(curl -sL https://api.github.com/repos/swagger-api/swagger-ui/releases/latest | jq -r ".tag_name")
echo ::set-output name=current_tag::$(<swagger-ui.version)
- name: Update Swagger UI
if: steps.swagger-ui.outputs.current_tag != steps.swagger-ui.outputs.release_tag
env:
RELEASE_TAG: ${{ steps.swagger-ui.outputs.release_tag }}
SWAGGER_YAML: "swagger.yaml"
run: |
# Delete the dist directory and index.html
rm -fr dist index.html
# Download the release
curl -sL -o $RELEASE_TAG https://api.github.com/repos/swagger-api/swagger-ui/tarball/$RELEASE_TAG
# Extract the dist directory
tar -xzf $RELEASE_TAG --strip-components=1 $(tar -tzf $RELEASE_TAG | head -1 | cut -f1 -d"/")/dist
rm $RELEASE_TAG
# Move index.html to the root
mv dist/index.html .
# Fix references in index.html
sed -i "s|https://petstore.swagger.io/v2/swagger.json|$SWAGGER_YAML|g" index.html
sed -i "s|href=\"./|href=\"dist/|g" index.html
sed -i "s|src=\"./|src=\"dist/|g" index.html
# Update current release
echo ${{ steps.swagger-ui.outputs.release_tag }} > swagger-ui.version
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
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: |
Updates [swagger-ui][1] to ${{ steps.swagger-ui.outputs.release_tag }}
Auto-generated by [create-pull-request][2]
[1]: https://github.com/swagger-api/swagger-ui
[2]: https://github.com/peter-evans/create-pull-request
labels: dependencies, automated pr
branch: swagger-ui-updates
branch-suffix: none
```
### Spider and download a website
This workflow spiders a website and downloads the content. Any changes to the website will be raised in a pull request.
```yml
name: Download Website
on:
schedule:
- cron: '0 10 * * *'
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Download website
run: |
wget \
--recursive \
--level=2 \
--wait=1 \
--no-clobber \
--page-requisites \
--html-extension \
--convert-links \
--domains quotes.toscrape.com \
http://quotes.toscrape.com/
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
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.
branch: website-updates
branch-suffix: none
```
## Use case: Create a pull request to update X by calling the GitHub API
You can use the GitHub API to trigger a webhook event called [`repository_dispatch`](https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#external-events-repository_dispatch) when you want to trigger a workflow for activity that happens outside of GitHub.
This pattern will work well for updating any kind of static content from an external source.
You can modify any of the examples in the previous section to work in this fashion.
Set the workflow to execute `on: repository_dispatch`.
```yml
on:
repository_dispatch:
types: [create-pull-request]
```
### Call the GitHub API from an external service
An `on: repository_dispatch` workflow can be triggered by a call to the GitHub API as follows.
- `[username]` is a GitHub username
- `[token]` is a `repo` scoped [Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line)
- `[repository]` is the name of the repository the workflow resides in.
```
curl -XPOST -u "[username]:[token]" \
-H "Accept: application/vnd.github.everest-preview+json" \
-H "Content-Type: application/json" \
https://api.github.com/repos/[username]/[repository]/dispatches \
--data '{"event_type": "create-pull-request"}'
```
### Call the GitHub API from another GitHub Actions workflow
An `on: repository_dispatch` workflow can be triggered from another workflow with [repository-dispatch](https://github.com/peter-evans/repository-dispatch) action.
```yml
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1.0.0
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: username/my-repo
event-type: create-pull-request
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
```
## Use case: Create a pull request to modify/fix pull requests
This is a pattern that works well for any automated code linting and fixing. A pull request can be created to fix or modify something during an `on: pull_request` workflow. The pull request containing the fix will be raised with the original pull request as the base. This can be then be merged to update the original pull request and pass any required tests.
Note that due to [limitations on forked repositories](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token) workflows for this use case do not work for pull requests raised from forks.
### autopep8
The following is an example workflow for a use case where [autopep8 action](https://github.com/peter-evans/autopep8) runs as both a check on pull requests and raises a further pull request to apply code fixes.
How it works:
1. When a pull request is raised the workflow executes as a check
2. If autopep8 makes any fixes a pull request will be raised for those fixes to be merged into the current pull request branch. The workflow then deliberately causes the check to fail.
3. When the pull request containing the fixes is merged the workflow runs again. This time autopep8 makes no changes and the check passes.
4. The original pull request can now be merged.
```yml
name: autopep8
on: pull_request
jobs:
autopep8:
# Check if the PR is not raised by this workflow and is not from a fork
if: startsWith(github.head_ref, 'autopep8-patches') == false && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: autopep8
id: autopep8
uses: peter-evans/autopep8@v1.1.0
with:
args: --exit-code --recursive --in-place --aggressive --aggressive .
- name: Set autopep8 branch name
id: vars
run: echo ::set-output name=branch-name::"autopep8-patches/$GITHUB_HEAD_REF"
- name: Create Pull Request
if: steps.autopep8.outputs.exit-code == 2
uses: peter-evans/create-pull-request@v1
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.
labels: autopep8, automated pr
branch: ${{ steps.vars.outputs.branch-name }}
branch-suffix: none
- name: Fail if autopep8 made changes
if: steps.autopep8.outputs.exit-code == 2
run: exit 1
```
## Misc workflow tips
### Filtering push events
For workflows using `on: push` you may want to ignore push events for tags and only execute for branches. Specifying `branches` causes only events on branches to trigger the workflow. The `'**'` wildcard will match any branch name.
```yml
on:
push:
branches:
- '**'
```
If you have a workflow that contains jobs to handle push events on branches as well as tags, you can make sure that the job where you use `create-pull-request` action only executes when `github.ref` is a branch by using an `if` condition as follows.
```yml
on: push
jobs:
createPullRequest:
if: startsWith(github.ref, 'refs/heads/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
...
someOtherJob:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
...
```
### Dynamic configuration using variables
The following examples show how configuration for the action can be dynamically defined in a previous workflow step.
The recommended method is to use [`set-output`](https://help.github.com/en/github/automating-your-workflow-with-github-actions/development-tools-for-github-actions#set-an-output-parameter-set-output). Note that the step where output variables are defined must have an id.
```yml
- name: Set output variables
id: vars
run: |
echo ::set-output name=pr_title::"[Test] Add report file $(date +%d-%m-%Y)"
echo ::set-output name=pr_body::"This PR was auto-generated on $(date +%d-%m-%Y) \
by [create-pull-request](https://github.com/peter-evans/create-pull-request)."
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ steps.vars.outputs.pr_title }}
body: ${{ steps.vars.outputs.pr_body }}
```
Alternatively, [`set-env`](https://help.github.com/en/github/automating-your-workflow-with-github-actions/development-tools-for-github-actions#set-an-environment-variable-set-env) can be used to create environment variables.
```yml
- name: Set environment variables
run: |
echo ::set-env name=PULL_REQUEST_TITLE::"[Test] Add report file $(date +%d-%m-%Y)"
echo ::set-env name=PULL_REQUEST_BODY::"This PR was auto-generated on $(date +%d-%m-%Y) \
by [create-pull-request](https://github.com/peter-evans/create-pull-request)."
- name: Create Pull Request
uses: peter-evans/create-pull-request@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ env.PULL_REQUEST_TITLE }}
body: ${{ env.PULL_REQUEST_BODY }}
```
### Debugging GitHub Actions
#### Runner Diagnostic Logging
[Runner diagnostic logging](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/managing-a-workflow-run#enabling-runner-diagnostic-logging) provides additional log files that contain information about how a runner is executing an action.
To enable runner diagnostic logging, set the secret `ACTIONS_RUNNER_DEBUG` to `true` in the repository that contains the workflow.
#### Step Debug Logging
[Step debug logging](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/managing-a-workflow-run#enabling-step-debug-logging) increases the verbosity of a job's logs during and after a job's execution.
To enable step debug logging set the secret `ACTIONS_STEP_DEBUG` to `true` in the repository that contains the workflow.
#### Output Various Contexts
```yml
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump job context
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
- name: Dump steps context
env:
STEPS_CONTEXT: ${{ toJson(steps) }}
run: echo "$STEPS_CONTEXT"
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
run: echo "$RUNNER_CONTEXT"
- name: Dump strategy context
env:
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
run: echo "$STRATEGY_CONTEXT"
- name: Dump matrix context
env:
MATRIX_CONTEXT: ${{ toJson(matrix) }}
run: echo "$MATRIX_CONTEXT"
```

View File

@ -1,25 +1,74 @@
const core = require('@actions/core');
const exec = require('@actions/exec');
const os = require('os');
const { inspect } = require("util");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./src/setup-python");
async function run() {
try {
core.info(`platform: ${os.platform()}`)
core.info(`action directory: ${__dirname}`)
// Allows ncc to find assets to be included in the distribution
const src = __dirname + "/src";
core.debug(`src: ${src}`);
if (os.platform() == 'linux') {
await exec.exec('sudo apt-get install python3-setuptools');
}
await exec.exec(`pip3 install --requirement ${__dirname}/requirements.txt`);
if (os.platform() == 'win32') {
await exec.exec(`python ${__dirname}/create-pull-request.py`);
} else {
await exec.exec(`python3 ${__dirname}/create-pull-request.py`);
}
}
catch (error) {
// Setup Python from the tool cache
setupPython("3.8.x", "x64");
// Install requirements
await exec.exec("pip", [
"install",
"--requirement",
`${src}/requirements.txt`
]);
// Fetch action inputs
const inputs = {
token: core.getInput("token"),
commitMessage: core.getInput("commit-message"),
commitAuthorName: core.getInput("author-name"),
commitAuthorEmail: core.getInput("author-email"),
committerName: core.getInput("committer-name"),
committerEmail: core.getInput("committer-email"),
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"),
debugEvent: core.getInput("debug-event")
};
core.debug(`Inputs: ${inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
if (inputs.commitMessage) process.env.COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.commitAuthorName) process.env.COMMIT_AUTHOR_NAME = inputs.commitAuthorName;
if (inputs.commitAuthorEmail) process.env.COMMIT_AUTHOR_EMAIL = inputs.commitAuthorEmail;
if (inputs.committerName) process.env.COMMITTER_NAME = inputs.committerName;
if (inputs.committerEmail) process.env.COMMITTER_EMAIL = inputs.committerEmail;
if (inputs.title) process.env.PULL_REQUEST_TITLE = inputs.title;
if (inputs.body) process.env.PULL_REQUEST_BODY = inputs.body;
if (inputs.labels) process.env.PULL_REQUEST_LABELS = inputs.labels;
if (inputs.assignees) process.env.PULL_REQUEST_ASSIGNEES = inputs.assignees;
if (inputs.reviewers) process.env.PULL_REQUEST_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers) process.env.PULL_REQUEST_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone) process.env.PULL_REQUEST_MILESTONE = inputs.milestone;
if (inputs.project) process.env.PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.branch) process.env.PULL_REQUEST_BRANCH = inputs.branch;
if (inputs.base) process.env.PULL_REQUEST_BASE = inputs.base;
if (inputs.branchSuffix) process.env.BRANCH_SUFFIX = inputs.branchSuffix;
if (inputs.debugEvent) process.env.DEBUG_EVENT = inputs.debugEvent;
// Execute python script
await exec.exec("python", [`${src}/create-pull-request.py`]);
} catch (error) {
core.setFailed(error.message);
}
}
run()
run();

97
node_modules/@actions/core/README.md generated vendored
View File

@ -1,97 +0,0 @@
# `@actions/core`
> Core functions for setting results, logging, registering secrets and exporting variables across actions
## Usage
#### Inputs/Outputs
You can use this library to get inputs or set outputs:
```js
const core = require('@actions/core');
const myInput = core.getInput('inputName', { required: true });
// Do stuff
core.setOutput('outputKey', 'outputVal');
```
#### Exporting variables
You can also export variables for future steps. Variables get set in the environment.
```js
const core = require('@actions/core');
// Do stuff
core.exportVariable('envVar', 'Val');
```
#### PATH Manipulation
You can explicitly add items to the path for all remaining steps in a workflow:
```js
const core = require('@actions/core');
core.addPath('pathToTool');
```
#### Exit codes
You should use this library to set the failing exit code for your action:
```js
const core = require('@actions/core');
try {
// Do stuff
}
catch (err) {
// setFailed logs the message and sets a failing exit code
core.setFailed(`Action failed with error ${err}`);
}
```
#### Logging
Finally, this library provides some utilities for logging. Note that debug logging is hidden from the logs by default. This behavior can be toggled by enabling the [Step Debug Logs](../../docs/action-debugging.md#step-debug-logs).
```js
const core = require('@actions/core');
const myInput = core.getInput('input');
try {
core.debug('Inside try block');
if (!myInput) {
core.warning('myInput was not set');
}
// Do stuff
}
catch (err) {
core.error(`Error ${err}, action may still succeed though`);
}
```
This library can also wrap chunks of output in foldable groups.
```js
const core = require('@actions/core')
// Manually wrap output
core.startGroup('Do some function')
doSomeFunction()
core.endGroup()
// Wrap an asynchronous function call
const result = await core.group('Do something async', async () => {
const response = await doSomeHTTPRequest()
return response
})
```

View File

@ -1,16 +0,0 @@
interface CommandProperties {
[key: string]: string;
}
/**
* Commands
*
* Command Format:
* ##[name key=value;key=value]message
*
* Examples:
* ##[warning]This is the user warning message
* ##[set-secret name=mypassword]definitelyNotAPassword!
*/
export declare function issueCommand(command: string, properties: CommandProperties, message: string): void;
export declare function issue(name: string, message?: string): void;
export {};

View File

@ -1,66 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
/**
* Commands
*
* Command Format:
* ##[name key=value;key=value]message
*
* Examples:
* ##[warning]This is the user warning message
* ##[set-secret name=mypassword]definitelyNotAPassword!
*/
function issueCommand(command, properties, message) {
const cmd = new Command(command, properties, message);
process.stdout.write(cmd.toString() + os.EOL);
}
exports.issueCommand = issueCommand;
function issue(name, message = '') {
issueCommand(name, {}, message);
}
exports.issue = issue;
const CMD_STRING = '::';
class Command {
constructor(command, properties, message) {
if (!command) {
command = 'missing.command';
}
this.command = command;
this.properties = properties;
this.message = message;
}
toString() {
let cmdStr = CMD_STRING + this.command;
if (this.properties && Object.keys(this.properties).length > 0) {
cmdStr += ' ';
for (const key in this.properties) {
if (this.properties.hasOwnProperty(key)) {
const val = this.properties[key];
if (val) {
// safely append the val - avoid blowing up when attempting to
// call .replace() if message is not a string for some reason
cmdStr += `${key}=${escape(`${val || ''}`)},`;
}
}
}
}
cmdStr += CMD_STRING;
// safely append the message - avoid blowing up when attempting to
// call .replace() if message is not a string for some reason
const message = `${this.message || ''}`;
cmdStr += escapeData(message);
return cmdStr;
}
}
function escapeData(s) {
return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A');
}
function escape(s) {
return s
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/]/g, '%5D')
.replace(/;/g, '%3B');
}
//# sourceMappingURL=command.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":";;AAAA,yBAAwB;AAQxB;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,UAA6B,EAC7B,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC;AAPD,oCAOC;AAED,SAAgB,KAAK,CAAC,IAAY,EAAE,UAAkB,EAAE;IACtD,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAFD,sBAEC;AAED,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,OAAO;IAKX,YAAY,OAAe,EAAE,UAA6B,EAAE,OAAe;QACzE,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,iBAAiB,CAAA;SAC5B;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAA;QAEtC,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9D,MAAM,IAAI,GAAG,CAAA;YACb,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;oBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAChC,IAAI,GAAG,EAAE;wBACP,8DAA8D;wBAC9D,6DAA6D;wBAC7D,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,CAAA;qBAC9C;iBACF;aACF;SACF;QAED,MAAM,IAAI,UAAU,CAAA;QAEpB,kEAAkE;QAClE,6DAA6D;QAC7D,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAA;QACvC,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,CAAA;QAE7B,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AACtD,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACzB,CAAC"}

View File

@ -1,99 +0,0 @@
/**
* Interface for getInput options
*/
export interface InputOptions {
/** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */
required?: boolean;
}
/**
* The code to exit an action
*/
export declare enum ExitCode {
/**
* A code indicating that the action was successful
*/
Success = 0,
/**
* A code indicating that the action was a failure
*/
Failure = 1
}
/**
* sets env variable for this action and future actions in the job
* @param name the name of the variable to set
* @param val the value of the variable
*/
export declare function exportVariable(name: string, val: string): void;
/**
* exports the variable and registers a secret which will get masked from logs
* @param name the name of the variable to set
* @param val value of the secret
*/
export declare function exportSecret(name: string, val: string): void;
/**
* Prepends inputPath to the PATH (for this action and future actions)
* @param inputPath
*/
export declare function addPath(inputPath: string): void;
/**
* Gets the value of an input. The value is also trimmed.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string
*/
export declare function getInput(name: string, options?: InputOptions): string;
/**
* Sets the value of an output.
*
* @param name name of the output to set
* @param value value to store
*/
export declare function setOutput(name: string, value: string): void;
/**
* Sets the action status to failed.
* When the action exits it will be with an exit code of 1
* @param message add error issue message
*/
export declare function setFailed(message: string): void;
/**
* Writes debug message to user log
* @param message debug message
*/
export declare function debug(message: string): void;
/**
* Adds an error issue
* @param message error issue message
*/
export declare function error(message: string): void;
/**
* Adds an warning issue
* @param message warning issue message
*/
export declare function warning(message: string): void;
/**
* Writes info to log with console.log.
* @param message info message
*/
export declare function info(message: string): void;
/**
* Begin an output group.
*
* Output until the next `groupEnd` will be foldable in this group
*
* @param name The name of the output group
*/
export declare function startGroup(name: string): void;
/**
* End an output group.
*/
export declare function endGroup(): void;
/**
* Wrap an asynchronous function call in a group.
*
* Returns the same type as the function itself.
*
* @param name The name of the group
* @param fn The function to wrap in the group
*/
export declare function group<T>(name: string, fn: () => Promise<T>): Promise<T>;

View File

@ -1,177 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const command_1 = require("./command");
const os = require("os");
const path = require("path");
/**
* The code to exit an action
*/
var ExitCode;
(function (ExitCode) {
/**
* A code indicating that the action was successful
*/
ExitCode[ExitCode["Success"] = 0] = "Success";
/**
* A code indicating that the action was a failure
*/
ExitCode[ExitCode["Failure"] = 1] = "Failure";
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
//-----------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------
/**
* sets env variable for this action and future actions in the job
* @param name the name of the variable to set
* @param val the value of the variable
*/
function exportVariable(name, val) {
process.env[name] = val;
command_1.issueCommand('set-env', { name }, val);
}
exports.exportVariable = exportVariable;
/**
* exports the variable and registers a secret which will get masked from logs
* @param name the name of the variable to set
* @param val value of the secret
*/
function exportSecret(name, val) {
exportVariable(name, val);
// the runner will error with not implemented
// leaving the function but raising the error earlier
command_1.issueCommand('set-secret', {}, val);
throw new Error('Not implemented.');
}
exports.exportSecret = exportSecret;
/**
* Prepends inputPath to the PATH (for this action and future actions)
* @param inputPath
*/
function addPath(inputPath) {
command_1.issueCommand('add-path', {}, inputPath);
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
}
exports.addPath = addPath;
/**
* Gets the value of an input. The value is also trimmed.
*
* @param name name of the input to get
* @param options optional. See InputOptions.
* @returns string
*/
function getInput(name, options) {
const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
if (options && options.required && !val) {
throw new Error(`Input required and not supplied: ${name}`);
}
return val.trim();
}
exports.getInput = getInput;
/**
* Sets the value of an output.
*
* @param name name of the output to set
* @param value value to store
*/
function setOutput(name, value) {
command_1.issueCommand('set-output', { name }, value);
}
exports.setOutput = setOutput;
//-----------------------------------------------------------------------
// Results
//-----------------------------------------------------------------------
/**
* Sets the action status to failed.
* When the action exits it will be with an exit code of 1
* @param message add error issue message
*/
function setFailed(message) {
process.exitCode = ExitCode.Failure;
error(message);
}
exports.setFailed = setFailed;
//-----------------------------------------------------------------------
// Logging Commands
//-----------------------------------------------------------------------
/**
* Writes debug message to user log
* @param message debug message
*/
function debug(message) {
command_1.issueCommand('debug', {}, message);
}
exports.debug = debug;
/**
* Adds an error issue
* @param message error issue message
*/
function error(message) {
command_1.issue('error', message);
}
exports.error = error;
/**
* Adds an warning issue
* @param message warning issue message
*/
function warning(message) {
command_1.issue('warning', message);
}
exports.warning = warning;
/**
* Writes info to log with console.log.
* @param message info message
*/
function info(message) {
process.stdout.write(message + os.EOL);
}
exports.info = info;
/**
* Begin an output group.
*
* Output until the next `groupEnd` will be foldable in this group
*
* @param name The name of the output group
*/
function startGroup(name) {
command_1.issue('group', name);
}
exports.startGroup = startGroup;
/**
* End an output group.
*/
function endGroup() {
command_1.issue('endgroup');
}
exports.endGroup = endGroup;
/**
* Wrap an asynchronous function call in a group.
*
* Returns the same type as the function itself.
*
* @param name The name of the group
* @param fn The function to wrap in the group
*/
function group(name, fn) {
return __awaiter(this, void 0, void 0, function* () {
startGroup(name);
let result;
try {
result = yield fn();
}
finally {
endGroup();
}
return result;
});
}
exports.group = group;
//# sourceMappingURL=core.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}

View File

@ -1,66 +0,0 @@
{
"_args": [
[
"@actions/core@1.1.1",
"/Users/peter.evans/git/create-pull-request"
]
],
"_from": "@actions/core@1.1.1",
"_id": "@actions/core@1.1.1",
"_inBundle": false,
"_integrity": "sha512-O5G6EmlzTVsng7VSpNtszIoQq6kOgMGNTFB/hmwKNNA4V71JyxImCIrL27vVHCt2Cb3ImkaCr6o27C2MV9Ylwg==",
"_location": "/@actions/core",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "@actions/core@1.1.1",
"name": "@actions/core",
"escapedName": "@actions%2fcore",
"scope": "@actions",
"rawSpec": "1.1.1",
"saveSpec": null,
"fetchSpec": "1.1.1"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.1.tgz",
"_spec": "1.1.1",
"_where": "/Users/peter.evans/git/create-pull-request",
"bugs": {
"url": "https://github.com/actions/toolkit/issues"
},
"description": "Actions core lib",
"devDependencies": {
"@types/node": "^12.0.2"
},
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"homepage": "https://github.com/actions/toolkit/tree/master/packages/core",
"keywords": [
"github",
"actions",
"core"
],
"license": "MIT",
"main": "lib/core.js",
"name": "@actions/core",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/toolkit.git"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1",
"tsc": "tsc"
},
"version": "1.1.1"
}

View File

@ -1,7 +0,0 @@
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

60
node_modules/@actions/exec/README.md generated vendored
View File

@ -1,60 +0,0 @@
# `@actions/exec`
## Usage
#### Basic
You can use this package to execute your tools on the command line in a cross platform way:
```js
const exec = require('@actions/exec');
await exec.exec('node index.js');
```
#### Args
You can also pass in arg arrays:
```js
const exec = require('@actions/exec');
await exec.exec('node', ['index.js', 'foo=bar']);
```
#### Output/options
Capture output or specify [other options](https://github.com/actions/toolkit/blob/d9347d4ab99fd507c0b9104b2cf79fb44fcc827d/packages/exec/src/interfaces.ts#L5):
```js
const exec = require('@actions/exec');
let myOutput = '';
let myError = '';
const options = {};
options.listeners = {
stdout: (data: Buffer) => {
myOutput += data.toString();
},
stderr: (data: Buffer) => {
myError += data.toString();
}
};
options.cwd = './lib';
await exec.exec('node', ['index.js', 'foo=bar'], options);
```
#### Exec tools not in the PATH
You can use it in conjunction with the `which` function from `@actions/io` to execute tools that are not in the PATH:
```js
const exec = require('@actions/exec');
const io = require('@actions/io');
const pythonPath: string = await io.which('python', true)
await exec.exec(`"${pythonPath}"`, ['main.py']);
```

View File

@ -1,12 +0,0 @@
import * as im from './interfaces';
/**
* Exec a command.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
* @param args optional arguments for tool. Escaping is handled by the lib.
* @param options optional exec options. See ExecOptions
* @returns Promise<number> exit code
*/
export declare function exec(commandLine: string, args?: string[], options?: im.ExecOptions): Promise<number>;

View File

@ -1,37 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const tr = require("./toolrunner");
/**
* Exec a command.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
* @param args optional arguments for tool. Escaping is handled by the lib.
* @param options optional exec options. See ExecOptions
* @returns Promise<number> exit code
*/
function exec(commandLine, args, options) {
return __awaiter(this, void 0, void 0, function* () {
const commandArgs = tr.argStringToArray(commandLine);
if (commandArgs.length === 0) {
throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
}
// Path to tool to execute should be first arg
const toolPath = commandArgs[0];
args = commandArgs.slice(1).concat(args || []);
const runner = new tr.ToolRunner(toolPath, args, options);
return runner.exec();
});
}
exports.exec = exec;
//# sourceMappingURL=exec.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":";;;;;;;;;;;AACA,mCAAkC;AAElC;;;;;;;;;GASG;AACH,SAAsB,IAAI,CACxB,WAAmB,EACnB,IAAe,EACf,OAAwB;;QAExB,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QACpD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;SACpE;QACD,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;QAC/B,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QAC9C,MAAM,MAAM,GAAkB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QACxE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;CAAA;AAdD,oBAcC"}

View File

@ -1,35 +0,0 @@
/// <reference types="node" />
import * as stream from 'stream';
/**
* Interface for exec options
*/
export interface ExecOptions {
/** optional working directory. defaults to current */
cwd?: string;
/** optional envvar dictionary. defaults to current process's env */
env?: {
[key: string]: string;
};
/** optional. defaults to false */
silent?: boolean;
/** optional out stream to use. Defaults to process.stdout */
outStream?: stream.Writable;
/** optional err stream to use. Defaults to process.stderr */
errStream?: stream.Writable;
/** optional. whether to skip quoting/escaping arguments if needed. defaults to false. */
windowsVerbatimArguments?: boolean;
/** optional. whether to fail if output to stderr. defaults to false */
failOnStdErr?: boolean;
/** optional. defaults to failing on non zero. ignore will not fail leaving it up to the caller */
ignoreReturnCode?: boolean;
/** optional. How long in ms to wait for STDIO streams to close after the exit event of the process before terminating. defaults to 10000 */
delay?: number;
/** optional. Listeners for output. Callback functions that will be called on these events */
listeners?: {
stdout?: (data: Buffer) => void;
stderr?: (data: Buffer) => void;
stdline?: (data: string) => void;
errline?: (data: string) => void;
debug?: (data: string) => void;
};
}

View File

@ -1,3 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":""}

View File

@ -1,37 +0,0 @@
/// <reference types="node" />
import * as events from 'events';
import * as im from './interfaces';
export declare class ToolRunner extends events.EventEmitter {
constructor(toolPath: string, args?: string[], options?: im.ExecOptions);
private toolPath;
private args;
private options;
private _debug;
private _getCommandString;
private _processLineBuffer;
private _getSpawnFileName;
private _getSpawnArgs;
private _endsWith;
private _isCmdFile;
private _windowsQuoteCmdArg;
private _uvQuoteCmdArg;
private _cloneExecOptions;
private _getSpawnOptions;
/**
* Exec a tool.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @param tool path to tool to exec
* @param options optional exec options. See ExecOptions
* @returns number
*/
exec(): Promise<number>;
}
/**
* Convert an arg string to an array of args. Handles escaping
*
* @param argString string of arguments
* @returns string[] array of arguments
*/
export declare function argStringToArray(argString: string): string[];

View File

@ -1,574 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
const events = require("events");
const child = require("child_process");
/* eslint-disable @typescript-eslint/unbound-method */
const IS_WINDOWS = process.platform === 'win32';
/*
* Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.
*/
class ToolRunner extends events.EventEmitter {
constructor(toolPath, args, options) {
super();
if (!toolPath) {
throw new Error("Parameter 'toolPath' cannot be null or empty.");
}
this.toolPath = toolPath;
this.args = args || [];
this.options = options || {};
}
_debug(message) {
if (this.options.listeners && this.options.listeners.debug) {
this.options.listeners.debug(message);
}
}
_getCommandString(options, noPrefix) {
const toolPath = this._getSpawnFileName();
const args = this._getSpawnArgs(options);
let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool
if (IS_WINDOWS) {
// Windows + cmd file
if (this._isCmdFile()) {
cmd += toolPath;
for (const a of args) {
cmd += ` ${a}`;
}
}
// Windows + verbatim
else if (options.windowsVerbatimArguments) {
cmd += `"${toolPath}"`;
for (const a of args) {
cmd += ` ${a}`;
}
}
// Windows (regular)
else {
cmd += this._windowsQuoteCmdArg(toolPath);
for (const a of args) {
cmd += ` ${this._windowsQuoteCmdArg(a)}`;
}
}
}
else {
// OSX/Linux - this can likely be improved with some form of quoting.
// creating processes on Unix is fundamentally different than Windows.
// on Unix, execvp() takes an arg array.
cmd += toolPath;
for (const a of args) {
cmd += ` ${a}`;
}
}
return cmd;
}
_processLineBuffer(data, strBuffer, onLine) {
try {
let s = strBuffer + data.toString();
let n = s.indexOf(os.EOL);
while (n > -1) {
const line = s.substring(0, n);
onLine(line);
// the rest of the string ...
s = s.substring(n + os.EOL.length);
n = s.indexOf(os.EOL);
}
strBuffer = s;
}
catch (err) {
// streaming lines to console is best effort. Don't fail a build.
this._debug(`error processing line. Failed with error ${err}`);
}
}
_getSpawnFileName() {
if (IS_WINDOWS) {
if (this._isCmdFile()) {
return process.env['COMSPEC'] || 'cmd.exe';
}
}
return this.toolPath;
}
_getSpawnArgs(options) {
if (IS_WINDOWS) {
if (this._isCmdFile()) {
let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;
for (const a of this.args) {
argline += ' ';
argline += options.windowsVerbatimArguments
? a
: this._windowsQuoteCmdArg(a);
}
argline += '"';
return [argline];
}
}
return this.args;
}
_endsWith(str, end) {
return str.endsWith(end);
}
_isCmdFile() {
const upperToolPath = this.toolPath.toUpperCase();
return (this._endsWith(upperToolPath, '.CMD') ||
this._endsWith(upperToolPath, '.BAT'));
}
_windowsQuoteCmdArg(arg) {
// for .exe, apply the normal quoting rules that libuv applies
if (!this._isCmdFile()) {
return this._uvQuoteCmdArg(arg);
}
// otherwise apply quoting rules specific to the cmd.exe command line parser.
// the libuv rules are generic and are not designed specifically for cmd.exe
// command line parser.
//
// for a detailed description of the cmd.exe command line parser, refer to
// http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
// need quotes for empty arg
if (!arg) {
return '""';
}
// determine whether the arg needs to be quoted
const cmdSpecialChars = [
' ',
'\t',
'&',
'(',
')',
'[',
']',
'{',
'}',
'^',
'=',
';',
'!',
"'",
'+',
',',
'`',
'~',
'|',
'<',
'>',
'"'
];
let needsQuotes = false;
for (const char of arg) {
if (cmdSpecialChars.some(x => x === char)) {
needsQuotes = true;
break;
}
}
// short-circuit if quotes not needed
if (!needsQuotes) {
return arg;
}
// the following quoting rules are very similar to the rules that by libuv applies.
//
// 1) wrap the string in quotes
//
// 2) double-up quotes - i.e. " => ""
//
// this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately
// doesn't work well with a cmd.exe command line.
//
// note, replacing " with "" also works well if the arg is passed to a downstream .NET console app.
// for example, the command line:
// foo.exe "myarg:""my val"""
// is parsed by a .NET console app into an arg array:
// [ "myarg:\"my val\"" ]
// which is the same end result when applying libuv quoting rules. although the actual
// command line from libuv quoting rules would look like:
// foo.exe "myarg:\"my val\""
//
// 3) double-up slashes that precede a quote,
// e.g. hello \world => "hello \world"
// hello\"world => "hello\\""world"
// hello\\"world => "hello\\\\""world"
// hello world\ => "hello world\\"
//
// technically this is not required for a cmd.exe command line, or the batch argument parser.
// the reasons for including this as a .cmd quoting rule are:
//
// a) this is optimized for the scenario where the argument is passed from the .cmd file to an
// external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.
//
// b) it's what we've been doing previously (by deferring to node default behavior) and we
// haven't heard any complaints about that aspect.
//
// note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be
// escaped when used on the command line directly - even though within a .cmd file % can be escaped
// by using %%.
//
// the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts
// the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.
//
// one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would
// often work, since it is unlikely that var^ would exist, and the ^ character is removed when the
// variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args
// to an external program.
//
// an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.
// % can be escaped within a .cmd file.
let reverse = '"';
let quoteHit = true;
for (let i = arg.length; i > 0; i--) {
// walk the string in reverse
reverse += arg[i - 1];
if (quoteHit && arg[i - 1] === '\\') {
reverse += '\\'; // double the slash
}
else if (arg[i - 1] === '"') {
quoteHit = true;
reverse += '"'; // double the quote
}
else {
quoteHit = false;
}
}
reverse += '"';
return reverse
.split('')
.reverse()
.join('');
}
_uvQuoteCmdArg(arg) {
// Tool runner wraps child_process.spawn() and needs to apply the same quoting as
// Node in certain cases where the undocumented spawn option windowsVerbatimArguments
// is used.
//
// Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,
// see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),
// pasting copyright notice from Node within this function:
//
// Copyright Joyent, Inc. and other Node contributors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
if (!arg) {
// Need double quotation for empty argument
return '""';
}
if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) {
// No quotation needed
return arg;
}
if (!arg.includes('"') && !arg.includes('\\')) {
// No embedded double quotes or backslashes, so I can just wrap
// quote marks around the whole thing.
return `"${arg}"`;
}
// Expected input/output:
// input : hello"world
// output: "hello\"world"
// input : hello""world
// output: "hello\"\"world"
// input : hello\world
// output: hello\world
// input : hello\\world
// output: hello\\world
// input : hello\"world
// output: "hello\\\"world"
// input : hello\\"world
// output: "hello\\\\\"world"
// input : hello world\
// output: "hello world\\" - note the comment in libuv actually reads "hello world\"
// but it appears the comment is wrong, it should be "hello world\\"
let reverse = '"';
let quoteHit = true;
for (let i = arg.length; i > 0; i--) {
// walk the string in reverse
reverse += arg[i - 1];
if (quoteHit && arg[i - 1] === '\\') {
reverse += '\\';
}
else if (arg[i - 1] === '"') {
quoteHit = true;
reverse += '\\';
}
else {
quoteHit = false;
}
}
reverse += '"';
return reverse
.split('')
.reverse()
.join('');
}
_cloneExecOptions(options) {
options = options || {};
const result = {
cwd: options.cwd || process.cwd(),
env: options.env || process.env,
silent: options.silent || false,
windowsVerbatimArguments: options.windowsVerbatimArguments || false,
failOnStdErr: options.failOnStdErr || false,
ignoreReturnCode: options.ignoreReturnCode || false,
delay: options.delay || 10000
};
result.outStream = options.outStream || process.stdout;
result.errStream = options.errStream || process.stderr;
return result;
}
_getSpawnOptions(options, toolPath) {
options = options || {};
const result = {};
result.cwd = options.cwd;
result.env = options.env;
result['windowsVerbatimArguments'] =
options.windowsVerbatimArguments || this._isCmdFile();
if (options.windowsVerbatimArguments) {
result.argv0 = `"${toolPath}"`;
}
return result;
}
/**
* Exec a tool.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @param tool path to tool to exec
* @param options optional exec options. See ExecOptions
* @returns number
*/
exec() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
this._debug(`exec tool: ${this.toolPath}`);
this._debug('arguments:');
for (const arg of this.args) {
this._debug(` ${arg}`);
}
const optionsNonNull = this._cloneExecOptions(this.options);
if (!optionsNonNull.silent && optionsNonNull.outStream) {
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
}
const state = new ExecState(optionsNonNull, this.toolPath);
state.on('debug', (message) => {
this._debug(message);
});
const fileName = this._getSpawnFileName();
const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));
const stdbuffer = '';
if (cp.stdout) {
cp.stdout.on('data', (data) => {
if (this.options.listeners && this.options.listeners.stdout) {
this.options.listeners.stdout(data);
}
if (!optionsNonNull.silent && optionsNonNull.outStream) {
optionsNonNull.outStream.write(data);
}
this._processLineBuffer(data, stdbuffer, (line) => {
if (this.options.listeners && this.options.listeners.stdline) {
this.options.listeners.stdline(line);
}
});
});
}
const errbuffer = '';
if (cp.stderr) {
cp.stderr.on('data', (data) => {
state.processStderr = true;
if (this.options.listeners && this.options.listeners.stderr) {
this.options.listeners.stderr(data);
}
if (!optionsNonNull.silent &&
optionsNonNull.errStream &&
optionsNonNull.outStream) {
const s = optionsNonNull.failOnStdErr
? optionsNonNull.errStream
: optionsNonNull.outStream;
s.write(data);
}
this._processLineBuffer(data, errbuffer, (line) => {
if (this.options.listeners && this.options.listeners.errline) {
this.options.listeners.errline(line);
}
});
});
}
cp.on('error', (err) => {
state.processError = err.message;
state.processExited = true;
state.processClosed = true;
state.CheckComplete();
});
cp.on('exit', (code) => {
state.processExitCode = code;
state.processExited = true;
this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
state.CheckComplete();
});
cp.on('close', (code) => {
state.processExitCode = code;
state.processExited = true;
state.processClosed = true;
this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);
state.CheckComplete();
});
state.on('done', (error, exitCode) => {
if (stdbuffer.length > 0) {
this.emit('stdline', stdbuffer);
}
if (errbuffer.length > 0) {
this.emit('errline', errbuffer);
}
cp.removeAllListeners();
if (error) {
reject(error);
}
else {
resolve(exitCode);
}
});
});
});
}
}
exports.ToolRunner = ToolRunner;
/**
* Convert an arg string to an array of args. Handles escaping
*
* @param argString string of arguments
* @returns string[] array of arguments
*/
function argStringToArray(argString) {
const args = [];
let inQuotes = false;
let escaped = false;
let arg = '';
function append(c) {
// we only escape double quotes.
if (escaped && c !== '"') {
arg += '\\';
}
arg += c;
escaped = false;
}
for (let i = 0; i < argString.length; i++) {
const c = argString.charAt(i);
if (c === '"') {
if (!escaped) {
inQuotes = !inQuotes;
}
else {
append(c);
}
continue;
}
if (c === '\\' && escaped) {
append(c);
continue;
}
if (c === '\\' && inQuotes) {
escaped = true;
continue;
}
if (c === ' ' && !inQuotes) {
if (arg.length > 0) {
args.push(arg);
arg = '';
}
continue;
}
append(c);
}
if (arg.length > 0) {
args.push(arg.trim());
}
return args;
}
exports.argStringToArray = argStringToArray;
class ExecState extends events.EventEmitter {
constructor(options, toolPath) {
super();
this.processClosed = false; // tracks whether the process has exited and stdio is closed
this.processError = '';
this.processExitCode = 0;
this.processExited = false; // tracks whether the process has exited
this.processStderr = false; // tracks whether stderr was written to
this.delay = 10000; // 10 seconds
this.done = false;
this.timeout = null;
if (!toolPath) {
throw new Error('toolPath must not be empty');
}
this.options = options;
this.toolPath = toolPath;
if (options.delay) {
this.delay = options.delay;
}
}
CheckComplete() {
if (this.done) {
return;
}
if (this.processClosed) {
this._setResult();
}
else if (this.processExited) {
this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this);
}
}
_debug(message) {
this.emit('debug', message);
}
_setResult() {
// determine whether there is an error
let error;
if (this.processExited) {
if (this.processError) {
error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);
}
else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {
error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);
}
else if (this.processStderr && this.options.failOnStdErr) {
error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);
}
}
// clear the timeout
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
this.done = true;
this.emit('done', error, this.processExitCode);
}
static HandleTimeout(state) {
if (state.done) {
return;
}
if (!state.processClosed && state.processExited) {
const message = `The STDIO streams did not close within ${state.delay /
1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;
state._debug(message);
}
state._setResult();
}
}
//# sourceMappingURL=toolrunner.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"toolrunner.js","sourceRoot":"","sources":["../src/toolrunner.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,yBAAwB;AACxB,iCAAgC;AAChC,uCAAsC;AAItC,sDAAsD;AAEtD,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA;AAE/C;;GAEG;AACH,MAAa,UAAW,SAAQ,MAAM,CAAC,YAAY;IACjD,YAAY,QAAgB,EAAE,IAAe,EAAE,OAAwB;QACrE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;SACjE;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;IAC9B,CAAC;IAMO,MAAM,CAAC,OAAe;QAC5B,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE;YAC1D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;SACtC;IACH,CAAC;IAEO,iBAAiB,CACvB,OAAuB,EACvB,QAAkB;QAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACxC,IAAI,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAA,CAAC,0CAA0C;QAChF,IAAI,UAAU,EAAE;YACd,qBAAqB;YACrB,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,GAAG,IAAI,QAAQ,CAAA;gBACf,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;oBACpB,GAAG,IAAI,IAAI,CAAC,EAAE,CAAA;iBACf;aACF;YACD,qBAAqB;iBAChB,IAAI,OAAO,CAAC,wBAAwB,EAAE;gBACzC,GAAG,IAAI,IAAI,QAAQ,GAAG,CAAA;gBACtB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;oBACpB,GAAG,IAAI,IAAI,CAAC,EAAE,CAAA;iBACf;aACF;YACD,oBAAoB;iBACf;gBACH,GAAG,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAA;gBACzC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;oBACpB,GAAG,IAAI,IAAI,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAA;iBACzC;aACF;SACF;aAAM;YACL,qEAAqE;YACrE,sEAAsE;YACtE,wCAAwC;YACxC,GAAG,IAAI,QAAQ,CAAA;YACf,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;gBACpB,GAAG,IAAI,IAAI,CAAC,EAAE,CAAA;aACf;SACF;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAEO,kBAAkB,CACxB,IAAY,EACZ,SAAiB,EACjB,MAA8B;QAE9B,IAAI;YACF,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;YACnC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;YAEzB,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE;gBACb,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC9B,MAAM,CAAC,IAAI,CAAC,CAAA;gBAEZ,6BAA6B;gBAC7B,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBAClC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;aACtB;YAED,SAAS,GAAG,CAAC,CAAA;SACd;QAAC,OAAO,GAAG,EAAE;YACZ,kEAAkE;YAClE,IAAI,CAAC,MAAM,CAAC,4CAA4C,GAAG,EAAE,CAAC,CAAA;SAC/D;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,UAAU,EAAE;YACd,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS,CAAA;aAC3C;SACF;QAED,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAEO,aAAa,CAAC,OAAuB;QAC3C,IAAI,UAAU,EAAE;YACd,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,IAAI,OAAO,GAAG,aAAa,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAA;gBACpE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE;oBACzB,OAAO,IAAI,GAAG,CAAA;oBACd,OAAO,IAAI,OAAO,CAAC,wBAAwB;wBACzC,CAAC,CAAC,CAAC;wBACH,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAA;iBAChC;gBAED,OAAO,IAAI,GAAG,CAAA;gBACd,OAAO,CAAC,OAAO,CAAC,CAAA;aACjB;SACF;QAED,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAEO,SAAS,CAAC,GAAW,EAAE,GAAW;QACxC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAEO,UAAU;QAChB,MAAM,aAAa,GAAW,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAA;QACzD,OAAO,CACL,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CACtC,CAAA;IACH,CAAC;IAEO,mBAAmB,CAAC,GAAW;QACrC,8DAA8D;QAC9D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE;YACtB,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;SAChC;QAED,6EAA6E;QAC7E,4EAA4E;QAC5E,uBAAuB;QACvB,EAAE;QACF,0EAA0E;QAC1E,4HAA4H;QAE5H,4BAA4B;QAC5B,IAAI,CAAC,GAAG,EAAE;YACR,OAAO,IAAI,CAAA;SACZ;QAED,+CAA+C;QAC/C,MAAM,eAAe,GAAG;YACtB,GAAG;YACH,IAAI;YACJ,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;YACH,GAAG;SACJ,CAAA;QACD,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE;YACtB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE;gBACzC,WAAW,GAAG,IAAI,CAAA;gBAClB,MAAK;aACN;SACF;QAED,qCAAqC;QACrC,IAAI,CAAC,WAAW,EAAE;YAChB,OAAO,GAAG,CAAA;SACX;QAED,mFAAmF;QACnF,EAAE;QACF,+BAA+B;QAC/B,EAAE;QACF,qCAAqC;QACrC,EAAE;QACF,mGAAmG;QACnG,oDAAoD;QACpD,EAAE;QACF,sGAAsG;QACtG,oCAAoC;QACpC,sCAAsC;QACtC,wDAAwD;QACxD,kCAAkC;QAClC,yFAAyF;QACzF,4DAA4D;QAC5D,sCAAsC;QACtC,EAAE;QACF,6CAA6C;QAC7C,6CAA6C;QAC7C,+CAA+C;QAC/C,iDAAiD;QACjD,8CAA8C;QAC9C,EAAE;QACF,gGAAgG;QAChG,gEAAgE;QAChE,EAAE;QACF,iGAAiG;QACjG,kGAAkG;QAClG,EAAE;QACF,6FAA6F;QAC7F,wDAAwD;QACxD,EAAE;QACF,oGAAoG;QACpG,mGAAmG;QACnG,eAAe;QACf,EAAE;QACF,sGAAsG;QACtG,sGAAsG;QACtG,EAAE;QACF,gGAAgG;QAChG,kGAAkG;QAClG,oGAAoG;QACpG,0BAA0B;QAC1B,EAAE;QACF,iGAAiG;QACjG,uCAAuC;QACvC,IAAI,OAAO,GAAG,GAAG,CAAA;QACjB,IAAI,QAAQ,GAAG,IAAI,CAAA;QACnB,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,6BAA6B;YAC7B,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACrB,IAAI,QAAQ,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;gBACnC,OAAO,IAAI,IAAI,CAAA,CAAC,mBAAmB;aACpC;iBAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;gBAC7B,QAAQ,GAAG,IAAI,CAAA;gBACf,OAAO,IAAI,GAAG,CAAA,CAAC,mBAAmB;aACnC;iBAAM;gBACL,QAAQ,GAAG,KAAK,CAAA;aACjB;SACF;QAED,OAAO,IAAI,GAAG,CAAA;QACd,OAAO,OAAO;aACX,KAAK,CAAC,EAAE,CAAC;aACT,OAAO,EAAE;aACT,IAAI,CAAC,EAAE,CAAC,CAAA;IACb,CAAC;IAEO,cAAc,CAAC,GAAW;QAChC,iFAAiF;QACjF,qFAAqF;QACrF,WAAW;QACX,EAAE;QACF,qFAAqF;QACrF,uFAAuF;QACvF,2DAA2D;QAC3D,EAAE;QACF,gFAAgF;QAChF,EAAE;QACF,oFAAoF;QACpF,gFAAgF;QAChF,kFAAkF;QAClF,mFAAmF;QACnF,kFAAkF;QAClF,gEAAgE;QAChE,EAAE;QACF,kFAAkF;QAClF,2DAA2D;QAC3D,EAAE;QACF,kFAAkF;QAClF,gFAAgF;QAChF,mFAAmF;QACnF,8EAA8E;QAC9E,+EAA+E;QAC/E,oFAAoF;QACpF,wBAAwB;QAExB,IAAI,CAAC,GAAG,EAAE;YACR,2CAA2C;YAC3C,OAAO,IAAI,CAAA;SACZ;QAED,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACnE,sBAAsB;YACtB,OAAO,GAAG,CAAA;SACX;QAED,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC7C,+DAA+D;YAC/D,sCAAsC;YACtC,OAAO,IAAI,GAAG,GAAG,CAAA;SAClB;QAED,yBAAyB;QACzB,wBAAwB;QACxB,2BAA2B;QAC3B,yBAAyB;QACzB,6BAA6B;QAC7B,wBAAwB;QACxB,wBAAwB;QACxB,yBAAyB;QACzB,yBAAyB;QACzB,yBAAyB;QACzB,6BAA6B;QAC7B,0BAA0B;QAC1B,+BAA+B;QAC/B,yBAAyB;QACzB,sFAAsF;QACtF,gGAAgG;QAChG,IAAI,OAAO,GAAG,GAAG,CAAA;QACjB,IAAI,QAAQ,GAAG,IAAI,CAAA;QACnB,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,6BAA6B;YAC7B,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACrB,IAAI,QAAQ,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;gBACnC,OAAO,IAAI,IAAI,CAAA;aAChB;iBAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;gBAC7B,QAAQ,GAAG,IAAI,CAAA;gBACf,OAAO,IAAI,IAAI,CAAA;aAChB;iBAAM;gBACL,QAAQ,GAAG,KAAK,CAAA;aACjB;SACF;QAED,OAAO,IAAI,GAAG,CAAA;QACd,OAAO,OAAO;aACX,KAAK,CAAC,EAAE,CAAC;aACT,OAAO,EAAE;aACT,IAAI,CAAC,EAAE,CAAC,CAAA;IACb,CAAC;IAEO,iBAAiB,CAAC,OAAwB;QAChD,OAAO,GAAG,OAAO,IAAoB,EAAE,CAAA;QACvC,MAAM,MAAM,GAAmC;YAC7C,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;YAC/B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,wBAAwB,EAAE,OAAO,CAAC,wBAAwB,IAAI,KAAK;YACnE,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK;YAC3C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,KAAK;YACnD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;SAC9B,CAAA;QACD,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAqB,OAAO,CAAC,MAAM,CAAA;QACvE,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAqB,OAAO,CAAC,MAAM,CAAA;QACvE,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,gBAAgB,CACtB,OAAuB,EACvB,QAAgB;QAEhB,OAAO,GAAG,OAAO,IAAoB,EAAE,CAAA;QACvC,MAAM,MAAM,GAAuB,EAAE,CAAA;QACrC,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;QACxB,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;QACxB,MAAM,CAAC,0BAA0B,CAAC;YAChC,OAAO,CAAC,wBAAwB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAA;QACvD,IAAI,OAAO,CAAC,wBAAwB,EAAE;YACpC,MAAM,CAAC,KAAK,GAAG,IAAI,QAAQ,GAAG,CAAA;SAC/B;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;;;;OAQG;IACG,IAAI;;YACR,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC7C,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;gBAC1C,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;gBACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE;oBAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;iBACzB;gBAED,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE;oBACtD,cAAc,CAAC,SAAS,CAAC,KAAK,CAC5B,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,GAAG,CAChD,CAAA;iBACF;gBAED,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;gBAC1D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,OAAe,EAAE,EAAE;oBACpC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBACtB,CAAC,CAAC,CAAA;gBAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;gBACzC,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CACpB,QAAQ,EACR,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,EAClC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAC9C,CAAA;gBAED,MAAM,SAAS,GAAG,EAAE,CAAA;gBACpB,IAAI,EAAE,CAAC,MAAM,EAAE;oBACb,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;wBACpC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE;4BAC3D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;yBACpC;wBAED,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE;4BACtD,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;yBACrC;wBAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE;4BACxD,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE;gCAC5D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;6BACrC;wBACH,CAAC,CAAC,CAAA;oBACJ,CAAC,CAAC,CAAA;iBACH;gBAED,MAAM,SAAS,GAAG,EAAE,CAAA;gBACpB,IAAI,EAAE,CAAC,MAAM,EAAE;oBACb,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;wBACpC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;wBAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE;4BAC3D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;yBACpC;wBAED,IACE,CAAC,cAAc,CAAC,MAAM;4BACtB,cAAc,CAAC,SAAS;4BACxB,cAAc,CAAC,SAAS,EACxB;4BACA,MAAM,CAAC,GAAG,cAAc,CAAC,YAAY;gCACnC,CAAC,CAAC,cAAc,CAAC,SAAS;gCAC1B,CAAC,CAAC,cAAc,CAAC,SAAS,CAAA;4BAC5B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;yBACd;wBAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE;4BACxD,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE;gCAC5D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;6BACrC;wBACH,CAAC,CAAC,CAAA;oBACJ,CAAC,CAAC,CAAA;iBACH;gBAED,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;oBAC5B,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,OAAO,CAAA;oBAChC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;oBAC1B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;oBAC1B,KAAK,CAAC,aAAa,EAAE,CAAA;gBACvB,CAAC,CAAC,CAAA;gBAEF,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;oBAC7B,KAAK,CAAC,eAAe,GAAG,IAAI,CAAA;oBAC5B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;oBAC1B,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,wBAAwB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;oBACtE,KAAK,CAAC,aAAa,EAAE,CAAA;gBACvB,CAAC,CAAC,CAAA;gBAEF,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE;oBAC9B,KAAK,CAAC,eAAe,GAAG,IAAI,CAAA;oBAC5B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;oBAC1B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;oBAC1B,IAAI,CAAC,MAAM,CAAC,uCAAuC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;oBACpE,KAAK,CAAC,aAAa,EAAE,CAAA;gBACvB,CAAC,CAAC,CAAA;gBAEF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAY,EAAE,QAAgB,EAAE,EAAE;oBAClD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;wBACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;qBAChC;oBAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;wBACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;qBAChC;oBAED,EAAE,CAAC,kBAAkB,EAAE,CAAA;oBAEvB,IAAI,KAAK,EAAE;wBACT,MAAM,CAAC,KAAK,CAAC,CAAA;qBACd;yBAAM;wBACL,OAAO,CAAC,QAAQ,CAAC,CAAA;qBAClB;gBACH,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;KAAA;CACF;AA9eD,gCA8eC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,SAAiB;IAChD,MAAM,IAAI,GAAa,EAAE,CAAA;IAEzB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,GAAG,GAAG,EAAE,CAAA;IAEZ,SAAS,MAAM,CAAC,CAAS;QACvB,gCAAgC;QAChC,IAAI,OAAO,IAAI,CAAC,KAAK,GAAG,EAAE;YACxB,GAAG,IAAI,IAAI,CAAA;SACZ;QAED,GAAG,IAAI,CAAC,CAAA;QACR,OAAO,GAAG,KAAK,CAAA;IACjB,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACzC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAE7B,IAAI,CAAC,KAAK,GAAG,EAAE;YACb,IAAI,CAAC,OAAO,EAAE;gBACZ,QAAQ,GAAG,CAAC,QAAQ,CAAA;aACrB;iBAAM;gBACL,MAAM,CAAC,CAAC,CAAC,CAAA;aACV;YACD,SAAQ;SACT;QAED,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,EAAE;YACzB,MAAM,CAAC,CAAC,CAAC,CAAA;YACT,SAAQ;SACT;QAED,IAAI,CAAC,KAAK,IAAI,IAAI,QAAQ,EAAE;YAC1B,OAAO,GAAG,IAAI,CAAA;YACd,SAAQ;SACT;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;YAC1B,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE;gBAClB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBACd,GAAG,GAAG,EAAE,CAAA;aACT;YACD,SAAQ;SACT;QAED,MAAM,CAAC,CAAC,CAAC,CAAA;KACV;IAED,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE;QAClB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;KACtB;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAvDD,4CAuDC;AAED,MAAM,SAAU,SAAQ,MAAM,CAAC,YAAY;IACzC,YAAY,OAAuB,EAAE,QAAgB;QACnD,KAAK,EAAE,CAAA;QAaT,kBAAa,GAAY,KAAK,CAAA,CAAC,4DAA4D;QAC3F,iBAAY,GAAW,EAAE,CAAA;QACzB,oBAAe,GAAW,CAAC,CAAA;QAC3B,kBAAa,GAAY,KAAK,CAAA,CAAC,wCAAwC;QACvE,kBAAa,GAAY,KAAK,CAAA,CAAC,uCAAuC;QAC9D,UAAK,GAAG,KAAK,CAAA,CAAC,aAAa;QAC3B,SAAI,GAAY,KAAK,CAAA;QAErB,YAAO,GAAwB,IAAI,CAAA;QAnBzC,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;SAC9C;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,OAAO,CAAC,KAAK,EAAE;YACjB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;SAC3B;IACH,CAAC;IAaD,aAAa;QACX,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,OAAM;SACP;QAED,IAAI,IAAI,CAAC,aAAa,EAAE;YACtB,IAAI,CAAC,UAAU,EAAE,CAAA;SAClB;aAAM,IAAI,IAAI,CAAC,aAAa,EAAE;YAC7B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;SACrE;IACH,CAAC;IAEO,MAAM,CAAC,OAAe;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7B,CAAC;IAEO,UAAU;QAChB,sCAAsC;QACtC,IAAI,KAAwB,CAAA;QAC5B,IAAI,IAAI,CAAC,aAAa,EAAE;YACtB,IAAI,IAAI,CAAC,YAAY,EAAE;gBACrB,KAAK,GAAG,IAAI,KAAK,CACf,8DACE,IAAI,CAAC,QACP,4DACE,IAAI,CAAC,YACP,EAAE,CACH,CAAA;aACF;iBAAM,IAAI,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE;gBACvE,KAAK,GAAG,IAAI,KAAK,CACf,gBAAgB,IAAI,CAAC,QAAQ,2BAC3B,IAAI,CAAC,eACP,EAAE,CACH,CAAA;aACF;iBAAM,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;gBAC1D,KAAK,GAAG,IAAI,KAAK,CACf,gBACE,IAAI,CAAC,QACP,sEAAsE,CACvE,CAAA;aACF;SACF;QAED,oBAAoB;QACpB,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;SACpB;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,CAAA;IAChD,CAAC;IAEO,MAAM,CAAC,aAAa,CAAC,KAAgB;QAC3C,IAAI,KAAK,CAAC,IAAI,EAAE;YACd,OAAM;SACP;QAED,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,EAAE;YAC/C,MAAM,OAAO,GAAG,0CAA0C,KAAK,CAAC,KAAK;gBACnE,IAAI,4CACJ,KAAK,CAAC,QACR,0FAA0F,CAAA;YAC1F,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;SACtB;QAED,KAAK,CAAC,UAAU,EAAE,CAAA;IACpB,CAAC;CACF"}

View File

@ -1,67 +0,0 @@
{
"_args": [
[
"@actions/exec@1.0.1",
"/Users/peter.evans/git/create-pull-request"
]
],
"_from": "@actions/exec@1.0.1",
"_id": "@actions/exec@1.0.1",
"_inBundle": false,
"_integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ==",
"_location": "/@actions/exec",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "@actions/exec@1.0.1",
"name": "@actions/exec",
"escapedName": "@actions%2fexec",
"scope": "@actions",
"rawSpec": "1.0.1",
"saveSpec": null,
"fetchSpec": "1.0.1"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz",
"_spec": "1.0.1",
"_where": "/Users/peter.evans/git/create-pull-request",
"bugs": {
"url": "https://github.com/actions/toolkit/issues"
},
"description": "Actions exec lib",
"devDependencies": {
"@actions/io": "^1.0.1"
},
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"gitHead": "a2ab4bcf78e4f7080f0d45856e6eeba16f0bbc52",
"homepage": "https://github.com/actions/toolkit/tree/master/packages/exec",
"keywords": [
"github",
"actions",
"exec"
],
"license": "MIT",
"main": "lib/exec.js",
"name": "@actions/exec",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/actions/toolkit.git"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1",
"tsc": "tsc"
},
"version": "1.0.1"
}

61
package-lock.json generated
View File

@ -1,18 +1,71 @@
{
"name": "create-pull-request",
"version": "1.2.1",
"version": "1.8.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@actions/core": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.1.tgz",
"integrity": "sha512-O5G6EmlzTVsng7VSpNtszIoQq6kOgMGNTFB/hmwKNNA4V71JyxImCIrL27vVHCt2Cb3ImkaCr6o27C2MV9Ylwg=="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.0.tgz",
"integrity": "sha512-ZKdyhlSlyz38S6YFfPnyNgCDZuAF2T0Qv5eHflNWytPS8Qjvz39bZFMry9Bb/dpSnqWcNeav5yM2CTYpJeY+Dw=="
},
"@actions/exec": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz",
"integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ=="
},
"@actions/io": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz",
"integrity": "sha512-rhq+tfZukbtaus7xyUtwKfuiCRXd1hWSfmJNEpFgBQJ4woqPEpsBw04awicjwz9tyG2/MVhAEMfVn664Cri5zA=="
},
"@actions/tool-cache": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.1.2.tgz",
"integrity": "sha512-IJczPaZr02ECa3Lgws/TJEVco9tjOujiQSZbO3dHuXXjhd5vrUtfOgGwhmz3/f97L910OraPZ8SknofUk6RvOQ==",
"requires": {
"@actions/core": "^1.1.0",
"@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1",
"semver": "^6.1.0",
"typed-rest-client": "^1.4.0",
"uuid": "^3.3.2"
}
},
"@zeit/ncc": {
"version": "0.20.5",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"tunnel": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz",
"integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM="
},
"typed-rest-client": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.5.0.tgz",
"integrity": "sha512-DVZRlmsfnTjp6ZJaatcdyvvwYwbWvR4YDNFDqb+qdTxpvaVP99YCpBkA8rxsLtAPjBVoDe4fNsnMIdZTiPuKWg==",
"requires": {
"tunnel": "0.0.4",
"underscore": "1.8.3"
}
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
},
"uuid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
}
}
}

View File

@ -1,22 +1,28 @@
{
"name": "create-pull-request",
"version": "1.2.1",
"version": "1.9.1",
"description": "Creates a pull request for changes to your repository in the actions workspace",
"main": "index.js",
"scripts": {
"package": "ncc build index.js -o dist"
},
"repository": {
"type": "git",
"url": "git+https://github.com/peter-evans/create-pull-request.git"
},
"keywords": [
"GitHub",
"Actions",
"Pull Request"
],
"keywords": [],
"author": "Peter Evans",
"license": "MIT",
"bugs": {
"url": "https://github.com/peter-evans/create-pull-request/issues"
},
"homepage": "https://github.com/peter-evans/create-pull-request",
"dependencies": {
"@actions/core": "^1.1.1",
"@actions/exec": "^1.0.1"
"@actions/exec": "^1.0.1",
"@actions/tool-cache": "^1.1.2"
},
"devDependencies": {
"@zeit/ncc": "0.20.5"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

View File

@ -1,2 +0,0 @@
GitPython==3.0.2
PyGithub==1.43.8

352
src/create-pull-request.py Executable file
View File

@ -0,0 +1,352 @@
#!/usr/bin/env python3
""" Create Pull Request """
import json
import os
import random
import string
import sys
import time
from git import Repo
from github import Github, GithubException
def get_github_event(github_event_path):
with open(github_event_path) as f:
github_event = json.load(f)
if bool(os.environ.get("DEBUG_EVENT")):
print(os.environ["GITHUB_EVENT_NAME"])
print(json.dumps(github_event, sort_keys=True, indent=2))
return github_event
def get_head_short_sha1(repo):
return repo.git.rev_parse("--short", "HEAD")
def get_random_suffix(size=7, chars=string.ascii_lowercase + string.digits):
return "".join(random.choice(chars) for _ in range(size))
def remote_branch_exists(repo, branch):
for ref in repo.remotes.origin.refs:
if ref.name == ("origin/%s" % branch):
return True
return False
def get_author_default(event_name, event_data):
if event_name == "push":
email = "{head_commit[author][email]}".format(**event_data)
name = "{head_commit[author][name]}".format(**event_data)
else:
email = os.environ["GITHUB_ACTOR"] + "@users.noreply.github.com"
name = os.environ["GITHUB_ACTOR"]
return email, name
def get_repo_url(token, github_repository):
return "https://x-access-token:%s@github.com/%s" % (token, github_repository)
def checkout_branch(git, remote_exists, branch):
if remote_exists:
print("Checking out branch '%s'" % branch)
git.stash("--include-untracked")
git.checkout(branch)
try:
git.stash("pop")
except BaseException:
git.checkout("--theirs", ".")
git.reset()
else:
print("Creating new branch '%s'" % branch)
git.checkout("HEAD", b=branch)
def push_changes(git, token, github_repository, branch, commit_message):
git.add("-A")
git.commit(m=commit_message)
repo_url = get_repo_url(token, github_repository)
return git.push("-f", repo_url, f"HEAD:refs/heads/{branch}")
def cs_string_to_list(str):
# Split the comma separated string into a list
l = [i.strip() for i in str.split(",")]
# Remove empty strings
return list(filter(None, l))
def create_project_card(github_repo, project_name, project_column_name, pull_request):
# Locate the project by name
project = None
for project_item in github_repo.get_projects("all"):
if project_item.name == project_name:
project = project_item
break
if not project:
print("::warning::Project not found. Unable to create project card.")
return
# Locate the column by name
column = None
for column_item in project.get_columns():
if column_item.name == project_column_name:
column = column_item
break
if not column:
print("::warning::Project column not found. Unable to create project card.")
return
# Create a project card for the pull request
column.create_card(content_id=pull_request.id, content_type="PullRequest")
print(
"Added pull request #%d to project '%s' under column '%s'"
% (pull_request.number, project.name, column.name)
)
def process_event(github_token, github_repository, repo, branch, base):
# Fetch optional environment variables with default values
commit_message = os.getenv(
"COMMIT_MESSAGE", "Auto-committed changes by create-pull-request action"
)
title = os.getenv(
"PULL_REQUEST_TITLE", "Auto-generated by create-pull-request action"
)
body = os.getenv(
"PULL_REQUEST_BODY",
"Auto-generated pull request by "
"[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action",
)
# Fetch optional environment variables with no default values
pull_request_labels = os.environ.get("PULL_REQUEST_LABELS")
pull_request_assignees = os.environ.get("PULL_REQUEST_ASSIGNEES")
pull_request_milestone = os.environ.get("PULL_REQUEST_MILESTONE")
pull_request_reviewers = os.environ.get("PULL_REQUEST_REVIEWERS")
pull_request_team_reviewers = os.environ.get("PULL_REQUEST_TEAM_REVIEWERS")
project_name = os.environ.get("PROJECT_NAME")
project_column_name = os.environ.get("PROJECT_COLUMN_NAME")
# Push the local changes to the remote branch
print("Pushing changes to 'origin/%s'" % branch)
push_result = push_changes(
repo.git, github_token, github_repository, branch, commit_message
)
print(push_result)
# 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
)
print(
"Created pull request #%d (%s => %s)" % (pull_request.number, branch, base)
)
except GithubException as e:
if e.status == 422:
# Format the branch name
head_branch = "%s:%s" % (github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
print(
"Updated pull request #%d (%s => %s)"
% (pull_request.number, branch, base)
)
else:
print(str(e))
sys.exit(1)
# Set the output variables
os.system("echo ::set-env name=PULL_REQUEST_NUMBER::%d" % pull_request.number)
os.system("echo ::set-output name=pr_number::%d" % pull_request.number)
# Set labels, assignees and milestone
if pull_request_labels is not None:
print("Applying labels '%s'" % pull_request_labels)
pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels))
if pull_request_assignees is not None:
print("Applying assignees '%s'" % pull_request_assignees)
pull_request.as_issue().edit(
assignees=cs_string_to_list(pull_request_assignees)
)
if pull_request_milestone is not None:
print("Applying milestone '%s'" % pull_request_milestone)
milestone = github_repo.get_milestone(int(pull_request_milestone))
pull_request.as_issue().edit(milestone=milestone)
# Set pull request reviewers
if pull_request_reviewers is not None:
print("Requesting reviewers '%s'" % pull_request_reviewers)
try:
pull_request.create_review_request(
reviewers=cs_string_to_list(pull_request_reviewers)
)
except GithubException as e:
# Likely caused by "Review cannot be requested from pull request
# author."
if e.status == 422:
print("Requesting reviewers failed - %s" % e.data["message"])
# Set pull request team reviewers
if pull_request_team_reviewers is not None:
print("Requesting team reviewers '%s'" % pull_request_team_reviewers)
pull_request.create_review_request(
team_reviewers=cs_string_to_list(pull_request_team_reviewers)
)
# Create a project card for the pull request
if project_name is not None and project_column_name is not None:
try:
create_project_card(
github_repo, project_name, project_column_name, pull_request
)
except GithubException as e:
# Likely caused by "Project already has the associated issue."
if e.status == 422:
print(
"Create project card failed - %s" % e.data["errors"][0]["message"]
)
# Fetch environment variables
github_token = os.environ["GITHUB_TOKEN"]
github_repository = os.environ["GITHUB_REPOSITORY"]
github_ref = os.environ["GITHUB_REF"]
event_name = os.environ["GITHUB_EVENT_NAME"]
# Get the JSON event data
event_data = get_github_event(os.environ["GITHUB_EVENT_PATH"])
# Get the default for author email and name
author_email, author_name = get_author_default(event_name, event_data)
# Set author name and email overrides
author_name = os.getenv("COMMIT_AUTHOR_NAME", author_name)
author_email = os.getenv("COMMIT_AUTHOR_EMAIL", author_email)
# Set committer name and email overrides
committer_name = os.getenv("COMMITTER_NAME", author_name)
committer_email = os.getenv("COMMITTER_EMAIL", author_email)
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Set git environment. This will not persist after the action completes.
print("Configuring git author as '%s <%s>'" % (author_name, author_email))
print("Configuring git committer as '%s <%s>'" % (committer_name, committer_email))
repo.git.update_environment(
GIT_AUTHOR_NAME=author_name,
GIT_AUTHOR_EMAIL=author_email,
GIT_COMMITTER_NAME=committer_name,
GIT_COMMITTER_EMAIL=committer_email,
)
# Fetch/Set the branch name
branch_prefix = os.getenv("PULL_REQUEST_BRANCH", "create-pull-request/patch")
# Fetch an optional base branch override
base_override = os.environ.get("PULL_REQUEST_BASE")
# Set the base branch
if base_override is not None:
base = base_override
print("Overriding the base with branch '%s'" % base)
checkout_branch(repo.git, True, base)
elif github_ref.startswith("refs/pull/"):
# Check the PR is not raised from a fork of the repository
head_repo = "{pull_request[head][repo][full_name]}".format(**event_data)
if head_repo != github_repository:
print(
"::warning::Pull request was raised from a fork of the repository. "
+ "Limitations on forked repositories have been imposed by GitHub Actions. "
+ "Unable to continue. Exiting."
)
sys.exit()
# Switch to the merging branch instead of the merge commit
base = os.environ["GITHUB_HEAD_REF"]
print(
"Removing the merge commit by switching to the pull request head branch '%s'"
% base
)
checkout_branch(repo.git, True, base)
elif github_ref.startswith("refs/heads/"):
base = github_ref[11:]
print("Currently checked out base assumed to be branch '%s'" % base)
else:
print(
f"::warning::Currently checked out ref '{github_ref}' is not a valid base for a pull request. "
+ "Unable to continue. Exiting."
)
sys.exit()
# Skip if the current branch is a PR branch created by this action.
# This may occur when using a PAT instead of GITHUB_TOKEN because
# a PAT allows workflow actions to trigger further events.
if base.startswith(branch_prefix):
print("Branch '%s' was created by this action. Skipping." % base)
sys.exit()
# Fetch an optional environment variable to determine the branch suffix
branch_suffix = os.getenv("BRANCH_SUFFIX", "short-commit-hash")
if branch_suffix == "short-commit-hash":
# Suffix with the short SHA1 hash
branch = "%s-%s" % (branch_prefix, get_head_short_sha1(repo))
elif branch_suffix == "timestamp":
# Suffix with the current timestamp
branch = "%s-%s" % (branch_prefix, int(time.time()))
elif branch_suffix == "random":
# Suffix with the current timestamp
branch = "%s-%s" % (branch_prefix, get_random_suffix())
elif branch_suffix == "none":
# Fixed branch name
branch = branch_prefix
else:
print("Branch suffix '%s' is not a valid value." % branch_suffix)
sys.exit(1)
# Output head branch
print("Pull request branch to create/update set to '%s'" % branch)
# Check if the determined head branch exists as a remote
remote_exists = remote_branch_exists(repo, branch)
if remote_exists:
print(
"Pull request branch '%s' already exists as remote branch 'origin/%s'"
% (branch, branch)
)
if branch_suffix == "short-commit-hash":
# A remote branch already exists for the HEAD commit
print(
"Pull request branch '%s' already exists for this commit. Skipping."
% branch
)
sys.exit()
elif branch_suffix in ["timestamp", "random"]:
# Generated branch name collision with an existing branch
print(
"Pull request branch '%s' collided with a branch of the same name. Please re-run."
% branch
)
sys.exit(1)
# Checkout branch
checkout_branch(repo.git, remote_exists, branch)
# Check if there are changes to pull request
if remote_exists:
print(
"Checking for local working copy changes indicating a "
+ "diff with existing pull request branch 'origin/%s'" % branch
)
else:
print(
"Checking for local working copy changes indicating a "
+ "diff with base 'origin/%s'" % base
)
if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Modified or untracked files detected.")
process_event(github_token, github_repository, repo, branch, base)
else:
print("No modified or untracked files detected. Skipping.")

2
src/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
GitPython==3.0.5
PyGithub==1.44.1

52
src/setup-python.js Normal file
View File

@ -0,0 +1,52 @@
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;