Compare commits

..

78 Commits
v2.7.1 ... v2

Author SHA1 Message Date
4d3b0a48ef Merge pull request #394 from peter-evans/update-distribution
Update distribution
2020-06-27 17:10:28 +09:00
e9a825aacd Update distribution 2020-06-27 08:06:58 +00:00
3509fd45ae Merge pull request #389 from peter-evans/dev
Parse repo urls with credentials
2020-06-27 17:03:41 +09:00
14ee9d1df2 Parse repo urls with credentials 2020-06-27 16:45:24 +09:00
5d969a55c1 Add gradle example 2020-06-05 18:23:04 +09:00
44130f6fc9 Merge pull request #369 from peter-evans/types
Add missing types
2020-06-03 17:09:43 +09:00
86ccd8cdef Add missing types 2020-06-03 16:47:02 +09:00
7e7fa32a5f Merge pull request #364 from peter-evans/fix-ci
Fix ci artifacts
2020-06-02 18:21:51 +09:00
5f7beeb2ff Fix ci artifacts 2020-06-02 18:16:23 +09:00
926d56fcba Update documentation 2020-06-02 16:44:14 +09:00
8d744a2cd3 Remove reaction-token 2020-06-02 15:58:02 +09:00
c2d829c681 Update documentation 2020-05-27 11:43:25 +09:00
d77392faf0 Update slash command dispatch token 2020-05-25 17:15:16 +09:00
ccd2b64012 Add rebase slash command 2020-05-25 16:12:13 +09:00
58fb221778 Merge pull request #339 from peter-evans/update-distribution
Update distribution
2020-05-24 09:36:26 +09:00
7a856e8b5d Update distribution 2020-05-24 00:34:21 +00:00
65d7a66451 Merge pull request #293 from peter-evans/renovate/setuptools-46.x
Update dependency setuptools to v46.4.0
2020-05-24 09:30:21 +09:00
44a7f59b6f Update dependency setuptools to v46.4.0 2020-05-23 06:24:24 +00:00
8acaf6bb4c Merge pull request #330 from peter-evans/int-tests
Integration testing
2020-05-23 15:16:37 +09:00
498d78cb23 Add integration testing 2020-05-23 14:43:18 +09:00
172ec762f8 Merge pull request #301 from peter-evans/update-distribution
Update distribution
2020-05-17 18:28:48 +09:00
5cb0d674f3 Update distribution 2020-05-17 09:26:30 +00:00
eb892d7803 Merge pull request #308 from peter-evans/typescript
Typescript
2020-05-17 18:24:18 +09:00
f8274253bd Convert to typescript 2020-05-17 18:02:41 +09:00
0f423da02c Merge pull request #315 from peter-evans/input-def
Add missing draft input definition
2020-05-17 17:55:03 +09:00
9573f479a0 Add missing draft input definition 2020-05-17 17:47:54 +09:00
eb4cde120d Update documentation 2020-05-17 14:42:46 +09:00
25902ccdd1 Remove dockerhub-description workflow 2020-05-16 14:36:18 +09:00
39b337e8bb Remove codeowners 2020-05-14 10:19:06 +09:00
7e70d8e63c Skip test job for pull requests from forks 2020-05-13 17:25:18 +09:00
1a640f5b01 Update README 2020-05-11 14:31:26 +09:00
9faa8dc1d9 Update pull request example image 2020-05-11 14:28:02 +09:00
afcf57957d Merge pull request #287 from peter-evans/update-distribution
Update distribution
2020-05-11 14:09:44 +09:00
8cc3564bf3 Update distribution 2020-05-11 05:09:19 +00:00
6910c5cd03 Merge pull request #271 from peter-evans/renovate/setuptools-46.x
Update dependency setuptools to v46.2.0
2020-05-11 14:07:27 +09:00
14836c6ff3 Update dependency setuptools to v46.2.0 2020-05-11 05:04:42 +00:00
8fbfcfbcbb Revert "Temporarily use deprecated output"
This reverts commit fbb7e0e650.
2020-05-11 14:01:43 +09:00
326f260418 Merge pull request #278 from peter-evans/update-distribution
Update distribution
2020-05-11 13:59:07 +09:00
75104b7d7e Update distribution 2020-05-11 04:58:23 +00:00
fbb7e0e650 Temporarily use deprecated output 2020-05-11 13:55:32 +09:00
0f1e60a1f8 Merge pull request #264 from peter-evans/dev
Deprecate pr_number, project and project-column
2020-05-11 13:50:08 +09:00
caa116d991 Deprecate project and project-column 2020-05-10 19:02:35 +09:00
d2f72f0799 Update workflows 2020-05-10 18:09:48 +09:00
ded05960f3 Deprecate pr_number output 2020-05-10 18:06:32 +09:00
eb605db8a3 Fix casing 2020-05-10 17:58:21 +09:00
b11e4c665b Merge pull request #263 from christopherthielen/patch-1
docs: request-on-parent  ->  request-to-parent
2020-05-09 07:43:25 +09:00
65327d17a5 docs: request-on-parent -> request-to-parent 2020-05-08 11:03:56 -07:00
0837238e66 Merge pull request #239 from peter-evans/update-distribution
Update distribution
2020-05-06 12:47:46 +09:00
17bd947e89 Update distribution 2020-05-06 03:42:38 +00:00
24b42ba7f4 Merge pull request #240 from peter-evans/renovate/gitpython-3.x
Update dependency GitPython to v3.1.2
2020-05-06 12:40:52 +09:00
c0aaf5bab9 Update documentation 2020-05-06 11:37:48 +09:00
968cb0f4d9 Ignore documentation paths 2020-05-06 11:31:35 +09:00
9d6f73d546 Update documentation 2020-05-06 11:23:37 +09:00
70d240d0c4 Add update dependencies workflow 2020-05-06 10:51:06 +09:00
7bb7d96c96 Update dependency GitPython to v3.1.2 2020-05-06 01:49:21 +00:00
66fcd19e8d Whitelist pip requirements updates 2020-05-06 10:46:29 +09:00
d93f2b46fd Update dependency jest to v26.0.1 2020-05-05 12:23:22 +00:00
246328e3d8 Add ci badge 2020-05-05 14:24:35 +09:00
61cff7c673 Update dependency jest to v26 2020-05-04 19:59:11 +00:00
46ba7bdfe8 Merge pull request #229 from peter-evans/update-distribution
Update distribution
2020-05-03 12:18:11 +09:00
d650be7389 Update distribution 2020-05-03 03:15:56 +00:00
2f7173349f Fix dist requirements version 2020-05-03 12:13:39 +09:00
4ca95026d7 Ignore dist for renovate updates 2020-05-03 12:12:19 +09:00
64c4efd526 Merge pull request #219 from peter-evans/renovate/pygithub-1.x
Update dependency PyGithub to v1.51
2020-05-03 11:46:05 +09:00
16e35685ce Update dependency PyGithub to v1.51 2020-05-03 02:36:00 +00:00
3b12cf0165 Merge pull request #220 from peter-evans/fix-ci
Fix CI workflow
2020-05-03 11:35:02 +09:00
2a283f5fc3 Fix ci workflow 2020-05-03 11:31:45 +09:00
8ed207bcca Merge pull request #214 from peter-evans/update-distribution
Update distribution
2020-05-02 21:56:54 +09:00
bd1f6727cd Update distribution 2020-05-02 11:27:54 +00:00
9a3acf8f32 Update dependency jest to v25.5.4 2020-05-02 11:26:02 +00:00
b38fd9eb87 Merge pull request #206 from peter-evans/renovate/actions-tool-cache-1.x
Update dependency @actions/tool-cache to v1.3.4
2020-05-02 19:28:31 +09:00
4a9e76e377 Update dependency @actions/tool-cache to v1.3.4 2020-05-02 09:57:02 +00:00
8cb4c8b741 Merge pull request #201 from peter-evans/update-distribution
Update distribution
2020-05-02 17:47:24 +09:00
b9eb5dd95e Update distribution 2020-05-02 08:45:04 +00:00
5502904068 Merge pull request #191 from peter-evans/renovate/actions-core-1.x
Update dependency @actions/core to v1.2.4
2020-05-02 17:43:01 +09:00
56ad1fed7b Update dependency @actions/core to v1.2.4 2020-05-02 08:40:54 +00:00
2132f428f6 Merge pull request #192 from peter-evans/renovate/actions-exec-1.x
Update dependency @actions/exec to v1.0.4
2020-05-02 17:40:28 +09:00
c558d39395 Update dependency @actions/exec to v1.0.4 2020-05-02 08:30:46 +00:00
57 changed files with 5714 additions and 4260 deletions

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
dist/
lib/
node_modules/

