Compare commits

...
6 Commits
Author SHA1 Message Date
Peter Evans cc7020a609 Merge pull request #107 from peter-evans/dev
Determine target github repository from git config
2020-02-07 19:01:09 +09:00
Peter Evans d8700620d6 Determine target github repository from git config 2020-02-07 11:05:01 +09:00
Peter Evans b7064071dc Move assets 2020-01-25 16:29:22 +09:00
Peter Evans 339e82d37b Update documentation 2020-01-24 13:00:38 +09:00
Peter Evans a319015452 Merge pull request #102 from peter-evans/dev
Vendor python dependencies
2020-01-23 18:59:19 +09:00
Peter Evans df0d07269b Vendor python dependencies 2020-01-23 16:59:19 +09:00
29 changed files with 121 additions and 8 deletions
+3
View File
@@ -1,3 +1,6 @@
__pycache__
.python-version
node_modules
.DS_Store
+2 -2
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.
@@ -194,7 +194,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
+3 -1
View File
@@ -1018,7 +1018,9 @@ async function run() {
await exec.exec("pip", [
"install",
"--requirement",
`${src}/requirements.txt`
`${src}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
+13
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>
+12 -1
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,7 +101,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 +113,11 @@ 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
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
# This check will fail in the following cases:
+17
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"
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 207 KiB

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 416 B

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 414 KiB

+22 -1
View File
@@ -10,6 +10,7 @@ This document covers terminology, how the action works, and general usage guidel
- [Pull request events](#pull-request-events)
- [Restrictions on forked repositories](#restrictions-on-forked-repositories)
- [Tag push events](#tag-push-events)
- [Security](#security)
## Terminology
@@ -46,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
@@ -171,3 +172,23 @@ jobs:
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.
+3 -1
View File
@@ -16,7 +16,9 @@ async function run() {
await exec.exec("pip", [
"install",
"--requirement",
`${src}/requirements.txt`
`${src}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
+4 -1
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",
+13
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>
+12 -1
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,7 +101,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 +113,11 @@ 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
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
# This check will fail in the following cases:
+17
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"