From e48dab0c1c87c8d7578b36221e791621b90d60cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Fri, 27 Mar 2020 18:56:55 +0100 Subject: [PATCH 1/6] Add PR creation from Fork --- .github/workflows/cpr-example-command.yml | 1 + README.md | 2 ++ action.yml | 5 ++++- dist/cpr/create_or_update_pull_request.py | 22 +++++++++++++++++----- dist/cpr/create_pull_request.py | 1 + dist/index.js | 2 ++ src/cpr/create_or_update_pull_request.py | 22 +++++++++++++++++----- src/cpr/create_pull_request.py | 3 ++- src/index.js | 2 ++ 9 files changed, 48 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cpr-example-command.yml b/.github/workflows/cpr-example-command.yml index 4020d0d..dcf8d2a 100644 --- a/.github/workflows/cpr-example-command.yml +++ b/.github/workflows/cpr-example-command.yml @@ -30,6 +30,7 @@ jobs: project: Example Project project-column: To do branch: example-patches + request-to-parent: false - name: Check outputs run: | echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}" diff --git a/README.md b/README.md index 5f02ecd..b1c9d34 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ With the exception of `token`, all inputs are **optional**. If not set, sensible | `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`. | | | `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` | +| `request-to-parent` | Whether or not the pull request should be create on the parent repository. | `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. | | @@ -186,6 +187,7 @@ jobs: project: Example Project project-column: To do branch: example-patches + request-to-parent: false - name: Check outputs run: | echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}" diff --git a/action.yml b/action.yml index 00f233d..46ca140 100644 --- a/action.yml +++ b/action.yml @@ -32,6 +32,9 @@ inputs: description: 'The name of the project column under which a card should be created.' branch: description: 'The pull request branch name.' + request-to-parent: + description: 'Whether or not the pull request should be create on the parent repository.' + default: false base: description: 'The pull request base branch.' branch-suffix: @@ -43,5 +46,5 @@ runs: using: 'node12' main: 'dist/index.js' branding: - icon: 'git-pull-request' + icon: 'git-pull-request' color: 'gray-dark' diff --git a/dist/cpr/create_or_update_pull_request.py b/dist/cpr/create_or_update_pull_request.py index bb2486a..ab189ea 100644 --- a/dist/cpr/create_or_update_pull_request.py +++ b/dist/cpr/create_or_update_pull_request.py @@ -56,25 +56,37 @@ def create_or_update_pull_request( team_reviewers, project_name, project_column_name, + request_to_parent, ): + if request_to_parent is None: + request_to_parent = False + else: + request_to_parent = request_to_parent.lower() in ['true', '1', 't', 'y', 'yes', 'on'] + + github_repo = head_repo = Github(github_token).get_repo(github_repository) + if request_to_parent: + github_repo = github_repo.parent + if github_repo is None: + raise ValueError("The repository is not a fork. The parameter 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 ) - print(f"Created pull request #{pull_request.number} ({branch} => {base})") + print(f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{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] # Update title and body pull_request.as_issue().edit(title=title, body=body) - print(f"Updated pull request #{pull_request.number} ({branch} => {base})") + print(f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})") else: print(str(e)) raise diff --git a/dist/cpr/create_pull_request.py b/dist/cpr/create_pull_request.py index c73befc..098a69b 100755 --- a/dist/cpr/create_pull_request.py +++ b/dist/cpr/create_pull_request.py @@ -224,4 +224,5 @@ 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_REQUEST_TO_PARENT"), ) diff --git a/dist/index.js b/dist/index.js index 32b5948..c506302 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4275,6 +4275,7 @@ async function run() { project: core.getInput("project"), projectColumn: core.getInput("project-column"), branch: core.getInput("branch"), + request_to_parent: core.getInput("request-to-parent"), base: core.getInput("base"), branchSuffix: core.getInput("branch-suffix") }; @@ -4296,6 +4297,7 @@ async function run() { 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.request_to_parent) process.env.CPR_REQUEST_TO_PARENT = inputs.request_to_parent; if (inputs.base) process.env.CPR_BASE = inputs.base; if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix; diff --git a/src/cpr/create_or_update_pull_request.py b/src/cpr/create_or_update_pull_request.py index bb2486a..ab189ea 100644 --- a/src/cpr/create_or_update_pull_request.py +++ b/src/cpr/create_or_update_pull_request.py @@ -56,25 +56,37 @@ def create_or_update_pull_request( team_reviewers, project_name, project_column_name, + request_to_parent, ): + if request_to_parent is None: + request_to_parent = False + else: + request_to_parent = request_to_parent.lower() in ['true', '1', 't', 'y', 'yes', 'on'] + + github_repo = head_repo = Github(github_token).get_repo(github_repository) + if request_to_parent: + github_repo = github_repo.parent + if github_repo is None: + raise ValueError("The repository is not a fork. The parameter 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 ) - print(f"Created pull request #{pull_request.number} ({branch} => {base})") + print(f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{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] # Update title and body pull_request.as_issue().edit(title=title, body=body) - print(f"Updated pull request #{pull_request.number} ({branch} => {base})") + print(f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})") else: print(str(e)) raise diff --git a/src/cpr/create_pull_request.py b/src/cpr/create_pull_request.py index c73befc..37052ec 100755 --- a/src/cpr/create_pull_request.py +++ b/src/cpr/create_pull_request.py @@ -192,7 +192,7 @@ result = coub.create_or_update_branch(repo, repo_url, commit_message, base, bran if result["action"] in ["created", "updated"]: # The branch was created or updated - print(f"Pushing pull request branch to 'origin/{branch}'") + print(f"Pushing pull request branch to '{repo.full_name}/{branch}'") repo.git.push("--force", repo_url, f"HEAD:refs/heads/{branch}") # Set the base. It would have been 'None' if not specified as an input @@ -224,4 +224,5 @@ 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_REQUEST_TO_PARENT"), ) diff --git a/src/index.js b/src/index.js index c82fe82..82bc834 100644 --- a/src/index.js +++ b/src/index.js @@ -63,6 +63,7 @@ async function run() { project: core.getInput("project"), projectColumn: core.getInput("project-column"), branch: core.getInput("branch"), + request_to_parent: core.getInput("request-to-parent"), base: core.getInput("base"), branchSuffix: core.getInput("branch-suffix") }; @@ -84,6 +85,7 @@ async function run() { 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.request_to_parent) process.env.CPR_REQUEST_TO_PARENT = inputs.request_to_parent; if (inputs.base) process.env.CPR_BASE = inputs.base; if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix; From cff2c3381db4c02ae7764e803f81ce07704394b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sat, 28 Mar 2020 13:27:58 +0100 Subject: [PATCH 2/6] Add doc --- docs/concepts-guidelines.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index 2f4bcf1..fdfbdcc 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -180,6 +180,34 @@ How to use SSH (deploy keys) with create-pull-request action: token: ${{ secrets.GITHUB_TOKEN }} ``` +### Push in fork + +To enforce security, you can use a dedicated user using [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, then login with this user. +2. fork the repository. +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 go back to your main user. +5. Add a secret to the repository containing the above PAT. +6. As show in the example bellow, switch the git remote to the fork's url after checkout and set the option `request-on-parent` + +```yaml + - uses: actions/checkout@v2 + + - run: | + git config user.password ${{ secrets.PAT }} + git remote set-url origin https://github.com/bot-user/fork-project + git fetch --unshallow -p origin + + # Make changes to pull request here + + - uses: peter-evans/create-pull-request@v2 + with: + token: ${{ secrets.PAT }} + request-on-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. From 4c347a451405ec63278a78547f033013c331a2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sat, 28 Mar 2020 16:42:57 +0100 Subject: [PATCH 3/6] Update docs/concepts-guidelines.md Co-Authored-By: Tobias Nyholm --- docs/concepts-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index fdfbdcc..29a1b61 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -190,7 +190,7 @@ This user has no access to the main repository, it will use their own fork to pu 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 go back to your main user. 5. Add a secret to the repository containing the above PAT. -6. As show in the example bellow, switch the git remote to the fork's url after checkout and set the option `request-on-parent` +6. As show in the example below, switch the git remote to the fork's url after checkout and set the option `request-on-parent` ```yaml - uses: actions/checkout@v2 From 6bb0e7771c2913850f7809d560b0561a23f210f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 29 Mar 2020 12:43:21 +0200 Subject: [PATCH 4/6] Apply suggestions from code review Co-Authored-By: Peter Evans --- README.md | 2 +- action.yml | 2 +- dist/cpr/create_or_update_pull_request.py | 2 +- docs/concepts-guidelines.md | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b1c9d34..6711984 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ With the exception of `token`, all inputs are **optional**. If not set, sensible | `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`. | | | `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` | -| `request-to-parent` | Whether or not the pull request should be create on the parent repository. | `false` | +| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. | `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. | | diff --git a/action.yml b/action.yml index 46ca140..ecbb65e 100644 --- a/action.yml +++ b/action.yml @@ -33,7 +33,7 @@ inputs: branch: description: 'The pull request branch name.' request-to-parent: - description: 'Whether or not the pull request should be create on the parent repository.' + description: 'Create the pull request in the parent repository of the checked out fork.' default: false base: description: 'The pull request base branch.' diff --git a/dist/cpr/create_or_update_pull_request.py b/dist/cpr/create_or_update_pull_request.py index ab189ea..ed08b24 100644 --- a/dist/cpr/create_or_update_pull_request.py +++ b/dist/cpr/create_or_update_pull_request.py @@ -67,7 +67,7 @@ def create_or_update_pull_request( if request_to_parent: github_repo = github_repo.parent if github_repo is None: - raise ValueError("The repository is not a fork. The parameter request-to-parent should be set to false.") + 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}" diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index 29a1b61..3d0f035 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -180,7 +180,7 @@ How to use SSH (deploy keys) with create-pull-request action: token: ${{ secrets.GITHUB_TOKEN }} ``` -### Push in fork +### Push pull request branches to a fork To enforce security, you can use a dedicated user using [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. @@ -190,7 +190,7 @@ This user has no access to the main repository, it will use their own fork to pu 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 go back to your main user. 5. Add a secret to the repository containing the above PAT. -6. As show in the example below, switch the git remote to the fork's url after checkout and set the option `request-on-parent` +6. As shown in the example below, switch the git remote to the fork's url after checkout and set the action input `request-on-parent` to `true`. ```yaml - uses: actions/checkout@v2 From 26bc40eea1b6901b9b6527e802204809d82a8cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 29 Mar 2020 12:43:45 +0200 Subject: [PATCH 5/6] Add link in TOC --- docs/concepts-guidelines.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index 3d0f035..c0e5d19 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -13,6 +13,7 @@ This document covers terminology, how the action works, general usage guidelines - [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) From 5bd05538d0485ca1a239d1760ea899d0de6949c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 29 Mar 2020 13:36:48 +0200 Subject: [PATCH 6/6] Update src/cpr/create_or_update_pull_request.py Co-Authored-By: Peter Evans --- src/cpr/create_or_update_pull_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpr/create_or_update_pull_request.py b/src/cpr/create_or_update_pull_request.py index ab189ea..ed08b24 100644 --- a/src/cpr/create_or_update_pull_request.py +++ b/src/cpr/create_or_update_pull_request.py @@ -67,7 +67,7 @@ def create_or_update_pull_request( if request_to_parent: github_repo = github_repo.parent if github_repo is None: - raise ValueError("The repository is not a fork. The parameter request-to-parent should be set to false.") + 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}"