Compare commits

...

34 Commits

Author SHA1 Message Date
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
c202684c92 Merge pull request #98 from peter-evans/dev
Follow the python minor version
2020-01-17 17:48:11 +09:00
e970adccb4 Follow the python minor version 2020-01-17 17:39:10 +09:00
9f9af3e969 Merge pull request #97 from peter-evans/dev
Update Python to version 3.8.1
2020-01-17 15:52:01 +09:00
615d7c82e3 Update Python to version 3.8.1 2020-01-17 15:46:49 +09:00
8246a6aea9 Merge pull request #95 from peter-evans/dev
Add path input
2020-01-10 00:35:16 +09:00
1e09ec2f22 Add path input 2020-01-10 00:11:42 +09:00
4c018f4174 Merge pull request #93 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.21.0
2020-01-05 08:08:32 +09:00
080aaa90aa Update dependency @zeit/ncc to v0.21.0 2020-01-04 15:45:00 +00:00
6ac64298f6 Update slash command 2020-01-04 21:44:01 +09:00
76e932f3c9 Update slash command 2020-01-04 21:38:54 +09:00
06078e295b Update examples 2020-01-04 20:02:09 +09:00
004434a414 Update examples 2020-01-04 12:08:41 +09:00
4661d6d7af Update docs 2020-01-03 19:22:46 +09:00
a972260284 Update docs 2020-01-03 17:50:03 +09:00
f1d6c2dca3 Update example screenshot 2020-01-03 14:52:21 +09:00
aa1cba4c18 Update cpr example workflow 2020-01-03 14:44:00 +09:00
9b33a4edd8 Add slash command for cpr example 2020-01-03 14:37:39 +09:00
39 changed files with 340 additions and 69 deletions

View File

@ -1,7 +1,7 @@
name: Create Pull Request
name: Create Pull Request Example Command
on:
repository_dispatch:
types: [create-pull-request]
types: [cpr-example-command]
jobs:
createPullRequest:
runs-on: ubuntu-latest
@ -34,3 +34,10 @@ jobs:
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
echo "Pull Request Number - ${{ steps.cpr.outputs.pr_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

@ -11,6 +11,28 @@ jobs:
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
commands: test, pytest, clean
permission: admin
repository: peter-evans/create-pull-request-tests
config: >
[
{
"command": "test",
"permission": "admin",
"repository": "peter-evans/create-pull-request-tests",
"named_args": true
},
{
"command": "pytest",
"permission": "admin",
"repository": "peter-evans/create-pull-request-tests",
"named_args": true
},
{
"command": "clean",
"permission": "admin",
"repository": "peter-evans/create-pull-request-tests"
},
{
"command": "cpr-example",
"permission": "admin",
"issue_type": "issue"
}
]

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
__pycache__
.python-version
node_modules
.DS_Store

View File