View File

@ -1,17 +1,19 @@
{ {
"env": { "env": { "node": true, "jest": true },
"commonjs": true, "parser": "@typescript-eslint/parser",
"es6": true, "parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
"node": true "extends": [
}, "eslint:recommended",
"extends": "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended",
"globals": { "plugin:@typescript-eslint/recommended",
"Atomics": "readonly", "plugin:import/errors",
"SharedArrayBuffer": "readonly" "plugin:import/warnings",
}, "plugin:import/typescript",
"parserOptions": { "plugin:prettier/recommended",
"ecmaVersion": 2018 "prettier/@typescript-eslint"
}, ],
"rules": { "plugins": ["@typescript-eslint"],
} "rules": {
} "@typescript-eslint/camelcase": "off"
}
}

1
.github/CODEOWNERS vendored
View File

@ -1 +0,0 @@
* @peter-evans

View File

@ -2,8 +2,14 @@ name: CI
on: on:
push: push:
branches: [master] branches: [master]
paths-ignore:
- 'README.md'
- 'docs/**'
pull_request: pull_request:
branches: [master] branches: [master]
paths-ignore:
- 'README.md'
- 'docs/**'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -17,31 +23,41 @@ jobs:
python-version: '3.x' python-version: '3.x'
- run: npm ci - run: npm ci
- run: npm run clean - run: npm run clean
- run: npm run build
- run: npm run format-check
- run: npm run lint
- run: npm run test - run: npm run test
- run: npm run package - run: npm run package
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: dist name: dist
path: dist path: dist
- uses: actions/upload-artifact@v2
with:
name: action.yml
path: action.yml
test: test:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
needs: [build] needs: [build]
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
target: [built, committed] target: [built, committed]
steps: steps:
- if: github.event_name == 'push' - uses: actions/checkout@v2
uses: actions/checkout@v2
- if: github.event_name == 'pull_request'
uses: actions/checkout@v2
with: with:
ref: ${{ github.head_ref }} ref: master
- if: matrix.target == 'built' - if: matrix.target == 'built' || github.event_name == 'pull_request'
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
with: with:
name: dist name: dist
path: dist path: dist
- if: matrix.target == 'built' || github.event_name == 'pull_request'
uses: actions/download-artifact@v2
with:
name: action.yml
path: .
- name: Create change - name: Create change
run: date +%s > report.txt run: date +%s > report.txt
@ -65,7 +81,7 @@ jobs:
- name: Close Pull - name: Close Pull
uses: peter-evans/close-pull@v1 uses: peter-evans/close-pull@v1
with: with:
pull-request-number: ${{ steps.cpr.outputs.pr_number }} pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
comment: '[CI] test ${{ matrix.target }}' comment: '[CI] test ${{ matrix.target }}'
delete-branch: true delete-branch: true
@ -99,6 +115,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: rm -rf dist
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v2
with: with:
name: dist name: dist

View File

@ -7,8 +7,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Create report file - name: Create report file
run: date +%s > report.txt run: date +%s > report.txt
- name: Create Pull Request - name: Create Pull Request
id: cpr id: cpr
uses: ./ uses: ./
@ -27,15 +29,15 @@ jobs:
assignees: peter-evans assignees: peter-evans
reviewers: peter-evans reviewers: peter-evans
milestone: 1 milestone: 1
project: Example Project
project-column: To do
draft: false draft: false
branch: example-patches branch: example-patches
request-to-parent: false request-to-parent: false
- name: Check outputs - name: Check outputs
run: | run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}" echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}" echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
- name: Add reaction - name: Add reaction
uses: peter-evans/create-or-update-comment@v1 uses: peter-evans/create-or-update-comment@v1
with: with:

View File

@ -1,19 +0,0 @@
name: Update Docker Hub Description
on:
push:
branches:
- master
paths:
- README.md
- .github/workflows/dockerhub-description.yml
jobs:
dockerHubDescription:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v2.1.0
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
DOCKERHUB_REPOSITORY: peterevans/create-pull-request

View File

