Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
cc7020a609 | |||
d8700620d6 | |||
b7064071dc | |||
339e82d37b | |||
a319015452 | |||
df0d07269b |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
__pycache__
|
||||
.python-version
|
||||
|
||||
node_modules
|
||||
|
||||
.DS_Store
|
||||
|
@ -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
|
||||
[](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:
|
||||
|
||||

|
||||

|
||||
|
||||
## License
|
||||
|
||||
|
4
dist/index.js
vendored
4
dist/index.js
vendored
@ -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
dist/src/common.py
vendored
13
dist/src/common.py
vendored
@ -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>
|
||||
|
13
dist/src/create_pull_request.py
vendored
13
dist/src/create_pull_request.py
vendored
@ -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
dist/src/test_common.py
vendored
17
dist/src/test_common.py
vendored
@ -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
BIN
dist/vendor/Deprecated-1.2.7.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/GitPython-3.0.5.tar.gz
vendored
Normal file
BIN
dist/vendor/GitPython-3.0.5.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/PyGithub-1.45.tar.gz
vendored
Normal file
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
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
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
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
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
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
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
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
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
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
BIN
dist/vendor/wrapt-1.11.2.tar.gz
vendored
Normal 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 |
@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
## 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.
|
||||
|
4
index.js
4
index.js
@ -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,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",
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
Reference in New Issue
Block a user