Compare commits

...

172 Commits

Author SHA1 Message Date
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
db640fa8db Merge pull request #168 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.5.3
2020-05-02 16:07:29 +09:00
95d6677567 Merge pull request #171 from peter-evans/ci
Add CI workflow
2020-05-02 16:04:14 +09:00
1f4e24248b Update test suite command 2020-05-02 16:02:02 +09:00
08595270b5 Filter by comment author 2020-05-02 15:32:34 +09:00
237244614a Remove author search condition 2020-05-02 15:25:52 +09:00
6295d61f0c Rename job 2020-05-02 15:19:44 +09:00
d4024e2876 Add test suite help comment 2020-05-02 15:13:50 +09:00
ee96ad03d9 Auto merge dev dependency updates 2020-05-02 14:55:39 +09:00
755b39d2ff Pin dependencies 2020-05-02 14:55:07 +09:00
9f95ac6c53 Setup python for missing pip dependency 2020-05-02 14:50:21 +09:00
cedbe4ad47 Add ci workflow 2020-05-02 14:46:15 +09:00
0e48ed8743 Update dependency jest to v25.5.3 2020-04-30 22:19:12 +00:00
e7291b422e Merge pull request #166 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.5.0
2020-04-29 08:08:26 +09:00
eb824681a8 Update dependency jest to v25.5.0 2020-04-28 19:53:37 +00:00
4cc13107a9 Merge pull request #165 from peter-evans/dev
Update dependency PyGithub to v1.50
2020-04-27 12:06:54 +09:00
c71b8e4206 Update vendored dependencies 2020-04-27 11:48:52 +09:00
e2bf7f9b75 Update dependency PyGithub to v1.50 2020-04-27 11:47:17 +09:00
e1f4cfdcd4 Merge pull request #162 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.4.0
2020-04-20 10:43:20 +09:00
b3f0552507 Update dependency jest to v25.4.0 2020-04-19 21:52:02 +00:00
f4be118b21 Merge pull request #160 from peter-evans/dev
Update dependency GitPython to v3.1.1
2020-04-14 12:02:29 +09:00
c9f22f86fb Vendor wheel 2020-04-14 11:48:20 +09:00
35d5f3c8ae Vendor setuptools 2020-04-14 11:43:07 +09:00
000a0fc06a Update vendored dependencies 2020-04-13 17:53:37 +09:00
2a59f517a7 Update dependency GitPython to v3.1.1 2020-04-13 17:51:52 +09:00
48ce89bc7d Update documentation 2020-04-13 09:57:57 +09:00
6570353abb Update README 2020-04-13 09:36:37 +09:00
8f6cecd6c4 Update workflow 2020-04-10 17:11:29 +09:00
e14ef3b543 Update README 2020-04-10 17:10:06 +09:00
c5778e5181 Merge pull request #157 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.3.0
2020-04-09 00:23:26 +09:00
374fc61fef Update dependency jest to v25.3.0 2020-04-08 14:53:23 +00:00
6fa547cc6f Update documentation 2020-04-06 09:37:35 +09:00
4db3619128 Merge pull request #154 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.22.1
2020-04-06 09:10:47 +09:00
989a8308ec Update dependency @zeit/ncc to v0.22.1 2020-04-05 20:34:21 +00:00
6249109e58 Update documentation 2020-04-05 18:17:05 +09:00
c9b850c450 Update workflow 2020-04-04 18:26:59 +09:00
340e629d2f Merge pull request #152 from peter-evans/dev
Add input for draft pull requests
2020-04-04 09:50:05 +09:00
abc19caa82 Add input for draft pull requests 2020-04-04 09:47:58 +09:00
3474dda921 Update documentation 2020-04-03 17:26:11 +09:00
ad11b10aa4 Merge pull request #151 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.7
2020-04-03 17:14:23 +09:00
86aa5be8bf Update dependency jest to v25.2.7 2020-04-03 07:58:49 +00:00
6867319cf3 Merge pull request #149 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.6
2020-04-02 21:58:25 +09:00
cc84a2389e Update dependency jest to v25.2.6 2020-04-02 10:36:04 +00:00
7e7150d0e8 Merge pull request #147 from peter-evans/dev
Default token to github.token
2020-04-01 19:09:39 +09:00
eb99d45ce6 Default token to github.token 2020-04-01 18:50:53 +09:00
115b7391e1 Revert "Update documentation"
This reverts commit 628c2d7d35.
2020-03-30 17:36:34 +09:00
8305970523 Merge pull request #146 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.4
2020-03-30 09:02:53 +09:00
32f5c5dd5f Update dependency jest to v25.2.4 2020-03-29 20:05:26 +00:00
628c2d7d35 Update documentation 2020-03-29 21:34:47 +09:00
37582e8764 Update documentation 2020-03-29 21:27:56 +09:00
1e6b4d1790 Merge pull request #145 from peter-evans/dev
Create pull requests in the parent repository of a checked out fork
2020-03-29 21:02:48 +09:00
a70c6ebe2a Merge pull request #144 from jderusse/fork
Allow custom repository when pushin in fork
2020-03-29 20:47:00 +09:00
5bd05538d0 Update src/cpr/create_or_update_pull_request.py
Co-Authored-By: Peter Evans <peter-evans@users.noreply.github.com>
2020-03-29 13:36:48 +02:00
26bc40eea1 Add link in TOC 2020-03-29 12:44:57 +02:00
6bb0e7771c Apply suggestions from code review
Co-Authored-By: Peter Evans <peter-evans@users.noreply.github.com>
2020-03-29 12:43:21 +02:00
4c347a4514 Update docs/concepts-guidelines.md
Co-Authored-By: Tobias Nyholm <tobias.nyholm@gmail.com>
2020-03-28 16:42:57 +01:00
cff2c3381d Add doc 2020-03-28 13:27:58 +01:00
e48dab0c1c Add PR creation from Fork 2020-03-28 13:10:12 +01:00
ac9f92d6e7 Merge pull request #141 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.3
2020-03-27 08:15:40 +09:00
3ff256ce08 Update dependency jest to v25.2.3 2020-03-26 20:38:32 +00:00
0bcb10560b Merge pull request #140 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.1
2020-03-26 19:03:52 +09:00
3c4b2793c1 Update dependency jest to v25.2.1 2020-03-26 09:43:37 +00:00
22870d7816 Merge pull request #139 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.0
2020-03-26 10:23:31 +09:00
e324a22ee1 Update dependency jest to v25.2.0 2020-03-25 18:18:56 +00:00
8b60386018 Merge pull request #135 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.22.0
2020-03-24 09:20:19 +09:00
6852d55922 Update dependency @zeit/ncc to v0.22.0 2020-03-23 22:31:46 +00:00
32e5bb80a5 Merge pull request #134 from peter-evans/dev
Update dependencies
2020-03-21 11:38:19 +09:00
619cf2115d Update dependencies due to security vulnerabilities 2020-03-21 11:31:34 +09:00
69008aa567 Update vendored dependencies 2020-03-21 11:29:37 +09:00
ae4278bf24 Update dependency PyGithub to v1.47 2020-03-21 11:23:42 +09:00
88da40fea7 Merge pull request #132 from peter-evans/dev
Update dependency GitPython to v3.1.0
2020-03-07 09:08:24 +09:00
694e068136 Update vendored dependencies 2020-03-07 08:57:59 +09:00
64c34f6885 Update README 2020-03-03 09:49:52 +09:00
52ada17960 Update dependency GitPython to v3.1.0 2020-02-25 13:12:00 +09:00
ce00b952cf Merge pull request #128 from peter-evans/dev
Unset and restore authorization extraheader only
2020-02-22 17:02:15 +09:00
0d42c285a3 Unset and restore authorization extraheader only 2020-02-22 16:56:42 +09:00
ea1eaf1734 Merge pull request #127 from peter-evans/dev
Unset and restore extraheader config option
2020-02-22 14:53:46 +09:00
d5c5ea3e20 Unset and restore extraheader config option 2020-02-22 14:08:54 +09:00
c7b64af0a4 Merge pull request #123 from peter-evans/dev
Authenticate with git extraheader
2020-02-18 19:49:13 +09:00
289fda9fea Authenticate with git extraheader 2020-02-18 19:35:15 +09:00
b021b9e27a Update vendored dependencies 2020-02-18 15:59:18 +09:00
c26314237b Update dependency GitPython to v3.0.8 2020-02-18 15:57:13 +09:00
ed7dd8d236 Update documentation 2020-02-14 20:10:27 +09:00
ca0e9d75fd Update documentation 2020-02-14 00:23:21 +09:00
87c27ee3eb Merge pull request #118 from peter-evans/dev
Assume python3 on PATH when running in a container
2020-02-14 00:07:03 +09:00
4beea725d3 Call python3 when running in a container 2020-02-13 17:37:08 +09:00
9d58699da5 Skip python setup when running in a container 2020-02-13 16:26:04 +09:00
bceebba814 Merge pull request #117 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.21.1
2020-02-13 09:58:46 +09:00
0b82710b2e Update dependency @zeit/ncc to v0.21.1 2020-02-12 16:54:11 +00:00
4aaaa0e760 Update README 2020-02-11 16:36:16 +09:00
918bfcb8a3 Update README 2020-02-11 16:28:16 +09:00
1ecfd1ae40 Merge pull request #116 from peter-evans/dev
Update dependency PyGithub to v1.46
2020-02-11 14:03:17 +09:00
4dd195d7c3 Update vendored dependencies 2020-02-11 13:51:59 +09:00
72b5f45bb4 Update dependency PyGithub to v1.46 2020-02-11 13:49:50 +09:00
5394814b39 Update documentation 2020-02-11 01:21:05 +09:00
83918398f5 Update documentation 2020-02-11 01:15:59 +09:00
b6a458d96a Merge pull request #114 from peter-evans/dev
Add support for ssh protocol
2020-02-10 23:06:03 +09:00
7b5ff6b642 Add support for ssh protocol 2020-02-10 22:52:00 +09:00
82eddd8828 Merge pull request #112 from peter-evans/dev
Skip python setup for alpine linux
2020-02-10 18:47:40 +09:00
6df2a462d1 Skip python setup for alpine linux 2020-02-10 09:53:43 +09:00
3689bd07d7 Merge pull request #110 from peter-evans/dev
Update dependency GitPython to v3.0.7
2020-02-08 16:45:18 +09:00
943f19ac64 Update vendored dependencies 2020-02-08 16:12:36 +09:00
e59d6c7fff Update dependency GitPython to v3.0.7 2020-02-08 16:09:50 +09:00
c65a4f39b3 Update documentation 2020-02-08 16:04:23 +09:00
2d18371789 Update documentation 2020-02-08 12:52:06 +09:00
cc7020a609 Merge pull request #107 from peter-evans/dev
Determine target github repository from git config
2020-02-07 19:01:09 +09:00
d8700620d6 Determine target github repository from git config 2020-02-07 11:05:01 +09:00
b7064071dc Move assets 2020-01-25 16:29:22 +09:00
339e82d37b Update documentation 2020-01-24 13:00:38 +09:00
a319015452 Merge pull request #102 from peter-evans/dev
Vendor python dependencies
2020-01-23 18:59:19 +09:00
df0d07269b Vendor python dependencies 2020-01-23 16:59:19 +09:00
2aa04baf2e Merge pull request #101 from peter-evans/dev
Update title and body when pr exists
2020-01-23 09:54:43 +09:00
d29f1e9296 Update title and body when pr exists 2020-01-23 09:47:35 +09:00
8ee12880b0 Update documentation 2020-01-21 22:35:00 +09:00
8d39de8771 Update documentation 2020-01-21 22:27:02 +09:00
63 changed files with 10482 additions and 2012 deletions