@ -9,8 +9,7 @@ jobs:
- name: Slash Command Dispatch - name: Slash Command Dispatch
uses: peter-evans/slash-command-dispatch@v1 uses: peter-evans/slash-command-dispatch@v1
with: with:
token: ${{ secrets.REPO_ACCESS_TOKEN }} token: ${{ secrets.ACTIONS_BOT_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
config: > config: >
[ [
{ {
@ -34,5 +33,11 @@ jobs:
"command": "cpr-example", "command": "cpr-example",
"permission": "admin", "permission": "admin",
"issue_type": "issue" "issue_type": "issue"
},
{
"command": "rebase",
"permission": "admin",
"repository": "peter-evans/slash-command-dispatch-processor",
"issue_type": "pull-request"
} }
] ]

31
.github/workflows/update-dep.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Update Dependencies
on:
schedule:
- cron: '0 1 * * 4'
jobs:
update-dep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: Update dependencies
run: |
npx -p npm-check-updates ncu -u
npm install
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
commit-message: Update dependencies
committer: GitHub <noreply@github.com>
author: actions-bot <actions-bot@users.noreply.github.com>
title: Update dependencies
body: |
- Dependency updates
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
__pycache__ __pycache__
.python-version .python-version
node_modules lib/
node_modules/
.DS_Store .DS_Store

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
dist/
lib/
node_modules/

11
.prettierrc.json Normal file
View File

@ -0,0 +1,11 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

View File

@ -1,4 +1,5 @@
# <img width="24" height="24" src="docs/assets/logo.svg"> Create Pull Request # <img width="24" height="24" src="docs/assets/logo.svg"> Create Pull Request
[![CI](https://github.com/peter-evans/create-pull-request/workflows/CI/badge.svg)](https://github.com/peter-evans/create-pull-request/actions?query=workflow%3ACI)
[![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) [![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. A GitHub action to create a pull request for changes to your repository in the actions workspace.
@ -51,15 +52,15 @@ All inputs are **optional**. If not set, sensible default values will be used.
| `reviewers` | A comma separated list of reviewers (GitHub usernames) to request a review from. | | | `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. A `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) may be required. See [this issue](https://github.com/peter-evans/create-pull-request/issues/155). | | | `team-reviewers` | A comma separated list of GitHub teams to request a review from. A `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) may be required. See [this issue](https://github.com/peter-evans/create-pull-request/issues/155). | |
| `milestone` | The number of the milestone to associate this pull request with. | | | `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` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
| `project-column` | The name of the project column under which a card should be created. Requires `project`. | | | `project-column` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
| `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` | | `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` |
| `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` | | `branch` | The branch name. See [Action behaviour](#action-behaviour) for details. | `create-pull-request/patch` |
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` | | `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` |
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. | | `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Branch naming](#branch-naming) for details. | | | `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Action behaviour](#action-behaviour) for details. | |
**Outputs** ### Action outputs
The pull request number is output as both an environment variable and a step output. 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. Note that in order to read the step output the action step must have an id.
@ -71,7 +72,7 @@ Note that in order to read the step output the action step must have an id.
- name: Check outputs - name: Check outputs
run: | run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}" echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}" echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
``` ```
### Checkout ### Checkout
@ -85,20 +86,29 @@ If there is some reason you need to use `actions/checkout@v1` the following step
- run: git checkout "${GITHUB_REF:11}" - run: git checkout "${GITHUB_REF:11}"
``` ```
### Branch naming ### Action behaviour
For branch naming there are two strategies. Create a fixed-name pull request branch that will be updated with new changes until it is merged or closed, OR, always create a new unique branch each time there are changes to be committed. The default behaviour of the action is to create a pull request that will be continually updated with new changes until it is merged or closed.
Changes are committed and pushed to a fixed-name branch, the name of which can be configured with the `branch` input.
Any subsequent changes will be committed to the *same* branch and reflected in the open pull request.
#### Strategy A - Create and update a pull request branch (default) How the action behaves:
This strategy is the default behaviour of the action. The input `branch` defaults to `create-pull-request/patch`. Changes will be committed to this branch and a pull request created. Any subsequent changes will be committed to the *same* branch and reflected in the open pull request. If the pull request is merged or closed a new one will be created. If subsequent changes cause the branch to no longer differ from the base the pull request will be automatically closed and the branch deleted. - If there are changes (i.e. a diff exists with the checked out base branch), the changes will be pushed to a new `branch` and a pull request created.
- If there are no changes (i.e. no diff exists with the checked out base branch), no pull request will be created and the action exits silently.
- If a pull request already exists and there are no further changes (i.e. no diff with the current pull request branch) then the action exits silently.
- If a pull request exists and new changes on the base branch make the pull request unnecessary (i.e. there is no longer a diff between the base and pull request branch), the pull request is automatically closed and the branch deleted.
#### Strategy B - Always create a new pull request branch For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
For this strategy there are three options to suffix the branch name. #### Alternative strategy - Always create a new pull request branch
The branch name is defined by the input `branch` and defaults to `create-pull-request/patch`. The following options are values for `branch-suffix`.
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. This option should be used if multiple pull requests will be created during the execution of a workflow. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd` For some use cases it *may* be desirable to always create a new unique branch each time there are changes to be committed.
This strategy is not recommended and mainly kept for backwards compatibility.
To use this strategy, set input `branch-suffix` with one of the following options.
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd`
- `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552` - `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552`
@ -143,6 +153,23 @@ As well as relying on the action to handle uncommitted changes, you can addition
uses: peter-evans/create-pull-request@v2 uses: peter-evans/create-pull-request@v2
``` ```
### Create a project card
To create a project card for the pull request, pass the `pull-request-number` step output to [create-or-update-project-card](https://github.com/peter-evans/create-or-update-project-card) action.
```yml
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v2
- name: Create or Update Project Card
uses: peter-evans/create-or-update-project-card@v1
with:
project-name: My project
column-name: My column
issue-number: ${{ steps.cpr.outputs.pull-request-number }}
```
## Reference Example ## Reference Example
The following workflow is a reference example that sets all the main inputs. The following workflow is a reference example that sets all the main inputs.
@ -179,18 +206,16 @@ jobs:
reviewers: peter-evans reviewers: peter-evans
team-reviewers: owners, maintainers team-reviewers: owners, maintainers
milestone: 1 milestone: 1
project: Example Project
project-column: To do
draft: false draft: false
branch: example-patches branch: example-patches
request-to-parent: false request-to-parent: false
- name: Check outputs - name: Check outputs
run: | run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}" echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}" echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
``` ```
This reference configuration will create pull requests that look like this: An example based on the above reference configuration creates pull requests that look like this:
![Pull Request Example](docs/assets/pull-request-example.png) ![Pull Request Example](docs/assets/pull-request-example.png)

29
__test__/entrypoint.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/sh -l
set -euo pipefail
# Save the working directory
WORKINGDIR=$PWD
# Serve remote repo
mkdir /git
git init --bare /git/test-repo.git
git daemon --verbose --enable=receive-pack --base-path=/git --export-all /git/test-repo.git &>/dev/null &
# Give the daemon time to start
sleep 2
# Clone and make an initial commit
git clone git://127.0.0.1/test-repo.git /git/test-repo
cd /git/test-repo
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
echo "#test-repo" > README.md
git add .
git commit -m "initial commit"
git push -u
# Restore the working directory
cd $WORKINGDIR
# Execute integration tests
jest int

153
__test__/git.int.test.ts Normal file
View File

@ -0,0 +1,153 @@
import {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
} from '../lib/git'
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
describe('git tests', () => {
beforeAll(() => {
// GitHub workspace
process.env['GITHUB_WORKSPACE'] = '/git/test-repo'
})
afterAll(() => {
// Restore GitHub workspace
delete process.env['GITHUB_WORKSPACE']
if (originalGitHubWorkspace) {
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
}
})
it('successfully executes a git command', async () => {
const repoPath = getRepoPath()
const result = await execGit(
repoPath,
['config', '--local', '--name-only', '--get-regexp', 'remote.origin.url'],
true
)
expect(result.exitCode).toEqual(0)
expect(result.stdout.trim()).toEqual('remote.origin.url')
})
it('adds and unsets a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.add.and.unset.config.option',
'foo'
)
expect(add).toBeTruthy()
const unset = await unsetConfigOption(
repoPath,
'test.add.and.unset.config.option'
)
expect(unset).toBeTruthy()
})
it('adds and unsets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.add.and.unset.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const unset = await unsetConfigOption(
repoPath,
'test.add.and.unset.config.option',
'^foo'
)
expect(unset).toBeTruthy()
})
it('determines that a config option exists', async () => {
const repoPath = getRepoPath()
const result = await configOptionExists(repoPath, 'remote.origin.url')
expect(result).toBeTruthy()
})
it('determines that a config option does not exist', async () => {
const repoPath = getRepoPath()
const result = await configOptionExists(repoPath, 'this.key.does.not.exist')
expect(result).toBeFalsy()
})
it('successfully retrieves a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(repoPath, 'test.get.config.option', 'foo')
expect(add).toBeTruthy()
const option = await getConfigOption(repoPath, 'test.get.config.option')
expect(option.value).toEqual('foo')
const unset = await unsetConfigOption(repoPath, 'test.get.config.option')
expect(unset).toBeTruthy()
})
it('gets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const option = await getConfigOption(
repoPath,
'test.get.config.option',
'^foo'
)
expect(option.value).toEqual('foo bar')
const unset = await unsetConfigOption(
repoPath,
'test.get.config.option',
'^foo'
)
expect(unset).toBeTruthy()
})
it('gets and unsets a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.and.unset.config.option',
'foo'
)
expect(add).toBeTruthy()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'test.get.and.unset.config.option'
)
expect(getAndUnset.value).toEqual('foo')
})
it('gets and unsets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.and.unset.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'test.get.and.unset.config.option',
'^foo'
)
expect(getAndUnset.value).toEqual('foo bar')
})
it('fails to get and unset a config option', async () => {
const repoPath = getRepoPath()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'this.key.does.not.exist'
)
expect(getAndUnset.name).toEqual('')
expect(getAndUnset.value).toEqual('')
})
})

