Add logging and handling for pr events from forks

This commit is contained in:
Peter Evans 2019-11-13 19:10:38 +09:00
parent 67e8822279
commit b6a98c049d
2 changed files with 96 additions and 40 deletions

View File

@ -7,8 +7,7 @@ import string
import sys import sys
import time import time
from git import Repo from git import Repo
from github import Github from github import Github, GithubException
from github import GithubException
def get_github_event(github_event_path): def get_github_event(github_event_path):
@ -46,6 +45,7 @@ def get_author_default(event_name, event_data):
def set_git_config(git, email, name): def set_git_config(git, email, name):
print("Configuring git user as '%s <%s>'" % (name, email))
git.config('--global', 'user.email', '"%s"' % email) git.config('--global', 'user.email', '"%s"' % email)
git.config('--global', 'user.name', '"%s"' % name) git.config('--global', 'user.name', '"%s"' % name)
@ -58,6 +58,7 @@ def set_git_remote_url(git, token, github_repository):
def checkout_branch(git, remote_exists, branch): def checkout_branch(git, remote_exists, branch):
if remote_exists: if remote_exists:
print("Checking out branch '%s'" % branch)
git.stash('--include-untracked') git.stash('--include-untracked')
git.checkout(branch) git.checkout(branch)
try: try:
@ -66,6 +67,7 @@ def checkout_branch(git, remote_exists, branch):
git.checkout('--theirs', '.') git.checkout('--theirs', '.')
git.reset() git.reset()
else: else:
print("Creating new branch '%s'" % branch)
git.checkout('HEAD', b=branch) git.checkout('HEAD', b=branch)
@ -101,7 +103,7 @@ def process_event(github_token, github_repository, repo, branch, base):
pull_request_team_reviewers = os.environ.get('PULL_REQUEST_TEAM_REVIEWERS') pull_request_team_reviewers = os.environ.get('PULL_REQUEST_TEAM_REVIEWERS')
# Push the local changes to the remote branch # Push the local changes to the remote branch
print("Pushing changes.") print("Pushing changes to 'origin/%s'" % branch)
push_result = push_changes(repo.git, branch, commit_message) push_result = push_changes(repo.git, branch, commit_message)
print(push_result) print(push_result)
@ -140,30 +142,31 @@ def process_event(github_token, github_repository, repo, branch, base):
# Set labels, assignees and milestone # Set labels, assignees and milestone
if pull_request_labels is not None: if pull_request_labels is not None:
print("Applying labels") print("Applying labels '%s'" % pull_request_labels)
pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels)) pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels))
if pull_request_assignees is not None: if pull_request_assignees is not None:
print("Applying assignees") print("Applying assignees '%s'" % pull_request_assignees)
pull_request.as_issue().edit(assignees=cs_string_to_list(pull_request_assignees)) pull_request.as_issue().edit(assignees=cs_string_to_list(pull_request_assignees))
if pull_request_milestone is not None: if pull_request_milestone is not None:
print("Applying milestone") print("Applying milestone '%s'" % pull_request_milestone)
milestone = github_repo.get_milestone(int(pull_request_milestone)) milestone = github_repo.get_milestone(int(pull_request_milestone))
pull_request.as_issue().edit(milestone=milestone) pull_request.as_issue().edit(milestone=milestone)
# Set pull request reviewers # Set pull request reviewers
if pull_request_reviewers is not None: if pull_request_reviewers is not None:
print("Requesting reviewers") print("Requesting reviewers '%s'" % pull_request_reviewers)
try: try:
pull_request.create_review_request( pull_request.create_review_request(
reviewers=cs_string_to_list(pull_request_reviewers)) reviewers=cs_string_to_list(pull_request_reviewers))
except GithubException as e: except GithubException as e:
# Likely caused by "Review cannot be requested from pull request author." # Likely caused by "Review cannot be requested from pull request
# author."
if e.status == 422: if e.status == 422:
print("Requesting reviewers failed - %s" % e.data["message"]) print("Requesting reviewers failed - %s" % e.data["message"])
# Set pull request team reviewers # Set pull request team reviewers
if pull_request_team_reviewers is not None: if pull_request_team_reviewers is not None:
print("Requesting team reviewers") print("Requesting team reviewers '%s'" % pull_request_team_reviewers)
pull_request.create_review_request( pull_request.create_review_request(
team_reviewers=cs_string_to_list(pull_request_team_reviewers)) team_reviewers=cs_string_to_list(pull_request_team_reviewers))
@ -198,16 +201,29 @@ base_override = os.environ.get('PULL_REQUEST_BASE')
# Set the base branch # Set the base branch
if base_override is not None: if base_override is not None:
base = base_override base = base_override
print("Overriding the base with branch '%s'" % base)
checkout_branch(repo.git, True, base) checkout_branch(repo.git, True, base)
elif github_ref.startswith('refs/pull/'): elif github_ref.startswith('refs/pull/'):
# Check the PR is not raised from a fork of the repository
head_repo = "{pull_request[head][repo][full_name]}".format(**event_data)
if head_repo != github_repository:
print("::warning::Pull request was raised from a fork of the repository. " +
"Limitations on forked repositories have been imposed by GitHub Actions. " +
"Unable to continue. Exiting.")
sys.exit()
# Switch to the merging branch instead of the merge commit # Switch to the merging branch instead of the merge commit
base = os.environ['GITHUB_HEAD_REF'] base = os.environ['GITHUB_HEAD_REF']
repo.git.checkout(base) print(
"Removing the merge commit by switching to the pull request head branch '%s'" %
base)
checkout_branch(repo.git, True, base)
else: else:
base = github_ref[11:] base = github_ref[11:]
print("Currently checked out base assumed to be branch '%s'" % base)
# Skip if the current branch is a PR branch created by this action. # Skip if the current branch is a PR branch created by this action.
# This may occur when using a PAT instead of GITHUB_TOKEN. # This may occur when using a PAT instead of GITHUB_TOKEN because
# a PAT allows workflow actions to trigger further events.
if base.startswith(branch_prefix): if base.startswith(branch_prefix):
print("Branch '%s' was created by this action. Skipping." % base) print("Branch '%s' was created by this action. Skipping." % base)
sys.exit() sys.exit()
@ -232,10 +248,15 @@ else:
branch_suffix) branch_suffix)
sys.exit(1) sys.exit(1)
# Check if the remote branch exists # Output head branch
remote_exists = remote_branch_exists(repo, branch) print("Pull request branch to create/update set to '%s'" % branch)
# Check if the determined head branch exists as a remote
remote_exists = remote_branch_exists(repo, branch)
if remote_exists: if remote_exists:
print(
"Pull request branch '%s' already exists as remote branch 'origin/%s'" %
(branch, branch))
if branch_suffix == 'short-commit-hash': if branch_suffix == 'short-commit-hash':
# A remote branch already exists for the HEAD commit # A remote branch already exists for the HEAD commit
print( print(
@ -243,9 +264,9 @@ if remote_exists:
branch) branch)
sys.exit() sys.exit()
elif branch_suffix in ['timestamp', 'random']: elif branch_suffix in ['timestamp', 'random']:
# Generated branch name clash with an existing branch # Generated branch name collision with an existing branch
print( print(
"Pull request branch '%s' already exists. Please re-run." % "Pull request branch '%s' collided with a branch of the same name. Please re-run." %
branch) branch)
sys.exit(1) sys.exit(1)
@ -253,8 +274,15 @@ if remote_exists:
checkout_branch(repo.git, remote_exists, branch) checkout_branch(repo.git, remote_exists, branch)
# Check if there are changes to pull request # Check if there are changes to pull request
if remote_exists:
print("Checking for local working copy changes indicating a " +
"diff with existing pull request branch 'origin/%s'" % branch)
else:
print("Checking for local working copy changes indicating a " +
"diff with base 'origin/%s'" % base)
if repo.is_dirty() or len(repo.untracked_files) > 0: if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Repository has modified or untracked files.") print("Modified or untracked files detected.")
process_event( process_event(
github_token, github_token,
github_repository, github_repository,
@ -262,4 +290,4 @@ if repo.is_dirty() or len(repo.untracked_files) > 0:
branch, branch,
base) base)
else: else:
print("Repository has no modified or untracked files. Skipping.") print("No modified or untracked files detected. Skipping.")