@ -1,4 +1,4 @@
# <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
[![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.
@ -33,15 +33,17 @@ Create Pull Request action will:
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.
**Note**: If you want pull requests created by this action to trigger an `on: pull_request` workflow then you must use a [Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) instead of the default `GITHUB_TOKEN`.
See [this issue](https://github.com/peter-evans/create-pull-request/issues/48) for further details.
### Action inputs
These inputs are *all optional*. If not set, sensible default values will be used.
| Name | Description | Default |
| --- | --- | --- |
| `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` |
| `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. |
@ -86,6 +88,21 @@ If there is some reason you need to use `actions/checkout@v1` the following step
- run: git checkout "${GITHUB_REF:11}"
```
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
# Create changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
```
### Branch naming
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.
@ -192,7 +209,7 @@ jobs:
This reference configuration will create pull requests that look like this:
![Pull Request Example](assets/pull-request-example.png)
![Pull Request Example](docs/assets/pull-request-example.png)
## License

View File

@ -2,8 +2,10 @@ name: 'Create Pull Request'
description: 'Creates a pull request for changes to your repository in the actions workspace'
inputs:
token:
description: 'The GitHub authentication token'
description: 'GITHUB_TOKEN or a repo scoped PAT'
required: true
path:
description: 'Relative path under $GITHUB_WORKSPACE to the repository.'
commit-message:
description: 'The message to use when committing changes.'
committer:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

26
dist/index.js vendored
View File

@ -1001,29 +1001,48 @@ module.exports = require("os");
/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
const { inspect } = __webpack_require__(669);
const fs = __webpack_require__(747);
const core = __webpack_require__(470);
const exec = __webpack_require__(986);
const setupPython = __webpack_require__(139);
function fileExists(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
core.debug(`e: ${inspect(e)}`);
return false;
}
}
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const src = __webpack_require__.ab + "src";
core.debug(`src: ${src}`);
// Setup Python from the tool cache
setupPython("3.8.0", "x64");
// Check if the platfrom is Alpine Linux
const alpineLinux = fileExists("/etc/alpine-release");
core.debug(`alpineLinux: ${alpineLinux}`);
// Skip Python setup if the platform is Alpine Linux
if (!alpineLinux)
// Setup Python from the tool cache
setupPython("3.8.x", "x64");
// Install requirements
await exec.exec("pip", [
"install",
"--requirement",
`${src}/requirements.txt`
`${src}/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"),
@ -1044,6 +1063,7 @@ async function run() {
// 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;

13
dist/src/common.py vendored
View File

@ -8,6 +8,19 @@ 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 github repository from a URL
# e.g. peter-evans/create-pull-request
pattern = re.compile(r"^https://github.com/(.+/.+)$")
# Check we have a match
match = pattern.match(url)
if match is None:
raise ValueError(f"The format of '{url}' is not a valid GitHub repository URL")
return match.group(1)
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

@ -72,6 +72,8 @@ def create_or_update_pull_request(
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
else:
print(str(e))

View File

@ -31,6 +31,13 @@ def get_git_config_value(repo, name):
return None
def get_github_repository():
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")
return cmn.parse_github_repository(remote_origin_url)
def git_user_config_is_set(repo):
name = get_git_config_value(repo, "user.name")
email = get_git_config_value(repo, "user.email")
@ -94,8 +101,8 @@ 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)
commit_message = os.getenv("CPR_COMMIT_MESSAGE", DEFAULT_COMMIT_MESSAGE)
# Get environment variables with a default of 'None'
@ -103,8 +110,13 @@ committer = os.environ.get("CPR_COMMITTER")
author = os.environ.get("CPR_AUTHOR")
base = os.environ.get("CPR_BASE")
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Set the repo path
repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
github_repository = get_github_repository()
print(f"Target repository set to {github_repository}")
# 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

View File

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

View File

@ -9,6 +9,23 @@ def test_get_random_string():
assert len(cmn.get_random_string(length=20)) == 20
def test_parse_github_repository_success():
repository = cmn.parse_github_repository(
"https://github.com/peter-evans/create-pull-request"
)
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"

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

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/PyGithub-1.45.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-2019.11.28.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/gitdb2-2.0.6.tar.gz vendored Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/six-1.14.0.tar.gz vendored Normal file

Binary file not shown.

BIN
dist/vendor/smmap2-2.0.5.tar.gz vendored Normal file

Binary file not shown.

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

Binary file not shown.

BIN
dist/vendor/wrapt-1.11.2.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: 414 KiB

View File

@ -9,6 +9,8 @@ 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)
- [Tag push events](#tag-push-events)
- [Security](#security)
## Terminology
@ -30,7 +32,7 @@ The default can be overridden by specifying a `ref` on checkout.
```yml
- uses: actions/checkout@v2
with:
ref: master
ref: develop
```
## How the action works
@ -45,7 +47,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
@ -105,3 +107,88 @@ jobs:
# Check if the event is not triggered by a fork
if: github.event.pull_request.head.repo.full_name == github.repository
```
### Tag push events
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}
- name: Create changes to pull request
run: <create changes here>
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
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
- name: Create changes to pull request
run: <create changes here>
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
### 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.

View File

@ -1,8 +1,9 @@
# Examples
- [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)
- [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically)
- [Update NPM dependencies](#update-npm-dependencies)
- [Keep Go up to date](#keep-go-up-to-date)
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
- [Spider and download a website](#spider-and-download-a-website)
- [Use case: Create a pull request to update X by calling the GitHub API](#use-case-create-a-pull-request-to-update-x-by-calling-the-github-api)
@ -16,6 +17,40 @@
- [Debugging GitHub Actions](#debugging-github-actions)
## Use case: Create a pull request to update X on push
This pattern will work well for updating any kind of static content based on pushed changes. Care should be taken when using this pattern in repositories with a high frequency of commits.
### Update project authors
Raises a pull request to update a file called `AUTHORS` with the git user names and email addresses of contributors.
```yml
name: Update AUTHORS
on:
push:
branches:
- master
jobs:
updateAuthors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Update AUTHORS
run: |
git log --format='%aN <%aE>%n%cN <%cE>' | sort -u > AUTHORS
- 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
```
## 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.
@ -51,39 +86,6 @@ jobs:
branch: dep-updates
```
### Keep Go up to date
Keep Go up to date with [ensure-latest-go](https://github.com/jmhodges/ensure-latest-go) action.
```yml
name: Keeping Go up to date
on:
schedule:
- cron: 47 4 * * *
push:
branches:
- master
jobs:
fresh_go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: master
- uses: jmhodges/ensure-latest-go@v1.0.2
id: ensure_go
- run: echo "##[set-output name=pr_title;]update to latest Go release ${{ steps.ensure_go.outputs.go_version}}"
id: pr_title_maker
- name: Create pull request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ steps.pr_title_maker.outputs.pr_title }}
body: Auto-generated pull request created by the GitHub Actions [create-pull-request](https://github.com/peter-evans/create-pull-request) and [ensure-latest-go](https://github.com/jmhodges/ensure-latest-go).
commit-message: ${{ steps.pr_title_maker.outputs.pr_title }}
branch: ensure-latest-go/patch-${{ steps.ensure_go.outputs.go_version }}
```
### Update SwaggerUI for GitHub Pages
When using [GitHub Pages to host Swagger documentation](https://github.com/peter-evans/swagger-github-pages), this workflow updates the repository with the latest distribution of [SwaggerUI](https://github.com/swagger-api/swagger-ui).
@ -225,7 +227,7 @@ An `on: repository_dispatch` workflow can be triggered from another workflow wit
## Use case: Create a pull request to modify/fix pull requests
**Note**: While the following approach does work in some cases, my strong recommendation would be to use a slash command style "ChatOps" solution for operations on pull requests. See [slash-command-dispatch](https://github.com/peter-evans/slash-command-dispatch) for such a solution.
**Note**: While the following approach does work, my strong recommendation would be to use a slash command style "ChatOps" solution for operations on pull requests. See [slash-command-dispatch](https://github.com/peter-evans/slash-command-dispatch) for such a solution.
This is a pattern that lends itself to automated code linting and fixing. A pull request can be created to fix or modify something during an `on: pull_request` workflow. The pull request containing the fix will be raised with the original pull request as the base. This can be then be merged to update the original pull request and pass any required tests.
@ -256,7 +258,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

View File

@ -1,27 +1,46 @@
const { inspect } = require("util");
const fs = require("fs");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./src/setup-python");
function fileExists(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
core.debug(`e: ${inspect(e)}`);
return false;
}
}
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.0", "x64");
// Check if the platfrom is Alpine Linux
const alpineLinux = fileExists("/etc/alpine-release");
core.debug(`alpineLinux: ${alpineLinux}`);
// Skip Python setup if the platform is Alpine Linux
if (!alpineLinux)
// Setup Python from the tool cache
setupPython("3.8.x", "x64");
// Install requirements
await exec.exec("pip", [
"install",
"--requirement",
`${src}/requirements.txt`
`${src}/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"),
@ -42,6 +61,7 @@ async function run() {
// 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;

6
package-lock.json generated
View File

@ -36,9 +36,9 @@
}
},
"@zeit/ncc": {
"version": "0.20.5",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
"version": "0.21.0",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.21.0.tgz",
"integrity": "sha512-RUMdvVK/w78oo+yBjruZltt0kJXYar2un/1bYQ2LuHG7GmFVm+QjxzEmySwREctaJdEnBvlMdUNWd9hXHxEI3g==",
"dev": true
},
"qs": {

View File

@ -4,7 +4,10 @@
"description": "Creates a pull request for changes to your repository in the actions workspace",
"main": "index.js",
"scripts": {
"package": "ncc build index.js -o dist"
"clean": "rm -rf dist",
"build": "ncc build index.js -o dist",
"vendor-deps": "pip download -r src/requirements.txt --no-binary=:all: -d dist/vendor",
"package": "npm run build && npm run vendor-deps"
},
"repository": {
"type": "git",
@ -23,6 +26,6 @@
"@actions/tool-cache": "^1.1.2"
},
"devDependencies": {
"@zeit/ncc": "0.20.5"
"@zeit/ncc": "0.21.0"
}
}

View File

@ -8,6 +8,19 @@ 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 github repository from a URL
# e.g. peter-evans/create-pull-request
pattern = re.compile(r"^https://github.com/(.+/.+)$")
# Check we have a match
match = pattern.match(url)
if match is None:
raise ValueError(f"The format of '{url}' is not a valid GitHub repository URL")
return match.group(1)
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

@ -72,6 +72,8 @@ def create_or_update_pull_request(
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
else:
print(str(e))

View File

@ -31,6 +31,13 @@ def get_git_config_value(repo, name):
return None
def get_github_repository():
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")
return cmn.parse_github_repository(remote_origin_url)
def git_user_config_is_set(repo):
name = get_git_config_value(repo, "user.name")
email = get_git_config_value(repo, "user.email")
@ -94,8 +101,8 @@ 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)
commit_message = os.getenv("CPR_COMMIT_MESSAGE", DEFAULT_COMMIT_MESSAGE)
# Get environment variables with a default of 'None'
@ -103,8 +110,13 @@ committer = os.environ.get("CPR_COMMITTER")
author = os.environ.get("CPR_AUTHOR")
base = os.environ.get("CPR_BASE")
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Set the repo path
repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
github_repository = get_github_repository()
print(f"Target repository set to {github_repository}")
# 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

View File

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

View File

@ -9,6 +9,23 @@ def test_get_random_string():
assert len(cmn.get_random_string(length=20)) == 20
def test_parse_github_repository_success():
repository = cmn.parse_github_repository(
"https://github.com/peter-evans/create-pull-request"
)
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"