26
__test__/git.unit.test.ts Normal file
View File

@ -0,0 +1,26 @@
import * as path from 'path'
import {getRepoPath} from '../lib/git'
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
describe('git tests', () => {
beforeAll(() => {
// GitHub workspace
process.env['GITHUB_WORKSPACE'] = __dirname
})
afterAll(() => {
// Restore GitHub workspace
delete process.env['GITHUB_WORKSPACE']
if (originalGitHubWorkspace) {
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
}
})
test('getRepoPath', async () => {
expect(getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE'])
expect(getRepoPath('foo')).toEqual(
path.resolve(process.env['GITHUB_WORKSPACE'] || '', 'foo')
)
})
})

23
__test__/integration-tests.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
IMAGE="cpr-integration-tests:latest"
ARG1=${1:-}
if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" || $ARG1 == "build" ]]; then
echo "Building Docker image $IMAGE ..."
cat > Dockerfile << EOF
FROM node:12-alpine
RUN apk --no-cache add git git-daemon
RUN npm install jest --global
WORKDIR /cpr
COPY __test__/entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EOF
docker build -t $IMAGE .
rm Dockerfile
fi
docker run -v $PWD:/cpr $IMAGE

View File

@ -27,9 +27,11 @@ inputs:
milestone: milestone:
description: 'The number of the milestone to associate this pull request with.' description: 'The number of the milestone to associate this pull request with.'
project: project:
description: 'The name of the project for which a card should be created.' description: 'Deprecated. See README for details.'
project-column: project-column:
description: 'The name of the project column under which a card should be created.' description: 'Deprecated. See README for details.'
draft:
description: 'Create a draft pull request'
branch: branch:
description: 'The pull request branch name.' description: 'The pull request branch name.'
request-to-parent: request-to-parent:
@ -40,7 +42,7 @@ inputs:
branch-suffix: branch-suffix:
description: 'The branch suffix type.' description: 'The branch suffix type.'
outputs: outputs:
pr_number: pull-request-number:
description: 'The pull request number' description: 'The pull request number'
runs: runs:
using: 'node12' using: 'node12'

2
dist/cpr/common.py vendored
View File

@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
def parse_github_repository(url): def parse_github_repository(url):
# Parse the protocol and github repository from a URL # Parse the protocol and github repository from a URL
# e.g. HTTPS, peter-evans/create-pull-request # e.g. HTTPS, peter-evans/create-pull-request
https_pattern = re.compile(r"^https://github.com/(.+/.+)$") https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$") ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
match = https_pattern.match(url) match = https_pattern.match(url)

View File

@ -113,6 +113,8 @@ def create_or_update_pull_request(
# Set the output variables # Set the output variables
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}") os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
# 'pr_number' is deprecated
os.system(f"echo ::set-output name=pr_number::{pull_request.number}") os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
# Set labels, assignees and milestone # Set labels, assignees and milestone

0
dist/cpr/create_pull_request.py vendored Executable file → Normal file
View File

View File

@ -1,4 +1,4 @@
setuptools==46.1.3 setuptools==46.4.0
wheel==0.34.2 wheel==0.34.2
GitPython==3.1.1 GitPython==3.1.2
PyGithub==1.50 PyGithub==1.51

View File

@ -16,6 +16,12 @@ def test_parse_github_repository_success():
assert protocol == "HTTPS" assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request" assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository(
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
)
assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository( protocol, repository = cmn.parse_github_repository(
"git@github.com:peter-evans/create-pull-request.git" "git@github.com:peter-evans/create-pull-request.git"
) )