3
.eslintignore Normal file
View File

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

19
.eslintrc.json Normal file
View File

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

1
.github/CODEOWNERS vendored
View File

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

127
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,127 @@
name: CI
on:
push:
branches: [master]
paths-ignore:
- 'README.md'
- 'docs/**'
pull_request:
branches: [master]
paths-ignore:
- 'README.md'
- 'docs/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- run: npm ci
- run: npm run clean
- run: npm run build
- run: npm run format-check
- run: npm run lint
- run: npm run test
- run: npm run package
- uses: actions/upload-artifact@v2
with:
name: dist
path: dist
test:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
needs: [build]
runs-on: ubuntu-latest
strategy:
matrix:
target: [built, committed]
steps:
- uses: actions/checkout@v2
with:
ref: master
- if: matrix.target == 'built' || github.event_name == 'pull_request'
uses: actions/download-artifact@v2
with:
name: dist
path: dist
- name: Create change
run: date +%s > report.txt
- name: Create Pull Request
id: cpr
uses: ./
with:
commit-message: '[CI] test ${{ matrix.target }}'
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
title: '[CI] test ${{ matrix.target }}'
body: |
- CI test case for target '${{ matrix.target }}'
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: ci-test-${{ matrix.target }}
- name: Close Pull
uses: peter-evans/close-pull@v1
with:
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
comment: '[CI] test ${{ matrix.target }}'
delete-branch: true
commentTestSuiteHelp:
if: github.event_name == 'pull_request'
needs: [test]
runs-on: ubuntu-latest
steps:
- name: Find Comment
uses: peter-evans/find-comment@v1
id: fc
with:
issue-number: ${{ github.event.number }}
comment-author: 'github-actions[bot]'
body-includes: Full test suite slash command
- if: steps.fc.outputs.comment-id == ''
name: Create comment
uses: peter-evans/create-or-update-comment@v1
with:
issue-number: ${{ github.event.number }}
body: |
Full test suite slash command (repository admin only)
```
/test repository=${{ github.event.pull_request.head.repo.full_name }} branch=${{ github.event.pull_request.head.ref }} build=true
```
package:
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: rm -rf dist
- uses: actions/download-artifact@v2
with:
name: dist
path: dist
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
commit-message: Update distribution
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
title: Update distribution
body: |
- Updates the distribution for changes on `master`
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: update-distribution