View File

@ -7,8 +7,7 @@ import string
import sys import sys
import time import time
from git import Repo from git import Repo
from github import Github from github import Github, GithubException
from github import GithubException
def get_github_event(github_event_path): def get_github_event(github_event_path):
@ -46,6 +45,7 @@ def get_author_default(event_name, event_data):
def set_git_config(git, email, name): def set_git_config(git, email, name):
print("Configuring git user as '%s <%s>'" % (name, email))
git.config('--global', 'user.email', '"%s"' % email) git.config('--global', 'user.email', '"%s"' % email)
git.config('--global', 'user.name', '"%s"' % name) git.config('--global', 'user.name', '"%s"' % name)
@ -58,6 +58,7 @@ def set_git_remote_url(git, token, github_repository):
def checkout_branch(git, remote_exists, branch): def checkout_branch(git, remote_exists, branch):
if remote_exists: if remote_exists:
print("Checking out branch '%s'" % branch)
git.stash('--include-untracked') git.stash('--include-untracked')
git.checkout(branch) git.checkout(branch)
try: try:
@ -66,6 +67,7 @@ def checkout_branch(git, remote_exists, branch):
git.checkout('--theirs', '.') git.checkout('--theirs', '.')
git.reset() git.reset()
else: else:
print("Creating new branch '%s'" % branch)
git.checkout('HEAD', b=branch) git.checkout('HEAD', b=branch)
@ -101,7 +103,7 @@ def process_event(github_token, github_repository, repo, branch, base):
pull_request_team_reviewers = os.environ.get('PULL_REQUEST_TEAM_REVIEWERS') pull_request_team_reviewers = os.environ.get('PULL_REQUEST_TEAM_REVIEWERS')
# Push the local changes to the remote branch # Push the local changes to the remote branch
print("Pushing changes.") print("Pushing changes to 'origin/%s'" % branch)
push_result = push_changes(repo.git, branch, commit_message) push_result = push_changes(repo.git, branch, commit_message)
print(push_result) print(push_result)
@ -140,30 +142,31 @@ def process_event(github_token, github_repository, repo, branch, base):
# Set labels, assignees and milestone # Set labels, assignees and milestone
if pull_request_labels is not None: if pull_request_labels is not None:
print("Applying labels") print("Applying labels '%s'" % pull_request_labels)
pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels)) pull_request.as_issue().edit(labels=cs_string_to_list(pull_request_labels))
if pull_request_assignees is not None: if pull_request_assignees is not None:
print("Applying assignees") print("Applying assignees '%s'" % pull_request_assignees)
pull_request.as_issue().edit(assignees=cs_string_to_list(pull_request_assignees)) pull_request.as_issue().edit(assignees=cs_string_to_list(pull_request_assignees))
if pull_request_milestone is not None: if pull_request_milestone is not None:
print("Applying milestone") print("Applying milestone '%s'" % pull_request_milestone)
milestone = github_repo.get_milestone(int(pull_request_milestone)) milestone = github_repo.get_milestone(int(pull_request_milestone))
pull_request.as_issue().edit(milestone=milestone) pull_request.as_issue().edit(milestone=milestone)
# Set pull request reviewers # Set pull request reviewers
if pull_request_reviewers is not None: if pull_request_reviewers is not None:
print("Requesting reviewers") print("Requesting reviewers '%s'" % pull_request_reviewers)
try: try:
pull_request.create_review_request( pull_request.create_review_request(
reviewers=cs_string_to_list(pull_request_reviewers)) reviewers=cs_string_to_list(pull_request_reviewers))
except GithubException as e: except GithubException as e:
# Likely caused by "Review cannot be requested from pull request author." # Likely caused by "Review cannot be requested from pull request
# author."
if e.status == 422: if e.status == 422:
print("Requesting reviewers failed - %s" % e.data["message"]) print("Requesting reviewers failed - %s" % e.data["message"])
# Set pull request team reviewers # Set pull request team reviewers
if pull_request_team_reviewers is not None: if pull_request_team_reviewers is not None:
print("Requesting team reviewers") print("Requesting team reviewers '%s'" % pull_request_team_reviewers)
pull_request.create_review_request( pull_request.create_review_request(
team_reviewers=cs_string_to_list(pull_request_team_reviewers)) team_reviewers=cs_string_to_list(pull_request_team_reviewers))
@ -198,16 +201,29 @@ base_override = os.environ.get('PULL_REQUEST_BASE')
# Set the base branch # Set the base branch
if base_override is not None: if base_override is not None:
base = base_override base = base_override
print("Overriding the base with branch '%s'" % base)
checkout_branch(repo.git, True, base) checkout_branch(repo.git, True, base)
elif github_ref.startswith('refs/pull/'): elif github_ref.startswith('refs/pull/'):
# Check the PR is not raised from a fork of the repository
head_repo = "{pull_request[head][repo][full_name]}".format(**event_data)
if head_repo != github_repository:
print("::warning::Pull request was raised from a fork of the repository. " +
"Limitations on forked repositories have been imposed by GitHub Actions. " +
"Unable to continue. Exiting.")
sys.exit()
# Switch to the merging branch instead of the merge commit # Switch to the merging branch instead of the merge commit
base = os.environ['GITHUB_HEAD_REF'] base = os.environ['GITHUB_HEAD_REF']
repo.git.checkout(base) print(
"Removing the merge commit by switching to the pull request head branch '%s'" %
base)
checkout_branch(repo.git, True, base)
else: else:
base = github_ref[11:] base = github_ref[11:]
print("Currently checked out base assumed to be branch '%s'" % base)
# Skip if the current branch is a PR branch created by this action. # Skip if the current branch is a PR branch created by this action.
# This may occur when using a PAT instead of GITHUB_TOKEN. # This may occur when using a PAT instead of GITHUB_TOKEN because
# a PAT allows workflow actions to trigger further events.
if base.startswith(branch_prefix): if base.startswith(branch_prefix):
print("Branch '%s' was created by this action. Skipping." % base) print("Branch '%s' was created by this action. Skipping." % base)
sys.exit() sys.exit()
@ -232,10 +248,15 @@ else:
branch_suffix) branch_suffix)
sys.exit(1) sys.exit(1)
# Check if the remote branch exists # Output head branch
remote_exists = remote_branch_exists(repo, branch) print("Pull request branch to create/update set to '%s'" % branch)
# Check if the determined head branch exists as a remote
remote_exists = remote_branch_exists(repo, branch)
if remote_exists: if remote_exists:
print(
"Pull request branch '%s' already exists as remote branch 'origin/%s'" %
(branch, branch))
if branch_suffix == 'short-commit-hash': if branch_suffix == 'short-commit-hash':
# A remote branch already exists for the HEAD commit # A remote branch already exists for the HEAD commit
print( print(
@ -243,9 +264,9 @@ if remote_exists:
branch) branch)
sys.exit() sys.exit()
elif branch_suffix in ['timestamp', 'random']: elif branch_suffix in ['timestamp', 'random']:
# Generated branch name clash with an existing branch # Generated branch name collision with an existing branch
print( print(
"Pull request branch '%s' already exists. Please re-run." % "Pull request branch '%s' collided with a branch of the same name. Please re-run." %
branch) branch)
sys.exit(1) sys.exit(1)
@ -253,8 +274,15 @@ if remote_exists:
checkout_branch(repo.git, remote_exists, branch) checkout_branch(repo.git, remote_exists, branch)
# Check if there are changes to pull request # Check if there are changes to pull request
if remote_exists:
print("Checking for local working copy changes indicating a " +
"diff with existing pull request branch 'origin/%s'" % branch)
else:
print("Checking for local working copy changes indicating a " +
"diff with base 'origin/%s'" % base)
if repo.is_dirty() or len(repo.untracked_files) > 0: if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Repository has modified or untracked files.") print("Modified or untracked files detected.")
process_event( process_event(
github_token, github_token,
github_repository, github_repository,
@ -262,4 +290,4 @@ if repo.is_dirty() or len(repo.untracked_files) > 0:
branch, branch,
base) base)
else: else:
print("Repository has no modified or untracked files. Skipping.") print("No modified or untracked files detected. Skipping.")