3240
dist/index.js vendored

File diff suppressed because it is too large Load Diff

BIN
dist/vendor/Deprecated-1.2.10.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
dist/vendor/GitPython-3.1.2.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
dist/vendor/PyGithub-1.51.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
dist/vendor/certifi-2020.6.20.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
dist/vendor/requests-2.24.0.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
dist/vendor/smmap-3.0.4.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -90,7 +90,7 @@ Workflows triggered by `pull_request` events will by default check out a [merge
### Restrictions on forked repositories ### Restrictions on forked repositories
GitHub Actions have imposed restrictions on events triggered by a forked repository. For example, the `pull_request` event triggered by a fork opening a pull request in the upstream repository. GitHub Actions have imposed restrictions on events triggered by a forked repository. Specifically, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
- Events from forks cannot access secrets, except for for the default `GITHUB_TOKEN`. - Events from forks cannot access secrets, except for for the default `GITHUB_TOKEN`.
> With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository. > With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository.
@ -101,7 +101,7 @@ GitHub Actions have imposed restrictions on events triggered by a forked reposit
[GitHub Actions: Permissions for the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token) [GitHub Actions: Permissions for the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token)
These restrictions mean that during a `pull_request` event triggered by a forked repository the action will be unable to commit changes to a branch. These restrictions mean that during a `pull_request` event triggered by a forked repository, actions have no write access to GitHub resources and will fail on attempt.
A job condition can be added to prevent workflows from executing when triggered by a repository fork. A job condition can be added to prevent workflows from executing when triggered by a repository fork.
@ -206,7 +206,7 @@ It will use their own fork to push code and create the pull request.
3. Create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). 3. Create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
4. Logout and log back in to your main user account. 4. Logout and log back in to your main user account.
5. Add a secret to your repository containing the above PAT. 5. Add a secret to your repository containing the above PAT.
6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and set the action input `request-on-parent` to `true`. 6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and set the action input `request-to-parent` to `true`.
```yaml ```yaml
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -221,7 +221,7 @@ It will use their own fork to push code and create the pull request.
- uses: peter-evans/create-pull-request@v2 - uses: peter-evans/create-pull-request@v2
with: with:
token: ${{ secrets.MACHINE_USER_PAT }} token: ${{ secrets.MACHINE_USER_PAT }}
request-on-parent: true request-to-parent: true
``` ```
### Running in a container ### Running in a container
@ -241,7 +241,9 @@ jobs:
image: alpine image: alpine
steps: steps:
- name: Install dependencies - name: Install dependencies
run: apk --no-cache add git python3 run: |
apk --no-cache add git python3
python3 -m ensurepip
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View File