View File

@ -7,15 +7,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create report file
run: date +%s > report.txt
- name: Create Pull Request
id: cpr
uses: ./
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Add report file
committer: Peter Evans <peter-evans@users.noreply.github.com>
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
title: '[Example] Add report file'
body: |
New report
@ -27,17 +29,18 @@ jobs:
assignees: peter-evans
reviewers: peter-evans
milestone: 1
project: Example Project
project-column: To do
draft: false
branch: example-patches
request-to-parent: false
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
- name: Add reaction
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.event.client_payload.github.payload.repository.full_name }}
comment-id: ${{ github.event.client_payload.github.payload.comment.id }}
reaction-type: hooray

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

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

6
.gitignore vendored
View File

@ -1,3 +1,7 @@
__pycache__
node_modules
.python-version
lib/
node_modules/
.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="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)
A GitHub action to create a pull request for changes to your repository in the actions workspace.
@ -18,7 +19,7 @@ Create Pull Request action will:
## Documentation
- [Concepts and guidelines](docs/concepts-guidelines.md)
- [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md)
- [Examples](docs/examples.md)
- [Updating from v1](docs/updating.md)
@ -27,23 +28,20 @@ Create Pull Request action will:
```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v2.x.x`
### Action inputs
With the exception of `token`, all inputs are **optional**. If not set, sensible default values will be used.
All inputs are **optional**. If not set, sensible default values will be used.
**Note**: If you want pull requests created by this action to trigger an `on: 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.
**Note**: If you want pull requests created by this action to trigger an `on: push` or `on: pull_request` workflow then you cannot use the default `GITHUB_TOKEN`. See the [documentation here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) for workarounds.
| Name | Description | Default |
| --- | --- | --- |
| `token` | `GITHUB_TOKEN` or a `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | |
| `path` | Relative path under `$GITHUB_WORKSPACE` to the repository. | `$GITHUB_WORKSPACE` |
| `token` | `GITHUB_TOKEN` or a `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | `GITHUB_TOKEN` |
| `path` | Relative path under `GITHUB_WORKSPACE` to the repository. | `GITHUB_WORKSPACE` |
| `commit-message` | The message to use when committing changes. | `[create-pull-request] automated change` |
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user. See [Committer and author](#committer-and-author) for details. |
| `author` | The author name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user. See [Committer and author](#committer-and-author) for details. |
@ -52,15 +50,17 @@ See [this issue](https://github.com/peter-evans/create-pull-request/issues/48) f
| `labels` | A comma separated list of labels. | |
| `assignees` | A comma separated list of assignees (GitHub usernames). | |
| `reviewers` | A comma separated list of reviewers (GitHub usernames) to request a review from. | |
| `team-reviewers` | A comma separated list of GitHub teams to request a review from. | |
| `team-reviewers` | A comma separated list of GitHub teams to request a review from. A `repo` scoped [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) may be required. See [this issue](https://github.com/peter-evans/create-pull-request/issues/155). | |
| `milestone` | The number of the milestone to associate this pull request with. | |
| `project` | The name of the project for which a card should be created. Requires `project-column`. | |
| `project-column` | The name of the project column under which a card should be created. Requires `project`. | |
| `project` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
| `project-column` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
| `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` |
| `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` |
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` |
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Branch naming](#branch-naming) for details. | |
**Outputs**
### Action outputs
The pull request number is output as both an environment variable and a step output.
Note that in order to read the step output the action step must have an id.
@ -69,12 +69,10 @@ Note that in order to read the step output the action step must have an id.
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
```
### Checkout
@ -115,13 +113,13 @@ If there are files or directories you want to ignore you can simply add them to
If neither `committer` or `author` inputs are supplied the action will default to making commits that appear to be made by the GitHub Actions bot user.
In most cases, where the committer and author are the same, just the committer can be set.
The following configuration can be used to have commits authored by the user who triggered the workflow event.
```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
committer: Peter Evans <peter-evans@users.noreply.github.com>
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
```
### Controlling commits
@ -144,8 +142,23 @@ As well as relying on the action to handle uncommitted changes, you can addition
run: date +%s > report.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
```
### Create a project card
To create a project card for the pull request, pass the `pull-request-number` step output to [create-or-update-project-card](https://github.com/peter-evans/create-or-update-project-card) action.
```yml
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v2
- name: Create or Update Project Card
uses: peter-evans/create-or-update-project-card@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
project-name: My project
column-name: My column
issue-number: ${{ steps.cpr.outputs.pull-request-number }}
```
## Reference Example
@ -170,8 +183,8 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Add report file
committer: Peter Evans <peter-evans@users.noreply.github.com>
author: Peter Evans <peter-evans@users.noreply.github.com>
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
title: '[Example] Add report file'
body: |
New report
@ -182,19 +195,20 @@ jobs:
labels: report, automated pr
assignees: peter-evans
reviewers: peter-evans
team-reviewers: owners, maintainers
milestone: 1
project: Example Project
project-column: To do
draft: false
branch: example-patches
request-to-parent: false
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
```
This reference configuration will create pull requests that look like this:
An example based on the above reference configuration creates pull requests that look like this:
![Pull Request Example](assets/pull-request-example.png)
![Pull Request Example](docs/assets/pull-request-example.png)
## License

162
__test__/git.test.ts Normal file
View File

@ -0,0 +1,162 @@
import * as path from 'path'
import {
ConfigOption,
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'] = __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')
)
})
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')
})
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()
})
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()
})
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('')
})
})

View File

@ -3,7 +3,7 @@ description: 'Creates a pull request for changes to your repository in the actio
inputs:
token:
description: 'GITHUB_TOKEN or a repo scoped PAT'
required: true
default: ${{ github.token }}
path:
description: 'Relative path under $GITHUB_WORKSPACE to the repository.'
commit-message:
@ -27,21 +27,26 @@ inputs:
milestone:
description: 'The number of the milestone to associate this pull request with.'
project:
description: 'The name of the project for which a card should be created.'
description: 'Deprecated. See README for details.'
project-column:
description: 'The name of the project column under which a card should be created.'
description: 'Deprecated. See README for details.'
draft:
description: 'Create a draft pull request'
branch:
description: 'The pull request branch name.'
request-to-parent:
description: 'Create the pull request in the parent repository of the checked out fork.'
default: false
base:
description: 'The pull request base branch.'
branch-suffix:
description: 'The branch suffix type.'
outputs:
pr_number:
pull-request-number:
description: 'The pull request number'
runs:
using: 'node12'
main: 'dist/index.js'
branding:
icon: 'git-pull-request'
icon: 'git-pull-request'
color: 'gray-dark'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

View File

@ -8,6 +8,23 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
return "".join(random.choice(chars) for _ in range(length))
def parse_github_repository(url):
# Parse the protocol and github repository from a URL
# e.g. HTTPS, peter-evans/create-pull-request
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
match = https_pattern.match(url)
if match is not None:
return "HTTPS", match.group(1)
match = ssh_pattern.match(url)
if match is not None:
return "SSH", match.group(1)
raise ValueError(f"The format of '{url}' is not a valid GitHub repository URL")
def parse_display_name_email(display_name_email):
# Parse the name and email address from a string in the following format
# Display Name <email@address.com>

View File

@ -4,6 +4,20 @@ from github import Github, GithubException
import os
def string_to_bool(str):
if str is None:
return False
else:
return str.lower() in [
"true",
"1",
"t",
"y",
"yes",
"on",
]
def cs_string_to_list(str):
# Split the comma separated string into a list
l = [i.strip() for i in str.split(",")]
@ -56,29 +70,51 @@ def create_or_update_pull_request(
team_reviewers,
project_name,
project_column_name,
draft,
request_to_parent,
):
github_repo = head_repo = Github(github_token).get_repo(github_repository)
if string_to_bool(request_to_parent):
github_repo = github_repo.parent
if github_repo is None:
raise ValueError(
"The checked out repository is not a fork. Input 'request-to-parent' should be set to false."
)
head_branch = f"{head_repo.owner.login}:{branch}"
# Create the pull request
github_repo = Github(github_token).get_repo(github_repository)
try:
pull_request = github_repo.create_pull(
title=title, body=body, base=base, head=branch
title=title,
body=body,
base=base,
head=head_branch,
draft=string_to_bool(draft),
)
print(
f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
)
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
except GithubException as e:
if e.status == 422:
# A pull request exists for this branch and base
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(
f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
)
else:
print(str(e))
raise
# Set the output variables
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
# 'pr_number' is deprecated
os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
# Set labels, assignees and milestone

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

@ -1,5 +1,6 @@
#!/usr/bin/env python3
""" Create Pull Request """
import base64
import common as cmn
import create_or_update_branch as coub
import create_or_update_pull_request as coupr
@ -31,6 +32,14 @@ def get_git_config_value(repo, name):
return None
def get_repository_detail(repo):
remote_origin_url = get_git_config_value(repo, "remote.origin.url")
if remote_origin_url is None:
raise ValueError("Failed to fetch 'remote.origin.url' from git config")
protocol, github_repository = cmn.parse_github_repository(remote_origin_url)
return remote_origin_url, protocol, github_repository
def git_user_config_is_set(repo):
name = get_git_config_value(repo, "user.name")
email = get_git_config_value(repo, "user.email")
@ -94,7 +103,6 @@ def set_committer_author(repo, committer, author):
# Get required environment variables
github_token = os.environ["GITHUB_TOKEN"]
github_repository = os.environ["GITHUB_REPOSITORY"]
# Get environment variables with defaults
path = os.getenv("CPR_PATH", os.getcwd())
branch = os.getenv("CPR_BRANCH", DEFAULT_BRANCH)
@ -107,6 +115,23 @@ base = os.environ.get("CPR_BASE")
# Set the repo path
repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
repo_url, protocol, github_repository = get_repository_detail(repo)
print(f"Target repository set to {github_repository}")
if protocol == "HTTPS":
print(f"::debug::Using HTTPS protocol")
# Encode and configure the basic credential for HTTPS access
basic_credential = base64.b64encode(
f"x-access-token:{github_token}".encode("utf-8")
).decode("utf-8")
# Mask the basic credential in logs and debug output
print(f"::add-mask::{basic_credential}")
repo.git.set_persistent_git_options(
c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}"
)
# Determine if the checked out ref is a valid base for a pull request
# The action needs the checked out HEAD ref to be a branch
# This check will fail in the following cases:
@ -162,9 +187,6 @@ except ValueError as e:
print(f"::error::{e} " + "Unable to continue. Exiting.")
sys.exit(1)
# Set the repository URL
repo_url = f"https://x-access-token:{github_token}@github.com/{github_repository}"
# Create or update the pull request branch
result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch)
@ -202,4 +224,6 @@ if result["action"] in ["created", "updated"]:
os.environ.get("CPR_TEAM_REVIEWERS"),
os.environ.get("CPR_PROJECT_NAME"),
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
os.environ.get("CPR_DRAFT"),
os.environ.get("CPR_REQUEST_TO_PARENT"),
)

4
dist/cpr/requirements.txt vendored Normal file
View File

@ -0,0 +1,4 @@
setuptools==46.2.0
wheel==0.34.2
GitPython==3.1.2
PyGithub==1.51

View File

@ -9,6 +9,30 @@ def test_get_random_string():
assert len(cmn.get_random_string(length=20)) == 20
def test_parse_github_repository_success():
protocol, repository = cmn.parse_github_repository(
"https://github.com/peter-evans/create-pull-request"
)
assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository(
"git@github.com:peter-evans/create-pull-request.git"
)
assert protocol == "SSH"
assert repository == "peter-evans/create-pull-request"
def test_parse_github_repository_failure():
url = "https://github.com/peter-evans"
with pytest.raises(ValueError) as e_info:
cmn.parse_github_repository(url)
assert (
e_info.value.args[0]
== f"The format of '{url}' is not a valid GitHub repository URL"
)
def test_parse_display_name_email_success():
name, email = cmn.parse_display_name_email("abc def <abc@def.com>")
assert name == "abc def"

3043
dist/index.js vendored

File diff suppressed because it is too large Load Diff

View File

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

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;

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/PyJWT-1.7.1.tar.gz vendored Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/gitdb-4.0.5.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/vendor/idna-2.9.tar.gz vendored Normal file

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/setuptools-46.2.0.zip vendored Normal file

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/urllib3-1.25.9.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/vendor/wheel-0.34.2.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/vendor/wrapt-1.12.1.tar.gz vendored Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 207 KiB

View File

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -1,6 +1,6 @@
# Concepts and guidelines
# Concepts, guidelines and advanced usage
This document covers terminology, how the action works, and general usage guidelines.
This document covers terminology, how the action works, general usage guidelines, and advanced usage.
- [Terminology](#terminology)
- [Events and checkout](#events-and-checkout)
@ -9,6 +9,14 @@ This document covers terminology, how the action works, and general usage guidel
- [Providing a consistent base](#providing-a-consistent-base)
- [Pull request events](#pull-request-events)
- [Restrictions on forked repositories](#restrictions-on-forked-repositories)
- [Triggering further workflow runs](#triggering-further-workflow-runs)
- [Security](#security)
- [Advanced usage](#advanced-usage)
- [Creating pull requests in a remote repository](#creating-pull-requests-in-a-remote-repository)
- [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys)
- [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork)
- [Running in a container](#running-in-a-container)
- [Creating pull requests on tag push](#creating-pull-requests-on-tag-push)
## Terminology
@ -45,7 +53,7 @@ Workflow steps:
The following git diagram shows how the action creates and updates a pull request branch.
![Create Pull Request GitGraph](../assets/cpr-gitgraph.png)
![Create Pull Request GitGraph](assets/cpr-gitgraph.png)
## Guidelines
@ -82,7 +90,7 @@ Workflows triggered by `pull_request` events will by default check out a [merge
### Restrictions on forked repositories
GitHub Actions have imposed restrictions on events triggered by a forked repository. For example, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
GitHub Actions have imposed restrictions on events triggered by a forked repository. Specifically, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
- Events from forks cannot access secrets, except for for the default `GITHUB_TOKEN`.
> With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository.
@ -93,7 +101,7 @@ GitHub Actions have imposed restrictions on events triggered by a forked reposit
[GitHub Actions: Permissions for the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token)
These restrictions mean that during a `pull_request` event triggered by a forked repository the action will be unable to commit changes to a branch.
These restrictions mean that during a `pull_request` event triggered by a forked repository, actions have no write access to GitHub resources and will fail on attempt.
A job condition can be added to prevent workflows from executing when triggered by a repository fork.
@ -105,3 +113,223 @@ jobs:
# Check if the event is not triggered by a fork
if: github.event.pull_request.head.repo.full_name == github.repository
```
### Triggering further workflow runs
Pull requests created by the action using the default `GITHUB_TOKEN` cannot trigger other workflows. If you have `on: pull_request` or `on: push` workflows acting as checks on pull requests, they will not run.
> When you use the repository's GITHUB_TOKEN to perform tasks on behalf of the GitHub Actions app, events triggered by the GITHUB_TOKEN will not create a new workflow run.
[GitHub Actions: Events that trigger workflows](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token)
#### Workarounds to trigger further workflow runs
There are a number of workarounds with different pros and cons.
- Use the default `GITHUB_TOKEN` and allow the action to create pull requests that have no checks enabled. Manually close pull requests and immediately reopen them. This will enable `on: pull_request` workflows to run and be added as checks.
- Use a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) created on an account that has write access to the repository that pull requests are being created in. This is the standard workaround and [recommended by GitHub](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token). However, the PAT cannot be scoped to a specific repository so the token becomes a very sensitive secret. If this is a concern, the PAT can instead be created for a dedicated [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements) that has collaborator access to the repository. Also note that because the account that owns the PAT will be the creator of pull requests, that user account will be unable to perform actions such as request changes or approve the pull request.
- Use [SSH (deploy keys)](#push-using-ssh-deploy-keys) to push the pull request branch. This is arguably more secure than using a PAT because deploy keys can be set per repository. However, this method will only trigger `on: push` workflows.
- Use a [machine account that creates pull requests from its own fork](#push-pull-request-branches-to-a-fork). This is the most secure because the PAT created only grants access to the machine account's fork, not the main repository. This method will trigger `on: pull_request` workflows to run. Workflows triggered `on: push` will not run because the push event is in the fork.
### Security
From a security perspective it's good practice to fork third-party actions, review the code, and use your fork of the action in workflows.
By using third-party actions directly the risk exists that it could be modified to do something malicious, such as capturing secrets.
This action uses [ncc](https://github.com/zeit/ncc) to compile the Node.js code and dependencies into a single file.
Python dependencies are vendored and committed to the repository [here](https://github.com/peter-evans/create-pull-request/tree/master/dist/vendor).
No dependencies are downloaded during the action execution.
Vendored Python dependencies can be reviewed by rebuilding the [dist](https://github.com/peter-evans/create-pull-request/tree/master/dist) directory and redownloading dependencies.
The following commands require Node and Python 3.
```
npm install
npm run clean
npm run package
```
The `dist` directory should be rebuilt leaving no git diff.
## Advanced usage
### Creating pull requests in a remote repository
Checking out a branch from a different repository from where the workflow is executing will make *that repository* the target for the created pull request. In this case, a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) is required.
```yml
- uses: actions/checkout@v2
with:
token: ${{ secrets.PAT }}
repository: owner/repo
# Make changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
```
### Push using SSH (deploy keys)
[Deploy keys](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) can be set per repository and so are arguably more secure than using a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
Allowing the action to push with a configured deploy key will trigger `on: push` workflows. This makes it an alternative to using a PAT to trigger checks for pull requests.
How to use SSH (deploy keys) with create-pull-request action:
1. [Create a new SSH key pair](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key) for your repository. Do not set a passphrase.
2. Copy the contents of the public key (.pub file) to a new repository [deploy key](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) and check the box to "Allow write access."
3. Add a secret to the repository containing the entire contents of the private key.
4. As shown in the example below, configure `actions/checkout` to use the deploy key you have created.
```yml
steps:
- uses: actions/checkout@v2
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
```
### Push pull request branches to a fork
Instead of pushing pull request branches to the repository you want to update, you can push them to a fork of that repository.
This allows you to employ the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) by using a dedicated user acting as a [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements).
This user has no access to the main repository.
It will use their own fork to push code and create the pull request.
1. Create a new GitHub user and login.
2. Fork the repository that you will be creating pull requests in.
3. Create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
4. Logout and log back in to your main user account.
5. Add a secret to your repository containing the above PAT.
6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and set the action input `request-to-parent` to `true`.
```yaml
- uses: actions/checkout@v2
- run: |
git config user.password ${{ secrets.MACHINE_USER_PAT }}
git remote set-url origin https://github.com/machine-user/fork-of-repository
git fetch --unshallow -p origin
# Make changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.MACHINE_USER_PAT }}
request-to-parent: true
```
### Running in a container
This action can be run inside a container by installing the action's dependencies either in the Docker image itself, or during the workflow.
The action requires `python3`, `pip3` and `git` to be installed and on the `PATH`.
Note that `actions/checkout` requires Git 2.18 or higher to be installed, otherwise it will just download the source of the repository instead of cloning it.
**Alpine container example:**
```yml
jobs:
createPullRequestAlpine:
runs-on: ubuntu-latest
container:
image: alpine
steps:
- name: Install dependencies
run: apk --no-cache add git python3
- uses: actions/checkout@v2
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
```
**Ubuntu container example:**
```yml
jobs:
createPullRequestAlpine:
runs-on: ubuntu-latest
container:
image: ubuntu
steps:
- name: Install dependencies
run: |
apt-get update
apt-get install -y software-properties-common
add-apt-repository -y ppa:git-core/ppa
apt-get install -y python3 python3-pip git
- uses: actions/checkout@v2
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
```
### Creating pull requests on tag push
An `on: push` workflow will also trigger when tags are pushed.
During these events, the `actions/checkout` action will check out the `ref/tags/<tag>` git ref by default.
This means the repository will *not* be checked out on an active branch.
If you would like to run `create-pull-request` action on the tagged commit you can achieve this by creating a temporary branch as follows.
```yml
on:
push:
tags:
- 'v*.*.*'
jobs:
example:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create a temporary tag branch
run: |
git config --global user.name 'GitHub'
git config --global user.email 'noreply@github.com'
git checkout -b temp-${GITHUB_REF:10}
git push --set-upstream origin temp-${GITHUB_REF:10}
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
base: master
- name: Delete tag branch
run: |
git push --delete origin temp-${GITHUB_REF:10}
```
This is an alternative, simpler workflow to the one above. However, this is not guaranteed to checkout the tagged commit.
There is a chance that in between the tag being pushed and checking out the `master` branch in the workflow, another commit is made to `master`. If that possibility is not a concern, this workflow will work fine.
```yml
on:
push:
tags:
- 'v*.*.*'
jobs:
example:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: master
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
```

View File

@ -2,6 +2,7 @@
- [Use case: Create a pull request to update X on push](#use-case-create-a-pull-request-to-update-x-on-push)
- [Update project authors](#update-project-authors)
- [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another)
- [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically)
- [Update NPM dependencies](#update-npm-dependencies)
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
@ -44,46 +45,103 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: update authors
title: Update AUTHORS
body: Credit new contributors by updating AUTHORS
branch: update-authors
```
### Keep a branch up-to-date with another
This is a use case where a branch should be kept up to date with another by opening a pull request to update it. The pull request should then be updated with new changes until it is merged or closed.
In this example scenario, a branch called `production` should be updated via pull request to keep it in sync with `master`. Merging the pull request is effectively promoting those changes to production.
```yml
name: Create production promotion pull request
on:
push:
branches:
- master
jobs:
productionPromotion:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: production
- name: Reset promotion branch
run: |
git fetch origin master:master
git reset --hard master
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
branch: production-promotion
```
## 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
This workflow will create a pull request for npm dependencies.
It works best in combination with a build workflow triggered on `push` and `pull_request`.
A [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) can be used in order for the creation of the pull request to trigger further workflows. See the [documentation here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) for further details.
```yml
name: Update Dependencies
on:
schedule:
- cron: '0 10 * * 1'
jobs:
update-deps:
update-dep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '10.x'
node-version: '12.x'
- name: Update dependencies
id: vars
run: |
npm install -g npm-check-updates
ncu -u
npx -p npm-check-updates ncu -u
npm install
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: update dependencies
title: Automated Dependency Updates
body: This is an auto-generated PR with dependency updates.
branch: dep-updates
token: ${{ secrets.PAT }}
commit-message: Update dependencies
title: Update dependencies
body: |
- Dependency updates
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
branch: update-dependencies
```
The above workflow works best in combination with a build workflow triggered on `push` and `pull_request`.
```yml
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
- run: npm ci
- run: npm run test
- run: npm run build
```
### Update SwaggerUI for GitHub Pages
@ -130,7 +188,6 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update swagger-ui to ${{ steps.swagger-ui.outputs.release_tag }}
title: Update SwaggerUI to ${{ steps.swagger-ui.outputs.release_tag }}
body: |
@ -173,7 +230,6 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: update local website copy
title: Automated Updates to Local Website Copy
body: This is an auto-generated PR with website updates.
@ -217,7 +273,7 @@ An `on: repository_dispatch` workflow can be triggered from another workflow wit
```yml
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1.0.0
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: username/my-repo
@ -258,7 +314,7 @@ jobs:
ref: ${{ github.head_ref }}
- name: autopep8
id: autopep8
uses: peter-evans/autopep8@v1.1.0
uses: peter-evans/autopep8@v1
with:
args: --exit-code --recursive --in-place --aggressive --aggressive .
- name: Set autopep8 branch name
@ -268,7 +324,6 @@ jobs:
if: steps.autopep8.outputs.exit-code == 2
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: autopep8 action fixes
title: Fixes by autopep8 action
body: This is an auto-generated PR with fixes by autopep8.
@ -327,7 +382,6 @@ The recommended method is to use [`set-output`](https://help.github.com/en/githu
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ steps.vars.outputs.pr_title }}
body: ${{ steps.vars.outputs.pr_body }}
```
@ -343,7 +397,6 @@ Alternatively, [`set-env`](https://help.github.com/en/github/automating-your-wor
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ env.PULL_REQUEST_TITLE }}
body: ${{ env.PULL_REQUEST_BODY }}
```

View File

@ -1,70 +0,0 @@
const { inspect } = require("util");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./src/setup-python");
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const src = __dirname + "/src";
core.debug(`src: ${src}`);
// 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"),
path: core.getInput("path"),
commitMessage: core.getInput("commit-message"),
committer: core.getInput("committer"),
author: core.getInput("author"),
title: core.getInput("title"),
body: core.getInput("body"),
labels: core.getInput("labels"),
assignees: core.getInput("assignees"),
reviewers: core.getInput("reviewers"),
teamReviewers: core.getInput("team-reviewers"),
milestone: core.getInput("milestone"),
project: core.getInput("project"),
projectColumn: core.getInput("project-column"),
branch: core.getInput("branch"),
base: core.getInput("base"),
branchSuffix: core.getInput("branch-suffix"),
};
core.debug(`Inputs: ${inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
if (inputs.path) process.env.CPR_PATH = inputs.path;
if (inputs.commitMessage) process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer;
if (inputs.author) process.env.CPR_AUTHOR = inputs.author;
if (inputs.title) process.env.CPR_TITLE = inputs.title;
if (inputs.body) process.env.CPR_BODY = inputs.body;
if (inputs.labels) process.env.CPR_LABELS = inputs.labels;
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees;
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers) process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone;
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Execute python script
await exec.exec("python", [`${src}/create_pull_request.py`]);
} catch (error) {
core.setFailed(error.message);
}
}
run();

11
jest.config.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}

7831
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,5 +1,9 @@
{
"extends": [
"config:base"
],
"enabledManagers": ["pip_requirements"],
"ignorePaths": [
"**/dist/**"
]
}

View File

@ -8,6 +8,23 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
return "".join(random.choice(chars) for _ in range(length))
def parse_github_repository(url):
# Parse the protocol and github repository from a URL
# e.g. HTTPS, peter-evans/create-pull-request
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
match = https_pattern.match(url)
if match is not None:
return "HTTPS", match.group(1)
match = ssh_pattern.match(url)
if match is not None:
return "SSH", match.group(1)
raise ValueError(f"The format of '{url}' is not a valid GitHub repository URL")
def parse_display_name_email(display_name_email):
# Parse the name and email address from a string in the following format
# Display Name <email@address.com>

View File

@ -4,6 +4,20 @@ from github import Github, GithubException
import os
def string_to_bool(str):
if str is None:
return False
else:
return str.lower() in [
"true",
"1",
"t",
"y",
"yes",
"on",
]
def cs_string_to_list(str):
# Split the comma separated string into a list
l = [i.strip() for i in str.split(",")]
@ -56,29 +70,51 @@ def create_or_update_pull_request(
team_reviewers,
project_name,
project_column_name,
draft,
request_to_parent,
):
github_repo = head_repo = Github(github_token).get_repo(github_repository)
if string_to_bool(request_to_parent):
github_repo = github_repo.parent
if github_repo is None:
raise ValueError(
"The checked out repository is not a fork. Input 'request-to-parent' should be set to false."
)
head_branch = f"{head_repo.owner.login}:{branch}"
# Create the pull request
github_repo = Github(github_token).get_repo(github_repository)
try:
pull_request = github_repo.create_pull(
title=title, body=body, base=base, head=branch
title=title,
body=body,
base=base,
head=head_branch,
draft=string_to_bool(draft),
)
print(
f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
)
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
except GithubException as e:
if e.status == 422:
# A pull request exists for this branch and base
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(
f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})"
)
else:
print(str(e))
raise
# Set the output variables
os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}")
os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}")
# 'pr_number' is deprecated
os.system(f"echo ::set-output name=pr_number::{pull_request.number}")
# Set labels, assignees and milestone

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
""" Create Pull Request """
import base64
import common as cmn
import create_or_update_branch as coub
import create_or_update_pull_request as coupr
@ -31,6 +32,14 @@ def get_git_config_value(repo, name):
return None
def get_repository_detail(repo):
remote_origin_url = get_git_config_value(repo, "remote.origin.url")
if remote_origin_url is None:
raise ValueError("Failed to fetch 'remote.origin.url' from git config")
protocol, github_repository = cmn.parse_github_repository(remote_origin_url)
return remote_origin_url, protocol, github_repository
def git_user_config_is_set(repo):
name = get_git_config_value(repo, "user.name")
email = get_git_config_value(repo, "user.email")
@ -94,7 +103,6 @@ def set_committer_author(repo, committer, author):
# Get required environment variables
github_token = os.environ["GITHUB_TOKEN"]
github_repository = os.environ["GITHUB_REPOSITORY"]
# Get environment variables with defaults
path = os.getenv("CPR_PATH", os.getcwd())
branch = os.getenv("CPR_BRANCH", DEFAULT_BRANCH)
@ -107,6 +115,23 @@ base = os.environ.get("CPR_BASE")
# Set the repo path
repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
repo_url, protocol, github_repository = get_repository_detail(repo)
print(f"Target repository set to {github_repository}")
if protocol == "HTTPS":
print(f"::debug::Using HTTPS protocol")
# Encode and configure the basic credential for HTTPS access
basic_credential = base64.b64encode(
f"x-access-token:{github_token}".encode("utf-8")
).decode("utf-8")
# Mask the basic credential in logs and debug output
print(f"::add-mask::{basic_credential}")
repo.git.set_persistent_git_options(
c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}"
)
# Determine if the checked out ref is a valid base for a pull request
# The action needs the checked out HEAD ref to be a branch
# This check will fail in the following cases:
@ -162,9 +187,6 @@ except ValueError as e:
print(f"::error::{e} " + "Unable to continue. Exiting.")
sys.exit(1)
# Set the repository URL
repo_url = f"https://x-access-token:{github_token}@github.com/{github_repository}"
# Create or update the pull request branch
result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch)
@ -202,4 +224,6 @@ if result["action"] in ["created", "updated"]:
os.environ.get("CPR_TEAM_REVIEWERS"),
os.environ.get("CPR_PROJECT_NAME"),
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
os.environ.get("CPR_DRAFT"),
os.environ.get("CPR_REQUEST_TO_PARENT"),
)

4
src/cpr/requirements.txt Normal file
View File

@ -0,0 +1,4 @@
setuptools==46.2.0
wheel==0.34.2
GitPython==3.1.2
PyGithub==1.51

View File

@ -9,6 +9,30 @@ def test_get_random_string():
assert len(cmn.get_random_string(length=20)) == 20
def test_parse_github_repository_success():
protocol, repository = cmn.parse_github_repository(
"https://github.com/peter-evans/create-pull-request"
)
assert protocol == "HTTPS"
assert repository == "peter-evans/create-pull-request"
protocol, repository = cmn.parse_github_repository(
"git@github.com:peter-evans/create-pull-request.git"
)
assert protocol == "SSH"
assert repository == "peter-evans/create-pull-request"
def test_parse_github_repository_failure():
url = "https://github.com/peter-evans"
with pytest.raises(ValueError) as e_info:
cmn.parse_github_repository(url)
assert (
e_info.value.args[0]
== f"The format of '{url}' is not a valid GitHub repository URL"
)
def test_parse_display_name_email_success():
name, email = cmn.parse_display_name_email("abc def <abc@def.com>")
assert name == "abc def"

117
src/git.ts Normal file
View File

@ -0,0 +1,117 @@
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, name, value): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--add', name, value],
true
)
return result.exitCode === 0
}
export async function unsetConfigOption(
repoPath,
name,
valueRegex = '.'
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--unset', name, valueRegex],
true
)
return result.exitCode === 0
}
export async function configOptionExists(
repoPath,
name,
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,
name,
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,
name,
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()
}

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,2 +0,0 @@
GitPython==3.0.5
PyGithub==1.45

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, arch): 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"]
}