@ -5,6 +5,7 @@
- [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another) - [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another)
- [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically) - [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically)
- [Update NPM dependencies](#update-npm-dependencies) - [Update NPM dependencies](#update-npm-dependencies)
- [Update Gradle dependencies](#update-gradle-dependencies)
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages) - [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
- [Spider and download a website](#spider-and-download-a-website) - [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) - [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)
@ -86,32 +87,100 @@ This pattern will work well for updating any kind of static content from an exte
### Update NPM dependencies ### Update NPM dependencies
This workflow will create a pull request for npm dependencies.
It works best in combination with a build workflow triggered on `push` and `pull_request`.
A [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) can be used in order for the creation of the pull request to trigger further workflows. See the [documentation here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) for further details.
```yml ```yml
name: Update Dependencies name: Update Dependencies
on: on:
schedule: schedule:
- cron: '0 10 * * 1' - cron: '0 10 * * 1'
jobs: jobs:
update-deps: update-dep:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: '10.x' node-version: '12.x'
- name: Update dependencies - name: Update dependencies
id: vars
run: | run: |
npm install -g npm-check-updates npx -p npm-check-updates ncu -u
ncu -u
npm install npm install
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v2 uses: peter-evans/create-pull-request@v2
with: with:
commit-message: update dependencies token: ${{ secrets.PAT }}
title: Automated Dependency Updates commit-message: Update dependencies
body: This is an auto-generated PR with dependency updates. title: Update dependencies
branch: dep-updates body: |
- Dependency updates
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies
```
The above workflow works best in combination with a build workflow triggered on `push` and `pull_request`.
```yml
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
- run: npm ci
- run: npm run test
- run: npm run build
```
### Update Gradle dependencies
The following workflow will create a pull request for Gradle dependencies.
It requires first configuring your project to use Gradle lockfiles.
See [here](https://github.com/peter-evans/gradle-auto-dependency-updates) for how to configure your project and use the following workflow.
```yml
name: Update Dependencies
on:
schedule:
- cron: '0 1 * * 1'
jobs:
update-dep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Perform dependency resolution and write new lockfiles
run: ./gradlew dependencies --write-locks
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
commit-message: Update dependencies
title: Update dependencies
body: |
- Dependency updates
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies
``` ```
### Update SwaggerUI for GitHub Pages ### Update SwaggerUI for GitHub Pages
@ -243,7 +312,7 @@ An `on: repository_dispatch` workflow can be triggered from another workflow wit
```yml ```yml
- name: Repository Dispatch - name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1.0.0 uses: peter-evans/repository-dispatch@v1
with: with:
token: ${{ secrets.REPO_ACCESS_TOKEN }} token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: username/my-repo repository: username/my-repo

View File

@ -1,3 +1,11 @@
process.env = Object.assign(process.env, { module.exports = {
GITHUB_WORKSPACE: __dirname clearMocks: true,
}); moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}

5377
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,31 @@
{ {
"name": "create-pull-request", "name": "create-pull-request",
"version": "2.0.0", "version": "2.0.0",
"private": true,
"description": "Creates a pull request for changes to your repository in the actions workspace", "description": "Creates a pull request for changes to your repository in the actions workspace",
"main": "index.js", "main": "lib/main.js",
"scripts": { "scripts": {
"clean": "rm -rf dist", "clean": "rm -rf dist",
"lint": "eslint src/index.js", "build": "tsc && ncc build",
"test": "eslint src/index.js && jest", "format": "prettier --write '**/*.ts'",
"build": "ncc build src/index.js -o dist", "format-check": "prettier --check '**/*.ts'",
"lint": "eslint src/**/*.ts",
"test:unit": "jest unit",
"test:int": "__test__/integration-tests.sh",
"test": "npm run test:unit && npm run test:int",
"pack-assets": "mkdir -p dist/cpr && cp -rv src/cpr/* dist/cpr",
"vendor-deps": "pip download -r src/cpr/requirements.txt --no-binary=:all: -d dist/vendor", "vendor-deps": "pip download -r src/cpr/requirements.txt --no-binary=:all: -d dist/vendor",
"package": "npm run build && npm run vendor-deps" "package": "npm run build && npm run pack-assets && npm run vendor-deps"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/peter-evans/create-pull-request.git" "url": "git+https://github.com/peter-evans/create-pull-request.git"
}, },
"keywords": [], "keywords": [
"actions",
"pull",
"request"
],
"author": "Peter Evans", "author": "Peter Evans",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
@ -23,14 +33,24 @@
}, },
"homepage": "https://github.com/peter-evans/create-pull-request", "homepage": "https://github.com/peter-evans/create-pull-request",
"dependencies": { "dependencies": {
"@actions/core": "1.2.0", "@actions/core": "1.2.4",
"@actions/exec": "1.0.2", "@actions/exec": "1.0.4",
"@actions/tool-cache": "1.1.2", "@actions/tool-cache": "1.3.4",
"is-docker": "2.0.0" "is-docker": "2.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "25.2.2",
"@types/node": "14.0.1",
"@typescript-eslint/parser": "2.33.0",
"@zeit/ncc": "0.22.1", "@zeit/ncc": "0.22.1",
"eslint": "6.8.0", "eslint": "7.0.0",
"jest": "25.5.3" "eslint-plugin-github": "3.4.1",
"eslint-plugin-jest": "23.11.0",
"jest": "26.0.1",
"jest-circus": "26.0.1",
"js-yaml": "3.13.1",
"prettier": "2.0.5",
"ts-jest": "25.5.1",
"typescript": "3.9.2"
} }
} }

View File

@ -2,10 +2,8 @@
"extends": [ "extends": [
"config:base" "config:base"
], ],
"packageRules": [ "enabledManagers": ["pip_requirements"],
{ "ignorePaths": [
"depTypeList": ["devDependencies"], "**/dist/**"
"automerge": true
}
] ]
} }

View File

@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
def parse_github_repository(url): def parse_github_repository(url):
# Parse the protocol and github repository from a URL # Parse the protocol and github repository from a URL
# e.g. HTTPS, peter-evans/create-pull-request # e.g. HTTPS, peter-evans/create-pull-request
https_pattern = re.compile(r"^https://github.com/(.+/.+)$") https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$") ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
match = https_pattern.match(url) match = https_pattern.match(url)

View File

@ -113,6 +113,8 @@ def create_or_update_pull_request(
# Set the output variables # Set the output variables
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}") os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
# 'pr_number' is deprecated
os.system(f"echo ::set-output name=pr_number::{pull_request.number}") os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
# Set labels, assignees and milestone # Set labels, assignees and milestone

View File

@ -1,4 +1,4 @@
setuptools==46.1.3 setuptools==46.4.0
wheel==0.34.2 wheel==0.34.2
GitPython==3.1.1 GitPython==3.1.2
PyGithub==1.50 PyGithub==1.51

View File

@ -16,6 +16,12 @@ def test_parse_github_repository_success():
assert protocol == "HTTPS" assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request" assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository(
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
)
assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository( protocol, repository = cmn.parse_github_repository(
"git@github.com:peter-evans/create-pull-request.git" "git@github.com:peter-evans/create-pull-request.git"
) )

View File

@ -1,97 +0,0 @@
const core = require("@actions/core");
const exec = require("@actions/exec");
const path = require("path");
function getRepoPath(relativePath) {
let githubWorkspacePath = process.env["GITHUB_WORKSPACE"];
if (!githubWorkspacePath) {
throw new Error("GITHUB_WORKSPACE not defined");
}
githubWorkspacePath = path.resolve(githubWorkspacePath);
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`);
repoPath = githubWorkspacePath;
if (relativePath) repoPath = path.resolve(repoPath, relativePath);
core.debug(`repoPath: ${repoPath}`);
return repoPath;
}
async function execGit(repoPath, args, ignoreReturnCode = false) {
const stdout = [];
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: data => {
stdout.push(data.toString());
}
}
};
var result = {};
result.exitCode = await exec.exec("git", args, options);
result.stdout = stdout.join("");
return result;
}
async function addConfigOption(repoPath, name, value) {
const result = await execGit(
repoPath,
["config", "--local", "--add", name, value],
true
);
return result.exitCode === 0;
}
async function unsetConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--unset", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function configOptionExists(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--name-only", "--get-regexp", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function getConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--get-regexp", name, valueRegex],
true
);
const option = result.stdout.trim().split(`${name} `);
return {
name: name,
value: option[1]
}
}
async function getAndUnsetConfigOption(repoPath, name, valueRegex=".") {
if (await configOptionExists(repoPath, name, valueRegex)) {
const option = await getConfigOption(repoPath, name, valueRegex);
if (await unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`);
return option;
}
}
return null;
}
module.exports = {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
};

View File

@ -1,98 +0,0 @@
const path = require("path");
const {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
} = require("./git");
test("getRepoPath", async () => {
expect(getRepoPath()).toEqual(process.env["GITHUB_WORKSPACE"]);
expect(getRepoPath("foo")).toEqual(
path.resolve(process.env["GITHUB_WORKSPACE"], "foo")
);
});
test("execGit", async () => {
const repoPath = getRepoPath();
const result = await execGit(
repoPath,
["config", "--local", "--name-only", "--get-regexp", "remote.origin.url"],
true
);
expect(result.exitCode).toEqual(0);
expect(result.stdout.trim()).toEqual("remote.origin.url");
});
test("add and unset config option", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo");
expect(add).toBeTruthy();
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option");
expect(unset).toBeTruthy();
});
test("add and unset config option with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo bar");
expect(add).toBeTruthy();
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option", "^foo");
expect(unset).toBeTruthy();
});
test("configOptionExists returns true", async () => {
const repoPath = getRepoPath();
const result = await configOptionExists(repoPath, "remote.origin.url");
expect(result).toBeTruthy();
});
test("configOptionExists returns false", async () => {
const repoPath = getRepoPath();
const result = await configOptionExists(repoPath, "this.key.does.not.exist");
expect(result).toBeFalsy();
});
test("get config option", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.config.option", "foo");
expect(add).toBeTruthy();
const option = await getConfigOption(repoPath, "test.get.config.option");
expect(option.value).toEqual("foo");
const unset = await unsetConfigOption(repoPath, "test.get.config.option");
expect(unset).toBeTruthy();
});
test("get config option with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.config.option", "foo bar");
expect(add).toBeTruthy();
const option = await getConfigOption(repoPath, "test.get.config.option", "^foo");
expect(option.value).toEqual("foo bar");
const unset = await unsetConfigOption(repoPath, "test.get.config.option", "^foo");
expect(unset).toBeTruthy();
});
test("get and unset config option is successful", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo");
expect(add).toBeTruthy();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option");
expect(getAndUnset.value).toEqual("foo");
});
test("get and unset config option is successful with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo bar");
expect(add).toBeTruthy();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option", "^foo");
expect(getAndUnset.value).toEqual("foo bar");
});
test("get and unset config option is unsuccessful", async () => {
const repoPath = getRepoPath();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "this.key.does.not.exist");
expect(getAndUnset).toBeNull();
});

121
src/git.ts Normal file
View File

@ -0,0 +1,121 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as path from 'path'
class GitOutput {
stdout = ''
exitCode = 0
}
export class ConfigOption {
name = ''
value = ''
}
export function getRepoPath(relativePath?: string): string {
let githubWorkspacePath = process.env['GITHUB_WORKSPACE']
if (!githubWorkspacePath) {
throw new Error('GITHUB_WORKSPACE not defined')
}
githubWorkspacePath = path.resolve(githubWorkspacePath)
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`)
let repoPath = githubWorkspacePath
if (relativePath) repoPath = path.resolve(repoPath, relativePath)
core.debug(`repoPath: ${repoPath}`)
return repoPath
}
export async function execGit(
repoPath: string,
args: string[],
ignoreReturnCode = false
): Promise<GitOutput> {
const result = new GitOutput()
const stdout: string[] = []
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: (data: Buffer): void => {
stdout.push(data.toString())
}
}
}
result.exitCode = await exec.exec('git', args, options)
result.stdout = stdout.join('')
return result
}
export async function addConfigOption(
repoPath: string,
name: string,
value: string
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--add', name, value],
true
)
return result.exitCode === 0
}
export async function unsetConfigOption(
repoPath: string,
name: string,
valueRegex = '.'
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--unset', name, valueRegex],
true
)
return result.exitCode === 0
}
export async function configOptionExists(
repoPath: string,
name: string,
valueRegex = '.'
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--name-only', '--get-regexp', name, valueRegex],
true
)
return result.exitCode === 0
}
export async function getConfigOption(
repoPath: string,
name: string,
valueRegex = '.'
): Promise<ConfigOption> {
const option = new ConfigOption()
const result = await execGit(
repoPath,
['config', '--local', '--get-regexp', name, valueRegex],
true
)
option.name = name
option.value = result.stdout.trim().split(`${name} `)[1]
return option
}
export async function getAndUnsetConfigOption(
repoPath: string,
name: string,
valueRegex = '.'
): Promise<ConfigOption> {
if (await configOptionExists(repoPath, name, valueRegex)) {
const option = await getConfigOption(repoPath, name, valueRegex)
if (await unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`)
return option
}
}
return new ConfigOption()
}

View File

@ -1,122 +0,0 @@
const { inspect } = require("util");
const isDocker = require("is-docker");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./setup-python");
const {
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} = require("./git");
const EXTRAHEADER_OPTION = "http.https://github.com/.extraheader";
const EXTRAHEADER_VALUE_REGEX = "^AUTHORIZATION:";
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const cpr = __dirname + "/cpr";
core.debug(`cpr: ${cpr}`);
// Determine how to access python and pip
const { pip, python } = (function() {
if (isDocker()) {
core.info("Running inside a Docker container");
// Python 3 assumed to be installed and on the PATH
return {
pip: "pip3",
python: "python3"
};
} else {
// Setup Python from the tool cache
setupPython("3.x", "x64");
return {
pip: "pip",
python: "python"
};
}
})();
// Install requirements
await exec.exec(pip, [
"install",
"--requirement",
`${cpr}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
const inputs = {
token: core.getInput("token"),
path: core.getInput("path"),
commitMessage: core.getInput("commit-message"),
committer: core.getInput("committer"),
author: core.getInput("author"),
title: core.getInput("title"),
body: core.getInput("body"),
labels: core.getInput("labels"),
assignees: core.getInput("assignees"),
reviewers: core.getInput("reviewers"),
teamReviewers: core.getInput("team-reviewers"),
milestone: core.getInput("milestone"),
project: core.getInput("project"),
projectColumn: core.getInput("project-column"),
draft: core.getInput("draft"),
branch: core.getInput("branch"),
request_to_parent: core.getInput("request-to-parent"),
base: core.getInput("base"),
branchSuffix: core.getInput("branch-suffix")
};
core.debug(`Inputs: ${inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
if (inputs.path) process.env.CPR_PATH = inputs.path;
if (inputs.commitMessage) process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer;
if (inputs.author) process.env.CPR_AUTHOR = inputs.author;
if (inputs.title) process.env.CPR_TITLE = inputs.title;
if (inputs.body) process.env.CPR_BODY = inputs.body;
if (inputs.labels) process.env.CPR_LABELS = inputs.labels;
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees;
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers) process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone;
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft;
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.request_to_parent) process.env.CPR_REQUEST_TO_PARENT = inputs.request_to_parent;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Get the repository path
var repoPath = getRepoPath(inputs.path);
// Get the extraheader config option if it exists
var extraHeaderOption = await getAndUnsetConfigOption(
repoPath,
EXTRAHEADER_OPTION,
EXTRAHEADER_VALUE_REGEX
);
// Execute create pull request
await exec.exec(python, [`${cpr}/create_pull_request.py`]);
} catch (error) {
core.setFailed(error.message);
} finally {
// Restore the extraheader config option
if (extraHeaderOption) {
if (
await addConfigOption(
repoPath,
EXTRAHEADER_OPTION,
extraHeaderOption.value
)
)
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`);
}
}
}
run();

22
src/isDocker.ts Normal file
View File

@ -0,0 +1,22 @@
import * as fs from 'fs'
function hasDockerEnv(): boolean {
try {
fs.statSync('/.dockerenv')
return true
} catch (_) {
return false
}
}
function hasDockerCGroup(): boolean {
try {
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker')
} catch (_) {
return false
}
}
export function isDocker(): boolean {
return hasDockerEnv() || hasDockerCGroup()
}

129
src/main.ts Normal file
View File

@ -0,0 +1,129 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import {isDocker} from './isDocker'
import {setupPython} from './setupPython'
import {
ConfigOption,
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} from './git'
import {inspect} from 'util'
const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader'
const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:'
async function run(): Promise<void> {
let repoPath
let extraHeaderOption = new ConfigOption()
try {
// Python assets
const cpr = `${__dirname}/cpr`
core.debug(`cpr: ${cpr}`)
// Determine how to access python and pip
const {pip, python} = (function (): {pip: string; python: string} {
if (isDocker()) {
core.info('Running inside a Docker container')
// Python 3 assumed to be installed and on the PATH
return {
pip: 'pip3',
python: 'python3'
}
} else {
// Setup Python from the tool cache
setupPython('3.x', 'x64')
return {
pip: 'pip',
python: 'python'
}
}
})()
// Install requirements
await exec.exec(pip, [
'install',
'--requirement',
`${cpr}/requirements.txt`,
'--no-index',
`--find-links=${__dirname}/vendor`
])
// Fetch action inputs
const inputs = {
token: core.getInput('token'),
path: core.getInput('path'),
commitMessage: core.getInput('commit-message'),
committer: core.getInput('committer'),
author: core.getInput('author'),
title: core.getInput('title'),
body: core.getInput('body'),
labels: core.getInput('labels'),
assignees: core.getInput('assignees'),
reviewers: core.getInput('reviewers'),
teamReviewers: core.getInput('team-reviewers'),
milestone: core.getInput('milestone'),
project: core.getInput('project'),
projectColumn: core.getInput('project-column'),
draft: core.getInput('draft'),
branch: core.getInput('branch'),
requestToParent: core.getInput('request-to-parent'),
base: core.getInput('base'),
branchSuffix: core.getInput('branch-suffix')
}
core.debug(`Inputs: ${inspect(inputs)}`)
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token
if (inputs.path) process.env.CPR_PATH = inputs.path
if (inputs.commitMessage)
process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer
if (inputs.author) process.env.CPR_AUTHOR = inputs.author
if (inputs.title) process.env.CPR_TITLE = inputs.title
if (inputs.body) process.env.CPR_BODY = inputs.body
if (inputs.labels) process.env.CPR_LABELS = inputs.labels
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers
if (inputs.teamReviewers)
process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project
if (inputs.projectColumn)
process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch
if (inputs.requestToParent)
process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent
if (inputs.base) process.env.CPR_BASE = inputs.base
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix
// Get the repository path
repoPath = getRepoPath(inputs.path)
// Get the extraheader config option if it exists
extraHeaderOption = await getAndUnsetConfigOption(
repoPath,
EXTRAHEADER_OPTION,
EXTRAHEADER_VALUE_REGEX
)
// Execute create pull request
await exec.exec(python, [`${cpr}/create_pull_request.py`])
} catch (error) {
core.setFailed(error.message)
} finally {
// Restore the extraheader config option
if (extraHeaderOption.value != '') {
if (
await addConfigOption(
repoPath,
EXTRAHEADER_OPTION,
extraHeaderOption.value
)
)
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`)
}
}
}
run()

View File

@ -1,52 +0,0 @@
const core = require("@actions/core");
const tc = require("@actions/tool-cache");
const path = require("path");
const semver = require("semver");
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
let setupPython = function(versionSpec, arch) {
return new Promise((resolve, reject) => {
const IS_WINDOWS = process.platform === "win32";
// Find the version of Python we want in the tool cache
const installDir = tc.find("Python", versionSpec, arch);
core.debug(`installDir: ${installDir}`);
// Set paths
core.exportVariable("pythonLocation", installDir);
core.addPath(installDir);
if (IS_WINDOWS) {
core.addPath(path.join(installDir, "Scripts"));
} else {
core.addPath(path.join(installDir, "bin"));
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(
process.env["APPDATA"] || "",
"Python",
`Python${major}${minor}`,
"Scripts"
);
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve();
});
};
module.exports = setupPython;

50
src/setupPython.ts Normal file
View File

@ -0,0 +1,50 @@
import * as core from '@actions/core'
import * as tc from '@actions/tool-cache'
import * as path from 'path'
import * as semver from 'semver'
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
export function setupPython(versionSpec: string, arch: string): Promise<void> {
return new Promise(resolve => {
const IS_WINDOWS = process.platform === 'win32'
// Find the version of Python we want in the tool cache
const installDir = tc.find('Python', versionSpec, arch)
core.debug(`installDir: ${installDir}`)
// Set paths
core.exportVariable('pythonLocation', installDir)
core.addPath(installDir)
if (IS_WINDOWS) {
core.addPath(path.join(installDir, 'Scripts'))
} else {
core.addPath(path.join(installDir, 'bin'))
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir))
const major = semver.major(version)
const minor = semver.minor(version)
const userScriptsDir = path.join(
process.env['APPDATA'] || '',
'Python',
`Python${major}${minor}`,
'Scripts'
)
core.addPath(userScriptsDir)
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve()
})
}

16
tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": [
"es6"
],
"outDir": "./lib",
"rootDir": "./src",
"declaration": true,
"strict": true,
"noImplicitAny": false,
"esModuleInterop": true
},
"exclude": ["__test__", "lib", "node_modules"]
}